WIP switching from Rustbox to Termion for terminal handling.
This commit is contained in:
parent
6ccba0510b
commit
c11aee9bf6
188
Cargo.lock
generated
188
Cargo.lock
generated
|
@ -4,9 +4,9 @@ version = "0.0.2"
|
|||
dependencies = [
|
||||
"docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ropey 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustbox 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
@ -19,16 +19,6 @@ dependencies = [
|
|||
"memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "docopt"
|
||||
version = "0.8.1"
|
||||
|
@ -41,38 +31,6 @@ dependencies = [
|
|||
"strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fuchsia-zircon"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fuchsia-zircon-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fuchsia-zircon-sys"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "gag"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tempfile 2.2.0 (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 = "0.2.11"
|
||||
|
@ -96,91 +54,24 @@ dependencies = [
|
|||
"libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num"
|
||||
version = "0.1.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-bigint 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-complex 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-rational 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.1.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-complex"
|
||||
version = "0.1.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-iter"
|
||||
version = "0.1.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-rational"
|
||||
version = "0.1.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-bigint 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.1.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "0.3.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.3.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"fuchsia-zircon 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.1.33"
|
||||
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.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "0.2.5"
|
||||
|
@ -207,22 +98,6 @@ dependencies = [
|
|||
"unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustbox"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gag 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"termbox-sys 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-serialize"
|
||||
version = "0.3.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.27"
|
||||
|
@ -276,22 +151,15 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "2.2.0"
|
||||
name = "termion"
|
||||
version = "1.5.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)",
|
||||
"libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_syscall 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.8 (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 = "termbox-sys"
|
||||
version = "0.2.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "0.3.5"
|
||||
|
@ -334,44 +202,19 @@ name = "void"
|
|||
version = "1.0.2"
|
||||
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-build"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[metadata]
|
||||
"checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4"
|
||||
"checksum bitflags 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a41f80ec2e140d19e789764fdf22d0f2da98fe7e55d26f99db59cb3d2605d327"
|
||||
"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"
|
||||
"checksum docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b5b93718f8b3e5544fcc914c43de828ca6c6ace23e0332c6080a2977b49787a"
|
||||
"checksum fuchsia-zircon 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bd510087c325af53ba24f3be8f1c081b0982319adcb8b03cad764512923ccc19"
|
||||
"checksum fuchsia-zircon-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "08b3a6f13ad6b96572b53ce7af74543132f1a7055ccceb6d073dd36c54481859"
|
||||
"checksum gag 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c606f5c0da18075916377e73de8aec7c140e1b6110a3cf26ae1f47873529b47e"
|
||||
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||
"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
|
||||
"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d"
|
||||
"checksum libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)" = "36fbc8a8929c632868295d0178dd8f63fc423fd7537ad0738372bd010b3ac9b0"
|
||||
"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d"
|
||||
"checksum num 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cc4083e14b542ea3eb9b5f33ff48bd373a92d78687e74f4cc0a30caeb754f0ca"
|
||||
"checksum num-bigint 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "bdc1494b5912f088f260b775799468d9b9209ac60885d8186a547a0476289e23"
|
||||
"checksum num-complex 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "58de7b4bf7cf5dbecb635a5797d489864eadd03b107930cbccf9e0fd7428b47c"
|
||||
"checksum num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "d1452e8b06e448a07f0e6ebb0bb1d92b8890eea63288c0b627331d53514d0fba"
|
||||
"checksum num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "7485fcc84f85b4ecd0ea527b14189281cf27d60e583ae65ebc9c088b13dffe01"
|
||||
"checksum num-rational 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "0c7cb72a95250d8a370105c828f388932373e0e94414919891a0f945222310fe"
|
||||
"checksum num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cacfcab5eb48250ee7d0c7896b51a2c5eec99c1feea5f32025635f5ae4b00070"
|
||||
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
|
||||
"checksum rand 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)" = "9e7944d95d25ace8f377da3ac7068ce517e4c646754c43a1b1849177bbf72e59"
|
||||
"checksum redox_syscall 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "07b8f011e3254d5a9b318fde596d409a0001c9ae4c6e7907520c2eaa4d988c99"
|
||||
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
|
||||
"checksum regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "744554e01ccbd98fff8c457c3b092cd67af62a555a43bfe97ae8a0451f7799fa"
|
||||
"checksum regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8e931c58b93d86f080c734bfd2bce7dd0079ae2331235818133c8be7f422e20e"
|
||||
"checksum ropey 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6eb4b74f76bc72338d8aebb193e9575398703552530e329dae718e38e4bf2ca0"
|
||||
"checksum rustbox 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "acc40f390f6c5e2d47ff358020103deb6ebd0e98f2df2cec3cb15e054f403ed8"
|
||||
"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
|
||||
"checksum serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "db99f3919e20faa51bb2996057f5031d8685019b5a06139b1ce761da671b8526"
|
||||
"checksum serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "f4ba7591cfe93755e89eeecdbcc668885624829b020050e6aec99c2a03bd3fd0"
|
||||
"checksum serde_derive_internals 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6e03f1c9530c3fb0a0a5c9b826bdd9246a5921ae995d75f512ac917fc4dd55b5"
|
||||
|
@ -379,8 +222,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
|
||||
"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
|
||||
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
|
||||
"checksum tempfile 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "11ce2fe9db64b842314052e2421ac61a73ce41b898dc8e3750398b219c5fc1e0"
|
||||
"checksum termbox-sys 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "e32daa27881ea4b2ef36e4972d6cdefb241c19ac48d318381b688d1a631b8760"
|
||||
"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
|
||||
"checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963"
|
||||
"checksum unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946"
|
||||
"checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f"
|
||||
|
@ -388,5 +230,3 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
|
||||
"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
|
||||
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
|
||||
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
|
||||
|
|
|
@ -15,4 +15,4 @@ unicode-width = "0.1"
|
|||
serde = "1.*"
|
||||
serde_derive = "1.*"
|
||||
docopt = "0.8"
|
||||
rustbox = "0.9"
|
||||
termion = "1.5"
|
|
@ -1,9 +1,9 @@
|
|||
extern crate docopt;
|
||||
extern crate ropey;
|
||||
extern crate rustbox;
|
||||
extern crate serde;
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
extern crate termion;
|
||||
extern crate unicode_segmentation;
|
||||
extern crate unicode_width;
|
||||
|
||||
|
@ -50,6 +50,7 @@ fn main() {
|
|||
};
|
||||
|
||||
// Initialize and start UI
|
||||
let mut ui = TermUI::new_from_editor(editor);
|
||||
let mut stdin = std::io::stdin();
|
||||
let mut ui = TermUI::new_from_editor(&mut stdin, editor);
|
||||
ui.main_ui_loop();
|
||||
}
|
||||
|
|
|
@ -1,306 +1,281 @@
|
|||
#![allow(dead_code)]
|
||||
|
||||
use rustbox;
|
||||
use rustbox::Color;
|
||||
use editor::Editor;
|
||||
use std::time::Duration;
|
||||
use formatter::{block_index_and_offset, LineFormatter, LINE_BLOCK_LENGTH};
|
||||
use std::char;
|
||||
use std::default::Default;
|
||||
use std::cell::RefCell;
|
||||
use std::cmp::min;
|
||||
use std::io;
|
||||
use std::io::Write;
|
||||
|
||||
use termion;
|
||||
use termion::event::{Event, Key};
|
||||
use termion::input::TermRead;
|
||||
use termion::color;
|
||||
use termion::raw::{IntoRawMode, RawTerminal};
|
||||
|
||||
use editor::Editor;
|
||||
use formatter::{block_index_and_offset, LineFormatter, LINE_BLOCK_LENGTH};
|
||||
use self::formatter::ConsoleLineFormatter;
|
||||
use string_utils::{is_line_ending, line_ending_to_str, LineEnding};
|
||||
use utils::digit_count;
|
||||
use self::formatter::ConsoleLineFormatter;
|
||||
|
||||
pub mod formatter;
|
||||
|
||||
// Key codes
|
||||
const K_ENTER: u16 = 13;
|
||||
const K_TAB: u16 = 9;
|
||||
const K_SPACE: u16 = 32;
|
||||
const K_BACKSPACE: u16 = 127;
|
||||
const K_DELETE: u16 = 65522;
|
||||
const K_PAGEUP: u16 = 65519;
|
||||
const K_PAGEDOWN: u16 = 65518;
|
||||
const K_UP: u16 = 65517;
|
||||
const K_DOWN: u16 = 65516;
|
||||
const K_LEFT: u16 = 65515;
|
||||
const K_RIGHT: u16 = 65514;
|
||||
const K_ESC: u16 = 27;
|
||||
const K_CTRL_L: u16 = 12;
|
||||
const K_CTRL_O: u16 = 15;
|
||||
const K_CTRL_Q: u16 = 17;
|
||||
const K_CTRL_S: u16 = 19;
|
||||
const K_CTRL_Y: u16 = 25;
|
||||
const K_CTRL_Z: u16 = 26;
|
||||
/// Generalized ui loop.
|
||||
macro_rules! ui_loop {
|
||||
($term_ui:ident, draw $draw:block, key_press($key:ident) $key_press:block) => {
|
||||
let mut stop = false;
|
||||
|
||||
pub struct TermUI {
|
||||
rb: rustbox::RustBox,
|
||||
loop {
|
||||
// Draw the editor to screen
|
||||
{$draw};
|
||||
$term_ui.present();
|
||||
|
||||
// Handle input
|
||||
match $term_ui.inp.next() {
|
||||
Some(Ok(Event::Key($key))) => {
|
||||
let status = || -> LoopStatus {
|
||||
$key_press
|
||||
}();
|
||||
if status == LoopStatus::Done {
|
||||
stop = true;
|
||||
// break;
|
||||
}
|
||||
}
|
||||
|
||||
_ => {
|
||||
// break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for screen resize
|
||||
let (w, h) = termion::terminal_size().unwrap();
|
||||
if $term_ui.width != w as usize || $term_ui.height != h as usize {
|
||||
$term_ui.width = w as usize;
|
||||
$term_ui.height = h as usize;
|
||||
$term_ui.editor.update_dim($term_ui.height - 1, $term_ui.width);
|
||||
}
|
||||
|
||||
if stop || $term_ui.quit {
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub struct TermUI<'a> {
|
||||
inp: termion::input::Events<io::StdinLock<'a>>,
|
||||
out: RefCell<RawTerminal<io::Stdout>>,
|
||||
editor: Editor<ConsoleLineFormatter>,
|
||||
width: usize,
|
||||
height: usize,
|
||||
quit: bool,
|
||||
}
|
||||
|
||||
impl TermUI {
|
||||
pub fn new() -> TermUI {
|
||||
let rb = match rustbox::RustBox::init(rustbox::InitOptions {
|
||||
buffer_stderr: true,
|
||||
..Default::default()
|
||||
}) {
|
||||
Ok(rbox) => rbox,
|
||||
Err(_) => panic!("Could not create Rustbox instance."),
|
||||
};
|
||||
let w = rb.width();
|
||||
let h = rb.height();
|
||||
let mut editor = Editor::new(ConsoleLineFormatter::new(4));
|
||||
editor.update_dim(h - 1, w);
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
enum LoopStatus {
|
||||
Done,
|
||||
Continue,
|
||||
}
|
||||
|
||||
TermUI {
|
||||
rb: rb,
|
||||
editor: editor,
|
||||
width: w,
|
||||
height: h,
|
||||
impl<'a> Drop for TermUI<'a> {
|
||||
fn drop(&mut self) {
|
||||
self.clear();
|
||||
write!(
|
||||
self.out.borrow_mut(),
|
||||
"{}{}",
|
||||
termion::cursor::Show,
|
||||
termion::cursor::Goto(0, 0),
|
||||
).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_from_editor(ed: Editor<ConsoleLineFormatter>) -> TermUI {
|
||||
let rb = match rustbox::RustBox::init(rustbox::InitOptions {
|
||||
buffer_stderr: true,
|
||||
..Default::default()
|
||||
}) {
|
||||
Ok(rbox) => rbox,
|
||||
Err(_) => panic!("Could not create Rustbox instance."),
|
||||
};
|
||||
let w = rb.width();
|
||||
let h = rb.height();
|
||||
impl<'a> TermUI<'a> {
|
||||
pub fn new<'b>(stdin: &'b mut io::Stdin) -> TermUI<'b> {
|
||||
TermUI::new_from_editor(stdin, Editor::new(ConsoleLineFormatter::new(4)))
|
||||
}
|
||||
|
||||
pub fn new_from_editor<'b>(
|
||||
stdin: &'b mut io::Stdin,
|
||||
ed: Editor<ConsoleLineFormatter>,
|
||||
) -> TermUI<'b> {
|
||||
let out = io::stdout().into_raw_mode().unwrap();
|
||||
let (w, h) = termion::terminal_size().unwrap();
|
||||
let mut editor = ed;
|
||||
editor.update_dim(h - 1, w);
|
||||
editor.update_dim(h as usize - 1, w as usize);
|
||||
|
||||
TermUI {
|
||||
rb: rb,
|
||||
inp: stdin.lock().events(),
|
||||
out: RefCell::new(out),
|
||||
editor: editor,
|
||||
width: w,
|
||||
height: h,
|
||||
width: w as usize,
|
||||
height: h as usize,
|
||||
quit: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main_ui_loop(&mut self) {
|
||||
// Quitting flag
|
||||
let mut quit = false;
|
||||
let mut resize: Option<(usize, usize)> = None;
|
||||
// Hide cursor
|
||||
write!(self.out.borrow_mut(), "{}", termion::cursor::Hide).unwrap();
|
||||
|
||||
self.editor.update_dim(self.height - 1, self.width);
|
||||
self.editor.formatter.set_wrap_width(self.width as usize);
|
||||
|
||||
loop {
|
||||
// Draw the editor to screen
|
||||
ui_loop!(
|
||||
self,
|
||||
|
||||
// Draw
|
||||
draw {
|
||||
self.editor.update_view_dim();
|
||||
self.editor.formatter.set_wrap_width(self.editor.view_dim.1);
|
||||
self.rb.clear();
|
||||
self.clear();
|
||||
self.draw_editor(&self.editor, (0, 0), (self.height - 1, self.width - 1));
|
||||
self.rb.present();
|
||||
},
|
||||
|
||||
// Handle events. We block on the first event, so that the
|
||||
// program doesn't loop like crazy, but then continue pulling
|
||||
// events in a non-blocking way until we run out of events
|
||||
// to handle.
|
||||
let mut e = self.rb.poll_event(true); // Block until we get an event
|
||||
loop {
|
||||
match e {
|
||||
Ok(rustbox::Event::KeyEventRaw(_, key, character)) => {
|
||||
// println!(" {} {} {}", modifier, key, character);
|
||||
// Handle input
|
||||
key_press(key) {
|
||||
match key {
|
||||
K_CTRL_Q => {
|
||||
quit = true;
|
||||
break;
|
||||
Key::Ctrl('q') => {
|
||||
self.quit = true;
|
||||
return LoopStatus::Done;
|
||||
}
|
||||
|
||||
K_CTRL_S => {
|
||||
Key::Ctrl('s') => {
|
||||
self.editor.save_if_dirty();
|
||||
}
|
||||
|
||||
K_CTRL_Z => {
|
||||
Key::Ctrl('z') => {
|
||||
self.editor.undo();
|
||||
}
|
||||
|
||||
K_CTRL_Y => {
|
||||
Key::Ctrl('y') => {
|
||||
self.editor.redo();
|
||||
}
|
||||
|
||||
K_CTRL_L => {
|
||||
Key::Ctrl('l') => {
|
||||
self.go_to_line_ui_loop();
|
||||
}
|
||||
|
||||
K_PAGEUP => {
|
||||
Key::PageUp => {
|
||||
self.editor.page_up();
|
||||
}
|
||||
|
||||
K_PAGEDOWN => {
|
||||
Key::PageDown => {
|
||||
self.editor.page_down();
|
||||
}
|
||||
|
||||
K_UP => {
|
||||
Key::Up => {
|
||||
self.editor.cursor_up(1);
|
||||
}
|
||||
|
||||
K_DOWN => {
|
||||
Key::Down => {
|
||||
self.editor.cursor_down(1);
|
||||
}
|
||||
|
||||
K_LEFT => {
|
||||
Key::Left => {
|
||||
self.editor.cursor_left(1);
|
||||
}
|
||||
|
||||
K_RIGHT => {
|
||||
Key::Right => {
|
||||
self.editor.cursor_right(1);
|
||||
}
|
||||
|
||||
K_ENTER => {
|
||||
Key::Char('\n') => {
|
||||
let nl = line_ending_to_str(self.editor.line_ending_type);
|
||||
self.editor.insert_text_at_cursor(nl);
|
||||
}
|
||||
|
||||
K_SPACE => {
|
||||
Key::Char(' ') => {
|
||||
self.editor.insert_text_at_cursor(" ");
|
||||
}
|
||||
|
||||
K_TAB => {
|
||||
Key::Char('\t') => {
|
||||
self.editor.insert_tab_at_cursor();
|
||||
}
|
||||
|
||||
K_BACKSPACE => {
|
||||
Key::Backspace => {
|
||||
self.editor.backspace_at_cursor();
|
||||
}
|
||||
|
||||
K_DELETE => {
|
||||
Key::Delete => {
|
||||
self.editor.remove_text_in_front_of_cursor(1);
|
||||
}
|
||||
|
||||
// Character
|
||||
0 => {
|
||||
if let Option::Some(c) = char::from_u32(character) {
|
||||
Key::Char(c) => {
|
||||
self.editor.insert_text_at_cursor(&c.to_string()[..]);
|
||||
}
|
||||
}
|
||||
|
||||
_ => {}
|
||||
k => {
|
||||
println!("{:?}", k);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(rustbox::Event::ResizeEvent(w, h)) => {
|
||||
resize = Some((h as usize, w as usize));
|
||||
}
|
||||
|
||||
_ => {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
e = self.rb.peek_event(Duration::from_millis(0), true); // Get next event (if any)
|
||||
}
|
||||
|
||||
if let Some((h, w)) = resize {
|
||||
self.width = w as usize;
|
||||
self.height = h as usize;
|
||||
self.editor.update_dim(self.height, self.width);
|
||||
}
|
||||
resize = None;
|
||||
|
||||
// Quit if quit flag is set
|
||||
if quit {
|
||||
break;
|
||||
}
|
||||
LoopStatus::Continue
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
fn go_to_line_ui_loop(&mut self) {
|
||||
let foreground = Color::Black;
|
||||
let background = Color::Cyan;
|
||||
let foreground = color::Black;
|
||||
let background = color::Cyan;
|
||||
|
||||
let mut cancel = false;
|
||||
let mut confirm = false;
|
||||
let prefix = "Jump to line: ";
|
||||
let mut line = String::new();
|
||||
|
||||
loop {
|
||||
// Draw the editor to screen
|
||||
ui_loop!(
|
||||
self,
|
||||
|
||||
// Draw
|
||||
draw {
|
||||
self.editor.update_view_dim();
|
||||
self.editor.formatter.set_wrap_width(self.editor.view_dim.1);
|
||||
self.rb.clear();
|
||||
self.clear();
|
||||
self.draw_editor(&self.editor, (0, 0), (self.height - 1, self.width - 1));
|
||||
for i in 0..self.width {
|
||||
self.rb
|
||||
.print(i, 0, rustbox::RB_NORMAL, foreground, background, " ");
|
||||
self.draw(i, 0, " ", foreground, background);
|
||||
}
|
||||
self.rb
|
||||
.print(1, 0, rustbox::RB_NORMAL, foreground, background, prefix);
|
||||
self.rb.print(
|
||||
self.draw(1, 0, prefix, foreground, background);
|
||||
self.draw(
|
||||
prefix.len() + 1,
|
||||
0,
|
||||
rustbox::RB_NORMAL,
|
||||
&line[..],
|
||||
foreground,
|
||||
background,
|
||||
&line[..],
|
||||
);
|
||||
self.rb.present();
|
||||
},
|
||||
|
||||
// Handle events. We block on the first event, so that the
|
||||
// program doesn't loop like crazy, but then continue pulling
|
||||
// events in a non-blocking way until we run out of events
|
||||
// to handle.
|
||||
let mut e = self.rb.poll_event(true); // Block until we get an event
|
||||
loop {
|
||||
match e {
|
||||
Ok(rustbox::Event::KeyEventRaw(_, key, character)) => {
|
||||
// Handle input
|
||||
key_press(key) {
|
||||
match key {
|
||||
K_ESC => {
|
||||
Key::Esc => {
|
||||
cancel = true;
|
||||
break;
|
||||
return LoopStatus::Done;
|
||||
}
|
||||
|
||||
K_ENTER => {
|
||||
confirm = true;
|
||||
break;
|
||||
Key::Char('\n') => {
|
||||
return LoopStatus::Done;
|
||||
}
|
||||
|
||||
K_BACKSPACE => {
|
||||
Key::Backspace => {
|
||||
line.pop();
|
||||
}
|
||||
|
||||
// Character
|
||||
0 => {
|
||||
if let Option::Some(c) = char::from_u32(character) {
|
||||
Key::Char(c) => {
|
||||
if c.is_numeric() {
|
||||
line.push(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(rustbox::Event::ResizeEvent(w, h)) => {
|
||||
self.width = w as usize;
|
||||
self.height = h as usize;
|
||||
self.editor.update_dim(self.height - 1, self.width);
|
||||
}
|
||||
|
||||
_ => {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
e = self.rb.peek_event(Duration::from_millis(0), true); // Get next event (if any)
|
||||
}
|
||||
|
||||
// Cancel if flag is set
|
||||
if cancel {
|
||||
break;
|
||||
return LoopStatus::Continue;
|
||||
}
|
||||
);
|
||||
|
||||
// Jump to line!
|
||||
if confirm {
|
||||
if !cancel {
|
||||
if let Ok(n) = line.parse() {
|
||||
let n2: usize = n; // Weird work-around: the type of n wasn't being inferred
|
||||
if n2 > 0 {
|
||||
|
@ -309,8 +284,6 @@ impl TermUI {
|
|||
self.editor.jump_to_line(0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -320,27 +293,19 @@ impl TermUI {
|
|||
c1: (usize, usize),
|
||||
c2: (usize, usize),
|
||||
) {
|
||||
let foreground = Color::Black;
|
||||
let background = Color::Cyan;
|
||||
let fg = color::Black;
|
||||
let bg = color::Cyan;
|
||||
|
||||
// Fill in top row with info line color
|
||||
for i in c1.1..(c2.1 + 1) {
|
||||
self.rb
|
||||
.print(i, c1.0, rustbox::RB_NORMAL, foreground, background, " ");
|
||||
self.draw(i, c1.0, " ", fg, bg);
|
||||
}
|
||||
|
||||
// Filename and dirty marker
|
||||
let filename = editor.file_path.display();
|
||||
let dirty_char = if editor.dirty { "*" } else { "" };
|
||||
let name = format!("{}{}", filename, dirty_char);
|
||||
self.rb.print(
|
||||
c1.1 + 1,
|
||||
c1.0,
|
||||
rustbox::RB_NORMAL,
|
||||
foreground,
|
||||
background,
|
||||
&name[..],
|
||||
);
|
||||
self.draw(c1.1 + 1, c1.0, &name[..], fg, bg);
|
||||
|
||||
// Percentage position in document
|
||||
// TODO: use view instead of cursor for calculation if there is more
|
||||
|
@ -352,14 +317,7 @@ impl TermUI {
|
|||
100
|
||||
};
|
||||
let pstring = format!("{}%", percentage);
|
||||
self.rb.print(
|
||||
c2.1 - pstring.len(),
|
||||
c1.0,
|
||||
rustbox::RB_NORMAL,
|
||||
foreground,
|
||||
background,
|
||||
&pstring[..],
|
||||
);
|
||||
self.draw(c2.1 - pstring.len(), c1.0, &pstring[..], fg, bg);
|
||||
|
||||
// Text encoding info and tab style
|
||||
let nl = match editor.line_ending_type {
|
||||
|
@ -378,14 +336,7 @@ impl TermUI {
|
|||
"UTF8:{} {}:{}",
|
||||
nl, soft_tabs_str, editor.soft_tab_width as usize
|
||||
);
|
||||
self.rb.print(
|
||||
c2.1 - 30,
|
||||
c1.0,
|
||||
rustbox::RB_NORMAL,
|
||||
foreground,
|
||||
background,
|
||||
&info_line[..],
|
||||
);
|
||||
self.draw(c2.1 - 30, c1.0, &info_line[..], fg, bg);
|
||||
|
||||
// Draw main text editing area
|
||||
self.draw_editor_text(editor, (c1.0 + 1, c1.1), c2);
|
||||
|
@ -424,8 +375,7 @@ impl TermUI {
|
|||
// Fill in the gutter with the appropriate background
|
||||
for y in c1.0..(c2.0 + 1) {
|
||||
for x in c1.1..(c1.1 + gutter_width - 1) {
|
||||
self.rb
|
||||
.print(x, y, rustbox::RB_NORMAL, Color::White, Color::Blue, " ");
|
||||
self.draw(x, y, " ", color::White, color::Blue);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -436,13 +386,12 @@ impl TermUI {
|
|||
let lnx = c1.1 + (gutter_width - 1 - digit_count(line_num as u32, 10) as usize);
|
||||
let lny = screen_line as usize;
|
||||
if lny >= c1.0 && lny <= c2.0 {
|
||||
self.rb.print(
|
||||
self.draw(
|
||||
lnx,
|
||||
lny,
|
||||
rustbox::RB_NORMAL,
|
||||
Color::White,
|
||||
Color::Blue,
|
||||
&format!("{}", line_num)[..],
|
||||
color::White,
|
||||
color::Blue,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -488,59 +437,42 @@ impl TermUI {
|
|||
// Actually print the character
|
||||
if is_line_ending(g) {
|
||||
if at_cursor {
|
||||
self.rb.print(
|
||||
self.draw(
|
||||
px as usize,
|
||||
py as usize,
|
||||
rustbox::RB_NORMAL,
|
||||
Color::Black,
|
||||
Color::White,
|
||||
" ",
|
||||
color::White,
|
||||
color::Black,
|
||||
);
|
||||
}
|
||||
} else if g == "\t" {
|
||||
for i in 0..width {
|
||||
let tpx = px as usize + i;
|
||||
if tpx <= c2.1 {
|
||||
self.rb.print(
|
||||
self.draw(
|
||||
tpx as usize,
|
||||
py as usize,
|
||||
rustbox::RB_NORMAL,
|
||||
Color::White,
|
||||
Color::Black,
|
||||
" ",
|
||||
color::White,
|
||||
color::Black,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if at_cursor {
|
||||
self.rb.print(
|
||||
self.draw(
|
||||
px as usize,
|
||||
py as usize,
|
||||
rustbox::RB_NORMAL,
|
||||
Color::Black,
|
||||
Color::White,
|
||||
" ",
|
||||
color::Black,
|
||||
color::White,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if at_cursor {
|
||||
self.rb.print(
|
||||
px as usize,
|
||||
py as usize,
|
||||
rustbox::RB_NORMAL,
|
||||
Color::Black,
|
||||
Color::White,
|
||||
g,
|
||||
);
|
||||
self.draw(px as usize, py as usize, g, color::Black, color::White);
|
||||
} else {
|
||||
self.rb.print(
|
||||
px as usize,
|
||||
py as usize,
|
||||
rustbox::RB_NORMAL,
|
||||
Color::White,
|
||||
Color::Black,
|
||||
g,
|
||||
);
|
||||
self.draw(px as usize, py as usize, g, color::White, color::Black);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -591,15 +523,40 @@ impl TermUI {
|
|||
if (px >= c1.1 as isize) && (py >= c1.0 as isize) && (px <= c2.1 as isize)
|
||||
&& (py <= c2.0 as isize)
|
||||
{
|
||||
self.rb.print(
|
||||
px as usize,
|
||||
py as usize,
|
||||
rustbox::RB_NORMAL,
|
||||
Color::Black,
|
||||
Color::White,
|
||||
" ",
|
||||
);
|
||||
self.draw(px as usize, py as usize, " ", color::Black, color::White);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn clear(&self) {
|
||||
write!(
|
||||
self.out.borrow_mut(),
|
||||
"{}{}",
|
||||
color::Bg(color::Black),
|
||||
termion::clear::All
|
||||
).unwrap();
|
||||
self.out.borrow_mut().flush().unwrap();
|
||||
}
|
||||
|
||||
fn present(&self) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
fn draw<C1: color::Color, C2: color::Color>(
|
||||
&self,
|
||||
x: usize,
|
||||
y: usize,
|
||||
text: &str,
|
||||
fg: C1,
|
||||
bg: C2,
|
||||
) {
|
||||
write!(
|
||||
self.out.borrow_mut(),
|
||||
"{}{}{}{}",
|
||||
termion::cursor::Goto((x + 1) as u16, (y + 1) as u16),
|
||||
color::Fg(fg),
|
||||
color::Bg(bg),
|
||||
text
|
||||
).unwrap();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user