Restructuring

This commit is contained in:
Yehuda Katz 2019-08-02 12:15:07 -07:00
parent 73deeb69db
commit fc173c46d8
54 changed files with 1498 additions and 879 deletions

171
Cargo.lock generated
View File

@ -9,7 +9,7 @@ dependencies = [
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.37 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -77,6 +77,16 @@ dependencies = [
"nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "async-trait"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "atty"
version = "0.2.11"
@ -570,7 +580,7 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.37 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -609,7 +619,7 @@ dependencies = [
"ident_case 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.37 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -622,7 +632,7 @@ dependencies = [
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
"strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.37 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -632,7 +642,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"darling_core 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.37 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -642,7 +652,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"darling_core 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.37 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -661,7 +671,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.37 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -673,7 +683,7 @@ dependencies = [
"derive_builder_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.37 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -684,7 +694,7 @@ dependencies = [
"darling 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.37 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -697,7 +707,7 @@ dependencies = [
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.37 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -844,7 +854,7 @@ dependencies = [
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive_internals 0.24.1 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.37 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -898,7 +908,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.37 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)",
"synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -961,16 +971,37 @@ version = "0.1.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "futures-channel-preview"
version = "0.3.0-alpha.16"
name = "futures-async-stream"
version = "0.1.0-alpha.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"futures-core-preview 0.3.0-alpha.16 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-async-stream-macro 0.1.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-core-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)",
"pin-project 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "futures-async-stream-macro"
version = "0.1.0-alpha.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "futures-channel-preview"
version = "0.3.0-alpha.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"futures-core-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-sink-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "futures-core-preview"
version = "0.3.0-alpha.16"
version = "0.3.0-alpha.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@ -984,56 +1015,51 @@ dependencies = [
[[package]]
name = "futures-executor-preview"
version = "0.3.0-alpha.16"
version = "0.3.0-alpha.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"futures-channel-preview 0.3.0-alpha.16 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-core-preview 0.3.0-alpha.16 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-util-preview 0.3.0-alpha.16 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-channel-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-core-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-util-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
"pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "futures-io-preview"
version = "0.3.0-alpha.16"
version = "0.3.0-alpha.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"futures-core-preview 0.3.0-alpha.16 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "futures-preview"
version = "0.3.0-alpha.16"
version = "0.3.0-alpha.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"futures-channel-preview 0.3.0-alpha.16 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-core-preview 0.3.0-alpha.16 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-executor-preview 0.3.0-alpha.16 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-io-preview 0.3.0-alpha.16 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-sink-preview 0.3.0-alpha.16 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-util-preview 0.3.0-alpha.16 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-channel-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-core-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-executor-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-io-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-sink-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-util-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "futures-sink-preview"
version = "0.3.0-alpha.16"
version = "0.3.0-alpha.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"futures-channel-preview 0.3.0-alpha.16 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-core-preview 0.3.0-alpha.16 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-core-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "futures-util-preview"
version = "0.3.0-alpha.16"
version = "0.3.0-alpha.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-channel-preview 0.3.0-alpha.16 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-core-preview 0.3.0-alpha.16 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-io-preview 0.3.0-alpha.16 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-sink-preview 0.3.0-alpha.16 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-channel-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-core-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-io-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-sink-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1042,11 +1068,11 @@ dependencies = [
[[package]]
name = "futures_codec"
version = "0.2.2"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-preview 0.3.0-alpha.16 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -1065,7 +1091,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.37 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -1445,7 +1471,7 @@ dependencies = [
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.37 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)",
"utf8-ranges 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -1648,6 +1674,7 @@ dependencies = [
"adhoc_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ansi_term 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
"app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"async-trait 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"byte-unit 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
"chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1664,9 +1691,10 @@ dependencies = [
"dunce 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"enum-utils 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"enum_derive 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-preview 0.3.0-alpha.16 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-sink-preview 0.3.0-alpha.16 (registry+https://github.com/rust-lang/crates.io-index)",
"futures_codec 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-async-stream 0.1.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-sink-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)",
"futures_codec 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
"getset 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
"git2 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
"image 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1697,7 +1725,6 @@ dependencies = [
"serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)",
"serde-hjson 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_bytes 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_ini 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1721,7 +1748,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.37 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -2000,6 +2027,16 @@ dependencies = [
"unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "pin-project"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "pin-utils"
version = "0.1.0-alpha.4"
@ -2636,7 +2673,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.37 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -2645,7 +2682,7 @@ version = "0.24.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.37 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -2781,7 +2818,7 @@ dependencies = [
[[package]]
name = "syn"
version = "0.15.37"
version = "0.15.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2796,7 +2833,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.37 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -3115,7 +3152,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"darling 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.37 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -3287,7 +3324,7 @@ dependencies = [
"log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.37 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)",
"wasm-bindgen-shared 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -3307,7 +3344,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.37 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)",
"wasm-bindgen-backend 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)",
"wasm-bindgen-shared 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -3431,6 +3468,7 @@ dependencies = [
"checksum app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e73a24bad9bd6a94d6395382a6c69fe071708ae4409f763c5475e14ee896313d"
"checksum argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392"
"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71"
"checksum async-trait 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "41f6b40ac5df0ab7ef35112d7a593428ca62bcaabcc7de20f88b506cf798928d"
"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652"
"checksum autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0e49efa51329a5fd37e7c79db4621af617cd4e3e5bc224939808d076077077bf"
"checksum backtrace 0.3.30 (registry+https://github.com/rust-lang/crates.io-index)" = "ada4c783bb7e7443c14e0480f429ae2cc99da95065aeab7ee1b81ada0419404f"
@ -3532,15 +3570,17 @@ dependencies = [
"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
"checksum futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)" = "a2037ec1c6c1c4f79557762eab1f7eae1f64f6cb418ace90fae88f0942b60139"
"checksum futures-channel-preview 0.3.0-alpha.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4cd523712fc272e9b714669165a2832debee5a5b7e409bfccdc7c0d5cd0cf07a"
"checksum futures-core-preview 0.3.0-alpha.16 (registry+https://github.com/rust-lang/crates.io-index)" = "719770f328642b657b849856bb5a607db9538dd5bb3000122e5ead55d0a58c36"
"checksum futures-async-stream 0.1.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c4aecac975d38ff13b935de313e12fded407231b0d563e7493fac40463272a2f"
"checksum futures-async-stream-macro 0.1.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4bbd6c677284a4bb3c043193ad20017f06c61cca34327ce5b0682691f92a182e"
"checksum futures-channel-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)" = "21c71ed547606de08e9ae744bb3c6d80f5627527ef31ecf2a7210d0e67bc8fae"
"checksum futures-core-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)" = "4b141ccf9b7601ef987f36f1c0d9522f76df3bba1cf2e63bfacccc044c4558f5"
"checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4"
"checksum futures-executor-preview 0.3.0-alpha.16 (registry+https://github.com/rust-lang/crates.io-index)" = "315dc58c908535d059576a329b86cd185933433382cfcd394fb2fa353330de03"
"checksum futures-io-preview 0.3.0-alpha.16 (registry+https://github.com/rust-lang/crates.io-index)" = "cca0bf7a1f39c9d32b797b0def93d5932aa71796236aad6b549bac6f7df159a3"
"checksum futures-preview 0.3.0-alpha.16 (registry+https://github.com/rust-lang/crates.io-index)" = "fcfeac5f016a4b5835bb93eb7961f50a64f0e001207562703d9ddf4109d7b263"
"checksum futures-sink-preview 0.3.0-alpha.16 (registry+https://github.com/rust-lang/crates.io-index)" = "49dcfdacd6b5974ca0b9b78bc38ffd1071da0206179735c3df82e279f5b784e4"
"checksum futures-util-preview 0.3.0-alpha.16 (registry+https://github.com/rust-lang/crates.io-index)" = "f7a0451b9c5047c2b9ab93425ffd0793165511e93c04b977cd45fbd41c6e34b2"
"checksum futures_codec 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b60f48aa03e365df015d2fbf0b79f17b440350c268a5e20305da17b394adcc1e"
"checksum futures-executor-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)" = "87ba260fe51080ba37f063ad5b0732c4ff1f737ea18dcb67833d282cdc2c6f14"
"checksum futures-io-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)" = "082e402605fcb8b1ae1e5ba7d7fdfd3e31ef510e2a8367dd92927bb41ae41b3a"
"checksum futures-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)" = "bf25f91c8a9a1f64c451e91b43ba269ed359b9f52d35ed4b3ce3f9c842435867"
"checksum futures-sink-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)" = "4309a25a1069a1f3c10647b227b9afe6722b67a030d3f00a9cbdc171fc038de4"
"checksum futures-util-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)" = "af8198c48b222f02326940ce2b3aa9e6e91a32886eeaad7ca3b8e4c70daa3f4e"
"checksum futures_codec 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "36552cd31353fd135114510d53b8d120758120c36aa636a9341970f9efb1e4a0"
"checksum getrandom 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e65cce4e5084b14874c4e7097f38cab54f47ee554f9194673456ea379dcc4c55"
"checksum getset 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "19fbde0fad0c1c1f9474694b1f5c9ba22b09f2f74f74e6d2bd19c43f6656e2cb"
"checksum gif 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "86c2f2b597d6e05c86ee5947b2223bda468fe8dad3e88e2a6520869322aaf568"
@ -3634,6 +3674,7 @@ dependencies = [
"checksum phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b03e85129e324ad4166b06b2c7491ae27fe3ec353af72e72cd1654c7225d517e"
"checksum phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662"
"checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0"
"checksum pin-project 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "2714268752963de91be73ea2689c3c63d2389b14fad04d033923e20cb3a1d99a"
"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 plist 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5f2a9f075f6394100e7c105ed1af73fb1859d6fd14e49d4290d578120beb167f"
@ -3723,7 +3764,7 @@ dependencies = [
"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
"checksum subprocess 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "28fc0f40f0c0da73339d347aa7d6d2b90341a95683a47722bc4eebed71ff3c00"
"checksum syn 0.15.37 (registry+https://github.com/rust-lang/crates.io-index)" = "e11410033fd5cf69a1cf2084604e011190c56f11e08ffc53df880f5f65f1c6e4"
"checksum syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)" = "eadc09306ca51a40555dd6fc2b415538e9e18bc9f870e47b1a524a79fe2dcf5e"
"checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f"
"checksum syntect 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e80b8831c5a543192ffc3727f01cf0e57579c6ac15558e3048bfb5708892167b"
"checksum sys-info 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)" = "76d6cf7b349b6a6daaf7a3797227e2f4108c8dd398e0aca7e29b9fb239948541"

View File

@ -28,18 +28,19 @@ chrono-humanize = "0.0.11"
byte-unit = "2.1.0"
ordered-float = {version = "1.0.2", features = ["serde"]}
prettyprint = "0.7.0"
futures-preview = { version = "=0.3.0-alpha.16", features = ["compat", "io-compat"] }
futures-sink-preview = "=0.3.0-alpha.16"
futures_codec = "0.2.2"
futures-preview = { version = "=0.3.0-alpha.17", features = ["compat", "io-compat"] }
futures-sink-preview = "=0.3.0-alpha.17"
futures-async-stream = "0.1.0-alpha.1"
async-trait = ""
futures_codec = "0.2.5"
term = "0.5.2"
bytes = "0.4.12"
log = "0.4.7"
pretty_env_logger = "0.3.0"
serde = "1.0.94"
serde = { version = "1.0.94", features = ["derive"] }
serde_json = "1.0.40"
serde-hjson = "0.9.0"
serde_yaml = "0.8"
serde_derive = "1.0.94"
serde_bytes = "0.11.1"
getset = "0.0.7"
logos = "0.10.0-rc2"

View File

@ -1,18 +1,17 @@
use crate::commands::autoview;
use crate::commands::classified::SinkCommand;
use crate::commands::classified::{
ClassifiedCommand, ClassifiedInputStream, ClassifiedPipeline, ExternalCommand, InternalCommand,
StreamNext,
};
use crate::commands::command::sink;
use crate::commands::plugin::JsonRpc;
use crate::commands::plugin::{PluginCommand, PluginSink};
use crate::commands::plugin::PluginCommand;
use crate::commands::{static_command, Command};
use crate::context::Context;
crate use crate::errors::ShellError;
use crate::git::current_branch;
use crate::object::Value;
use crate::parser::parse::span::Spanned;
use crate::parser::registry::CommandConfig;
use crate::parser::registry::Signature;
use crate::parser::{hir, Pipeline, PipelineElement, TokenNode};
use crate::prelude::*;
@ -61,8 +60,7 @@ fn load_plugin(path: &std::path::Path, context: &mut Context) -> Result<(), Shel
let mut input = String::new();
match reader.read_line(&mut input) {
Ok(_) => {
let response =
serde_json::from_str::<JsonRpc<Result<CommandConfig, ShellError>>>(&input);
let response = serde_json::from_str::<JsonRpc<Result<Signature, ShellError>>>(&input);
match response {
Ok(jrpc) => match jrpc.params {
Ok(params) => {
@ -70,15 +68,10 @@ fn load_plugin(path: &std::path::Path, context: &mut Context) -> Result<(), Shel
if params.is_filter {
let fname = fname.to_string();
let name = params.name.clone();
context.add_commands(vec![Arc::new(PluginCommand::new(
context.add_commands(vec![static_command(PluginCommand::new(
name, fname, params,
))]);
Ok(())
} else if params.is_sink {
let fname = fname.to_string();
let name = params.name.clone();
context.add_sinks(vec![Arc::new(PluginSink::new(name, fname, params))]);
Ok(())
} else {
Ok(())
}
@ -158,10 +151,8 @@ pub async fn cli() -> Result<(), Box<dyn Error>> {
command("ps", Box::new(ps::ps)),
command("ls", Box::new(ls::ls)),
command("sysinfo", Box::new(sysinfo::sysinfo)),
command("cd", Box::new(cd::cd)),
command("size", Box::new(size::size)),
command("from-yaml", Box::new(from_yaml::from_yaml)),
command("get", Box::new(get::get)),
command("exit", Box::new(exit::exit)),
command("lines", Box::new(lines::lines)),
command("split-column", Box::new(split_column::split_column)),
@ -175,19 +166,18 @@ pub async fn cli() -> Result<(), Box<dyn Error>> {
command("to-toml", Box::new(to_toml::to_toml)),
command("to-yaml", Box::new(to_yaml::to_yaml)),
command("sort-by", Box::new(sort_by::sort_by)),
Arc::new(Remove),
Arc::new(Open),
Arc::new(Where),
Arc::new(Config),
Arc::new(SkipWhile),
]);
context.add_sinks(vec![
sink("autoview", Box::new(autoview::autoview)),
sink("clip", Box::new(clip::clip)),
sink("save", Box::new(save::save)),
sink("table", Box::new(table::table)),
sink("vtable", Box::new(vtable::vtable)),
static_command(Get),
static_command(Cd),
static_command(Remove),
static_command(Open),
static_command(Where),
static_command(Config),
static_command(SkipWhile),
static_command(Clip),
static_command(Autoview),
// command("save", Box::new(save::save)),
// command("table", Box::new(table::table)),
// command("vtable", Box::new(vtable::vtable)),
]);
}
let _ = load_plugins(&mut context);
@ -341,17 +331,19 @@ async fn process_line(readline: Result<String, ReadlineError>, ctx: &mut Context
.map_err(|err| (line.clone(), err))?;
match pipeline.commands.last() {
Some(ClassifiedCommand::Sink(_)) => {}
Some(ClassifiedCommand::External(_)) => {}
_ => pipeline.commands.push(ClassifiedCommand::Sink(SinkCommand {
command: sink("autoview", Box::new(autoview::autoview)),
name_span: None,
args: hir::Call::new(
Box::new(hir::Expression::synthetic_string("autoview")),
None,
None,
),
})),
_ => pipeline
.commands
.push(ClassifiedCommand::Internal(InternalCommand {
command: static_command(autoview::Autoview),
name_span: None,
source_map: ctx.source_map,
args: hir::Call::new(
Box::new(hir::Expression::synthetic_string("autoview")),
None,
None,
),
})),
}
let mut input = ClassifiedInputStream::new();
@ -379,18 +371,6 @@ async fn process_line(readline: Result<String, ReadlineError>, ctx: &mut Context
)
}
(Some(ClassifiedCommand::Sink(SinkCommand { name_span, .. })), Some(_)) => {
return LineResult::Error(line.clone(), ShellError::maybe_labeled_error("Commands like table, save, and autoview must come last in the pipeline", "must come last", name_span));
}
(Some(ClassifiedCommand::Sink(left)), None) => {
let input_vec: Vec<Spanned<Value>> = input.objects.into_vec().await;
if let Err(err) = left.run(ctx, input_vec, &Text::from(line)) {
return LineResult::Error(line.clone(), err);
}
break;
}
(
Some(ClassifiedCommand::Internal(left)),
Some(ClassifiedCommand::External(_)),
@ -485,7 +465,7 @@ fn classify_command(
match context.has_command(name) {
true => {
let command = context.get_command(name);
let config = command.config();
let config = command.signature();
trace!(target: "nu::build_pipeline", "classifying {:?}", config);
@ -498,20 +478,8 @@ fn classify_command(
args,
}))
}
false => match context.has_sink(name) {
true => {
let command = context.get_sink(name);
let config = command.config();
let args = config.parse_args(call, context.registry(), source)?;
Ok(ClassifiedCommand::Sink(SinkCommand {
command,
name_span: Some(head.span().clone()),
args,
}))
}
false => {
false => match context.get_command(name).as_ref() {
Command::Static(command) => {
let arg_list_strings: Vec<Spanned<String>> = match call.children() {
//Some(args) => args.iter().map(|i| i.as_external_arg(source)).collect(),
Some(args) => args

View File

@ -42,8 +42,15 @@ crate mod trim;
crate mod vtable;
crate mod where_;
crate use command::{command, EvaluatedStaticCommandArgs};
crate use autoview::Autoview;
crate use cd::Cd;
crate use clip::Clip;
crate use command::{
command, static_command, CallInfo, Command, CommandArgs, EvaluatedStaticCommandArgs,
StaticCommand, UnevaluatedCallInfo,
};
crate use config::Config;
crate use get::Get;
crate use open::Open;
crate use rm::Remove;
crate use skip_while::SkipWhile;

View File

@ -1,11 +1,31 @@
use crate::commands::command::SinkCommandArgs;
use crate::commands::StaticCommand;
use crate::context::{SourceMap, SpanSource};
use crate::errors::ShellError;
use crate::format::GenericView;
use crate::prelude::*;
use std::path::Path;
pub fn autoview(args: SinkCommandArgs) -> Result<(), ShellError> {
pub struct Autoview;
impl StaticCommand for Autoview {
fn name(&self) -> &str {
"autoview"
}
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
args.process(registry, autoview)?.run()
}
fn signature(&self) -> Signature {
Signature::build("autoview").sink()
}
}
pub fn autoview(args: (), context: RunnableContext) -> Result<OutputStream, ShellError> {
if args.input.len() > 0 {
if let Spanned {
item: Value::Binary(_),
@ -27,7 +47,7 @@ pub fn autoview(args: SinkCommandArgs) -> Result<(), ShellError> {
}
}
Ok(())
Ok(OutputStream::empty())
}
fn equal_shapes(input: &Vec<Spanned<Value>>) -> bool {

View File

@ -1,27 +1,54 @@
use crate::commands::StaticCommand;
use crate::errors::ShellError;
use crate::prelude::*;
use std::env;
use std::path::PathBuf;
pub fn cd(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
let env = args.env.clone();
let env = env.lock().unwrap();
let args = args.evaluate_once(registry)?;
let cwd = env.path().to_path_buf();
pub struct Cd;
let path = match args.nth(0) {
#[derive(Deserialize)]
pub struct CdArgs {
target: Option<Spanned<PathBuf>>,
}
impl StaticCommand for Cd {
fn name(&self) -> &str {
"cd"
}
fn signature(&self) -> Signature {
Signature::build("cd")
.optional("target", SyntaxType::Path)
.filter()
}
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
args.process(registry, cd)?.run()
// cd(args, registry)
}
}
pub fn cd(CdArgs { target }: CdArgs, context: RunnableContext) -> Result<OutputStream, ShellError> {
let cwd = context.cwd().to_path_buf();
let path = match &target {
None => match dirs::home_dir() {
Some(o) => o,
_ => {
return Err(ShellError::maybe_labeled_error(
"Can not change to home directory",
"can not go to home",
args.name_span(),
context.name,
))
}
},
Some(v) => {
let target = v.as_string()?;
match dunce::canonicalize(cwd.join(target).as_path()) {
// let target = v.item.as_string()?;
match dunce::canonicalize(cwd.join(&v.item()).as_path()) {
Ok(p) => p,
Err(_) => {
return Err(ShellError::labeled_error(
@ -38,11 +65,11 @@ pub fn cd(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream,
match env::set_current_dir(&path) {
Ok(_) => {}
Err(_) => {
if args.len() > 0 {
if let Some(path) = target {
return Err(ShellError::labeled_error(
"Can not change to directory",
"directory not found",
args.nth(0).unwrap().span.clone(),
path.span,
));
} else {
return Err(ShellError::string("Can not change to directory"));

View File

@ -1,6 +1,5 @@
use crate::commands::command::Sink;
use crate::commands::Command;
use crate::context::SourceMap;
use crate::evaluate::Scope;
use crate::parser::{hir, Span, Spanned, TokenNode};
use crate::prelude::*;
use bytes::{BufMut, BytesMut};
@ -83,7 +82,6 @@ crate enum ClassifiedCommand {
#[allow(unused)]
Expr(TokenNode),
Internal(InternalCommand),
Sink(SinkCommand),
External(ExternalCommand),
}
@ -93,34 +91,13 @@ impl ClassifiedCommand {
match self {
ClassifiedCommand::Expr(token) => token.span(),
ClassifiedCommand::Internal(internal) => internal.name_span.into(),
ClassifiedCommand::Sink(sink) => sink.name_span.into(),
ClassifiedCommand::External(external) => external.name_span.into(),
}
}
}
crate struct SinkCommand {
crate command: Arc<dyn Sink>,
crate name_span: Option<Span>,
crate args: hir::Call,
}
impl SinkCommand {
crate fn run(
self,
context: &mut Context,
input: Vec<Spanned<Value>>,
source: &Text,
) -> Result<(), ShellError> {
let args = self
.args
.evaluate(context.registry(), &Scope::empty(), source)?;
context.run_sink(self.command, self.name_span.clone(), args, input)
}
}
crate struct InternalCommand {
crate command: Arc<dyn Command>,
crate command: Arc<Command>,
crate name_span: Option<Span>,
crate source_map: SourceMap,
crate args: hir::Call,
@ -142,14 +119,16 @@ impl InternalCommand {
let objects: InputStream =
trace_stream!(target: "nu::trace_stream::internal", "input" = input.objects);
let result = context.run_command(
self.command,
self.name_span.clone(),
self.source_map,
self.args,
source,
objects,
)?;
let result = context
.run_command(
self.command,
self.name_span.clone(),
self.source_map,
self.args,
source,
objects,
)
.await?;
let mut result = result.values;

View File

@ -1,25 +1,71 @@
use crate::commands::command::SinkCommandArgs;
use crate::commands::{CommandArgs, StaticCommand};
use crate::context::CommandRegistry;
use crate::errors::{labelled, ShellError};
use crate::prelude::*;
use clipboard::{ClipboardContext, ClipboardProvider};
use futures::stream::StreamExt;
use futures_async_stream::async_stream_block;
pub fn clip(args: SinkCommandArgs) -> Result<(), ShellError> {
pub struct Clip;
#[derive(Deserialize)]
pub struct ClipArgs {}
impl StaticCommand for Clip {
fn name(&self) -> &str {
"clip"
}
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
args.process(registry, clip)?.run()
}
fn signature(&self) -> Signature {
Signature::build("clip").sink()
}
}
pub fn clip(
ClipArgs {}: ClipArgs,
RunnableContext { input, name, .. }: RunnableContext,
) -> Result<OutputStream, ShellError> {
let stream = async_stream_block! {
let values: Vec<Spanned<Value>> = input.values.collect().await;
inner_clip(values, name);
};
let stream: BoxStream<'static, ReturnValue> = stream.boxed();
Ok(OutputStream::from(stream))
}
async fn inner_clip(input: Vec<Spanned<Value>>, name: Option<Span>) -> OutputStream {
let mut clip_context: ClipboardContext = ClipboardProvider::new().unwrap();
let mut new_copy_data = String::new();
if args.input.len() > 0 {
if input.len() > 0 {
let mut first = true;
for i in args.input.iter() {
for i in input.iter() {
if !first {
new_copy_data.push_str("\n");
} else {
first = false;
}
let string = i.as_string().map_err(labelled(
args.name_span(),
let s = i.as_string().map_err(labelled(
name,
"Given non-string data",
"expected strings from pipeline",
))?;
));
let string: String = match s {
Ok(string) => string,
Err(err) => return OutputStream::one(Err(err)),
};
new_copy_data.push_str(&string);
}
@ -27,5 +73,5 @@ pub fn clip(args: SinkCommandArgs) -> Result<(), ShellError> {
clip_context.set_contents(new_copy_data).unwrap();
Ok(())
OutputStream::empty()
}

View File

@ -3,8 +3,9 @@ use crate::errors::ShellError;
use crate::evaluate::Scope;
use crate::object::Value;
use crate::parser::hir;
use crate::parser::{registry, Span, Spanned};
use crate::parser::{registry, ConfigDeserializer, Span, Spanned};
use crate::prelude::*;
use derive_new::new;
use getset::Getters;
use serde::{Deserialize, Serialize};
use std::fmt;
@ -80,6 +81,67 @@ impl CommandArgs {
pub fn name_span(&self) -> Option<Span> {
self.call_info.name_span
}
pub fn process<'de, T: Deserialize<'de>>(
self,
registry: &CommandRegistry,
callback: fn(T, RunnableContext) -> Result<OutputStream, ShellError>,
) -> Result<RunnableArgs<T>, ShellError> {
let env = self.env.clone();
let args = self.evaluate_once(registry)?;
let (input, args) = args.split();
let name_span = args.call_info.name_span;
let mut deserializer = ConfigDeserializer::from_call_node(args);
Ok(RunnableArgs {
args: T::deserialize(&mut deserializer)?,
context: RunnableContext {
input: input,
env,
name: name_span,
},
callback,
})
}
}
pub struct SinkContext {
pub input: Vec<Spanned<Value>>,
pub env: Arc<Mutex<Environment>>,
pub name: Option<Span>,
}
pub struct SinkArgs<T> {
args: T,
context: SinkContext,
callback: fn(T, SinkContext) -> Result<(), ShellError>,
}
pub struct RunnableContext {
pub input: InputStream,
pub env: Arc<Mutex<Environment>>,
pub name: Option<Span>,
}
impl RunnableContext {
pub fn cwd(&self) -> PathBuf {
let env = self.env.clone();
let env = env.lock().unwrap();
env.path.clone()
}
}
pub struct RunnableArgs<T> {
args: T,
context: RunnableContext,
callback: fn(T, RunnableContext) -> Result<OutputStream, ShellError>,
}
impl<T> RunnableArgs<T> {
pub fn run(self) -> Result<OutputStream, ShellError> {
(self.callback)(self.args, self.context)
}
}
pub struct EvaluatedStaticCommandArgs {
@ -120,6 +182,12 @@ impl EvaluatedStaticCommandArgs {
(input, args.call_info.args)
}
pub fn split(self) -> (InputStream, EvaluatedCommandArgs) {
let EvaluatedStaticCommandArgs { args, input } = self;
(input, args)
}
}
#[derive(Getters)]
@ -155,7 +223,7 @@ impl EvaluatedFilterCommandArgs {
}
}
#[derive(Getters)]
#[derive(Getters, new)]
#[get = "crate"]
pub struct EvaluatedCommandArgs {
pub host: Arc<Mutex<dyn Host>>,
@ -184,24 +252,21 @@ impl EvaluatedCommandArgs {
self.call_info.args.get(name)
}
pub fn slice_from(&self, from: usize) -> Vec<Spanned<Value>> {
let positional = &self.call_info.args.positional;
match positional {
None => vec![],
Some(list) => list[from..].to_vec(),
}
}
#[allow(unused)]
pub fn has(&self, name: &str) -> bool {
self.call_info.args.has(name)
}
}
pub struct SinkCommandArgs {
pub ctx: Context,
pub call_info: CallInfo,
pub input: Vec<Spanned<Value>>,
}
impl SinkCommandArgs {
pub fn name_span(&self) -> Option<Span> {
self.call_info.name_span
}
}
#[derive(Debug, Serialize, Deserialize)]
pub enum CommandAction {
ChangePath(PathBuf),
@ -241,38 +306,56 @@ impl ReturnSuccess {
}
}
pub trait Command: Send + Sync {
pub trait StaticCommand: Send + Sync {
fn name(&self) -> &str;
fn run(
&self,
args: CommandArgs,
registry: &registry::CommandRegistry,
) -> Result<OutputStream, ShellError>;
fn name(&self) -> &str;
fn config(&self) -> registry::CommandConfig {
registry::CommandConfig {
fn signature(&self) -> Signature {
Signature {
name: self.name().to_string(),
positional: vec![],
rest_positional: true,
named: indexmap::IndexMap::new(),
is_filter: true,
is_sink: false,
}
}
}
pub trait Sink {
fn run(&self, args: SinkCommandArgs) -> Result<(), ShellError>;
fn name(&self) -> &str;
pub enum Command {
Static(Arc<dyn StaticCommand>),
}
fn config(&self) -> registry::CommandConfig {
registry::CommandConfig {
name: self.name().to_string(),
positional: vec![],
rest_positional: true,
named: indexmap::IndexMap::new(),
is_filter: false,
is_sink: true,
impl Command {
pub fn name(&self) -> &str {
match self {
Command::Static(command) => command.name(),
}
}
pub fn is_sink(&self) -> bool {
match self {
Command::Static(..) => false,
}
}
pub fn signature(&self) -> Signature {
match self {
Command::Static(command) => command.signature(),
}
}
pub async fn run(
&self,
args: CommandArgs,
registry: &registry::CommandRegistry,
) -> Result<OutputStream, ShellError> {
match self {
Command::Static(command) => command.run(args, registry),
}
}
}
@ -283,7 +366,7 @@ pub struct FnFilterCommand {
func: fn(EvaluatedFilterCommandArgs) -> Result<OutputStream, ShellError>,
}
impl Command for FnFilterCommand {
impl StaticCommand for FnFilterCommand {
fn name(&self) -> &str {
&self.name
}
@ -339,7 +422,11 @@ pub struct FnRawCommand {
>,
}
impl Command for FnRawCommand {
impl StaticCommand for FnRawCommand {
fn name(&self) -> &str {
&self.name
}
fn run(
&self,
args: CommandArgs,
@ -347,10 +434,6 @@ impl Command for FnRawCommand {
) -> Result<OutputStream, ShellError> {
(self.func)(args, registry)
}
fn name(&self) -> &str {
&self.name
}
}
pub fn command(
@ -360,45 +443,24 @@ pub fn command(
+ Send
+ Sync,
>,
) -> Arc<dyn Command> {
Arc::new(FnRawCommand {
) -> Arc<Command> {
Arc::new(Command::Static(Arc::new(FnRawCommand {
name: name.to_string(),
func,
})
})))
}
pub fn static_command(command: impl StaticCommand + 'static) -> Arc<Command> {
Arc::new(Command::Static(Arc::new(command)))
}
#[allow(unused)]
pub fn filter(
name: &str,
func: fn(EvaluatedFilterCommandArgs) -> Result<OutputStream, ShellError>,
) -> Arc<dyn Command> {
Arc::new(FnFilterCommand {
) -> Arc<Command> {
Arc::new(Command::Static(Arc::new(FnFilterCommand {
name: name.to_string(),
func,
})
}
pub struct FnSink {
name: String,
func: Box<dyn Fn(SinkCommandArgs) -> Result<(), ShellError>>,
}
impl Sink for FnSink {
fn run(&self, args: SinkCommandArgs) -> Result<(), ShellError> {
(self.func)(args)
}
fn name(&self) -> &str {
&self.name
}
}
pub fn sink(
name: &str,
func: Box<dyn Fn(SinkCommandArgs) -> Result<(), ShellError>>,
) -> Arc<dyn Sink> {
Arc::new(FnSink {
name: name.to_string(),
func,
})
})))
}

View File

@ -1,57 +1,61 @@
use crate::prelude::*;
use crate::commands::EvaluatedStaticCommandArgs;
use crate::commands::StaticCommand;
use crate::errors::ShellError;
use crate::object::{config, Value};
use crate::parser::hir::SyntaxType;
use crate::parser::registry::{self, CommandConfig, NamedType};
use indexmap::IndexMap;
use log::trace;
use crate::parser::registry::{self};
use std::iter::FromIterator;
pub struct Config;
impl Command for Config {
#[derive(Deserialize)]
pub struct ConfigArgs {
set: Option<(Spanned<String>, Spanned<Value>)>,
get: Option<Spanned<String>>,
clear: Spanned<bool>,
remove: Option<Spanned<String>>,
path: Spanned<bool>,
}
impl StaticCommand for Config {
fn name(&self) -> &str {
"config"
}
fn signature(&self) -> Signature {
Signature::build("config")
.named("set", SyntaxType::Any)
.named("get", SyntaxType::Any)
.named("remove", SyntaxType::Any)
.switch("clear")
.switch("path")
.sink()
}
fn run(
&self,
args: CommandArgs,
registry: &registry::CommandRegistry,
) -> Result<OutputStream, ShellError> {
let args = args.evaluate_once(registry)?;
config(args)
}
fn name(&self) -> &str {
"config"
}
fn config(&self) -> CommandConfig {
let mut named: IndexMap<String, NamedType> = IndexMap::new();
named.insert("set".to_string(), NamedType::Optional(SyntaxType::Any));
named.insert("get".to_string(), NamedType::Optional(SyntaxType::Any));
named.insert("clear".to_string(), NamedType::Switch);
named.insert("remove".to_string(), NamedType::Optional(SyntaxType::Any));
CommandConfig {
name: self.name().to_string(),
positional: vec![],
rest_positional: false,
named,
is_sink: true,
is_filter: false,
}
args.process(registry, config)?.run()
}
}
pub fn config(args: EvaluatedStaticCommandArgs) -> Result<OutputStream, ShellError> {
let mut result = crate::object::config::config(args.name_span())?;
pub fn config(
ConfigArgs {
set,
get,
clear,
remove,
path,
}: ConfigArgs,
RunnableContext { name, .. }: RunnableContext,
) -> Result<OutputStream, ShellError> {
let mut result = crate::object::config::config(name)?;
trace!("{:#?}", args.call_args().positional);
trace!("{:#?}", args.call_args().named);
if let Some(v) = args.get("get") {
let key = v.as_string()?;
if let Some(v) = get {
let key = v.to_string();
let value = result
.get(&key)
.ok_or_else(|| ShellError::string(&format!("Missing key {} in config", key)))?;
@ -61,31 +65,38 @@ pub fn config(args: EvaluatedStaticCommandArgs) -> Result<OutputStream, ShellErr
);
}
if let Some(v) = args.get("set") {
if let Ok((key, value)) = v.as_pair() {
result.insert(key.as_string()?.to_string(), value.clone());
if let Some((key, value)) = set {
result.insert(key.to_string(), value.clone());
config::write_config(&result)?;
config::write_config(&result)?;
return Ok(
stream![Spanned::from_item(Value::Object(result.into()), v.span())]
.from_input_stream(),
);
}
return Ok(stream![Spanned::from_item(
Value::Object(result.into()),
value.span()
)]
.from_input_stream());
}
if let Some(c) = args.get("clear") {
if let Spanned { item: true, span } = clear {
result.clear();
config::write_config(&result)?;
return Ok(
stream![Spanned::from_item(Value::Object(result.into()), c.span())].from_input_stream(),
stream![Spanned::from_item(Value::Object(result.into()), span)].from_input_stream(),
);
}
if let Some(v) = args.get("remove") {
let key = v.as_string()?;
if let Spanned { item: true, span } = path {
let path = config::config_path()?;
return Ok(
stream![Value::Primitive(Primitive::Path(path)).spanned(span)].from_input_stream(),
);
}
if let Some(v) = remove {
let key = v.to_string();
if result.contains_key(&key) {
result.remove(&key);
@ -96,13 +107,9 @@ pub fn config(args: EvaluatedStaticCommandArgs) -> Result<OutputStream, ShellErr
)));
}
let obj = VecDeque::from_iter(vec![Value::Object(result.into()).spanned(v)]);
let obj = VecDeque::from_iter(vec![Value::Object(result.into()).spanned(v.span())]);
return Ok(obj.from_input_stream());
}
if args.len() == 0 {
return Ok(vec![Value::Object(result.into()).spanned(args.name_span())].into());
}
Err(ShellError::string(format!("Unimplemented")))
return Ok(vec![Value::Object(result.into()).spanned(name)].into());
}

View File

@ -2,7 +2,7 @@ use crate::object::base::OF64;
use crate::object::{Primitive, SpannedDictBuilder, Value};
use crate::prelude::*;
fn convert_toml_value_to_nu_value(v: &toml::Value, span: impl Into<Span>) -> Spanned<Value> {
pub fn convert_toml_value_to_nu_value(v: &toml::Value, span: impl Into<Span>) -> Spanned<Value> {
let span = span.into();
match v {

View File

@ -1,9 +1,33 @@
use crate::commands::StaticCommand;
use crate::errors::ShellError;
use crate::object::Value;
use crate::parser::Span;
use crate::prelude::*;
fn get_member(path: &str, span: Span, obj: &Spanned<Value>) -> Result<Spanned<Value>, ShellError> {
pub struct Get;
#[derive(Deserialize)]
pub struct GetArgs {
rest: Vec<Spanned<String>>,
}
impl StaticCommand for Get {
fn name(&self) -> &str {
"get"
}
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
args.process(registry, get)?.run()
}
fn signature(&self) -> Signature {
Signature::build("get").rest()
}
}
fn get_member(path: &Spanned<String>, obj: &Spanned<Value>) -> Result<Spanned<Value>, ShellError> {
let mut current = obj;
for p in path.split(".") {
match current.get_data_by_key(p) {
@ -12,7 +36,7 @@ fn get_member(path: &str, span: Span, obj: &Spanned<Value>) -> Result<Spanned<Va
return Err(ShellError::labeled_error(
"Unknown field",
"object missing field",
span,
path.span,
));
}
}
@ -21,42 +45,21 @@ fn get_member(path: &str, span: Span, obj: &Spanned<Value>) -> Result<Spanned<Va
Ok(current.clone())
}
pub fn get(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
let args = args.evaluate_once(registry)?;
let span = args.name_span();
let len = args.len();
if len == 0 {
return Err(ShellError::maybe_labeled_error(
"Get requires a field or field path",
"needs parameter",
span,
));
}
let amount = args.expect_nth(0)?.as_i64();
let (input, args) = args.parts();
let positional = args.positional;
pub fn get(
GetArgs { rest: fields }: GetArgs,
RunnableContext { input, .. }: RunnableContext,
) -> Result<OutputStream, ShellError> {
// If it's a number, get the row instead of the column
if let Ok(amount) = amount {
return Ok(input.values.skip(amount as u64).take(1).from_input_stream());
}
let fields: Result<Vec<(String, Span)>, _> = positional
.iter()
.flatten()
.map(|a| (a.as_string().map(|x| (x, a.span))))
.collect();
let fields = fields?;
// if let Some(amount) = amount {
// return Ok(input.values.skip(amount as u64).take(1).from_input_stream());
// }
let stream = input
.values
.map(move |item| {
let mut result = VecDeque::new();
for field in &fields {
match get_member(&field.0, field.1, &item) {
match get_member(field, &item) {
Ok(Spanned {
item: Value::List(l),
..

View File

@ -12,7 +12,7 @@ macro_rules! command {
Named { $export:tt $args:ident $body:block }
Positional { $($number:tt)* }
Rest {}
CommandConfig {
Signature {
name: $config_name:tt,
mandatory_positional: vec![ $($mandatory_positional:tt)* ],
optional_positional: vec![ $($optional_positional:tt)* ],
@ -52,8 +52,8 @@ macro_rules! command {
stringify!($config_name)
}
fn config(&self) -> $crate::parser::registry::CommandConfig {
$crate::parser::registry::CommandConfig {
fn config(&self) -> $crate::parser::registry::Signature {
$crate::parser::registry::Signature {
name: self.name().to_string(),
positional: vec![$($mandatory_positional)*],
rest_positional: false,
@ -82,7 +82,7 @@ macro_rules! command {
Named { $export:tt $args:ident $body:block }
Positional { $($positional_count:tt)* }
Rest { -- $param_name:ident : Switch , $($rest:tt)* }
CommandConfig {
Signature {
name: $config_name:tt,
mandatory_positional: vec![ $($mandatory_positional:tt)* ],
optional_positional: vec![ $($optional_positional:tt)* ],
@ -102,7 +102,7 @@ macro_rules! command {
Named { $export $args $body }
Positional { $($positional_count)* + 1 }
Rest { $($rest)* }
CommandConfig {
Signature {
name: $config_name,
mandatory_positional: vec![ $($mandatory_positional)* ],
optional_positional: vec![ $($optional_positional)* ],
@ -132,7 +132,7 @@ macro_rules! command {
Named { $export:tt $args:ident $body:block }
Positional { $($positional_count:tt)* }
Rest { -- $param_name:ident : $param_kind:ty , $($rest:tt)* }
CommandConfig {
Signature {
name: $config_name:tt,
mandatory_positional: vec![ $($mandatory_positional:tt)* ],
optional_positional: vec![ $($optional_positional:tt)* ],
@ -152,7 +152,7 @@ macro_rules! command {
Named { $export $args $body }
Positional { $($positional_count)* + 1 }
Rest { $($rest)* }
CommandConfig {
Signature {
name: $config_name,
mandatory_positional: vec![ $($mandatory_positional)* ],
optional_positional: vec![ $($optional_positional)* ],
@ -182,7 +182,7 @@ macro_rules! command {
Named { $export:tt $args:ident $body:block }
Positional { $($positional_count:tt)* }
Rest { -- $param_name:ident ? : $param_kind:ty , $($rest:tt)* }
CommandConfig {
Signature {
name: $config_name:tt,
mandatory_positional: vec![ $($mandatory_positional:tt)* ],
optional_positional: vec![ $($optional_positional:tt)* ],
@ -202,7 +202,7 @@ macro_rules! command {
Named { $export $args $body }
Positional { $($positional_count)* + 1 }
Rest { $($rest)* }
CommandConfig {
Signature {
name: $config_name,
mandatory_positional: vec![ $($mandatory_positional)* ],
optional_positional: vec![ $($optional_positional)* ],
@ -232,7 +232,7 @@ macro_rules! command {
Named { $export:ident $args:ident $body:block }
Positional { $($positional_count:tt)* }
Rest { $param_name:ident : Block , $($rest:tt)* }
CommandConfig {
Signature {
name: $config_name:tt,
mandatory_positional: vec![ $($mandatory_positional:tt)* ],
optional_positional: vec![ $($optional_positional:tt)* ],
@ -255,7 +255,7 @@ macro_rules! command {
Named { $export $args $body }
Positional { $($positional_count)* + 1 }
Rest { $($rest)* }
CommandConfig {
Signature {
name: $config_name,
mandatory_positional: vec![ $($mandatory_positional)* $crate::parser::registry::PositionalType::mandatory_block(
stringify!($param_name)
@ -287,7 +287,7 @@ macro_rules! command {
Named { $export:ident $args:ident $body:block }
Positional { $($positional_count:tt)* }
Rest { $param_name:ident : $param_kind:ty , $($rest:tt)* }
CommandConfig {
Signature {
name: $config_name:tt,
mandatory_positional: vec![ $($mandatory_positional:tt)* ],
optional_positional: vec![ $($optional_positional:tt)* ],
@ -310,7 +310,7 @@ macro_rules! command {
Named { $export $args $body }
Positional { $($positional_count)* + 1 }
Rest { $($rest)* }
CommandConfig {
Signature {
name: $config_name,
mandatory_positional: vec![ $($mandatory_positional)* $crate::parser::registry::PositionalType::mandatory(
stringify!($param_name), <$param_kind>::syntax_type()
@ -341,7 +341,7 @@ macro_rules! command {
Named { $export $args $body }
Positional { 0 }
Rest { $($command_rest)* }
CommandConfig {
Signature {
name: $config_name,
mandatory_positional: vec![],
optional_positional: vec![],
@ -377,11 +377,11 @@ macro_rules! command {
// stringify!($name)
// }
// fn config(&self) -> CommandConfig {
// fn config(&self) -> Signature {
// let mut named: IndexMap<String, NamedType> = IndexMap::new();
// named.insert(stringify!($param).to_string(), NamedType::$kind);
// CommandConfig {
// Signature {
// name: self.name().to_string(),
// mandatory_positional: vec![],
// optional_positional: vec![],

View File

@ -1,9 +1,10 @@
use crate::commands::StaticCommand;
use crate::context::SpanSource;
use crate::errors::ShellError;
use crate::object::{Primitive, Value};
use crate::parser::hir::SyntaxType;
use crate::parser::parse::span::Span;
use crate::parser::registry::{self, CommandConfig, NamedType};
use crate::parser::registry::{self, Signature};
use crate::prelude::*;
use mime::Mime;
use std::path::{Path, PathBuf};
@ -12,75 +13,81 @@ use uuid::Uuid;
pub struct Open;
impl Command for Open {
#[derive(Deserialize)]
pub struct OpenArgs {
path: Spanned<PathBuf>,
raw: bool,
}
impl StaticCommand for Open {
fn name(&self) -> &str {
"open"
}
fn signature(&self) -> Signature {
Signature::build(self.name())
.required("path", SyntaxType::Block)
.switch("raw")
.sink()
}
fn run(
&self,
args: CommandArgs,
registry: &registry::CommandRegistry,
) -> Result<OutputStream, ShellError> {
let env = args.env.clone();
let args = args.evaluate_once(registry)?;
let path = <Spanned<PathBuf>>::extract(args.expect_nth(0)?)?;
let raw = args.has("raw");
args.process(registry, run)?.run()
}
}
let span = args.name_span();
fn run(
OpenArgs { raw, path }: OpenArgs,
RunnableContext { env, name, .. }: RunnableContext,
) -> Result<OutputStream, ShellError> {
let cwd = env.lock().unwrap().path().to_path_buf();
let full_path = PathBuf::from(cwd);
let cwd = env.lock().unwrap().path().to_path_buf();
let full_path = PathBuf::from(cwd);
let path_str = path.to_str().ok_or(ShellError::type_error(
"Path",
"invalid path".spanned(path.span),
))?;
let path_str = path.to_str().ok_or(ShellError::type_error(
"Path",
"invalid path".spanned(path.span),
))?;
let (file_extension, contents, contents_span, span_source) =
fetch(&full_path, path_str, path.span)?;
let (file_extension, contents, contents_span, span_source) =
fetch(&full_path, path_str, path.span)?;
let file_extension = if raw { None } else { file_extension };
let file_extension = if raw { None } else { file_extension };
let mut stream = VecDeque::new();
let mut stream = VecDeque::new();
if let Some(uuid) = contents_span.source {
// If we have loaded something, track its source
stream.push_back(ReturnSuccess::action(CommandAction::AddSpanSource(
uuid,
span_source,
)))
}
if let Some(uuid) = contents_span.source {
// If we have loaded something, track its source
stream.push_back(ReturnSuccess::action(CommandAction::AddSpanSource(
uuid,
span_source,
)))
match contents {
Value::Primitive(Primitive::String(string)) => {
let value = parse_as_value(file_extension, string, contents_span, name)?;
match value {
Spanned {
item: Value::List(list),
..
} => {
for elem in list {
stream.push_back(ReturnSuccess::value(elem));
}
}
x => stream.push_back(ReturnSuccess::value(x)),
}
}
match contents {
Value::Primitive(Primitive::String(string)) => {
let value = parse_as_value(file_extension, string, contents_span, span)?;
other => stream.push_back(ReturnSuccess::value(other.spanned(contents_span))),
};
match value {
Spanned {
item: Value::List(list),
..
} => {
for elem in list {
stream.push_back(ReturnSuccess::value(elem));
}
}
x => stream.push_back(ReturnSuccess::value(x)),
}
}
other => stream.push_back(ReturnSuccess::value(other.spanned(contents_span))),
};
Ok(stream.boxed().to_output_stream())
}
fn name(&self) -> &str {
"open"
}
fn config(&self) -> CommandConfig {
CommandConfig::new(self.name())
.required("path", SyntaxType::Block)
.named("raw", NamedType::Switch)
.sink()
}
Ok(stream.boxed().to_output_stream())
}
// command! {

View File

@ -1,7 +1,9 @@
use crate::commands::StaticCommand;
use crate::errors::ShellError;
use crate::parser::registry;
use crate::prelude::*;
use derive_new::new;
use futures_async_stream::async_stream_block;
use serde::{self, Deserialize, Serialize};
use std::io::prelude::*;
use std::io::BufReader;
@ -37,10 +39,18 @@ pub enum NuResult {
pub struct PluginCommand {
name: String,
path: String,
config: registry::CommandConfig,
config: registry::Signature,
}
impl Command for PluginCommand {
impl StaticCommand for PluginCommand {
fn name(&self) -> &str {
&self.name
}
fn signature(&self) -> registry::Signature {
self.config.clone()
}
fn run(
&self,
args: CommandArgs,
@ -48,29 +58,36 @@ impl Command for PluginCommand {
) -> Result<OutputStream, ShellError> {
filter_plugin(self.path.clone(), args, registry)
}
fn name(&self) -> &str {
&self.name
}
fn config(&self) -> registry::CommandConfig {
self.config.clone()
}
}
#[derive(new)]
pub struct PluginSink {
name: String,
path: String,
config: registry::CommandConfig,
config: registry::Signature,
}
impl Sink for PluginSink {
fn run(&self, args: SinkCommandArgs) -> Result<(), ShellError> {
sink_plugin(self.path.clone(), args)
impl StaticCommand for PluginSink {
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
let path = self.path.clone();
let stream = async_stream_block! {
sink_plugin(path, args).await;
};
let stream: BoxStream<'static, ReturnValue> = stream.boxed();
Ok(OutputStream::from(stream))
}
fn name(&self) -> &str {
&self.name
&self.config.name
}
fn config(&self) -> registry::CommandConfig {
fn signature(&self) -> registry::Signature {
self.config.clone()
}
}
@ -191,9 +208,10 @@ pub fn filter_plugin(
Ok(stream.to_output_stream())
}
pub fn sink_plugin(path: String, args: SinkCommandArgs) -> Result<(), ShellError> {
pub async fn sink_plugin(path: String, args: CommandArgs) -> Result<OutputStream, ShellError> {
//use subprocess::Exec;
let request = JsonRpc::new("sink", (args.call_info, args.input));
let input: Vec<Spanned<Value>> = args.input.values.collect().await;
let request = JsonRpc::new("sink", (args.call_info, input));
let request_raw = serde_json::to_string(&request).unwrap();
let mut tmpfile = tempfile::NamedTempFile::new()?;
let _ = writeln!(tmpfile, "{}", request_raw);
@ -206,5 +224,5 @@ pub fn sink_plugin(path: String, args: SinkCommandArgs) -> Result<(), ShellError
let _ = child.wait();
Ok(())
Ok(OutputStream::empty())
}

View File

@ -1,63 +1,57 @@
use crate::commands::EvaluatedStaticCommandArgs;
use crate::commands::{EvaluatedStaticCommandArgs, StaticCommand};
use crate::errors::ShellError;
use crate::parser::hir::SyntaxType;
use crate::parser::registry::{CommandConfig, NamedType, PositionalType};
use crate::parser::registry::{NamedType, PositionalType};
use crate::prelude::*;
use indexmap::IndexMap;
use std::path::PathBuf;
pub struct Remove;
impl Command for Remove {
#[derive(Deserialize)]
pub struct RemoveArgs {
path: Spanned<PathBuf>,
recursive: bool,
}
impl StaticCommand for Remove {
fn name(&self) -> &str {
"rm"
}
fn signature(&self) -> Signature {
Signature::build("rm")
.required("path", SyntaxType::Path)
.switch("recursive")
.sink()
}
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
let env = args.env.clone();
rm(args.evaluate_once(registry)?, env)
}
fn name(&self) -> &str {
"rm"
}
fn config(&self) -> CommandConfig {
let mut named: IndexMap<String, NamedType> = IndexMap::new();
named.insert("recursive".to_string(), NamedType::Switch);
CommandConfig {
name: self.name().to_string(),
positional: vec![PositionalType::mandatory("file", SyntaxType::Path)],
rest_positional: false,
named,
is_sink: true,
is_filter: false,
}
args.process(registry, rm)?.run()
}
}
pub fn rm(
args: EvaluatedStaticCommandArgs,
env: Arc<Mutex<Environment>>,
RemoveArgs { path, recursive }: RemoveArgs,
context: RunnableContext,
) -> Result<OutputStream, ShellError> {
let mut full_path = env.lock().unwrap().path().to_path_buf();
let mut full_path = context.cwd();
match args
.nth(0)
.ok_or_else(|| ShellError::string(&format!("No file or directory specified")))?
.as_string()?
.as_str()
{
match path.item.to_str().unwrap() {
"." | ".." => return Err(ShellError::string("\".\" and \"..\" may not be removed")),
file => full_path.push(file),
}
if full_path.is_dir() {
if !args.has("recursive") {
return Err(ShellError::labeled_error(
if !recursive {
return Err(ShellError::maybe_labeled_error(
"is a directory",
"",
args.name_span().unwrap(),
context.name,
));
}
std::fs::remove_dir_all(&full_path).expect("can not remove directory");

View File

@ -1,100 +1,119 @@
use crate::commands::command::SinkCommandArgs;
use crate::commands::to_csv::{to_string as to_csv_to_string, value_to_csv_value};
use crate::commands::to_json::value_to_json_value;
use crate::commands::to_toml::value_to_toml_value;
use crate::commands::to_yaml::value_to_yaml_value;
use crate::commands::StaticCommand;
use crate::errors::ShellError;
use crate::object::{Primitive, Value};
use crate::parser::Spanned;
use crate::prelude::*;
use futures_async_stream::async_stream_block;
use std::path::{Path, PathBuf};
pub fn save(args: SinkCommandArgs) -> Result<(), ShellError> {
if args.call_info.args.positional.is_none() {
return Err(ShellError::maybe_labeled_error(
"Save requires a filepath",
"needs path",
args.name_span(),
));
}
pub struct Save;
let positional = match args.call_info.args.positional {
None => return Err(ShellError::string("save requires a filepath")),
Some(p) => p,
};
let cwd = args.ctx.env.lock().unwrap().path().to_path_buf();
let mut full_path = PathBuf::from(cwd);
match &(positional[0].item) {
Value::Primitive(Primitive::String(s)) => full_path.push(Path::new(s)),
_ => {}
}
let save_raw = match positional.get(1) {
Some(Spanned {
item: Value::Primitive(Primitive::String(s)),
..
}) if s == "--raw" => true,
_ => false,
};
let contents = match full_path.extension() {
Some(x) if x == "csv" && !save_raw => {
if args.input.len() != 1 {
return Err(ShellError::string(
"saving to csv requires a single object (or use --raw)",
));
}
to_csv_to_string(&value_to_csv_value(&args.input[0])).unwrap()
}
Some(x) if x == "toml" && !save_raw => {
if args.input.len() != 1 {
return Err(ShellError::string(
"saving to toml requires a single object (or use --raw)",
));
}
toml::to_string(&value_to_toml_value(&args.input[0])).unwrap()
}
Some(x) if x == "json" && !save_raw => {
if args.input.len() != 1 {
return Err(ShellError::string(
"saving to json requires a single object (or use --raw)",
));
}
serde_json::to_string(&value_to_json_value(&args.input[0])).unwrap()
}
Some(x) if x == "yml" && !save_raw => {
if args.input.len() != 1 {
return Err(ShellError::string(
"saving to yml requires a single object (or use --raw)",
));
}
serde_yaml::to_string(&value_to_yaml_value(&args.input[0])).unwrap()
}
Some(x) if x == "yaml" && !save_raw => {
if args.input.len() != 1 {
return Err(ShellError::string(
"saving to yaml requires a single object (or use --raw)",
));
}
serde_yaml::to_string(&value_to_yaml_value(&args.input[0])).unwrap()
}
_ => {
let mut save_data = String::new();
if args.input.len() > 0 {
let mut first = true;
for i in args.input.iter() {
if !first {
save_data.push_str("\n");
} else {
first = false;
}
save_data.push_str(&i.as_string().unwrap());
}
}
save_data
}
};
let _ = std::fs::write(full_path, contents);
Ok(())
#[derive(Deserialize)]
struct SaveArgs {
path: Spanned<PathBuf>,
raw: bool,
}
impl StaticCommand for Save {
fn name(&self) -> &str {
"save"
}
fn signature(&self) -> Signature {
Signature::build("save")
.required("path", SyntaxType::Path)
.switch("raw")
.sink()
}
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
args.process(registry, save)?.run()
}
}
pub fn save(
SaveArgs {
path,
raw: save_raw,
}: SaveArgs,
context: RunnableContext,
) -> Result<OutputStream, ShellError> {
let mut full_path = context.cwd();
full_path.push(path.item());
let stream = async_stream_block! {
let input: Vec<Spanned<Value>> = context.input.values.collect().await;
let contents = match full_path.extension() {
Some(x) if x == "csv" && !save_raw => {
if input.len() != 1 {
return Err(ShellError::string(
"saving to csv requires a single object (or use --raw)",
));
}
to_csv_to_string(&value_to_csv_value(&input[0])).unwrap()
}
Some(x) if x == "toml" && !save_raw => {
if input.len() != 1 {
return Err(ShellError::string(
"saving to toml requires a single object (or use --raw)",
));
}
toml::to_string(&value_to_toml_value(&input[0])).unwrap()
}
Some(x) if x == "json" && !save_raw => {
if input.len() != 1 {
return Err(ShellError::string(
"saving to json requires a single object (or use --raw)",
));
}
serde_json::to_string(&value_to_json_value(&input[0])).unwrap()
}
Some(x) if x == "yml" && !save_raw => {
if input.len() != 1 {
return Err(ShellError::string(
"saving to yml requires a single object (or use --raw)",
));
}
serde_yaml::to_string(&value_to_yaml_value(&input[0])).unwrap()
}
Some(x) if x == "yaml" && !save_raw => {
if input.len() != 1 {
return Err(ShellError::string(
"saving to yaml requires a single object (or use --raw)",
));
}
serde_yaml::to_string(&value_to_yaml_value(&input[0])).unwrap()
}
_ => {
let mut save_data = String::new();
if input.len() > 0 {
let mut first = true;
for i in input.iter() {
if !first {
save_data.push_str("\n");
} else {
first = false;
}
save_data.push_str(&i.as_string().unwrap());
}
}
save_data
}
};
let _ = std::fs::write(full_path, contents);
};
let stream: BoxStream<'static, ReturnValue> = stream.boxed();
Ok(OutputStream::from(stream))
}

View File

@ -1,54 +1,40 @@
use crate::commands::StaticCommand;
use crate::errors::ShellError;
use crate::parser::registry::CommandConfig;
use crate::parser::registry::PositionalType;
use crate::prelude::*;
pub struct SkipWhile;
impl Command for SkipWhile {
#[derive(Deserialize)]
pub struct SkipWhileArgs {
condition: value::Block,
}
impl StaticCommand for SkipWhile {
fn name(&self) -> &str {
"skip-while"
}
fn signature(&self) -> Signature {
Signature::build("skip-while")
.required("condition", SyntaxType::Block)
.filter()
}
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
skip_while(args, registry)
}
fn name(&self) -> &str {
"skip-while"
}
fn config(&self) -> CommandConfig {
CommandConfig {
name: self.name().to_string(),
positional: vec![PositionalType::mandatory_block("condition")],
rest_positional: false,
named: indexmap::IndexMap::new(),
is_filter: true,
is_sink: false,
}
args.process(registry, skip_while)?.run()
}
}
pub fn skip_while(
args: CommandArgs,
registry: &CommandRegistry,
SkipWhileArgs { condition }: SkipWhileArgs,
RunnableContext { input, .. }: RunnableContext,
) -> Result<OutputStream, ShellError> {
let args = args.evaluate_once(registry)?;
let block = args.expect_nth(0)?.as_block()?;
let span = args.name_span();
let len = args.len();
let input = args.input;
if len == 0 {
return Err(ShellError::maybe_labeled_error(
"Where requires a condition",
"needs condition",
span,
));
}
let objects = input.values.skip_while(move |item| {
let result = block.invoke(&item);
let result = condition.invoke(&item);
let return_value = match result {
Ok(v) if v.is_true() => true,

View File

@ -1,9 +1,8 @@
use crate::commands::command::SinkCommandArgs;
use crate::errors::ShellError;
use crate::format::TableView;
use crate::prelude::*;
pub fn table(args: SinkCommandArgs) -> Result<(), ShellError> {
pub fn table(args: CommandArgs, context: RunnableContext) -> Result<(), ShellError> {
if args.input.len() > 0 {
let mut host = args.ctx.host.lock().unwrap();
let view = TableView::from_list(&args.input);

View File

@ -1,9 +1,8 @@
use crate::commands::command::SinkCommandArgs;
use crate::errors::ShellError;
use crate::format::VTableView;
use crate::prelude::*;
pub fn vtable(args: SinkCommandArgs) -> Result<(), ShellError> {
pub fn vtable(args: CommandArgs, context: RunnableContext) -> Result<(), ShellError> {
if args.input.len() > 0 {
let mut host = args.ctx.host.lock().unwrap();
let view = VTableView::from_list(&args.input);

View File

@ -1,75 +1,58 @@
use crate::commands::StaticCommand;
use crate::errors::ShellError;
use crate::object::base as value;
use crate::parser::hir::SyntaxType;
use crate::parser::registry::{self, CommandConfig, PositionalType};
use crate::parser::registry;
use crate::prelude::*;
use futures::future::ready;
use indexmap::IndexMap;
use log::trace;
use serde::Deserialize;
pub struct Where;
impl Command for Where {
#[derive(Deserialize)]
struct WhereArgs {
condition: value::Block,
}
impl StaticCommand for Where {
fn name(&self) -> &str {
"where"
}
fn signature(&self) -> registry::Signature {
Signature::build("where")
.required("condition", SyntaxType::Block)
.sink()
}
fn run(
&self,
args: CommandArgs,
registry: &registry::CommandRegistry,
) -> Result<OutputStream, ShellError> {
let args = args.evaluate_once(registry)?;
let condition = value::Block::extract(args.expect_nth(0)?)?;
let input = args.input;
let input: InputStream =
trace_stream!(target: "nu::trace_stream::where", "where input" = input);
Ok(input
.values
.filter_map(move |item| {
let result = condition.invoke(&item);
let return_value = match result {
Err(err) => Some(Err(err)),
Ok(v) if v.is_true() => Some(Ok(ReturnSuccess::Value(item.clone()))),
_ => None,
};
ready(return_value)
})
.boxed()
.to_output_stream())
}
fn name(&self) -> &str {
"where"
}
fn config(&self) -> CommandConfig {
CommandConfig {
name: self.name().to_string(),
positional: vec![PositionalType::mandatory("condition", SyntaxType::Block)],
rest_positional: false,
named: IndexMap::default(),
is_sink: true,
is_filter: false,
}
args.process(registry, run)?.run()
}
}
// command! {
// Where as where(args, condition: Block,) {
// let input = args.input;
// let input: InputStream = trace_stream!(target: "nu::trace_stream::where", "where input" = input);
fn run(
WhereArgs { condition }: WhereArgs,
context: RunnableContext,
) -> Result<OutputStream, ShellError> {
Ok(context
.input
.values
.filter_map(move |item| {
let result = condition.invoke(&item);
// input.values.filter_map(move |item| {
// let result = condition.invoke(&item);
let return_value = match result {
Err(err) => Some(Err(err)),
Ok(v) if v.is_true() => Some(Ok(ReturnSuccess::Value(item.clone()))),
_ => None,
};
// let return_value = match result {
// Err(err) => Some(Err(err)),
// Ok(v) if v.is_true() => Some(Ok(ReturnSuccess::Value(item.clone()))),
// _ => None,
// };
// ready(return_value)
// })
// }
// }
ready(return_value)
})
.boxed()
.to_output_stream())
}

View File

@ -1,4 +1,4 @@
use crate::commands::command::{CallInfo, Sink, SinkCommandArgs, UnevaluatedCallInfo};
use crate::commands::{CallInfo, Command, StaticCommand, UnevaluatedCallInfo};
use crate::parser::{hir, registry, Span};
use crate::prelude::*;
@ -37,7 +37,7 @@ impl SourceMap {
#[derive(Clone, new)]
pub struct CommandRegistry {
#[new(value = "Arc::new(Mutex::new(IndexMap::default()))")]
registry: Arc<Mutex<IndexMap<String, Arc<dyn Command>>>>,
registry: Arc<Mutex<IndexMap<String, Arc<Command>>>>,
}
impl CommandRegistry {
@ -47,7 +47,7 @@ impl CommandRegistry {
}
}
fn get_command(&self, name: &str) -> Option<Arc<dyn Command>> {
fn get_command(&self, name: &str) -> Option<Arc<Command>> {
let registry = self.registry.lock().unwrap();
registry.get(name).map(|c| c.clone())
@ -59,7 +59,7 @@ impl CommandRegistry {
registry.contains_key(name)
}
fn insert(&mut self, name: impl Into<String>, command: Arc<dyn Command>) {
fn insert(&mut self, name: impl Into<String>, command: Arc<Command>) {
let mut registry = self.registry.lock().unwrap();
registry.insert(name.into(), command);
}
@ -73,7 +73,6 @@ impl CommandRegistry {
#[derive(Clone)]
pub struct Context {
registry: CommandRegistry,
sinks: IndexMap<String, Arc<dyn Sink>>,
crate source_map: SourceMap,
crate host: Arc<Mutex<dyn Host + Send>>,
crate env: Arc<Mutex<Environment>>,
@ -87,57 +86,22 @@ impl Context {
crate fn basic() -> Result<Context, Box<dyn Error>> {
Ok(Context {
registry: CommandRegistry::new(),
sinks: indexmap::IndexMap::new(),
source_map: SourceMap::new(),
host: Arc::new(Mutex::new(crate::env::host::BasicHost)),
env: Arc::new(Mutex::new(Environment::basic()?)),
})
}
pub fn add_commands(&mut self, commands: Vec<Arc<dyn Command>>) {
pub fn add_commands(&mut self, commands: Vec<Arc<Command>>) {
for command in commands {
self.registry.insert(command.name().to_string(), command);
}
}
pub fn add_sinks(&mut self, sinks: Vec<Arc<dyn Sink>>) {
for sink in sinks {
self.sinks.insert(sink.name().to_string(), sink);
}
}
pub fn add_span_source(&mut self, uuid: Uuid, span_source: SpanSource) {
self.source_map.insert(uuid, span_source);
}
crate fn has_sink(&self, name: &str) -> bool {
self.sinks.contains_key(name)
}
crate fn get_sink(&self, name: &str) -> Arc<dyn Sink> {
self.sinks.get(name).unwrap().clone()
}
crate fn run_sink(
&mut self,
command: Arc<dyn Sink>,
name_span: Option<Span>,
args: registry::EvaluatedArgs,
input: Vec<Spanned<Value>>,
) -> Result<(), ShellError> {
let command_args = SinkCommandArgs {
ctx: self.clone(),
call_info: CallInfo {
name_span,
source_map: self.source_map.clone(),
args,
},
input,
};
command.run(command_args)
}
pub fn clone_commands(&self) -> CommandRegistry {
self.registry.clone()
}
@ -146,13 +110,13 @@ impl Context {
self.registry.has(name)
}
crate fn get_command(&self, name: &str) -> Arc<dyn Command> {
crate fn get_command(&self, name: &str) -> Arc<Command> {
self.registry.get_command(name).unwrap()
}
crate fn run_command(
crate async fn run_command(
&mut self,
command: Arc<dyn Command>,
command: Arc<Command>,
name_span: Option<Span>,
source_map: SourceMap,
args: hir::Call,
@ -161,7 +125,7 @@ impl Context {
) -> Result<OutputStream, ShellError> {
let command_args = self.command_args(args, input, source, source_map, name_span);
command.run(command_args, self.registry())
command.run(command_args, self.registry()).await
}
fn call_info(

View File

@ -62,6 +62,15 @@ pub struct ShellError {
cause: Option<Box<ProximateShellError>>,
}
impl serde::de::Error for ShellError {
fn custom<T>(msg: T) -> Self
where
T: std::fmt::Display,
{
ShellError::string(msg.to_string())
}
}
impl ShellError {
crate fn type_error(
expected: impl Into<String>,
@ -351,16 +360,6 @@ impl std::convert::From<std::io::Error> for ShellError {
}
}
impl std::convert::From<futures_sink::VecSinkError> for ShellError {
fn from(_input: futures_sink::VecSinkError) -> ShellError {
ProximateShellError::String(StringError {
title: format!("Unexpected Vec Sink Error"),
error: Value::nothing(),
})
.start()
}
}
impl std::convert::From<subprocess::PopenError> for ShellError {
fn from(input: subprocess::PopenError) -> ShellError {
ProximateShellError::String(StringError {

View File

@ -55,6 +55,16 @@ crate fn evaluate_baseline_expr(
)),
}
}
RawExpression::List(list) => {
let mut exprs = vec![];
for expr in list {
let expr = evaluate_baseline_expr(expr, registry, scope, source)?;
exprs.push(expr);
}
Ok(Value::List(exprs).spanned(expr.span()))
}
RawExpression::Block(block) => Ok(Spanned::from_item(
Value::Block(Block::new(block.clone(), source.clone(), *expr.span())),
expr.span(),

View File

@ -1,11 +1,15 @@
#![feature(crate_visibility_modifier)]
#![feature(in_band_lifetimes)]
#![feature(async_await)]
#![feature(generators)]
#![feature(try_trait)]
#![feature(bind_by_move_pattern_guards)]
#![feature(box_syntax)]
#![feature(type_ascription)]
#![feature(core_intrinsics)]
#![feature(option_flattening)]
#![feature(specialization)]
#![feature(proc_macro_hygiene)]
#[macro_use]
mod prelude;
@ -37,4 +41,4 @@ pub use cli::cli;
pub use errors::ShellError;
pub use object::base::{Primitive, Value};
pub use parser::parse::text::Text;
pub use parser::registry::{CommandConfig, EvaluatedArgs, NamedType, PositionalType};
pub use parser::registry::{EvaluatedArgs, NamedType, PositionalType, Signature};

View File

@ -6,6 +6,6 @@ crate mod into;
crate mod process;
crate mod types;
crate use base::{Primitive, Value};
crate use base::{Block, Primitive, Switch, Value};
crate use dict::{Dictionary, SpannedDictBuilder};
crate use files::dir_entry_dict;

View File

@ -10,7 +10,7 @@ use chrono::{DateTime, Utc};
use chrono_humanize::Humanize;
use derive_new::new;
use ordered_float::OrderedFloat;
use serde::{ser::SerializeSeq, Deserialize, Deserializer, Serialize, Serializer};
use serde::{Deserialize, Serialize};
use std::fmt;
use std::path::PathBuf;
use std::time::SystemTime;
@ -123,42 +123,13 @@ pub struct Operation {
crate right: Value,
}
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Clone, new)]
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Clone, Serialize, Deserialize, new)]
pub struct Block {
crate expressions: Vec<hir::Expression>,
crate source: Text,
crate span: Span,
}
impl Serialize for Block {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut seq = serializer.serialize_seq(None)?;
let list = self
.expressions
.iter()
.map(|e| e.source(&self.source.clone()));
for item in list {
seq.serialize_element(item.as_ref())?;
}
seq.end()
}
}
impl Deserialize<'de> for Block {
fn deserialize<D>(_deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
unimplemented!("deserialize block")
}
}
impl Block {
pub fn invoke(&self, value: &Spanned<Value>) -> Result<Spanned<Value>, ShellError> {
let scope = Scope::new(value.clone());
@ -260,6 +231,7 @@ impl std::convert::TryFrom<&'a Spanned<Value>> for i64 {
}
}
#[derive(Serialize, Deserialize)]
pub enum Switch {
Present,
Absent,

View File

@ -1,12 +1,15 @@
use crate::commands::from_toml::convert_toml_value_to_nu_value;
use crate::commands::to_toml::value_to_toml_value;
use crate::errors::ShellError;
use crate::object::{Dictionary, Value};
use crate::prelude::*;
use app_dirs::*;
use indexmap::IndexMap;
use log::trace;
use serde_derive::{Deserialize, Serialize};
use serde::{Deserialize, Serialize};
use std::fs::{self, OpenOptions};
use std::io;
use std::path::Path;
use std::path::{Path, PathBuf};
const APP_INFO: AppInfo = AppInfo {
name: "nu",
@ -16,7 +19,14 @@ const APP_INFO: AppInfo = AppInfo {
#[derive(Deserialize, Serialize)]
struct Config {
#[serde(flatten)]
extra: IndexMap<String, Spanned<Value>>,
extra: IndexMap<String, Value>,
}
crate fn config_path() -> Result<PathBuf, ShellError> {
let location = app_root(AppDataType::UserConfig, &APP_INFO)
.map_err(|err| ShellError::string(&format!("Couldn't open config file:\n{}", err)))?;
Ok(location.join("config.toml"))
}
crate fn write_config(config: &IndexMap<String, Spanned<Value>>) -> Result<(), ShellError> {
@ -26,9 +36,9 @@ crate fn write_config(config: &IndexMap<String, Spanned<Value>>) -> Result<(), S
let filename = location.join("config.toml");
touch(&filename)?;
let contents = toml::to_string(&Config {
extra: config.iter().map(|(k, v)| (k.clone(), v.clone())).collect(),
})?;
let contents = value_to_toml_value(&Value::Object(Dictionary::new(config.clone())));
let contents = toml::to_string(&contents)?;
fs::write(&filename, &contents)?;
@ -50,10 +60,18 @@ crate fn config(span: impl Into<Span>) -> Result<IndexMap<String, Spanned<Value>
.map(|v| v.spanned(span))
.map_err(|err| ShellError::string(&format!("Couldn't read config file:\n{}", err)))?;
let parsed: Config = toml::from_str(&contents)
let parsed: toml::Value = toml::from_str(&contents)
.map_err(|err| ShellError::string(&format!("Couldn't parse config file:\n{}", err)))?;
Ok(parsed.extra)
let value = convert_toml_value_to_nu_value(&parsed, span);
match value.item {
Value::Object(Dictionary { entries }) => Ok(entries),
other => Err(ShellError::type_error(
"Dictionary",
other.type_name().spanned(value.span),
)),
}
}
// A simple implementation of `% touch path` (ignores existing files)

View File

@ -1,16 +1,9 @@
use crate::object::base as value;
use crate::parser::hir;
use crate::prelude::*;
use derive_new::new;
use serde_derive::Deserialize;
use log::trace;
use std::path::PathBuf;
pub trait Type: std::fmt::Debug + Send {
type Extractor: ExtractType;
fn name(&self) -> &'static str;
}
pub trait ExtractType: Sized {
fn extract(value: &Spanned<Value>) -> Result<Self, ShellError>;
fn check(value: &'value Spanned<Value>) -> Result<&'value Spanned<Value>, ShellError>;
@ -19,8 +12,120 @@ pub trait ExtractType: Sized {
}
}
impl<T> ExtractType for T {
default fn extract(_value: &Spanned<Value>) -> Result<T, ShellError> {
let name = unsafe { std::intrinsics::type_name::<T>() };
Err(ShellError::unimplemented(format!(
"<T> ExtractType for {}",
name
)))
}
default fn check(_value: &'value Spanned<Value>) -> Result<&'value Spanned<Value>, ShellError> {
Err(ShellError::unimplemented("ExtractType for T"))
}
default fn syntax_type() -> hir::SyntaxType {
hir::SyntaxType::Any
}
}
impl<T: ExtractType> ExtractType for Vec<Spanned<T>> {
fn extract(value: &Spanned<Value>) -> Result<Self, ShellError> {
let name = unsafe { std::intrinsics::type_name::<T>() };
trace!("<Vec> Extracting {:?} for Vec<{}>", value, name);
match value.item() {
Value::List(items) => {
let mut out = vec![];
for item in items {
out.push(T::extract(item)?.spanned(item.span));
}
Ok(out)
}
other => Err(ShellError::type_error(
"Vec",
other.type_name().spanned(value.span),
)),
}
}
fn check(value: &'value Spanned<Value>) -> Result<&'value Spanned<Value>, ShellError> {
match value.item() {
Value::List(_) => Ok(value),
other => Err(ShellError::type_error(
"Vec",
other.type_name().spanned(value.span),
)),
}
}
fn syntax_type() -> hir::SyntaxType {
hir::SyntaxType::List
}
}
impl<T: ExtractType, U: ExtractType> ExtractType for (T, U) {
fn extract(value: &Spanned<Value>) -> Result<(T, U), ShellError> {
let t_name = unsafe { std::intrinsics::type_name::<T>() };
let u_name = unsafe { std::intrinsics::type_name::<U>() };
trace!("Extracting {:?} for ({}, {})", value, t_name, u_name);
match value.item() {
Value::List(items) => {
if items.len() == 2 {
let first = &items[0];
let second = &items[1];
Ok((T::extract(first)?, U::extract(second)?))
} else {
Err(ShellError::type_error(
"two-element-tuple",
"not-two".spanned(value.span),
))
}
}
other => Err(ShellError::type_error(
"two-element-tuple",
other.type_name().spanned(value.span),
)),
}
}
}
impl<T: ExtractType> ExtractType for Option<T> {
fn extract(value: &Spanned<Value>) -> Result<Option<T>, ShellError> {
let name = unsafe { std::intrinsics::type_name::<T>() };
trace!("<Option> Extracting {:?} for Option<{}>", value, name);
let result = match value.item() {
Value::Primitive(Primitive::Nothing) => None,
_ => Some(T::extract(value)?),
};
Ok(result)
}
fn check(value: &'value Spanned<Value>) -> Result<&'value Spanned<Value>, ShellError> {
match value.item() {
Value::Primitive(Primitive::Nothing) => Ok(value),
_ => T::check(value),
}
}
fn syntax_type() -> hir::SyntaxType {
T::syntax_type()
}
}
impl<T: ExtractType> ExtractType for Spanned<T> {
fn extract(value: &Spanned<Value>) -> Result<Spanned<T>, ShellError> {
let name = unsafe { std::intrinsics::type_name::<T>() };
trace!("<Spanned> Extracting {:?} for Spanned<{}>", value, name);
Ok(T::extract(value)?.spanned(value.span))
}
@ -33,25 +138,52 @@ impl<T: ExtractType> ExtractType for Spanned<T> {
}
}
#[derive(Debug, Deserialize, Clone, Eq, PartialEq, Hash, Ord, PartialOrd, new)]
pub struct Any;
impl ExtractType for Value {
fn extract(value: &Spanned<Value>) -> Result<Value, ShellError> {
trace!("<Spanned> Extracting {:?} for Value", value);
impl Type for Any {
type Extractor = Spanned<Value>;
fn name(&self) -> &'static str {
"Any"
}
}
impl ExtractType for Spanned<Value> {
fn extract(value: &Spanned<Value>) -> Result<Self, ShellError> {
Ok(value.clone())
Ok(value.item().clone())
}
fn check(value: &'value Spanned<Value>) -> Result<&'value Spanned<Value>, ShellError> {
Ok(value)
}
fn syntax_type() -> hir::SyntaxType {
SyntaxType::Any
}
}
impl ExtractType for bool {
fn syntax_type() -> hir::SyntaxType {
hir::SyntaxType::Boolean
}
fn extract(value: &'a Spanned<Value>) -> Result<bool, ShellError> {
trace!("Extracting {:?} for bool", value);
match &value {
Spanned {
item: Value::Primitive(Primitive::Boolean(b)),
..
} => Ok(*b),
Spanned {
item: Value::Primitive(Primitive::Nothing),
..
} => Ok(false),
other => Err(ShellError::type_error("Boolean", other.spanned_type_name())),
}
}
fn check(value: &'value Spanned<Value>) -> Result<&'value Spanned<Value>, ShellError> {
match &value {
value @ Spanned {
item: Value::Primitive(Primitive::Boolean(_)),
..
} => Ok(value),
other => Err(ShellError::type_error("Boolean", other.spanned_type_name())),
}
}
}
impl ExtractType for std::path::PathBuf {
@ -60,6 +192,8 @@ impl ExtractType for std::path::PathBuf {
}
fn extract(value: &'a Spanned<Value>) -> Result<std::path::PathBuf, ShellError> {
trace!("Extracting {:?} for PathBuf", value);
match &value {
Spanned {
item: Value::Primitive(Primitive::String(p)),
@ -80,19 +214,10 @@ impl ExtractType for std::path::PathBuf {
}
}
#[derive(Debug, Deserialize, Clone, Eq, PartialEq, Hash, Ord, PartialOrd, new)]
pub struct Integer;
impl Type for Integer {
type Extractor = i64;
fn name(&self) -> &'static str {
"Integer"
}
}
impl ExtractType for i64 {
fn extract(value: &Spanned<Value>) -> Result<i64, ShellError> {
trace!("Extracting {:?} for i64", value);
match value {
&Spanned {
item: Value::Primitive(Primitive::Int(int)),
@ -113,19 +238,10 @@ impl ExtractType for i64 {
}
}
#[derive(Debug, Deserialize, Clone, Eq, PartialEq, Hash, Ord, PartialOrd, new)]
pub struct NuString;
impl Type for NuString {
type Extractor = String;
fn name(&self) -> &'static str {
"Integer"
}
}
impl ExtractType for String {
fn extract(value: &Spanned<Value>) -> Result<String, ShellError> {
trace!("Extracting {:?} for String", value);
match value {
Spanned {
item: Value::Primitive(Primitive::String(string)),
@ -146,19 +262,10 @@ impl ExtractType for String {
}
}
#[derive(Debug, Deserialize, Clone, Eq, PartialEq, Hash, Ord, PartialOrd, new)]
pub struct Block;
impl Type for Block {
type Extractor = value::Block;
fn name(&self) -> &'static str {
"Block"
}
}
impl ExtractType for value::Block {
fn check(value: &'value Spanned<Value>) -> Result<&'value Spanned<Value>, ShellError> {
trace!("Extracting {:?} for Block", value);
match value {
v @ Spanned {
item: Value::Block(_),

View File

@ -1,3 +1,4 @@
crate mod deserializer;
crate mod hir;
crate mod parse;
crate mod parse_command;
@ -5,6 +6,7 @@ crate mod registry;
use crate::errors::ShellError;
crate use deserializer::ConfigDeserializer;
crate use hir::baseline_parse_tokens::baseline_parse_tokens;
crate use parse::call_node::CallNode;
crate use parse::files::Files;

307
src/parser/deserializer.rs Normal file
View File

@ -0,0 +1,307 @@
use crate::commands::command::EvaluatedCommandArgs;
use crate::prelude::*;
use log::trace;
use serde::{de, forward_to_deserialize_any};
#[derive(Debug)]
pub struct DeserializerItem<'de> {
key: String,
struct_field: &'de str,
val: Spanned<Value>,
}
pub struct ConfigDeserializer<'de> {
args: EvaluatedCommandArgs,
stack: Vec<DeserializerItem<'de>>,
saw_root: bool,
position: usize,
}
impl ConfigDeserializer<'de> {
pub fn from_call_node(args: EvaluatedCommandArgs) -> ConfigDeserializer<'de> {
ConfigDeserializer {
args,
stack: vec![],
saw_root: false,
position: 0,
}
}
pub fn push(&mut self, name: &'static str) -> Result<(), ShellError> {
let value: Option<Spanned<Value>> = if name == "rest" {
let positional = self.args.slice_from(self.position);
self.position += positional.len();
Some(Value::List(positional).spanned_unknown()) // TODO: correct span
} else {
if self.args.has(name) {
self.args.get(name).map(|x| x.clone())
} else {
let position = self.position;
self.position += 1;
self.args.nth(position).map(|x| x.clone())
}
};
trace!("pushing {:?}", value);
self.stack.push(DeserializerItem {
key: name.to_string(),
struct_field: name,
val: value.unwrap_or_else(|| Value::nothing().spanned(self.args.call_info.name_span)),
});
Ok(())
}
pub fn pop(&mut self) -> DeserializerItem {
let value = self.stack.pop();
trace!("popping value :: {:?}", value);
value.expect("Can't pop an empty stack")
}
}
use de::Visitor;
impl<'de, 'a> de::Deserializer<'de> for &'a mut ConfigDeserializer<'de> {
type Error = ShellError;
fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
let value = self.pop();
let name = unsafe { std::intrinsics::type_name::<V::Value>() };
trace!("<Deserialize any> Extracting {:?}", name);
V::Value::extract(&value.val)
}
forward_to_deserialize_any! { bool option seq }
fn deserialize_i8<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_i8")
}
fn deserialize_i16<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_i16")
}
fn deserialize_i32<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_i32")
}
fn deserialize_i64<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_i64")
}
fn deserialize_u8<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_u8")
}
fn deserialize_u16<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_u16")
}
fn deserialize_u32<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_u32")
}
fn deserialize_u64<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_u64")
}
fn deserialize_f32<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_f32")
}
fn deserialize_f64<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_f64")
}
fn deserialize_char<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_char")
}
fn deserialize_str<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_str")
}
fn deserialize_string<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_string")
}
fn deserialize_bytes<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_bytes")
}
fn deserialize_byte_buf<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_byte_buf")
}
fn deserialize_unit<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_unit")
}
fn deserialize_unit_struct<V>(
self,
_name: &'static str,
_visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_unit_struct")
}
fn deserialize_newtype_struct<V>(
self,
_name: &'static str,
_visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_newtype_struct")
}
fn deserialize_tuple<V>(self, _len: usize, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_tuple")
}
fn deserialize_tuple_struct<V>(
self,
_name: &'static str,
_len: usize,
_visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_tuple_struct")
}
fn deserialize_map<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_map")
}
fn deserialize_struct<V>(
mut self,
name: &'static str,
fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
trace!(
"deserializing struct {:?} {:?} (stack={:?})",
name,
fields,
self.stack
);
if self.saw_root {
let value = self.pop();
let name = unsafe { std::intrinsics::type_name::<V::Value>() };
trace!("Extracting {:?} for {:?}", value.val, name);
V::Value::extract(&value.val)
} else {
self.saw_root = true;
visitor.visit_seq(StructDeserializer::new(&mut self, fields))
}
}
fn deserialize_enum<V>(
self,
_name: &'static str,
_variants: &'static [&'static str],
_visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_enum")
}
fn deserialize_identifier<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_identifier")
}
fn deserialize_ignored_any<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!("deserialize_ignored_any")
}
}
struct StructDeserializer<'a, 'de: 'a> {
de: &'a mut ConfigDeserializer<'de>,
fields: &'static [&'static str],
}
impl<'a, 'de: 'a> StructDeserializer<'a, 'de> {
fn new(de: &'a mut ConfigDeserializer<'de>, fields: &'static [&'static str]) -> Self {
StructDeserializer {
de: de,
fields: fields,
}
}
}
impl<'a, 'de: 'a> de::SeqAccess<'de> for StructDeserializer<'a, 'de> {
type Error = ShellError;
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
where
T: de::DeserializeSeed<'de>,
{
if self.fields.len() == 0 {
return Ok(None);
}
trace!("Processing {}", self.fields[0]);
self.de.push(self.fields[0])?;
self.fields = &self.fields[1..];
seed.deserialize(&mut *self.de).map(Some)
}
fn size_hint(&self) -> Option<usize> {
return Some(self.fields.len());
}
}

View File

@ -9,7 +9,7 @@ use crate::parser::{registry, Span, Spanned, Unit};
use crate::prelude::*;
use derive_new::new;
use getset::Getters;
use serde_derive::{Deserialize, Serialize};
use serde::{Deserialize, Serialize};
use std::fmt;
crate use baseline_parse::{baseline_parse_single_token, baseline_parse_token_as_string};
@ -76,6 +76,7 @@ pub enum RawExpression {
Variable(Variable),
Binary(Box<Binary>),
Block(Vec<Expression>),
List(Vec<Expression>),
Path(Box<Path>),
#[allow(unused)]
@ -101,6 +102,7 @@ impl RawExpression {
RawExpression::Literal(literal) => literal.type_name(),
RawExpression::Synthetic(synthetic) => synthetic.type_name(),
RawExpression::Variable(..) => "variable",
RawExpression::List(..) => "list",
RawExpression::Binary(..) => "binary",
RawExpression::Block(..) => "block",
RawExpression::Path(..) => "path",
@ -170,6 +172,15 @@ impl ToDebug for Expression {
write!(f, "}}")
}
RawExpression::List(exprs) => {
write!(f, "[ ")?;
for expr in exprs {
write!(f, "{} ", expr.debug(source))?;
}
write!(f, "]")
}
RawExpression::Path(p) => write!(f, "{}", p.debug(source)),
RawExpression::Boolean(true) => write!(f, "$yes"),
RawExpression::Boolean(false) => write!(f, "$no"),

View File

@ -8,7 +8,7 @@ use crate::parser::{
use crate::{SpannedItem, Text};
use derive_new::new;
use log::trace;
use serde_derive::{Deserialize, Serialize};
use serde::{Deserialize, Serialize};
pub fn baseline_parse_tokens(
token_nodes: &mut TokensIterator<'_>,
@ -33,6 +33,7 @@ pub fn baseline_parse_tokens(
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
pub enum SyntaxType {
Any,
List,
Literal,
Variable,
Path,
@ -210,7 +211,14 @@ pub fn baseline_parse_delimited(
Ok(Spanned::from_item(expr, token.span()))
}
Delimiter::Paren => unimplemented!(),
Delimiter::Square => unimplemented!(),
Delimiter::Square => {
let children = token.children();
let exprs =
baseline_parse_tokens(&mut TokensIterator::new(children), registry, source)?;
let expr = hir::RawExpression::List(exprs);
Ok(expr.spanned(token.span()))
}
}
}

View File

@ -2,7 +2,7 @@ use crate::parser::{hir::Expression, Operator, Spanned};
use crate::prelude::*;
use derive_new::new;
use getset::Getters;
use serde_derive::{Deserialize, Serialize};
use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(

View File

@ -4,7 +4,7 @@ use crate::prelude::*;
use derive_new::new;
use indexmap::IndexMap;
use log::trace;
use serde_derive::{Deserialize, Serialize};
use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]

View File

@ -2,7 +2,7 @@ use crate::parser::{hir::Expression, Spanned};
use crate::prelude::*;
use derive_new::new;
use getset::Getters;
use serde_derive::{Deserialize, Serialize};
use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(

View File

@ -1,7 +1,7 @@
use crate::parser::Span;
use derive_new::new;
use getset::Getters;
use serde_derive::{Deserialize, Serialize};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)]
pub enum FlagKind {

View File

@ -1,5 +1,5 @@
use crate::prelude::*;
use serde_derive::{Deserialize, Serialize};
use serde::{Deserialize, Serialize};
use std::fmt;
use std::str::FromStr;

View File

@ -2,8 +2,8 @@ use crate::prelude::*;
use crate::Text;
use derive_new::new;
use getset::Getters;
use serde::Deserialize;
use serde::Serialize;
use serde_derive::Deserialize;
use uuid::Uuid;
#[derive(

View File

@ -1,6 +1,6 @@
use serde_derive::{Deserialize, Serialize};
use std::str::FromStr;
use crate::object::base::Value;
use serde::{Deserialize, Serialize};
use std::str::FromStr;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)]
pub enum Unit {
@ -46,7 +46,7 @@ impl FromStr for Unit {
type Err = ();
fn from_str(input: &str) -> Result<Self, <Self as std::str::FromStr>::Err> {
match input {
"B" | "b" => Ok(Unit::B),
"B" | "b" => Ok(Unit::B),
"KB" | "kb" | "Kb" | "K" | "k" => Ok(Unit::KB),
"MB" | "mb" | "Mb" => Ok(Unit::MB),
"GB" | "gb" | "Gb" => Ok(Unit::GB),

View File

@ -1,5 +1,5 @@
use crate::errors::{ArgumentError, ShellError};
use crate::parser::registry::{CommandConfig, CommandRegistry, NamedType, PositionalType};
use crate::parser::registry::{Signature, CommandRegistry, NamedType, PositionalType};
use crate::parser::{baseline_parse_tokens, CallNode, Span, Spanned};
use crate::parser::{
hir::{self, NamedArguments},
@ -9,7 +9,7 @@ use crate::Text;
use log::trace;
pub fn parse_command(
config: &CommandConfig,
config: &Signature,
registry: &CommandRegistry,
call: &Spanned<CallNode>,
source: &Text,
@ -62,7 +62,7 @@ fn parse_command_head(head: &TokenNode) -> Result<hir::Expression, ShellError> {
}
fn parse_command_tail(
config: &CommandConfig,
config: &Signature,
registry: &CommandRegistry,
tail: Option<Vec<TokenNode>>,
source: &Text,
@ -197,7 +197,7 @@ fn extract_switch(name: &str, tokens: &mut hir::TokensIterator<'_>, source: &Tex
}
fn extract_mandatory(
config: &CommandConfig,
config: &Signature,
name: &str,
tokens: &mut hir::TokensIterator<'a>,
source: &Text,

View File

@ -69,52 +69,76 @@ impl PositionalType {
}
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct CommandConfig {
#[derive(Debug, Serialize, Deserialize, Clone, new)]
pub struct Signature {
pub name: String,
#[new(default)]
pub positional: Vec<PositionalType>,
#[new(value = "false")]
pub rest_positional: bool,
#[new(default)]
pub named: IndexMap<String, NamedType>,
#[new(value = "false")]
pub is_filter: bool,
pub is_sink: bool,
}
impl CommandConfig {
pub fn new(name: impl Into<String>) -> CommandConfig {
CommandConfig {
name: name.into(),
positional: vec![],
rest_positional: false,
named: IndexMap::default(),
is_filter: false,
is_sink: false,
}
impl Signature {
pub fn build(name: impl Into<String>) -> Signature {
Signature::new(name.into())
}
pub fn required(mut self, name: impl Into<String>, ty: impl Into<SyntaxType>) -> CommandConfig {
pub fn required(mut self, name: impl Into<String>, ty: impl Into<SyntaxType>) -> Signature {
self.positional
.push(PositionalType::Mandatory(name.into(), ty.into()));
self
}
pub fn optional(mut self, name: impl Into<String>, ty: impl Into<SyntaxType>) -> CommandConfig {
pub fn optional(mut self, name: impl Into<String>, ty: impl Into<SyntaxType>) -> Signature {
self.positional
.push(PositionalType::Optional(name.into(), ty.into()));
self
}
pub fn named(mut self, name: impl Into<String>, ty: impl Into<NamedType>) -> CommandConfig {
self.named.insert(name.into(), ty.into());
pub fn named(mut self, name: impl Into<String>, ty: impl Into<SyntaxType>) -> Signature {
self.named
.insert(name.into(), NamedType::Optional(ty.into()));
self
}
pub fn sink(mut self) -> CommandConfig {
pub fn required_named(
mut self,
name: impl Into<String>,
ty: impl Into<SyntaxType>,
) -> Signature {
self.named
.insert(name.into(), NamedType::Mandatory(ty.into()));
self
}
pub fn switch(mut self, name: impl Into<String>) -> Signature {
self.named.insert(name.into(), NamedType::Switch);
self
}
pub fn sink(mut self) -> Signature {
self.is_sink = true;
self
}
pub fn filter(mut self) -> Signature {
self.is_filter = true;
self
}
pub fn rest(mut self) -> Signature {
self.rest_positional = true;
self
}
}
#[derive(Debug, Default, new, Serialize, Deserialize)]
@ -245,7 +269,7 @@ impl Iterator for PositionalIter<'a> {
}
}
impl CommandConfig {
impl Signature {
crate fn parse_args(
&self,
call: &Spanned<CallNode>,

View File

@ -1,9 +1,9 @@
use crate::{CallInfo, CommandConfig, ReturnValue, ShellError, Spanned, Value};
use crate::{CallInfo, Signature, ReturnValue, ShellError, Spanned, Value};
use serde::{Deserialize, Serialize};
use std::io;
pub trait Plugin {
fn config(&mut self) -> Result<CommandConfig, ShellError>;
fn config(&mut self) -> Result<Signature, ShellError>;
#[allow(unused)]
fn begin_filter(&mut self, call_info: CallInfo) -> Result<(), ShellError> {
Err(ShellError::string(

View File

@ -1,6 +1,6 @@
use indexmap::IndexMap;
use nu::{
serve_plugin, CallInfo, CommandConfig, Plugin, PositionalType, Primitive, ReturnSuccess,
serve_plugin, CallInfo, Signature, Plugin, PositionalType, Primitive, ReturnSuccess,
ReturnValue, ShellError, Spanned, Value,
};
@ -40,8 +40,8 @@ impl Add {
}
impl Plugin for Add {
fn config(&mut self) -> Result<CommandConfig, ShellError> {
Ok(CommandConfig {
fn config(&mut self) -> Result<Signature, ShellError> {
Ok(Signature {
name: "add".to_string(),
positional: vec![
PositionalType::mandatory_any("Field"),

View File

@ -2,7 +2,7 @@
use crossterm::{cursor, terminal, Attribute, RawScreen};
use indexmap::IndexMap;
use nu::{
serve_plugin, CallInfo, CommandConfig, NamedType, Plugin, ShellError, SpanSource, Spanned,
serve_plugin, CallInfo, Signature, NamedType, Plugin, ShellError, SpanSource, Spanned,
Value,
};
use pretty_hex::*;
@ -16,10 +16,10 @@ impl BinaryView {
}
impl Plugin for BinaryView {
fn config(&mut self) -> Result<CommandConfig, ShellError> {
fn config(&mut self) -> Result<Signature, ShellError> {
let mut named = IndexMap::new();
named.insert("lores".to_string(), NamedType::Switch);
Ok(CommandConfig {
Ok(Signature {
name: "binaryview".to_string(),
positional: vec![],
is_filter: false,

View File

@ -1,6 +1,6 @@
use indexmap::IndexMap;
use nu::{
serve_plugin, CallInfo, CommandConfig, Plugin, PositionalType, Primitive, ReturnSuccess,
serve_plugin, CallInfo, Signature, Plugin, PositionalType, Primitive, ReturnSuccess,
ReturnValue, ShellError, Spanned, Value,
};
@ -40,8 +40,8 @@ impl Edit {
}
impl Plugin for Edit {
fn config(&mut self) -> Result<CommandConfig, ShellError> {
Ok(CommandConfig {
fn config(&mut self) -> Result<Signature, ShellError> {
Ok(Signature {
name: "edit".to_string(),
positional: vec![
PositionalType::mandatory_any("Field"),

View File

@ -1,6 +1,6 @@
use indexmap::IndexMap;
use nu::{
serve_plugin, CallInfo, CommandConfig, NamedType, Plugin, PositionalType, Primitive,
serve_plugin, CallInfo, Signature, NamedType, Plugin, PositionalType, Primitive,
ReturnSuccess, ReturnValue, ShellError, Spanned, SpannedItem, Value,
};
@ -84,13 +84,13 @@ impl Inc {
}
impl Plugin for Inc {
fn config(&mut self) -> Result<CommandConfig, ShellError> {
fn config(&mut self) -> Result<Signature, ShellError> {
let mut named = IndexMap::new();
named.insert("major".to_string(), NamedType::Switch);
named.insert("minor".to_string(), NamedType::Switch);
named.insert("patch".to_string(), NamedType::Switch);
Ok(CommandConfig {
Ok(Signature {
name: "inc".to_string(),
positional: vec![PositionalType::optional_any("Field")],
is_filter: true,

View File

@ -1,6 +1,6 @@
use indexmap::IndexMap;
use nu::{
serve_plugin, CallInfo, CommandConfig, Plugin, Primitive, ReturnSuccess, ReturnValue,
serve_plugin, CallInfo, Signature, Plugin, Primitive, ReturnSuccess, ReturnValue,
ShellError, Spanned, Value,
};
@ -14,8 +14,8 @@ impl NewSkip {
}
impl Plugin for NewSkip {
fn config(&mut self) -> Result<CommandConfig, ShellError> {
Ok(CommandConfig {
fn config(&mut self) -> Result<Signature, ShellError> {
Ok(Signature {
name: "skip".to_string(),
positional: vec![],
is_filter: true,

View File

@ -1,6 +1,6 @@
use derive_new::new;
use indexmap::IndexMap;
use nu::{serve_plugin, CallInfo, CommandConfig, Plugin, ShellError, Spanned, Value};
use nu::{serve_plugin, CallInfo, Signature, Plugin, ShellError, Spanned, Value};
use ptree::item::StringItem;
use ptree::output::print_tree_with;
use ptree::print_config::PrintConfig;
@ -80,8 +80,8 @@ impl TreeView {
struct TreeViewer;
impl Plugin for TreeViewer {
fn config(&mut self) -> Result<CommandConfig, ShellError> {
Ok(CommandConfig {
fn config(&mut self) -> Result<Signature, ShellError> {
Ok(Signature {
name: "tree".to_string(),
positional: vec![],
is_filter: false,

View File

@ -34,20 +34,23 @@ macro_rules! trace_stream {
crate use crate::cli::MaybeOwned;
crate use crate::commands::command::{
Command, CommandAction, CommandArgs, ReturnSuccess, ReturnValue, Sink, SinkCommandArgs,
CommandAction, CommandArgs, ReturnSuccess, ReturnValue, RunnableContext,
};
crate use crate::context::{CommandRegistry, Context};
crate use crate::env::host::handle_unexpected;
crate use crate::env::{Environment, Host};
crate use crate::errors::ShellError;
crate use crate::object::base as value;
crate use crate::object::types::ExtractType;
crate use crate::object::{Primitive, Value};
crate use crate::parser::{Span, Spanned, SpannedItem};
crate use crate::parser::registry::Signature;
crate use crate::parser::{hir::SyntaxType, Span, Spanned, SpannedItem};
crate use crate::stream::{InputStream, OutputStream};
crate use crate::traits::{HasSpan, ToDebug};
crate use crate::Text;
crate use futures::stream::BoxStream;
crate use futures::{FutureExt, Stream, StreamExt};
crate use serde::{Deserialize, Serialize};
crate use std::collections::VecDeque;
crate use std::future::Future;
crate use std::sync::{Arc, Mutex};

View File

@ -46,12 +46,17 @@ pub struct OutputStream {
}
impl OutputStream {
#[allow(unused)]
pub fn empty() -> OutputStream {
let v: VecDeque<ReturnValue> = VecDeque::new();
v.into()
}
pub fn one(item: impl Into<ReturnValue>) -> OutputStream {
let v: VecDeque<ReturnValue> = VecDeque::new();
v.push_back(item.into());
v.into()
}
pub fn from_input(input: impl Stream<Item = Spanned<Value>> + Send + 'static) -> OutputStream {
OutputStream {
values: input.map(ReturnSuccess::value).boxed(),

View File

@ -19,13 +19,18 @@ impl AbsolutePath {
}
}
impl Div<&str> for AbsolutePath {
impl Div<&str> for &AbsolutePath {
type Output = AbsolutePath;
fn div(self, rhs: &str) -> Self::Output {
AbsolutePath {
inner: self.inner.join(rhs),
let parts = rhs.split("/");
let mut result = self.inner.clone();
for part in parts {
result = result.join(part);
}
AbsolutePath::new(result)
}
}
@ -51,12 +56,17 @@ impl RelativePath {
}
}
impl<T: AsRef<str>> Div<T> for RelativePath {
impl<T: AsRef<str>> Div<T> for &RelativePath {
type Output = RelativePath;
fn div(self, rhs: T) -> Self::Output {
RelativePath {
inner: self.inner.join(rhs.as_ref()),
let parts = rhs.as_ref().split("/");
let mut result = self.inner.clone();
for part in parts {
result = result.join(part);
}
RelativePath::new(result)
}
}

View File

@ -83,27 +83,32 @@ fn open_error_if_file_not_found() {
#[test]
fn save_can_write_out_csv() -> Result<(), std::io::Error> {
let (playground, tmp, dir) = h::setup_playground_for("save_test")?;
let (playground, tmp, _dir) = h::setup_playground_for("save_test")?;
let tmp = AbsolutePath::new(tmp);
let expected_file = tmp.as_ref().join("cargo_sample.csv");
let expected_file = tmp / "cargo_sample.csv";
let root = &AbsolutePath::new(std::env::current_dir()?);
let root = AbsolutePath::new(std::env::current_dir()?);
let path = root / "tests" / "fixtures" / "formats" / "cargo_sample.toml";
let path = root / "tests/fixtures/formats/cargo_sample.toml";
let command = format!(
"open {} | inc package.version --minor | get package | save {}/cargo_sample.csv",
"open {} | inc package.version --minor | get package | save {}",
path.as_ref().display(),
dir
"cargo_sample.csv"
);
nu!(_output, playground.path().display(), command);
for item in std::fs::read_dir(tmp.as_ref()) {
println!("item :: {:?}", item);
}
nu!(_output, tmp.as_ref().display(), command);
let actual = h::file_contents(&expected_file);
assert!(actual.contains("[list list],A shell for the GitHub era,2018,ISC,nu,0.2.0"));
drop(playground);
drop(tmp);
Ok(())
}
@ -113,8 +118,7 @@ fn rm_can_remove_a_file() -> Result<(), std::io::Error> {
let (_playground, tmp, _) = h::setup_playground_for("remove_file")?;
let file = AbsolutePath::new(&tmp) / "rm_test.txt";
// let file = tmp.path().join("rm_test.txt");
let file = &AbsolutePath::new(&tmp) / "rm_test.txt";
h::create_file_at(&file)?;

View File

@ -82,6 +82,8 @@ macro_rules! nu_error {
}
pub fn setup_playground_for(topic: &str) -> Result<(TempDir, TempDir, String), std::io::Error> {
let _ = pretty_env_logger::try_init();
let home = TempDir::new("nuplayground")?;
let child = TempDir::new_in(home.path(), topic)?;
let relative = child
@ -105,7 +107,10 @@ pub fn setup_playground_for(topic: &str) -> Result<(TempDir, TempDir, String), s
}
pub fn file_contents(full_path: impl AsRef<Path>) -> String {
let mut file = std::fs::File::open(full_path).expect("can not open file");
let full_path = full_path.as_ref();
let mut file = std::fs::File::open(full_path)
.expect(&format!("can not open file {}", &full_path.display()));
let mut contents = String::new();
file.read_to_string(&mut contents)
.expect("can not read file");