diff --git a/.gitignore b/.gitignore index aa2de79a..709309bd 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ update.sh .zsh_history .zshrc /.fish +.vscode/**/* diff --git a/Cargo.lock b/Cargo.lock index 531448a6..01133599 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -43,29 +43,17 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" -[[package]] -name = "bstr" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" -dependencies = [ - "lazy_static", - "memchr", - "regex-automata", - "serde", -] - [[package]] name = "bumpalo" -version = "3.11.1" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" [[package]] name = "cc" -version = "1.0.78" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" [[package]] name = "cfg-if" @@ -90,9 +78,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.0.29" +version = "4.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d63b9e9c07271b9957ad22c173bae2a4d9a81127680962039296abcd2f8251d" +checksum = "ec0b0588d44d4d63a87dbd75c136c166bbfd9a86a31cb89e09906521c7d3f5e3" dependencies = [ "bitflags", "clap_derive", @@ -105,9 +93,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.0.21" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0177313f9f02afc995627906bbd8967e2be069f5261954222dac78290c2b9014" +checksum = "684a277d672e91966334af371f1a7b5833f9aa00b07c84e92fbce95e00208ce8" dependencies = [ "heck", "proc-macro-error", @@ -118,9 +106,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.3.0" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8" +checksum = "350b9cf31731f9957399229e9b2adc51eeabdfbe9d71d9a0552275fd12710d09" dependencies = [ "os_str_bytes", ] @@ -141,13 +129,38 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" +[[package]] +name = "crossterm" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77f67c7faacd4db07a939f55d66a983a5355358a1f17d32cc9a8d01d1266b9ce" +dependencies = [ + "bitflags", + "crossterm_winapi", + "filedescriptor", + "libc", + "mio", + "parking_lot", + "signal-hook", + "signal-hook-mio", + "winapi", +] + +[[package]] +name = "crossterm_winapi" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ae1b35a484aa10e07fe0638d02301c5ad24de82d310ccbd2f3693da5f09bf1c" +dependencies = [ + "winapi", +] + [[package]] name = "csv" -version = "1.1.6" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1" +checksum = "af91f40b7355f82b0a891f50e70399475945bb0b0da4f1700ce60761c9d3e359" dependencies = [ - "bstr", "csv-core", "itoa", "ryu", @@ -165,9 +178,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.83" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdf07d07d6531bfcdbe9b8b739b104610c6508dcc4d63b410585faf338241daf" +checksum = "86d3488e7665a7a483b57e25bdd90d0aeb2bc7608c8d0346acf2ad3f1caf1d62" dependencies = [ "cc", "cxxbridge-flags", @@ -177,9 +190,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.83" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2eb5b96ecdc99f72657332953d4d9c50135af1bac34277801cc3937906ebd39" +checksum = "48fcaf066a053a41a81dfb14d57d99738b767febb8b735c3016e469fac5da690" dependencies = [ "cc", "codespan-reporting", @@ -192,15 +205,15 @@ dependencies = [ [[package]] name = "cxxbridge-flags" -version = "1.0.83" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac040a39517fd1674e0f32177648334b0f4074625b5588a64519804ba0553b12" +checksum = "a2ef98b8b717a829ca5603af80e1f9e2e48013ab227b68ef37872ef84ee479bf" [[package]] name = "cxxbridge-macro" -version = "1.0.83" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1362b0ddcfc4eb0a1f57b68bd77dd99f0e826958a96abd0ae9bd092e114ffed6" +checksum = "086c685979a698443656e5cf7856c95c642295a38599f12fb1ff76fb28d19892" dependencies = [ "proc-macro2", "quote", @@ -250,9 +263,9 @@ dependencies = [ [[package]] name = "either" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" [[package]] name = "errno" @@ -287,6 +300,17 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" +[[package]] +name = "filedescriptor" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7199d965852c3bac31f779ef99cbb4537f80e952e2d6aa0ffeb30cce00f4f46e" +dependencies = [ + "libc", + "thiserror", + "winapi", +] + [[package]] name = "getrandom" version = "0.2.8" @@ -318,18 +342,15 @@ dependencies = [ [[package]] name = "heck" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.2.6" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" [[package]] name = "humantime" @@ -363,9 +384,9 @@ dependencies = [ [[package]] name = "io-lifetimes" -version = "1.0.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46112a93252b123d31a119a8d1a1ac19deac4fac6e0e8b0df58f0d4e5870e63c" +checksum = "1abeb7a0dd0f8181267ff8adc397075586500b81b28a73e8a0208b00fc170fb3" dependencies = [ "libc", "windows-sys", @@ -373,9 +394,9 @@ dependencies = [ [[package]] name = "is-terminal" -version = "0.4.1" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927609f78c2913a6f6ac3c27a4fe87f43e2a35367c0c4b0f8265e8f49a104330" +checksum = "21b6b32576413a8e69b90e952e4a026476040d81017b80445deda5f2d3921857" dependencies = [ "hermit-abi", "io-lifetimes", @@ -394,30 +415,24 @@ dependencies = [ [[package]] name = "itoa" -version = "0.4.8" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" +checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" [[package]] name = "js-sys" -version = "0.3.60" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" dependencies = [ "wasm-bindgen", ] -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - [[package]] name = "libc" -version = "0.2.138" +version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" [[package]] name = "libsqlite3-sys" @@ -432,9 +447,9 @@ dependencies = [ [[package]] name = "link-cplusplus" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369" +checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" dependencies = [ "cc", ] @@ -445,6 +460,16 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" +[[package]] +name = "lock_api" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +dependencies = [ + "autocfg", + "scopeguard", +] + [[package]] name = "log" version = "0.4.17" @@ -460,6 +485,7 @@ version = "0.7.1" dependencies = [ "chrono", "clap", + "crossterm", "csv", "directories-next", "humantime", @@ -470,7 +496,6 @@ dependencies = [ "relative-path", "rusqlite", "shellexpand", - "termion", "unicode-segmentation", ] @@ -480,6 +505,18 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +[[package]] +name = "mio" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" +dependencies = [ + "libc", + "log", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys", +] + [[package]] name = "num-integer" version = "0.1.45" @@ -499,17 +536,11 @@ dependencies = [ "autocfg", ] -[[package]] -name = "numtoa" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" - [[package]] name = "once_cell" -version = "1.16.0" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" [[package]] name = "os_str_bytes" @@ -517,6 +548,29 @@ version = "6.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-sys", +] + [[package]] name = "pkg-config" version = "0.3.26" @@ -555,18 +609,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.47" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" +checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.21" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" dependencies = [ "proc-macro2", ] @@ -610,15 +664,6 @@ dependencies = [ "bitflags", ] -[[package]] -name = "redox_termios" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8440d8acb4fd3d277125b4bd01a6f38aee8d814b3b5fc09b3f2b825d37d3fe8f" -dependencies = [ - "redox_syscall", -] - [[package]] name = "redox_users" version = "0.4.3" @@ -632,21 +677,15 @@ dependencies = [ [[package]] name = "regex" -version = "1.7.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" +checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" dependencies = [ "aho-corasick", "memchr", "regex-syntax", ] -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" - [[package]] name = "regex-syntax" version = "0.6.28" @@ -655,9 +694,9 @@ checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" [[package]] name = "relative-path" -version = "1.7.2" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0df32d82cedd1499386877b062ebe8721f806de80b08d183c70184ef17dd1d42" +checksum = "d3bf6b372449361333ac1f498b7edae4dd5e70dccd7c0c2a7c7bce8f05ede648" [[package]] name = "rusqlite" @@ -675,9 +714,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.36.5" +version = "0.36.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3807b5d10909833d3e9acd1eb5fb988f79376ff10fce42937de71a449c4c588" +checksum = "f43abb88211988493c1abb44a70efa56ff0ce98f233b7b276146f1f3f7ba9644" dependencies = [ "bitflags", "errno", @@ -689,21 +728,27 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" +checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "scratch" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898" +checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2" [[package]] name = "serde" -version = "1.0.150" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e326c9ec8042f1b5da33252c8a37e9ffbd2c9bef0155215b6e6c80c790e05f91" +checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" [[package]] name = "shellexpand" @@ -714,6 +759,36 @@ dependencies = [ "dirs", ] +[[package]] +name = "signal-hook" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "732768f1176d21d09e076c23a93123d40bba92d50c4058da34d45c8de8e682b9" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-mio" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" +dependencies = [ + "libc", + "mio", + "signal-hook", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + [[package]] name = "smallvec" version = "1.10.0" @@ -728,9 +803,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "1.0.105" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", "quote", @@ -739,39 +814,27 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.1.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" dependencies = [ "winapi-util", ] -[[package]] -name = "termion" -version = "1.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "077185e2eac69c3f8379a4298e1e07cd36beb962290d4a51199acf0fdc10607e" -dependencies = [ - "libc", - "numtoa", - "redox_syscall", - "redox_termios", -] - [[package]] name = "thiserror" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" +checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" +checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" dependencies = [ "proc-macro2", "quote", @@ -791,15 +854,15 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" [[package]] name = "unicode-segmentation" -version = "1.10.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" [[package]] name = "unicode-width" @@ -833,9 +896,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -843,9 +906,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" dependencies = [ "bumpalo", "log", @@ -858,9 +921,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -868,9 +931,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" dependencies = [ "proc-macro2", "quote", @@ -881,9 +944,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" [[package]] name = "winapi" @@ -918,9 +981,18 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" -version = "0.42.0" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", @@ -933,42 +1005,42 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" +checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" [[package]] name = "windows_aarch64_msvc" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" +checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" [[package]] name = "windows_i686_gnu" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" +checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" [[package]] name = "windows_i686_msvc" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" +checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" [[package]] name = "windows_x86_64_gnu" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" +checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" +checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" [[package]] name = "windows_x86_64_msvc" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" +checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" diff --git a/Cargo.toml b/Cargo.toml index e90ce156..25430af8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,13 +26,18 @@ rand = "0.8" regex = "1" relative-path = "1.7" shellexpand = "2.1" -termion = "1.5" unicode-segmentation = "1.9" [dependencies.rusqlite] version = "0.28" features = ["bundled", "functions", "unlock_notify"] +[dependencies.crossterm] +version = "0.26" +features = ["use-dev-tty"] + + [dependencies.clap] version = "4" features = ["derive"] + diff --git a/src/fixed_length_grapheme_string.rs b/src/fixed_length_grapheme_string.rs index 7ee515b3..5e903128 100644 --- a/src/fixed_length_grapheme_string.rs +++ b/src/fixed_length_grapheme_string.rs @@ -1,3 +1,4 @@ +use std::io::Write; use unicode_segmentation::UnicodeSegmentation; #[derive(Debug)] @@ -7,6 +8,18 @@ pub struct FixedLengthGraphemeString { pub max_grapheme_length: u16, } +impl Write for FixedLengthGraphemeString { + fn write(&mut self, buf: &[u8]) -> std::io::Result { + let s = String::from_utf8(buf.to_vec()).unwrap(); + self.push_str(&s); + Ok(s.len()) + } + + fn flush(&mut self) -> std::io::Result<()> { + Ok(()) + } +} + impl FixedLengthGraphemeString { pub fn empty(max_grapheme_length: u16) -> FixedLengthGraphemeString { FixedLengthGraphemeString { diff --git a/src/interface.rs b/src/interface.rs index 2e7dad37..f93818b1 100644 --- a/src/interface.rs +++ b/src/interface.rs @@ -7,14 +7,15 @@ use crate::history_cleaner; use crate::settings::{InterfaceView, KeyScheme}; use crate::settings::{ResultSort, Settings}; use chrono::{Duration, TimeZone, Utc}; +use crossterm::event::KeyCode::Char; +use crossterm::event::{read, Event, KeyCode, KeyEvent, KeyModifiers}; +use crossterm::style::{Color, Print, SetBackgroundColor, SetForegroundColor}; +use crossterm::terminal::{self, LeaveAlternateScreen}; +use crossterm::terminal::{Clear, ClearType, EnterAlternateScreen}; +use crossterm::{cursor, execute, queue}; use humantime::format_duration; -use std::io::{stdin, stdout, Write}; -use termion::color; -use termion::event::Key; -use termion::input::TermRead; -use termion::raw::IntoRawMode; -use termion::screen::AlternateScreen; -use termion::{clear, cursor, terminal_size}; +use std::io::{stdout, Write}; +use std::string::String; pub struct Interface<'a> { history: &'a History, @@ -84,10 +85,10 @@ impl MenuMode { menu_text } - fn bg(&self) -> String { + fn bg(&self) -> Color { match *self { - MenuMode::Normal => color::Bg(color::LightBlue).to_string(), - MenuMode::ConfirmDelete => color::Bg(color::Red).to_string(), + MenuMode::Normal => Color::Blue, + MenuMode::ConfirmDelete => Color::Red, } } } @@ -152,74 +153,66 @@ impl<'a> Interface<'a> { } fn menubar(&self, screen: &mut W) { - if !self.settings.disable_menu { - let (width, _height): (u16, u16) = terminal_size().unwrap(); - write!( - screen, - "{hide}{cursor}{clear}{fg}{bg}{text:width$}{reset_bg}", - hide = cursor::Hide, - fg = color::Fg(color::LightWhite), - bg = self.menu_mode.bg(), - cursor = cursor::Goto(1, self.info_line_index()), - clear = clear::CurrentLine, + let (width, _height): (u16, u16) = terminal::size().unwrap(); + + queue!( + screen, + cursor::Hide, + cursor::MoveTo(0, self.info_line_index()), + Clear(ClearType::CurrentLine), + SetBackgroundColor(self.menu_mode.bg()), + SetForegroundColor(Color::White), + cursor::MoveTo(1, self.info_line_index()), + Print(format!( + "{text:width$}", text = self.menu_mode.text(self), - reset_bg = color::Bg(color::Reset), - width = width as usize - ) - .unwrap(); - screen.flush().unwrap(); - } + width = width as usize - 1 + )), + SetBackgroundColor(Color::Reset) + ) + .unwrap(); } fn prompt(&self, screen: &mut W) { let prompt_line_index = self.prompt_line_index(); - write!( - screen, - "{}{}{}{} {}", - if self.settings.lightmode { - color::Fg(color::Black).to_string() - } else { - color::Fg(color::LightWhite).to_string() - }, - cursor::Goto(1, self.prompt_line_index()), - clear::CurrentLine, - self.settings.prompt, - self.input - ) - .unwrap(); - write!( + let fg = if self.settings.lightmode { + Color::Black + } else { + Color::White + }; + queue!( screen, - "{}{}", - cursor::Goto(self.input.cursor as u16 + 3, prompt_line_index), + cursor::MoveTo(1, prompt_line_index), + SetForegroundColor(fg), + Clear(ClearType::CurrentLine), + Print(format!("{} {}", self.settings.prompt, self.input)), + cursor::MoveTo(self.input.cursor as u16 + 3, prompt_line_index), cursor::Show ) .unwrap(); - screen.flush().unwrap(); } fn debug_cursor(&self, screen: &mut W) { let result_top_index = self.result_top_index(); - write!( + queue!( screen, - "{}{}", cursor::Hide, - cursor::Goto(0, result_top_index + self.settings.results + 1) + cursor::MoveTo(0, result_top_index + self.settings.results + 1) ) .unwrap(); - screen.flush().unwrap(); } fn results(&mut self, screen: &mut W) { let result_top_index = self.result_top_index(); - write!( + queue!( screen, - "{}{}{}", cursor::Hide, - cursor::Goto(1, result_top_index), - clear::All + cursor::MoveTo(1, result_top_index), + Clear(ClearType::All) ) .unwrap(); - let (width, _height): (u16, u16) = terminal_size().unwrap(); + + let (width, _height): (u16, u16) = terminal::size().unwrap(); if !self.matches.is_empty() && self.selection > self.matches.len() - 1 { self.selection = self.matches.len() - 1; @@ -227,55 +220,52 @@ impl<'a> Interface<'a> { for (index, command) in self.matches.iter().enumerate() { let mut fg = if self.settings.lightmode { - color::Fg(color::Black).to_string() + Color::Black } else { - color::Fg(color::LightWhite).to_string() + Color::White }; let mut highlight = if self.settings.lightmode { - color::Fg(color::Blue).to_string() + Color::DarkBlue } else { - color::Fg(color::Green).to_string() + Color::DarkGreen }; - let mut bg = color::Bg(color::Reset).to_string(); + let mut bg = Color::Reset; if index == self.selection { if self.settings.lightmode { - fg = color::Fg(color::LightWhite).to_string(); - bg = color::Bg(color::LightBlack).to_string(); - highlight = color::Fg(color::White).to_string(); + fg = Color::White; + bg = Color::DarkGrey; + highlight = Color::Grey; } else { - fg = color::Fg(color::Black).to_string(); - bg = color::Bg(color::LightWhite).to_string(); - highlight = color::Fg(color::Green).to_string(); + fg = Color::Black; + bg = Color::White; + highlight = Color::DarkGreen; } } - write!(screen, "{}{}", fg, bg).unwrap(); - let command_line_index = self.command_line_index(index as i16); - - write!( + queue!( screen, - "{}{}", - cursor::Goto(1, (command_line_index + result_top_index as i16) as u16), - Interface::truncate_for_display( + cursor::MoveTo(1, (command_line_index + result_top_index as i16) as u16), + SetBackgroundColor(bg), + SetForegroundColor(fg), + Print(Interface::truncate_for_display( command, &self.input.command, width, highlight, fg, self.debug - ) + )) ) .unwrap(); if command.last_run.is_some() { - write!( + queue!( screen, - "{}", - cursor::Goto( + cursor::MoveTo( width - 9, (command_line_index + result_top_index as i16) as u16 ) @@ -312,32 +302,37 @@ impl<'a> Interface<'a> { .collect::>() .join(" "); - let highlight = if self.settings.lightmode { - color::Fg(color::Blue).to_string() + let timing_color = if self.settings.lightmode { + Color::DarkBlue } else { - color::Fg(color::LightBlue).to_string() + Color::Blue }; - - write!(screen, "{}", highlight).unwrap(); - write!(screen, "{:>9}", duration).unwrap(); + queue!( + screen, + cursor::MoveTo( + width - 9, + (command_line_index + self.result_top_index() as i16) as u16 + ), + SetForegroundColor(timing_color), + Print(format!("{:>9}", duration)), + SetForegroundColor(Color::Reset), + SetBackgroundColor(Color::Reset) + ) + .unwrap(); } - - write!(screen, "{}", color::Bg(color::Reset)).unwrap(); - write!(screen, "{}", color::Fg(color::Reset)).unwrap(); } - screen.flush().unwrap(); } #[allow(unused)] fn debug>(&self, screen: &mut W, s: S) { - write!( + queue!( screen, - "{}{}{}", - cursor::Goto(1, 2), - clear::CurrentLine, - s.into() + cursor::MoveTo(0, 0), + Clear(ClearType::CurrentLine), + Print(s.into()) ) .unwrap(); + screen.flush().unwrap(); } @@ -414,123 +409,243 @@ impl<'a> Interface<'a> { } fn select(&mut self) { - let stdin = stdin(); - let mut screen = AlternateScreen::from(stdout().into_raw_mode().unwrap()); - // let mut screen = stdout().into_raw_mode().unwrap(); - write!(screen, "{}", clear::All).unwrap(); + let mut screen = stdout(); + terminal::enable_raw_mode().unwrap(); + queue!(screen, EnterAlternateScreen, Clear(ClearType::All)).unwrap(); self.refresh_matches(true); self.results(&mut screen); self.menubar(&mut screen); self.prompt(&mut screen); - for c in stdin.keys() { + screen.flush().unwrap(); + + loop { + terminal::enable_raw_mode().unwrap(); + let event = + read().unwrap_or_else(|e| panic!("McFly error: failed to read input {:?}", &e)); self.debug_cursor(&mut screen); - if self.menu_mode != MenuMode::Normal { - match c.unwrap() { - Key::Ctrl('c') - | Key::Ctrl('d') - | Key::Ctrl('g') - | Key::Ctrl('z') - | Key::Ctrl('r') => { - self.run = false; - self.input.clear(); + if let Event::Key(key_event) = event { + if self.menu_mode != MenuMode::Normal { + match key_event { + KeyEvent { + modifiers: KeyModifiers::CONTROL, + code: Char('c') | Char('d') | Char('g') | Char('z') | Char('r'), + .. + } => { + self.run = false; + self.input.clear(); + break; + } + KeyEvent { + code: Char('y') | Char('Y'), + .. + } => { + self.confirm(true); + } + KeyEvent { + code: Char('n') | Char('N'), + .. + } + | KeyEvent { + code: KeyCode::Esc, .. + } => { + self.confirm(false); + } + _ => {} + }; + } else { + let early_out = match self.settings.key_scheme { + KeyScheme::Emacs => self.select_with_emacs_key_scheme(key_event), + KeyScheme::Vim => self.select_with_vim_key_scheme(key_event), + }; + + if early_out { break; } - Key::Char('y') | Key::Char('Y') => { - self.confirm(true); - } - Key::Char('n') | Key::Char('N') | Key::Esc => { - self.confirm(false); - } - _ => {} - } - } else { - let early_out = match self.settings.key_scheme { - KeyScheme::Emacs => self.select_with_emacs_key_scheme(c.unwrap()), - KeyScheme::Vim => self.select_with_vim_key_scheme(c.unwrap()), - }; - - if early_out { - break; } } self.results(&mut screen); self.menubar(&mut screen); self.prompt(&mut screen); + screen.flush().unwrap(); } - write!(screen, "{}{}", clear::All, cursor::Show).unwrap(); + queue!( + screen, + Clear(ClearType::All), + cursor::Show, + LeaveAlternateScreen + ) + .unwrap(); + terminal::disable_raw_mode().unwrap(); } - fn select_with_emacs_key_scheme(&mut self, k: Key) -> bool { - match k { - Key::Char('\n') | Key::Char('\r') | Key::Ctrl('j') => { + fn select_with_emacs_key_scheme(&mut self, event: KeyEvent) -> bool { + match event { + KeyEvent { + code: KeyCode::Enter, + .. + } + | KeyEvent { + modifiers: KeyModifiers::CONTROL, + code: Char('j'), + .. + } + | KeyEvent { + code: Char('\r'), .. + } + | KeyEvent { + code: Char('\n'), .. + } => { self.run = !self.settings.disable_run_command; self.accept_selection(); return true; } - Key::Char('\t') => { + + KeyEvent { + code: KeyCode::Tab, .. + } => { self.run = false; self.accept_selection(); return true; } - Key::Ctrl('c') | Key::Ctrl('g') | Key::Ctrl('z') | Key::Esc | Key::Ctrl('r') => { + + KeyEvent { + modifiers: KeyModifiers::CONTROL, + code: Char('c') | Char('g') | Char('z') | Char('r'), + .. + } + | KeyEvent { + code: KeyCode::Esc, .. + } => { self.run = false; self.input.clear(); return true; } - Key::Ctrl('b') => self.input.move_cursor(Move::Backward), - Key::Ctrl('f') => self.input.move_cursor(Move::Forward), - Key::Ctrl('a') => self.input.move_cursor(Move::BOL), - Key::Ctrl('e') => self.input.move_cursor(Move::EOL), - Key::Ctrl('w') | Key::Alt('\x08') | Key::Alt('\x7f') => { + + KeyEvent { + modifiers: KeyModifiers::CONTROL, + code, + .. + } => match code { + Char('b') => self.input.move_cursor(Move::Backward), + Char('f') => self.input.move_cursor(Move::Forward), + Char('a') => self.input.move_cursor(Move::BOL), + Char('e') => self.input.move_cursor(Move::EOL), + Char('v') => self.debug = !self.debug, + Char('k') => { + self.input.delete(Move::EOL); + self.refresh_matches(true); + } + Char('u') => { + self.input.delete(Move::BOL); + self.refresh_matches(true); + } + Char('w') => { + self.input.delete(Move::BackwardWord); + self.refresh_matches(true); + } + Char('p') => self.move_selection(MoveSelection::Up), + Char('n') => self.move_selection(MoveSelection::Down), + Char('h') => { + self.input.delete(Move::Backward); + self.refresh_matches(true); + } + Char('d') => { + self.input.delete(Move::Forward); + self.refresh_matches(true); + } + _ => {} + }, + + KeyEvent { + modifiers: KeyModifiers::ALT, + code: Char('\x08') | Char('\x7f'), + .. + } => { self.input.delete(Move::BackwardWord); self.refresh_matches(true); } - Key::Alt('d') => { - self.input.delete(Move::ForwardWord); - self.refresh_matches(true); - } - Key::Ctrl('v') => { - self.debug = !self.debug; - } - Key::Alt('b') => self.input.move_cursor(Move::BackwardWord), - Key::Alt('f') => self.input.move_cursor(Move::ForwardWord), - Key::Left => self.input.move_cursor(Move::Backward), - Key::Right => self.input.move_cursor(Move::Forward), - Key::Up | Key::PageUp | Key::Ctrl('p') => self.move_selection(MoveSelection::Up), - Key::Down | Key::PageDown | Key::Ctrl('n') => self.move_selection(MoveSelection::Down), - Key::Ctrl('k') => { - self.input.delete(Move::EOL); - self.refresh_matches(true); - } - Key::Ctrl('u') => { - self.input.delete(Move::BOL); - self.refresh_matches(true); - self.selection = 0; - } - Key::Backspace | Key::Ctrl('h') => { + + KeyEvent { + modifiers: KeyModifiers::ALT, + code, + .. + } => match code { + Char('b') => self.input.move_cursor(Move::BackwardWord), + Char('f') => self.input.move_cursor(Move::ForwardWord), + Char('d') => { + self.input.delete(Move::ForwardWord); + self.refresh_matches(true); + } + _ => {} + }, + + KeyEvent { + code: KeyCode::Left, + .. + } => self.input.move_cursor(Move::Backward), + + KeyEvent { + code: KeyCode::Right, + .. + } => self.input.move_cursor(Move::Forward), + + KeyEvent { + code: KeyCode::Up | KeyCode::PageUp, + .. + } => self.move_selection(MoveSelection::Up), + + KeyEvent { + code: KeyCode::Down | KeyCode::PageDown, + .. + } => self.move_selection(MoveSelection::Down), + + KeyEvent { + code: KeyCode::Backspace, + .. + } => { self.input.delete(Move::Backward); self.refresh_matches(true); } - Key::Delete | Key::Ctrl('d') => { + + KeyEvent { + code: KeyCode::Delete, + .. + } => { self.input.delete(Move::Forward); self.refresh_matches(true); } - Key::Home => self.input.move_cursor(Move::BOL), - Key::End => self.input.move_cursor(Move::EOL), - Key::Char(c) => { + + KeyEvent { + code: KeyCode::Home, + .. + } => self.input.move_cursor(Move::BOL), + + KeyEvent { + code: KeyCode::End, .. + } => self.input.move_cursor(Move::EOL), + + KeyEvent { code: Char(c), .. } => { self.input.insert(c); self.refresh_matches(true); } - Key::F(1) => { + + KeyEvent { + code: KeyCode::F(1), + .. + } => { self.switch_result_sort(); self.refresh_matches(true); } - Key::F(2) => { + + KeyEvent { + code: KeyCode::F(2), + .. + } => { if !self.matches.is_empty() { if self.settings.delete_without_confirm { self.delete_selection(); @@ -539,62 +654,116 @@ impl<'a> Interface<'a> { } } } + _ => {} } false } - fn select_with_vim_key_scheme(&mut self, k: Key) -> bool { + fn select_with_vim_key_scheme(&mut self, event: KeyEvent) -> bool { if self.in_vim_insert_mode { - match k { - Key::Char('\n') | Key::Char('\r') | Key::Ctrl('j') => { - self.run = !self.settings.disable_run_command; + match event { + KeyEvent { + code: KeyCode::Tab, .. + } => { + self.run = false; self.accept_selection(); return true; } - Key::Char('\t') => { - self.run = false; + + KeyEvent { + code: KeyCode::Enter, + .. + } + | KeyEvent { + modifiers: KeyModifiers::CONTROL, + code: Char('j'), + .. + } => { + self.run = !self.settings.disable_run_command; self.accept_selection(); return true; } - Key::Ctrl('c') | Key::Ctrl('g') | Key::Ctrl('z') | Key::Ctrl('r') => { + + KeyEvent { + modifiers: KeyModifiers::CONTROL, + code: Char('c') | Char('g') | Char('z') | Char('r'), + .. + } => { self.run = false; self.input.clear(); return true; } - Key::Left => self.input.move_cursor(Move::Backward), - Key::Right => self.input.move_cursor(Move::Forward), - Key::Up | Key::PageUp | Key::Ctrl('u') | Key::Ctrl('p') => { - self.move_selection(MoveSelection::Up) + + KeyEvent { + code: KeyCode::Left, + .. + } => self.input.move_cursor(Move::Backward), + KeyEvent { + code: KeyCode::Right, + .. + } => self.input.move_cursor(Move::Forward), + + KeyEvent { + code: KeyCode::Up | KeyCode::PageUp, + .. } - Key::Down | Key::PageDown | Key::Ctrl('d') | Key::Ctrl('n') => { - self.move_selection(MoveSelection::Down) + | KeyEvent { + modifiers: KeyModifiers::CONTROL, + code: Char('u') | Char('p'), + .. + } => self.move_selection(MoveSelection::Up), + + KeyEvent { + code: KeyCode::Down | KeyCode::PageDown, + .. } - Key::Esc => self.in_vim_insert_mode = false, - Key::Backspace => { + | KeyEvent { + modifiers: KeyModifiers::CONTROL, + code: Char('d') | Char('n'), + .. + } => self.move_selection(MoveSelection::Down), + + KeyEvent { + code: KeyCode::Esc, .. + } => self.in_vim_insert_mode = false, + KeyEvent { + code: KeyCode::Backspace, + .. + } => { self.input.delete(Move::Backward); self.refresh_matches(true); } - Key::Delete => { + KeyEvent { + code: KeyCode::Delete, + .. + } => { self.input.delete(Move::Forward); self.refresh_matches(true); } - Key::Ctrl('w') => { - self.input.delete(Move::BackwardWord); - self.refresh_matches(true); - } - Key::Home => self.input.move_cursor(Move::BOL), - Key::End => self.input.move_cursor(Move::EOL), - Key::Char(c) => { + KeyEvent { + code: KeyCode::Home, + .. + } => self.input.move_cursor(Move::BOL), + KeyEvent { + code: KeyCode::End, .. + } => self.input.move_cursor(Move::EOL), + KeyEvent { code: Char(c), .. } => { self.input.insert(c); self.refresh_matches(true); } - Key::F(1) => { + KeyEvent { + code: KeyCode::F(1), + .. + } => { self.switch_result_sort(); self.refresh_matches(true); } - Key::F(2) => { + KeyEvent { + code: KeyCode::F(2), + .. + } => { if !self.matches.is_empty() { if self.settings.delete_without_confirm { self.delete_selection(); @@ -606,71 +775,128 @@ impl<'a> Interface<'a> { _ => {} } } else { - match k { - Key::Char('\n') | Key::Char('\r') | Key::Ctrl('j') => { - self.run = ! self.settings.disable_run_command; + match event { + KeyEvent { + code: KeyCode::Tab, .. + } => { + self.run = false; self.accept_selection(); return true; } - Key::Char('\t') => { - self.run = false; + + KeyEvent { + code: KeyCode::Enter, + .. + } + | KeyEvent { + modifiers: KeyModifiers::CONTROL, + code: Char('j'), + .. + } => { + self.run = !self.settings.disable_run_command; self.accept_selection(); return true; } - Key::Ctrl('c') - | Key::Ctrl('g') - | Key::Ctrl('z') - | Key::Esc - | Key::Char('q') - // TODO add ZZ as shortcut - | Key::Ctrl('r') => { + + KeyEvent { + modifiers: KeyModifiers::CONTROL, + code: Char('c') | Char('g') | Char('z') | Char('r'), // TODO add ZZ as shortcut + .. + } + | KeyEvent { + code: KeyCode::Esc, .. + } => { self.run = false; self.input.clear(); return true; } - Key::Left | Key::Char('h') => self.input.move_cursor(Move::Backward), - Key::Right | Key::Char('l') => self.input.move_cursor(Move::Forward), - Key::Up | Key::PageUp | Key::Char('k') | Key::Ctrl('u') => self.move_selection(MoveSelection::Up), - Key::Down | Key::PageDown | Key::Char('j') | Key::Ctrl('d') => self.move_selection(MoveSelection::Down), - Key::Char('b') | Key::Char('e') => self.input.move_cursor(Move::BackwardWord), - Key::Char('w') => self.input.move_cursor(Move::ForwardWord), - Key::Char('0') | Key::Char('^') => self.input.move_cursor(Move::BOL), - Key::Char('$') => self.input.move_cursor(Move::EOL), - Key::Char('i') => self.in_vim_insert_mode = true, - Key::Char('I') => { - self.input.move_cursor(Move::BOL); - self.in_vim_insert_mode = true; - } - Key::Char('a') => { - self.input.move_cursor(Move::Forward); - self.in_vim_insert_mode = true; - } - Key::Char('A') => { - self.input.move_cursor(Move::EOL); - self.in_vim_insert_mode = true; - } - Key::Backspace => { + + KeyEvent { + code: KeyCode::Left | Char('h'), + .. + } => self.input.move_cursor(Move::Backward), + KeyEvent { + code: KeyCode::Right | Char('l'), + .. + } => self.input.move_cursor(Move::Forward), + + KeyEvent { + code: KeyCode::Up | KeyCode::PageUp | Char('k'), + .. + } + | KeyEvent { + modifiers: KeyModifiers::CONTROL, + code: Char('u'), + .. + } => self.move_selection(MoveSelection::Up), + + KeyEvent { + code: KeyCode::Down | KeyCode::PageDown | Char('j'), + .. + } + | KeyEvent { + modifiers: KeyModifiers::CONTROL, + code: Char('d'), + .. + } => self.move_selection(MoveSelection::Down), + + KeyEvent { + code: Char('b') | Char('e'), + .. + } => self.input.move_cursor(Move::BackwardWord), + KeyEvent { + code: Char('w'), .. + } => self.input.move_cursor(Move::ForwardWord), + KeyEvent { + code: Char('0') | Char('^'), + .. + } => self.input.move_cursor(Move::BOL), + KeyEvent { + code: Char('$'), .. + } => self.input.move_cursor(Move::EOL), + + KeyEvent { + code: Char('i') | Char('a'), + .. + } => self.in_vim_insert_mode = true, + + KeyEvent { + code: KeyCode::Backspace, + .. + } => { self.input.delete(Move::Backward); self.refresh_matches(true); } - Key::Delete | Key::Char('x') => { + KeyEvent { + code: KeyCode::Delete | Char('x'), + .. + } => { self.input.delete(Move::Forward); self.refresh_matches(true); } - Key::Home => self.input.move_cursor(Move::BOL), - Key::End => self.input.move_cursor(Move::EOL), - Key::Char(_c) => { - - } - Key::F(1) => { + KeyEvent { + code: KeyCode::Home, + .. + } => self.input.move_cursor(Move::BOL), + KeyEvent { + code: KeyCode::End, .. + } => self.input.move_cursor(Move::EOL), + + KeyEvent { + code: KeyCode::F(1), + .. + } => { self.switch_result_sort(); self.refresh_matches(true); - }, - Key::F(2) => { + } + KeyEvent { + code: KeyCode::F(2), + .. + } => { if !self.matches.is_empty() { if self.settings.delete_without_confirm { self.delete_selection(); - }else{ + } else { self.menu_mode = MenuMode::ConfirmDelete; } } @@ -686,8 +912,8 @@ impl<'a> Interface<'a> { command: &Command, search: &str, width: u16, - highlight_color: String, - base_color: String, + highlight_color: Color, + base_color: Color, debug: bool, ) -> String { let mut prev: usize = 0; @@ -705,9 +931,9 @@ impl<'a> Interface<'a> { out.push_grapheme_str(&command.cmd[prev..*start]); } - out.push_str(&highlight_color); + execute!(out, SetForegroundColor(highlight_color)).unwrap(); out.push_grapheme_str(&command.cmd[*start..*end]); - out.push_str(&base_color); + execute!(out, SetForegroundColor(base_color)).unwrap(); prev = *end; } } @@ -719,7 +945,7 @@ impl<'a> Interface<'a> { if debug { out.max_grapheme_length += debug_space; out.push_grapheme_str(" "); - out.push_str(&format!("{}", color::Fg(color::LightBlue))); + execute!(out, SetForegroundColor(Color::Blue)).unwrap(); out.push_grapheme_str(format!("rnk: {:.*} ", 2, command.rank)); out.push_grapheme_str(format!("age: {:.*} ", 2, command.features.age_factor)); out.push_grapheme_str(format!("lng: {:.*} ", 2, command.features.length_factor)); @@ -746,14 +972,14 @@ impl<'a> Interface<'a> { "s_occ: {:.*} ", 2, command.features.selected_occurrences_factor )); - out.push_str(&base_color); + execute!(out, SetForegroundColor(base_color)).unwrap(); } out.string } fn result_top_index(&self) -> u16 { - let (_width, height): (u16, u16) = terminal_size().unwrap(); + let (_width, height): (u16, u16) = terminal::size().unwrap(); if self.is_screen_view_bottom() { return height - RESULTS_TOP_INDEX; @@ -762,7 +988,7 @@ impl<'a> Interface<'a> { } fn prompt_line_index(&self) -> u16 { - let (_width, height): (u16, u16) = terminal_size().unwrap(); + let (_width, height): (u16, u16) = terminal::size().unwrap(); if self.is_screen_view_bottom() { return height - PROMPT_LINE_INDEX; } @@ -770,7 +996,7 @@ impl<'a> Interface<'a> { } fn info_line_index(&self) -> u16 { - let (_width, height): (u16, u16) = terminal_size().unwrap(); + let (_width, height): (u16, u16) = terminal::size().unwrap(); if self.is_screen_view_bottom() { return height; }