Moved from termion to crossterm for terminal handling.

This should (hopefully) make led work on Windows now.  Although
I don't have a Windows box to test on.

This also fixes a bug where control codes were ocassionally split
on input, resulting in e.g. a pg-down resulting in control
characters inserted into the buffer.
This commit is contained in:
Nathan Vegdahl 2020-01-25 04:07:56 +09:00
parent a867892183
commit 9ace1ecb68
5 changed files with 418 additions and 188 deletions

249
Cargo.lock generated
View File

@ -6,9 +6,9 @@ version = "0.0.2"
dependencies = [ dependencies = [
"backend 0.1.0", "backend 0.1.0",
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "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-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)", "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)", "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]] [[package]]
name = "atty" name = "atty"
version = "0.2.14" version = "0.2.14"
@ -44,6 +49,11 @@ name = "bitflags"
version = "1.2.1" version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "clap" name = "clap"
version = "2.33.0" version = "2.33.0"
@ -58,6 +68,51 @@ dependencies = [
"vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "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]] [[package]]
name = "hermit-abi" name = "hermit-abi"
version = "0.1.6" version = "0.1.6"
@ -66,34 +121,120 @@ dependencies = [
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "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]] [[package]]
name = "libc" name = "libc"
version = "0.2.66" version = "0.2.66"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "maybe-uninit" name = "maybe-uninit"
version = "2.0.0" version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "numtoa" name = "mio"
version = "0.1.0" version = "0.6.21"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "redox_syscall" name = "redox_syscall"
version = "0.1.56" version = "0.1.56"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "ropey" name = "ropey"
version = "1.1.0" version = "1.1.0"
@ -102,6 +243,35 @@ dependencies = [
"smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "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]] [[package]]
name = "smallvec" name = "smallvec"
version = "0.6.13" version = "0.6.13"
@ -120,17 +290,6 @@ name = "strsim"
version = "0.8.0" version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "textwrap" name = "textwrap"
version = "0.11.0" version = "0.11.0"
@ -154,6 +313,11 @@ name = "vec_map"
version = "0.8.1" version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "winapi" name = "winapi"
version = "0.3.8" 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)", "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]] [[package]]
name = "winapi-i686-pc-windows-gnu" name = "winapi-i686-pc-windows-gnu"
version = "0.4.0" version = "0.4.0"
@ -173,26 +342,56 @@ name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0" version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" 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] [metadata]
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "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 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 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 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 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 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 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_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 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 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 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 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 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-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 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 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 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-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 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"

View File

@ -21,7 +21,7 @@ unicode-segmentation = "1"
unicode-width = "0.1" unicode-width = "0.1"
clap = "2" clap = "2"
smallvec = "1" smallvec = "1"
termion = "1" crossterm = "0.14"
# Local crate dependencies # Local crate dependencies
[dependencies.backend] [dependencies.backend]

View File

@ -255,7 +255,7 @@ impl<T: LineFormatter> Editor<T> {
/// Updates the view dimensions, and returns whether that /// Updates the view dimensions, and returns whether that
/// actually changed anything. /// 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; 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 { if self.editor_dim.0 != h || self.editor_dim.1 != w {
self.editor_dim = (h, w); self.editor_dim = (h, w);
@ -266,12 +266,8 @@ impl<T: LineFormatter> Editor<T> {
self.editor_dim.0 - 1, self.editor_dim.0 - 1,
self.editor_dim.1 - line_count_digits - 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) { } 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; self.view_dim.1 = self.editor_dim.1 - line_count_digits - 1;
return true;
} else {
return false;
} }
} }

View File

