mirror of
https://github.com/nushell/nushell.git
synced 2024-11-22 08:23:24 +01:00
A real parser (lalrpop)
This commit is contained in:
parent
cd92f579c9
commit
b74daa2e60
0
.cargo/config
Normal file
0
.cargo/config
Normal file
53
Cargo.lock
generated
53
Cargo.lock
generated
@ -639,6 +639,18 @@ dependencies = [
|
|||||||
"syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
"syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "env_logger"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "error-chain"
|
name = "error-chain"
|
||||||
version = "0.12.1"
|
version = "0.12.1"
|
||||||
@ -828,6 +840,11 @@ dependencies = [
|
|||||||
"winapi-build 0.1.1 (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 = "lalrpop-util"
|
||||||
|
version = "0.17.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lazy_static"
|
name = "lazy_static"
|
||||||
version = "1.3.0"
|
version = "1.3.0"
|
||||||
@ -985,11 +1002,15 @@ dependencies = [
|
|||||||
"futures_codec 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures_codec 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"lalrpop-util 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"nom 5.0.0-beta1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"nom 5.0.0-beta1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ordered-float 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ordered-float 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"pancurses 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"pancurses 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"pretty_env_logger 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"prettyprint 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"prettyprint 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"prettytable-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"prettytable-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rustyline 4.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustyline 4.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"subprocess 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
"subprocess 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"sysinfo 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"sysinfo 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -1179,6 +1200,16 @@ dependencies = [
|
|||||||
"xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pretty_env_logger"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "prettyprint"
|
name = "prettyprint"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
@ -1656,6 +1687,14 @@ dependencies = [
|
|||||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "termcolor"
|
||||||
|
version = "1.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "termion"
|
name = "termion"
|
||||||
version = "1.5.2"
|
version = "1.5.2"
|
||||||
@ -1854,6 +1893,15 @@ 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 = "wincolor"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winreg"
|
name = "winreg"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
@ -1953,6 +2001,7 @@ dependencies = [
|
|||||||
"checksum enum-map-internals 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "38b0bacf3ea7aba18ce84032efc3f0fa29f5c814048b742ab3e64d07d83ac3e8"
|
"checksum enum-map-internals 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "38b0bacf3ea7aba18ce84032efc3f0fa29f5c814048b742ab3e64d07d83ac3e8"
|
||||||
"checksum enumset 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cac0a22e173f6570a7d69a2ab9e3fe79cf0dcdd0fdb162bfc932b97158f2b2a7"
|
"checksum enumset 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cac0a22e173f6570a7d69a2ab9e3fe79cf0dcdd0fdb162bfc932b97158f2b2a7"
|
||||||
"checksum enumset_derive 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "01d93b926a992a4a526c2a14e2faf734fdef5bf9d0a52ba69a2ca7d4494c284b"
|
"checksum enumset_derive 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "01d93b926a992a4a526c2a14e2faf734fdef5bf9d0a52ba69a2ca7d4494c284b"
|
||||||
|
"checksum env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b61fa891024a945da30a9581546e8cfaf5602c7b3f4c137a2805cf388f92075a"
|
||||||
"checksum error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab49e9dcb602294bc42f9a7dfc9bc6e936fca4418ea300dbfb84fe16de0b7d9"
|
"checksum error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab49e9dcb602294bc42f9a7dfc9bc6e936fca4418ea300dbfb84fe16de0b7d9"
|
||||||
"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2"
|
"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2"
|
||||||
"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1"
|
"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1"
|
||||||
@ -1976,6 +2025,7 @@ dependencies = [
|
|||||||
"checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358"
|
"checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358"
|
||||||
"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f"
|
"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f"
|
||||||
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||||
|
"checksum lalrpop-util 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9768f55211206d3c17181108d8facb80bdffc1f1e674a67b1dddb2743529ca19"
|
||||||
"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14"
|
"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14"
|
||||||
"checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
|
"checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
|
||||||
"checksum lexical-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e82e023e062f1d25f807ad182008fba1b46538e999f908a08cc0c29e084462e"
|
"checksum lexical-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e82e023e062f1d25f807ad182008fba1b46538e999f908a08cc0c29e084462e"
|
||||||
@ -2014,6 +2064,7 @@ dependencies = [
|
|||||||
"checksum pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587"
|
"checksum pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587"
|
||||||
"checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c"
|
"checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c"
|
||||||
"checksum plist 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f4739851c08dd9a62a78beff2edf1a438517268b2c563c42fc6d9d3139e42d2a"
|
"checksum plist 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f4739851c08dd9a62a78beff2edf1a438517268b2c563c42fc6d9d3139e42d2a"
|
||||||
|
"checksum pretty_env_logger 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df8b3f4e0475def7d9c2e5de8e5a1306949849761e107b360d03e98eafaffd61"
|
||||||
"checksum prettyprint 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2705417f8aa07cb6308db42e55623479c1c9667942a4d5e4174c684e5da5590d"
|
"checksum prettyprint 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2705417f8aa07cb6308db42e55623479c1c9667942a4d5e4174c684e5da5590d"
|
||||||
"checksum prettytable-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0fd04b170004fa2daccf418a7f8253aaf033c27760b5f225889024cf66d7ac2e"
|
"checksum prettytable-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0fd04b170004fa2daccf418a7f8253aaf033c27760b5f225889024cf66d7ac2e"
|
||||||
"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
|
"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
|
||||||
@ -2069,6 +2120,7 @@ dependencies = [
|
|||||||
"checksum sysinfo 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)" = "65f0e28a49b7bf142cee89befd7077b40627d7cc70aa8a8acfe03afc26016c33"
|
"checksum sysinfo 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)" = "65f0e28a49b7bf142cee89befd7077b40627d7cc70aa8a8acfe03afc26016c33"
|
||||||
"checksum term 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "edd106a334b7657c10b7c540a0106114feadeb4dc314513e97df481d5d966f42"
|
"checksum term 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "edd106a334b7657c10b7c540a0106114feadeb4dc314513e97df481d5d966f42"
|
||||||
"checksum term_size 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9e5b9a66db815dcfd2da92db471106457082577c3c278d4138ab3e3b4e189327"
|
"checksum term_size 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9e5b9a66db815dcfd2da92db471106457082577c3c278d4138ab3e3b4e189327"
|
||||||
|
"checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f"
|
||||||
"checksum termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dde0593aeb8d47accea5392b39350015b5eccb12c0d98044d856983d89548dea"
|
"checksum termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dde0593aeb8d47accea5392b39350015b5eccb12c0d98044d856983d89548dea"
|
||||||
"checksum termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72b620c5ea021d75a735c943269bb07d30c9b77d6ac6b236bc8b5c496ef05625"
|
"checksum termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72b620c5ea021d75a735c943269bb07d30c9b77d6ac6b236bc8b5c496ef05625"
|
||||||
"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"
|
||||||
@ -2096,6 +2148,7 @@ dependencies = [
|
|||||||
"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-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9"
|
"checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9"
|
||||||
"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 wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba"
|
||||||
"checksum winreg 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a27a759395c1195c4cc5cda607ef6f8f6498f64e78f7900f5de0a127a424704a"
|
"checksum winreg 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a27a759395c1195c4cc5cda607ef6f8f6498f64e78f7900f5de0a127a424704a"
|
||||||
"checksum xi-unicode 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "12ea8eda4b1eb72f02d148402e23832d56a33f55d8c1b2d5bcdde91d79d47cb1"
|
"checksum xi-unicode 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "12ea8eda4b1eb72f02d148402e23832d56a33f55d8c1b2d5bcdde91d79d47cb1"
|
||||||
"checksum xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "541b12c998c5b56aa2b4e6f18f03664eef9a4fd0a246a55594efae6cc2d964b5"
|
"checksum xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "541b12c998c5b56aa2b4e6f18f03664eef9a4fd0a246a55594efae6cc2d964b5"
|
||||||
|
@ -33,6 +33,10 @@ tokio-fs = "0.1.6"
|
|||||||
futures_codec = "0.2.2"
|
futures_codec = "0.2.2"
|
||||||
term = "0.5.2"
|
term = "0.5.2"
|
||||||
bytes = "0.4.12"
|
bytes = "0.4.12"
|
||||||
|
log = "0.4.6"
|
||||||
|
pretty_env_logger = "0.3.0"
|
||||||
|
lalrpop-util = "0.17.0"
|
||||||
|
regex = "1.1.6"
|
||||||
|
|
||||||
[dependencies.pancurses]
|
[dependencies.pancurses]
|
||||||
version = "0.16"
|
version = "0.16"
|
||||||
|
9
Makefile.toml
Normal file
9
Makefile.toml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
[tasks.lalrpop]
|
||||||
|
install_crate = { crate_name = "lalrpop", binary = "lalrpop", test_arg = "--help" }
|
||||||
|
command = "lalrpop"
|
||||||
|
args = ["src/parser/parser.lalrpop"]
|
||||||
|
|
||||||
|
[tasks.build]
|
||||||
|
command = "cargo"
|
||||||
|
args = ["build"]
|
||||||
|
dependencies = ["lalrpop"]
|
77
src/cli.rs
77
src/cli.rs
@ -1,14 +1,17 @@
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
use crate::commands::classified::{
|
use crate::commands::classified::{
|
||||||
ClassifiedCommand, ClassifiedInputStream, ExternalCommand, InternalCommand, StreamNext,
|
ClassifiedCommand, ClassifiedInputStream, ClassifiedPipeline, ExternalCommand, InternalCommand,
|
||||||
|
StreamNext,
|
||||||
};
|
};
|
||||||
use crate::context::Context;
|
use crate::context::Context;
|
||||||
crate use crate::errors::ShellError;
|
crate use crate::errors::ShellError;
|
||||||
crate use crate::format::{EntriesListView, GenericView};
|
crate use crate::format::{EntriesListView, GenericView};
|
||||||
use crate::object::Value;
|
use crate::object::Value;
|
||||||
|
use crate::parser::{ParsedCommand, Pipeline};
|
||||||
use crate::stream::empty_stream;
|
use crate::stream::empty_stream;
|
||||||
|
|
||||||
|
use log::debug;
|
||||||
use rustyline::error::ReadlineError;
|
use rustyline::error::ReadlineError;
|
||||||
use rustyline::{self, ColorMode, Config, Editor};
|
use rustyline::{self, ColorMode, Config, Editor};
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
@ -32,20 +35,6 @@ impl<T> MaybeOwned<'a, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn cli() -> Result<(), Box<Error>> {
|
pub async fn cli() -> Result<(), Box<Error>> {
|
||||||
let config = Config::builder().color_mode(ColorMode::Forced).build();
|
|
||||||
let h = crate::shell::Helper::new();
|
|
||||||
let mut rl: Editor<crate::shell::Helper> = Editor::with_config(config);
|
|
||||||
|
|
||||||
#[cfg(windows)]
|
|
||||||
{
|
|
||||||
let _ = ansi_term::enable_ansi_support();
|
|
||||||
}
|
|
||||||
|
|
||||||
rl.set_helper(Some(h));
|
|
||||||
if rl.load_history("history.txt").is_err() {
|
|
||||||
println!("No previous history.");
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut context = Context::basic()?;
|
let mut context = Context::basic()?;
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -68,6 +57,20 @@ pub async fn cli() -> Result<(), Box<Error>> {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let config = Config::builder().color_mode(ColorMode::Forced).build();
|
||||||
|
let h = crate::shell::Helper::new(context.clone_commands());
|
||||||
|
let mut rl: Editor<crate::shell::Helper> = Editor::with_config(config);
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
{
|
||||||
|
let _ = ansi_term::enable_ansi_support();
|
||||||
|
}
|
||||||
|
|
||||||
|
rl.set_helper(Some(h));
|
||||||
|
if rl.load_history("history.txt").is_err() {
|
||||||
|
println!("No previous history.");
|
||||||
|
}
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let readline = rl.readline(&format!(
|
let readline = rl.readline(&format!(
|
||||||
"{}> ",
|
"{}> ",
|
||||||
@ -141,7 +144,7 @@ async fn process_line(readline: Result<String, ReadlineError>, ctx: &mut Context
|
|||||||
Ok(line) if line.trim() == "" => LineResult::Success(line.clone()),
|
Ok(line) if line.trim() == "" => LineResult::Success(line.clone()),
|
||||||
|
|
||||||
Ok(line) => {
|
Ok(line) => {
|
||||||
let result = match crate::parser::shell_parser(&line) {
|
let result = match crate::parser::parse(&line, &ctx.registry()) {
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
return LineResult::Error(format!("{:?}", err));
|
return LineResult::Error(format!("{:?}", err));
|
||||||
}
|
}
|
||||||
@ -149,17 +152,14 @@ async fn process_line(readline: Result<String, ReadlineError>, ctx: &mut Context
|
|||||||
Ok(val) => val,
|
Ok(val) => val,
|
||||||
};
|
};
|
||||||
|
|
||||||
let parsed: Result<Vec<_>, _> = result
|
debug!("=== Parsed ===");
|
||||||
.1
|
debug!("{:#?}", result);
|
||||||
.into_iter()
|
|
||||||
.map(|item| classify_command(&item, ctx))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let parsed = parsed?;
|
let pipeline = classify_pipeline(&result, ctx)?;
|
||||||
|
|
||||||
let mut input = ClassifiedInputStream::new();
|
let mut input = ClassifiedInputStream::new();
|
||||||
|
|
||||||
let mut iter = parsed.into_iter().peekable();
|
let mut iter = pipeline.commands.into_iter().peekable();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let item: Option<ClassifiedCommand> = iter.next();
|
let item: Option<ClassifiedCommand> = iter.next();
|
||||||
@ -194,7 +194,7 @@ async fn process_line(readline: Result<String, ReadlineError>, ctx: &mut Context
|
|||||||
(
|
(
|
||||||
Some(ClassifiedCommand::Internal(_)),
|
Some(ClassifiedCommand::Internal(_)),
|
||||||
Some(ClassifiedCommand::External(_)),
|
Some(ClassifiedCommand::External(_)),
|
||||||
) => unimplemented!(),
|
) => return LineResult::Error(format!("Unimplemented Internal -> External",)),
|
||||||
|
|
||||||
(
|
(
|
||||||
Some(ClassifiedCommand::External(left)),
|
Some(ClassifiedCommand::External(left)),
|
||||||
@ -245,17 +245,34 @@ async fn process_line(readline: Result<String, ReadlineError>, ctx: &mut Context
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn classify_pipeline(
|
||||||
|
pipeline: &Pipeline,
|
||||||
|
context: &Context,
|
||||||
|
) -> Result<ClassifiedPipeline, ShellError> {
|
||||||
|
let commands: Result<Vec<_>, _> = pipeline
|
||||||
|
.commands
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.map(|item| classify_command(&item, context))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Ok(ClassifiedPipeline {
|
||||||
|
commands: commands?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn classify_command(
|
fn classify_command(
|
||||||
command: &[crate::parser::Item],
|
command: &ParsedCommand,
|
||||||
context: &Context,
|
context: &Context,
|
||||||
) -> Result<ClassifiedCommand, ShellError> {
|
) -> Result<ClassifiedCommand, ShellError> {
|
||||||
let command_name = &command[0].name()?;
|
let command_name = &command.name[..];
|
||||||
|
let args = &command.args;
|
||||||
|
|
||||||
let arg_list: Vec<Value> = command[1..].iter().map(|i| i.as_value()).collect();
|
let arg_list: Vec<Value> = args.iter().map(|i| Value::from_expr(i)).collect();
|
||||||
let arg_list_strings: Vec<String> = command[1..].iter().map(|i| i.print()).collect();
|
let arg_list_strings: Vec<String> = args.iter().map(|i| i.print()).collect();
|
||||||
|
|
||||||
match *command_name {
|
match command_name {
|
||||||
other => match context.has_command(*command_name) {
|
other => match context.has_command(command_name) {
|
||||||
true => {
|
true => {
|
||||||
let command = context.get_command(command_name);
|
let command = context.get_command(command_name);
|
||||||
Ok(ClassifiedCommand::Internal(InternalCommand {
|
Ok(ClassifiedCommand::Internal(InternalCommand {
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use futures::TryStreamExt;
|
use bytes::{BufMut, BytesMut};
|
||||||
use futures_codec::{Encoder, Decoder, Framed};
|
use futures_codec::{Decoder, Encoder, Framed};
|
||||||
|
use std::io::{Error, ErrorKind};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use subprocess::Exec;
|
use subprocess::Exec;
|
||||||
use std::io::{Error, ErrorKind};
|
|
||||||
use bytes::{BufMut, BytesMut};
|
|
||||||
|
|
||||||
/// A simple `Codec` implementation that splits up data into lines.
|
/// A simple `Codec` implementation that splits up data into lines.
|
||||||
pub struct LinesCodec {}
|
pub struct LinesCodec {}
|
||||||
@ -37,7 +36,7 @@ impl Decoder for LinesCodec {
|
|||||||
.map(Some)
|
.map(Some)
|
||||||
.map_err(|e| Error::new(ErrorKind::InvalidData, e))
|
.map_err(|e| Error::new(ErrorKind::InvalidData, e))
|
||||||
}
|
}
|
||||||
_ => Ok(None)
|
_ => Ok(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -70,6 +69,10 @@ impl ClassifiedInputStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
crate struct ClassifiedPipeline {
|
||||||
|
crate commands: Vec<ClassifiedCommand>,
|
||||||
|
}
|
||||||
|
|
||||||
crate enum ClassifiedCommand {
|
crate enum ClassifiedCommand {
|
||||||
Internal(InternalCommand),
|
Internal(InternalCommand),
|
||||||
External(ExternalCommand),
|
External(ExternalCommand),
|
||||||
@ -127,8 +130,7 @@ impl ExternalCommand {
|
|||||||
cmd.push_str(" ");
|
cmd.push_str(" ");
|
||||||
cmd.push_str(&arg);
|
cmd.push_str(&arg);
|
||||||
}
|
}
|
||||||
let process = Exec::shell(&cmd)
|
let process = Exec::shell(&cmd).cwd(context.env.lock().unwrap().cwd());
|
||||||
.cwd(context.env.lock().unwrap().cwd());
|
|
||||||
|
|
||||||
let mut process = match stream_next {
|
let mut process = match stream_next {
|
||||||
StreamNext::Last => process,
|
StreamNext::Last => process,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use crate::errors::ShellError;
|
use crate::errors::ShellError;
|
||||||
use crate::object::Value;
|
use crate::object::{Primitive, Value};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use log::debug;
|
||||||
|
|
||||||
// TODO: "Amount remaining" wrapper
|
// TODO: "Amount remaining" wrapper
|
||||||
|
|
||||||
@ -13,18 +14,27 @@ pub fn split(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
.map(move |v| match v {
|
.map(move |v| match v {
|
||||||
Value::Primitive(Primitive::String(s)) => {
|
Value::Primitive(Primitive::String(s)) => {
|
||||||
let splitter = args[0].as_string().unwrap();
|
let splitter = args[0].as_string().unwrap();
|
||||||
|
debug!("splitting with {:?}", splitter);
|
||||||
let split_result: Vec<_> = s.split(&splitter).filter(|s| s.trim() != "").collect();
|
let split_result: Vec<_> = s.split(&splitter).filter(|s| s.trim() != "").collect();
|
||||||
|
|
||||||
|
debug!("split result = {:?}", split_result);
|
||||||
|
|
||||||
if split_result.len() == (args.len() - 1) {
|
if split_result.len() == (args.len() - 1) {
|
||||||
let mut dict = crate::object::Dictionary::default();
|
let mut dict = crate::object::Dictionary::default();
|
||||||
for (k, v) in split_result.iter().zip(args.iter().skip(1)) {
|
for (k, v) in split_result.iter().zip(args.iter().skip(1)) {
|
||||||
dict.add(v.as_string().unwrap(), Value::Primitive(Primitive::String(k.to_string())));
|
dict.add(
|
||||||
|
v.as_string().unwrap(),
|
||||||
|
Value::Primitive(Primitive::String(k.to_string())),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
ReturnValue::Value(Value::Object(dict))
|
ReturnValue::Value(Value::Object(dict))
|
||||||
} else {
|
} else {
|
||||||
let mut dict = crate::object::Dictionary::default();
|
let mut dict = crate::object::Dictionary::default();
|
||||||
for k in args.iter().skip(1) {
|
for k in args.iter().skip(1) {
|
||||||
dict.add(k.as_string().unwrap().trim(), Value::Primitive(Primitive::String("".to_string())));
|
dict.add(
|
||||||
|
k.as_string().unwrap().trim(),
|
||||||
|
Value::Primitive(Primitive::String("".to_string())),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
ReturnValue::Value(Value::Object(dict))
|
ReturnValue::Value(Value::Object(dict))
|
||||||
}
|
}
|
||||||
|
@ -7,24 +7,15 @@ pub fn r#where(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
return Err(ShellError::string("select requires a field"));
|
return Err(ShellError::string("select requires a field"));
|
||||||
}
|
}
|
||||||
|
|
||||||
let field: Result<String, _> = args.args[0].as_string();
|
let operation = args.args[0].as_operation()?;
|
||||||
let field = field?;
|
let field = operation.left.as_string()?;
|
||||||
|
let operator = operation.operator;
|
||||||
|
let right = operation.right;
|
||||||
let input = args.input;
|
let input = args.input;
|
||||||
let operator = args.args[1].copy();
|
|
||||||
|
|
||||||
match operator {
|
let objects = input
|
||||||
Value::Primitive(Primitive::Operator(operator)) => {
|
.filter(move |item| futures::future::ready(find(&item, &field, &operator, &right)))
|
||||||
let right = args.args[2].copy();
|
.map(|item| ReturnValue::Value(item.copy()));
|
||||||
|
|
||||||
let objects = input
|
Ok(objects.boxed())
|
||||||
.filter(move |item| futures::future::ready(find(&item, &field, &operator, &right)))
|
|
||||||
.map(|item| ReturnValue::Value(item.copy()));
|
|
||||||
|
|
||||||
Ok(objects.boxed())
|
|
||||||
}
|
|
||||||
x => {
|
|
||||||
println!("{:?}", x);
|
|
||||||
Err(ShellError::string("expected a comparison operator"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
|
use crate::parser::{CommandConfig, CommandRegistry};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
use indexmap::IndexMap;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub struct Context {
|
pub struct Context {
|
||||||
commands: indexmap::IndexMap<String, Arc<dyn Command>>,
|
commands: IndexMap<String, Arc<dyn Command>>,
|
||||||
crate host: Arc<Mutex<dyn Host + Send>>,
|
crate host: Arc<Mutex<dyn Host + Send>>,
|
||||||
crate env: Arc<Mutex<Environment>>,
|
crate env: Arc<Mutex<Environment>>,
|
||||||
}
|
}
|
||||||
@ -24,6 +26,16 @@ impl Context {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn clone_commands(&self) -> indexmap::IndexMap<String, Arc<dyn Command>> {
|
||||||
|
self.commands.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn registry(&self) -> CommandMap {
|
||||||
|
CommandMap {
|
||||||
|
commands: self.clone_commands(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
crate fn has_command(&self, name: &str) -> bool {
|
crate fn has_command(&self, name: &str) -> bool {
|
||||||
self.commands.contains_key(name)
|
self.commands.contains_key(name)
|
||||||
}
|
}
|
||||||
@ -48,3 +60,20 @@ impl Context {
|
|||||||
command.run(command_args)
|
command.run(command_args)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct CommandMap {
|
||||||
|
#[allow(unused)]
|
||||||
|
commands: IndexMap<String, Arc<dyn Command>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CommandRegistry for CommandMap {
|
||||||
|
fn get(&self, name: &str) -> CommandConfig {
|
||||||
|
CommandConfig {
|
||||||
|
name: name.to_string(),
|
||||||
|
mandatory_positional: vec![],
|
||||||
|
optional_positional: vec![],
|
||||||
|
rest_positional: true,
|
||||||
|
named: IndexMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -3,7 +3,7 @@ use crate::prelude::*;
|
|||||||
|
|
||||||
use derive_new::new;
|
use derive_new::new;
|
||||||
|
|
||||||
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, new)]
|
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, new, Clone)]
|
||||||
pub struct ShellError {
|
pub struct ShellError {
|
||||||
title: String,
|
title: String,
|
||||||
error: Value,
|
error: Value,
|
||||||
@ -60,3 +60,12 @@ impl std::convert::From<subprocess::PopenError> for ShellError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::convert::From<nom::Err<(&str, nom::error::ErrorKind)>> for ShellError {
|
||||||
|
fn from(input: nom::Err<(&str, nom::error::ErrorKind)>) -> ShellError {
|
||||||
|
ShellError {
|
||||||
|
title: format!("{:?}", input),
|
||||||
|
error: Value::nothing(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -43,6 +43,14 @@ impl RenderView for GenericView<'value> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Value::Operation(o) => {
|
||||||
|
host.stdout(&format!(
|
||||||
|
"Unexpectedly trying to print an operation: {:?}",
|
||||||
|
o
|
||||||
|
));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
Value::Error(e) => {
|
Value::Error(e) => {
|
||||||
host.stdout(&format!("{:?}", e));
|
host.stdout(&format!("{:?}", e));
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -19,6 +19,7 @@ mod stream;
|
|||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
fn main() -> Result<(), Box<Error>> {
|
fn main() -> Result<(), Box<Error>> {
|
||||||
|
pretty_env_logger::init();
|
||||||
futures::executor::block_on(crate::cli::cli())?;
|
futures::executor::block_on(crate::cli::cli())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
use crate::errors::ShellError;
|
use crate::errors::ShellError;
|
||||||
use crate::object::DataDescriptor;
|
use crate::object::DataDescriptor;
|
||||||
use crate::parser::parse::Operator;
|
use crate::parser::tokens::{self, Operator};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use ansi_term::Color;
|
use ansi_term::Color;
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use chrono_humanize::Humanize;
|
use chrono_humanize::Humanize;
|
||||||
|
use derive_new::new;
|
||||||
use ordered_float::OrderedFloat;
|
use ordered_float::OrderedFloat;
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
|
|
||||||
@ -20,7 +21,6 @@ pub enum Primitive {
|
|||||||
String(String),
|
String(String),
|
||||||
Boolean(bool),
|
Boolean(bool),
|
||||||
Date(DateTime<Utc>),
|
Date(DateTime<Utc>),
|
||||||
Operator(Operator),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Primitive {
|
impl Primitive {
|
||||||
@ -51,27 +51,64 @@ impl Primitive {
|
|||||||
(false, Some(_)) => format!(""),
|
(false, Some(_)) => format!(""),
|
||||||
},
|
},
|
||||||
Primitive::Date(d) => format!("{}", d.humanize()),
|
Primitive::Date(d) => format!("{}", d.humanize()),
|
||||||
Primitive::Operator(o) => o.print(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq)]
|
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Clone, new)]
|
||||||
|
pub struct Operation {
|
||||||
|
crate left: Value,
|
||||||
|
crate operator: Operator,
|
||||||
|
crate right: Value,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Clone)]
|
||||||
pub enum Value {
|
pub enum Value {
|
||||||
Primitive(Primitive),
|
Primitive(Primitive),
|
||||||
Object(crate::object::Dictionary),
|
Object(crate::object::Dictionary),
|
||||||
List(Vec<Value>),
|
List(Vec<Value>),
|
||||||
|
Operation(Box<Operation>),
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
Error(Box<ShellError>),
|
Error(Box<ShellError>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Value {
|
impl Value {
|
||||||
|
crate fn from_leaf(leaf: &tokens::Leaf) -> Value {
|
||||||
|
use tokens::*;
|
||||||
|
|
||||||
|
match leaf {
|
||||||
|
Leaf::String(s) => Value::string(s),
|
||||||
|
Leaf::Bare(s) => Value::string(s),
|
||||||
|
Leaf::Boolean(b) => Value::boolean(*b),
|
||||||
|
Leaf::Int(i) => Value::int(*i),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
crate fn from_expr(expr: &tokens::Expression) -> Value {
|
||||||
|
use tokens::*;
|
||||||
|
|
||||||
|
match expr {
|
||||||
|
Expression::Leaf(leaf) => Value::from_leaf(leaf),
|
||||||
|
|
||||||
|
Expression::Binary(Binary {
|
||||||
|
left,
|
||||||
|
operator,
|
||||||
|
right,
|
||||||
|
}) => Value::Operation(Box::new(Operation::new(
|
||||||
|
Value::from_leaf(left),
|
||||||
|
*operator,
|
||||||
|
Value::from_leaf(right),
|
||||||
|
))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
crate fn data_descriptors(&self) -> Vec<DataDescriptor> {
|
crate fn data_descriptors(&self) -> Vec<DataDescriptor> {
|
||||||
match self {
|
match self {
|
||||||
Value::Primitive(_) => vec![DataDescriptor::value_of()],
|
Value::Primitive(_) => vec![DataDescriptor::value_of()],
|
||||||
Value::Object(o) => o.data_descriptors(),
|
Value::Object(o) => o.data_descriptors(),
|
||||||
Value::List(_) => vec![],
|
Value::List(_) => vec![],
|
||||||
|
Value::Operation(_) => vec![],
|
||||||
Value::Error(_) => vec![],
|
Value::Error(_) => vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -81,6 +118,7 @@ impl Value {
|
|||||||
Value::Primitive(_) => MaybeOwned::Owned(Value::nothing()),
|
Value::Primitive(_) => MaybeOwned::Owned(Value::nothing()),
|
||||||
Value::Object(o) => o.get_data_by_key(name),
|
Value::Object(o) => o.get_data_by_key(name),
|
||||||
Value::List(_) => MaybeOwned::Owned(Value::nothing()),
|
Value::List(_) => MaybeOwned::Owned(Value::nothing()),
|
||||||
|
Value::Operation(_) => MaybeOwned::Owned(Value::nothing()),
|
||||||
Value::Error(_) => MaybeOwned::Owned(Value::nothing()),
|
Value::Error(_) => MaybeOwned::Owned(Value::nothing()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -90,6 +128,7 @@ impl Value {
|
|||||||
p @ Value::Primitive(_) => MaybeOwned::Borrowed(p),
|
p @ Value::Primitive(_) => MaybeOwned::Borrowed(p),
|
||||||
Value::Object(o) => o.get_data(desc),
|
Value::Object(o) => o.get_data(desc),
|
||||||
Value::List(_) => MaybeOwned::Owned(Value::nothing()),
|
Value::List(_) => MaybeOwned::Owned(Value::nothing()),
|
||||||
|
Value::Operation(_) => MaybeOwned::Owned(Value::nothing()),
|
||||||
Value::Error(_) => MaybeOwned::Owned(Value::nothing()),
|
Value::Error(_) => MaybeOwned::Owned(Value::nothing()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -102,6 +141,7 @@ impl Value {
|
|||||||
let list = l.iter().map(|i| i.copy()).collect();
|
let list = l.iter().map(|i| i.copy()).collect();
|
||||||
Value::List(list)
|
Value::List(list)
|
||||||
}
|
}
|
||||||
|
Value::Operation(o) => Value::Operation(o.clone()),
|
||||||
Value::Error(e) => Value::Error(Box::new(e.copy_error())),
|
Value::Error(e) => Value::Error(Box::new(e.copy_error())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -111,6 +151,7 @@ impl Value {
|
|||||||
Value::Primitive(p) => p.format(field_name),
|
Value::Primitive(p) => p.format(field_name),
|
||||||
Value::Object(_) => format!("[object Object]"),
|
Value::Object(_) => format!("[object Object]"),
|
||||||
Value::List(_) => format!("[list List]"),
|
Value::List(_) => format!("[list List]"),
|
||||||
|
Value::Operation(_) => format!("[operation Operation]"),
|
||||||
Value::Error(e) => format!("{}", e),
|
Value::Error(e) => format!("{}", e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -127,6 +168,18 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
crate fn as_operation(&self) -> Result<Operation, ShellError> {
|
||||||
|
match self {
|
||||||
|
Value::Operation(o) => Ok(*o.clone()),
|
||||||
|
|
||||||
|
// TODO: this should definitely be more general with better errors
|
||||||
|
other => Err(ShellError::string(format!(
|
||||||
|
"Expected operation, got {:?}",
|
||||||
|
other
|
||||||
|
))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
crate fn as_int(&self) -> Result<i64, ShellError> {
|
crate fn as_int(&self) -> Result<i64, ShellError> {
|
||||||
match self {
|
match self {
|
||||||
Value::Primitive(Primitive::Int(i)) => Ok(*i),
|
Value::Primitive(Primitive::Int(i)) => Ok(*i),
|
||||||
|
@ -79,6 +79,16 @@ impl DescriptorName {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Clone for DataDescriptor {
|
||||||
|
fn clone(&self) -> DataDescriptor {
|
||||||
|
DataDescriptor {
|
||||||
|
name: self.name.clone(),
|
||||||
|
readonly: self.readonly,
|
||||||
|
ty: self.ty.copy(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl DataDescriptor {
|
impl DataDescriptor {
|
||||||
crate fn value_of() -> DataDescriptor {
|
crate fn value_of() -> DataDescriptor {
|
||||||
DataDescriptor {
|
DataDescriptor {
|
||||||
|
@ -5,7 +5,7 @@ use crate::object::{Primitive, Value};
|
|||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use std::cmp::{Ordering, PartialOrd};
|
use std::cmp::{Ordering, PartialOrd};
|
||||||
|
|
||||||
#[derive(Debug, Default, Eq, PartialEq)]
|
#[derive(Debug, Default, Eq, PartialEq, Clone)]
|
||||||
pub struct Dictionary {
|
pub struct Dictionary {
|
||||||
entries: IndexMap<DataDescriptor, Value>,
|
entries: IndexMap<DataDescriptor, Value>,
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,18 @@
|
|||||||
crate mod completer;
|
crate mod completer;
|
||||||
crate mod parse;
|
crate mod parser;
|
||||||
|
crate mod registry;
|
||||||
|
crate mod tokens;
|
||||||
|
|
||||||
crate use self::parse::{shell_parser, Item};
|
crate use registry::{CommandConfig, CommandRegistry};
|
||||||
|
crate use tokens::{ParsedCommand, Pipeline};
|
||||||
|
|
||||||
|
use crate::errors::ShellError;
|
||||||
|
use parser::PipelineParser;
|
||||||
|
|
||||||
|
pub fn parse(input: &str, _registry: &dyn CommandRegistry) -> Result<Pipeline, ShellError> {
|
||||||
|
let parser = PipelineParser::new();
|
||||||
|
|
||||||
|
parser
|
||||||
|
.parse(input)
|
||||||
|
.map_err(|e| ShellError::string(format!("{:?}", e)))
|
||||||
|
}
|
||||||
|
@ -1,144 +0,0 @@
|
|||||||
use crate::prelude::*;
|
|
||||||
use nom::branch::alt;
|
|
||||||
use nom::bytes::complete::{escaped, is_a, is_not, tag};
|
|
||||||
use nom::character::complete::one_of;
|
|
||||||
use nom::multi::separated_list;
|
|
||||||
use nom::sequence::{preceded, terminated};
|
|
||||||
use nom::IResult;
|
|
||||||
use nom::{complete, named, ws};
|
|
||||||
use std::str::FromStr;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum Item {
|
|
||||||
Quoted(String),
|
|
||||||
Bare(String),
|
|
||||||
Int(i64),
|
|
||||||
Boolean(bool),
|
|
||||||
Operator(Operator),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
|
||||||
pub enum Operator {
|
|
||||||
Equal,
|
|
||||||
NotEqual,
|
|
||||||
LessThan,
|
|
||||||
GreaterThan,
|
|
||||||
LessThanOrEqual,
|
|
||||||
GreaterThanOrEqual,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Operator {
|
|
||||||
pub fn print(&self) -> String {
|
|
||||||
match *self {
|
|
||||||
Operator::Equal => "==".to_string(),
|
|
||||||
Operator::NotEqual => "!=".to_string(),
|
|
||||||
Operator::LessThan => "<".to_string(),
|
|
||||||
Operator::GreaterThan => ">".to_string(),
|
|
||||||
Operator::LessThanOrEqual => "<=".to_string(),
|
|
||||||
Operator::GreaterThanOrEqual => ">=".to_string(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromStr for Operator {
|
|
||||||
type Err = ();
|
|
||||||
fn from_str(input: &str) -> Result<Self, <Self as std::str::FromStr>::Err> {
|
|
||||||
match input {
|
|
||||||
"==" => Ok(Operator::Equal),
|
|
||||||
"!=" => Ok(Operator::NotEqual),
|
|
||||||
"<" => Ok(Operator::LessThan),
|
|
||||||
">" => Ok(Operator::GreaterThan),
|
|
||||||
"<=" => Ok(Operator::LessThanOrEqual),
|
|
||||||
">=" => Ok(Operator::GreaterThanOrEqual),
|
|
||||||
_ => Err(()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Item {
|
|
||||||
crate fn as_value(&self) -> Value {
|
|
||||||
match self {
|
|
||||||
Item::Quoted(s) => Value::Primitive(Primitive::String(s.clone())),
|
|
||||||
Item::Bare(s) => Value::Primitive(Primitive::String(s.clone())),
|
|
||||||
Item::Int(i) => Value::Primitive(Primitive::Int(*i)),
|
|
||||||
Item::Boolean(b) => Value::Primitive(Primitive::Boolean(*b)),
|
|
||||||
Item::Operator(o) => Value::Primitive(Primitive::Operator(o.clone())),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn print(&self) -> String {
|
|
||||||
match self {
|
|
||||||
Item::Bare(s) => format!("{}", s),
|
|
||||||
Item::Quoted(s) => format!("{}", s),
|
|
||||||
Item::Int(i) => format!("{:?}", i),
|
|
||||||
Item::Boolean(b) => format!("{:?}", b),
|
|
||||||
Item::Operator(o) => o.print(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Item {
|
|
||||||
crate fn name(&self) -> Result<&str, ShellError> {
|
|
||||||
match self {
|
|
||||||
Item::Quoted(s) => Ok(s),
|
|
||||||
Item::Bare(s) => Ok(s),
|
|
||||||
Item::Boolean(i) => Err(ShellError::string(format!("{} is not a valid command", i))),
|
|
||||||
Item::Int(i) => Err(ShellError::string(format!("{} is not a valid command", i))),
|
|
||||||
Item::Operator(x) => Err(ShellError::string(format!(
|
|
||||||
"{:?} is not a valid command",
|
|
||||||
x
|
|
||||||
))),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn esc(s: &str) -> IResult<&str, &str> {
|
|
||||||
escaped(is_not("\\\""), '\\', one_of("\"n\\"))(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn quoted(s: &str) -> IResult<&str, Item> {
|
|
||||||
terminated(preceded(tag("\""), esc), tag("\""))(s)
|
|
||||||
.map(|(a, b)| (a, Item::Quoted(b.to_string())))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn unquoted(s: &str) -> IResult<&str, Item> {
|
|
||||||
is_not(" |")(s).map(|(a, b)| (a, Item::Bare(b.to_string())))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn operator(s: &str) -> IResult<&str, Item> {
|
|
||||||
alt((
|
|
||||||
tag("=="),
|
|
||||||
tag("!="),
|
|
||||||
tag("<"),
|
|
||||||
tag(">"),
|
|
||||||
tag("<="),
|
|
||||||
tag(">="),
|
|
||||||
))(s)
|
|
||||||
.map(|(a, b)| (a, Item::Operator(FromStr::from_str(b).unwrap())))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn int(s: &str) -> IResult<&str, Item> {
|
|
||||||
is_a("1234567890")(s).map(|(a, b)| (a, Item::Int(FromStr::from_str(b).unwrap())))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn boolean(s: &str) -> IResult<&str, Item> {
|
|
||||||
alt((tag("true"), tag("false")))(s)
|
|
||||||
.map(|(a, b)| (a, Item::Boolean(FromStr::from_str(b).unwrap())))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn command_token(s: &str) -> IResult<&str, Item> {
|
|
||||||
alt((boolean, int, operator, quoted, unquoted))(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn command_args(s: &str) -> IResult<&str, Vec<Item>> {
|
|
||||||
separated_list(tag(" "), command_token)(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
named!(
|
|
||||||
pub shell_parser(&str) -> Vec<Vec<Item>>,
|
|
||||||
complete!(
|
|
||||||
ws!(
|
|
||||||
separated_list!(tag("|"), command_args)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
56
src/parser/parser.lalrpop
Normal file
56
src/parser/parser.lalrpop
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
use std::str::FromStr;
|
||||||
|
use crate::parser::tokens::*;
|
||||||
|
|
||||||
|
grammar;
|
||||||
|
|
||||||
|
pub Pipeline: Pipeline = {
|
||||||
|
<first:Command> => Pipeline::new(vec![first]),
|
||||||
|
<first:Command> <rest: ( "|" <Command> )+> => Pipeline::from_parts(first, rest),
|
||||||
|
}
|
||||||
|
|
||||||
|
Command: ParsedCommand = {
|
||||||
|
<command:RawBareWord> <expr:Expr*> => ParsedCommand::new(command, expr)
|
||||||
|
}
|
||||||
|
|
||||||
|
Expr: Expression = {
|
||||||
|
<Leaf> => Expression::Leaf(<>),
|
||||||
|
<Binary> => Expression::Binary(<>),
|
||||||
|
}
|
||||||
|
|
||||||
|
Operator: Operator = {
|
||||||
|
"==" => Operator::Equal,
|
||||||
|
"!=" => Operator::NotEqual,
|
||||||
|
"<" => Operator::LessThan,
|
||||||
|
">" => Operator::GreaterThan,
|
||||||
|
"<=" => Operator::LessThanOrEqual,
|
||||||
|
">=" => Operator::GreaterThanOrEqual
|
||||||
|
}
|
||||||
|
|
||||||
|
Binary: Binary = {
|
||||||
|
<left:Leaf> <op:Operator> <right:Leaf> => Binary::new(left, op, right),
|
||||||
|
}
|
||||||
|
|
||||||
|
Flag: Flag = {
|
||||||
|
"-" <RawBareWord> => Flag::Shorthand(<>.to_string()),
|
||||||
|
"--" <RawBareWord> => Flag::Longhand(<>.to_string()),
|
||||||
|
}
|
||||||
|
|
||||||
|
String: String = {
|
||||||
|
SQString,
|
||||||
|
DQString,
|
||||||
|
}
|
||||||
|
|
||||||
|
Leaf: Leaf = {
|
||||||
|
<String> => Leaf::String(<>),
|
||||||
|
<Num> => Leaf::Int(<>),
|
||||||
|
<RawBareWord> => match <>.as_ref() {
|
||||||
|
"true" => Leaf::Boolean(true),
|
||||||
|
"false" => Leaf::Boolean(false),
|
||||||
|
_ => Leaf::Bare(<>),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RawBareWord: String = <s:r#"[^0-9"'\-][^\s]*"#> => <>.to_string();
|
||||||
|
DQString: String = <s:r#""([^"]|\\")*""#> => s[1..s.len() - 1].to_string();
|
||||||
|
SQString: String = <s:r#"'([^']|\\')*'"#> => s[1..s.len() - 1].to_string();
|
||||||
|
Num: i64 = <s:r"-?[0-9]+"> => i64::from_str(s).unwrap();
|
2109
src/parser/parser.rs
Normal file
2109
src/parser/parser.rs
Normal file
File diff suppressed because it is too large
Load Diff
21
src/parser/registry.rs
Normal file
21
src/parser/registry.rs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
use indexmap::IndexMap;
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
|
pub enum CommandType {
|
||||||
|
Switch,
|
||||||
|
Single,
|
||||||
|
Array,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
|
pub struct CommandConfig {
|
||||||
|
crate name: String,
|
||||||
|
crate mandatory_positional: Vec<String>,
|
||||||
|
crate optional_positional: Vec<String>,
|
||||||
|
crate rest_positional: bool,
|
||||||
|
crate named: IndexMap<String, CommandType>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait CommandRegistry {
|
||||||
|
fn get(&self, name: &str) -> CommandConfig;
|
||||||
|
}
|
128
src/parser/tokens.rs
Normal file
128
src/parser/tokens.rs
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
use derive_new::new;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
pub enum Operator {
|
||||||
|
Equal,
|
||||||
|
NotEqual,
|
||||||
|
LessThan,
|
||||||
|
GreaterThan,
|
||||||
|
LessThanOrEqual,
|
||||||
|
GreaterThanOrEqual,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Operator {
|
||||||
|
pub fn print(&self) -> String {
|
||||||
|
match *self {
|
||||||
|
Operator::Equal => "==".to_string(),
|
||||||
|
Operator::NotEqual => "!=".to_string(),
|
||||||
|
Operator::LessThan => "<".to_string(),
|
||||||
|
Operator::GreaterThan => ">".to_string(),
|
||||||
|
Operator::LessThanOrEqual => "<=".to_string(),
|
||||||
|
Operator::GreaterThanOrEqual => ">=".to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for Operator {
|
||||||
|
type Err = ();
|
||||||
|
fn from_str(input: &str) -> Result<Self, <Self as std::str::FromStr>::Err> {
|
||||||
|
match input {
|
||||||
|
"==" => Ok(Operator::Equal),
|
||||||
|
"!=" => Ok(Operator::NotEqual),
|
||||||
|
"<" => Ok(Operator::LessThan),
|
||||||
|
">" => Ok(Operator::GreaterThan),
|
||||||
|
"<=" => Ok(Operator::LessThanOrEqual),
|
||||||
|
">=" => Ok(Operator::GreaterThanOrEqual),
|
||||||
|
_ => Err(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum Expression {
|
||||||
|
Leaf(Leaf),
|
||||||
|
Binary(Binary),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Expression {
|
||||||
|
crate fn print(&self) -> String {
|
||||||
|
match self {
|
||||||
|
Expression::Leaf(l) => l.print(),
|
||||||
|
Expression::Binary(b) => b.print(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum Leaf {
|
||||||
|
String(String),
|
||||||
|
Bare(String),
|
||||||
|
Boolean(bool),
|
||||||
|
Int(i64),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Leaf {
|
||||||
|
fn print(&self) -> String {
|
||||||
|
match self {
|
||||||
|
Leaf::String(s) => format!("{:?}", s),
|
||||||
|
Leaf::Bare(s) => format!("{}", s),
|
||||||
|
Leaf::Boolean(b) => format!("{}", b),
|
||||||
|
Leaf::Int(i) => format!("{}", i),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, new)]
|
||||||
|
pub struct Binary {
|
||||||
|
crate left: Leaf,
|
||||||
|
crate operator: Operator,
|
||||||
|
crate right: Leaf,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Binary {
|
||||||
|
fn print(&self) -> String {
|
||||||
|
format!(
|
||||||
|
"{} {} {}",
|
||||||
|
self.left.print(),
|
||||||
|
self.operator.print(),
|
||||||
|
self.right.print()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum Flag {
|
||||||
|
Shorthand(String),
|
||||||
|
Longhand(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Flag {
|
||||||
|
#[allow(unused)]
|
||||||
|
fn print(&self) -> String {
|
||||||
|
match self {
|
||||||
|
Flag::Shorthand(s) => format!("-{}", s),
|
||||||
|
Flag::Longhand(s) => format!("--{}", s),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(new, Debug, Clone)]
|
||||||
|
pub struct ParsedCommand {
|
||||||
|
crate name: String,
|
||||||
|
crate args: Vec<Expression>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(new, Debug)]
|
||||||
|
pub struct Pipeline {
|
||||||
|
crate commands: Vec<ParsedCommand>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Pipeline {
|
||||||
|
crate fn from_parts(command: ParsedCommand, rest: Vec<ParsedCommand>) -> Pipeline {
|
||||||
|
let mut commands = vec![command];
|
||||||
|
commands.extend(rest);
|
||||||
|
|
||||||
|
Pipeline { commands }
|
||||||
|
}
|
||||||
|
}
|
@ -4,7 +4,7 @@ crate use crate::context::Context;
|
|||||||
crate use crate::env::host::handle_unexpected;
|
crate use crate::env::host::handle_unexpected;
|
||||||
crate use crate::env::{Environment, Host};
|
crate use crate::env::{Environment, Host};
|
||||||
crate use crate::errors::ShellError;
|
crate use crate::errors::ShellError;
|
||||||
crate use crate::object::{Primitive, Value};
|
crate use crate::object::Value;
|
||||||
crate use crate::stream::{single_output, InputStream, OutputStream};
|
crate use crate::stream::{single_output, InputStream, OutputStream};
|
||||||
crate use futures::{FutureExt, SinkExt, StreamExt};
|
crate use futures::{FutureExt, SinkExt, StreamExt};
|
||||||
crate use std::collections::VecDeque;
|
crate use std::collections::VecDeque;
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
|
use crate::prelude::*;
|
||||||
|
use derive_new::new;
|
||||||
use rustyline::completion::Completer;
|
use rustyline::completion::Completer;
|
||||||
use rustyline::completion::{self, FilenameCompleter};
|
use rustyline::completion::{self, FilenameCompleter};
|
||||||
use rustyline::line_buffer::LineBuffer;
|
use rustyline::line_buffer::LineBuffer;
|
||||||
|
|
||||||
|
#[derive(new)]
|
||||||
crate struct NuCompleter {
|
crate struct NuCompleter {
|
||||||
pub file_completer: FilenameCompleter,
|
pub file_completer: FilenameCompleter,
|
||||||
|
pub commands: indexmap::IndexMap<String, Arc<dyn Command>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Completer for NuCompleter {
|
impl Completer for NuCompleter {
|
||||||
@ -15,10 +19,7 @@ impl Completer for NuCompleter {
|
|||||||
pos: usize,
|
pos: usize,
|
||||||
context: &rustyline::Context,
|
context: &rustyline::Context,
|
||||||
) -> rustyline::Result<(usize, Vec<completion::Pair>)> {
|
) -> rustyline::Result<(usize, Vec<completion::Pair>)> {
|
||||||
let commands = [
|
let commands: Vec<String> = self.commands.keys().cloned().collect();
|
||||||
"ps", "ls", "cd", "view", "skip", "take", "select", "reject", "to-array", "where",
|
|
||||||
"sort-by",
|
|
||||||
];
|
|
||||||
|
|
||||||
let mut completions = self.file_completer.complete(line, pos, context)?.1;
|
let mut completions = self.file_completer.complete(line, pos, context)?.1;
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use crate::shell::completer::NuCompleter;
|
use crate::shell::completer::NuCompleter;
|
||||||
|
|
||||||
|
use crate::prelude::*;
|
||||||
use rustyline::completion::{self, Completer, FilenameCompleter};
|
use rustyline::completion::{self, Completer, FilenameCompleter};
|
||||||
use rustyline::error::ReadlineError;
|
use rustyline::error::ReadlineError;
|
||||||
use rustyline::highlight::{Highlighter, MatchingBracketHighlighter};
|
use rustyline::highlight::{Highlighter, MatchingBracketHighlighter};
|
||||||
@ -13,10 +14,11 @@ crate struct Helper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Helper {
|
impl Helper {
|
||||||
crate fn new() -> Helper {
|
crate fn new(commands: indexmap::IndexMap<String, Arc<dyn Command>>) -> Helper {
|
||||||
Helper {
|
Helper {
|
||||||
completer: NuCompleter {
|
completer: NuCompleter {
|
||||||
file_completer: FilenameCompleter::new(),
|
file_completer: FilenameCompleter::new(),
|
||||||
|
commands,
|
||||||
},
|
},
|
||||||
highlighter: MatchingBracketHighlighter::new(),
|
highlighter: MatchingBracketHighlighter::new(),
|
||||||
hinter: HistoryHinter {},
|
hinter: HistoryHinter {},
|
||||||
|
Loading…
Reference in New Issue
Block a user