Dispaly caret, unify text character render
This commit is contained in:
parent
399b0b7144
commit
85014a2af2
219
Cargo.lock
generated
219
Cargo.lock
generated
@ -1,3 +1,47 @@
|
||||
[[package]]
|
||||
name = "argon2rs"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.4.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace-sys"
|
||||
version = "0.1.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bit-set"
|
||||
version = "0.4.0"
|
||||
@ -21,11 +65,25 @@ name = "bitflags"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "blake2-rfc"
|
||||
version = "0.2.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "c_vec"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.6"
|
||||
@ -39,13 +97,52 @@ dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "constant_time_eq"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "dirs"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_users 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "editor"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"dirs 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"plex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"sdl2 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "failure"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "failure_derive"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.15.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -62,6 +159,11 @@ name = "fuchsia-zircon-sys"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "lalr"
|
||||
version = "0.0.2"
|
||||
@ -74,7 +176,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.44"
|
||||
version = "0.2.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "nodrop"
|
||||
version = "0.1.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
@ -143,7 +250,7 @@ version = "0.3.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -153,7 +260,7 @@ version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -164,7 +271,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -191,6 +298,37 @@ dependencies = [
|
||||
"vec_map 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.1.50"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "redox_users"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "scoped_threadpool"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "sdl2"
|
||||
version = "0.31.0"
|
||||
@ -199,7 +337,7 @@ dependencies = [
|
||||
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"c_vec 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"sdl2-sys 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -213,6 +351,31 @@ dependencies = [
|
||||
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.15.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "0.14.9"
|
||||
@ -223,6 +386,27 @@ dependencies = [
|
||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "0.15.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "synstructure"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.15.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.1.0"
|
||||
@ -253,18 +437,31 @@ version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[metadata]
|
||||
"checksum argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392"
|
||||
"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71"
|
||||
"checksum autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4e5f34df7a019573fb8bdc7e24a2bfebe51a2a1d6bfdbaeccedb3c41fc574727"
|
||||
"checksum backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b5b493b66e03090ebc4343eb02f94ff944e0cbc9ac6571491d170ba026741eb5"
|
||||
"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6"
|
||||
"checksum bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9bf6104718e80d7b26a68fdbacff3481cfc05df670821affc7e9cbc1884400c"
|
||||
"checksum bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "02b4ff8b16e6076c3e14220b39fbc1fabb6737522281a388998046859400895f"
|
||||
"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
|
||||
"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
|
||||
"checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400"
|
||||
"checksum c_vec 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6c32b15e95ce816aaf991a41420854e6ba772a2679a9296d906eab1114f1b4e9"
|
||||
"checksum cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a8b715cb4597106ea87c7c84b2f1d452c7492033765df7f32651e66fcf749"
|
||||
"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4"
|
||||
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
||||
"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e"
|
||||
"checksum dirs 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "88972de891f6118092b643d85a0b28e0678e0f948d7f879aa32f2d5aafe97d2a"
|
||||
"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2"
|
||||
"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1"
|
||||
"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
|
||||
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
|
||||
"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b"
|
||||
"checksum lalr 0.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "106d7548f95adbe3019b4fc4954554d7b72535867aa9ce326d2f766b68958de7"
|
||||
"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
|
||||
"checksum libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)" = "10923947f84a519a45c8fefb7dd1b3e8c08747993381adee176d7a82b4195311"
|
||||
"checksum libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)" = "2d2857ec59fadc0773853c664d2d18e7198e83883e7060b63c924cb077bd5c74"
|
||||
"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945"
|
||||
"checksum num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e"
|
||||
"checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea"
|
||||
"checksum num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "af3fdbbc3291a5464dc57b03860ec37ca6bf915ed6ee385e7c6c052c422b2124"
|
||||
@ -278,9 +475,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372"
|
||||
"checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db"
|
||||
"checksum redfa 0.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "29cc2771cc9f5fb0061cdedc05a37170254694dffec6b89920a6e767f08c4220"
|
||||
"checksum redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)" = "52ee9a534dc1301776eff45b4fa92d2c39b1d8c3d3357e6eb593e0d795506fc2"
|
||||
"checksum redox_users 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "214a97e49be64fd2c86f568dd0cb2c757d2cc53de95b273b6ad0a1c908482f26"
|
||||
"checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619"
|
||||
"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7"
|
||||
"checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8"
|
||||
"checksum sdl2 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a74c2a98a354b20713b90cce70aef9e927e46110d1bc4ef728fd74e0d53eba60"
|
||||
"checksum sdl2-sys 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5c543ce8a6e33a30cb909612eeeb22e693848211a84558d5a00bb11e791b7ab7"
|
||||
"checksum serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)" = "0e732ed5a5592c17d961555e3b552985baf98d50ce418b7b655f31f6ba7eb1b7"
|
||||
"checksum serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d6115a3ca25c224e409185325afc16a0d5aaaabc15c42b09587d6f1ba39a5b"
|
||||
"checksum serde_json 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)" = "bdf540260cfee6da923831f4776ddc495ada940c30117977c70f1313a6130545"
|
||||
"checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741"
|
||||
"checksum syn 0.15.23 (registry+https://github.com/rust-lang/crates.io-index)" = "9545a6a093a3f0bd59adb472700acc08cad3776f860f16a897dfce8c88721cbc"
|
||||
"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015"
|
||||
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
||||
"checksum vec_map 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cac5efe5cb0fa14ec2f84f83c701c562ee63f6dcc680861b21d65c682adfb05f"
|
||||
"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0"
|
||||
|
@ -7,6 +7,10 @@ edition = "2018"
|
||||
[dependencies]
|
||||
rand = "0.5"
|
||||
plex = "*"
|
||||
dirs = "*"
|
||||
serde = "*"
|
||||
serde_json = "*"
|
||||
serde_derive = "*"
|
||||
|
||||
[dependencies.sdl2]
|
||||
version = "0.31.0"
|
||||
|
56
assets/theme.txt
Normal file
56
assets/theme.txt
Normal file
@ -0,0 +1,56 @@
|
||||
```railscasts
|
||||
|
||||
``comment
|
||||
#BC9358
|
||||
italic
|
||||
|
||||
``escaped character
|
||||
#509E4F
|
||||
|
||||
``class
|
||||
#FFF
|
||||
|
||||
``constant
|
||||
#FFF
|
||||
|
||||
``float
|
||||
#A4C260
|
||||
|
||||
``function
|
||||
#FFC56D
|
||||
|
||||
``global variable
|
||||
#D0CFFE
|
||||
|
||||
``integer
|
||||
#A4C260
|
||||
|
||||
``inline code
|
||||
#151515
|
||||
|
||||
``instance variable
|
||||
#D0CFFE
|
||||
|
||||
``doctype
|
||||
#E7BE69
|
||||
|
||||
``keyword
|
||||
#CB7832
|
||||
|
||||
``keyword
|
||||
#CB7832
|
||||
|
||||
``regex
|
||||
#A4C260
|
||||
|
||||
``string
|
||||
#A4C260
|
||||
|
||||
``symbol
|
||||
#6C9CBD
|
||||
|
||||
``html tag
|
||||
#E7BE69
|
||||
|
||||
``boolean
|
||||
#6C9CBD
|
@ -2,43 +2,54 @@ use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use std::boxed::Box;
|
||||
use crate::app::{UpdateResult, WindowCanvas};
|
||||
use crate::ui::*;
|
||||
use crate::ui::caret::Caret;
|
||||
use crate::file::*;
|
||||
use crate::renderer::Renderer;
|
||||
use crate::file::editor_file::EditorFile;
|
||||
use crate::renderer::Renderer;
|
||||
|
||||
pub struct AppState<'a> {
|
||||
pub files: Vec<EditorFile<'a>>,
|
||||
pub struct AppState {
|
||||
pub files: Vec<EditorFile>,
|
||||
pub current_file: i16,
|
||||
caret: Caret,
|
||||
}
|
||||
|
||||
impl<'a> AppState<'a> {
|
||||
impl AppState {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
files: vec![],
|
||||
current_file: -1,
|
||||
caret: Caret::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn open_file(&mut self, file_path: String, renderer: &mut Renderer) {
|
||||
pub fn open_file(&mut self, file_path: String) {
|
||||
use std::fs::read_to_string;
|
||||
if let Ok(buffer) = read_to_string(&file_path) {
|
||||
println!("read: {}\n{}", file_path, buffer);
|
||||
let file = EditorFile::new(file_path.clone(), buffer, renderer);
|
||||
let file = EditorFile::new(file_path.clone(), buffer);
|
||||
self.current_file = self.files.len() as i16;
|
||||
self.files.push(file);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self, ticks: i32) -> UpdateResult {
|
||||
if let Some(ref mut file) = self.files.get(self.current_file as usize) {
|
||||
file.update(ticks);
|
||||
}
|
||||
UpdateResult::NoOp
|
||||
}
|
||||
|
||||
pub fn render(&mut self, canvas: &mut WindowCanvas, renderer: &mut Renderer) {
|
||||
if let Some(ref mut file) = self.files.get(self.current_file as usize) {
|
||||
impl Render for AppState {
|
||||
fn render(&mut self, canvas: &mut WindowCanvas, renderer: &mut Renderer) -> UpdateResult {
|
||||
if let Some(file) = self.files.get_mut(self.current_file as usize) {
|
||||
file.render(canvas, renderer);
|
||||
}
|
||||
self.caret.render(canvas, renderer);
|
||||
UpdateResult::NoOp
|
||||
}
|
||||
}
|
||||
|
||||
impl Update for AppState {
|
||||
fn update(&mut self, ticks: i32) -> UpdateResult {
|
||||
if let Some(file) = self.files.get_mut(self.current_file as usize) {
|
||||
file.update(ticks);
|
||||
}
|
||||
self.caret.update(ticks);
|
||||
UpdateResult::NoOp
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
use crate::themes::Theme;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct EditorConfig {
|
||||
pub character_size: u16,
|
||||
@ -9,6 +11,7 @@ pub struct Config {
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
pub editor_config: EditorConfig,
|
||||
pub theme: Theme,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
@ -20,6 +23,7 @@ impl Config {
|
||||
character_size: 24,
|
||||
font_path: "./assets/fonts/hinted-ElaineSans-Medium.ttf".to_string(),
|
||||
},
|
||||
theme: Theme::load("default".to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,8 @@ pub type WindowCanvas = Canvas<Window>;
|
||||
|
||||
use crate::app::app_state::AppState;
|
||||
use crate::app::config::Config;
|
||||
use crate::themes::Theme;
|
||||
use crate::ui::*;
|
||||
use crate::renderer::Renderer;
|
||||
|
||||
#[derive(PartialEq, Clone, Debug)]
|
||||
@ -71,12 +73,13 @@ impl Application {
|
||||
let mut timer: TimerSubsystem = self.sdl_context.timer().unwrap();
|
||||
let mut event_pump = self.sdl_context.event_pump().unwrap();
|
||||
let font_context = sdl2::ttf::init().unwrap();
|
||||
let texture_creator = self.canvas.texture_creator();
|
||||
let sleep_time = Duration::new(0, 1_000_000_000u32 / 60);
|
||||
let mut app_state = AppState::new();
|
||||
let mut renderer = Renderer::new(
|
||||
self.config.clone(),
|
||||
&font_context,
|
||||
self.canvas.texture_creator()
|
||||
&texture_creator
|
||||
);
|
||||
|
||||
'running: loop {
|
||||
@ -89,14 +92,7 @@ impl Application {
|
||||
match task {
|
||||
Task::OpenFile { file_path } => {
|
||||
use crate::file::editor_file::*;
|
||||
app_state.open_file(file_path.clone(), &mut renderer);
|
||||
// use std::fs::read_to_string;
|
||||
// if let Ok(buffer) = read_to_string(&file_path) {
|
||||
// println!("read: {}\n{}", file_path, buffer);
|
||||
// let file = EditorFile::new(file_path.clone(), buffer, &mut renderer);
|
||||
// app_state.current_file = app_state.files.len() as i16;
|
||||
// app_state.files.push(file);
|
||||
// }
|
||||
app_state.open_file(file_path.clone());
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -1,19 +0,0 @@
|
||||
pub struct Caret<'a> {
|
||||
character: char,
|
||||
source: Rect,
|
||||
dest: Rect,
|
||||
visible: bool,
|
||||
texture: Option<Rc<Texture<'a>>>,
|
||||
}
|
||||
|
||||
impl<'a> Caret<'a> {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
character: '│',
|
||||
source: Rect::new(0, 0, 0, 0),
|
||||
dest: Rect::new(0, 0, 0, 0),
|
||||
visible: true,
|
||||
texture: None,
|
||||
}
|
||||
}
|
||||
}
|
@ -1,41 +1,22 @@
|
||||
use sdl2::rect::Rect;
|
||||
use crate::file::editor_file_section::EditorFileSection;
|
||||
use crate::renderer::Renderer;
|
||||
use crate::app::UpdateResult;
|
||||
use crate::app::WindowCanvas;
|
||||
use crate::app::{UpdateResult, WindowCanvas};
|
||||
use crate::ui::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct EditorFile<'l> {
|
||||
pub struct EditorFile {
|
||||
pub path: String,
|
||||
pub sections: Vec<EditorFileSection<'l>>,
|
||||
pub sections: Vec<EditorFileSection>,
|
||||
}
|
||||
|
||||
impl<'l> EditorFile<'l> {
|
||||
pub fn new(path: String, buffer: String, renderer: &'l mut Renderer) -> Self {
|
||||
let section = EditorFileSection::new(buffer, renderer);
|
||||
impl EditorFile {
|
||||
pub fn new(path: String, buffer: String) -> Self {
|
||||
let section = EditorFileSection::new(buffer);
|
||||
let sections = vec![section];
|
||||
Self { path, sections }
|
||||
}
|
||||
|
||||
pub fn update(&mut self, ticks: i32) -> UpdateResult {
|
||||
let mut result = UpdateResult::NoOp;
|
||||
for section in self.sections.iter_mut() {
|
||||
result = section.update(ticks);
|
||||
}
|
||||
|
||||
if result == UpdateResult::RefreshPositions {
|
||||
self.refresh_characters_position();
|
||||
result = UpdateResult::NoOp;
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
pub fn render(&self, canvas: &mut WindowCanvas, renderer: &mut Renderer) {
|
||||
for ref section in self.sections.iter() {
|
||||
section.render(canvas, renderer);
|
||||
}
|
||||
}
|
||||
|
||||
fn refresh_characters_position(&mut self) {
|
||||
let mut current: Rect = Rect::new(0, 0, 0, 0);
|
||||
for section in self.sections.iter_mut() {
|
||||
@ -43,3 +24,29 @@ impl<'l> EditorFile<'l> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for EditorFile {
|
||||
fn render(&mut self, canvas: &mut WindowCanvas, renderer: &mut Renderer) -> UpdateResult {
|
||||
let mut res = UpdateResult::NoOp;
|
||||
for section in self.sections.iter_mut() {
|
||||
res = section.render(canvas, renderer);
|
||||
}
|
||||
if res == UpdateResult::RefreshPositions {
|
||||
self.refresh_characters_position();
|
||||
for section in self.sections.iter_mut() {
|
||||
section.render(canvas, renderer);
|
||||
}
|
||||
}
|
||||
UpdateResult::NoOp
|
||||
}
|
||||
}
|
||||
|
||||
impl Update for EditorFile {
|
||||
fn update(&mut self, ticks: i32) -> UpdateResult {
|
||||
let mut result = UpdateResult::NoOp;
|
||||
for section in self.sections.iter_mut() {
|
||||
result = section.update(ticks);
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
|
@ -4,48 +4,54 @@ use crate::app::UpdateResult;
|
||||
use crate::app::WindowCanvas;
|
||||
use crate::renderer::Renderer;
|
||||
use crate::file::editor_file_token::EditorFileToken;
|
||||
use crate::ui::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct EditorFileSection<'l> {
|
||||
pub tokens: Vec<EditorFileToken<'l>>,
|
||||
pub struct EditorFileSection {
|
||||
pub tokens: Vec<EditorFileToken>,
|
||||
pub language: Language,
|
||||
}
|
||||
|
||||
impl<'l> EditorFileSection<'l> {
|
||||
pub fn new(buffer: String, renderer: &'l mut Renderer) -> Self {
|
||||
impl EditorFileSection {
|
||||
pub fn new(buffer: String) -> Self {
|
||||
use crate::lexer;
|
||||
let lexer_tokens = lexer::parse(buffer.clone(), Language::PlainText);
|
||||
|
||||
let mut tokens: Vec<EditorFileToken> = vec![];
|
||||
for token_type in lexer_tokens {
|
||||
let token = EditorFileToken::new(
|
||||
renderer,
|
||||
token_type.get_start(),
|
||||
token_type.clone(),
|
||||
);
|
||||
let token = EditorFileToken::new(token_type);
|
||||
tokens.push(token.clone());
|
||||
}
|
||||
let language = Language::PlainText;
|
||||
Self { tokens, language }
|
||||
}
|
||||
|
||||
pub fn update(&mut self, ticks: i32) -> UpdateResult {
|
||||
let mut result = UpdateResult::NoOp;
|
||||
for file_char in self.tokens.iter_mut() {
|
||||
result = file_char.update(ticks)
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
pub fn render(&self, canvas: &mut WindowCanvas, renderer: &mut Renderer) {
|
||||
for ref character in self.tokens.iter() {
|
||||
character.render(canvas, renderer);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_positions(&mut self, current: &mut Rect) {
|
||||
for c in self.tokens.iter_mut() {
|
||||
c.update_position(current);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for EditorFileSection {
|
||||
fn render(&mut self, canvas: &mut WindowCanvas, renderer: &mut Renderer) -> UpdateResult {
|
||||
let mut res = UpdateResult::NoOp;
|
||||
for character in self.tokens.iter_mut() {
|
||||
let r = character.render(canvas, renderer);
|
||||
if res == UpdateResult::NoOp {
|
||||
res = r;
|
||||
}
|
||||
}
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl Update for EditorFileSection {
|
||||
fn update(&mut self, ticks: i32) -> UpdateResult {
|
||||
let mut result = UpdateResult::NoOp;
|
||||
for file_char in self.tokens.iter_mut() {
|
||||
result = file_char.update(ticks)
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
|
@ -2,116 +2,90 @@ use std::rc::Rc;
|
||||
use sdl2::rect::Rect;
|
||||
use sdl2::render::Texture;
|
||||
use sdl2::ttf::Font;
|
||||
use sdl2::pixels::Color;
|
||||
|
||||
use crate::lexer::TokenType;
|
||||
use crate::renderer::Renderer;
|
||||
use crate::renderer::managers::TextDetails;
|
||||
use crate::renderer::resolve_color::resolve_color;
|
||||
use crate::app::UpdateResult;
|
||||
use crate::app::WindowCanvas;
|
||||
use crate::app::{UpdateResult, WindowCanvas};
|
||||
use crate::renderer::managers::FontDetails;
|
||||
use crate::ui::*;
|
||||
use crate::ui::text_character::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct EditorFileToken<'l> {
|
||||
pos: usize,
|
||||
text: String,
|
||||
font_size: u16,
|
||||
pub struct TextCharacterMeasure {
|
||||
source: Rect,
|
||||
dest: Rect,
|
||||
token_type: TokenType,
|
||||
texture: Option<Rc<Texture<'l>>>,
|
||||
}
|
||||
|
||||
impl<'l> EditorFileToken<'l> {
|
||||
pub fn new(renderer: &'l mut Renderer, pos: usize, token_type: TokenType) -> Self {
|
||||
let c = match token_type {
|
||||
_ if token_type.is_space() => "°".to_string(),
|
||||
_ if token_type.is_new_line() => "\n".to_string(),
|
||||
TokenType::Whitespace { .. } => "°".to_string(),
|
||||
_ => token_type.get_text(),
|
||||
};
|
||||
let details = TextDetails {
|
||||
text: c.clone(),
|
||||
font_details: FontDetails::new(
|
||||
renderer.config.editor_config.font_path.as_str(),
|
||||
renderer.config.editor_config.character_size.clone(),
|
||||
),
|
||||
color: resolve_color(&token_type),
|
||||
};
|
||||
#[derive(Clone)]
|
||||
pub struct EditorFileToken {
|
||||
characters: Vec<TextCharacter>,
|
||||
token_type: TokenType,
|
||||
}
|
||||
|
||||
impl Into<Color> for TokenType {
|
||||
fn into(self) -> Color {
|
||||
match &self {
|
||||
&TokenType::Whitespace { .. } => Color::RGBA(220, 220, 220, 90),
|
||||
_ => Color::RGBA(0, 0, 0, 0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl EditorFileToken {
|
||||
pub fn new(token_type: TokenType) -> Self {
|
||||
Self {
|
||||
pos,
|
||||
text: c,
|
||||
font_size: 0,
|
||||
source: Rect::new(0, 0, 0, 0),
|
||||
dest: Rect::new(0, 0, 0, 0),
|
||||
characters: vec![],
|
||||
token_type,
|
||||
texture: renderer.render_text(details).clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self, _ticks: i32) -> UpdateResult {
|
||||
// if self.font_size != config.editor_config.character_size {
|
||||
// self.update_view(renderer);
|
||||
// return UpdateResult::RefreshPositions;
|
||||
// }
|
||||
UpdateResult::NoOp
|
||||
}
|
||||
|
||||
pub fn render(&self, canvas: &mut WindowCanvas, renderer: &mut Renderer) {
|
||||
if self.token_type.is_new_line() {
|
||||
return;
|
||||
}
|
||||
match &self.texture {
|
||||
Some(texture) => {
|
||||
renderer.render_texture(canvas, &texture, &self.source, &self.dest)
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_position(&mut self, current: &mut Rect) {
|
||||
match self.token_type {
|
||||
_ if self.token_type.is_new_line() => {
|
||||
current.set_x(0);
|
||||
current.set_y(
|
||||
(self.token_type.line() as usize * self.source.height() as usize) as i32,
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
self.dest.set_x(current.x());
|
||||
self.dest.set_y(current.y());
|
||||
self.dest.set_width(self.source.width());
|
||||
self.dest.set_height(self.source.height());
|
||||
current.set_x(self.dest.x() + self.source.width() as i32);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn update_view(&mut self, renderer: &mut Renderer) {
|
||||
self.font_size = renderer.config.editor_config.character_size.clone();
|
||||
let font_details = FontDetails::new(
|
||||
renderer.config.editor_config.font_path.as_str(),
|
||||
self.font_size.clone(),
|
||||
);
|
||||
|
||||
if let Ok(font) = renderer.font_manager.load(&font_details) {
|
||||
if let Some((width, height)) = self.measure_text(&font) {
|
||||
self.source.set_width(width as u32);
|
||||
self.source.set_height(height as u32);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn measure_text(&self, font: &Rc<Font>) -> Option<(usize, usize)> {
|
||||
let mut w: usize = 0;
|
||||
let mut h: usize = 0;
|
||||
for c in self.text.chars() {
|
||||
if let Ok((width, height)) = font.size_of_char(c) {
|
||||
w += width as usize;
|
||||
h = height as usize;
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
for text_character in self.characters.iter_mut() {
|
||||
text_character.update_position(current);
|
||||
}
|
||||
Some((w, h))
|
||||
}
|
||||
|
||||
fn update_view(&mut self, renderer: &mut Renderer) -> UpdateResult {
|
||||
for c in self.token_type.text().chars() {
|
||||
let mut text_character = TextCharacter::new(
|
||||
c.clone(),
|
||||
self.token_type.line(),
|
||||
self.token_type.clone().into(),
|
||||
);
|
||||
text_character.update_view(renderer);
|
||||
self.characters.push(text_character);
|
||||
}
|
||||
|
||||
UpdateResult::RefreshPositions
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for EditorFileToken {
|
||||
/**
|
||||
* Must first create targets so even if new line appear renderer will know
|
||||
* where move render starting point
|
||||
*/
|
||||
fn render(&mut self, canvas: &mut WindowCanvas, renderer: &mut Renderer) -> UpdateResult {
|
||||
if self.characters.is_empty() {
|
||||
return self.update_view(renderer);
|
||||
}
|
||||
if self.token_type.is_new_line() {
|
||||
return UpdateResult::NoOp;
|
||||
}
|
||||
for text_character in self.characters.iter_mut() {
|
||||
text_character.render(canvas, renderer);
|
||||
}
|
||||
UpdateResult::NoOp
|
||||
}
|
||||
}
|
||||
|
||||
impl Update for EditorFileToken {
|
||||
fn update(&mut self, ticks: i32) -> UpdateResult {
|
||||
for text_character in self.characters.iter_mut() {
|
||||
text_character.update(ticks);
|
||||
}
|
||||
UpdateResult::NoOp
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,10 @@ pub enum TokenType {
|
||||
String { token: Token },
|
||||
Number { token: Token },
|
||||
Identifier { token: Token },
|
||||
Literal { token: Token },
|
||||
Comment { token: Token },
|
||||
Operator { token: Token },
|
||||
Separator { token: Token },
|
||||
}
|
||||
|
||||
impl TokenType {
|
||||
@ -34,42 +38,34 @@ impl TokenType {
|
||||
TokenType::Identifier { token } => TokenType::Identifier {
|
||||
token: token.move_to(line, character, start, end),
|
||||
},
|
||||
TokenType::Literal { token } => TokenType::Literal {
|
||||
token: token.move_to(line, character, start, end),
|
||||
},
|
||||
TokenType::Comment { token } => TokenType::Comment {
|
||||
token: token.move_to(line, character, start, end),
|
||||
},
|
||||
TokenType::Operator { token } => TokenType::Operator {
|
||||
token: token.move_to(line, character, start, end),
|
||||
},
|
||||
TokenType::Separator { token } => TokenType::Separator {
|
||||
token: token.move_to(line, character, start, end),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_new_line(&self) -> bool {
|
||||
match self {
|
||||
TokenType::Whitespace { token } => token.text() == "\n".to_string(),
|
||||
TokenType::Whitespace { token } => token.text().as_str() == "\n",
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_space(&self) -> bool {
|
||||
match self {
|
||||
TokenType::Whitespace { token } => token.text() == " ".to_string(),
|
||||
TokenType::Whitespace { token } => token.text().as_str() == " ",
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_start(&self) -> usize {
|
||||
match self {
|
||||
TokenType::Whitespace { token } => token.start(),
|
||||
TokenType::Keyword { token } => token.start(),
|
||||
TokenType::String { token } => token.start(),
|
||||
TokenType::Number { token } => token.start(),
|
||||
TokenType::Identifier { token } => token.start(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_text(&self) -> String {
|
||||
match self {
|
||||
TokenType::Whitespace { token } => token.text(),
|
||||
TokenType::Keyword { token } => token.text(),
|
||||
TokenType::String { token } => token.text(),
|
||||
TokenType::Number { token } => token.text(),
|
||||
TokenType::Identifier { token } => token.text(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for TokenType {
|
||||
@ -82,6 +78,10 @@ impl Deref for TokenType {
|
||||
TokenType::String { token } => token,
|
||||
TokenType::Number { token } => token,
|
||||
TokenType::Identifier { token } => token,
|
||||
TokenType::Literal { token } => token,
|
||||
TokenType::Comment { token } => token,
|
||||
TokenType::Operator { token } => token,
|
||||
TokenType::Separator { token } => token,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -112,8 +112,8 @@ impl Token {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn text(&self) -> String {
|
||||
self.text.clone()
|
||||
pub fn text(&self) -> &String {
|
||||
&self.text
|
||||
}
|
||||
|
||||
pub fn line(&self) -> usize {
|
||||
@ -146,7 +146,7 @@ impl Token {
|
||||
pub fn parse(text: String, language: Language) -> Vec<TokenType> {
|
||||
match language {
|
||||
Language::PlainText => plain::lexer::Lexer::new(text.as_str())
|
||||
.inspect(|tok| eprintln!("tok: {:?}", tok))
|
||||
.inspect(|tok| println!("tok: {:?}", tok))
|
||||
.map(|t| t.0)
|
||||
.collect(),
|
||||
}
|
||||
|
10
src/main.rs
10
src/main.rs
@ -1,14 +1,22 @@
|
||||
#![allow(unused_imports)]
|
||||
#![feature(use_extern_macros)]
|
||||
|
||||
extern crate plex;
|
||||
extern crate rand;
|
||||
extern crate sdl2;
|
||||
extern crate dirs;
|
||||
#[macro_use]
|
||||
extern crate serde;
|
||||
#[macro_use]
|
||||
extern crate serde_json;
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
pub mod app;
|
||||
pub mod ui;
|
||||
pub mod file;
|
||||
pub mod lexer;
|
||||
pub mod renderer;
|
||||
pub mod themes;
|
||||
|
||||
use crate::app::Application;
|
||||
|
||||
|
@ -26,16 +26,15 @@ pub struct FontDetails {
|
||||
pub struct TextDetails {
|
||||
pub text: String,
|
||||
pub color: Color,
|
||||
pub font_details: FontDetails,
|
||||
pub font: FontDetails,
|
||||
}
|
||||
|
||||
impl TextDetails {
|
||||
pub fn get_cache_key(&self) -> String {
|
||||
format!(
|
||||
"text({}) size({}) {:?}",
|
||||
self.text, self.font_details.size, self.color
|
||||
)
|
||||
.to_string()
|
||||
self.text, self.font.size, self.color
|
||||
).to_string()
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,7 +43,7 @@ impl<'a> From<&'a TextDetails> for TextDetails {
|
||||
Self {
|
||||
text: details.text.clone(),
|
||||
color: details.color.clone(),
|
||||
font_details: details.font_details.clone(),
|
||||
font: details.font.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -72,28 +71,28 @@ pub type FontManager<'l> = ResourceManager<'l, FontDetails, Font<'l, 'static>, S
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ResourceManager<'l, K, R, L>
|
||||
where
|
||||
K: Hash + Eq,
|
||||
L: 'l + ResourceLoader<'l, R>,
|
||||
where
|
||||
K: Hash + Eq,
|
||||
L: 'l + ResourceLoader<'l, R>,
|
||||
{
|
||||
loader: &'l L,
|
||||
cache: HashMap<K, Rc<R>>,
|
||||
}
|
||||
|
||||
impl<'l, K, R, L> ResourceManager<'l, K, R, L>
|
||||
where
|
||||
K: Hash + Eq,
|
||||
L: ResourceLoader<'l, R>,
|
||||
where
|
||||
K: Hash + Eq,
|
||||
L: ResourceLoader<'l, R>,
|
||||
{
|
||||
pub fn new(loader: &'l L) -> Self {
|
||||
Self { cache: HashMap::new(), loader }
|
||||
}
|
||||
|
||||
pub fn load<D>(&mut self, details: &D) -> Result<Rc<R>, String>
|
||||
where
|
||||
L: ResourceLoader<'l, R, Args = D>,
|
||||
D: Eq + Hash + ?Sized,
|
||||
K: Borrow<D> + for<'a> From<&'a D>,
|
||||
where
|
||||
L: ResourceLoader<'l, R, Args=D>,
|
||||
D: Eq + Hash + ?Sized,
|
||||
K: Borrow<D> + for<'a> From<&'a D>,
|
||||
{
|
||||
self.cache.get(details).cloned().map_or_else(
|
||||
|| {
|
||||
@ -104,6 +103,10 @@ where
|
||||
Ok,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn loader(&self) -> &L {
|
||||
self.loader
|
||||
}
|
||||
}
|
||||
|
||||
impl<'l, T> ResourceLoader<'l, Texture<'l>> for TextureCreator<T> {
|
||||
@ -124,25 +127,25 @@ impl<'l> ResourceLoader<'l, Font<'l, 'static>> for Sdl2TtfContext {
|
||||
}
|
||||
}
|
||||
|
||||
//impl<'l, T> TextureManager<'l, T> {
|
||||
// pub fn load_text(
|
||||
// &mut self,
|
||||
// details: &mut TextDetails,
|
||||
// font: &Font,
|
||||
// ) -> Result<Rc<Texture<'l>>, String> {
|
||||
// let key = details.get_cache_key();
|
||||
// self.cache.get(key.as_str()).cloned().map_or_else(
|
||||
// || {
|
||||
// let surface = font
|
||||
// .render(details.text.as_str())
|
||||
// .blended(details.color)
|
||||
// .unwrap();
|
||||
// let texture = self.loader.create_texture_from_surface(&surface).unwrap();
|
||||
// let resource = Rc::new(texture);
|
||||
// self.cache.insert(key, resource.clone());
|
||||
// Ok(resource)
|
||||
// },
|
||||
// Ok,
|
||||
// )
|
||||
// }
|
||||
//}
|
||||
impl<'l, T> TextureManager<'l, T> {
|
||||
pub fn load_text(
|
||||
&mut self,
|
||||
details: &mut TextDetails,
|
||||
font: &Rc<Font>,
|
||||
) -> Result<Rc<Texture<'l>>, String> {
|
||||
let key = details.get_cache_key();
|
||||
self.cache.get(key.as_str()).cloned().map_or_else(
|
||||
|| {
|
||||
let surface = font
|
||||
.render(details.text.as_str())
|
||||
.blended(details.color)
|
||||
.unwrap();
|
||||
let texture = self.loader.create_texture_from_surface(&surface).unwrap();
|
||||
let resource = Rc::new(texture);
|
||||
self.cache.insert(key, resource.clone());
|
||||
Ok(resource)
|
||||
},
|
||||
Ok,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
pub mod managers;
|
||||
pub mod resolve_color;
|
||||
|
||||
use crate::renderer::managers::{FontManager, TextureManager};
|
||||
|
||||
@ -18,7 +17,6 @@ pub struct Renderer<'a> {
|
||||
pub config: Config,
|
||||
pub font_manager: FontManager<'a>,
|
||||
pub texture_manager: TextureManager<'a, WindowContext>,
|
||||
pub texture_creator: TextureCreator<WindowContext>,
|
||||
pub scroll: Point,
|
||||
}
|
||||
|
||||
@ -26,13 +24,12 @@ impl<'a> Renderer<'a> {
|
||||
pub fn new(
|
||||
config: Config,
|
||||
font_context: &'a Sdl2TtfContext,
|
||||
texture_creator: TextureCreator<WindowContext>,
|
||||
texture_creator: &'a TextureCreator<WindowContext>,
|
||||
) -> Self {
|
||||
Self {
|
||||
config,
|
||||
font_manager: FontManager::new(&font_context),
|
||||
texture_manager: TextureManager::new(&texture_creator),
|
||||
texture_creator,
|
||||
scroll: (0, 0).into(),
|
||||
}
|
||||
}
|
||||
@ -52,7 +49,7 @@ impl<'a> Renderer<'a> {
|
||||
}
|
||||
|
||||
pub fn render_text(&mut self, details: TextDetails) -> Option<Rc<Texture>> {
|
||||
let font = self.font_manager.load(&details.font_details).unwrap();
|
||||
let font = self.font_manager.load(&details.font).unwrap();
|
||||
let surface = font
|
||||
.render(details.text.as_str())
|
||||
.blended(details.color);
|
||||
@ -62,7 +59,8 @@ impl<'a> Renderer<'a> {
|
||||
return None;
|
||||
};
|
||||
let texture = self
|
||||
.texture_creator
|
||||
.texture_manager
|
||||
.loader()
|
||||
.create_texture_from_surface(&surface);
|
||||
let texture = if let Ok(t) = texture {
|
||||
Rc::new(t)
|
||||
|
@ -1,10 +0,0 @@
|
||||
use sdl2::pixels::Color;
|
||||
|
||||
use crate::lexer::TokenType;
|
||||
|
||||
pub fn resolve_color(token_type: &TokenType) -> Color {
|
||||
match token_type {
|
||||
&TokenType::Whitespace { .. } => Color::RGBA(220, 220, 220, 90),
|
||||
_ => Color::RGBA(0, 0, 0, 0),
|
||||
}
|
||||
}
|
376
src/themes/mod.rs
Normal file
376
src/themes/mod.rs
Normal file
@ -0,0 +1,376 @@
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
use std::env;
|
||||
use sdl2::pixels::Color;
|
||||
use serde_json;
|
||||
use serde::ser::{Serialize, Serializer, SerializeSeq, SerializeMap};
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
|
||||
pub struct SerdeColor {
|
||||
pub r: u8,
|
||||
pub g: u8,
|
||||
pub b: u8,
|
||||
pub a: u8
|
||||
}
|
||||
|
||||
impl SerdeColor {
|
||||
pub fn new(r: u8,g: u8,b: u8,a: u8) -> Self {
|
||||
Self { r,g,b,a }
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<Color> for SerdeColor {
|
||||
fn into(self) -> Color {
|
||||
Color {
|
||||
r: self.r,
|
||||
g: self.g,
|
||||
b: self.b,
|
||||
a: self.a
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
|
||||
pub struct ThemeConfig {
|
||||
color: SerdeColor,
|
||||
italic: bool,
|
||||
bold: bool,
|
||||
}
|
||||
|
||||
impl ThemeConfig {
|
||||
pub fn color(&self) -> &SerdeColor {
|
||||
&self.color
|
||||
}
|
||||
|
||||
pub fn italic(&self) -> bool {
|
||||
self.italic
|
||||
}
|
||||
|
||||
pub fn bold(&self) -> bool {
|
||||
self.bold
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
|
||||
pub struct CaretColor {
|
||||
bright: ThemeConfig,
|
||||
blur: ThemeConfig,
|
||||
}
|
||||
|
||||
impl Default for CaretColor {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
bright: ThemeConfig {
|
||||
color: SerdeColor::new(0, 0, 0, 0),
|
||||
italic: false,
|
||||
bold: false,
|
||||
},
|
||||
blur: ThemeConfig {
|
||||
color: SerdeColor::new(0, 0, 0, 0),
|
||||
italic: false,
|
||||
bold: false,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CaretColor {
|
||||
pub fn bright(&self) -> &ThemeConfig {
|
||||
&self.bright
|
||||
}
|
||||
|
||||
pub fn blur(&self) -> &ThemeConfig {
|
||||
&self.blur
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
|
||||
pub struct CodeHighlightingColor {
|
||||
whitespace: ThemeConfig,
|
||||
keyword: ThemeConfig,
|
||||
string: ThemeConfig,
|
||||
number: ThemeConfig,
|
||||
identifier: ThemeConfig,
|
||||
literal: ThemeConfig,
|
||||
comment: ThemeConfig,
|
||||
operator: ThemeConfig,
|
||||
separator: ThemeConfig,
|
||||
}
|
||||
|
||||
impl Default for CodeHighlightingColor {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
whitespace: ThemeConfig {
|
||||
color: SerdeColor::new(0, 0, 0, 0),
|
||||
bold: false,
|
||||
italic: false,
|
||||
},
|
||||
keyword: ThemeConfig {
|
||||
color: SerdeColor::new(0, 0, 0, 0),
|
||||
bold: false,
|
||||
italic: false,
|
||||
},
|
||||
string: ThemeConfig {
|
||||
color: SerdeColor::new(0, 0, 0, 0),
|
||||
bold: false,
|
||||
italic: false,
|
||||
},
|
||||
number: ThemeConfig {
|
||||
color: SerdeColor::new(0, 0, 0, 0),
|
||||
bold: false,
|
||||
italic: false,
|
||||
},
|
||||
identifier: ThemeConfig {
|
||||
color: SerdeColor::new(0, 0, 0, 0),
|
||||
bold: false,
|
||||
italic: false,
|
||||
},
|
||||
literal: ThemeConfig {
|
||||
color: SerdeColor::new(0, 0, 0, 0),
|
||||
bold: false,
|
||||
italic: false,
|
||||
},
|
||||
comment: ThemeConfig {
|
||||
color: SerdeColor::new(0, 0, 0, 0),
|
||||
bold: false,
|
||||
italic: false,
|
||||
},
|
||||
operator: ThemeConfig {
|
||||
color: SerdeColor::new(0, 0, 0, 0),
|
||||
bold: false,
|
||||
italic: false,
|
||||
},
|
||||
separator: ThemeConfig {
|
||||
color: SerdeColor::new(0, 0, 0, 0),
|
||||
bold: false,
|
||||
italic: false,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CodeHighlightingColor {
|
||||
pub fn whitespace(&self) -> &ThemeConfig {
|
||||
&self.whitespace
|
||||
}
|
||||
|
||||
pub fn keyword(&self) -> &ThemeConfig {
|
||||
&self.keyword
|
||||
}
|
||||
|
||||
pub fn string(&self) -> &ThemeConfig {
|
||||
&self.string
|
||||
}
|
||||
|
||||
pub fn number(&self) -> &ThemeConfig {
|
||||
&self.number
|
||||
}
|
||||
|
||||
pub fn identifier(&self) -> &ThemeConfig {
|
||||
&self.identifier
|
||||
}
|
||||
|
||||
pub fn literal(&self) -> &ThemeConfig {
|
||||
&self.literal
|
||||
}
|
||||
|
||||
pub fn comment(&self) -> &ThemeConfig {
|
||||
&self.comment
|
||||
}
|
||||
|
||||
pub fn operator(&self) -> &ThemeConfig {
|
||||
&self.operator
|
||||
}
|
||||
|
||||
pub fn separator(&self) -> &ThemeConfig {
|
||||
&self.separator
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
|
||||
pub struct Theme {
|
||||
name: String,
|
||||
background: SerdeColor,
|
||||
caret: CaretColor,
|
||||
code_highlighting: CodeHighlightingColor,
|
||||
}
|
||||
|
||||
impl Default for Theme {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
name: "Default".to_string(),
|
||||
background: SerdeColor::new(255, 255, 255, 0),
|
||||
caret: CaretColor::default(),
|
||||
code_highlighting: CodeHighlightingColor::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Theme {
|
||||
pub fn name(&self) -> &String {
|
||||
&self.name
|
||||
}
|
||||
|
||||
pub fn background(&self) -> &SerdeColor {
|
||||
&self.background
|
||||
}
|
||||
|
||||
pub fn caret(&self) -> &CaretColor {
|
||||
&self.caret
|
||||
}
|
||||
|
||||
pub fn code_highlighting(&self) -> &CodeHighlightingColor {
|
||||
&self.code_highlighting
|
||||
}
|
||||
|
||||
fn railscasts() -> Self {
|
||||
Self {
|
||||
name: "railscasts".to_string(),
|
||||
background: SerdeColor {
|
||||
r: 60,
|
||||
g: 60,
|
||||
b: 60,
|
||||
a: 0
|
||||
},
|
||||
caret: CaretColor { bright: ThemeConfig {
|
||||
color: SerdeColor {
|
||||
r: 0,
|
||||
g: 0,
|
||||
b: 0,
|
||||
a: 0
|
||||
},
|
||||
italic: false,
|
||||
bold: false
|
||||
}, blur: ThemeConfig {
|
||||
color: SerdeColor {
|
||||
r: 0,
|
||||
g: 0,
|
||||
b: 0,
|
||||
a: 0
|
||||
},
|
||||
italic: false,
|
||||
bold: false
|
||||
} },
|
||||
code_highlighting: CodeHighlightingColor {
|
||||
whitespace: ThemeConfig {
|
||||
color: SerdeColor {
|
||||
r: 0,
|
||||
g: 0,
|
||||
b: 0,
|
||||
a: 0
|
||||
},
|
||||
italic: false,
|
||||
bold: false
|
||||
},
|
||||
keyword: ThemeConfig {
|
||||
color: SerdeColor {
|
||||
r: 203,
|
||||
g: 120,
|
||||
b: 50,
|
||||
a: 0
|
||||
},
|
||||
italic: false,
|
||||
bold: true
|
||||
},
|
||||
string: ThemeConfig {
|
||||
color: SerdeColor {
|
||||
r: 0,
|
||||
g: 0,
|
||||
b: 0,
|
||||
a: 0
|
||||
},
|
||||
italic: false,
|
||||
bold: false
|
||||
},
|
||||
number: ThemeConfig {
|
||||
color: SerdeColor {
|
||||
r: 0,
|
||||
g: 0,
|
||||
b: 0,
|
||||
a: 0
|
||||
},
|
||||
italic: false,
|
||||
bold: false
|
||||
},
|
||||
identifier: ThemeConfig {
|
||||
color: SerdeColor {
|
||||
r: 0,
|
||||
g: 0,
|
||||
b: 0,
|
||||
a: 0
|
||||
},
|
||||
italic: false,
|
||||
bold: false
|
||||
},
|
||||
literal: ThemeConfig {
|
||||
color: SerdeColor {
|
||||
r: 0,
|
||||
g: 0,
|
||||
b: 0,
|
||||
a: 0
|
||||
},
|
||||
italic: false,
|
||||
bold: false
|
||||
},
|
||||
comment: ThemeConfig {
|
||||
color: SerdeColor {
|
||||
r: 188,
|
||||
g: 147,
|
||||
b: 88,
|
||||
a: 0
|
||||
},
|
||||
italic: true,
|
||||
bold: false
|
||||
},
|
||||
operator: ThemeConfig {
|
||||
color: SerdeColor {
|
||||
r: 0,
|
||||
g: 0,
|
||||
b: 0,
|
||||
a: 0
|
||||
},
|
||||
italic: false,
|
||||
bold: false
|
||||
},
|
||||
separator: ThemeConfig {
|
||||
color: SerdeColor {
|
||||
r: 0,
|
||||
g: 0,
|
||||
b: 0,
|
||||
a: 0
|
||||
},
|
||||
italic: false,
|
||||
bold: false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load(_theme_name: String) -> Self {
|
||||
use dirs;
|
||||
let home_dir = dirs::config_dir().unwrap();
|
||||
let mut config_dir = home_dir.clone();
|
||||
config_dir.push("rider/themes");
|
||||
fs::create_dir_all(&config_dir)
|
||||
.unwrap_or_else(|_| panic!("Cannot create config directory"));
|
||||
let theme = Self::load_content(&config_dir, "default.json");
|
||||
println!("theme config:\n{:?}", theme);
|
||||
theme
|
||||
}
|
||||
|
||||
fn load_content(config_dir: &PathBuf, file_name: &str) -> Theme {
|
||||
let mut config_file = config_dir.clone();
|
||||
config_file.push(file_name);
|
||||
let contents = match fs::read_to_string(&config_file) {
|
||||
Ok(s) => s,
|
||||
Err(_) => {
|
||||
let contents = serde_json::to_string_pretty(&Theme::default())
|
||||
.unwrap();
|
||||
fs::write(&config_file, contents.clone())
|
||||
.unwrap_or_else(|_| panic!("Failed to crate theme config file"));
|
||||
contents.to_string()
|
||||
}
|
||||
};
|
||||
serde_json::from_str(&contents).unwrap_or_default()
|
||||
}
|
||||
}
|
68
src/ui/caret.rs
Normal file
68
src/ui/caret.rs
Normal file
@ -0,0 +1,68 @@
|
||||
use sdl2::rect::Rect;
|
||||
use sdl2::render::Texture;
|
||||
use sdl2::pixels::Color;
|
||||
use crate::app::{WindowCanvas, UpdateResult};
|
||||
use crate::ui::*;
|
||||
use crate::ui::text_character::TextCharacter;
|
||||
use crate::renderer::Renderer;
|
||||
|
||||
const CARET_CHARACTER: char = '│';
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
enum CaretState {
|
||||
Bright,
|
||||
Blur,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Caret {
|
||||
state: CaretState,
|
||||
bright_character: TextCharacter,
|
||||
blur_character: TextCharacter,
|
||||
blink_delay: u8,
|
||||
}
|
||||
|
||||
impl Caret {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
bright_character: TextCharacter::new(CARET_CHARACTER, 0, Color::RGBA(0, 0, 0, 0)),
|
||||
blur_character: TextCharacter::new(CARET_CHARACTER, 0, Color::RGBA(100, 100, 100, 0)),
|
||||
state: CaretState::Bright,
|
||||
blink_delay: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn toggle_state(&mut self) {
|
||||
self.state = if self.state == CaretState::Bright {
|
||||
CaretState::Blur
|
||||
} else {
|
||||
CaretState::Bright
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for Caret {
|
||||
fn render(&mut self, canvas: &mut WindowCanvas, renderer: &mut Renderer) -> UpdateResult {
|
||||
match self.state {
|
||||
CaretState::Bright => {
|
||||
self.bright_character.update_position(&mut Rect::new(100, 220, 0, 0));
|
||||
self.bright_character.render(canvas, renderer)
|
||||
},
|
||||
CaretState::Blur => {
|
||||
self.blur_character.update_position(&mut Rect::new(100, 220, 0, 0));
|
||||
self.blur_character.render(canvas, renderer)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Update for Caret {
|
||||
fn update(&mut self, _ticks: i32) -> UpdateResult {
|
||||
self.blink_delay += 1;
|
||||
if self.blink_delay >= 30 {
|
||||
self.blink_delay = 0;
|
||||
self.toggle_state();
|
||||
}
|
||||
UpdateResult::NoOp
|
||||
}
|
||||
}
|
13
src/ui/mod.rs
Normal file
13
src/ui/mod.rs
Normal file
@ -0,0 +1,13 @@
|
||||
pub mod caret;
|
||||
pub mod text_character;
|
||||
|
||||
use crate::renderer::Renderer;
|
||||
use crate::app::{WindowCanvas,UpdateResult};
|
||||
|
||||
pub trait Render {
|
||||
fn render(&mut self, canvas: &mut WindowCanvas, renderer: &mut Renderer) -> UpdateResult;
|
||||
}
|
||||
|
||||
pub trait Update {
|
||||
fn update(&mut self, ticks: i32) -> UpdateResult;
|
||||
}
|
141
src/ui/text_character.rs
Normal file
141
src/ui/text_character.rs
Normal file
@ -0,0 +1,141 @@
|
||||
use std::rc::Rc;
|
||||
use sdl2::rect::Rect;
|
||||
use sdl2::render::Texture;
|
||||
use sdl2::ttf::Font;
|
||||
use sdl2::pixels::Color;
|
||||
|
||||
use crate::lexer::TokenType;
|
||||
use crate::renderer::Renderer;
|
||||
use crate::renderer::managers::TextDetails;
|
||||
use crate::app::{UpdateResult, WindowCanvas};
|
||||
use crate::renderer::managers::FontDetails;
|
||||
use crate::ui::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct TextCharacter {
|
||||
pending: bool,
|
||||
text_character: char,
|
||||
line: usize,
|
||||
source: Rect,
|
||||
dest: Rect,
|
||||
color: Color,
|
||||
}
|
||||
|
||||
impl TextCharacter {
|
||||
pub fn new(text_character: char, line: usize, color: Color) -> Self {
|
||||
Self {
|
||||
pending: true,
|
||||
text_character,
|
||||
line,
|
||||
source: Rect::new(0, 0, 0, 0),
|
||||
dest: Rect::new(0, 0, 0, 0),
|
||||
color,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dest(&self) -> &Rect {
|
||||
&self.dest
|
||||
}
|
||||
|
||||
pub fn source(&self) -> &Rect {
|
||||
&self.source
|
||||
}
|
||||
|
||||
pub fn color(&self) -> &Color {
|
||||
&self.color
|
||||
}
|
||||
|
||||
pub fn update_position(&mut self, current: &mut Rect) {
|
||||
if self.is_new_line() {
|
||||
let y = (self.line * self.source.height() as usize) as i32;
|
||||
current.set_x(0);
|
||||
current.set_y(y);
|
||||
} else {
|
||||
self.dest.set_x(current.x());
|
||||
self.dest.set_y(current.y());
|
||||
self.dest.set_width(self.source.width());
|
||||
self.dest.set_height(self.source.height());
|
||||
current.set_x(self.dest.x() + self.source.width() as i32);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_view(&mut self, renderer: &mut Renderer) -> UpdateResult {
|
||||
let config = &renderer.config.editor_config;
|
||||
let font_details = FontDetails::new(
|
||||
config.font_path.as_str(),
|
||||
config.character_size.clone(),
|
||||
);
|
||||
let font = renderer.font_manager
|
||||
.load(&font_details)
|
||||
.unwrap_or_else(|_| panic!("Font not found {:?}", font_details));
|
||||
|
||||
let c = self.text_character.clone();
|
||||
if let Ok((width, height)) = font.size_of_char(c) {
|
||||
self.source = Rect::new(0, 0, width, height);
|
||||
self.dest = Rect::new(0, 0, width, height);
|
||||
}
|
||||
let mut details = TextDetails {
|
||||
text: c.to_string(),
|
||||
color: self.color.clone(),
|
||||
font: font_details.clone(),
|
||||
};
|
||||
renderer.texture_manager
|
||||
.load_text(&mut details, &font)
|
||||
.unwrap_or_else(|_| panic!("Could not create texture for {:?}", c));
|
||||
println!("texture for '{}' created", self.text_character);
|
||||
|
||||
self.pending = false;
|
||||
UpdateResult::RefreshPositions
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_new_line(&self) -> bool {
|
||||
self.text_character == '\n'
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_pending(&self) -> bool {
|
||||
self.pending
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for TextCharacter {
|
||||
/**
|
||||
* Must first create targets so even if new line appear renderer will know
|
||||
* where move render starting point
|
||||
*/
|
||||
fn render(&mut self, canvas: &mut WindowCanvas, renderer: &mut Renderer) -> UpdateResult {
|
||||
if self.is_pending() {
|
||||
return self.update_view(renderer);
|
||||
}
|
||||
if self.is_new_line() {
|
||||
return UpdateResult::NoOp;
|
||||
}
|
||||
|
||||
let config = &renderer.config.editor_config;
|
||||
let font_details = FontDetails::new(
|
||||
config.font_path.as_str(),
|
||||
config.character_size.clone(),
|
||||
);
|
||||
let font = renderer.font_manager
|
||||
.load(&font_details)
|
||||
.unwrap_or_else(|_| panic!("Could not load font for {:?}", font_details));
|
||||
|
||||
let c = self.text_character.clone();
|
||||
let mut details = TextDetails {
|
||||
text: c.to_string(),
|
||||
color: self.color.clone(),
|
||||
font: font_details.clone(),
|
||||
};
|
||||
if let Ok(texture) = renderer.texture_manager.load_text(&mut details, &font) {
|
||||
renderer.render_texture(canvas, &texture, &self.source, &self.dest);
|
||||
}
|
||||
UpdateResult::NoOp
|
||||
}
|
||||
}
|
||||
|
||||
impl Update for TextCharacter {
|
||||
fn update(&mut self, _ticks: i32) -> UpdateResult {
|
||||
UpdateResult::NoOp
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user