@ -4,12 +4,12 @@ pub mod formatter;
mod screen; mod screen;
pub mod smallstring; pub mod smallstring;
use std; use std::{cmp::min, time::Duration};
use std::cmp::min;
use termion; use crossterm::{
use termion::event::{Event, Key}; event::{Event, KeyCode, KeyEvent, KeyModifiers},
use termion::input::TermRead; style::Color,
};
use crate::{ use crate::{
editor::Editor, editor::Editor,
@ -20,9 +20,11 @@ use crate::{
use self::{ use self::{
formatter::ConsoleLineFormatter, formatter::ConsoleLineFormatter,
screen::{Color, Screen, Style}, screen::{Screen, Style},
}; };
const EMPTY_MOD: KeyModifiers = KeyModifiers::empty();
/// Generalized ui loop. /// Generalized ui loop.
macro_rules! ui_loop { macro_rules! ui_loop {
($term_ui:ident,draw $draw:block,key_press($key:ident) $key_press:block) => { ($term_ui:ident,draw $draw:block,key_press($key:ident) $key_press:block) => {
@ -40,8 +42,9 @@ macro_rules! ui_loop {
// Handle input // Handle input
loop { loop {
match $term_ui.inp.next() { if crossterm::event::poll(Duration::from_millis(5)).unwrap() {
Some(Ok(Event::Key($key))) => { match crossterm::event::read().unwrap() {
Event::Key($key) => {
let (status, state_changed) = || -> (LoopStatus, bool) { $key_press }(); let (status, state_changed) = || -> (LoopStatus, bool) { $key_press }();
should_redraw |= state_changed; should_redraw |= state_changed;
if status == LoopStatus::Done { if status == LoopStatus::Done {
@ -50,9 +53,20 @@ macro_rules! ui_loop {
} }
} }
_ => { Event::Mouse(_) => {
break; 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;
}
}
} else {
break;
} }
} }
@ -61,36 +75,26 @@ macro_rules! ui_loop {
break; break;
} }
// Check for screen resize // Draw the editor to screen
let (w, h) = termion::terminal_size().unwrap(); if should_redraw {
let needs_update = $term_ui.editor.update_dim(h as usize - 1, w as usize); // Make sure display dimensions are up-to-date.
if needs_update { $term_ui.editor.update_dim($term_ui.height, $term_ui.width);
$term_ui.width = w as usize;
$term_ui.height = h as usize;
$term_ui.screen.resize(w as usize, h as usize);
$term_ui $term_ui
.editor .editor
.formatter .formatter
.set_wrap_width($term_ui.editor.view_dim.1); .set_wrap_width($term_ui.editor.view_dim.1);
should_redraw = true;
}
// Draw the editor to screen // Draw!
if should_redraw {
{ {
$draw $draw
}; };
$term_ui.screen.present(); $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 { pub struct TermUI {
inp: termion::input::Events<termion::AsyncReader>,
screen: Screen, screen: Screen,
editor: Editor<ConsoleLineFormatter>, editor: Editor<ConsoleLineFormatter>,
width: usize, width: usize,
@ -110,12 +114,11 @@ impl TermUI {
} }
pub fn new_from_editor(ed: Editor<ConsoleLineFormatter>) -> TermUI { pub fn new_from_editor(ed: Editor<ConsoleLineFormatter>) -> TermUI {
let (w, h) = termion::terminal_size().unwrap(); let (w, h) = crossterm::terminal::size().unwrap();
let mut editor = ed; let mut editor = ed;
editor.update_dim(h as usize - 1, w as usize); editor.update_dim(h as usize - 1, w as usize);
TermUI { TermUI {
inp: termion::async_stdin().events(),
screen: Screen::new(), screen: Screen::new(),
editor: editor, editor: editor,
width: w as usize, width: w as usize,
@ -129,7 +132,7 @@ impl TermUI {
self.screen.hide_cursor(); self.screen.hide_cursor();
// Set terminal size info // Set terminal size info
let (w, h) = termion::terminal_size().unwrap(); let (w, h) = crossterm::terminal::size().unwrap();
self.width = w as usize; self.width = w as usize;
self.height = h as usize; self.height = h as usize;
self.editor.update_dim(self.height - 1, self.width); self.editor.update_dim(self.height - 1, self.width);
@ -150,74 +153,119 @@ impl TermUI {
key_press(key) { key_press(key) {
let mut state_changed = true; let mut state_changed = true;
match key { match key {
Key::Ctrl('q') => { KeyEvent {
code: KeyCode::Char('q'),
// modifiers: EMPTY_MOD,
modifiers: KeyModifiers::CONTROL,
} => {
self.quit = true; self.quit = true;
return (LoopStatus::Done, true); return (LoopStatus::Done, true);
} }
Key::Ctrl('s') => { KeyEvent {
code: KeyCode::Char('s'),
modifiers: KeyModifiers::CONTROL,
} => {
self.editor.save_if_dirty(); self.editor.save_if_dirty();
} }
Key::Ctrl('z') => { KeyEvent {
code: KeyCode::Char('z'),
modifiers: KeyModifiers::CONTROL,
} => {
self.editor.undo(); self.editor.undo();
} }
Key::Ctrl('y') => { KeyEvent {
code: KeyCode::Char('y'),
modifiers: KeyModifiers::CONTROL,
} => {
self.editor.redo(); self.editor.redo();
} }
Key::Ctrl('l') => { KeyEvent {
code: KeyCode::Char('l'),
modifiers: KeyModifiers::CONTROL,
} => {
self.go_to_line_ui_loop(); self.go_to_line_ui_loop();
} }
Key::PageUp => { KeyEvent {
code: KeyCode::PageUp,
modifiers: EMPTY_MOD,
} => {
self.editor.page_up(); self.editor.page_up();
} }
Key::PageDown => { KeyEvent {
code: KeyCode::PageDown,
modifiers: EMPTY_MOD,
} => {
self.editor.page_down(); self.editor.page_down();
} }
Key::Up => { KeyEvent {
code: KeyCode::Up,
modifiers: EMPTY_MOD,
} => {
self.editor.cursor_up(1); self.editor.cursor_up(1);
} }
Key::Down => { KeyEvent {
code: KeyCode::Down,
modifiers: EMPTY_MOD,
} => {
self.editor.cursor_down(1); self.editor.cursor_down(1);
} }
Key::Left => { KeyEvent {
code: KeyCode::Left,
modifiers: EMPTY_MOD,
} => {
self.editor.cursor_left(1); self.editor.cursor_left(1);
} }
Key::Right => { KeyEvent {
code: KeyCode::Right,
modifiers: EMPTY_MOD,
} => {
self.editor.cursor_right(1); 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); let nl = line_ending_to_str(self.editor.line_ending_type);
self.editor.insert_text_at_cursor(nl); self.editor.insert_text_at_cursor(nl);
} }
Key::Char(' ') => { KeyEvent {
self.editor.insert_text_at_cursor(" "); code: KeyCode::Tab,
} modifiers: EMPTY_MOD,
} => {
Key::Char('\t') => {
self.editor.insert_tab_at_cursor(); self.editor.insert_tab_at_cursor();
} }
Key::Backspace => { KeyEvent {
code: KeyCode::Backspace,
modifiers: EMPTY_MOD,
} => {
self.editor.backspace_at_cursor(); self.editor.backspace_at_cursor();
} }
Key::Delete => { KeyEvent {
code: KeyCode::Delete,
modifiers: EMPTY_MOD,
} => {
self.editor.remove_text_in_front_of_cursor(1); self.editor.remove_text_in_front_of_cursor(1);
} }
// Character // Character
Key::Char(c) => { KeyEvent {
code: KeyCode::Char(c),
modifiers: EMPTY_MOD,
} => {
self.editor.insert_text_at_cursor(&c.to_string()[..]); self.editor.insert_text_at_cursor(&c.to_string()[..]);
} }
@ -261,21 +309,41 @@ impl TermUI {
key_press(key) { key_press(key) {
let mut state_changed = true; let mut state_changed = true;
match key { 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; cancel = true;
return (LoopStatus::Done, true); return (LoopStatus::Done, true);
} }
Key::Char('\n') => { KeyEvent {
code: KeyCode::Enter,
modifiers: EMPTY_MOD,
} => {
return (LoopStatus::Done, true); return (LoopStatus::Done, true);
} }
Key::Backspace => { KeyEvent {
code: KeyCode::Backspace,
modifiers: EMPTY_MOD,
} => {
line.pop(); line.pop();
} }
// Character // Character
Key::Char(c) => { KeyEvent {
code: KeyCode::Char(c),
modifiers: EMPTY_MOD,
} => {
if c.is_numeric() { if c.is_numeric() {
line.push(c); line.push(c);
} }

View File

@ -3,11 +3,8 @@ use std::cell::RefCell;
use std::io; use std::io;
use std::io::{BufWriter, Write}; use std::io::{BufWriter, Write};
use crossterm::{self, execute, queue};
use ropey::RopeSlice; use ropey::RopeSlice;
use termion;
use termion::color;
use termion::raw::{IntoRawMode, RawTerminal};
use termion::screen::AlternateScreen;
use unicode_segmentation::UnicodeSegmentation; use unicode_segmentation::UnicodeSegmentation;
use unicode_width::UnicodeWidthStr; use unicode_width::UnicodeWidthStr;
@ -16,7 +13,7 @@ use crate::utils::{grapheme_width, RopeGraphemes};
use super::smallstring::SmallString; use super::smallstring::SmallString;
pub(crate) struct Screen { pub(crate) struct Screen {
out: RefCell<AlternateScreen<RawTerminal<BufWriter<io::Stdout>>>>, out: RefCell<BufWriter<io::Stdout>>,
buf: RefCell<Vec<Option<(Style, SmallString)>>>, buf: RefCell<Vec<Option<(Style, SmallString)>>>,
w: usize, w: usize,
h: usize, h: usize,
@ -24,23 +21,31 @@ pub(crate) struct Screen {
impl Screen { impl Screen {
pub(crate) fn new() -> Self { pub(crate) fn new() -> Self {
let (w, h) = termion::terminal_size().unwrap(); let mut out = BufWriter::with_capacity(1 << 14, io::stdout());
let buf = std::iter::repeat(Some((Style(Color::Black, Color::Black), " ".into()))) 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) .take(w as usize * h as usize)
.collect(); .collect();
Screen { Screen {
out: RefCell::new(AlternateScreen::from( out: RefCell::new(out),
BufWriter::with_capacity(1 << 14, io::stdout())
.into_raw_mode()
.unwrap(),
)),
buf: RefCell::new(buf), buf: RefCell::new(buf),
w: w as usize, w: w as usize,
h: h 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() { for cell in self.buf.borrow_mut().iter_mut() {
match *cell { match *cell {
Some((ref mut style, ref mut text)) => { Some((ref mut style, ref mut text)) => {
@ -58,26 +63,46 @@ impl Screen {
pub(crate) fn resize(&mut self, w: usize, h: usize) { pub(crate) fn resize(&mut self, w: usize, h: usize) {
self.w = w; self.w = w;
self.h = h; self.h = h;
self.buf self.buf.borrow_mut().resize(
.borrow_mut() w * h,
.resize(w * h, Some((Style(Color::Black, Color::Black), " ".into()))); Some((
Style(
crossterm::style::Color::White,
crossterm::style::Color::Black,
),
" ".into(),
)),
);
} }
pub(crate) fn present(&self) { pub(crate) fn present(&self) {
let mut out = self.out.borrow_mut(); let mut out = self.out.borrow_mut();
let buf = self.buf.borrow(); let buf = self.buf.borrow();
let mut last_style = Style(Color::Black, Color::Black); let mut last_style = Style(
write!(out, "{}", last_style).unwrap(); 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 { for y in 0..self.h {
let mut x = 0; 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 { while x < self.w {
if let Some((style, ref text)) = buf[y * self.w + x] { if let Some((style, ref text)) = buf[y * self.w + x] {
if style != last_style { if style != last_style {
write!(out, "{}", style).unwrap(); queue!(
out,
crossterm::style::SetForegroundColor(style.0),
crossterm::style::SetBackgroundColor(style.1),
)
.unwrap();
last_style = style; last_style = style;
} }
write!(out, "{}", text).unwrap(); 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(); out.flush().unwrap();
} }
@ -137,92 +162,34 @@ impl Screen {
} }
pub(crate) fn hide_cursor(&self) { 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) { 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 { impl Drop for Screen {
fn drop(&mut self) { fn drop(&mut self) {
write!( crossterm::terminal::disable_raw_mode().unwrap();
self.out.borrow_mut(), let mut out = self.out.borrow_mut();
"{}{}{}", execute!(
color::Fg(color::Reset), out,
color::Bg(color::Reset), crossterm::terminal::Clear(crossterm::terminal::ClearType::All),
termion::clear::All, crossterm::style::ResetColor,
// crossterm::style::Attribute::Reset,
crossterm::terminal::LeaveAlternateScreen,
crossterm::cursor::Show,
) )
.unwrap(); .unwrap();
self.show_cursor(); out.flush().unwrap();
} }
} }
#[derive(Debug, Copy, Clone, PartialEq)] #[derive(Debug, Copy, Clone, PartialEq)]
pub(crate) enum Color { pub(crate) struct Style(pub crossterm::style::Color, pub crossterm::style::Color); // Fg, Bg
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)),
}
}
}