diff --git a/Cargo.lock b/Cargo.lock index 369be41..18445d1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6,9 +6,9 @@ version = "0.0.2" dependencies = [ "backend 0.1.0", "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossterm 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)", "ropey 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "termion 1.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -21,6 +21,11 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "arc-swap" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "atty" version = "0.2.14" @@ -44,6 +49,11 @@ name = "bitflags" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "clap" version = "2.33.0" @@ -58,6 +68,51 @@ dependencies = [ "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossterm" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossterm_winapi 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "signal-hook 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossterm_winapi" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fuchsia-zircon" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fuchsia-zircon-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "hermit-abi" version = "0.1.6" @@ -66,34 +121,120 @@ dependencies = [ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "iovec" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "libc" version = "0.2.66" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "lock_api" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "log" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "maybe-uninit" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "numtoa" -version = "0.1.0" +name = "mio" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "miow" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "net2" +version = "0.2.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lock_api 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot_core" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "redox_syscall" version = "0.1.56" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "redox_termios" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "ropey" version = "1.1.0" @@ -102,6 +243,35 @@ dependencies = [ "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "scopeguard" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "signal-hook" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", + "signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "signal-hook-registry" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arc-swap 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "slab" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "smallvec" version = "0.6.13" @@ -120,17 +290,6 @@ name = "strsim" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "termion" -version = "1.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "textwrap" version = "0.11.0" @@ -154,6 +313,11 @@ name = "vec_map" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "winapi" version = "0.3.8" @@ -163,6 +327,11 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -173,26 +342,56 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "ws2_32-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [metadata] "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +"checksum arc-swap 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d7b8a9123b8027467bce0099fe556c628a53c8d83df0507084c31e9ba2e39aff" "checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" +"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +"checksum crossterm 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5750773d74a7dc612eac2ded3f55e9cdeeaa072210cd17c0192aedb48adb3618" +"checksum crossterm_winapi 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8777c700901e2d5b50c406f736ed6b8f9e43645c7e104ddb74f8bc42b8ae62f6" +"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 hermit-abi 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eff2656d88f158ce120947499e971d743c05dbcbed62e5bd2f38f1698bbc3772" +"checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" "checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" +"checksum lock_api 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "79b2de95ecb4691949fea4716ca53cdbcfccb2c612e19644a8bad05edcf9f47b" +"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" "checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" -"checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" +"checksum mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)" = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f" +"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" +"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" +"checksum parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "92e98c49ab0b7ce5b222f2cc9193fc4efe11c6d0bd4f648e374684a6857b1cfc" +"checksum parking_lot_core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7582838484df45743c8434fbff785e8edf260c28748353d44bc0da32e0ceabf1" "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" -"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum ropey 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba326a8508a4add47e7b260333aa2d896213a5f3572fde11ed6e9130241b7f71" +"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" +"checksum signal-hook 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "7a9c17dd3ba2d36023a5c9472ecddeda07e27fd0b05436e8c1e0c8f178185652" +"checksum signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94f478ede9f64724c5d173d7bb56099ec3e2d9fc2774aac65d34b8b890405f41" +"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" "checksum smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44e59e0c9fa00817912ae6e4e6e3c4fe04455e75699d06eedc7d85917ed8e8f4" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" -"checksum termion 1.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c22cec9d8978d906be5ac94bceb5a010d885c626c4c8855721a4dbd20e3ac905" "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" "checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" +"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" diff --git a/Cargo.toml b/Cargo.toml index 769ab35..2ba5c5f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ unicode-segmentation = "1" unicode-width = "0.1" clap = "2" smallvec = "1" -termion = "1" +crossterm = "0.14" # Local crate dependencies [dependencies.backend] diff --git a/src/editor/mod.rs b/src/editor/mod.rs index 2dcbae8..bb8be80 100644 --- a/src/editor/mod.rs +++ b/src/editor/mod.rs @@ -255,7 +255,7 @@ impl Editor { /// Updates the view dimensions, and returns whether that /// actually changed anything. - pub fn update_dim(&mut self, h: usize, w: usize) -> bool { + pub fn update_dim(&mut self, h: usize, w: usize) { let line_count_digits = digit_count(self.buffer.line_count() as u32, 10) as usize; if self.editor_dim.0 != h || self.editor_dim.1 != w { self.editor_dim = (h, w); @@ -266,12 +266,8 @@ impl Editor { self.editor_dim.0 - 1, self.editor_dim.1 - line_count_digits - 1, ); - return true; } else if self.view_dim.1 != (self.editor_dim.1 - line_count_digits - 1) { self.view_dim.1 = self.editor_dim.1 - line_count_digits - 1; - return true; - } else { - return false; } } diff --git a/src/term_ui/mod.rs b/src/term_ui/mod.rs index b0bda73..d6ac41b 100644 --- a/src/term_ui/mod.rs +++ b/src/term_ui/mod.rs @@ -4,12 +4,12 @@ pub mod formatter; mod screen; pub mod smallstring; -use std; -use std::cmp::min; +use std::{cmp::min, time::Duration}; -use termion; -use termion::event::{Event, Key}; -use termion::input::TermRead; +use crossterm::{ + event::{Event, KeyCode, KeyEvent, KeyModifiers}, + style::Color, +}; use crate::{ editor::Editor, @@ -20,9 +20,11 @@ use crate::{ use self::{ formatter::ConsoleLineFormatter, - screen::{Color, Screen, Style}, + screen::{Screen, Style}, }; +const EMPTY_MOD: KeyModifiers = KeyModifiers::empty(); + /// Generalized ui loop. macro_rules! ui_loop { ($term_ui:ident,draw $draw:block,key_press($key:ident) $key_press:block) => { @@ -40,19 +42,31 @@ macro_rules! ui_loop { // Handle input loop { - match $term_ui.inp.next() { - Some(Ok(Event::Key($key))) => { - let (status, state_changed) = || -> (LoopStatus, bool) { $key_press }(); - should_redraw |= state_changed; - if status == LoopStatus::Done { - stop = true; + if crossterm::event::poll(Duration::from_millis(5)).unwrap() { + match crossterm::event::read().unwrap() { + Event::Key($key) => { + let (status, state_changed) = || -> (LoopStatus, bool) { $key_press }(); + should_redraw |= state_changed; + if status == LoopStatus::Done { + stop = true; + break; + } + } + + Event::Mouse(_) => { + break; + } + + Event::Resize(w, h) => { + $term_ui.width = w as usize; + $term_ui.height = h as usize; + $term_ui.screen.resize(w as usize, h as usize); + should_redraw = true; break; } } - - _ => { - break; - } + } else { + break; } } @@ -61,36 +75,26 @@ macro_rules! ui_loop { break; } - // Check for screen resize - let (w, h) = termion::terminal_size().unwrap(); - let needs_update = $term_ui.editor.update_dim(h as usize - 1, w as usize); - if needs_update { - $term_ui.width = w as usize; - $term_ui.height = h as usize; - $term_ui.screen.resize(w as usize, h as usize); + // Draw the editor to screen + if should_redraw { + // Make sure display dimensions are up-to-date. + $term_ui.editor.update_dim($term_ui.height, $term_ui.width); $term_ui .editor .formatter .set_wrap_width($term_ui.editor.view_dim.1); - should_redraw = true; - } - // Draw the editor to screen - if should_redraw { + // Draw! { $draw }; $term_ui.screen.present(); } - - // Sleep for a small bit so we don't just spin on the CPU - std::thread::sleep(std::time::Duration::from_millis(5)); } }; } pub struct TermUI { - inp: termion::input::Events, screen: Screen, editor: Editor, width: usize, @@ -110,12 +114,11 @@ impl TermUI { } pub fn new_from_editor(ed: Editor) -> TermUI { - let (w, h) = termion::terminal_size().unwrap(); + let (w, h) = crossterm::terminal::size().unwrap(); let mut editor = ed; editor.update_dim(h as usize - 1, w as usize); TermUI { - inp: termion::async_stdin().events(), screen: Screen::new(), editor: editor, width: w as usize, @@ -129,7 +132,7 @@ impl TermUI { self.screen.hide_cursor(); // Set terminal size info - let (w, h) = termion::terminal_size().unwrap(); + let (w, h) = crossterm::terminal::size().unwrap(); self.width = w as usize; self.height = h as usize; self.editor.update_dim(self.height - 1, self.width); @@ -150,74 +153,119 @@ impl TermUI { key_press(key) { let mut state_changed = true; match key { - Key::Ctrl('q') => { + KeyEvent { + code: KeyCode::Char('q'), + // modifiers: EMPTY_MOD, + modifiers: KeyModifiers::CONTROL, + } => { self.quit = true; return (LoopStatus::Done, true); } - Key::Ctrl('s') => { + KeyEvent { + code: KeyCode::Char('s'), + modifiers: KeyModifiers::CONTROL, + } => { self.editor.save_if_dirty(); } - Key::Ctrl('z') => { + KeyEvent { + code: KeyCode::Char('z'), + modifiers: KeyModifiers::CONTROL, + } => { self.editor.undo(); } - Key::Ctrl('y') => { + KeyEvent { + code: KeyCode::Char('y'), + modifiers: KeyModifiers::CONTROL, + } => { self.editor.redo(); } - Key::Ctrl('l') => { + KeyEvent { + code: KeyCode::Char('l'), + modifiers: KeyModifiers::CONTROL, + } => { self.go_to_line_ui_loop(); } - Key::PageUp => { + KeyEvent { + code: KeyCode::PageUp, + modifiers: EMPTY_MOD, + } => { self.editor.page_up(); } - Key::PageDown => { + KeyEvent { + code: KeyCode::PageDown, + modifiers: EMPTY_MOD, + } => { self.editor.page_down(); } - Key::Up => { + KeyEvent { + code: KeyCode::Up, + modifiers: EMPTY_MOD, + } => { self.editor.cursor_up(1); } - Key::Down => { + KeyEvent { + code: KeyCode::Down, + modifiers: EMPTY_MOD, + } => { self.editor.cursor_down(1); } - Key::Left => { + KeyEvent { + code: KeyCode::Left, + modifiers: EMPTY_MOD, + } => { self.editor.cursor_left(1); } - Key::Right => { + KeyEvent { + code: KeyCode::Right, + modifiers: EMPTY_MOD, + } => { self.editor.cursor_right(1); } - Key::Char('\n') => { + KeyEvent { + code: KeyCode::Enter, + modifiers: EMPTY_MOD, + } => { let nl = line_ending_to_str(self.editor.line_ending_type); self.editor.insert_text_at_cursor(nl); } - Key::Char(' ') => { - self.editor.insert_text_at_cursor(" "); - } - - Key::Char('\t') => { + KeyEvent { + code: KeyCode::Tab, + modifiers: EMPTY_MOD, + } => { self.editor.insert_tab_at_cursor(); } - Key::Backspace => { + KeyEvent { + code: KeyCode::Backspace, + modifiers: EMPTY_MOD, + } => { self.editor.backspace_at_cursor(); } - Key::Delete => { + KeyEvent { + code: KeyCode::Delete, + modifiers: EMPTY_MOD, + } => { self.editor.remove_text_in_front_of_cursor(1); } // Character - Key::Char(c) => { + KeyEvent { + code: KeyCode::Char(c), + modifiers: EMPTY_MOD, + } => { self.editor.insert_text_at_cursor(&c.to_string()[..]); } @@ -261,21 +309,41 @@ impl TermUI { key_press(key) { let mut state_changed = true; match key { - Key::Esc => { + KeyEvent { + code: KeyCode::Char('q'), + modifiers: KeyModifiers::CONTROL, + } => { + self.quit = true; + return (LoopStatus::Done, true); + } + + KeyEvent { + code: KeyCode::Esc, + modifiers: EMPTY_MOD, + } => { cancel = true; return (LoopStatus::Done, true); } - Key::Char('\n') => { + KeyEvent { + code: KeyCode::Enter, + modifiers: EMPTY_MOD, + } => { return (LoopStatus::Done, true); } - Key::Backspace => { + KeyEvent { + code: KeyCode::Backspace, + modifiers: EMPTY_MOD, + } => { line.pop(); } // Character - Key::Char(c) => { + KeyEvent { + code: KeyCode::Char(c), + modifiers: EMPTY_MOD, + } => { if c.is_numeric() { line.push(c); } diff --git a/src/term_ui/screen.rs b/src/term_ui/screen.rs index 112604a..32169a2 100644 --- a/src/term_ui/screen.rs +++ b/src/term_ui/screen.rs @@ -3,11 +3,8 @@ use std::cell::RefCell; use std::io; use std::io::{BufWriter, Write}; +use crossterm::{self, execute, queue}; use ropey::RopeSlice; -use termion; -use termion::color; -use termion::raw::{IntoRawMode, RawTerminal}; -use termion::screen::AlternateScreen; use unicode_segmentation::UnicodeSegmentation; use unicode_width::UnicodeWidthStr; @@ -16,7 +13,7 @@ use crate::utils::{grapheme_width, RopeGraphemes}; use super::smallstring::SmallString; pub(crate) struct Screen { - out: RefCell>>>, + out: RefCell>, buf: RefCell>>, w: usize, h: usize, @@ -24,23 +21,31 @@ pub(crate) struct Screen { impl Screen { pub(crate) fn new() -> Self { - let (w, h) = termion::terminal_size().unwrap(); - let buf = std::iter::repeat(Some((Style(Color::Black, Color::Black), " ".into()))) - .take(w as usize * h as usize) - .collect(); + let mut out = BufWriter::with_capacity(1 << 14, io::stdout()); + execute!(out, crossterm::terminal::EnterAlternateScreen).unwrap(); + out.flush().unwrap(); + crossterm::terminal::enable_raw_mode().unwrap(); + + let (w, h) = crossterm::terminal::size().unwrap(); + let buf = std::iter::repeat(Some(( + Style( + crossterm::style::Color::White, + crossterm::style::Color::Black, + ), + " ".into(), + ))) + .take(w as usize * h as usize) + .collect(); + Screen { - out: RefCell::new(AlternateScreen::from( - BufWriter::with_capacity(1 << 14, io::stdout()) - .into_raw_mode() - .unwrap(), - )), + out: RefCell::new(out), buf: RefCell::new(buf), w: w as usize, h: h as usize, } } - pub(crate) fn clear(&self, col: Color) { + pub(crate) fn clear(&self, col: crossterm::style::Color) { for cell in self.buf.borrow_mut().iter_mut() { match *cell { Some((ref mut style, ref mut text)) => { @@ -58,26 +63,46 @@ impl Screen { pub(crate) fn resize(&mut self, w: usize, h: usize) { self.w = w; self.h = h; - self.buf - .borrow_mut() - .resize(w * h, Some((Style(Color::Black, Color::Black), " ".into()))); + self.buf.borrow_mut().resize( + w * h, + Some(( + Style( + crossterm::style::Color::White, + crossterm::style::Color::Black, + ), + " ".into(), + )), + ); } pub(crate) fn present(&self) { let mut out = self.out.borrow_mut(); let buf = self.buf.borrow(); - let mut last_style = Style(Color::Black, Color::Black); - write!(out, "{}", last_style).unwrap(); + let mut last_style = Style( + crossterm::style::Color::White, + crossterm::style::Color::Black, + ); + queue!( + out, + crossterm::style::SetForegroundColor(last_style.0), + crossterm::style::SetBackgroundColor(last_style.1), + ) + .unwrap(); - // Write everything to the tmp_string first. + // Write everything to the buffered output. for y in 0..self.h { let mut x = 0; - write!(out, "{}", termion::cursor::Goto(1, y as u16 + 1)).unwrap(); + queue!(out, crossterm::cursor::MoveTo(0, y as u16)).unwrap(); while x < self.w { if let Some((style, ref text)) = buf[y * self.w + x] { if style != last_style { - write!(out, "{}", style).unwrap(); + queue!( + out, + crossterm::style::SetForegroundColor(style.0), + crossterm::style::SetBackgroundColor(style.1), + ) + .unwrap(); last_style = style; } write!(out, "{}", text).unwrap(); @@ -88,7 +113,7 @@ impl Screen { } } - // Make sure everything is written out + // Make sure everything is written out from the buffer. out.flush().unwrap(); } @@ -137,92 +162,34 @@ impl Screen { } pub(crate) fn hide_cursor(&self) { - write!(self.out.borrow_mut(), "{}", termion::cursor::Hide).unwrap(); + let mut out = self.out.borrow_mut(); + execute!(out, crossterm::cursor::Hide).unwrap(); + out.flush().unwrap(); } pub(crate) fn show_cursor(&self) { - write!(self.out.borrow_mut(), "{}", termion::cursor::Show).unwrap(); + let mut out = self.out.borrow_mut(); + execute!(out, crossterm::cursor::Show).unwrap(); + out.flush().unwrap(); } } impl Drop for Screen { fn drop(&mut self) { - write!( - self.out.borrow_mut(), - "{}{}{}", - color::Fg(color::Reset), - color::Bg(color::Reset), - termion::clear::All, + crossterm::terminal::disable_raw_mode().unwrap(); + let mut out = self.out.borrow_mut(); + execute!( + out, + crossterm::terminal::Clear(crossterm::terminal::ClearType::All), + crossterm::style::ResetColor, + // crossterm::style::Attribute::Reset, + crossterm::terminal::LeaveAlternateScreen, + crossterm::cursor::Show, ) .unwrap(); - self.show_cursor(); + out.flush().unwrap(); } } #[derive(Debug, Copy, Clone, PartialEq)] -pub(crate) enum Color { - Black, - Blue, - Cyan, - Green, - LightBlack, - LightBlue, - LightCyan, - LightGreen, - LightMagenta, - LightRed, - LightWhite, - LightYellow, - Magenta, - Red, - Rgb(u8, u8, u8), - White, - Yellow, -} - -#[derive(Debug, Copy, Clone, PartialEq)] -pub(crate) struct Style(pub Color, pub Color); // Fg, Bg - -impl std::fmt::Display for Style { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - match self.0 { - Color::Black => write!(f, "{}", color::Fg(color::Black)), - Color::Blue => write!(f, "{}", color::Fg(color::Blue)), - Color::Cyan => write!(f, "{}", color::Fg(color::Cyan)), - Color::Green => write!(f, "{}", color::Fg(color::Green)), - Color::LightBlack => write!(f, "{}", color::Fg(color::LightBlack)), - Color::LightBlue => write!(f, "{}", color::Fg(color::LightBlue)), - Color::LightCyan => write!(f, "{}", color::Fg(color::LightCyan)), - Color::LightGreen => write!(f, "{}", color::Fg(color::LightGreen)), - Color::LightMagenta => write!(f, "{}", color::Fg(color::LightMagenta)), - Color::LightRed => write!(f, "{}", color::Fg(color::LightRed)), - Color::LightWhite => write!(f, "{}", color::Fg(color::LightWhite)), - Color::LightYellow => write!(f, "{}", color::Fg(color::LightYellow)), - Color::Magenta => write!(f, "{}", color::Fg(color::Magenta)), - Color::Red => write!(f, "{}", color::Fg(color::Red)), - Color::Rgb(r, g, b) => write!(f, "{}", color::Fg(color::Rgb(r, g, b))), - Color::White => write!(f, "{}", color::Fg(color::White)), - Color::Yellow => write!(f, "{}", color::Fg(color::Yellow)), - }?; - - match self.1 { - Color::Black => write!(f, "{}", color::Bg(color::Black)), - Color::Blue => write!(f, "{}", color::Bg(color::Blue)), - Color::Cyan => write!(f, "{}", color::Bg(color::Cyan)), - Color::Green => write!(f, "{}", color::Bg(color::Green)), - Color::LightBlack => write!(f, "{}", color::Bg(color::LightBlack)), - Color::LightBlue => write!(f, "{}", color::Bg(color::LightBlue)), - Color::LightCyan => write!(f, "{}", color::Bg(color::LightCyan)), - Color::LightGreen => write!(f, "{}", color::Bg(color::LightGreen)), - Color::LightMagenta => write!(f, "{}", color::Bg(color::LightMagenta)), - Color::LightRed => write!(f, "{}", color::Bg(color::LightRed)), - Color::LightWhite => write!(f, "{}", color::Bg(color::LightWhite)), - Color::LightYellow => write!(f, "{}", color::Bg(color::LightYellow)), - Color::Magenta => write!(f, "{}", color::Bg(color::Magenta)), - Color::Red => write!(f, "{}", color::Bg(color::Red)), - Color::Rgb(r, g, b) => write!(f, "{}", color::Bg(color::Rgb(r, g, b))), - Color::White => write!(f, "{}", color::Bg(color::White)), - Color::Yellow => write!(f, "{}", color::Bg(color::Yellow)), - } - } -} +pub(crate) struct Style(pub crossterm::style::Color, pub crossterm::style::Color); // Fg, Bg