From 076fde16dd71259ee29703ef7fa3e4b25b741416 Mon Sep 17 00:00:00 2001 From: Jonathan Turner Date: Fri, 15 May 2020 20:18:24 -0700 Subject: [PATCH] Evaluation of command arguments (#1801) * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * Finish adding the baseline refactors for argument invocation * Finish cleanup and add test * Add missing plugin references --- Cargo.lock | 553 ++++++++++-------- Cargo.toml | 9 +- crates/nu-cli/Cargo.toml | 2 + crates/nu-cli/src/cli.rs | 1 - crates/nu-cli/src/commands.rs | 2 - crates/nu-cli/src/commands/alias.rs | 14 +- crates/nu-cli/src/commands/append.rs | 24 +- crates/nu-cli/src/commands/cal.rs | 85 +-- crates/nu-cli/src/commands/calc.rs | 28 +- crates/nu-cli/src/commands/cd.rs | 18 +- .../nu-cli/src/commands/classified/block.rs | 2 +- crates/nu-cli/src/commands/classified/expr.rs | 4 +- .../src/commands/classified/external.rs | 6 +- crates/nu-cli/src/commands/clip.rs | 11 +- crates/nu-cli/src/commands/command.rs | 159 ++--- crates/nu-cli/src/commands/compact.rs | 52 +- crates/nu-cli/src/commands/config.rs | 29 +- crates/nu-cli/src/commands/count.rs | 13 +- crates/nu-cli/src/commands/cp.rs | 19 +- crates/nu-cli/src/commands/date.rs | 28 +- crates/nu-cli/src/commands/debug.rs | 25 +- crates/nu-cli/src/commands/default.rs | 26 +- crates/nu-cli/src/commands/drop.rs | 8 +- crates/nu-cli/src/commands/du.rs | 115 ++-- crates/nu-cli/src/commands/each.rs | 23 +- crates/nu-cli/src/commands/echo.rs | 52 +- crates/nu-cli/src/commands/enter.rs | 85 ++- crates/nu-cli/src/commands/evaluate_by.rs | 9 +- crates/nu-cli/src/commands/exit.rs | 17 +- crates/nu-cli/src/commands/first.rs | 32 +- crates/nu-cli/src/commands/format.rs | 19 +- crates/nu-cli/src/commands/from.rs | 12 +- crates/nu-cli/src/commands/from_bson.rs | 9 +- crates/nu-cli/src/commands/from_csv.rs | 62 +- .../src/commands/from_delimited_data.rs | 3 +- crates/nu-cli/src/commands/from_eml.rs | 13 +- crates/nu-cli/src/commands/from_ics.rs | 9 +- crates/nu-cli/src/commands/from_ini.rs | 8 +- crates/nu-cli/src/commands/from_json.rs | 11 +- crates/nu-cli/src/commands/from_ods.rs | 14 +- crates/nu-cli/src/commands/from_sqlite.rs | 9 +- crates/nu-cli/src/commands/from_ssv.rs | 14 +- crates/nu-cli/src/commands/from_toml.rs | 9 +- crates/nu-cli/src/commands/from_tsv.rs | 20 +- crates/nu-cli/src/commands/from_url.rs | 9 +- crates/nu-cli/src/commands/from_vcf.rs | 9 +- crates/nu-cli/src/commands/from_xlsx.rs | 15 +- crates/nu-cli/src/commands/from_xml.rs | 9 +- crates/nu-cli/src/commands/from_yaml.rs | 9 +- crates/nu-cli/src/commands/get.rs | 52 +- crates/nu-cli/src/commands/group_by.rs | 10 +- crates/nu-cli/src/commands/group_by_date.rs | 12 +- crates/nu-cli/src/commands/headers.rs | 10 +- crates/nu-cli/src/commands/help.rs | 134 ++--- crates/nu-cli/src/commands/histogram.rs | 9 +- crates/nu-cli/src/commands/history.rs | 11 +- crates/nu-cli/src/commands/insert.rs | 10 +- crates/nu-cli/src/commands/is_empty.rs | 44 +- crates/nu-cli/src/commands/keep.rs | 29 +- crates/nu-cli/src/commands/keep_until.rs | 115 ++-- crates/nu-cli/src/commands/keep_while.rs | 115 ++-- crates/nu-cli/src/commands/kill.rs | 92 +-- crates/nu-cli/src/commands/last.rs | 8 +- crates/nu-cli/src/commands/lines.rs | 10 +- crates/nu-cli/src/commands/ls.rs | 19 +- crates/nu-cli/src/commands/map_max_by.rs | 10 +- crates/nu-cli/src/commands/merge.rs | 24 +- crates/nu-cli/src/commands/mkdir.rs | 19 +- crates/nu-cli/src/commands/mv.rs | 19 +- crates/nu-cli/src/commands/nth.rs | 29 +- crates/nu-cli/src/commands/open.rs | 12 +- crates/nu-cli/src/commands/parse.rs | 167 ------ crates/nu-cli/src/commands/pivot.rs | 19 +- crates/nu-cli/src/commands/plugin.rs | 314 +++++----- crates/nu-cli/src/commands/prepend.rs | 22 +- crates/nu-cli/src/commands/pwd.rs | 16 +- crates/nu-cli/src/commands/range.rs | 30 +- crates/nu-cli/src/commands/reduce_by.rs | 9 +- crates/nu-cli/src/commands/reject.rs | 37 +- crates/nu-cli/src/commands/rename.rs | 34 +- crates/nu-cli/src/commands/reverse.rs | 21 +- crates/nu-cli/src/commands/rm.rs | 18 +- crates/nu-cli/src/commands/run_alias.rs | 2 +- crates/nu-cli/src/commands/run_external.rs | 11 +- crates/nu-cli/src/commands/save.rs | 34 +- crates/nu-cli/src/commands/select.rs | 52 +- crates/nu-cli/src/commands/shuffle.rs | 9 +- crates/nu-cli/src/commands/skip.rs | 29 +- crates/nu-cli/src/commands/skip_until.rs | 118 ++-- crates/nu-cli/src/commands/skip_while.rs | 118 ++-- crates/nu-cli/src/commands/sort_by.rs | 17 +- crates/nu-cli/src/commands/split_by.rs | 10 +- crates/nu-cli/src/commands/split_column.rs | 34 +- crates/nu-cli/src/commands/split_row.rs | 30 +- crates/nu-cli/src/commands/t_sort_by.rs | 20 +- crates/nu-cli/src/commands/table.rs | 7 +- crates/nu-cli/src/commands/to.rs | 13 +- crates/nu-cli/src/commands/to_bson.rs | 9 +- crates/nu-cli/src/commands/to_csv.rs | 62 +- .../nu-cli/src/commands/to_delimited_data.rs | 3 +- crates/nu-cli/src/commands/to_html.rs | 6 +- crates/nu-cli/src/commands/to_json.rs | 7 +- crates/nu-cli/src/commands/to_md.rs | 6 +- crates/nu-cli/src/commands/to_sqlite.rs | 5 +- crates/nu-cli/src/commands/to_toml.rs | 7 +- crates/nu-cli/src/commands/to_tsv.rs | 26 +- crates/nu-cli/src/commands/to_url.rs | 9 +- crates/nu-cli/src/commands/to_yaml.rs | 9 +- crates/nu-cli/src/commands/touch.rs | 26 +- crates/nu-cli/src/commands/uniq.rs | 11 +- crates/nu-cli/src/commands/update.rs | 149 +++-- crates/nu-cli/src/commands/version.rs | 5 +- crates/nu-cli/src/commands/what.rs | 9 +- crates/nu-cli/src/commands/where_.rs | 73 +-- crates/nu-cli/src/commands/which_.rs | 24 +- crates/nu-cli/src/commands/with_env.rs | 25 +- crates/nu-cli/src/commands/wrap.rs | 11 +- crates/nu-cli/src/context.rs | 6 +- crates/nu-cli/src/evaluate/evaluate_args.rs | 67 ++- crates/nu-cli/src/evaluate/evaluator.rs | 49 +- crates/nu-cli/src/prelude.rs | 2 +- crates/nu-cli/src/shell/filesystem_shell.rs | 8 +- crates/nu-cli/src/shell/help_shell.rs | 7 +- crates/nu-cli/src/shell/shell.rs | 7 +- crates/nu-cli/src/shell/shell_manager.rs | 45 +- crates/nu-cli/src/shell/value_shell.rs | 4 +- crates/nu-cli/src/stream/input.rs | 6 + crates/nu-cli/tests/commands/cal.rs | 2 +- crates/nu-parser/src/parse.rs | 60 +- crates/nu-parser/src/shapes.rs | 1 + crates/nu-protocol/src/hir.rs | 14 + crates/nu_plugin_parse/Cargo.toml | 21 + crates/nu_plugin_parse/build.rs | 3 + crates/nu_plugin_parse/src/lib.rs | 4 + crates/nu_plugin_parse/src/main.rs | 7 + crates/nu_plugin_parse/src/nu/mod.rs | 153 +++++ crates/nu_plugin_parse/src/parse.rs | 19 + src/plugins/nu_plugin_stable_parse.rs | 7 + tests/shell/pipeline/commands/internal.rs | 12 + 139 files changed, 2496 insertions(+), 2188 deletions(-) delete mode 100644 crates/nu-cli/src/commands/parse.rs create mode 100644 crates/nu_plugin_parse/Cargo.toml create mode 100644 crates/nu_plugin_parse/build.rs create mode 100644 crates/nu_plugin_parse/src/lib.rs create mode 100644 crates/nu_plugin_parse/src/main.rs create mode 100644 crates/nu_plugin_parse/src/nu/mod.rs create mode 100644 crates/nu_plugin_parse/src/parse.rs create mode 100644 src/plugins/nu_plugin_stable_parse.rs diff --git a/Cargo.lock b/Cargo.lock index 12f7c263f..36790d68a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,14 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "addr2line" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456d75cbb82da1ad150c8a9d97285ffcd21c9931dcb11e995903e7d75141b38b" +dependencies = [ + "gimli", +] + [[package]] name = "adler32" version = "1.0.4" @@ -34,10 +43,22 @@ dependencies = [ ] [[package]] -name = "arc-swap" -version = "0.4.5" +name = "app_dirs" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d663a8e9a99154b5fb793032533f6328da35e23aac63d5c152279aa8ba356825" +checksum = "e73a24bad9bd6a94d6395382a6c69fe071708ae4409f763c5475e14ee896313d" +dependencies = [ + "ole32-sys", + "shell32-sys", + "winapi 0.2.8", + "xdg", +] + +[[package]] +name = "arc-swap" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b585a98a234c46fc563103e9278c9391fde1f4e6850334da895d27edb9580f62" [[package]] name = "arrayref" @@ -70,6 +91,17 @@ dependencies = [ "syn", ] +[[package]] +name = "async-recursion" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5444eec77a9ec2bfe4524139e09195862e981400c4358d3b760cae634e4c4ee" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "async-std" version = "1.5.0" @@ -137,7 +169,7 @@ dependencies = [ "log", "native-tls", "openssl", - "serde 1.0.106", + "serde 1.0.110", "serde_urlencoded", "url", ] @@ -161,26 +193,17 @@ checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" [[package]] name = "backtrace" -version = "0.3.46" +version = "0.3.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e692897359247cc6bb902933361652380af0f1b7651ae5c5013407f30e109e" +checksum = "0df2f85c8a2abbe3b7d7e748052fdd9b76a0458fdeb16ad4223f5eca78c7c130" dependencies = [ - "backtrace-sys", + "addr2line", "cfg-if", "libc", + "object", "rustc-demangle", ] -[[package]] -name = "backtrace-sys" -version = "0.1.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7de8aba10a69c8e8d7622c5710229485ec32e9d55fdad160ea559c086fdcd118" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "base64" version = "0.10.1" @@ -198,9 +221,9 @@ checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" [[package]] name = "base64" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d5ca2cd0adc3f48f9e9ea5a6bbdf9ccc0bfade884847e484d452414c7ccffb3" +checksum = "53d1ccbaf7d9ec9537465a97bf19edc1a4e158ecb49fc16178202238c569cc42" [[package]] name = "battery" @@ -221,14 +244,14 @@ dependencies = [ [[package]] name = "bigdecimal" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "460825c9e21708024d67c07057cd5560e5acdccac85de0de624a81d3de51bacb" +checksum = "1374191e2dd25f9ae02e3aa95041ed5d747fc77b3c102b49fe2dd9a8117a6244" dependencies = [ "num-bigint", "num-integer", "num-traits 0.2.11", - "serde 1.0.106", + "serde 1.0.110", ] [[package]] @@ -238,23 +261,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5753e2a71534719bf3f4e57006c3a4f0d2c672a4b676eec84161f763eca87dbf" dependencies = [ "byteorder", - "serde 1.0.106", + "serde 1.0.110", ] [[package]] name = "bit-set" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e84c238982c4b1e1ee668d136c510c67a13465279c0cb367ea6baf6310620a80" +checksum = "6e11e16035ea35e4e5997b393eacbf6f63983188f7a2ad25bfb13465f5ad59de" dependencies = [ "bit-vec", ] [[package]] name = "bit-vec" -version = "0.5.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f59bbe95d4e52a6398ec21238d31577f2b28a9d86807f06ca59d191d8440d0bb" +checksum = "5f0dc55f2d8a1a85650ac47858bb001b4c0dd73d79e3c455a842925e68d29cd3" [[package]] name = "bitflags" @@ -290,31 +313,31 @@ dependencies = [ "decimal", "hex 0.3.2", "libc", - "linked-hash-map 0.5.2", + "linked-hash-map 0.5.3", "md5", "rand", - "serde 1.0.106", + "serde 1.0.110", "serde_json", "time", ] [[package]] name = "bstr" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2889e6d50f394968c8bf4240dc3f2a7eb4680844d27308f798229ac9d4725f41" +checksum = "31accafdb70df7871592c058eca3985b71104e15ac32f64706022c58867da931" dependencies = [ "lazy_static 1.4.0", "memchr", "regex-automata", - "serde 1.0.106", + "serde 1.0.110", ] [[package]] name = "bumpalo" -version = "3.2.1" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12ae9db68ad7fac5fe51304d20f016c911539251075a214f8e663babefa35187" +checksum = "5356f1d23ee24a1f785a56d1d1a5f0fd5b0f6a0c0fb2412ce11da71649ab78f6" [[package]] name = "byte-unit" @@ -355,15 +378,15 @@ dependencies = [ "encoding_rs", "log", "quick-xml", - "serde 1.0.106", + "serde 1.0.110", "zip", ] [[package]] name = "cc" -version = "1.0.50" +version = "1.0.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd" +checksum = "404b1fe4f65288577753b17e3b36a04596ee784493ec249bf81c7f2d2acd751c" dependencies = [ "jobserver", ] @@ -382,15 +405,15 @@ checksum = "80094f509cf8b5ae86a4966a39b3ff66cd7e2a3e594accec3743ff3fabeab5b2" dependencies = [ "num-integer", "num-traits 0.2.11", - "serde 1.0.106", + "serde 1.0.110", "time", ] [[package]] name = "clap" -version = "2.33.0" +version = "2.33.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" +checksum = "bdfa80d47f954d53a35a64987ca1422f495b8d6483c0fe9f7117b36c2a792129" dependencies = [ "ansi_term 0.11.0", "atty", @@ -450,7 +473,7 @@ dependencies = [ "lazy_static 1.4.0", "nom 4.2.3", "rust-ini", - "serde 1.0.106", + "serde 1.0.110", "serde-hjson 0.8.2", "serde_json", "toml 0.4.10", @@ -582,9 +605,9 @@ dependencies = [ [[package]] name = "crossterm" -version = "0.17.3" +version = "0.17.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccdd8ef63a44e821956c6a276eca0faaa889d6a067dfcdbd5bfe85dce3a1d250" +checksum = "2a880035bfe4707e344da9acf50cc94d003fe337f50afd94c8722c1bb4e0a933" dependencies = [ "bitflags", "crossterm_winapi", @@ -615,7 +638,7 @@ dependencies = [ "csv-core", "itoa", "ryu", - "serde 1.0.106", + "serde 1.0.110", ] [[package]] @@ -629,9 +652,9 @@ dependencies = [ [[package]] name = "ctor" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47c5e5ac752e18207b12e16b10631ae5f7f68f8805f335f9b817ead83d9ffce1" +checksum = "cf6b25ee9ac1995c54d7adb2eff8cfffb7260bc774fb63c601ec65467f43cd9d" dependencies = [ "quote", "syn", @@ -649,9 +672,9 @@ dependencies = [ [[package]] name = "curl" -version = "0.4.28" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eda1c0c03cacf3365d84818a40293f0e3f3953db8759c9c565a3b434edf0b52e" +checksum = "762e34611d2d5233a506a79072be944fddd057db2f18e04c0d6fa79e3fd466fd" dependencies = [ "curl-sys", "libc", @@ -664,9 +687,9 @@ dependencies = [ [[package]] name = "curl-sys" -version = "0.4.30+curl-7.69.1" +version = "0.4.31+curl-7.70.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "923b38e423a8f47a4058e96f2a1fa2865a6231097ee860debd678d244277d50c" +checksum = "dcd62757cc4f5ab9404bc6ca9f0ae447e729a1403948ce5106bd588ceac6a3b0" dependencies = [ "cc", "libc", @@ -824,9 +847,9 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "encoding_rs" -version = "0.8.22" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd8d03faa7fe0c1431609dfad7bbe827af30f82e1e2ae6f7ee4fca6bd764bc28" +checksum = "e8ac63f94732332f44fe654443c46f6375d1939684c17b0afb6cb56b0456e171" dependencies = [ "cfg-if", ] @@ -838,7 +861,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" dependencies = [ "atty", - "humantime 1.3.0", + "humantime", "log", "regex", "termcolor", @@ -850,14 +873,14 @@ version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d88b6d1705e16a4d62e05ea61cc0496c2bd190f4fa8e5c1f11ce747be6bcf3d1" dependencies = [ - "serde 1.0.106", + "serde 1.0.110", ] [[package]] name = "failure" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8529c2421efa3066a5cbd8063d2244603824daccb6936b079010bb2aa89464b" +checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" dependencies = [ "backtrace", "failure_derive", @@ -865,9 +888,9 @@ dependencies = [ [[package]] name = "failure_derive" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "030a733c8287d6213886dd487564ff5c8f6aae10278b3588ed177f9d18f8d231" +checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" dependencies = [ "proc-macro2", "quote", @@ -889,9 +912,9 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" [[package]] name = "fancy-regex" -version = "0.3.3" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0e2de1b89ad299d536b7cefc5d177f5c005957fa2266ce58eca4d189e74bff5" +checksum = "ae91abf6555234338687bb47913978d275539235fcb77ba9863b779090b42b14" dependencies = [ "bit-set", "regex", @@ -926,9 +949,9 @@ dependencies = [ [[package]] name = "fnv" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "foreign-types" @@ -969,9 +992,9 @@ checksum = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" [[package]] name = "futures" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c329ae8753502fb44ae4fc2b622fa2a94652c41e795143765ba0927f92ab780" +checksum = "1e05b85ec287aac0dc34db7d4a569323df697f9c55b99b15d6b4ef8cde49f613" dependencies = [ "futures-channel", "futures-core", @@ -984,9 +1007,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0c77d04ce8edd9cb903932b608268b3fffec4163dc053b3b402bf47eac1f1a8" +checksum = "f366ad74c28cca6ba456d95e6422883cfb4b252a83bed929c83abfdbbf2967d5" dependencies = [ "futures-core", "futures-sink", @@ -1004,9 +1027,9 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f25592f769825e89b92358db00d26f965761e094951ac44d3663ef25b7ac464a" +checksum = "59f5fff90fd5d971f936ad674802482ba441b6f09ba5e15fd8b39145582ca399" [[package]] name = "futures-core-preview" @@ -1016,9 +1039,9 @@ checksum = "b35b6263fb1ef523c3056565fa67b1d16f0a8604ff12b11b08c25f28a734c60a" [[package]] name = "futures-executor" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f674f3e1bcb15b37284a90cedf55afdba482ab061c407a9c0ebbd0f3109741ba" +checksum = "10d6bb888be1153d3abeb9006b11b02cf5e9b209fda28693c31ae1e4e012e314" dependencies = [ "futures-core", "futures-task", @@ -1038,9 +1061,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a638959aa96152c7a4cddf50fcb1e3fede0583b27157c26e67d6f99904090dc6" +checksum = "de27142b013a8e869c14957e6d2edeef89e97c289e69d042ee3a49acd8b51789" [[package]] name = "futures-io-preview" @@ -1050,9 +1073,9 @@ checksum = "f4914ae450db1921a56c91bde97a27846287d062087d4a652efc09bb3a01ebda" [[package]] name = "futures-macro" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a5081aa3de1f7542a794a397cde100ed903b0630152d0973479018fd85423a7" +checksum = "d0b5a30a4328ab5473878237c447333c093297bded83a4983d10f4deea240d39" dependencies = [ "proc-macro-hack", "proc-macro2", @@ -1076,9 +1099,9 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3466821b4bc114d95b087b850a724c6f83115e929bc88f1fa98a3304a944c8a6" +checksum = "3f2032893cb734c7a05d85ce0cc8b8c4075278e93b24b66f9de99d6eb0fa8acc" [[package]] name = "futures-sink-preview" @@ -1088,9 +1111,12 @@ checksum = "86f148ef6b69f75bb610d4f9a2336d4fc88c4b5b67129d1a340dd0fd362efeec" [[package]] name = "futures-task" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b0a34e53cf6cdcd0178aa573aed466b646eb3db769570841fda0c7ede375a27" +checksum = "bdb66b5f09e22019b1ab0830f7785bcea8e7a42148683f99214f73f8ec21a626" +dependencies = [ + "once_cell", +] [[package]] name = "futures-timer" @@ -1106,9 +1132,9 @@ checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" [[package]] name = "futures-util" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22766cf25d64306bedf0384da004d05c9974ab104fcc4528f1236181c18004c5" +checksum = "8764574ff08b701a084482c3c7031349104b07ac897393010494beaa18ce32c6" dependencies = [ "futures 0.1.29", "futures-channel", @@ -1118,6 +1144,7 @@ dependencies = [ "futures-sink", "futures-task", "memchr", + "pin-project", "pin-utils", "proc-macro-hack", "proc-macro-nested", @@ -1149,7 +1176,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe8859feb7140742ed1a2a85a07941100ad2b5f98a421b353931d718a34144d1" dependencies = [ "bytes 0.5.4", - "futures 0.3.4", + "futures 0.3.5", "memchr", "pin-project", ] @@ -1177,9 +1204,9 @@ dependencies = [ [[package]] name = "getset" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f62a139c59ae846c3964c392f12aac68f1997d1a40e9d3b40a89a4ab553e04a0" +checksum = "24b328c01a4d71d2d8173daa93562a73ab0fe85616876f02500f53d82948c504" dependencies = [ "proc-macro-error", "proc-macro2", @@ -1199,10 +1226,16 @@ dependencies = [ ] [[package]] -name = "git2" -version = "0.13.2" +name = "gimli" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cfb93ca10f2934069c3aaafb753fbe0663f08ee009a01b6d62e062391447b15" +checksum = "bcc8e0c9bce37868955864dbecd2b1ab2bdf967e6f28066d65aaac620444b65c" + +[[package]] +name = "git2" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1e02a51cd90229028c9bd8be0a0364f85b6b3199cccaa0ef39005ddbd5ac165" dependencies = [ "bitflags", "libc", @@ -1393,9 +1426,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d737e0f947a1864e93d33fdef4af8445a00d1ed8dc0c8ddb73139ea6abf15" +checksum = "61565ff7aaace3525556587bd2dc31d4a07071957be715e63ce7b1eccf51a8f4" dependencies = [ "libc", ] @@ -1449,12 +1482,6 @@ dependencies = [ "quick-error", ] -[[package]] -name = "humantime" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9b6c53306532d3c8e8087b44e6580e10db51a023cf9b433cea2ac38066b92da" - [[package]] name = "ical" version = "0.6.0" @@ -1472,7 +1499,7 @@ checksum = "ea685d38f1becb4f0a04e6cbff9256c6c2cd5e5905563b251401d1c13d12c654" dependencies = [ "async-std", "cfg-if", - "futures 0.3.4", + "futures 0.3.5", "thiserror", ] @@ -1508,7 +1535,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "076f042c5b7b98f31d205f1249267e12a6518c1481e9dae9764af19b707d2292" dependencies = [ "autocfg", - "serde 1.0.106", + "serde 1.0.110", ] [[package]] @@ -1618,18 +1645,18 @@ dependencies = [ [[package]] name = "jpeg-decoder" -version = "0.1.18" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0256f0aec7352539102a9efbcb75543227b7ab1117e0f95450023af730128451" +checksum = "5b47b4c4e017b01abdc5bcc126d2d1002e5a75bbe3ce73f9f4f311a916363704" dependencies = [ "byteorder", ] [[package]] name = "js-sys" -version = "0.3.37" +version = "0.3.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a27d435371a2fa5b6d2b028a74bbdb1234f308da363226a2854ca3ff8ba7055" +checksum = "fa5a448de267e7358beaf4a5d849518fe9a0c13fce7afd44b06e68550e5562a7" dependencies = [ "wasm-bindgen", ] @@ -1646,9 +1673,9 @@ dependencies = [ [[package]] name = "kv-log-macro" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c54d9f465d530a752e6ebdc217e081a7a614b48cb200f6f0aee21ba6bc9aabb" +checksum = "2a2d3beed37e5483887d81eb39de6de03a8346531410e1306ca48a9a89bd3a51" dependencies = [ "log", ] @@ -1663,7 +1690,7 @@ dependencies = [ "itertools 0.7.11", "log", "render-tree", - "serde 1.0.106", + "serde 1.0.110", "serde_derive", "termcolor", ] @@ -1701,15 +1728,15 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.69" +version = "0.2.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99e85c08494b21a9054e7fe1374a732aeadaff3980b6990b94bfd3a70f690005" +checksum = "3baa92041a6fec78c687fa0cc2b3fae8884f743d672cf551bed1d6dac6988d0f" [[package]] name = "libgit2-sys" -version = "0.12.3+1.0.0" +version = "0.12.5+1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7637dc15e7f05a16011723e0448655081fc01a374bcd368e2c9b9c7f5c5ab3ea" +checksum = "3eadeec65514971355bf7134967a543f71372f35b53ac6c7143e7bd157f07535" dependencies = [ "cc", "libc", @@ -1771,9 +1798,9 @@ dependencies = [ [[package]] name = "linked-hash-map" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" +checksum = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a" [[package]] name = "lock_api" @@ -1799,7 +1826,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" dependencies = [ - "linked-hash-map 0.5.2", + "linked-hash-map 0.5.3", ] [[package]] @@ -1905,9 +1932,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.6.21" +version = "0.6.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f" +checksum = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430" dependencies = [ "cfg-if", "fuchsia-zircon", @@ -1924,9 +1951,9 @@ dependencies = [ [[package]] name = "mio-uds" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" +checksum = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0" dependencies = [ "iovec", "libc", @@ -1981,16 +2008,16 @@ dependencies = [ "bincode", "cfg-if", "log", - "serde 1.0.106", + "serde 1.0.110", "serde_derive", "wasm-bindgen", ] [[package]] name = "net2" -version = "0.2.33" +version = "0.2.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" +checksum = "2ba7c918ac76704fb42afcbbb43891e72731f3dcca3bef2a19786297baf14af7" dependencies = [ "cfg-if", "libc", @@ -2058,9 +2085,9 @@ dependencies = [ [[package]] name = "ntapi" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26e041cd983acbc087e30fcba770380cfa352d0e392e175b2344ebaf7ea0602" +checksum = "7a31937dea023539c72ddae0e3571deadc1414b300483fa7aaec176168cfa9d2" dependencies = [ "winapi 0.3.8", ] @@ -2073,7 +2100,7 @@ dependencies = [ "crossterm", "ctrlc", "dunce", - "futures 0.3.4", + "futures 0.3.5", "log", "nu-build", "nu-cli", @@ -2089,6 +2116,7 @@ dependencies = [ "nu_plugin_fetch", "nu_plugin_inc", "nu_plugin_match", + "nu_plugin_parse", "nu_plugin_post", "nu_plugin_ps", "nu_plugin_start", @@ -2098,7 +2126,7 @@ dependencies = [ "nu_plugin_tree", "pretty_env_logger", "semver", - "serde 1.0.106", + "serde 1.0.110", "syntect", "toml 0.5.6", "url", @@ -2109,7 +2137,7 @@ name = "nu-build" version = "0.14.1" dependencies = [ "lazy_static 1.4.0", - "serde 1.0.106", + "serde 1.0.110", "serde_json", "toml 0.5.6", ] @@ -2119,8 +2147,10 @@ name = "nu-cli" version = "0.14.1" dependencies = [ "ansi_term 0.12.1", + "app_dirs", + "async-recursion", "async-stream", - "base64 0.12.0", + "base64 0.12.1", "bigdecimal", "bson", "byte-unit", @@ -2138,7 +2168,7 @@ dependencies = [ "dunce", "eml-parser", "filesize", - "futures 0.3.4", + "futures 0.3.5", "futures-util", "futures_codec", "getset", @@ -2179,7 +2209,7 @@ dependencies = [ "roxmltree", "rusqlite", "rustyline", - "serde 1.0.106", + "serde 1.0.110", "serde-hjson 0.9.1", "serde_bytes", "serde_ini", @@ -2216,7 +2246,7 @@ dependencies = [ "nu-source", "num-bigint", "num-traits 0.2.11", - "serde 1.0.106", + "serde 1.0.110", "serde_json", "serde_yaml", "toml 0.5.6", @@ -2237,7 +2267,7 @@ dependencies = [ "num-bigint", "num-traits 0.2.11", "parking_lot", - "serde 1.0.106", + "serde 1.0.110", "shellexpand", ] @@ -2252,7 +2282,7 @@ dependencies = [ "nu-source", "nu-value-ext", "num-bigint", - "serde 1.0.106", + "serde 1.0.110", "serde_json", ] @@ -2276,7 +2306,7 @@ dependencies = [ "num-bigint", "num-traits 0.2.11", "query_interface", - "serde 1.0.106", + "serde 1.0.110", "serde_bytes", "serde_json", "serde_yaml", @@ -2293,7 +2323,7 @@ dependencies = [ "language-reporting", "nu-build", "pretty", - "serde 1.0.106", + "serde 1.0.110", "termcolor", ] @@ -2359,7 +2389,7 @@ dependencies = [ name = "nu_plugin_fetch" version = "0.14.1" dependencies = [ - "futures 0.3.4", + "futures 0.3.5", "nu-build", "nu-errors", "nu-plugin", @@ -2386,7 +2416,20 @@ dependencies = [ name = "nu_plugin_match" version = "0.14.1" dependencies = [ - "futures 0.3.4", + "futures 0.3.5", + "nu-build", + "nu-errors", + "nu-plugin", + "nu-protocol", + "nu-source", + "regex", +] + +[[package]] +name = "nu_plugin_parse" +version = "0.14.1" +dependencies = [ + "futures 0.3.5", "nu-build", "nu-errors", "nu-plugin", @@ -2399,8 +2442,8 @@ dependencies = [ name = "nu_plugin_post" version = "0.14.1" dependencies = [ - "base64 0.12.0", - "futures 0.3.4", + "base64 0.12.1", + "futures 0.3.5", "nu-build", "nu-errors", "nu-plugin", @@ -2416,7 +2459,7 @@ dependencies = [ name = "nu_plugin_ps" version = "0.14.1" dependencies = [ - "futures 0.3.4", + "futures 0.3.5", "futures-timer 3.0.2", "heim", "nu-build", @@ -2459,7 +2502,7 @@ name = "nu_plugin_sys" version = "0.14.1" dependencies = [ "battery", - "futures 0.3.4", + "futures 0.3.5", "futures-util", "heim", "nu-build", @@ -2506,7 +2549,7 @@ dependencies = [ "autocfg", "num-integer", "num-traits 0.2.11", - "serde 1.0.106", + "serde 1.0.110", ] [[package]] @@ -2599,10 +2642,26 @@ dependencies = [ ] [[package]] -name = "once_cell" -version = "1.3.1" +name = "object" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c601810575c99596d4afc46f78a678c80105117c379eb3650cf99b8a21ce5b" +checksum = "9cbca9424c482ee628fa549d9c812e2cd22f1180b9222c9200fdfa6eb31aecb2" + +[[package]] +name = "ole32-sys" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d2c49021782e5233cd243168edfa8037574afed4eba4bbaf538b3d8d1789d8c" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + +[[package]] +name = "once_cell" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b631f7e854af39a1739f401cf34a8a013dfe09eac4fa4dba91e9768bd28168d" [[package]] name = "open" @@ -2635,9 +2694,9 @@ checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" [[package]] name = "openssl-sys" -version = "0.9.55" +version = "0.9.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7717097d810a0f2e2323f9e5d11e71608355e24828410b55b9d4f18aa5f9a5d8" +checksum = "f02309a7f127000ed50594f0b50ecc69e7c654e16d41b4e8156d1b3df8e0b52e" dependencies = [ "autocfg", "cc", @@ -2663,12 +2722,12 @@ checksum = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063" [[package]] name = "os_info" -version = "2.0.2" +version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ecb53e7b83e5016bf4ac041e15e02b0d240cb27072b19b651b0b4d8cd6bbda9" +checksum = "ae61f9dcacbe39e64641baaff75d97d61a0e7409a60dc6c7fc83691511afb3fe" dependencies = [ "log", - "serde 1.0.106", + "serde 1.0.110", "winapi 0.3.8", ] @@ -2684,9 +2743,9 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e136c1904604defe99ce5fd71a28d473fa60a12255d511aa78a9ddf11237aeb" +checksum = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3" dependencies = [ "cfg-if", "cloudabi", @@ -2720,18 +2779,18 @@ dependencies = [ [[package]] name = "pin-project" -version = "0.4.9" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f6a7f5eee6292c559c793430c55c00aea9d3b3d1905e855806ca4d7253426a2" +checksum = "81d480cb4e89522ccda96d0eed9af94180b7a5f93fb28f66e1fd7d68431663d1" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "0.4.9" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8988430ce790d8682672117bc06dda364c0be32d3abd738234f19f3240bad99a" +checksum = "a82996f11efccb19b685b14b5df818de31c1edcee3daa256ab5775dd98e72feb" dependencies = [ "proc-macro2", "quote", @@ -2740,15 +2799,15 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "237844750cfbb86f67afe27eee600dfbbcb6188d734139b534cbfbf4f96792ae" +checksum = "f7505eeebd78492e0f6108f7171c4948dbb120ee8119d9d77d0afa5469bef67f" [[package]] name = "pin-utils" -version = "0.1.0-alpha.4" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" @@ -2764,15 +2823,15 @@ checksum = "feb3b2b1033b8a60b4da6ee470325f887758c95d5320f52f9ce0df055a55940e" [[package]] name = "plist" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50ce7c785e06e3a9e6f546c1a30d3d59111a31a21bc294fb1496241a572c9a00" +checksum = "9b59eb8d91dfa89208ec74a920e3b55f840476cf46568026c18dbaa2999e0d48" dependencies = [ "base64 0.10.1", - "humantime 2.0.0", + "chrono", "indexmap", "line-wrap", - "serde 1.0.106", + "serde 1.0.110", "xml-rs", ] @@ -2841,9 +2900,9 @@ dependencies = [ [[package]] name = "proc-macro-error" -version = "0.4.12" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18f33027081eba0a6d8aba6d1b1c3a3be58cbb12106341c2d5759fcd9b5277e7" +checksum = "98e9e4b82e0ef281812565ea4751049f1bdcdfccda7d3f459f2e138a40c08678" dependencies = [ "proc-macro-error-attr", "proc-macro2", @@ -2854,9 +2913,9 @@ dependencies = [ [[package]] name = "proc-macro-error-attr" -version = "0.4.12" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a5b4b77fdb63c1eca72173d68d24501c54ab1269409f6b672c85deb18af69de" +checksum = "4f5444ead4e9935abd7f27dc51f7e852a0569ac888096d5ec2499470794e2e53" dependencies = [ "proc-macro2", "quote", @@ -2879,9 +2938,9 @@ checksum = "8e946095f9d3ed29ec38de908c22f95d9ac008e424c7bcae54c75a79c527c694" [[package]] name = "proc-macro2" -version = "1.0.10" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df246d292ff63439fea9bc8c0a270bed0e390d5ebd4db4ba15aba81111b5abe3" +checksum = "8872cf6f48eee44265156c111456a700ab3483686b3f96df4cf5481c89157319" dependencies = [ "unicode-xid", ] @@ -2897,7 +2956,7 @@ dependencies = [ "directories 1.0.2", "isatty", "petgraph", - "serde 1.0.106", + "serde 1.0.110", "serde-value", "serde_derive", "tint", @@ -2950,9 +3009,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f" +checksum = "42934bc9c8ab0d3b273a16d8551c8f0fcff46be73276ca083ec2414c15c4ba5e" dependencies = [ "proc-macro2", ] @@ -3169,7 +3228,7 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e46a2036019fdb888131db7a4c847a1063a7493f971ed94ea82c67eada63ca54" dependencies = [ - "serde 1.0.106", + "serde 1.0.110", "serde_derive", ] @@ -3209,9 +3268,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "535622e6be132bccd223f4bb2b8ac8d53cda3c7a6394944d3b2b33fb974f9d76" +checksum = "ed3d612bc64430efeb3f7ee6ef26d590dce0c43249217bddc62112540c7941e1" [[package]] name = "safemem" @@ -3230,9 +3289,9 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.18" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "039c25b130bd8c1321ee2d7de7fde2659fa9c2744e4bb29711cfc852ea53cd19" +checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" dependencies = [ "lazy_static 1.4.0", "winapi 0.3.8", @@ -3246,9 +3305,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "security-framework" -version = "0.4.2" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "572dfa3a0785509e7a44b5b4bebcf94d41ba34e9ed9eb9df722545c3b3c4144a" +checksum = "64808902d7d99f78eaddd2b4e2509713babc3dc3c85ad6f4c447680f3c01e535" dependencies = [ "bitflags", "core-foundation 0.7.0", @@ -3259,9 +3318,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ddb15a5fec93b7021b8a9e96009c5d8d51c15673569f7c0f6b7204e5b7b404f" +checksum = "17bf11d99252f512695eb468de5516e5cf75455521e69dfe343f3b74e4748405" dependencies = [ "core-foundation-sys 0.7.0", "libc", @@ -3290,9 +3349,9 @@ checksum = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8" [[package]] name = "serde" -version = "1.0.106" +version = "1.0.110" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df6ac6412072f67cf767ebbde4133a5b2e88e76dc6187fa7104cd16f783399" +checksum = "99e7b308464d16b56eba9964e4972a3eee817760ab60d88c3f86e1fecb08204c" dependencies = [ "serde_derive", ] @@ -3330,23 +3389,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a663f873dedc4eac1a559d4c6bc0d0b2c34dc5ac4702e105014b8281489e44f" dependencies = [ "ordered-float", - "serde 1.0.106", + "serde 1.0.110", ] [[package]] name = "serde_bytes" -version = "0.11.3" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "325a073952621257820e7a3469f55ba4726d8b28657e7e36653d1c36dc2c84ae" +checksum = "3bf487fbf5c6239d7ea2ff8b10cb6b811cd4b5080d1c2aeed1dec18753c06e10" dependencies = [ - "serde 1.0.106", + "serde 1.0.110", ] [[package]] name = "serde_derive" -version = "1.0.106" +version = "1.0.110" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e549e3abf4fb8621bd1609f11dfc9f5e50320802273b12f3811a67e6716ea6c" +checksum = "818fbf6bfa9a42d3bfcaca148547aa00c7b915bec71d1757aa2d44ca68771984" dependencies = [ "proc-macro2", "quote", @@ -3360,20 +3419,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb236687e2bb073a7521c021949be944641e671b8505a94069ca37b656c81139" dependencies = [ "result", - "serde 1.0.106", + "serde 1.0.110", "void", ] [[package]] name = "serde_json" -version = "1.0.51" +version = "1.0.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da07b57ee2623368351e9a0488bb0b261322a15a6e0ae53e243cbdc0f4208da9" +checksum = "993948e75b189211a9b31a7528f950c6adc21f9720b6438ff80a7fa2f864cea2" dependencies = [ "indexmap", "itoa", "ryu", - "serde 1.0.106", + "serde 1.0.110", ] [[package]] @@ -3393,22 +3452,32 @@ checksum = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97" dependencies = [ "dtoa", "itoa", - "serde 1.0.106", + "serde 1.0.110", "url", ] [[package]] name = "serde_yaml" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35" +checksum = "16c7a592a1ec97c9c1c68d75b6e537dcbf60c7618e038e7841e00af1d9ccf0c4" dependencies = [ "dtoa", - "linked-hash-map 0.5.2", - "serde 1.0.106", + "linked-hash-map 0.5.3", + "serde 1.0.110", "yaml-rust", ] +[[package]] +name = "shell32-sys" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ee04b46101f57121c9da2b151988283b6beb79b34f5bb29a58ee48cb695122c" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + [[package]] name = "shellexpand" version = "2.0.0" @@ -3420,9 +3489,9 @@ dependencies = [ [[package]] name = "signal-hook" -version = "0.1.13" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10b9f3a1686a29f53cfd91ee5e3db3c12313ec02d33765f02c1a9645a1811e2c" +checksum = "8ff2db2112d6c761e12522c65f7768548bd6e8cd23d2a9dae162520626629bd6" dependencies = [ "libc", "mio", @@ -3458,9 +3527,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05720e22615919e4734f6a99ceae50d00226c3c5aca406e102ebc33298214e0a" +checksum = "c7cb5678e1615754284ec264d9bb5b4c27d2018577fd90ac0ceb578591ed5ee4" [[package]] name = "socket2" @@ -3555,7 +3624,7 @@ dependencies = [ "log", "mime", "mime_guess", - "serde 1.0.106", + "serde 1.0.110", "serde_json", "serde_urlencoded", "url", @@ -3566,9 +3635,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.17" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03" +checksum = "4696caa4048ac7ce2bcd2e484b3cef88c1004e41b8e945a277e2c25dc0b72060" dependencies = [ "proc-macro2", "quote", @@ -3600,9 +3669,9 @@ dependencies = [ [[package]] name = "syntect" -version = "4.1.0" +version = "4.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "274f5e6be6e730e919e4e371dba490cd35cf7401fad41dac4a39a8d88884c731" +checksum = "6bc79276a4d38e39fbeb83c5fd9c23fbd027eeec7c50ee6a3d07deee33d7f621" dependencies = [ "bincode", "bitflags", @@ -3613,7 +3682,7 @@ dependencies = [ "lazycell", "plist", "regex-syntax", - "serde 1.0.106", + "serde 1.0.110", "serde_derive", "serde_json", "walkdir", @@ -3662,13 +3731,12 @@ dependencies = [ [[package]] name = "term_size" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5b9a66db815dcfd2da92db471106457082577c3c278d4138ab3e3b4e189327" +checksum = "1e4129646ca0ed8f45d09b929036bafad5377103edd06e50bf574b353d2b08d9" dependencies = [ - "kernel32-sys", "libc", - "winapi 0.2.8", + "winapi 0.3.8", ] [[package]] @@ -3692,18 +3760,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.15" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54b3d3d2ff68104100ab257bb6bb0cb26c901abe4bd4ba15961f3bf867924012" +checksum = "5976891d6950b4f68477850b5b9e5aa64d955961466f9e174363f573e54e8ca7" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.15" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca972988113b7715266f91250ddb98070d033c62a011fa0fcc57434a649310dd" +checksum = "ab81dbd1cd69cd2ce22ecfbdd3bdb73334ba25350649408cc6c085f46d89573d" dependencies = [ "proc-macro2", "quote", @@ -3721,21 +3789,20 @@ dependencies = [ [[package]] name = "threadpool" -version = "1.7.1" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" dependencies = [ "num_cpus", ] [[package]] name = "time" -version = "0.1.42" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" +checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" dependencies = [ "libc", - "redox_syscall", "winapi 0.3.8", ] @@ -3765,7 +3832,7 @@ version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" dependencies = [ - "serde 1.0.106", + "serde 1.0.110", ] [[package]] @@ -3774,7 +3841,7 @@ version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a" dependencies = [ - "serde 1.0.106", + "serde 1.0.110", ] [[package]] @@ -3807,7 +3874,7 @@ dependencies = [ "erased-serde", "inventory", "lazy_static 1.4.0", - "serde 1.0.106", + "serde 1.0.110", "typetag-impl", ] @@ -3951,9 +4018,9 @@ checksum = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168" [[package]] name = "vec_map" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "version_check" @@ -4001,9 +4068,9 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] name = "wasm-bindgen" -version = "0.2.60" +version = "0.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cc57ce05287f8376e998cbddfb4c8cb43b84a7ec55cf4551d7c00eef317a47f" +checksum = "e3c7d40d09cdbf0f4895ae58cf57d92e1e57a9dd8ed2e8390514b54a47cc5551" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -4011,9 +4078,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.60" +version = "0.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d967d37bf6c16cca2973ca3af071d0a2523392e4a594548155d89a678f4237cd" +checksum = "c3972e137ebf830900db522d6c8fd74d1900dcfc733462e9a12e942b00b4ac94" dependencies = [ "bumpalo", "lazy_static 1.4.0", @@ -4042,9 +4109,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.60" +version = "0.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bd151b63e1ea881bb742cd20e1d6127cef28399558f3b5d415289bc41eee3a4" +checksum = "2cd85aa2c579e8892442954685f0d801f9129de24fa2136b2c6a539c76b65776" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4052,9 +4119,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.60" +version = "0.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d68a5b36eef1be7868f668632863292e37739656a80fc4b9acec7b0bd35a4931" +checksum = "8eb197bd3a47553334907ffd2f16507b4f4f01bbec3ac921a7719e0decdfe72a" dependencies = [ "proc-macro2", "quote", @@ -4065,15 +4132,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.60" +version = "0.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daf76fe7d25ac79748a37538b7daeed1c7a6867c92d3245c12c6222e4a20d639" +checksum = "a91c2916119c17a8e316507afaaa2dd94b47646048014bbdf6bef098c1bb58ad" [[package]] name = "web-sys" -version = "0.3.37" +version = "0.3.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d6f51648d8c56c366144378a33290049eafdd784071077f6fe37dae64c1c4cb" +checksum = "8bc359e5dd3b46cb9687a051d50a2fdd228e4ba7cf6fcf861a5365c3d671a642" dependencies = [ "js-sys", "wasm-bindgen", @@ -4125,9 +4192,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa515c5163a99cc82bab70fd3bfdd36d827be85de63737b40fcef2ce084a436e" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" dependencies = [ "winapi 0.3.8", ] @@ -4178,10 +4245,16 @@ dependencies = [ ] [[package]] -name = "xml-rs" -version = "0.8.2" +name = "xdg" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bb76e5c421bbbeb8924c60c030331b345555024d56261dae8f3e786ed817c23" +checksum = "d089681aa106a86fade1b0128fb5daf07d5867a509ab036d99988dec80429a57" + +[[package]] +name = "xml-rs" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b07db065a5cf61a7e4ba64f29e67db906fb1787316516c4e6e5ff0fea1efcd8a" [[package]] name = "xmlparser" @@ -4195,7 +4268,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "65923dd1784f44da1d2c3dbbc5e822045628c590ba72123e1c73d3c230c4434d" dependencies = [ - "linked-hash-map 0.5.2", + "linked-hash-map 0.5.3", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 4ed49d2f6..7bdb8bfb0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,6 +30,7 @@ nu_plugin_binaryview = { version = "0.14.1", path = "./crates/nu_plugin_binaryvi nu_plugin_fetch = { version = "0.14.1", path = "./crates/nu_plugin_fetch", optional=true } nu_plugin_inc = { version = "0.14.1", path = "./crates/nu_plugin_inc", optional=true } nu_plugin_match = { version = "0.14.1", path = "./crates/nu_plugin_match", optional=true } +nu_plugin_parse = { version = "0.14.1", path = "./crates/nu_plugin_parse", optional=true } nu_plugin_post = { version = "0.14.1", path = "./crates/nu_plugin_post", optional=true } nu_plugin_ps = { version = "0.14.1", path = "./crates/nu_plugin_ps", optional=true } nu_plugin_start = { version = "0.1.0", path = "./crates/nu_plugin_start", optional=true } @@ -63,7 +64,7 @@ nu-build = { version = "0.14.1", path = "./crates/nu-build" } test-bins = [] default = ["sys", "ps", "textview", "inc", "str"] -stable = ["default", "starship-prompt", "binaryview", "match", "tree", "average", "post", "fetch", "clipboard-cli", "trash-support", "start"] +stable = ["default", "starship-prompt", "binaryview", "match", "tree", "average", "parse", "post", "fetch", "clipboard-cli", "trash-support", "start"] # Default textview = ["crossterm", "syntect", "url", "nu_plugin_textview"] @@ -77,6 +78,7 @@ average = ["nu_plugin_average"] binaryview = ["nu_plugin_binaryview"] fetch = ["nu_plugin_fetch"] match = ["nu_plugin_match"] +parse = ["nu_plugin_parse"] post = ["nu_plugin_post"] trace = ["nu-parser/trace"] tree = ["nu_plugin_tree"] @@ -160,6 +162,11 @@ name = "nu_plugin_stable_match" path = "src/plugins/nu_plugin_stable_match.rs" required-features = ["match"] +[[bin]] +name = "nu_plugin_stable_parse" +path = "src/plugins/nu_plugin_stable_parse.rs" +required-features = ["parse"] + [[bin]] name = "nu_plugin_stable_post" path = "src/plugins/nu_plugin_stable_post.rs" diff --git a/crates/nu-cli/Cargo.toml b/crates/nu-cli/Cargo.toml index 51797c9f2..5b234d4d7 100644 --- a/crates/nu-cli/Cargo.toml +++ b/crates/nu-cli/Cargo.toml @@ -20,6 +20,8 @@ nu-test-support = { version = "0.14.1", path = "../nu-test-support" } ansi_term = "0.12.1" +app_dirs = "1.2.1" +async-recursion = "0.3.1" directories = "2.0.2" async-stream = "0.2" base64 = "0.12.0" diff --git a/crates/nu-cli/src/cli.rs b/crates/nu-cli/src/cli.rs index 530bfa179..901c2c9d9 100644 --- a/crates/nu-cli/src/cli.rs +++ b/crates/nu-cli/src/cli.rs @@ -284,7 +284,6 @@ pub fn create_default_context( whole_stream_command(Lines), whole_stream_command(Trim), whole_stream_command(Echo), - whole_stream_command(Parse), // Column manipulation whole_stream_command(Reject), whole_stream_command(Select), diff --git a/crates/nu-cli/src/commands.rs b/crates/nu-cli/src/commands.rs index 0b7ef21f7..465e7e835 100644 --- a/crates/nu-cli/src/commands.rs +++ b/crates/nu-cli/src/commands.rs @@ -71,7 +71,6 @@ pub(crate) mod mv; pub(crate) mod next; pub(crate) mod nth; pub(crate) mod open; -pub(crate) mod parse; pub(crate) mod pivot; pub(crate) mod plugin; pub(crate) mod prepend; @@ -199,7 +198,6 @@ pub(crate) use mv::Move; pub(crate) use next::Next; pub(crate) use nth::Nth; pub(crate) use open::Open; -pub(crate) use parse::Parse; pub(crate) use pivot::Pivot; pub(crate) use prepend::Prepend; pub(crate) use prev::Previous; diff --git a/crates/nu-cli/src/commands/alias.rs b/crates/nu-cli/src/commands/alias.rs index 8c78eac4b..389643c58 100644 --- a/crates/nu-cli/src/commands/alias.rs +++ b/crates/nu-cli/src/commands/alias.rs @@ -39,7 +39,8 @@ impl WholeStreamCommand for Alias { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, alias)?.run() + //args.process(registry, alias)?.run() + alias(args, registry) } fn examples(&self) -> &[Example] { @@ -56,15 +57,10 @@ impl WholeStreamCommand for Alias { } } -pub fn alias( - AliasArgs { - name, - args: list, - block, - }: AliasArgs, - _: RunnableContext, -) -> Result { +pub fn alias(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); let stream = async_stream! { + let (AliasArgs { name, args: list, block }, _) = args.process(®istry).await?; let mut args: Vec = vec![]; for item in list.iter() { if let Ok(string) = item.as_string() { diff --git a/crates/nu-cli/src/commands/append.rs b/crates/nu-cli/src/commands/append.rs index e3b12c748..0a81e52be 100644 --- a/crates/nu-cli/src/commands/append.rs +++ b/crates/nu-cli/src/commands/append.rs @@ -2,7 +2,7 @@ use crate::commands::WholeStreamCommand; use crate::context::CommandRegistry; use crate::prelude::*; use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, Value}; +use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, Value}; #[derive(Deserialize)] struct AppendArgs { @@ -33,7 +33,7 @@ impl WholeStreamCommand for Append { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, append)?.run() + append(args, registry) } fn examples(&self) -> &[Example] { @@ -44,13 +44,17 @@ impl WholeStreamCommand for Append { } } -fn append( - AppendArgs { row }: AppendArgs, - RunnableContext { input, .. }: RunnableContext, -) -> Result { - let mut after: VecDeque = VecDeque::new(); - after.push_back(row); - let after = futures::stream::iter(after); +fn append(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); - Ok(OutputStream::from_input(input.chain(after))) + let stream = async_stream! { + let (AppendArgs { row }, mut input) = args.process(®istry).await?; + + while let Some(item) = input.next().await { + yield ReturnSuccess::value(item); + } + yield ReturnSuccess::value(row); + }; + + Ok(stream.to_output_stream()) } diff --git a/crates/nu-cli/src/commands/cal.rs b/crates/nu-cli/src/commands/cal.rs index 98d9f0b3b..0c9479ca3 100644 --- a/crates/nu-cli/src/commands/cal.rs +++ b/crates/nu-cli/src/commands/cal.rs @@ -5,7 +5,7 @@ use nu_protocol::Dictionary; use crate::commands::{command::EvaluatedWholeStreamCommandArgs, WholeStreamCommand}; use indexmap::IndexMap; -use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value}; +use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value}; pub struct Cal; @@ -59,52 +59,59 @@ impl WholeStreamCommand for Cal { } pub fn cal(args: CommandArgs, registry: &CommandRegistry) -> Result { - let args = args.evaluate_once(registry)?; - let mut calendar_vec_deque = VecDeque::new(); - let tag = args.call_info.name_tag.clone(); + let registry = registry.clone(); + let stream = async_stream! { + let args = args.evaluate_once(®istry).await?; + let mut calendar_vec_deque = VecDeque::new(); + let tag = args.call_info.name_tag.clone(); - let (current_year, current_month, current_day) = get_current_date(); + let (current_year, current_month, current_day) = get_current_date(); - if args.has("full-year") { - let mut day_value: Option = Some(current_day); - let mut year_value = current_year as u64; + if args.has("full-year") { + let mut day_value: Option = Some(current_day); + let mut year_value = current_year as u64; - if let Some(year) = args.get("full-year") { - if let Ok(year_u64) = year.as_u64() { - year_value = year_u64; + if let Some(year) = args.get("full-year") { + if let Ok(year_u64) = year.as_u64() { + year_value = year_u64; + } + + if year_value != current_year as u64 { + day_value = None + } } - if year_value != current_year as u64 { - day_value = None - } + add_year_to_table( + &mut calendar_vec_deque, + &tag, + year_value as i32, + current_year, + current_month, + day_value, + &args, + ); + } else { + let (day_start_offset, number_of_days_in_month, _) = + get_month_information(current_year, current_month, current_year); + + add_month_to_table( + &mut calendar_vec_deque, + &tag, + current_year, + current_month, + Some(current_day), + day_start_offset, + number_of_days_in_month as usize, + &args, + ); } - add_year_to_table( - &mut calendar_vec_deque, - &tag, - year_value as i32, - current_year, - current_month, - day_value, - &args, - ); - } else { - let (day_start_offset, number_of_days_in_month, _) = - get_month_information(current_year, current_month, current_year); + for item in calendar_vec_deque { + yield ReturnSuccess::value(item); + } + }; - add_month_to_table( - &mut calendar_vec_deque, - &tag, - current_year, - current_month, - Some(current_day), - day_start_offset, - number_of_days_in_month as usize, - &args, - ); - } - - Ok(futures::stream::iter(calendar_vec_deque).to_output_stream()) + Ok(stream.to_output_stream()) } fn get_current_date() -> (i32, u32, u32) { diff --git a/crates/nu-cli/src/commands/calc.rs b/crates/nu-cli/src/commands/calc.rs index 0196cd55c..c21359491 100644 --- a/crates/nu-cli/src/commands/calc.rs +++ b/crates/nu-cli/src/commands/calc.rs @@ -5,9 +5,6 @@ use nu_protocol::{Primitive, ReturnSuccess, UntaggedValue, Value}; pub struct Calc; -#[derive(Deserialize)] -pub struct CalcArgs {} - impl WholeStreamCommand for Calc { fn name(&self) -> &str { "calc" @@ -22,7 +19,7 @@ impl WholeStreamCommand for Calc { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, calc)?.run() + calc(args, registry) } fn examples(&self) -> &[Example] { @@ -33,30 +30,31 @@ impl WholeStreamCommand for Calc { } } -pub fn calc( - _: CalcArgs, - RunnableContext { input, name, .. }: RunnableContext, -) -> Result { - Ok(input - .map(move |input| { +pub fn calc(args: CommandArgs, _registry: &CommandRegistry) -> Result { + let stream = async_stream! { + let mut input = args.input; + let name = args.call_info.name_tag.clone(); + while let Some(input) = input.next().await { if let Ok(string) = input.as_string() { match parse(&string, &input.tag) { - Ok(value) => ReturnSuccess::value(value), - Err(err) => Err(ShellError::labeled_error( + Ok(value) => yield ReturnSuccess::value(value), + Err(err) => yield Err(ShellError::labeled_error( "Calculation error", err, &input.tag.span, )), } } else { - Err(ShellError::labeled_error( + yield Err(ShellError::labeled_error( "Expected a string from pipeline", "requires string input", name.clone(), )) } - }) - .to_output_stream()) + } + }; + + Ok(stream.to_output_stream()) } pub fn parse(math_expression: &str, tag: impl Into) -> Result { diff --git a/crates/nu-cli/src/commands/cd.rs b/crates/nu-cli/src/commands/cd.rs index 3d2a01781..1dd35d0dd 100644 --- a/crates/nu-cli/src/commands/cd.rs +++ b/crates/nu-cli/src/commands/cd.rs @@ -36,7 +36,7 @@ impl WholeStreamCommand for Cd { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, cd)?.run() + cd(args, registry) } fn examples(&self) -> &[Example] { @@ -61,6 +61,18 @@ impl WholeStreamCommand for Cd { } } -fn cd(args: CdArgs, context: RunnableContext) -> Result { - context.shell_manager.cd(args, &context) +fn cd(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); + let stream = async_stream! { + let name = args.call_info.name_tag.clone(); + let shell_manager = args.shell_manager.clone(); + + let (args, _): (CdArgs, _) = args.process(®istry).await?; + let mut result = shell_manager.cd(args, name)?; + while let Some(item) = result.next().await { + yield item; + } + }; + + Ok(stream.to_output_stream()) } diff --git a/crates/nu-cli/src/commands/classified/block.rs b/crates/nu-cli/src/commands/classified/block.rs index 79a631f44..9eb3b40a0 100644 --- a/crates/nu-cli/src/commands/classified/block.rs +++ b/crates/nu-cli/src/commands/classified/block.rs @@ -78,7 +78,7 @@ async fn run_pipeline( } (Some(ClassifiedCommand::Expr(expr)), _) => { - run_expression_block(*expr, ctx, input, scope)? + run_expression_block(*expr, ctx, input, scope).await? } (Some(ClassifiedCommand::Error(err)), _) => return Err(err.into()), (_, Some(ClassifiedCommand::Error(err))) => return Err(err.clone().into()), diff --git a/crates/nu-cli/src/commands/classified/expr.rs b/crates/nu-cli/src/commands/classified/expr.rs index 8a10aaf4b..9657719ec 100644 --- a/crates/nu-cli/src/commands/classified/expr.rs +++ b/crates/nu-cli/src/commands/classified/expr.rs @@ -8,7 +8,7 @@ use nu_errors::ShellError; use nu_protocol::hir::SpannedExpression; use nu_protocol::Scope; -pub(crate) fn run_expression_block( +pub(crate) async fn run_expression_block( expr: SpannedExpression, context: &mut Context, _input: InputStream, @@ -21,7 +21,7 @@ pub(crate) fn run_expression_block( let scope = scope.clone(); let registry = context.registry().clone(); - let output = evaluate_baseline_expr(&expr, ®istry, &scope)?; + let output = evaluate_baseline_expr(&expr, ®istry, &scope).await?; Ok(once(async { Ok(output) }).to_input_stream()) } diff --git a/crates/nu-cli/src/commands/classified/external.rs b/crates/nu-cli/src/commands/classified/external.rs index 8772389c6..0095bd658 100644 --- a/crates/nu-cli/src/commands/classified/external.rs +++ b/crates/nu-cli/src/commands/classified/external.rs @@ -99,10 +99,10 @@ pub(crate) async fn run_external_command( )); } - run_with_stdin(command, context, input, scope, is_last) + run_with_stdin(command, context, input, scope, is_last).await } -fn run_with_stdin( +async fn run_with_stdin( command: ExternalCommand, context: &mut Context, input: InputStream, @@ -115,7 +115,7 @@ fn run_with_stdin( let mut command_args = vec![]; for arg in command.args.iter() { - let value = evaluate_baseline_expr(arg, &context.registry, scope)?; + let value = evaluate_baseline_expr(arg, &context.registry, scope).await?; // Skip any arguments that don't really exist, treating them as optional // FIXME: we may want to preserve the gap in the future, though it's hard to say // what value we would put in its place. diff --git a/crates/nu-cli/src/commands/clip.rs b/crates/nu-cli/src/commands/clip.rs index 2fb112e15..70f099f84 100644 --- a/crates/nu-cli/src/commands/clip.rs +++ b/crates/nu-cli/src/commands/clip.rs @@ -11,9 +11,6 @@ pub mod clipboard { pub struct Clip; - #[derive(Deserialize)] - pub struct ClipArgs {} - impl WholeStreamCommand for Clip { fn name(&self) -> &str { "clip" @@ -32,7 +29,7 @@ pub mod clipboard { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, clip)?.run() + clip(args, registry) } fn examples(&self) -> &[Example] { @@ -44,10 +41,12 @@ pub mod clipboard { } pub fn clip( - ClipArgs {}: ClipArgs, - RunnableContext { input, name, .. }: RunnableContext, + args: CommandArgs, + _registry: &CommandRegistry, ) -> Result { let stream = async_stream! { + let mut input = args.input; + let name = args.call_info.name_tag.clone(); let values: Vec = input.collect().await; let mut clip_stream = inner_clip(values, name).await; diff --git a/crates/nu-cli/src/commands/command.rs b/crates/nu-cli/src/commands/command.rs index aedb67b75..25d75a084 100644 --- a/crates/nu-cli/src/commands/command.rs +++ b/crates/nu-cli/src/commands/command.rs @@ -7,7 +7,7 @@ use derive_new::new; use getset::Getters; use nu_errors::ShellError; use nu_protocol::hir; -use nu_protocol::{CallInfo, EvaluatedArgs, ReturnValue, Scope, Signature, Value}; +use nu_protocol::{CallInfo, EvaluatedArgs, ReturnSuccess, Scope, Signature, UntaggedValue, Value}; use serde::{Deserialize, Serialize}; use std::ops::Deref; use std::sync::atomic::AtomicBool; @@ -20,8 +20,8 @@ pub struct UnevaluatedCallInfo { } impl UnevaluatedCallInfo { - pub fn evaluate(self, registry: &CommandRegistry) -> Result { - let args = evaluate_args(&self.args, registry, &self.scope)?; + pub async fn evaluate(self, registry: &CommandRegistry) -> Result { + let args = evaluate_args(&self.args, registry, &self.scope).await?; Ok(CallInfo { args, @@ -29,14 +29,14 @@ impl UnevaluatedCallInfo { }) } - pub fn evaluate_with_new_it( + pub async fn evaluate_with_new_it( self, registry: &CommandRegistry, it: &Value, ) -> Result { let mut scope = self.scope.clone(); scope = scope.set_it(it.clone()); - let args = evaluate_args(&self.args, registry, &scope)?; + let args = evaluate_args(&self.args, registry, &scope).await?; Ok(CallInfo { args, @@ -87,7 +87,7 @@ impl std::fmt::Debug for CommandArgs { } impl CommandArgs { - pub fn evaluate_once( + pub async fn evaluate_once( self, registry: &CommandRegistry, ) -> Result { @@ -95,7 +95,7 @@ impl CommandArgs { let ctrl_c = self.ctrl_c.clone(); let shell_manager = self.shell_manager.clone(); let input = self.input; - let call_info = self.call_info.evaluate(registry)?; + let call_info = self.call_info.evaluate(registry).await?; Ok(EvaluatedWholeStreamCommandArgs::new( host, @@ -106,7 +106,7 @@ impl CommandArgs { )) } - pub fn evaluate_once_with_scope( + pub async fn evaluate_once_with_scope( self, registry: &CommandRegistry, scope: &Scope, @@ -120,7 +120,7 @@ impl CommandArgs { args: self.call_info.args, scope: scope.clone(), }; - let call_info = call_info.evaluate(registry)?; + let call_info = call_info.evaluate(registry).await?; Ok(EvaluatedWholeStreamCommandArgs::new( host, @@ -131,69 +131,16 @@ impl CommandArgs { )) } - pub fn process<'de, T: Deserialize<'de>, O: ToOutputStream>( + pub async fn process<'de, T: Deserialize<'de>>( self, registry: &CommandRegistry, - callback: fn(T, RunnableContext) -> Result, - ) -> Result, ShellError> { - let shell_manager = self.shell_manager.clone(); - let host = self.host.clone(); - let ctrl_c = self.ctrl_c.clone(); - let args = self.evaluate_once(registry)?; - let call_info = args.call_info.clone(); - let (input, args) = args.split(); - let name_tag = args.call_info.name_tag; - let mut deserializer = ConfigDeserializer::from_call_info(call_info); - - Ok(RunnableArgs { - args: T::deserialize(&mut deserializer)?, - context: RunnableContext { - input, - registry: registry.clone(), - shell_manager, - name: name_tag, - host, - ctrl_c, - }, - callback, - }) - } - - pub fn process_raw<'de, T: Deserialize<'de>>( - self, - registry: &CommandRegistry, - callback: fn(T, RunnableContext, RawCommandArgs) -> Result, - ) -> Result, ShellError> { - let raw_args = RawCommandArgs { - host: self.host.clone(), - ctrl_c: self.ctrl_c.clone(), - shell_manager: self.shell_manager.clone(), - call_info: self.call_info.clone(), - }; - - let shell_manager = self.shell_manager.clone(); - let host = self.host.clone(); - let ctrl_c = self.ctrl_c.clone(); - let args = self.evaluate_once(registry)?; + ) -> Result<(T, InputStream), ShellError> { + let args = self.evaluate_once(registry).await?; let call_info = args.call_info.clone(); - let (input, args) = args.split(); - let name_tag = args.call_info.name_tag; let mut deserializer = ConfigDeserializer::from_call_info(call_info); - Ok(RunnableRawArgs { - args: T::deserialize(&mut deserializer)?, - context: RunnableContext { - input, - registry: registry.clone(), - shell_manager, - name: name_tag, - host, - ctrl_c, - }, - raw_args, - callback, - }) + Ok((T::deserialize(&mut deserializer)?, args.input)) } } @@ -212,34 +159,6 @@ impl RunnableContext { } } -pub struct RunnableArgs { - args: T, - context: RunnableContext, - callback: fn(T, RunnableContext) -> Result, -} - -impl RunnableArgs { - pub fn run(self) -> Result { - (self.callback)(self.args, self.context).map(|v| v.to_output_stream()) - } -} - -pub struct RunnableRawArgs { - args: T, - raw_args: RawCommandArgs, - context: RunnableContext, - callback: fn(T, RunnableContext, RawCommandArgs) -> Result, -} - -impl RunnableRawArgs { - pub fn run(self) -> OutputStream { - match (self.callback)(self.args, self.context, self.raw_args) { - Ok(stream) => stream, - Err(err) => OutputStream::one(Err(err)), - } - } -} - pub struct EvaluatedWholeStreamCommandArgs { pub args: EvaluatedCommandArgs, pub input: InputStream, @@ -416,7 +335,12 @@ impl Command { pub fn run(&self, args: CommandArgs, registry: &CommandRegistry) -> OutputStream { if args.call_info.switch_present("help") { - get_help(&*self.0, registry).into() + let cl = self.0.clone(); + let registry = registry.clone(); + let stream = async_stream! { + yield Ok(ReturnSuccess::Value(UntaggedValue::string(get_help(&*cl, ®istry)).into_value(Tag::unknown()))); + }; + stream.to_output_stream() } else { match self.0.run(args, registry) { Ok(stream) => stream, @@ -458,37 +382,40 @@ impl WholeStreamCommand for FnFilterCommand { ctrl_c, shell_manager, call_info, - input, + mut input, } = args; let host: Arc> = host.clone(); let registry: CommandRegistry = registry.clone(); let func = self.func; - let result = input.map(move |it| { - let registry = registry.clone(); - let call_info = match call_info.clone().evaluate_with_new_it(®istry, &it) { - Err(err) => return OutputStream::from(vec![Err(err)]).values, - Ok(args) => args, - }; + let stream = async_stream! { + while let Some(it) = input.next().await { + let registry = registry.clone(); + let call_info = match call_info.clone().evaluate_with_new_it(®istry, &it).await { + Err(err) => { yield Err(err); return; }, + Ok(args) => args, + }; - let args = EvaluatedFilterCommandArgs::new( - host.clone(), - ctrl_c.clone(), - shell_manager.clone(), - call_info, - ); + let args = EvaluatedFilterCommandArgs::new( + host.clone(), + ctrl_c.clone(), + shell_manager.clone(), + call_info, + ); - match func(args) { - Err(err) => OutputStream::from(vec![Err(err)]).values, - Ok(stream) => stream.values, + match func(args) { + Err(err) => yield Err(err), + Ok(mut stream) => { + while let Some(value) = stream.values.next().await { + yield value; + } + } + } } - }); + }; - let result = result.flatten(); - let result: BoxStream = result.boxed(); - - Ok(result.into()) + Ok(stream.to_output_stream()) } } diff --git a/crates/nu-cli/src/commands/compact.rs b/crates/nu-cli/src/commands/compact.rs index 0300c10f8..fb2902239 100644 --- a/crates/nu-cli/src/commands/compact.rs +++ b/crates/nu-cli/src/commands/compact.rs @@ -3,7 +3,7 @@ use crate::context::CommandRegistry; use crate::prelude::*; use futures::stream::StreamExt; use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value}; +use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value}; use nu_source::Tagged; pub struct Compact; @@ -31,7 +31,7 @@ impl WholeStreamCommand for Compact { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, compact)?.run() + compact(args, registry) } fn examples(&self) -> &[Example] { @@ -42,27 +42,29 @@ impl WholeStreamCommand for Compact { } } -pub fn compact( - CompactArgs { rest: columns }: CompactArgs, - RunnableContext { input, .. }: RunnableContext, -) -> Result { - let objects = input.filter(move |item| { - let keep = if columns.is_empty() { - item.is_some() - } else { - match item { - Value { - value: UntaggedValue::Row(ref r), - .. - } => columns - .iter() - .all(|field| r.get_data(field).borrow().is_some()), - _ => false, - } - }; - - futures::future::ready(keep) - }); - - Ok(objects.from_input_stream()) +pub fn compact(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); + let stream = async_stream! { + let (CompactArgs { rest: columns }, mut input) = args.process(®istry).await?; + while let Some(item) = input.next().await { + if columns.is_empty() { + if !item.is_empty() { + yield ReturnSuccess::value(item); + } + } else { + match item { + Value { + value: UntaggedValue::Row(ref r), + .. + } => if columns + .iter() + .all(|field| r.get_data(field).borrow().is_some()) { + yield ReturnSuccess::value(item); + } + _ => {}, + } + }; + } + }; + Ok(stream.to_output_stream()) } diff --git a/crates/nu-cli/src/commands/config.rs b/crates/nu-cli/src/commands/config.rs index 99689b68e..dbb1ee06b 100644 --- a/crates/nu-cli/src/commands/config.rs +++ b/crates/nu-cli/src/commands/config.rs @@ -70,7 +70,7 @@ impl WholeStreamCommand for Config { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, config)?.run() + config(args, registry) } fn examples(&self) -> &[Example] { @@ -107,21 +107,22 @@ impl WholeStreamCommand for Config { } } -pub fn config( - ConfigArgs { - load, - set, - set_into, - get, - clear, - remove, - path, - }: ConfigArgs, - RunnableContext { name, input, .. }: RunnableContext, -) -> Result { - let name_span = name.clone(); +pub fn config(args: CommandArgs, registry: &CommandRegistry) -> Result { + let name_span = args.call_info.name_tag.clone(); + let name = args.call_info.name_tag.clone(); + let registry = registry.clone(); let stream = async_stream! { + let (ConfigArgs { + load, + set, + set_into, + get, + clear, + remove, + path, + }, mut input) = args.process(®istry).await?; + let configuration = if let Some(supplied) = load { Some(supplied.item().clone()) } else { diff --git a/crates/nu-cli/src/commands/count.rs b/crates/nu-cli/src/commands/count.rs index 5ed2b0bb8..828882b54 100644 --- a/crates/nu-cli/src/commands/count.rs +++ b/crates/nu-cli/src/commands/count.rs @@ -7,9 +7,6 @@ use nu_protocol::{ReturnSuccess, Signature, UntaggedValue, Value}; pub struct Count; -#[derive(Deserialize)] -pub struct CountArgs {} - impl WholeStreamCommand for Count { fn name(&self) -> &str { "count" @@ -28,7 +25,7 @@ impl WholeStreamCommand for Count { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, count)?.run() + count(args, registry) } fn examples(&self) -> &[Example] { @@ -39,12 +36,10 @@ impl WholeStreamCommand for Count { } } -pub fn count( - CountArgs {}: CountArgs, - RunnableContext { input, name, .. }: RunnableContext, -) -> Result { +pub fn count(args: CommandArgs, _registry: &CommandRegistry) -> Result { let stream = async_stream! { - let rows: Vec = input.collect().await; + let name = args.call_info.name_tag.clone(); + let rows: Vec = args.input.collect().await; yield ReturnSuccess::value(UntaggedValue::int(rows.len()).into_value(name)) }; diff --git a/crates/nu-cli/src/commands/cp.rs b/crates/nu-cli/src/commands/cp.rs index 946565edc..0f19a6548 100644 --- a/crates/nu-cli/src/commands/cp.rs +++ b/crates/nu-cli/src/commands/cp.rs @@ -40,7 +40,7 @@ impl WholeStreamCommand for Cpy { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, cp)?.run() + cp(args, registry) } fn examples(&self) -> &[Example] { @@ -57,7 +57,18 @@ impl WholeStreamCommand for Cpy { } } -pub fn cp(args: CopyArgs, context: RunnableContext) -> Result { - let shell_manager = context.shell_manager.clone(); - shell_manager.cp(args, &context) +pub fn cp(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); + let stream = async_stream! { + let shell_manager = args.shell_manager.clone(); + let name = args.call_info.name_tag.clone(); + let (args, _) = args.process(®istry).await?; + let mut result = shell_manager.cp(args, name)?; + + while let Some(item) = result.next().await { + yield item; + } + }; + + Ok(stream.to_output_stream()) } diff --git a/crates/nu-cli/src/commands/date.rs b/crates/nu-cli/src/commands/date.rs index c12a5e6cc..13ffcf512 100644 --- a/crates/nu-cli/src/commands/date.rs +++ b/crates/nu-cli/src/commands/date.rs @@ -7,7 +7,7 @@ use crate::commands::WholeStreamCommand; use chrono::{Datelike, TimeZone, Timelike}; use core::fmt::Display; use indexmap::IndexMap; -use nu_protocol::{Signature, UntaggedValue}; +use nu_protocol::{ReturnSuccess, Signature, UntaggedValue}; pub struct Date; @@ -89,20 +89,22 @@ where } pub fn date(args: CommandArgs, registry: &CommandRegistry) -> Result { - let args = args.evaluate_once(registry)?; + let registry = registry.clone(); + let stream = async_stream! { + let args = args.evaluate_once(®istry).await?; - let mut date_out = VecDeque::new(); - let tag = args.call_info.name_tag.clone(); + let tag = args.call_info.name_tag.clone(); - let value = if args.has("utc") { - let utc: DateTime = Utc::now(); - date_to_value(utc, tag) - } else { - let local: DateTime = Local::now(); - date_to_value(local, tag) + let value = if args.has("utc") { + let utc: DateTime = Utc::now(); + date_to_value(utc, tag) + } else { + let local: DateTime = Local::now(); + date_to_value(local, tag) + }; + + yield ReturnSuccess::value(value); }; - date_out.push_back(value); - - Ok(futures::stream::iter(date_out).to_output_stream()) + Ok(stream.to_output_stream()) } diff --git a/crates/nu-cli/src/commands/debug.rs b/crates/nu-cli/src/commands/debug.rs index 12bc8acfd..3fc6d041d 100644 --- a/crates/nu-cli/src/commands/debug.rs +++ b/crates/nu-cli/src/commands/debug.rs @@ -28,23 +28,24 @@ impl WholeStreamCommand for Debug { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, debug_value)?.run() + debug_value(args, registry) } } -fn debug_value( - DebugArgs { raw }: DebugArgs, - RunnableContext { input, .. }: RunnableContext, -) -> Result { - Ok(input - .map(move |v| { +fn debug_value(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); + let stream = async_stream! { + let (DebugArgs { raw }, mut input) = args.process(®istry).await?; + while let Some(v) = input.next().await { if raw { - ReturnSuccess::value( + yield ReturnSuccess::value( UntaggedValue::string(format!("{:#?}", v)).into_untagged_value(), - ) + ); } else { - ReturnSuccess::debug_value(v) + yield ReturnSuccess::debug_value(v); } - }) - .to_output_stream()) + } + }; + + Ok(stream.to_output_stream()) } diff --git a/crates/nu-cli/src/commands/default.rs b/crates/nu-cli/src/commands/default.rs index 27d6364f7..b2da0bebb 100644 --- a/crates/nu-cli/src/commands/default.rs +++ b/crates/nu-cli/src/commands/default.rs @@ -38,7 +38,7 @@ impl WholeStreamCommand for Default { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, default)?.run() + default(args, registry) } fn examples(&self) -> &[Example] { @@ -49,14 +49,11 @@ impl WholeStreamCommand for Default { } } -fn default( - DefaultArgs { column, value }: DefaultArgs, - RunnableContext { input, .. }: RunnableContext, -) -> Result { - let stream = input - .map(move |item| { - let mut result = VecDeque::new(); - +fn default(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); + let stream = async_stream! { + let (DefaultArgs { column, value }, mut input) = args.process(®istry).await?; + while let Some(item) = input.next().await { let should_add = match item { Value { value: UntaggedValue::Row(ref r), @@ -67,16 +64,15 @@ fn default( if should_add { match item.insert_data_at_path(&column.item, value.clone()) { - Some(new_value) => result.push_back(ReturnSuccess::value(new_value)), - None => result.push_back(ReturnSuccess::value(item)), + Some(new_value) => yield ReturnSuccess::value(new_value), + None => yield ReturnSuccess::value(item), } } else { - result.push_back(ReturnSuccess::value(item)); + yield ReturnSuccess::value(item); } - futures::stream::iter(result) - }) - .flatten(); + } + }; Ok(stream.to_output_stream()) } diff --git a/crates/nu-cli/src/commands/drop.rs b/crates/nu-cli/src/commands/drop.rs index 3f7faddc4..8931992d1 100644 --- a/crates/nu-cli/src/commands/drop.rs +++ b/crates/nu-cli/src/commands/drop.rs @@ -34,7 +34,7 @@ impl WholeStreamCommand for Drop { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, drop)?.run() + drop(args, registry) } fn examples(&self) -> &[Example] { @@ -51,9 +51,11 @@ impl WholeStreamCommand for Drop { } } -fn drop(DropArgs { rows }: DropArgs, context: RunnableContext) -> Result { +fn drop(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); let stream = async_stream! { - let v: Vec<_> = context.input.into_vec().await; + let (DropArgs { rows }, mut input) = args.process(®istry).await?; + let v: Vec<_> = input.into_vec().await; let rows_to_drop = if let Some(quantity) = rows { *quantity as usize diff --git a/crates/nu-cli/src/commands/du.rs b/crates/nu-cli/src/commands/du.rs index b3924fb18..e4164f54d 100644 --- a/crates/nu-cli/src/commands/du.rs +++ b/crates/nu-cli/src/commands/du.rs @@ -76,7 +76,7 @@ impl WholeStreamCommand for Du { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, du)?.run() + du(args, registry) } fn examples(&self) -> &[Example] { @@ -87,65 +87,72 @@ impl WholeStreamCommand for Du { } } -fn du(args: DuArgs, ctx: RunnableContext) -> Result { - let tag = ctx.name.clone(); +fn du(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); + let tag = args.call_info.name_tag.clone(); + let ctrl_c = args.ctrl_c.clone(); - let exclude = args.exclude.map_or(Ok(None), move |x| { - Pattern::new(&x.item) - .map(Option::Some) - .map_err(|e| ShellError::labeled_error(e.msg, "glob error", x.tag.clone())) - })?; + let stream = async_stream! { + let (args, mut input): (DuArgs, _) = args.process(®istry).await?; + let exclude = args.exclude.map_or(Ok(None), move |x| { + Pattern::new(&x.item) + .map(Option::Some) + .map_err(|e| ShellError::labeled_error(e.msg, "glob error", x.tag.clone())) + })?; - let include_files = args.all; - let paths = match args.path { - Some(p) => { - let p = p.item.to_str().expect("Why isn't this encoded properly?"); - glob::glob_with(p, GLOB_PARAMS) - } - None => glob::glob_with("*", GLOB_PARAMS), - } - .map_err(|e| ShellError::labeled_error(e.msg, "glob error", tag.clone()))? - .filter(move |p| { - if include_files { - true - } else { - match p { - Ok(f) if f.is_dir() => true, - Err(e) if e.path().is_dir() => true, - _ => false, + let include_files = args.all; + let paths = match args.path { + Some(p) => { + let p = p.item.to_str().expect("Why isn't this encoded properly?"); + glob::glob_with(p, GLOB_PARAMS) } + None => glob::glob_with("*", GLOB_PARAMS), } - }) - .map(|v| v.map_err(glob_err_into)); - - let ctrl_c = ctx.ctrl_c; - let all = args.all; - let deref = args.deref; - let max_depth = args.max_depth.map(|f| f.item); - let min_size = args.min_size.map(|f| f.item); - - let params = DirBuilder { - tag: tag.clone(), - min: min_size, - deref, - exclude, - all, - }; - - let stream = futures::stream::iter(paths) - .interruptible(ctrl_c) - .map(move |path| match path { - Ok(p) => { - if p.is_dir() { - Ok(ReturnSuccess::Value( - DirInfo::new(p, ¶ms, max_depth).into(), - )) - } else { - FileInfo::new(p, deref, tag.clone()).map(|v| ReturnSuccess::Value(v.into())) + .map_err(|e| ShellError::labeled_error(e.msg, "glob error", tag.clone()))? + .filter(move |p| { + if include_files { + true + } else { + match p { + Ok(f) if f.is_dir() => true, + Err(e) if e.path().is_dir() => true, + _ => false, } } - Err(e) => Err(e), - }); + }) + .map(|v| v.map_err(glob_err_into)); + + let all = args.all; + let deref = args.deref; + let max_depth = args.max_depth.map(|f| f.item); + let min_size = args.min_size.map(|f| f.item); + + let params = DirBuilder { + tag: tag.clone(), + min: min_size, + deref, + exclude, + all, + }; + + let mut inp = futures::stream::iter(paths).interruptible(ctrl_c); + while let Some(path) = inp.next().await { + match path { + Ok(p) => { + if p.is_dir() { + yield Ok(ReturnSuccess::Value( + DirInfo::new(p, ¶ms, max_depth).into(), + )) + } else { + for v in FileInfo::new(p, deref, tag.clone()).into_iter() { + yield Ok(ReturnSuccess::Value(v.into())); + } + } + } + Err(e) => yield Err(e), + } + } + }; Ok(stream.to_output_stream()) } diff --git a/crates/nu-cli/src/commands/each.rs b/crates/nu-cli/src/commands/each.rs index 305b39a4a..57e78f1ee 100644 --- a/crates/nu-cli/src/commands/each.rs +++ b/crates/nu-cli/src/commands/each.rs @@ -39,7 +39,7 @@ impl WholeStreamCommand for Each { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - Ok(args.process_raw(registry, each)?.run()) + each(args, registry) } fn examples(&self) -> &[Example] { @@ -60,21 +60,18 @@ fn is_expanded_it_usage(head: &SpannedExpression) -> bool { } } -fn each( - each_args: EachArgs, - context: RunnableContext, - raw_args: RawCommandArgs, -) -> Result { - let block = each_args.block; - let scope = raw_args.call_info.scope.clone(); - let registry = context.registry.clone(); - let mut input_stream = context.input; +fn each(raw_args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); let stream = async_stream! { - while let Some(input) = input_stream.next().await { - let mut context = Context::from_raw(&raw_args, ®istry); + let head = raw_args.call_info.args.head.clone(); + let scope = raw_args.call_info.scope.clone(); + let mut context = Context::from_raw(&raw_args, ®istry); + let (each_args, mut input): (EachArgs, _) = raw_args.process(®istry).await?; + let block = each_args.block; + while let Some(input) = input.next().await { let input_clone = input.clone(); - let input_stream = if is_expanded_it_usage(&raw_args.call_info.args.head) { + let input_stream = if is_expanded_it_usage(&head) { InputStream::empty() } else { once(async { Ok(input) }).to_input_stream() diff --git a/crates/nu-cli/src/commands/echo.rs b/crates/nu-cli/src/commands/echo.rs index e0cfe3e53..68a2f1df8 100644 --- a/crates/nu-cli/src/commands/echo.rs +++ b/crates/nu-cli/src/commands/echo.rs @@ -28,7 +28,7 @@ impl WholeStreamCommand for Echo { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, echo)?.run() + echo(args, registry) } fn examples(&self) -> &[Example] { @@ -45,34 +45,34 @@ impl WholeStreamCommand for Echo { } } -fn echo(args: EchoArgs, _: RunnableContext) -> Result { - let mut output = vec![]; +fn echo(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); + let stream = async_stream! { + let (args, _): (EchoArgs, _) = args.process(®istry).await?; - for i in args.rest { - match i.as_string() { - Ok(s) => { - output.push(Ok(ReturnSuccess::Value( - UntaggedValue::string(s).into_value(i.tag.clone()), - ))); - } - _ => match i { - Value { - value: UntaggedValue::Table(table), - .. - } => { - for value in table { - output.push(Ok(ReturnSuccess::Value(value.clone()))); + for i in args.rest { + match i.as_string() { + Ok(s) => { + yield Ok(ReturnSuccess::Value( + UntaggedValue::string(s).into_value(i.tag.clone()), + )); + } + _ => match i { + Value { + value: UntaggedValue::Table(table), + .. + } => { + for value in table { + yield Ok(ReturnSuccess::Value(value.clone())); + } } - } - _ => { - output.push(Ok(ReturnSuccess::Value(i.clone()))); - } - }, + _ => { + yield Ok(ReturnSuccess::Value(i.clone())); + } + }, + } } - } - - // TODO: This whole block can probably be replaced with `.map()` - let stream = futures::stream::iter(output); + }; Ok(stream.to_output_stream()) } diff --git a/crates/nu-cli/src/commands/enter.rs b/crates/nu-cli/src/commands/enter.rs index 962c61de3..0fea8db4d 100644 --- a/crates/nu-cli/src/commands/enter.rs +++ b/crates/nu-cli/src/commands/enter.rs @@ -38,7 +38,7 @@ impl WholeStreamCommand for Enter { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - Ok(args.process_raw(registry, enter)?.run()) + enter(args, registry) } fn examples(&self) -> &[Example] { @@ -55,44 +55,42 @@ impl WholeStreamCommand for Enter { } } -fn enter( - EnterArgs { location }: EnterArgs, - RunnableContext { - registry, - name: tag, - .. - }: RunnableContext, - raw_args: RawCommandArgs, -) -> Result { - let location_string = location.display().to_string(); - let location_clone = location_string.clone(); +fn enter(raw_args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); + let stream = async_stream! { + let scope = raw_args.call_info.scope.clone(); + let shell_manager = raw_args.shell_manager.clone(); + let head = raw_args.call_info.args.head.clone(); + let ctrl_c = raw_args.ctrl_c.clone(); + let host = raw_args.host.clone(); + let tag = raw_args.call_info.name_tag.clone(); + let (EnterArgs { location }, _) = raw_args.process(®istry).await?; + let location_string = location.display().to_string(); + let location_clone = location_string.clone(); - if location_string.starts_with("help") { - let spec = location_string.split(':').collect::>(); + if location_string.starts_with("help") { + let spec = location_string.split(':').collect::>(); - if spec.len() == 2 { - let (_, command) = (spec[0], spec[1]); + if spec.len() == 2 { + let (_, command) = (spec[0], spec[1]); - if registry.has(command) { - return Ok(vec![Ok(ReturnSuccess::Action(CommandAction::EnterHelpShell( - UntaggedValue::string(command).into_value(Tag::unknown()), - )))] - .into()); + if registry.has(command) { + yield Ok(ReturnSuccess::Action(CommandAction::EnterHelpShell( + UntaggedValue::string(command).into_value(Tag::unknown()), + ))); + return; + } } - } - Ok(vec![Ok(ReturnSuccess::Action(CommandAction::EnterHelpShell( - UntaggedValue::nothing().into_value(Tag::unknown()), - )))] - .into()) - } else if location.is_dir() { - Ok(vec![Ok(ReturnSuccess::Action(CommandAction::EnterShell( - location_clone, - )))] - .into()) - } else { - let stream = async_stream! { + yield Ok(ReturnSuccess::Action(CommandAction::EnterHelpShell( + UntaggedValue::nothing().into_value(Tag::unknown()), + ))); + } else if location.is_dir() { + yield Ok(ReturnSuccess::Action(CommandAction::EnterShell( + location_clone, + ))); + } else { // If it's a file, attempt to open the file as a value and enter it - let cwd = raw_args.shell_manager.path(); + let cwd = shell_manager.path(); let full_path = std::path::PathBuf::from(cwd); @@ -113,19 +111,19 @@ fn enter( registry.get_command(&command_name) { let new_args = RawCommandArgs { - host: raw_args.host, - ctrl_c: raw_args.ctrl_c, - shell_manager: raw_args.shell_manager, + host, + ctrl_c, + shell_manager, call_info: UnevaluatedCallInfo { args: nu_protocol::hir::Call { - head: raw_args.call_info.args.head, + head, positional: None, named: None, span: Span::unknown(), is_last: false, }, - name_tag: raw_args.call_info.name_tag, - scope: raw_args.call_info.scope.clone() + name_tag: tag.clone(), + scope: scope.clone() }, }; let mut result = converter.run( @@ -162,7 +160,8 @@ fn enter( yield Ok(ReturnSuccess::Action(CommandAction::EnterValueShell(tagged_contents))); } } - }; - Ok(stream.to_output_stream()) - } + } + }; + + Ok(stream.to_output_stream()) } diff --git a/crates/nu-cli/src/commands/evaluate_by.rs b/crates/nu-cli/src/commands/evaluate_by.rs index a63910ac7..f464d9d69 100644 --- a/crates/nu-cli/src/commands/evaluate_by.rs +++ b/crates/nu-cli/src/commands/evaluate_by.rs @@ -36,15 +36,18 @@ impl WholeStreamCommand for EvaluateBy { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, evaluate_by)?.run() + evaluate_by(args, registry) } } pub fn evaluate_by( - EvaluateByArgs { evaluate_with }: EvaluateByArgs, - RunnableContext { input, name, .. }: RunnableContext, + args: CommandArgs, + registry: &CommandRegistry, ) -> Result { + let registry = registry.clone(); let stream = async_stream! { + let name = args.call_info.name_tag.clone(); + let (EvaluateByArgs { evaluate_with }, mut input) = args.process(®istry).await?; let values: Vec = input.collect().await; if values.is_empty() { diff --git a/crates/nu-cli/src/commands/exit.rs b/crates/nu-cli/src/commands/exit.rs index 134567210..bc9999a0d 100644 --- a/crates/nu-cli/src/commands/exit.rs +++ b/crates/nu-cli/src/commands/exit.rs @@ -42,11 +42,16 @@ impl WholeStreamCommand for Exit { } pub fn exit(args: CommandArgs, registry: &CommandRegistry) -> Result { - let args = args.evaluate_once(registry)?; + let registry = registry.clone(); + let stream = async_stream! { + let args = args.evaluate_once(®istry).await?; - if args.call_info.args.has("now") { - Ok(vec![Ok(ReturnSuccess::Action(CommandAction::Exit))].into()) - } else { - Ok(vec![Ok(ReturnSuccess::Action(CommandAction::LeaveShell))].into()) - } + if args.call_info.args.has("now") { + yield Ok(ReturnSuccess::Action(CommandAction::Exit)); + } else { + yield Ok(ReturnSuccess::Action(CommandAction::LeaveShell)); + } + }; + + Ok(stream.to_output_stream()) } diff --git a/crates/nu-cli/src/commands/first.rs b/crates/nu-cli/src/commands/first.rs index 010e0a732..486dfbbbf 100644 --- a/crates/nu-cli/src/commands/first.rs +++ b/crates/nu-cli/src/commands/first.rs @@ -2,7 +2,7 @@ use crate::commands::WholeStreamCommand; use crate::context::CommandRegistry; use crate::prelude::*; use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape}; +use nu_protocol::{ReturnSuccess, Signature, SyntaxShape}; use nu_source::Tagged; pub struct First; @@ -34,7 +34,7 @@ impl WholeStreamCommand for First { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, first)?.run() + first(args, registry) } fn examples(&self) -> &[Example] { @@ -51,15 +51,25 @@ impl WholeStreamCommand for First { } } -fn first( - FirstArgs { rows }: FirstArgs, - context: RunnableContext, -) -> Result { - let rows_desired = if let Some(quantity) = rows { - *quantity - } else { - 1 +fn first(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); + let stream = async_stream! { + let (FirstArgs { rows }, mut input) = args.process(®istry).await?; + let mut rows_desired = if let Some(quantity) = rows { + *quantity + } else { + 1 + }; + + while let Some(input) = input.next().await { + if rows_desired > 0 { + yield ReturnSuccess::value(input); + rows_desired -= 1; + } else { + break; + } + } }; - Ok(OutputStream::from_input(context.input.take(rows_desired))) + Ok(stream.to_output_stream()) } diff --git a/crates/nu-cli/src/commands/format.rs b/crates/nu-cli/src/commands/format.rs index 2ff3a5e62..f2c2caf7c 100644 --- a/crates/nu-cli/src/commands/format.rs +++ b/crates/nu-cli/src/commands/format.rs @@ -36,7 +36,7 @@ impl WholeStreamCommand for Format { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, format_command)?.run() + format_command(args, registry) } fn examples(&self) -> &[Example] { @@ -48,16 +48,17 @@ impl WholeStreamCommand for Format { } fn format_command( - FormatArgs { pattern }: FormatArgs, - RunnableContext { input, .. }: RunnableContext, + args: CommandArgs, + registry: &CommandRegistry, ) -> Result { - let pattern_tag = pattern.tag.clone(); - - let format_pattern = format(&pattern); - let commands = format_pattern; - let mut input = input; - + let registry = registry.clone(); let stream = async_stream! { + let (FormatArgs { pattern }, mut input) = args.process(®istry).await?; + let pattern_tag = pattern.tag.clone(); + + let format_pattern = format(&pattern); + let commands = format_pattern; + while let Some(value) = input.next().await { match value { value diff --git a/crates/nu-cli/src/commands/from.rs b/crates/nu-cli/src/commands/from.rs index f6475005a..e5302fb6a 100644 --- a/crates/nu-cli/src/commands/from.rs +++ b/crates/nu-cli/src/commands/from.rs @@ -1,7 +1,7 @@ use crate::commands::WholeStreamCommand; use crate::prelude::*; use nu_errors::ShellError; -use nu_protocol::Signature; +use nu_protocol::{ReturnSuccess, Signature, UntaggedValue}; pub struct From; @@ -23,6 +23,14 @@ impl WholeStreamCommand for From { _args: CommandArgs, registry: &CommandRegistry, ) -> Result { - Ok(crate::commands::help::get_help(&*self, registry).into()) + let registry = registry.clone(); + let stream = async_stream! { + yield Ok(ReturnSuccess::Value( + UntaggedValue::string(crate::commands::help::get_help(&From, ®istry)) + .into_value(Tag::unknown()), + )); + }; + + Ok(stream.to_output_stream()) } } diff --git a/crates/nu-cli/src/commands/from_bson.rs b/crates/nu-cli/src/commands/from_bson.rs index 8b20d9549..5097541d4 100644 --- a/crates/nu-cli/src/commands/from_bson.rs +++ b/crates/nu-cli/src/commands/from_bson.rs @@ -207,11 +207,12 @@ pub fn from_bson_bytes_to_value(bytes: Vec, tag: impl Into) -> Result Result { - let args = args.evaluate_once(registry)?; - let tag = args.name_tag(); - let input = args.input; - + let registry = registry.clone(); let stream = async_stream! { + let args = args.evaluate_once(®istry).await?; + let tag = args.name_tag(); + let input = args.input; + let bytes = input.collect_binary(tag.clone()).await?; match from_bson_bytes_to_value(bytes.item, tag.clone()) { diff --git a/crates/nu-cli/src/commands/from_csv.rs b/crates/nu-cli/src/commands/from_csv.rs index 019bcecde..0ad66dc29 100644 --- a/crates/nu-cli/src/commands/from_csv.rs +++ b/crates/nu-cli/src/commands/from_csv.rs @@ -41,7 +41,7 @@ impl WholeStreamCommand for FromCSV { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, from_csv)?.run() + from_csv(args, registry) } fn examples(&self) -> &[Example] { @@ -62,35 +62,41 @@ impl WholeStreamCommand for FromCSV { } } -fn from_csv( - FromCSVArgs { - headerless, - separator, - }: FromCSVArgs, - runnable_context: RunnableContext, -) -> Result { - let sep = match separator { - Some(Value { - value: UntaggedValue::Primitive(Primitive::String(s)), - tag, - .. - }) => { - if s == r"\t" { - '\t' - } else { - let vec_s: Vec = s.chars().collect(); - if vec_s.len() != 1 { - return Err(ShellError::labeled_error( - "Expected a single separator char from --separator", - "requires a single character string input", - tag, - )); - }; - vec_s[0] +fn from_csv(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); + let name = args.call_info.name_tag.clone(); + let stream = async_stream! { + let (FromCSVArgs { headerless, separator }, mut input) = args.process(®istry).await?; + let sep = match separator { + Some(Value { + value: UntaggedValue::Primitive(Primitive::String(s)), + tag, + .. + }) => { + if s == r"\t" { + '\t' + } else { + let vec_s: Vec = s.chars().collect(); + if vec_s.len() != 1 { + yield Err(ShellError::labeled_error( + "Expected a single separator char from --separator", + "requires a single character string input", + tag, + )); + return; + }; + vec_s[0] + } } + _ => ',', + }; + + let mut result = from_delimited_data(headerless, sep, "CSV", input, name)?; + while let Some(item) = result.next().await { + yield item; } - _ => ',', + }; - from_delimited_data(headerless, sep, "CSV", runnable_context) + Ok(stream.to_output_stream()) } diff --git a/crates/nu-cli/src/commands/from_delimited_data.rs b/crates/nu-cli/src/commands/from_delimited_data.rs index 58919bae7..eaa9ed442 100644 --- a/crates/nu-cli/src/commands/from_delimited_data.rs +++ b/crates/nu-cli/src/commands/from_delimited_data.rs @@ -45,7 +45,8 @@ pub fn from_delimited_data( headerless: bool, sep: char, format_name: &'static str, - RunnableContext { input, name, .. }: RunnableContext, + input: InputStream, + name: Tag, ) -> Result { let name_tag = name; diff --git a/crates/nu-cli/src/commands/from_eml.rs b/crates/nu-cli/src/commands/from_eml.rs index 251468954..ceb6e9b12 100644 --- a/crates/nu-cli/src/commands/from_eml.rs +++ b/crates/nu-cli/src/commands/from_eml.rs @@ -39,7 +39,7 @@ impl WholeStreamCommand for FromEML { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, from_eml)?.run() + from_eml(args, registry) } } @@ -76,14 +76,11 @@ fn headerfieldvalue_to_value(tag: &Tag, value: &HeaderFieldValue) -> UntaggedVal } } -fn from_eml( - eml_args: FromEMLArgs, - runnable_context: RunnableContext, -) -> Result { - let input = runnable_context.input; - let tag = runnable_context.name; - +fn from_eml(args: CommandArgs, registry: &CommandRegistry) -> Result { + let tag = args.call_info.name_tag.clone(); + let registry = registry.clone(); let stream = async_stream! { + let (eml_args, mut input): (FromEMLArgs, _) = args.process(®istry).await?; let value = input.collect_string(tag.clone()).await?; let body_preview = eml_args.preview_body.map(|b| b.item).unwrap_or(DEFAULT_BODY_PREVIEW); diff --git a/crates/nu-cli/src/commands/from_ics.rs b/crates/nu-cli/src/commands/from_ics.rs index 79f3fcfb2..1c45cefe2 100644 --- a/crates/nu-cli/src/commands/from_ics.rs +++ b/crates/nu-cli/src/commands/from_ics.rs @@ -32,11 +32,12 @@ impl WholeStreamCommand for FromIcs { } fn from_ics(args: CommandArgs, registry: &CommandRegistry) -> Result { - let args = args.evaluate_once(registry)?; - let tag = args.name_tag(); - let input = args.input; - + let registry = registry.clone(); let stream = async_stream! { + let args = args.evaluate_once(®istry).await?; + let tag = args.name_tag(); + let input = args.input; + let input_string = input.collect_string(tag.clone()).await?.item; let input_bytes = input_string.as_bytes(); let buf_reader = BufReader::new(input_bytes); diff --git a/crates/nu-cli/src/commands/from_ini.rs b/crates/nu-cli/src/commands/from_ini.rs index f0cd5a1e5..ff9aec269 100644 --- a/crates/nu-cli/src/commands/from_ini.rs +++ b/crates/nu-cli/src/commands/from_ini.rs @@ -64,11 +64,11 @@ pub fn from_ini_string_to_value( } fn from_ini(args: CommandArgs, registry: &CommandRegistry) -> Result { - let args = args.evaluate_once(registry)?; - let tag = args.name_tag(); - let input = args.input; - + let registry = registry.clone(); let stream = async_stream! { + let args = args.evaluate_once(®istry).await?; + let tag = args.name_tag(); + let input = args.input; let concat_string = input.collect_string(tag.clone()).await?; match from_ini_string_to_value(concat_string.item, tag.clone()) { diff --git a/crates/nu-cli/src/commands/from_json.rs b/crates/nu-cli/src/commands/from_json.rs index be1b23f7e..a97280a30 100644 --- a/crates/nu-cli/src/commands/from_json.rs +++ b/crates/nu-cli/src/commands/from_json.rs @@ -32,7 +32,7 @@ impl WholeStreamCommand for FromJSON { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, from_json)?.run() + from_json(args, registry) } } @@ -70,13 +70,12 @@ pub fn from_json_string_to_value(s: String, tag: impl Into) -> serde_hjson: Ok(convert_json_value_to_nu_value(&v, tag)) } -fn from_json( - FromJSONArgs { objects }: FromJSONArgs, - RunnableContext { input, name, .. }: RunnableContext, -) -> Result { - let name_tag = name; +fn from_json(args: CommandArgs, registry: &CommandRegistry) -> Result { + let name_tag = args.call_info.name_tag.clone(); + let registry = registry.clone(); let stream = async_stream! { + let (FromJSONArgs { objects }, mut input) = args.process(®istry).await?; let concat_string = input.collect_string(name_tag.clone()).await?; if objects { diff --git a/crates/nu-cli/src/commands/from_ods.rs b/crates/nu-cli/src/commands/from_ods.rs index a429bce2e..d48e894f2 100644 --- a/crates/nu-cli/src/commands/from_ods.rs +++ b/crates/nu-cli/src/commands/from_ods.rs @@ -35,20 +35,16 @@ impl WholeStreamCommand for FromODS { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, from_ods)?.run() + from_ods(args, registry) } } -fn from_ods( - FromODSArgs { - headerless: _headerless, - }: FromODSArgs, - runnable_context: RunnableContext, -) -> Result { - let input = runnable_context.input; - let tag = runnable_context.name; +fn from_ods(args: CommandArgs, registry: &CommandRegistry) -> Result { + let tag = args.call_info.name_tag.clone(); + let registry = registry.clone(); let stream = async_stream! { + let (FromODSArgs { headerless: _headerless }, mut input) = args.process(®istry).await?; let bytes = input.collect_binary(tag.clone()).await?; let mut buf: Cursor> = Cursor::new(bytes.item); let mut ods = Ods::<_>::new(buf).map_err(|_| ShellError::labeled_error( diff --git a/crates/nu-cli/src/commands/from_sqlite.rs b/crates/nu-cli/src/commands/from_sqlite.rs index c6430f6d5..b750f0808 100644 --- a/crates/nu-cli/src/commands/from_sqlite.rs +++ b/crates/nu-cli/src/commands/from_sqlite.rs @@ -133,11 +133,12 @@ pub fn from_sqlite_bytes_to_value( } fn from_sqlite(args: CommandArgs, registry: &CommandRegistry) -> Result { - let args = args.evaluate_once(registry)?; - let tag = args.name_tag(); - let input = args.input; - + let registry = registry.clone(); let stream = async_stream! { + let args = args.evaluate_once(®istry).await?; + let tag = args.name_tag(); + let input = args.input; + let bytes = input.collect_binary(tag.clone()).await?; match from_sqlite_bytes_to_value(bytes.item, tag.clone()) { Ok(x) => match x { diff --git a/crates/nu-cli/src/commands/from_ssv.rs b/crates/nu-cli/src/commands/from_ssv.rs index 04bf09800..c6d41c8dc 100644 --- a/crates/nu-cli/src/commands/from_ssv.rs +++ b/crates/nu-cli/src/commands/from_ssv.rs @@ -50,7 +50,7 @@ impl WholeStreamCommand for FromSSV { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, from_ssv)?.run() + from_ssv(args, registry) } } @@ -250,15 +250,11 @@ fn from_ssv_string_to_value( Some(UntaggedValue::Table(rows).into_value(&tag)) } -fn from_ssv( - FromSSVArgs { - headerless, - aligned_columns, - minimum_spaces, - }: FromSSVArgs, - RunnableContext { input, name, .. }: RunnableContext, -) -> Result { +fn from_ssv(args: CommandArgs, registry: &CommandRegistry) -> Result { + let name = args.call_info.name_tag.clone(); + let registry = registry.clone(); let stream = async_stream! { + let (FromSSVArgs { headerless, aligned_columns, minimum_spaces }, mut input) = args.process(®istry).await?; let concat_string = input.collect_string(name.clone()).await?; let split_at = match minimum_spaces { Some(number) => number.item, diff --git a/crates/nu-cli/src/commands/from_toml.rs b/crates/nu-cli/src/commands/from_toml.rs index 65b7897c5..e03d6373a 100644 --- a/crates/nu-cli/src/commands/from_toml.rs +++ b/crates/nu-cli/src/commands/from_toml.rs @@ -67,11 +67,12 @@ pub fn from_toml( args: CommandArgs, registry: &CommandRegistry, ) -> Result { - let args = args.evaluate_once(registry)?; - let tag = args.name_tag(); - let input = args.input; - + let registry = registry.clone(); let stream = async_stream! { + let args = args.evaluate_once(®istry).await?; + let tag = args.name_tag(); + let input = args.input; + let concat_string = input.collect_string(tag.clone()).await?; match from_toml_string_to_value(concat_string.item, tag.clone()) { Ok(x) => match x { diff --git a/crates/nu-cli/src/commands/from_tsv.rs b/crates/nu-cli/src/commands/from_tsv.rs index ecd484ead..014974a04 100644 --- a/crates/nu-cli/src/commands/from_tsv.rs +++ b/crates/nu-cli/src/commands/from_tsv.rs @@ -33,13 +33,21 @@ impl WholeStreamCommand for FromTSV { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, from_tsv)?.run() + from_tsv(args, registry) } } -fn from_tsv( - FromTSVArgs { headerless }: FromTSVArgs, - runnable_context: RunnableContext, -) -> Result { - from_delimited_data(headerless, '\t', "TSV", runnable_context) +fn from_tsv(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); + let name = args.call_info.name_tag.clone(); + let stream = async_stream! { + let (FromTSVArgs { headerless }, mut input) = args.process(®istry).await?; + let mut result = from_delimited_data(headerless, '\t', "TSV", input, name)?; + + while let Some(output) = result.next().await { + yield output; + } + }; + + Ok(stream.to_output_stream()) } diff --git a/crates/nu-cli/src/commands/from_url.rs b/crates/nu-cli/src/commands/from_url.rs index 84073ac56..bcbd30e5d 100644 --- a/crates/nu-cli/src/commands/from_url.rs +++ b/crates/nu-cli/src/commands/from_url.rs @@ -28,11 +28,12 @@ impl WholeStreamCommand for FromURL { } fn from_url(args: CommandArgs, registry: &CommandRegistry) -> Result { - let args = args.evaluate_once(registry)?; - let tag = args.name_tag(); - let input = args.input; - + let registry = registry.clone(); let stream = async_stream! { + let args = args.evaluate_once(®istry).await?; + let tag = args.name_tag(); + let input = args.input; + let concat_string = input.collect_string(tag.clone()).await?; let result = serde_urlencoded::from_str::>(&concat_string.item); diff --git a/crates/nu-cli/src/commands/from_vcf.rs b/crates/nu-cli/src/commands/from_vcf.rs index 82c94fac4..37aed643f 100644 --- a/crates/nu-cli/src/commands/from_vcf.rs +++ b/crates/nu-cli/src/commands/from_vcf.rs @@ -32,11 +32,12 @@ impl WholeStreamCommand for FromVcf { } fn from_vcf(args: CommandArgs, registry: &CommandRegistry) -> Result { - let args = args.evaluate_once(registry)?; - let tag = args.name_tag(); - let input = args.input; - + let registry = registry.clone(); let stream = async_stream! { + let args = args.evaluate_once(®istry).await?; + let tag = args.name_tag(); + let input = args.input; + let input_string = input.collect_string(tag.clone()).await?.item; let input_bytes = input_string.as_bytes(); let buf_reader = BufReader::new(input_bytes); diff --git a/crates/nu-cli/src/commands/from_xlsx.rs b/crates/nu-cli/src/commands/from_xlsx.rs index 983b185ea..9c82cbe05 100644 --- a/crates/nu-cli/src/commands/from_xlsx.rs +++ b/crates/nu-cli/src/commands/from_xlsx.rs @@ -35,20 +35,15 @@ impl WholeStreamCommand for FromXLSX { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, from_xlsx)?.run() + from_xlsx(args, registry) } } -fn from_xlsx( - FromXLSXArgs { - headerless: _headerless, - }: FromXLSXArgs, - runnable_context: RunnableContext, -) -> Result { - let input = runnable_context.input; - let tag = runnable_context.name; - +fn from_xlsx(args: CommandArgs, registry: &CommandRegistry) -> Result { + let tag = args.call_info.name_tag.clone(); + let registry = registry.clone(); let stream = async_stream! { + let (FromXLSXArgs { headerless: _headerless }, mut input) = args.process(®istry).await?; let value = input.collect_binary(tag.clone()).await?; let mut buf: Cursor> = Cursor::new(value.item); diff --git a/crates/nu-cli/src/commands/from_xml.rs b/crates/nu-cli/src/commands/from_xml.rs index 140444cd9..d125d7812 100644 --- a/crates/nu-cli/src/commands/from_xml.rs +++ b/crates/nu-cli/src/commands/from_xml.rs @@ -99,11 +99,12 @@ pub fn from_xml_string_to_value(s: String, tag: impl Into) -> Result Result { - let args = args.evaluate_once(registry)?; - let tag = args.name_tag(); - let input = args.input; - + let registry = registry.clone(); let stream = async_stream! { + let args = args.evaluate_once(®istry).await?; + let tag = args.name_tag(); + let input = args.input; + let concat_string = input.collect_string(tag.clone()).await?; match from_xml_string_to_value(concat_string.item, tag.clone()) { diff --git a/crates/nu-cli/src/commands/from_yaml.rs b/crates/nu-cli/src/commands/from_yaml.rs index 10c16d84f..fcabd28ad 100644 --- a/crates/nu-cli/src/commands/from_yaml.rs +++ b/crates/nu-cli/src/commands/from_yaml.rs @@ -119,11 +119,12 @@ pub fn from_yaml_string_to_value(s: String, tag: impl Into) -> Result Result { - let args = args.evaluate_once(registry)?; - let tag = args.name_tag(); - let input = args.input; - + let registry = registry.clone(); let stream = async_stream! { + let args = args.evaluate_once(®istry).await?; + let tag = args.name_tag(); + let input = args.input; + let concat_string = input.collect_string(tag.clone()).await?; match from_yaml_string_to_value(concat_string.item, tag.clone()) { diff --git a/crates/nu-cli/src/commands/get.rs b/crates/nu-cli/src/commands/get.rs index def162ced..fbf608c7e 100644 --- a/crates/nu-cli/src/commands/get.rs +++ b/crates/nu-cli/src/commands/get.rs @@ -4,8 +4,8 @@ use indexmap::set::IndexSet; use log::trace; use nu_errors::ShellError; use nu_protocol::{ - did_you_mean, ColumnPath, PathMember, Primitive, ReturnSuccess, ReturnValue, Signature, - SyntaxShape, UnspannedPathMember, UntaggedValue, Value, + did_you_mean, ColumnPath, PathMember, Primitive, ReturnSuccess, Signature, SyntaxShape, + UnspannedPathMember, UntaggedValue, Value, }; use nu_source::span_for_spanned_list; use nu_value_ext::get_data_by_column_path; @@ -38,7 +38,7 @@ impl WholeStreamCommand for Get { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, get)?.run() + get(args, registry) } fn examples(&self) -> &[Example] { @@ -189,30 +189,21 @@ pub fn get_column_path(path: &ColumnPath, obj: &Value) -> Result Result { - if fields.is_empty() { - let stream = async_stream! { +pub fn get(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); + let stream = async_stream! { + let (GetArgs { rest: mut fields }, mut input) = args.process(®istry).await?; + if fields.is_empty() { let mut vec = input.drain_vec().await; let descs = nu_protocol::merge_descriptors(&vec); for desc in descs { yield ReturnSuccess::value(desc); } - }; - - let stream: BoxStream<'static, ReturnValue> = stream.boxed(); - - Ok(stream.to_output_stream()) - } else { - let member = fields.remove(0); - trace!("get {:?} {:?}", member, fields); - let stream = input - .map(move |item| { - let mut result = VecDeque::new(); - + } else { + let member = fields.remove(0); + trace!("get {:?} {:?}", member, fields); + while let Some(item) = input.next().await { let member = vec![member.clone()]; let column_paths = vec![&member, &fields] @@ -230,25 +221,22 @@ pub fn get( .. } => { for item in rows { - result.push_back(ReturnSuccess::value(item.clone())); + yield ReturnSuccess::value(item.clone()); } } Value { value: UntaggedValue::Primitive(Primitive::Nothing), .. } => {} - other => result.push_back(ReturnSuccess::value(other.clone())), + other => yield ReturnSuccess::value(other.clone()), }, - Err(reason) => result.push_back(ReturnSuccess::value( + Err(reason) => yield ReturnSuccess::value( UntaggedValue::Error(reason).into_untagged_value(), - )), + ), } } - - futures::stream::iter(result) - }) - .flatten(); - - Ok(stream.to_output_stream()) - } + } + } + }; + Ok(stream.to_output_stream()) } diff --git a/crates/nu-cli/src/commands/group_by.rs b/crates/nu-cli/src/commands/group_by.rs index 235365c06..fc40ed5b4 100644 --- a/crates/nu-cli/src/commands/group_by.rs +++ b/crates/nu-cli/src/commands/group_by.rs @@ -33,7 +33,7 @@ impl WholeStreamCommand for GroupBy { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, group_by)?.run() + group_by(args, registry) } fn examples(&self) -> &[Example] { @@ -44,11 +44,11 @@ impl WholeStreamCommand for GroupBy { } } -pub fn group_by( - GroupByArgs { column_name }: GroupByArgs, - RunnableContext { input, name, .. }: RunnableContext, -) -> Result { +pub fn group_by(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); + let name = args.call_info.name_tag.clone(); let stream = async_stream! { + let (GroupByArgs { column_name }, mut input) = args.process(®istry).await?; let values: Vec = input.collect().await; if values.is_empty() { diff --git a/crates/nu-cli/src/commands/group_by_date.rs b/crates/nu-cli/src/commands/group_by_date.rs index 2bdae9f99..ec84441bb 100644 --- a/crates/nu-cli/src/commands/group_by_date.rs +++ b/crates/nu-cli/src/commands/group_by_date.rs @@ -41,7 +41,7 @@ impl WholeStreamCommand for GroupByDate { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, group_by_date)?.run() + group_by_date(args, registry) } fn examples(&self) -> &[Example] { @@ -57,13 +57,13 @@ enum Grouper { } pub fn group_by_date( - GroupByDateArgs { - column_name, - format, - }: GroupByDateArgs, - RunnableContext { input, name, .. }: RunnableContext, + args: CommandArgs, + registry: &CommandRegistry, ) -> Result { + let registry = registry.clone(); + let name = args.call_info.name_tag.clone(); let stream = async_stream! { + let (GroupByDateArgs { column_name, format }, mut input) = args.process(®istry).await?; let values: Vec = input.collect().await; if values.is_empty() { diff --git a/crates/nu-cli/src/commands/headers.rs b/crates/nu-cli/src/commands/headers.rs index 9e4748a1c..cb56a3baa 100644 --- a/crates/nu-cli/src/commands/headers.rs +++ b/crates/nu-cli/src/commands/headers.rs @@ -8,8 +8,6 @@ use nu_protocol::Dictionary; use nu_protocol::{ReturnSuccess, Signature, UntaggedValue, Value}; pub struct Headers; -#[derive(Deserialize)] -pub struct HeadersArgs {} impl WholeStreamCommand for Headers { fn name(&self) -> &str { @@ -29,7 +27,7 @@ impl WholeStreamCommand for Headers { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, headers)?.run() + headers(args, registry) } fn examples(&self) -> &[Example] { @@ -40,11 +38,9 @@ impl WholeStreamCommand for Headers { } } -pub fn headers( - HeadersArgs {}: HeadersArgs, - RunnableContext { input, .. }: RunnableContext, -) -> Result { +pub fn headers(args: CommandArgs, _registry: &CommandRegistry) -> Result { let stream = async_stream! { + let mut input = args.input; let rows: Vec = input.collect().await; if rows.len() < 1 { diff --git a/crates/nu-cli/src/commands/help.rs b/crates/nu-cli/src/commands/help.rs index 9f7076fe7..c1b857794 100644 --- a/crates/nu-cli/src/commands/help.rs +++ b/crates/nu-cli/src/commands/help.rs @@ -35,72 +35,70 @@ impl WholeStreamCommand for Help { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, help)?.run() + help(args, registry) } } -fn help( - HelpArgs { rest }: HelpArgs, - RunnableContext { registry, name, .. }: RunnableContext, -) -> Result { - if let Some(document) = rest.get(0) { - let mut help = VecDeque::new(); - if document.item == "commands" { - let mut sorted_names = registry.names(); - sorted_names.sort(); - for cmd in sorted_names { - // If it's a subcommand, don't list it during the commands list - if cmd.contains(' ') { - continue; - } - let mut short_desc = TaggedDictBuilder::new(name.clone()); - let document_tag = document.tag.clone(); - let value = command_dict( - registry.get_command(&cmd).ok_or_else(|| { - ShellError::labeled_error( - format!("Could not load {}", cmd), - "could not load command", - document_tag, - ) - })?, - name.clone(), - ); - - short_desc.insert_untagged("name", cmd); - short_desc.insert_untagged( - "description", - get_data_by_key(&value, "usage".spanned_unknown()) - .ok_or_else(|| { +fn help(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); + let name = args.call_info.name_tag.clone(); + let stream = async_stream! { + let (HelpArgs { rest }, mut input) = args.process(®istry).await?; + if let Some(document) = rest.get(0) { + if document.item == "commands" { + let mut sorted_names = registry.names(); + sorted_names.sort(); + for cmd in sorted_names { + // If it's a subcommand, don't list it during the commands list + if cmd.contains(' ') { + continue; + } + let mut short_desc = TaggedDictBuilder::new(name.clone()); + let document_tag = document.tag.clone(); + let value = command_dict( + registry.get_command(&cmd).ok_or_else(|| { ShellError::labeled_error( - "Expected a usage key", - "expected a 'usage' key", - &value.tag, + format!("Could not load {}", cmd), + "could not load command", + document_tag, ) - })? - .as_string()?, - ); + })?, + name.clone(), + ); - help.push_back(ReturnSuccess::value(short_desc.into_value())); + short_desc.insert_untagged("name", cmd); + short_desc.insert_untagged( + "description", + get_data_by_key(&value, "usage".spanned_unknown()) + .ok_or_else(|| { + ShellError::labeled_error( + "Expected a usage key", + "expected a 'usage' key", + &value.tag, + ) + })? + .as_string()?, + ); + + yield ReturnSuccess::value(short_desc.into_value()); + } + } else if rest.len() == 2 { + // Check for a subcommand + let command_name = format!("{} {}", rest[0].item, rest[1].item); + if let Some(command) = registry.get_command(&command_name) { + yield Ok(ReturnSuccess::Value(UntaggedValue::string(get_help(command.stream_command(), ®istry)).into_value(Tag::unknown()))); + } + } else if let Some(command) = registry.get_command(&document.item) { + yield Ok(ReturnSuccess::Value(UntaggedValue::string(get_help(command.stream_command(), ®istry)).into_value(Tag::unknown()))); + } else { + yield Err(ShellError::labeled_error( + "Can't find command (use 'help commands' for full list)", + "can't find command", + document.tag.span, + )); } - } else if rest.len() == 2 { - // Check for a subcommand - let command_name = format!("{} {}", rest[0].item, rest[1].item); - if let Some(command) = registry.get_command(&command_name) { - return Ok(get_help(command.stream_command(), ®istry).into()); - } - } else if let Some(command) = registry.get_command(&document.item) { - return Ok(get_help(command.stream_command(), ®istry).into()); } else { - return Err(ShellError::labeled_error( - "Can't find command (use 'help commands' for full list)", - "can't find command", - document.tag.span, - )); - } - let help = futures::stream::iter(help); - Ok(help.to_output_stream()) - } else { - let msg = r#"Welcome to Nushell. + let msg = r#"Welcome to Nushell. Here are some tips to help you get started. * help commands - list all available commands @@ -122,22 +120,17 @@ Get the processes on your system actively using CPU: You can also learn more at https://www.nushell.sh/book/"#; - let output_stream = futures::stream::iter(vec![ReturnSuccess::value( - UntaggedValue::string(msg).into_value(name), - )]); + yield Ok(ReturnSuccess::Value(UntaggedValue::string(msg).into_value(Tag::unknown()))); + } + }; - Ok(output_stream.to_output_stream()) - } + Ok(stream.to_output_stream()) } #[allow(clippy::cognitive_complexity)] -pub fn get_help( - cmd: &dyn WholeStreamCommand, - registry: &CommandRegistry, -) -> impl Into { +pub fn get_help(cmd: &dyn WholeStreamCommand, registry: &CommandRegistry) -> String { let cmd_name = cmd.name(); let signature = cmd.signature(); - let mut help = VecDeque::new(); let mut long_desc = String::new(); long_desc.push_str(&cmd.usage()); @@ -285,8 +278,5 @@ pub fn get_help( long_desc.push_str("\n"); - help.push_back(ReturnSuccess::value( - UntaggedValue::string(long_desc).into_value(Tag::from((0, cmd_name.len(), None))), - )); - help + long_desc } diff --git a/crates/nu-cli/src/commands/histogram.rs b/crates/nu-cli/src/commands/histogram.rs index b650d02d5..361ff5dde 100644 --- a/crates/nu-cli/src/commands/histogram.rs +++ b/crates/nu-cli/src/commands/histogram.rs @@ -44,7 +44,7 @@ impl WholeStreamCommand for Histogram { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, histogram)?.run() + histogram(args, registry) } fn examples(&self) -> &[Example] { @@ -67,10 +67,13 @@ impl WholeStreamCommand for Histogram { } pub fn histogram( - HistogramArgs { column_name, rest }: HistogramArgs, - RunnableContext { input, name, .. }: RunnableContext, + args: CommandArgs, + registry: &CommandRegistry, ) -> Result { + let registry = registry.clone(); + let name = args.call_info.name_tag.clone(); let stream = async_stream! { + let (HistogramArgs { column_name, rest}, mut input) = args.process(®istry).await?; let values: Vec = input.collect().await; let Tagged { item: group_by, .. } = column_name.clone(); diff --git a/crates/nu-cli/src/commands/history.rs b/crates/nu-cli/src/commands/history.rs index 0c11a1952..60d5e37e4 100644 --- a/crates/nu-cli/src/commands/history.rs +++ b/crates/nu-cli/src/commands/history.rs @@ -8,9 +8,6 @@ use std::io::{BufRead, BufReader}; pub struct History; -#[derive(Deserialize)] -pub struct HistoryArgs {} - impl WholeStreamCommand for History { fn name(&self) -> &str { "history" @@ -29,14 +26,12 @@ impl WholeStreamCommand for History { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, history)?.run() + history(args, registry) } } -fn history( - _: HistoryArgs, - RunnableContext { name: tag, .. }: RunnableContext, -) -> Result { +fn history(args: CommandArgs, _registry: &CommandRegistry) -> Result { + let tag = args.call_info.name_tag; let stream = async_stream! { let history_path = HistoryFile::path(); let file = File::open(history_path); diff --git a/crates/nu-cli/src/commands/insert.rs b/crates/nu-cli/src/commands/insert.rs index 7fd5869e1..beb65f10d 100644 --- a/crates/nu-cli/src/commands/insert.rs +++ b/crates/nu-cli/src/commands/insert.rs @@ -41,17 +41,15 @@ impl WholeStreamCommand for Insert { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, insert)?.run() + insert(args, registry) } } -fn insert( - InsertArgs { column, value }: InsertArgs, - RunnableContext { input, .. }: RunnableContext, -) -> Result { - let mut input = input; +fn insert(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); let stream = async_stream! { + let (InsertArgs { column, value }, mut input) = args.process(®istry).await?; match input.next().await { Some(obj @ Value { value: UntaggedValue::Row(_), diff --git a/crates/nu-cli/src/commands/is_empty.rs b/crates/nu-cli/src/commands/is_empty.rs index d38740449..ff0e3d520 100644 --- a/crates/nu-cli/src/commands/is_empty.rs +++ b/crates/nu-cli/src/commands/is_empty.rs @@ -41,16 +41,15 @@ impl WholeStreamCommand for IsEmpty { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, is_empty)?.run() + is_empty(args, registry) } } -fn is_empty( - IsEmptyArgs { rest }: IsEmptyArgs, - RunnableContext { input, .. }: RunnableContext, -) -> Result { - Ok(input - .map(move |value| { +fn is_empty(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); + let stream = async_stream! { + let (IsEmptyArgs { rest }, mut input) = args.process(®istry).await?; + while let Some(value) = input.next().await { let value_tag = value.tag(); let action = if rest.len() <= 2 { @@ -85,7 +84,7 @@ fn is_empty( }; match action { - IsEmptyFor::Value => Ok(ReturnSuccess::Value( + IsEmptyFor::Value => yield Ok(ReturnSuccess::Value( UntaggedValue::boolean(value.is_empty()).into_value(value_tag), )), IsEmptyFor::RowWithFieldsAndFallback(fields, default) => { @@ -93,7 +92,7 @@ fn is_empty( for field in fields.iter() { let val = - out.get_data_by_column_path(&field, Box::new(move |(_, _, err)| err))?; + crate::commands::get::get_column_path(&field, &out)?; let emptiness_value = match out { obj @@ -125,11 +124,11 @@ fn is_empty( out = emptiness_value?; } - Ok(ReturnSuccess::Value(out)) + yield Ok(ReturnSuccess::Value(out)) } IsEmptyFor::RowWithField(field) => { let val = - value.get_data_by_column_path(&field, Box::new(move |(_, _, err)| err))?; + crate::commands::get::get_column_path(&field, &value)?; match &value { obj @@ -143,18 +142,18 @@ fn is_empty( &field, UntaggedValue::boolean(true).into_value(&value_tag), ) { - Some(v) => Ok(ReturnSuccess::Value(v)), - None => Err(ShellError::labeled_error( + Some(v) => yield Ok(ReturnSuccess::Value(v)), + None => yield Err(ShellError::labeled_error( "empty? could not find place to check emptiness", "column name", &field.tag, )), } } else { - Ok(ReturnSuccess::Value(value)) + yield Ok(ReturnSuccess::Value(value)) } } - _ => Err(ShellError::labeled_error( + _ => yield Err(ShellError::labeled_error( "Unrecognized type in stream", "original value", &value_tag, @@ -163,7 +162,7 @@ fn is_empty( } IsEmptyFor::RowWithFieldAndFallback(field, default) => { let val = - value.get_data_by_column_path(&field, Box::new(move |(_, _, err)| err))?; + crate::commands::get::get_column_path(&field, &value)?; match &value { obj @@ -174,18 +173,18 @@ fn is_empty( } => { if val.is_empty() { match obj.replace_data_at_column_path(&field, default) { - Some(v) => Ok(ReturnSuccess::Value(v)), - None => Err(ShellError::labeled_error( + Some(v) => yield Ok(ReturnSuccess::Value(v)), + None => yield Err(ShellError::labeled_error( "empty? could not find place to check emptiness", "column name", &field.tag, )), } } else { - Ok(ReturnSuccess::Value(value)) + yield Ok(ReturnSuccess::Value(value)) } } - _ => Err(ShellError::labeled_error( + _ => yield Err(ShellError::labeled_error( "Unrecognized type in stream", "original value", &value_tag, @@ -193,6 +192,7 @@ fn is_empty( } } } - }) - .to_output_stream()) + } + }; + Ok(stream.to_output_stream()) } diff --git a/crates/nu-cli/src/commands/keep.rs b/crates/nu-cli/src/commands/keep.rs index 982320a0c..be7df636d 100644 --- a/crates/nu-cli/src/commands/keep.rs +++ b/crates/nu-cli/src/commands/keep.rs @@ -2,7 +2,7 @@ use crate::commands::WholeStreamCommand; use crate::context::CommandRegistry; use crate::prelude::*; use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape}; +use nu_protocol::{ReturnSuccess, Signature, SyntaxShape}; use nu_source::Tagged; pub struct Keep; @@ -34,7 +34,7 @@ impl WholeStreamCommand for Keep { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, keep)?.run() + keep(args, registry) } fn examples(&self) -> &[Example] { @@ -51,12 +51,25 @@ impl WholeStreamCommand for Keep { } } -fn keep(KeepArgs { rows }: KeepArgs, context: RunnableContext) -> Result { - let rows_desired = if let Some(quantity) = rows { - *quantity - } else { - 1 +fn keep(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); + let stream = async_stream! { + let (KeepArgs { rows }, mut input) = args.process(®istry).await?; + let mut rows_desired = if let Some(quantity) = rows { + *quantity + } else { + 1 + }; + + while let Some(input) = input.next().await { + if rows_desired > 0 { + yield ReturnSuccess::value(input); + rows_desired -= 1; + } else { + break; + } + } }; - Ok(OutputStream::from_input(context.input.take(rows_desired))) + Ok(stream.to_output_stream()) } diff --git a/crates/nu-cli/src/commands/keep_until.rs b/crates/nu-cli/src/commands/keep_until.rs index 3ede81b10..9c72c289c 100644 --- a/crates/nu-cli/src/commands/keep_until.rs +++ b/crates/nu-cli/src/commands/keep_until.rs @@ -3,7 +3,9 @@ use crate::evaluate::evaluate_baseline_expr; use crate::prelude::*; use log::trace; use nu_errors::ShellError; -use nu_protocol::{hir::ClassifiedCommand, Signature, SyntaxShape, UntaggedValue, Value}; +use nu_protocol::{ + hir::ClassifiedCommand, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value, +}; pub struct KeepUntil; @@ -33,66 +35,77 @@ impl WholeStreamCommand for KeepUntil { ) -> Result { let registry = registry.clone(); let scope = args.call_info.scope.clone(); - let call_info = args.evaluate_once(®istry)?; + let stream = async_stream! { + let mut call_info = args.evaluate_once(®istry).await?; - let block = call_info.args.expect_nth(0)?.clone(); + let block = call_info.args.expect_nth(0)?.clone(); - let condition = match block { - Value { - value: UntaggedValue::Block(block), - tag, - } => { - if block.block.len() != 1 { - return Err(ShellError::labeled_error( - "Expected a condition", - "expected a condition", - tag, - )); - } - match block.block[0].list.get(0) { - Some(item) => match item { - ClassifiedCommand::Expr(expr) => expr.clone(), - _ => { - return Err(ShellError::labeled_error( - "Expected a condition", - "expected a condition", - tag, - )) - } - }, - None => { - return Err(ShellError::labeled_error( + let condition = match block { + Value { + value: UntaggedValue::Block(block), + tag, + } => { + if block.block.len() != 1 { + yield Err(ShellError::labeled_error( "Expected a condition", "expected a condition", tag, )); + return; + } + match block.block[0].list.get(0) { + Some(item) => match item { + ClassifiedCommand::Expr(expr) => expr.clone(), + _ => { + yield Err(ShellError::labeled_error( + "Expected a condition", + "expected a condition", + tag, + )); + return; + } + }, + None => { + yield Err(ShellError::labeled_error( + "Expected a condition", + "expected a condition", + tag, + )); + return; + } } } - } - Value { tag, .. } => { - return Err(ShellError::labeled_error( - "Expected a condition", - "expected a condition", - tag, - )); + Value { tag, .. } => { + yield Err(ShellError::labeled_error( + "Expected a condition", + "expected a condition", + tag, + )); + return; + } + }; + + while let Some(item) = call_info.input.next().await { + let condition = condition.clone(); + trace!("ITEM = {:?}", item); + let result = + evaluate_baseline_expr(&*condition, ®istry, &scope.clone().set_it(item.clone())) + .await; + trace!("RESULT = {:?}", result); + + let return_value = match result { + Ok(ref v) if v.is_true() => false, + _ => true, + }; + + if return_value { + yield ReturnSuccess::value(item); + } else { + break; + } } }; - let objects = call_info.input.take_while(move |item| { - let condition = condition.clone(); - trace!("ITEM = {:?}", item); - let result = - evaluate_baseline_expr(&*condition, ®istry, &scope.clone().set_it(item.clone())); - trace!("RESULT = {:?}", result); - - let return_value = match result { - Ok(ref v) if v.is_true() => false, - _ => true, - }; - - futures::future::ready(return_value) - }); - - Ok(objects.from_input_stream()) + Ok(stream.to_output_stream()) } } diff --git a/crates/nu-cli/src/commands/keep_while.rs b/crates/nu-cli/src/commands/keep_while.rs index 5b8ee693b..e45b57102 100644 --- a/crates/nu-cli/src/commands/keep_while.rs +++ b/crates/nu-cli/src/commands/keep_while.rs @@ -3,7 +3,9 @@ use crate::evaluate::evaluate_baseline_expr; use crate::prelude::*; use log::trace; use nu_errors::ShellError; -use nu_protocol::{hir::ClassifiedCommand, Signature, SyntaxShape, UntaggedValue, Value}; +use nu_protocol::{ + hir::ClassifiedCommand, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value, +}; pub struct KeepWhile; @@ -33,66 +35,77 @@ impl WholeStreamCommand for KeepWhile { ) -> Result { let registry = registry.clone(); let scope = args.call_info.scope.clone(); - let call_info = args.evaluate_once(®istry)?; + let stream = async_stream! { + let mut call_info = args.evaluate_once(®istry).await?; - let block = call_info.args.expect_nth(0)?.clone(); + let block = call_info.args.expect_nth(0)?.clone(); - let condition = match block { - Value { - value: UntaggedValue::Block(block), - tag, - } => { - if block.block.len() != 1 { - return Err(ShellError::labeled_error( - "Expected a condition", - "expected a condition", - tag, - )); - } - match block.block[0].list.get(0) { - Some(item) => match item { - ClassifiedCommand::Expr(expr) => expr.clone(), - _ => { - return Err(ShellError::labeled_error( - "Expected a condition", - "expected a condition", - tag, - )) - } - }, - None => { - return Err(ShellError::labeled_error( + let condition = match block { + Value { + value: UntaggedValue::Block(block), + tag, + } => { + if block.block.len() != 1 { + yield Err(ShellError::labeled_error( "Expected a condition", "expected a condition", tag, )); + return; + } + match block.block[0].list.get(0) { + Some(item) => match item { + ClassifiedCommand::Expr(expr) => expr.clone(), + _ => { + yield Err(ShellError::labeled_error( + "Expected a condition", + "expected a condition", + tag, + )); + return; + } + }, + None => { + yield Err(ShellError::labeled_error( + "Expected a condition", + "expected a condition", + tag, + )); + return; + } } } - } - Value { tag, .. } => { - return Err(ShellError::labeled_error( - "Expected a condition", - "expected a condition", - tag, - )); + Value { tag, .. } => { + yield Err(ShellError::labeled_error( + "Expected a condition", + "expected a condition", + tag, + )); + return; + } + }; + + while let Some(item) = call_info.input.next().await { + let condition = condition.clone(); + trace!("ITEM = {:?}", item); + let result = + evaluate_baseline_expr(&*condition, ®istry, &scope.clone().set_it(item.clone())) + .await; + trace!("RESULT = {:?}", result); + + let return_value = match result { + Ok(ref v) if v.is_true() => true, + _ => false, + }; + + if return_value { + yield ReturnSuccess::value(item); + } else { + break; + } } }; - let objects = call_info.input.take_while(move |item| { - let condition = condition.clone(); - trace!("ITEM = {:?}", item); - let result = - evaluate_baseline_expr(&*condition, ®istry, &scope.clone().set_it(item.clone())); - trace!("RESULT = {:?}", result); - - let return_value = match result { - Ok(ref v) if v.is_true() => true, - _ => false, - }; - - futures::future::ready(return_value) - }); - - Ok(objects.from_input_stream()) + Ok(stream.to_output_stream()) } } diff --git a/crates/nu-cli/src/commands/kill.rs b/crates/nu-cli/src/commands/kill.rs index 6aab7e8ef..9053e44c6 100644 --- a/crates/nu-cli/src/commands/kill.rs +++ b/crates/nu-cli/src/commands/kill.rs @@ -2,7 +2,7 @@ use crate::commands::WholeStreamCommand; use crate::context::CommandRegistry; use crate::prelude::*; use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape}; +use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue}; use nu_source::Tagged; use std::process::{Command, Stdio}; @@ -42,7 +42,7 @@ impl WholeStreamCommand for Kill { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, kill)?.run() + kill(args, registry) } fn examples(&self) -> &[Example] { @@ -59,55 +59,61 @@ impl WholeStreamCommand for Kill { } } -fn kill( - KillArgs { - pid, - rest, - force, - quiet, - }: KillArgs, - _context: RunnableContext, -) -> Result { - let mut cmd = if cfg!(windows) { - let mut cmd = Command::new("taskkill"); +fn kill(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); - if *force { - cmd.arg("/F"); - } + let stream = async_stream! { + let (KillArgs { + pid, + rest, + force, + quiet, + }, mut input) = args.process(®istry).await?; + let mut cmd = if cfg!(windows) { + let mut cmd = Command::new("taskkill"); - cmd.arg("/PID"); - cmd.arg(pid.item().to_string()); + if *force { + cmd.arg("/F"); + } - // each pid must written as `/PID 0` otherwise - // taskkill will act as `killall` unix command - for id in &rest { cmd.arg("/PID"); - cmd.arg(id.item().to_string()); + cmd.arg(pid.item().to_string()); + + // each pid must written as `/PID 0` otherwise + // taskkill will act as `killall` unix command + for id in &rest { + cmd.arg("/PID"); + cmd.arg(id.item().to_string()); + } + + cmd + } else { + let mut cmd = Command::new("kill"); + + if *force { + cmd.arg("-9"); + } + + cmd.arg(pid.item().to_string()); + + cmd.args(rest.iter().map(move |id| id.item().to_string())); + + cmd + }; + + // pipe everything to null + if *quiet { + cmd.stdin(Stdio::null()) + .stdout(Stdio::null()) + .stderr(Stdio::null()); } - cmd - } else { - let mut cmd = Command::new("kill"); + cmd.status().expect("failed to execute shell command"); - if *force { - cmd.arg("-9"); + if false { + yield ReturnSuccess::value(UntaggedValue::nothing().into_value(Tag::unknown())); } - - cmd.arg(pid.item().to_string()); - - cmd.args(rest.iter().map(move |id| id.item().to_string())); - - cmd }; - // pipe everything to null - if *quiet { - cmd.stdin(Stdio::null()) - .stdout(Stdio::null()) - .stderr(Stdio::null()); - } - - cmd.status().expect("failed to execute shell command"); - - Ok(OutputStream::empty()) + Ok(stream.to_output_stream()) } diff --git a/crates/nu-cli/src/commands/last.rs b/crates/nu-cli/src/commands/last.rs index e914f0293..0b30dcc30 100644 --- a/crates/nu-cli/src/commands/last.rs +++ b/crates/nu-cli/src/commands/last.rs @@ -34,7 +34,7 @@ impl WholeStreamCommand for Last { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, last)?.run() + last(args, registry) } fn examples(&self) -> &[Example] { @@ -51,9 +51,11 @@ impl WholeStreamCommand for Last { } } -fn last(LastArgs { rows }: LastArgs, context: RunnableContext) -> Result { +fn last(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); let stream = async_stream! { - let v: Vec<_> = context.input.into_vec().await; + let (LastArgs { rows }, mut input) = args.process(®istry).await?; + let v: Vec<_> = input.into_vec().await; let rows_desired = if let Some(quantity) = rows { *quantity diff --git a/crates/nu-cli/src/commands/lines.rs b/crates/nu-cli/src/commands/lines.rs index 34aa74f6d..cebdc1acf 100644 --- a/crates/nu-cli/src/commands/lines.rs +++ b/crates/nu-cli/src/commands/lines.rs @@ -45,14 +45,14 @@ fn ends_with_line_ending(st: &str) -> bool { } fn lines(args: CommandArgs, registry: &CommandRegistry) -> Result { - let args = args.evaluate_once(registry)?; - let tag = args.name_tag(); - let name_span = tag.span; - let mut input = args.input; - let mut leftover = vec![]; let mut leftover_string = String::new(); + let registry = registry.clone(); let stream = async_stream! { + let args = args.evaluate_once(®istry).await.unwrap(); + let tag = args.name_tag(); + let name_span = tag.span; + let mut input = args.input; loop { match input.next().await { Some(Value { value: UntaggedValue::Primitive(Primitive::String(st)), ..}) => { diff --git a/crates/nu-cli/src/commands/ls.rs b/crates/nu-cli/src/commands/ls.rs index d167c0a49..2094f39c1 100644 --- a/crates/nu-cli/src/commands/ls.rs +++ b/crates/nu-cli/src/commands/ls.rs @@ -64,7 +64,7 @@ impl WholeStreamCommand for Ls { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, ls)?.run() + ls(args, registry) } fn examples(&self) -> &[Example] { @@ -85,6 +85,19 @@ impl WholeStreamCommand for Ls { } } -fn ls(args: LsArgs, context: RunnableContext) -> Result { - context.shell_manager.ls(args, &context) +fn ls(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); + let stream = async_stream! { + let name = args.call_info.name_tag.clone(); + let ctrl_c = args.ctrl_c.clone(); + let shell_manager = args.shell_manager.clone(); + let (args, _) = args.process(®istry).await?; + let mut result = shell_manager.ls(args, name, ctrl_c)?; + + while let Some(item) = result.next().await { + yield item; + } + }; + + Ok(stream.to_output_stream()) } diff --git a/crates/nu-cli/src/commands/map_max_by.rs b/crates/nu-cli/src/commands/map_max_by.rs index 23a751c0d..e0ddb7b56 100644 --- a/crates/nu-cli/src/commands/map_max_by.rs +++ b/crates/nu-cli/src/commands/map_max_by.rs @@ -37,18 +37,20 @@ impl WholeStreamCommand for MapMaxBy { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, map_max_by)?.run() + map_max_by(args, registry) } } pub fn map_max_by( - MapMaxByArgs { column_name }: MapMaxByArgs, - RunnableContext { input, name, .. }: RunnableContext, + args: CommandArgs, + registry: &CommandRegistry, ) -> Result { + let registry = registry.clone(); + let name = args.call_info.name_tag.clone(); let stream = async_stream! { + let (MapMaxByArgs { column_name }, mut input) = args.process(®istry).await?; let values: Vec = input.collect().await; - if values.is_empty() { yield Err(ShellError::labeled_error( "Expected table from pipeline", diff --git a/crates/nu-cli/src/commands/merge.rs b/crates/nu-cli/src/commands/merge.rs index bd3bdcf8c..f77bf6687 100644 --- a/crates/nu-cli/src/commands/merge.rs +++ b/crates/nu-cli/src/commands/merge.rs @@ -36,7 +36,7 @@ impl WholeStreamCommand for Merge { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - Ok(args.process_raw(registry, merge)?.run()) + merge(args, registry) } fn examples(&self) -> &[Example] { @@ -47,19 +47,15 @@ impl WholeStreamCommand for Merge { } } -fn merge( - merge_args: MergeArgs, - context: RunnableContext, - raw_args: RawCommandArgs, -) -> Result { - let block = merge_args.block; - let registry = context.registry.clone(); - let mut input = context.input; - let scope = raw_args.call_info.scope.clone(); - - let mut context = Context::from_raw(&raw_args, ®istry); - +fn merge(raw_args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); let stream = async_stream! { + let mut context = Context::from_raw(&raw_args, ®istry); + let name_tag = raw_args.call_info.name_tag.clone(); + let scope = raw_args.call_info.scope.clone(); + let (merge_args, mut input): (MergeArgs, _) = raw_args.process(®istry).await?; + let block = merge_args.block; + let table: Option> = match run_block(&block, &mut context, InputStream::empty(), @@ -74,7 +70,7 @@ fn merge( let table = table.unwrap_or_else(|| vec![Value { value: UntaggedValue::row(IndexMap::default()), - tag: raw_args.call_info.name_tag, + tag: name_tag, }]); let mut idx = 0; diff --git a/crates/nu-cli/src/commands/mkdir.rs b/crates/nu-cli/src/commands/mkdir.rs index d967e7d51..03ba04d55 100644 --- a/crates/nu-cli/src/commands/mkdir.rs +++ b/crates/nu-cli/src/commands/mkdir.rs @@ -31,7 +31,7 @@ impl WholeStreamCommand for Mkdir { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, mkdir)?.run() + mkdir(args, registry) } fn examples(&self) -> &[Example] { @@ -42,7 +42,18 @@ impl WholeStreamCommand for Mkdir { } } -fn mkdir(args: MkdirArgs, context: RunnableContext) -> Result { - let shell_manager = context.shell_manager.clone(); - shell_manager.mkdir(args, &context) +fn mkdir(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); + let stream = async_stream! { + let name = args.call_info.name_tag.clone(); + let shell_manager = args.shell_manager.clone(); + let (args, _) = args.process(®istry).await?; + let mut result = shell_manager.mkdir(args, name)?; + + while let Some(item) = result.next().await { + yield item; + } + }; + + Ok(stream.to_output_stream()) } diff --git a/crates/nu-cli/src/commands/mv.rs b/crates/nu-cli/src/commands/mv.rs index 3b2452393..dfa79fe04 100644 --- a/crates/nu-cli/src/commands/mv.rs +++ b/crates/nu-cli/src/commands/mv.rs @@ -42,7 +42,7 @@ impl WholeStreamCommand for Move { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, mv)?.run() + mv(args, registry) } fn examples(&self) -> &[Example] { @@ -63,7 +63,18 @@ impl WholeStreamCommand for Move { } } -fn mv(args: MoveArgs, context: RunnableContext) -> Result { - let shell_manager = context.shell_manager.clone(); - shell_manager.mv(args, &context) +fn mv(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); + let stream = async_stream! { + let name = args.call_info.name_tag.clone(); + let shell_manager = args.shell_manager.clone(); + let (args, _) = args.process(®istry).await?; + let mut result = shell_manager.mv(args, name)?; + + while let Some(item) = result.next().await { + yield item; + } + }; + + Ok(stream.to_output_stream()) } diff --git a/crates/nu-cli/src/commands/nth.rs b/crates/nu-cli/src/commands/nth.rs index 60cd6e6d0..5606f1ce1 100644 --- a/crates/nu-cli/src/commands/nth.rs +++ b/crates/nu-cli/src/commands/nth.rs @@ -37,7 +37,7 @@ impl WholeStreamCommand for Nth { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, nth)?.run() + nth(args, registry) } fn examples(&self) -> &[Example] { @@ -54,16 +54,13 @@ impl WholeStreamCommand for Nth { } } -fn nth( - NthArgs { - row_number, - rest: and_rows, - }: NthArgs, - RunnableContext { input, .. }: RunnableContext, -) -> Result { - let stream = input - .enumerate() - .map(move |(idx, item)| { +fn nth(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); + let stream = async_stream! { + let (NthArgs { row_number, rest: and_rows}, input) = args.process(®istry).await?; + + let mut inp = input.enumerate(); + while let Some((idx, item)) = inp.next().await { let row_number = vec![row_number.clone()]; let row_numbers = vec![&row_number, &and_rows] @@ -71,18 +68,14 @@ fn nth( .flatten() .collect::>>(); - let mut result = VecDeque::new(); - if row_numbers .iter() .any(|requested| requested.item == idx as u64) { - result.push_back(ReturnSuccess::value(item)); + yield ReturnSuccess::value(item); } - - futures::stream::iter(result) - }) - .flatten(); + } + }; Ok(stream.to_output_stream()) } diff --git a/crates/nu-cli/src/commands/open.rs b/crates/nu-cli/src/commands/open.rs index 1ad09eff6..c18b9159c 100644 --- a/crates/nu-cli/src/commands/open.rs +++ b/crates/nu-cli/src/commands/open.rs @@ -41,19 +41,17 @@ impl WholeStreamCommand for Open { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, open)?.run() + open(args, registry) } } -fn open( - OpenArgs { path, raw }: OpenArgs, - RunnableContext { shell_manager, .. }: RunnableContext, -) -> Result { - let cwd = PathBuf::from(shell_manager.path()); +fn open(args: CommandArgs, registry: &CommandRegistry) -> Result { + let cwd = PathBuf::from(args.shell_manager.path()); let full_path = cwd; + let registry = registry.clone(); let stream = async_stream! { - + let (OpenArgs { path, raw }, _) = args.process(®istry).await?; let result = fetch(&full_path, &path.item, path.tag.span).await; if let Err(e) = result { diff --git a/crates/nu-cli/src/commands/parse.rs b/crates/nu-cli/src/commands/parse.rs deleted file mode 100644 index 0a11c2ed5..000000000 --- a/crates/nu-cli/src/commands/parse.rs +++ /dev/null @@ -1,167 +0,0 @@ -use crate::commands::WholeStreamCommand; -use crate::context::CommandRegistry; -use crate::prelude::*; -use nu_errors::ShellError; -use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, TaggedDictBuilder, UntaggedValue}; -use nu_source::Tagged; -use regex::Regex; - -#[derive(Debug)] -enum ParseCommand { - Text(String), - Column(String), -} - -fn parse(input: &str) -> Vec { - let mut output = vec![]; - - //let mut loop_input = input; - let mut loop_input = input.chars(); - loop { - let mut before = String::new(); - - while let Some(c) = loop_input.next() { - if c == '{' { - break; - } - before.push(c); - } - - if !before.is_empty() { - output.push(ParseCommand::Text(before.to_string())); - } - // Look for column as we're now at one - let mut column = String::new(); - - while let Some(c) = loop_input.next() { - if c == '}' { - break; - } - column.push(c); - } - - if !column.is_empty() { - output.push(ParseCommand::Column(column.to_string())); - } - - if before.is_empty() && column.is_empty() { - break; - } - } - - output -} - -fn column_names(commands: &[ParseCommand]) -> Vec { - let mut output = vec![]; - - for command in commands { - if let ParseCommand::Column(c) = command { - output.push(c.clone()); - } - } - - output -} - -fn build_regex(commands: &[ParseCommand]) -> String { - let mut output = String::new(); - - for command in commands { - match command { - ParseCommand::Text(s) => { - output.push_str(&s.replace("(", "\\(")); - } - ParseCommand::Column(_) => { - output.push_str("(.*)"); - } - } - } - - output -} -pub struct Parse; - -#[derive(Deserialize)] -pub struct ParseArgs { - pattern: Tagged, -} - -impl WholeStreamCommand for Parse { - fn name(&self) -> &str { - "parse" - } - - fn signature(&self) -> Signature { - Signature::build("parse").required( - "pattern", - SyntaxShape::String, - "the pattern to match. Eg) \"{foo}: {bar}\"", - ) - } - - fn usage(&self) -> &str { - "Parse columns from string data using a simple pattern." - } - - fn run( - &self, - args: CommandArgs, - registry: &CommandRegistry, - ) -> Result { - args.process(registry, parse_command)?.run() - } - - fn examples(&self) -> &[Example] { - &[Example { - description: "Parse values from a string into a table", - example: r#"echo "data: 123" | parse "{key}: {value}""#, - }] - } -} - -fn parse_command( - ParseArgs { pattern }: ParseArgs, - RunnableContext { name, input, .. }: RunnableContext, -) -> Result { - let parse_pattern = parse(&pattern.item); - let parse_regex = build_regex(&parse_pattern); - let column_names = column_names(&parse_pattern); - let name = name.span; - let regex = Regex::new(&parse_regex).map_err(|_| { - ShellError::labeled_error( - "Could not parse regex", - "could not parse regex", - &pattern.tag, - ) - })?; - - Ok(input - .map(move |value| { - if let Ok(s) = value.as_string() { - let mut output = vec![]; - for cap in regex.captures_iter(&s) { - let mut dict = TaggedDictBuilder::new(value.tag()); - for (idx, column_name) in column_names.iter().enumerate() { - dict.insert_untagged( - column_name, - UntaggedValue::string(cap[idx + 1].to_string()), - ); - } - output.push(Ok(ReturnSuccess::Value(dict.into_value()))); - } - output - } else { - vec![Err(ShellError::labeled_error_with_secondary( - "Expected string input", - "expected string input", - name, - "value originated here", - value.tag, - ))] - } - }) - .map(futures::stream::iter) - .flatten() - .to_output_stream()) -} diff --git a/crates/nu-cli/src/commands/pivot.rs b/crates/nu-cli/src/commands/pivot.rs index 8b5efbe9d..894971e64 100644 --- a/crates/nu-cli/src/commands/pivot.rs +++ b/crates/nu-cli/src/commands/pivot.rs @@ -50,20 +50,23 @@ impl WholeStreamCommand for Pivot { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, pivot)?.run() + pivot(args, registry) } } -pub fn pivot(args: PivotArgs, context: RunnableContext) -> Result { +pub fn pivot(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); + let name = args.call_info.name_tag.clone(); let stream = async_stream! { - let input = context.input.into_vec().await; + let (args, mut input): (PivotArgs, _) = args.process(®istry).await?; + let input = input.into_vec().await; let descs = merge_descriptors(&input); let mut headers: Vec = vec![]; if args.rest.len() > 0 && args.header_row { - yield Err(ShellError::labeled_error("Can not provide header names and use header row", "using header row", context.name)); + yield Err(ShellError::labeled_error("Can not provide header names and use header row", "using header row", name)); return; } @@ -75,17 +78,17 @@ pub fn pivot(args: PivotArgs, context: RunnableContext) -> Result { - yield Err(ShellError::labeled_error("Header row is incomplete and can't be used", "using incomplete header row", context.name)); + yield Err(ShellError::labeled_error("Header row is incomplete and can't be used", "using incomplete header row", name)); return; } } } else { - yield Err(ShellError::labeled_error("Header row is incomplete and can't be used", "using incomplete header row", context.name)); + yield Err(ShellError::labeled_error("Header row is incomplete and can't be used", "using incomplete header row", name)); return; } } @@ -107,7 +110,7 @@ pub fn pivot(args: PivotArgs, context: RunnableContext) -> Result Result { trace!("filter_plugin :: {}", path); + let registry = registry.clone(); - let scope = &args + let scope = args .call_info .scope .clone() .set_it(UntaggedValue::string("$it").into_untagged_value()); - let args = args.evaluate_once_with_scope(registry, &scope)?; + let stream = async_stream! { + let mut args = args.evaluate_once_with_scope(®istry, &scope).await?; - let mut child = std::process::Command::new(path) - .stdin(std::process::Stdio::piped()) - .stdout(std::process::Stdio::piped()) - .spawn() - .expect("Failed to spawn child process"); + let mut child = std::process::Command::new(path) + .stdin(std::process::Stdio::piped()) + .stdout(std::process::Stdio::piped()) + .spawn() + .expect("Failed to spawn child process"); - let mut bos: VecDeque = VecDeque::new(); - bos.push_back(UntaggedValue::Primitive(Primitive::BeginningOfStream).into_untagged_value()); - let bos = futures::stream::iter(bos); + let call_info = args.call_info.clone(); - let mut eos: VecDeque = VecDeque::new(); - eos.push_back(UntaggedValue::Primitive(Primitive::EndOfStream).into_untagged_value()); - let eos = futures::stream::iter(eos); + trace!("filtering :: {:?}", call_info); - let call_info = args.call_info.clone(); + // Beginning of the stream + { + let stdin = child.stdin.as_mut().expect("Failed to open stdin"); + let stdout = child.stdout.as_mut().expect("Failed to open stdout"); - trace!("filtering :: {:?}", call_info); + let mut reader = BufReader::new(stdout); - let stream = bos - .chain(args.input) - .chain(eos) - .map(move |v| match v { - Value { - value: UntaggedValue::Primitive(Primitive::BeginningOfStream), - .. - } => { - let stdin = child.stdin.as_mut().expect("Failed to open stdin"); - let stdout = child.stdout.as_mut().expect("Failed to open stdout"); + let request = JsonRpc::new("begin_filter", call_info.clone()); + let request_raw = serde_json::to_string(&request); - let mut reader = BufReader::new(stdout); - - let request = JsonRpc::new("begin_filter", call_info.clone()); - let request_raw = serde_json::to_string(&request); - - match request_raw { - Err(_) => { - let mut result = VecDeque::new(); - result.push_back(Err(ShellError::labeled_error( - "Could not load json from plugin", - "could not load json from plugin", - &call_info.name_tag, - ))); - return result; - } - Ok(request_raw) => match stdin.write(format!("{}\n", request_raw).as_bytes()) { - Ok(_) => {} - Err(err) => { - let mut result = VecDeque::new(); - result.push_back(Err(ShellError::unexpected(format!("{}", err)))); - return result; - } - }, + match request_raw { + Err(_) => { + yield Err(ShellError::labeled_error( + "Could not load json from plugin", + "could not load json from plugin", + &call_info.name_tag, + )); } - - let mut input = String::new(); - match reader.read_line(&mut input) { - Ok(_) => { - let response = serde_json::from_str::(&input); - match response { - Ok(NuResult::response { params }) => match params { - Ok(params) => params, - Err(e) => { - let mut result = VecDeque::new(); - result.push_back(ReturnValue::Err(e)); - result - } - }, - Err(e) => { - let mut result = VecDeque::new(); - result.push_back(Err(ShellError::untagged_runtime_error(format!( - "Error while processing begin_filter response: {:?} {}", - e, input - )))); - result - } - } - } - Err(e) => { - let mut result = VecDeque::new(); - result.push_back(Err(ShellError::untagged_runtime_error(format!( - "Error while reading begin_filter response: {:?}", - e - )))); - result - } - } - } - Value { - value: UntaggedValue::Primitive(Primitive::EndOfStream), - .. - } => { - let stdin = child.stdin.as_mut().expect("Failed to open stdin"); - let stdout = child.stdout.as_mut().expect("Failed to open stdout"); - - let mut reader = BufReader::new(stdout); - - let request: JsonRpc> = JsonRpc::new("end_filter", vec![]); - let request_raw = match serde_json::to_string(&request) { - Ok(req) => req, + Ok(request_raw) => match stdin.write(format!("{}\n", request_raw).as_bytes()) { + Ok(_) => {} Err(err) => { - let mut result = VecDeque::new(); - result.push_back(Err(ShellError::unexpected(format!("{}", err)))); - return result; + yield Err(ShellError::unexpected(format!("{}", err))); } - }; + }, + } - let _ = stdin.write(format!("{}\n", request_raw).as_bytes()); // TODO: Handle error - - let mut input = String::new(); - let result = match reader.read_line(&mut input) { - Ok(_) => { - let response = serde_json::from_str::(&input); - match response { - Ok(NuResult::response { params }) => match params { - Ok(params) => { - let request: JsonRpc> = - JsonRpc::new("quit", vec![]); - let request_raw = serde_json::to_string(&request); - match request_raw { - Ok(request_raw) => { - let _ = stdin.write(format!("{}\n", request_raw).as_bytes()); // TODO: Handle error - } - Err(e) => { - let mut result = VecDeque::new(); - result.push_back(Err(ShellError::untagged_runtime_error(format!( - "Error while processing begin_filter response: {:?} {}", - e, input - )))); - return result; - } - } - - params - } - Err(e) => { - let mut result = VecDeque::new(); - result.push_back(ReturnValue::Err(e)); - result - } - }, + let mut input = String::new(); + match reader.read_line(&mut input) { + Ok(_) => { + let response = serde_json::from_str::(&input); + match response { + Ok(NuResult::response { params }) => match params { + Ok(params) => for param in params { yield param }, Err(e) => { - let mut result = VecDeque::new(); - result.push_back(Err(ShellError::untagged_runtime_error(format!( - "Error while processing end_filter response: {:?} {}", - e, input - )))); - result + yield ReturnValue::Err(e); } + }, + Err(e) => { + yield Err(ShellError::untagged_runtime_error(format!( + "Error while processing begin_filter response: {:?} {}", + e, input + ))); } } - Err(e) => { - let mut result = VecDeque::new(); - result.push_back(Err(ShellError::untagged_runtime_error(format!( - "Error while reading end_filter: {:?}", - e - )))); - result - } - }; - - let _ = child.wait(); - - result + } + Err(e) => { + yield Err(ShellError::untagged_runtime_error(format!( + "Error while reading begin_filter response: {:?}", + e + ))); + } } - _ => { + } + + // Stream contents + { + while let Some(v) = args.input.next().await { let stdin = child.stdin.as_mut().expect("Failed to open stdin"); let stdout = child.stdout.as_mut().expect("Failed to open stdout"); @@ -256,12 +160,10 @@ pub fn filter_plugin( let _ = stdin.write(format!("{}\n", request_raw).as_bytes()); // TODO: Handle error } Err(e) => { - let mut result = VecDeque::new(); - result.push_back(Err(ShellError::untagged_runtime_error(format!( + yield Err(ShellError::untagged_runtime_error(format!( "Error while processing filter response: {:?}", e - )))); - return result; + ))); } } @@ -271,36 +173,97 @@ pub fn filter_plugin( let response = serde_json::from_str::(&input); match response { Ok(NuResult::response { params }) => match params { - Ok(params) => params, + Ok(params) => for param in params { yield param }, Err(e) => { - let mut result = VecDeque::new(); - result.push_back(ReturnValue::Err(e)); - result + yield ReturnValue::Err(e); } }, Err(e) => { - let mut result = VecDeque::new(); - result.push_back(Err(ShellError::untagged_runtime_error(format!( + yield Err(ShellError::untagged_runtime_error(format!( "Error while processing filter response: {:?}\n== input ==\n{}", e, input - )))); - result + ))); } } } Err(e) => { - let mut result = VecDeque::new(); - result.push_back(Err(ShellError::untagged_runtime_error(format!( + yield Err(ShellError::untagged_runtime_error(format!( "Error while reading filter response: {:?}", e - )))); - result + ))); } } + } - }) - .map(futures::stream::iter) // convert to a stream - .flatten(); + } + + // End of the stream + { + let stdin = child.stdin.as_mut().expect("Failed to open stdin"); + let stdout = child.stdout.as_mut().expect("Failed to open stdout"); + + let mut reader = BufReader::new(stdout); + + let request: JsonRpc> = JsonRpc::new("end_filter", vec![]); + let request_raw = match serde_json::to_string(&request) { + Ok(req) => req, + Err(err) => { + yield Err(ShellError::unexpected(format!("{}", err))); + return; + } + }; + + let _ = stdin.write(format!("{}\n", request_raw).as_bytes()); // TODO: Handle error + + let mut input = String::new(); + match reader.read_line(&mut input) { + Ok(_) => { + let response = serde_json::from_str::(&input); + match response { + Ok(NuResult::response { params }) => match params { + Ok(params) => { + let request: JsonRpc> = + JsonRpc::new("quit", vec![]); + let request_raw = serde_json::to_string(&request); + match request_raw { + Ok(request_raw) => { + let _ = stdin.write(format!("{}\n", request_raw).as_bytes()); // TODO: Handle error + } + Err(e) => { + yield Err(ShellError::untagged_runtime_error(format!( + "Error while processing begin_filter response: {:?} {}", + e, input + ))); + return; + } + } + + //yield ReturnValue::Ok(params) + //yield ReturnSuccess::value(Value) + } + Err(e) => { + yield ReturnValue::Err(e); + } + }, + Err(e) => { + yield Err(ShellError::untagged_runtime_error(format!( + "Error while processing end_filter response: {:?} {}", + e, input + ))); + } + } + } + Err(e) => { + yield Err(ShellError::untagged_runtime_error(format!( + "Error while reading end_filter: {:?}", + e + ))); + } + }; + + let _ = child.wait(); + } + }; Ok(stream.to_output_stream()) } @@ -339,10 +302,11 @@ pub fn sink_plugin( args: CommandArgs, registry: &CommandRegistry, ) -> Result { - let args = args.evaluate_once(registry)?; - let call_info = args.call_info.clone(); - + let registry = registry.clone(); let stream = async_stream! { + let args = args.evaluate_once(®istry).await?; + let call_info = args.call_info.clone(); + let input: Vec = args.input.collect().await; let request = JsonRpc::new("sink", (call_info.clone(), input)); diff --git a/crates/nu-cli/src/commands/prepend.rs b/crates/nu-cli/src/commands/prepend.rs index 272777577..e250bfff5 100644 --- a/crates/nu-cli/src/commands/prepend.rs +++ b/crates/nu-cli/src/commands/prepend.rs @@ -2,7 +2,7 @@ use crate::commands::WholeStreamCommand; use crate::context::CommandRegistry; use crate::prelude::*; use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, Value}; +use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, Value}; #[derive(Deserialize)] struct PrependArgs { @@ -33,7 +33,7 @@ impl WholeStreamCommand for Prepend { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, prepend)?.run() + prepend(args, registry) } fn examples(&self) -> &[Example] { @@ -44,11 +44,17 @@ impl WholeStreamCommand for Prepend { } } -fn prepend( - PrependArgs { row }: PrependArgs, - RunnableContext { input, .. }: RunnableContext, -) -> Result { - let prepend = futures::stream::iter(vec![row]); +fn prepend(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); - Ok(prepend.chain(input).to_output_stream()) + let stream = async_stream! { + let (PrependArgs { row }, mut input) = args.process(®istry).await?; + + yield ReturnSuccess::value(row); + while let Some(item) = input.next().await { + yield ReturnSuccess::value(item); + } + }; + + Ok(stream.to_output_stream()) } diff --git a/crates/nu-cli/src/commands/pwd.rs b/crates/nu-cli/src/commands/pwd.rs index a8330aa2f..77c646d23 100644 --- a/crates/nu-cli/src/commands/pwd.rs +++ b/crates/nu-cli/src/commands/pwd.rs @@ -35,7 +35,17 @@ impl WholeStreamCommand for Pwd { } pub fn pwd(args: CommandArgs, registry: &CommandRegistry) -> Result { - let shell_manager = args.shell_manager.clone(); - let args = args.evaluate_once(registry)?; - shell_manager.pwd(args) + let registry = registry.clone(); + + let stream = async_stream! { + let shell_manager = args.shell_manager.clone(); + let args = args.evaluate_once(®istry).await?; + let mut out = shell_manager.pwd(args)?; + + while let Some(l) = out.next().await { + yield l; + } + }; + + Ok(stream.to_output_stream()) } diff --git a/crates/nu-cli/src/commands/range.rs b/crates/nu-cli/src/commands/range.rs index ee97e0e0f..15a4c2936 100644 --- a/crates/nu-cli/src/commands/range.rs +++ b/crates/nu-cli/src/commands/range.rs @@ -3,7 +3,7 @@ use crate::context::CommandRegistry; use crate::deserializer::NumericRange; use crate::prelude::*; use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape}; +use nu_protocol::{ReturnSuccess, Signature, SyntaxShape}; use nu_source::Tagged; #[derive(Deserialize)] @@ -35,20 +35,26 @@ impl WholeStreamCommand for Range { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, range)?.run() + range(args, registry) } } -fn range( - RangeArgs { area }: RangeArgs, - RunnableContext { input, .. }: RunnableContext, -) -> Result { - let range = area.item; - let (from, _) = range.from; - let (to, _) = range.to; +fn range(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); + let stream = async_stream! { + let (RangeArgs { area }, mut input) = args.process(®istry).await?; + let range = area.item; + let (from, _) = range.from; + let (to, _) = range.to; - let from = *from as usize; - let to = *to as usize; + let from = *from as usize; + let to = *to as usize; - Ok(input.skip(from).take(to - from + 1).to_output_stream()) + let mut inp = input.skip(from).take(to - from + 1); + while let Some(item) = inp.next().await { + yield ReturnSuccess::value(item); + } + }; + + Ok(stream.to_output_stream()) } diff --git a/crates/nu-cli/src/commands/reduce_by.rs b/crates/nu-cli/src/commands/reduce_by.rs index b87eef5a5..11991f5e6 100644 --- a/crates/nu-cli/src/commands/reduce_by.rs +++ b/crates/nu-cli/src/commands/reduce_by.rs @@ -36,15 +36,18 @@ impl WholeStreamCommand for ReduceBy { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, reduce_by)?.run() + reduce_by(args, registry) } } pub fn reduce_by( - ReduceByArgs { reduce_with }: ReduceByArgs, - RunnableContext { input, name, .. }: RunnableContext, + args: CommandArgs, + registry: &CommandRegistry, ) -> Result { + let registry = registry.clone(); + let name = args.call_info.name_tag.clone(); let stream = async_stream! { + let (ReduceByArgs { reduce_with }, mut input) = args.process(®istry).await?; let values: Vec = input.collect().await; if values.is_empty() { diff --git a/crates/nu-cli/src/commands/reject.rs b/crates/nu-cli/src/commands/reject.rs index 5908699bf..fd345860d 100644 --- a/crates/nu-cli/src/commands/reject.rs +++ b/crates/nu-cli/src/commands/reject.rs @@ -2,7 +2,7 @@ use crate::commands::WholeStreamCommand; use crate::data::base::reject_fields; use crate::prelude::*; use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape}; +use nu_protocol::{ReturnSuccess, Signature, SyntaxShape}; use nu_source::Tagged; #[derive(Deserialize)] @@ -30,25 +30,30 @@ impl WholeStreamCommand for Reject { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, reject)?.run() + reject(args, registry) } } -fn reject( - RejectArgs { rest: fields }: RejectArgs, - RunnableContext { input, name, .. }: RunnableContext, -) -> Result { - if fields.is_empty() { - return Err(ShellError::labeled_error( - "Reject requires fields", - "needs parameter", - name, - )); - } +fn reject(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); + let stream = async_stream! { + let name = args.call_info.name_tag.clone(); + let (RejectArgs { rest: fields }, mut input) = args.process(®istry).await?; + if fields.is_empty() { + yield Err(ShellError::labeled_error( + "Reject requires fields", + "needs parameter", + name, + )); + return; + } - let fields: Vec<_> = fields.iter().map(|f| f.item.clone()).collect(); + let fields: Vec<_> = fields.iter().map(|f| f.item.clone()).collect(); - let stream = input.map(move |item| reject_fields(&item, &fields, &item.tag)); + while let Some(item) = input.next().await { + yield ReturnSuccess::value(reject_fields(&item, &fields, &item.tag)); + } + }; - Ok(stream.from_input_stream()) + Ok(stream.to_output_stream()) } diff --git a/crates/nu-cli/src/commands/rename.rs b/crates/nu-cli/src/commands/rename.rs index f2b8f717e..52d7a0102 100644 --- a/crates/nu-cli/src/commands/rename.rs +++ b/crates/nu-cli/src/commands/rename.rs @@ -37,7 +37,7 @@ impl WholeStreamCommand for Rename { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, rename)?.run() + rename(args, registry) } fn examples(&self) -> &[Example] { @@ -54,19 +54,17 @@ impl WholeStreamCommand for Rename { } } -pub fn rename( - Arguments { column_name, rest }: Arguments, - RunnableContext { input, name, .. }: RunnableContext, -) -> Result { - let mut new_column_names = vec![vec![column_name]]; - new_column_names.push(rest); +pub fn rename(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); + let name = args.call_info.name_tag.clone(); + let stream = async_stream! { + let (Arguments { column_name, rest }, mut input) = args.process(®istry).await?; + let mut new_column_names = vec![vec![column_name]]; + new_column_names.push(rest); - let new_column_names = new_column_names.into_iter().flatten().collect::>(); - - let stream = input - .map(move |item| { - let mut result = VecDeque::new(); + let new_column_names = new_column_names.into_iter().flatten().collect::>(); + while let Some(item) = input.next().await { if let Value { value: UntaggedValue::Row(row), tag, @@ -86,21 +84,19 @@ pub fn rename( let out = UntaggedValue::Row(renamed_row.into()).into_value(tag); - result.push_back(ReturnSuccess::value(out)); + yield ReturnSuccess::value(out); } else { - result.push_back(ReturnSuccess::value( + yield ReturnSuccess::value( UntaggedValue::Error(ShellError::labeled_error( "no column names available", "can't rename", &name, )) .into_untagged_value(), - )); + ); } - - futures::stream::iter(result) - }) - .flatten(); + } + }; Ok(stream.to_output_stream()) } diff --git a/crates/nu-cli/src/commands/reverse.rs b/crates/nu-cli/src/commands/reverse.rs index c63594af0..8f18d348e 100644 --- a/crates/nu-cli/src/commands/reverse.rs +++ b/crates/nu-cli/src/commands/reverse.rs @@ -2,7 +2,7 @@ use crate::commands::WholeStreamCommand; use crate::context::CommandRegistry; use crate::prelude::*; use nu_errors::ShellError; -use nu_protocol::Signature; +use nu_protocol::{ReturnSuccess, Signature}; pub struct Reverse; @@ -36,15 +36,16 @@ impl WholeStreamCommand for Reverse { } fn reverse(args: CommandArgs, registry: &CommandRegistry) -> Result { - let args = args.evaluate_once(registry)?; - let (input, _args) = args.parts(); + let registry = registry.clone(); + let stream = async_stream! { + let args = args.evaluate_once(®istry).await?; + let (input, _args) = args.parts(); - let input = input.collect::>(); + let input = input.collect::>().await; + for output in input.into_iter().rev() { + yield ReturnSuccess::value(output); + } + }; - let output = input.map(move |mut vec| { - vec.reverse(); - futures::stream::iter(vec) - }); - - Ok(output.flatten_stream().from_input_stream()) + Ok(stream.to_output_stream()) } diff --git a/crates/nu-cli/src/commands/rm.rs b/crates/nu-cli/src/commands/rm.rs index 7550ca21b..bd479d842 100644 --- a/crates/nu-cli/src/commands/rm.rs +++ b/crates/nu-cli/src/commands/rm.rs @@ -41,7 +41,7 @@ impl WholeStreamCommand for Remove { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, rm)?.run() + rm(args, registry) } fn examples(&self) -> &[Example] { @@ -58,7 +58,17 @@ impl WholeStreamCommand for Remove { } } -fn rm(args: RemoveArgs, context: RunnableContext) -> Result { - let shell_manager = context.shell_manager.clone(); - shell_manager.rm(args, &context) +fn rm(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); + let stream = async_stream! { + let name = args.call_info.name_tag.clone(); + let shell_manager = args.shell_manager.clone(); + let (args, _): (RemoveArgs, _) = args.process(®istry).await?; + let mut result = shell_manager.rm(args, name)?; + while let Some(item) = result.next().await { + yield item; + } + }; + + Ok(stream.to_output_stream()) } diff --git a/crates/nu-cli/src/commands/run_alias.rs b/crates/nu-cli/src/commands/run_alias.rs index 4f06502e4..fcebf47e8 100644 --- a/crates/nu-cli/src/commands/run_alias.rs +++ b/crates/nu-cli/src/commands/run_alias.rs @@ -47,7 +47,7 @@ impl WholeStreamCommand for AliasCommand { let stream = async_stream! { let mut scope = call_info.scope.clone(); - let evaluated = call_info.evaluate(®istry)?; + let evaluated = call_info.evaluate(®istry).await?; if let Some(positional) = &evaluated.args.positional { for (pos, arg) in positional.iter().enumerate() { scope = scope.set_var(alias_command.args[pos].to_string(), arg.clone()); diff --git a/crates/nu-cli/src/commands/run_external.rs b/crates/nu-cli/src/commands/run_external.rs index c9a4daa95..316919465 100644 --- a/crates/nu-cli/src/commands/run_external.rs +++ b/crates/nu-cli/src/commands/run_external.rs @@ -117,16 +117,7 @@ impl WholeStreamCommand for RunExternalCommand { }) }; - let context = RunnableContext { - input: InputStream::empty(), - shell_manager: external_context.shell_manager.clone(), - host: external_context.host.clone(), - ctrl_c: external_context.ctrl_c.clone(), - registry: external_context.registry.clone(), - name: args.call_info.name_tag.clone(), - }; - - let result = external_context.shell_manager.cd(cd_args, &context); + let result = external_context.shell_manager.cd(cd_args, args.call_info.name_tag.clone()); match result { Ok(mut stream) => { while let Some(value) = stream.next().await { diff --git a/crates/nu-cli/src/commands/save.rs b/crates/nu-cli/src/commands/save.rs index 7b5b371ce..3863c581d 100644 --- a/crates/nu-cli/src/commands/save.rs +++ b/crates/nu-cli/src/commands/save.rs @@ -153,31 +153,23 @@ impl WholeStreamCommand for Save { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - Ok(args.process_raw(registry, save)?.run()) + save(args, registry) } } -fn save( - SaveArgs { - path, - raw: save_raw, - }: SaveArgs, - RunnableContext { - input, - name, - shell_manager, - host, - ctrl_c, - registry, - .. - }: RunnableContext, - raw_args: RawCommandArgs, -) -> Result { - let mut full_path = PathBuf::from(shell_manager.path()); - let name_tag = name.clone(); +fn save(raw_args: CommandArgs, registry: &CommandRegistry) -> Result { + let mut full_path = PathBuf::from(raw_args.shell_manager.path()); + let name_tag = raw_args.call_info.name_tag.clone(); + let name = raw_args.call_info.name_tag.clone(); let scope = raw_args.call_info.scope.clone(); + let registry = registry.clone(); + let host = raw_args.host.clone(); + let ctrl_c = raw_args.ctrl_c.clone(); + let shell_manager = raw_args.shell_manager.clone(); let stream = async_stream! { + let head = raw_args.call_info.args.head.clone(); + let (SaveArgs { path, raw: save_raw }, mut input) = raw_args.process(®istry).await?; let input: Vec = input.collect().await; if path.is_none() { // If there is no filename, check the metadata for the anchor filename @@ -230,13 +222,13 @@ fn save( shell_manager, call_info: UnevaluatedCallInfo { args: nu_protocol::hir::Call { - head: raw_args.call_info.args.head, + head, positional: None, named: None, span: Span::unknown(), is_last: false, }, - name_tag: raw_args.call_info.name_tag, + name_tag: name_tag.clone(), scope, } }; diff --git a/crates/nu-cli/src/commands/select.rs b/crates/nu-cli/src/commands/select.rs index 015927207..18dd18060 100644 --- a/crates/nu-cli/src/commands/select.rs +++ b/crates/nu-cli/src/commands/select.rs @@ -3,8 +3,8 @@ use crate::context::CommandRegistry; use crate::prelude::*; use nu_errors::ShellError; use nu_protocol::{ - ColumnPath, PathMember, Primitive, ReturnSuccess, ReturnValue, Signature, SyntaxShape, - TaggedDictBuilder, UnspannedPathMember, UntaggedValue, Value, + ColumnPath, PathMember, Primitive, ReturnSuccess, Signature, SyntaxShape, TaggedDictBuilder, + UnspannedPathMember, UntaggedValue, Value, }; use nu_source::span_for_spanned_list; use nu_value_ext::{as_string, get_data_by_column_path}; @@ -37,7 +37,7 @@ impl WholeStreamCommand for Select { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, select)?.run() + select(args, registry) } fn examples(&self) -> &[Example] { @@ -54,30 +54,28 @@ impl WholeStreamCommand for Select { } } -fn select( - SelectArgs { rest: mut fields }: SelectArgs, - RunnableContext { - mut input, name, .. - }: RunnableContext, -) -> Result { - if fields.is_empty() { - return Err(ShellError::labeled_error( - "Select requires columns to select", - "needs parameter", - name, - )); - } - - let member = fields.remove(0); - let member = vec![member]; - - let column_paths = vec![&member, &fields] - .into_iter() - .flatten() - .cloned() - .collect::>(); - +fn select(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); + let name = args.call_info.name_tag.clone(); let stream = async_stream! { + let (SelectArgs { rest: mut fields }, mut input) = args.process(®istry).await?; + if fields.is_empty() { + yield Err(ShellError::labeled_error( + "Select requires columns to select", + "needs parameter", + name, + )); + return; + } + + let member = fields.remove(0); + let member = vec![member]; + + let column_paths = vec![&member, &fields] + .into_iter() + .flatten() + .cloned() + .collect::>(); let mut empty = true; let mut bring_back: indexmap::IndexMap> = indexmap::IndexMap::new(); @@ -172,7 +170,5 @@ fn select( } }; - let stream: BoxStream<'static, ReturnValue> = stream.boxed(); - Ok(stream.to_output_stream()) } diff --git a/crates/nu-cli/src/commands/shuffle.rs b/crates/nu-cli/src/commands/shuffle.rs index 900c489eb..2595d55dd 100644 --- a/crates/nu-cli/src/commands/shuffle.rs +++ b/crates/nu-cli/src/commands/shuffle.rs @@ -39,15 +39,14 @@ impl WholeStreamCommand for Shuffle { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, shuffle)?.run() + shuffle(args, registry) } } -fn shuffle( - Arguments { limit }: Arguments, - RunnableContext { input, .. }: RunnableContext, -) -> Result { +fn shuffle(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); let stream = async_stream! { + let (Arguments { limit }, mut input) = args.process(®istry).await?; let mut values: Vec = input.collect().await; let out = if let Some(n) = limit { diff --git a/crates/nu-cli/src/commands/skip.rs b/crates/nu-cli/src/commands/skip.rs index 7dd9c08f3..22018181c 100644 --- a/crates/nu-cli/src/commands/skip.rs +++ b/crates/nu-cli/src/commands/skip.rs @@ -2,7 +2,7 @@ use crate::commands::WholeStreamCommand; use crate::context::CommandRegistry; use crate::prelude::*; use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape}; +use nu_protocol::{ReturnSuccess, Signature, SyntaxShape}; use nu_source::Tagged; pub struct Skip; @@ -30,7 +30,7 @@ impl WholeStreamCommand for Skip { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, skip)?.run() + skip(args, registry) } fn examples(&self) -> &[Example] { @@ -41,12 +41,25 @@ impl WholeStreamCommand for Skip { } } -fn skip(SkipArgs { rows }: SkipArgs, context: RunnableContext) -> Result { - let rows_desired = if let Some(quantity) = rows { - *quantity - } else { - 1 +fn skip(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); + let stream = async_stream! { + let (SkipArgs { rows }, mut input) = args.process(®istry).await?; + let mut rows_desired = if let Some(quantity) = rows { + *quantity + } else { + 1 + }; + + while let Some(input) = input.next().await { + if rows_desired == 0 { + yield ReturnSuccess::value(input); + } + if rows_desired > 0{ + rows_desired -= 1; + } + } }; - Ok(OutputStream::from_input(context.input.skip(rows_desired))) + Ok(stream.to_output_stream()) } diff --git a/crates/nu-cli/src/commands/skip_until.rs b/crates/nu-cli/src/commands/skip_until.rs index ce6201bb7..dc34d34b2 100644 --- a/crates/nu-cli/src/commands/skip_until.rs +++ b/crates/nu-cli/src/commands/skip_until.rs @@ -3,7 +3,9 @@ use crate::evaluate::evaluate_baseline_expr; use crate::prelude::*; use log::trace; use nu_errors::ShellError; -use nu_protocol::{hir::ClassifiedCommand, Signature, SyntaxShape, UntaggedValue, Value}; +use nu_protocol::{ + hir::ClassifiedCommand, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value, +}; pub struct SkipUntil; @@ -33,66 +35,80 @@ impl WholeStreamCommand for SkipUntil { ) -> Result { let registry = registry.clone(); let scope = args.call_info.scope.clone(); - let call_info = args.evaluate_once(®istry)?; + let stream = async_stream! { + let mut call_info = args.evaluate_once(®istry).await?; - let block = call_info.args.expect_nth(0)?.clone(); + let block = call_info.args.expect_nth(0)?.clone(); - let condition = match block { - Value { - value: UntaggedValue::Block(block), - tag, - } => { - if block.block.len() != 1 { - return Err(ShellError::labeled_error( - "Expected a condition", - "expected a condition", - tag, - )); - } - match block.block[0].list.get(0) { - Some(item) => match item { - ClassifiedCommand::Expr(expr) => expr.clone(), - _ => { - return Err(ShellError::labeled_error( - "Expected a condition", - "expected a condition", - tag, - )) - } - }, - None => { - return Err(ShellError::labeled_error( + let condition = match block { + Value { + value: UntaggedValue::Block(block), + tag, + } => { + if block.block.len() != 1 { + yield Err(ShellError::labeled_error( "Expected a condition", "expected a condition", tag, )); + return; + } + match block.block[0].list.get(0) { + Some(item) => match item { + ClassifiedCommand::Expr(expr) => expr.clone(), + _ => { + yield Err(ShellError::labeled_error( + "Expected a condition", + "expected a condition", + tag, + )); + return; + } + }, + None => { + yield Err(ShellError::labeled_error( + "Expected a condition", + "expected a condition", + tag, + )); + return; + } } } - } - Value { tag, .. } => { - return Err(ShellError::labeled_error( - "Expected a condition", - "expected a condition", - tag, - )); + Value { tag, .. } => { + yield Err(ShellError::labeled_error( + "Expected a condition", + "expected a condition", + tag, + )); + return; + } + }; + + let mut skipping = true; + while let Some(item) = call_info.input.next().await { + let condition = condition.clone(); + trace!("ITEM = {:?}", item); + let result = + evaluate_baseline_expr(&*condition, ®istry, &scope.clone().set_it(item.clone())) + .await; + trace!("RESULT = {:?}", result); + + let return_value = match result { + Ok(ref v) if v.is_true() => true, + _ => false, + }; + + if return_value { + skipping = false; + } + + if !skipping { + yield ReturnSuccess::value(item); + } } }; - let objects = call_info.input.skip_while(move |item| { - let condition = condition.clone(); - trace!("ITEM = {:?}", item); - let result = - evaluate_baseline_expr(&*condition, ®istry, &scope.clone().set_it(item.clone())); - trace!("RESULT = {:?}", result); - - let return_value = match result { - Ok(ref v) if v.is_true() => false, - _ => true, - }; - - futures::future::ready(return_value) - }); - - Ok(objects.from_input_stream()) + Ok(stream.to_output_stream()) } } diff --git a/crates/nu-cli/src/commands/skip_while.rs b/crates/nu-cli/src/commands/skip_while.rs index d5585cd0c..94341528f 100644 --- a/crates/nu-cli/src/commands/skip_while.rs +++ b/crates/nu-cli/src/commands/skip_while.rs @@ -3,7 +3,9 @@ use crate::evaluate::evaluate_baseline_expr; use crate::prelude::*; use log::trace; use nu_errors::ShellError; -use nu_protocol::{hir::ClassifiedCommand, Signature, SyntaxShape, UntaggedValue, Value}; +use nu_protocol::{ + hir::ClassifiedCommand, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value, +}; pub struct SkipWhile; @@ -33,66 +35,80 @@ impl WholeStreamCommand for SkipWhile { ) -> Result { let registry = registry.clone(); let scope = args.call_info.scope.clone(); - let call_info = args.evaluate_once(®istry)?; + let stream = async_stream! { + let mut call_info = args.evaluate_once(®istry).await?; - let block = call_info.args.expect_nth(0)?.clone(); + let block = call_info.args.expect_nth(0)?.clone(); - let condition = match block { - Value { - value: UntaggedValue::Block(block), - tag, - } => { - if block.block.len() != 1 { - return Err(ShellError::labeled_error( - "Expected a condition", - "expected a condition", - tag, - )); - } - match block.block[0].list.get(0) { - Some(item) => match item { - ClassifiedCommand::Expr(expr) => expr.clone(), - _ => { - return Err(ShellError::labeled_error( - "Expected a condition", - "expected a condition", - tag, - )) - } - }, - None => { - return Err(ShellError::labeled_error( + let condition = match block { + Value { + value: UntaggedValue::Block(block), + tag, + } => { + if block.block.len() != 1 { + yield Err(ShellError::labeled_error( "Expected a condition", "expected a condition", tag, )); + return; + } + match block.block[0].list.get(0) { + Some(item) => match item { + ClassifiedCommand::Expr(expr) => expr.clone(), + _ => { + yield Err(ShellError::labeled_error( + "Expected a condition", + "expected a condition", + tag, + )); + return; + } + }, + None => { + yield Err(ShellError::labeled_error( + "Expected a condition", + "expected a condition", + tag, + )); + return; + } } } - } - Value { tag, .. } => { - return Err(ShellError::labeled_error( - "Expected a condition", - "expected a condition", - tag, - )); + Value { tag, .. } => { + yield Err(ShellError::labeled_error( + "Expected a condition", + "expected a condition", + tag, + )); + return; + } + }; + + let mut skipping = true; + while let Some(item) = call_info.input.next().await { + let condition = condition.clone(); + trace!("ITEM = {:?}", item); + let result = + evaluate_baseline_expr(&*condition, ®istry, &scope.clone().set_it(item.clone())) + .await; + trace!("RESULT = {:?}", result); + + let return_value = match result { + Ok(ref v) if v.is_true() => false, + _ => true, + }; + + if return_value { + skipping = false; + } + + if !skipping { + yield ReturnSuccess::value(item); + } } }; - let objects = call_info.input.skip_while(move |item| { - let condition = condition.clone(); - trace!("ITEM = {:?}", item); - let result = - evaluate_baseline_expr(&*condition, ®istry, &scope.clone().set_it(item.clone())); - trace!("RESULT = {:?}", result); - - let return_value = match result { - Ok(ref v) if v.is_true() => true, - _ => false, - }; - - futures::future::ready(return_value) - }); - - Ok(objects.from_input_stream()) + Ok(stream.to_output_stream()) } } diff --git a/crates/nu-cli/src/commands/sort_by.rs b/crates/nu-cli/src/commands/sort_by.rs index 06d83644e..b8c12ff16 100644 --- a/crates/nu-cli/src/commands/sort_by.rs +++ b/crates/nu-cli/src/commands/sort_by.rs @@ -30,7 +30,7 @@ impl WholeStreamCommand for SortBy { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, sort_by)?.run() + sort_by(args, registry) } fn examples(&self) -> &[Example] { @@ -47,12 +47,11 @@ impl WholeStreamCommand for SortBy { } } -fn sort_by( - SortByArgs { rest }: SortByArgs, - mut context: RunnableContext, -) -> Result { - Ok(OutputStream::new(async_stream! { - let mut vec = context.input.drain_vec().await; +fn sort_by(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); + let stream = async_stream! { + let (SortByArgs { rest }, mut input) = args.process(®istry).await?; + let mut vec = input.drain_vec().await; if vec.is_empty() { return; @@ -78,5 +77,7 @@ fn sort_by( for item in vec { yield item.into(); } - })) + }; + + Ok(stream.to_output_stream()) } diff --git a/crates/nu-cli/src/commands/split_by.rs b/crates/nu-cli/src/commands/split_by.rs index c10854bf4..787906429 100644 --- a/crates/nu-cli/src/commands/split_by.rs +++ b/crates/nu-cli/src/commands/split_by.rs @@ -35,15 +35,15 @@ impl WholeStreamCommand for SplitBy { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, split_by)?.run() + split_by(args, registry) } } -pub fn split_by( - SplitByArgs { column_name }: SplitByArgs, - RunnableContext { input, name, .. }: RunnableContext, -) -> Result { +pub fn split_by(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); let stream = async_stream! { + let name = args.call_info.name_tag.clone(); + let (SplitByArgs { column_name }, mut input) = args.process(®istry).await?; let values: Vec = input.collect().await; if values.len() > 1 || values.is_empty() { diff --git a/crates/nu-cli/src/commands/split_column.rs b/crates/nu-cli/src/commands/split_column.rs index 03b0f6ac3..0987b5cfc 100644 --- a/crates/nu-cli/src/commands/split_column.rs +++ b/crates/nu-cli/src/commands/split_column.rs @@ -42,22 +42,16 @@ impl WholeStreamCommand for SplitColumn { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, split_column)?.run() + split_column(args, registry) } } -fn split_column( - SplitColumnArgs { - separator, - rest, - collapse_empty, - }: SplitColumnArgs, - RunnableContext { input, name, .. }: RunnableContext, -) -> Result { - let name_span = name.span; - - Ok(input - .map(move |v| { +fn split_column(args: CommandArgs, registry: &CommandRegistry) -> Result { + let name_span = args.call_info.name_tag.span; + let registry = registry.clone(); + let stream = async_stream! { + let (SplitColumnArgs { separator, rest, collapse_empty }, mut input) = args.process(®istry).await?; + while let Some(v) = input.next().await { if let Ok(s) = v.as_string() { let splitter = separator.replace("\\n", "\n"); trace!("splitting with {:?}", splitter); @@ -84,7 +78,7 @@ fn split_column( dict.insert_untagged(v.clone(), Primitive::String(k.into())); } - ReturnSuccess::value(dict.into_value()) + yield ReturnSuccess::value(dict.into_value()); } else { let mut dict = TaggedDictBuilder::new(&v.tag); for (&k, v) in split_result.iter().zip(positional.iter()) { @@ -93,17 +87,19 @@ fn split_column( UntaggedValue::Primitive(Primitive::String(k.into())), ); } - ReturnSuccess::value(dict.into_value()) + yield ReturnSuccess::value(dict.into_value()); } } else { - Err(ShellError::labeled_error_with_secondary( + yield Err(ShellError::labeled_error_with_secondary( "Expected a string from pipeline", "requires string input", name_span, "value originates from here", v.tag.span, - )) + )); } - }) - .to_output_stream()) + } + }; + + Ok(stream.to_output_stream()) } diff --git a/crates/nu-cli/src/commands/split_row.rs b/crates/nu-cli/src/commands/split_row.rs index 511d763de..6dfd8425d 100644 --- a/crates/nu-cli/src/commands/split_row.rs +++ b/crates/nu-cli/src/commands/split_row.rs @@ -34,16 +34,16 @@ impl WholeStreamCommand for SplitRow { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, split_row)?.run() + split_row(args, registry) } } -fn split_row( - SplitRowArgs { separator }: SplitRowArgs, - RunnableContext { input, name, .. }: RunnableContext, -) -> Result { - let stream = input - .map(move |v| { +fn split_row(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); + let stream = async_stream! { + let name = args.call_info.name_tag.clone(); + let (SplitRowArgs { separator }, mut input) = args.process(®istry).await?; + while let Some(v) = input.next().await { if let Ok(s) = v.as_string() { let splitter = separator.item.replace("\\n", "\n"); trace!("splitting with {:?}", splitter); @@ -51,26 +51,22 @@ fn split_row( trace!("split result = {:?}", split_result); - let mut result = VecDeque::new(); for s in split_result { - result.push_back(ReturnSuccess::value( + yield ReturnSuccess::value( UntaggedValue::Primitive(Primitive::String(s.into())).into_value(&v.tag), - )); + ); } - futures::stream::iter(result) } else { - let mut result = VecDeque::new(); - result.push_back(Err(ShellError::labeled_error_with_secondary( + yield Err(ShellError::labeled_error_with_secondary( "Expected a string from pipeline", "requires string input", name.span, "value originates from here", v.tag.span, - ))); - futures::stream::iter(result) + )); } - }) - .flatten(); + } + }; Ok(stream.to_output_stream()) } diff --git a/crates/nu-cli/src/commands/t_sort_by.rs b/crates/nu-cli/src/commands/t_sort_by.rs index 25f4428a2..682305571 100644 --- a/crates/nu-cli/src/commands/t_sort_by.rs +++ b/crates/nu-cli/src/commands/t_sort_by.rs @@ -56,19 +56,15 @@ impl WholeStreamCommand for TSortBy { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, t_sort_by)?.run() + t_sort_by(args, registry) } } -fn t_sort_by( - TSortByArgs { - show_columns, - group_by, - .. - }: TSortByArgs, - RunnableContext { input, name, .. }: RunnableContext, -) -> Result { - Ok(OutputStream::new(async_stream! { +fn t_sort_by(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); + let stream = async_stream! { + let name = args.call_info.name_tag.clone(); + let (TSortByArgs { show_columns, group_by, ..}, mut input) = args.process(®istry).await?; let values: Vec = input.collect().await; let column_grouped_by_name = if let Some(grouped_by) = group_by { @@ -87,5 +83,7 @@ fn t_sort_by( Err(err) => yield Err(err) } } - })) + }; + + Ok(stream.to_output_stream()) } diff --git a/crates/nu-cli/src/commands/table.rs b/crates/nu-cli/src/commands/table.rs index 795879d95..a1e514f21 100644 --- a/crates/nu-cli/src/commands/table.rs +++ b/crates/nu-cli/src/commands/table.rs @@ -38,10 +38,11 @@ impl WholeStreamCommand for Table { } fn table(args: CommandArgs, registry: &CommandRegistry) -> Result { - let mut args = args.evaluate_once(registry)?; - let mut finished = false; - + let registry = registry.clone(); let stream = async_stream! { + let mut args = args.evaluate_once(®istry).await?; + let mut finished = false; + let host = args.host.clone(); let mut start_number = match args.get("start_number") { Some(Value { value: UntaggedValue::Primitive(Primitive::Int(i)), .. }) => { diff --git a/crates/nu-cli/src/commands/to.rs b/crates/nu-cli/src/commands/to.rs index d33bebd01..41a09793e 100644 --- a/crates/nu-cli/src/commands/to.rs +++ b/crates/nu-cli/src/commands/to.rs @@ -1,8 +1,9 @@ use crate::commands::WholeStreamCommand; use crate::prelude::*; use nu_errors::ShellError; -use nu_protocol::Signature; +use nu_protocol::{ReturnSuccess, Signature, UntaggedValue}; +#[derive(Clone)] pub struct To; impl WholeStreamCommand for To { @@ -23,6 +24,14 @@ impl WholeStreamCommand for To { _args: CommandArgs, registry: &CommandRegistry, ) -> Result { - Ok(crate::commands::help::get_help(self, registry).into()) + let registry = registry.clone(); + let stream = async_stream! { + yield Ok(ReturnSuccess::Value( + UntaggedValue::string(crate::commands::help::get_help(&To, ®istry)) + .into_value(Tag::unknown()), + )); + }; + + Ok(stream.to_output_stream()) } } diff --git a/crates/nu-cli/src/commands/to_bson.rs b/crates/nu-cli/src/commands/to_bson.rs index 2ac9d6929..30c5b15b6 100644 --- a/crates/nu-cli/src/commands/to_bson.rs +++ b/crates/nu-cli/src/commands/to_bson.rs @@ -261,11 +261,12 @@ fn bson_value_to_bytes(bson: Bson, tag: Tag) -> Result, ShellError> { } fn to_bson(args: CommandArgs, registry: &CommandRegistry) -> Result { - let args = args.evaluate_once(registry)?; - let name_tag = args.name_tag(); - let name_span = name_tag.span; - + let registry = registry.clone(); let stream = async_stream! { + let args = args.evaluate_once(®istry).await?; + let name_tag = args.name_tag(); + let name_span = name_tag.span; + let input: Vec = args.input.collect().await; let to_process_input = if input.len() > 1 { diff --git a/crates/nu-cli/src/commands/to_csv.rs b/crates/nu-cli/src/commands/to_csv.rs index d789ca46a..a3f0ed0c4 100644 --- a/crates/nu-cli/src/commands/to_csv.rs +++ b/crates/nu-cli/src/commands/to_csv.rs @@ -41,39 +41,45 @@ impl WholeStreamCommand for ToCSV { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, to_csv)?.run() + to_csv(args, registry) } } -fn to_csv( - ToCSVArgs { - separator, - headerless, - }: ToCSVArgs, - runnable_context: RunnableContext, -) -> Result { - let sep = match separator { - Some(Value { - value: UntaggedValue::Primitive(Primitive::String(s)), - tag, - .. - }) => { - if s == r"\t" { - '\t' - } else { - let vec_s: Vec = s.chars().collect(); - if vec_s.len() != 1 { - return Err(ShellError::labeled_error( - "Expected a single separator char from --separator", - "requires a single character string input", - tag, - )); - }; - vec_s[0] +fn to_csv(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); + let stream = async_stream! { + let name = args.call_info.name_tag.clone(); + let (ToCSVArgs { separator, headerless }, mut input) = args.process(®istry).await?; + let sep = match separator { + Some(Value { + value: UntaggedValue::Primitive(Primitive::String(s)), + tag, + .. + }) => { + if s == r"\t" { + '\t' + } else { + let vec_s: Vec = s.chars().collect(); + if vec_s.len() != 1 { + yield Err(ShellError::labeled_error( + "Expected a single separator char from --separator", + "requires a single character string input", + tag, + )); + return; + }; + vec_s[0] + } } + _ => ',', + }; + + let mut result = to_delimited_data(headerless, sep, "CSV", input, name)?; + + while let Some(item) = result.next().await { + yield item; } - _ => ',', }; - to_delimited_data(headerless, sep, "CSV", runnable_context) + Ok(stream.to_output_stream()) } diff --git a/crates/nu-cli/src/commands/to_delimited_data.rs b/crates/nu-cli/src/commands/to_delimited_data.rs index f8b8be6de..995862031 100644 --- a/crates/nu-cli/src/commands/to_delimited_data.rs +++ b/crates/nu-cli/src/commands/to_delimited_data.rs @@ -169,7 +169,8 @@ pub fn to_delimited_data( headerless: bool, sep: char, format_name: &'static str, - RunnableContext { input, name, .. }: RunnableContext, + input: InputStream, + name: Tag, ) -> Result { let name_tag = name; let name_span = name_tag.span; diff --git a/crates/nu-cli/src/commands/to_html.rs b/crates/nu-cli/src/commands/to_html.rs index 36867b290..18714a87a 100644 --- a/crates/nu-cli/src/commands/to_html.rs +++ b/crates/nu-cli/src/commands/to_html.rs @@ -31,10 +31,10 @@ impl WholeStreamCommand for ToHTML { } fn to_html(args: CommandArgs, registry: &CommandRegistry) -> Result { - let args = args.evaluate_once(registry)?; - let name_tag = args.name_tag(); - //let name_span = name_tag.span; + let registry = registry.clone(); let stream = async_stream! { + let args = args.evaluate_once(®istry).await?; + let name_tag = args.name_tag(); let input: Vec = args.input.collect().await; let headers = nu_protocol::merge_descriptors(&input); let mut output_string = "".to_string(); diff --git a/crates/nu-cli/src/commands/to_json.rs b/crates/nu-cli/src/commands/to_json.rs index dc0b71c67..44f7e08ef 100644 --- a/crates/nu-cli/src/commands/to_json.rs +++ b/crates/nu-cli/src/commands/to_json.rs @@ -132,10 +132,11 @@ fn json_list(input: &[Value]) -> Result, ShellError> { } fn to_json(args: CommandArgs, registry: &CommandRegistry) -> Result { - let args = args.evaluate_once(registry)?; - let name_tag = args.name_tag(); - let name_span = name_tag.span; + let registry = registry.clone(); let stream = async_stream! { + let args = args.evaluate_once(®istry).await?; + let name_tag = args.name_tag(); + let name_span = name_tag.span; let input: Vec = args.input.collect().await; let to_process_input = if input.len() > 1 { diff --git a/crates/nu-cli/src/commands/to_md.rs b/crates/nu-cli/src/commands/to_md.rs index 9bf98b7c3..5fcb66ec1 100644 --- a/crates/nu-cli/src/commands/to_md.rs +++ b/crates/nu-cli/src/commands/to_md.rs @@ -30,10 +30,10 @@ impl WholeStreamCommand for ToMarkdown { } fn to_html(args: CommandArgs, registry: &CommandRegistry) -> Result { - let args = args.evaluate_once(registry)?; - let name_tag = args.name_tag(); - //let name_span = name_tag.span; + let registry = registry.clone(); let stream = async_stream! { + let args = args.evaluate_once(®istry).await?; + let name_tag = args.name_tag(); let input: Vec = args.input.collect().await; let headers = nu_protocol::merge_descriptors(&input); let mut output_string = String::new(); diff --git a/crates/nu-cli/src/commands/to_sqlite.rs b/crates/nu-cli/src/commands/to_sqlite.rs index 4eedd7104..d752906fb 100644 --- a/crates/nu-cli/src/commands/to_sqlite.rs +++ b/crates/nu-cli/src/commands/to_sqlite.rs @@ -202,9 +202,10 @@ fn sqlite_input_stream_to_bytes(values: Vec) -> Result Result { - let args = args.evaluate_once(registry)?; - let name_tag = args.name_tag(); + let registry = registry.clone(); let stream = async_stream! { + let args = args.evaluate_once(®istry).await?; + let name_tag = args.name_tag(); let input: Vec = args.input.collect().await; match sqlite_input_stream_to_bytes(input) { diff --git a/crates/nu-cli/src/commands/to_toml.rs b/crates/nu-cli/src/commands/to_toml.rs index cda9c9efb..5e78a046d 100644 --- a/crates/nu-cli/src/commands/to_toml.rs +++ b/crates/nu-cli/src/commands/to_toml.rs @@ -94,10 +94,11 @@ fn collect_values(input: &[Value]) -> Result, ShellError> { } fn to_toml(args: CommandArgs, registry: &CommandRegistry) -> Result { - let args = args.evaluate_once(registry)?; - let name_tag = args.name_tag(); - let name_span = name_tag.span; + let registry = registry.clone(); let stream = async_stream! { + let args = args.evaluate_once(®istry).await?; + let name_tag = args.name_tag(); + let name_span = name_tag.span; let input: Vec = args.input.collect().await; let to_process_input = if input.len() > 1 { diff --git a/crates/nu-cli/src/commands/to_tsv.rs b/crates/nu-cli/src/commands/to_tsv.rs index bcbf655fb..70c417613 100644 --- a/crates/nu-cli/src/commands/to_tsv.rs +++ b/crates/nu-cli/src/commands/to_tsv.rs @@ -33,13 +33,27 @@ impl WholeStreamCommand for ToTSV { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, to_tsv)?.run() + to_tsv(args, registry) } } -fn to_tsv( - ToTSVArgs { headerless }: ToTSVArgs, - runnable_context: RunnableContext, -) -> Result { - to_delimited_data(headerless, '\t', "TSV", runnable_context) +fn to_tsv(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); + let stream = async_stream! { + let name = args.call_info.name_tag.clone(); + let (ToTSVArgs { headerless }, mut input) = args.process(®istry).await?; + let mut result = to_delimited_data( + headerless, + '\t', + "TSV", + input, + name, + )?; + + while let Some(item) = result.next().await { + yield item; + } + }; + + Ok(stream.to_output_stream()) } diff --git a/crates/nu-cli/src/commands/to_url.rs b/crates/nu-cli/src/commands/to_url.rs index 7b42ec61c..a1de46fde 100644 --- a/crates/nu-cli/src/commands/to_url.rs +++ b/crates/nu-cli/src/commands/to_url.rs @@ -28,11 +28,12 @@ impl WholeStreamCommand for ToURL { } fn to_url(args: CommandArgs, registry: &CommandRegistry) -> Result { - let args = args.evaluate_once(registry)?; - let tag = args.name_tag(); - let input = args.input; - + let registry = registry.clone(); let stream = async_stream! { + let args = args.evaluate_once(®istry).await?; + let tag = args.name_tag(); + let input = args.input; + let input: Vec = input.collect().await; for value in input { diff --git a/crates/nu-cli/src/commands/to_yaml.rs b/crates/nu-cli/src/commands/to_yaml.rs index 7c834e57f..d37d28e50 100644 --- a/crates/nu-cli/src/commands/to_yaml.rs +++ b/crates/nu-cli/src/commands/to_yaml.rs @@ -125,11 +125,12 @@ pub fn value_to_yaml_value(v: &Value) -> Result { } fn to_yaml(args: CommandArgs, registry: &CommandRegistry) -> Result { - let args = args.evaluate_once(registry)?; - let name_tag = args.name_tag(); - let name_span = name_tag.span; - + let registry = registry.clone(); let stream = async_stream! { + let args = args.evaluate_once(®istry).await?; + let name_tag = args.name_tag(); + let name_span = name_tag.span; + let input: Vec = args.input.collect().await; let to_process_input = if input.len() > 1 { diff --git a/crates/nu-cli/src/commands/touch.rs b/crates/nu-cli/src/commands/touch.rs index 6f1076b0b..c688dd3ec 100644 --- a/crates/nu-cli/src/commands/touch.rs +++ b/crates/nu-cli/src/commands/touch.rs @@ -32,16 +32,22 @@ impl WholeStreamCommand for Touch { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, touch)?.run() + touch(args, registry) } } -fn touch(TouchArgs { target }: TouchArgs, _: RunnableContext) -> Result { - match OpenOptions::new().write(true).create(true).open(&target) { - Ok(_) => Ok(OutputStream::empty()), - Err(err) => Err(ShellError::labeled_error( - "File Error", - err.to_string(), - &target.tag, - )), - } +fn touch(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); + let stream = async_stream! { + let (TouchArgs { target }, _) = args.process(®istry).await?; + match OpenOptions::new().write(true).create(true).open(&target) { + Ok(_) => {}, + Err(err) => yield Err(ShellError::labeled_error( + "File Error", + err.to_string(), + &target.tag, + )), + } + }; + + Ok(stream.to_output_stream()) } diff --git a/crates/nu-cli/src/commands/uniq.rs b/crates/nu-cli/src/commands/uniq.rs index 332985095..3fd1251bd 100644 --- a/crates/nu-cli/src/commands/uniq.rs +++ b/crates/nu-cli/src/commands/uniq.rs @@ -5,9 +5,6 @@ use indexmap::set::IndexSet; use nu_errors::ShellError; use nu_protocol::{ReturnSuccess, Signature}; -#[derive(Deserialize)] -struct UniqArgs {} - pub struct Uniq; impl WholeStreamCommand for Uniq { @@ -28,15 +25,13 @@ impl WholeStreamCommand for Uniq { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, uniq)?.run() + uniq(args, registry) } } -fn uniq( - UniqArgs {}: UniqArgs, - RunnableContext { input, .. }: RunnableContext, -) -> Result { +fn uniq(args: CommandArgs, _registry: &CommandRegistry) -> Result { let stream = async_stream! { + let mut input = args.input; let uniq_values: IndexSet<_> = input.collect().await; for item in uniq_values.iter().map(|row| ReturnSuccess::value(row.clone())) { diff --git a/crates/nu-cli/src/commands/update.rs b/crates/nu-cli/src/commands/update.rs index 7582c4298..aa79e2972 100644 --- a/crates/nu-cli/src/commands/update.rs +++ b/crates/nu-cli/src/commands/update.rs @@ -43,104 +43,101 @@ impl WholeStreamCommand for Update { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - Ok(args.process_raw(registry, update)?.run()) + update(args, registry) } } -fn update( - UpdateArgs { field, replacement }: UpdateArgs, - context: RunnableContext, - raw_args: RawCommandArgs, -) -> Result { +fn update(raw_args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); let scope = raw_args.call_info.scope.clone(); - let registry = context.registry.clone(); - let mut input_stream = context.input; let stream = async_stream! { - while let Some(input) = input_stream.next().await { - let replacement = replacement.clone(); - match replacement { - Value { - value: UntaggedValue::Block(block), - tag, - } => { - let mut context = Context::from_raw(&raw_args, ®istry); - let for_block = input.clone(); - let input_clone = input.clone(); - let input_stream = once(async { Ok(for_block) }).to_input_stream(); + let mut context = Context::from_raw(&raw_args, ®istry); + let (UpdateArgs { field, replacement }, mut input) = raw_args.process(®istry).await?; + while let Some(input) = input.next().await { + let replacement = replacement.clone(); + match replacement { + Value { + value: UntaggedValue::Block(block), + tag, + } => { + let for_block = input.clone(); + let input_clone = input.clone(); + let input_stream = once(async { Ok(for_block) }).to_input_stream(); - let result = run_block( - &block, - &mut context, - input_stream, - &scope.clone().set_it(input_clone), - ).await; + let result = run_block( + &block, + &mut context, + input_stream, + &scope.clone().set_it(input_clone), + ).await; - match result { - Ok(mut stream) => { - let errors = context.get_errors(); - if let Some(error) = errors.first() { - yield Err(error.clone()); - } + match result { + Ok(mut stream) => { + let errors = context.get_errors(); + if let Some(error) = errors.first() { + yield Err(error.clone()); + } - match input { - obj @ Value { - value: UntaggedValue::Row(_), - .. - } => { - if let Some(result) = stream.next().await { - match obj.replace_data_at_column_path(&field, result.clone()) { - Some(v) => yield Ok(ReturnSuccess::Value(v)), - None => { - yield Err(ShellError::labeled_error( - "update could not find place to insert column", - "column name", - obj.tag, - )) + match input { + obj @ Value { + value: UntaggedValue::Row(_), + .. + } => { + if let Some(result) = stream.next().await { + match obj.replace_data_at_column_path(&field, result.clone()) { + Some(v) => yield Ok(ReturnSuccess::Value(v)), + None => { + yield Err(ShellError::labeled_error( + "update could not find place to insert column", + "column name", + obj.tag, + )) + } } } } + Value { tag, ..} => { + yield Err(ShellError::labeled_error( + "Unrecognized type in stream", + "original value", + tag, + )) + } } - Value { tag, ..} => { + } + Err(e) => { + yield Err(e); + } + } + } + _ => { + match input { + obj @ Value { + value: UntaggedValue::Row(_), + .. + } => match obj.replace_data_at_column_path(&field, replacement.clone()) { + Some(v) => yield Ok(ReturnSuccess::Value(v)), + None => { yield Err(ShellError::labeled_error( - "Unrecognized type in stream", - "original value", - tag, + "update could not find place to insert column", + "column name", + obj.tag, )) } - } - } - Err(e) => { - yield Err(e); - } - } - } - _ => { - match input { - obj @ Value { - value: UntaggedValue::Row(_), - .. - } => match obj.replace_data_at_column_path(&field, replacement.clone()) { - Some(v) => yield Ok(ReturnSuccess::Value(v)), - None => { + }, + Value { tag, ..} => { yield Err(ShellError::labeled_error( - "update could not find place to insert column", - "column name", - obj.tag, + "Unrecognized type in stream", + "original value", + tag, )) } - }, - Value { tag, ..} => { - yield Err(ShellError::labeled_error( - "Unrecognized type in stream", - "original value", - tag, - )) + _ => {} } - _ => {} } } - }} + } }; Ok(stream.to_output_stream()) diff --git a/crates/nu-cli/src/commands/version.rs b/crates/nu-cli/src/commands/version.rs index 9c74249a6..1e884b6c5 100644 --- a/crates/nu-cli/src/commands/version.rs +++ b/crates/nu-cli/src/commands/version.rs @@ -28,9 +28,8 @@ impl WholeStreamCommand for Version { } } -pub fn version(args: CommandArgs, registry: &CommandRegistry) -> Result { - let args = args.evaluate_once(registry)?; - let tag = args.call_info.name_tag.clone(); +pub fn version(args: CommandArgs, _registry: &CommandRegistry) -> Result { + let tag = args.call_info.args.span; let mut indexmap = IndexMap::new(); indexmap.insert( diff --git a/crates/nu-cli/src/commands/what.rs b/crates/nu-cli/src/commands/what.rs index 23a461052..57b2290c9 100644 --- a/crates/nu-cli/src/commands/what.rs +++ b/crates/nu-cli/src/commands/what.rs @@ -27,15 +27,14 @@ impl WholeStreamCommand for What { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, what)?.run() + // args.process(registry, what)?.run() + what(args, registry) } } -pub fn what( - _: WhatArgs, - RunnableContext { mut input, .. }: RunnableContext, -) -> Result { +pub fn what(args: CommandArgs, _registry: &CommandRegistry) -> Result { let stream = async_stream! { + let mut input = args.input; while let Some(row) = input.next().await { let name = value::format_type(&row, 100); yield ReturnSuccess::value(UntaggedValue::string(name).into_value(Tag::unknown_anchor(row.tag.span))); diff --git a/crates/nu-cli/src/commands/where_.rs b/crates/nu-cli/src/commands/where_.rs index 079510e75..68f9dcd7e 100644 --- a/crates/nu-cli/src/commands/where_.rs +++ b/crates/nu-cli/src/commands/where_.rs @@ -34,55 +34,56 @@ impl WholeStreamCommand for Where { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - Ok(args.process_raw(registry, where_command)?.run()) + where_command(args, registry) } } fn where_command( - WhereArgs { block }: WhereArgs, - RunnableContext { - name: tag, - registry, - input, - .. - }: RunnableContext, - raw_args: RawCommandArgs, + raw_args: CommandArgs, + registry: &CommandRegistry, ) -> Result { - let condition = { - if block.block.len() != 1 { - return Err(ShellError::labeled_error( - "Expected a condition", - "expected a condition", - tag, - )); - } - match block.block[0].list.get(0) { - Some(item) => match item { - ClassifiedCommand::Expr(expr) => expr.clone(), - _ => { - return Err(ShellError::labeled_error( - "Expected a condition", - "expected a condition", - tag, - )) - } - }, - None => { - return Err(ShellError::labeled_error( + let registry = registry.clone(); + let stream = async_stream! { + let tag = raw_args.call_info.name_tag.clone(); + let scope = raw_args.call_info.scope.clone(); + + let (WhereArgs { block }, mut input) = raw_args.process(®istry).await?; + let condition = { + if block.block.len() != 1 { + yield Err(ShellError::labeled_error( "Expected a condition", "expected a condition", tag, )); + return; } - } - }; + match block.block[0].list.get(0) { + Some(item) => match item { + ClassifiedCommand::Expr(expr) => expr.clone(), + _ => { + yield Err(ShellError::labeled_error( + "Expected a condition", + "expected a condition", + tag, + )); + return; + } + }, + None => { + yield Err(ShellError::labeled_error( + "Expected a condition", + "expected a condition", + tag, + )); + return; + } + } + }; - let mut input = input; - let scope = raw_args.call_info.scope; - let stream = async_stream! { + let mut input = input; while let Some(input) = input.next().await { //FIXME: should we use the scope that's brought in as well? - let condition = evaluate_baseline_expr(&condition, ®istry, &scope.clone().set_it(input.clone()))?; + let condition = evaluate_baseline_expr(&condition, ®istry, &scope.clone().set_it(input.clone())).await?; match condition.as_bool() { Ok(b) => { diff --git a/crates/nu-cli/src/commands/which_.rs b/crates/nu-cli/src/commands/which_.rs index 0a96cd5bf..9a6d19f0d 100644 --- a/crates/nu-cli/src/commands/which_.rs +++ b/crates/nu-cli/src/commands/which_.rs @@ -27,7 +27,7 @@ impl WholeStreamCommand for Which { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, which)?.run() + which(args, registry) } } @@ -76,18 +76,18 @@ struct WhichArgs { all: bool, } -fn which( - WhichArgs { application, all }: WhichArgs, - RunnableContext { registry, .. }: RunnableContext, -) -> Result { - let external = application.starts_with('^'); - let item = if external { - application.item[1..].to_string() - } else { - application.item.clone() - }; - +fn which(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); + let mut all = true; let stream = async_stream! { + let (WhichArgs { application, all: all_items }, _) = args.process(®istry).await?; + all = all_items; + let external = application.starts_with('^'); + let item = if external { + application.item[1..].to_string() + } else { + application.item.clone() + }; if !external { let builtin = registry.has(&item); if builtin { diff --git a/crates/nu-cli/src/commands/with_env.rs b/crates/nu-cli/src/commands/with_env.rs index 98bd41e4d..43b8f9aa4 100644 --- a/crates/nu-cli/src/commands/with_env.rs +++ b/crates/nu-cli/src/commands/with_env.rs @@ -40,7 +40,7 @@ impl WholeStreamCommand for WithEnv { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - Ok(args.process_raw(registry, with_env)?.run()) + with_env(args, registry) } fn examples(&self) -> &[Example] { @@ -51,21 +51,18 @@ impl WholeStreamCommand for WithEnv { } } -fn with_env( - WithEnvArgs { variable, block }: WithEnvArgs, - context: RunnableContext, - raw_args: RawCommandArgs, -) -> Result { - let scope = raw_args - .call_info - .scope - .clone() - .set_env_var(variable.0.item, variable.1.item); - let registry = context.registry.clone(); - let input = context.input; - let mut context = Context::from_raw(&raw_args, ®istry); +fn with_env(raw_args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); let stream = async_stream! { + let mut context = Context::from_raw(&raw_args, ®istry); + let scope = raw_args + .call_info + .scope + .clone(); + let (WithEnvArgs { variable, block }, mut input) = raw_args.process(®istry).await?; + let scope = scope.set_env_var(variable.0.item, variable.1.item); + let result = run_block( &block, &mut context, diff --git a/crates/nu-cli/src/commands/wrap.rs b/crates/nu-cli/src/commands/wrap.rs index 820f4ad12..006b65c25 100644 --- a/crates/nu-cli/src/commands/wrap.rs +++ b/crates/nu-cli/src/commands/wrap.rs @@ -35,7 +35,8 @@ impl WholeStreamCommand for Wrap { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - args.process(registry, wrap)?.run() + // args.process(registry, wrap)?.run() + wrap(args, registry) } fn examples(&self) -> &[Example] { @@ -52,13 +53,11 @@ impl WholeStreamCommand for Wrap { } } -fn wrap( - WrapArgs { column }: WrapArgs, - context: RunnableContext, -) -> Result { - let mut input = context.input; +fn wrap(args: CommandArgs, registry: &CommandRegistry) -> Result { + let registry = registry.clone(); let stream = async_stream! { + let (WrapArgs { column }, mut input) = args.process(®istry).await?; let mut result_table = vec![]; let mut are_all_rows = true; diff --git a/crates/nu-cli/src/context.rs b/crates/nu-cli/src/context.rs index 8c80e7b77..fc2c32a00 100644 --- a/crates/nu-cli/src/context.rs +++ b/crates/nu-cli/src/context.rs @@ -1,6 +1,4 @@ -use crate::commands::{ - command::CommandArgs, command::RawCommandArgs, Command, UnevaluatedCallInfo, -}; +use crate::commands::{command::CommandArgs, Command, UnevaluatedCallInfo}; use crate::env::host::Host; use crate::shell::shell_manager::ShellManager; use crate::stream::{InputStream, OutputStream}; @@ -88,7 +86,7 @@ impl Context { &self.registry } - pub(crate) fn from_raw(raw_args: &RawCommandArgs, registry: &CommandRegistry) -> Context { + pub(crate) fn from_raw(raw_args: &CommandArgs, registry: &CommandRegistry) -> Context { #[cfg(windows)] { Context { diff --git a/crates/nu-cli/src/evaluate/evaluate_args.rs b/crates/nu-cli/src/evaluate/evaluate_args.rs index 493036a4a..2be94443a 100644 --- a/crates/nu-cli/src/evaluate/evaluate_args.rs +++ b/crates/nu-cli/src/evaluate/evaluate_args.rs @@ -5,48 +5,51 @@ use indexmap::IndexMap; use nu_errors::ShellError; use nu_protocol::{hir, EvaluatedArgs, Scope, UntaggedValue, Value}; -pub(crate) fn evaluate_args( +pub(crate) async fn evaluate_args( call: &hir::Call, registry: &CommandRegistry, scope: &Scope, ) -> Result { - let positional: Result>, _> = call - .positional - .as_ref() - .map(|p| { - p.iter() - .map(|e| evaluate_baseline_expr(e, registry, scope)) - .collect() - }) - .transpose(); + let mut positional_args: Vec = vec![]; - let positional = positional?; + if let Some(positional) = &call.positional { + for pos in positional { + let result = evaluate_baseline_expr(pos, registry, scope).await?; + positional_args.push(result); + } + } - let named: Result>, ShellError> = call - .named - .as_ref() - .map(|n| { - let mut results = IndexMap::new(); + let positional = if !positional_args.is_empty() { + Some(positional_args) + } else { + None + }; - for (name, value) in n.named.iter() { - match value { - hir::NamedValue::PresentSwitch(tag) => { - results.insert(name.clone(), UntaggedValue::boolean(true).into_value(tag)); - } - hir::NamedValue::Value(_, expr) => { - results - .insert(name.clone(), evaluate_baseline_expr(expr, registry, scope)?); - } + let mut named_args = IndexMap::new(); - _ => {} - }; - } + if let Some(named) = &call.named { + for (name, value) in named.iter() { + match value { + hir::NamedValue::PresentSwitch(tag) => { + named_args.insert(name.clone(), UntaggedValue::boolean(true).into_value(tag)); + } + hir::NamedValue::Value(_, expr) => { + named_args.insert( + name.clone(), + evaluate_baseline_expr(expr, registry, scope).await?, + ); + } - Ok(results) - }) - .transpose(); + _ => {} + }; + } + } - let named = named?; + let named = if !named_args.is_empty() { + Some(named_args) + } else { + None + }; Ok(EvaluatedArgs::new(positional, named)) } diff --git a/crates/nu-cli/src/evaluate/evaluator.rs b/crates/nu-cli/src/evaluate/evaluator.rs index a6f814679..ea4bc2281 100644 --- a/crates/nu-cli/src/evaluate/evaluator.rs +++ b/crates/nu-cli/src/evaluate/evaluator.rs @@ -1,6 +1,8 @@ +use crate::commands::classified::block::run_block; use crate::context::CommandRegistry; use crate::evaluate::operator::apply_operator; use crate::prelude::*; +use async_recursion::async_recursion; use log::trace; use nu_errors::{ArgumentError, ShellError}; use nu_protocol::hir::{self, Expression, SpannedExpression}; @@ -8,7 +10,8 @@ use nu_protocol::{ ColumnPath, Primitive, RangeInclusion, Scope, UnspannedPathMember, UntaggedValue, Value, }; -pub(crate) fn evaluate_baseline_expr( +#[async_recursion] +pub(crate) async fn evaluate_baseline_expr( expr: &SpannedExpression, registry: &CommandRegistry, scope: &Scope, @@ -17,8 +20,9 @@ pub(crate) fn evaluate_baseline_expr( span: expr.span, anchor: None, }; + let span = expr.span; match &expr.expr { - Expression::Literal(literal) => Ok(evaluate_literal(literal, expr.span)), + Expression::Literal(literal) => Ok(evaluate_literal(&literal, span)), Expression::ExternalWord => Err(ShellError::argument_error( "Invalid external word".spanned(tag.span), ArgumentError::InvalidExternalWord, @@ -27,13 +31,14 @@ pub(crate) fn evaluate_baseline_expr( Expression::Synthetic(hir::Synthetic::String(s)) => { Ok(UntaggedValue::string(s).into_untagged_value()) } - Expression::Variable(var) => evaluate_reference(var, scope, tag), - Expression::Command(_) => evaluate_command(tag, scope), - Expression::ExternalCommand(external) => evaluate_external(external, scope), + Expression::Variable(var) => evaluate_reference(&var, &scope, tag), + Expression::Command(_) => evaluate_command(tag, &scope), + Expression::Invocation(block) => evaluate_invocation(block, registry, scope).await, + Expression::ExternalCommand(external) => evaluate_external(&external, &scope), Expression::Binary(binary) => { // TODO: If we want to add short-circuiting, we'll need to move these down - let left = evaluate_baseline_expr(&binary.left, registry, scope)?; - let right = evaluate_baseline_expr(&binary.right, registry, scope)?; + let left = evaluate_baseline_expr(&binary.left, registry, scope).await?; + let right = evaluate_baseline_expr(&binary.right, registry, scope).await?; trace!("left={:?} right={:?}", left.value, right.value); @@ -54,8 +59,8 @@ pub(crate) fn evaluate_baseline_expr( let left = &range.left; let right = &range.right; - let left = evaluate_baseline_expr(left, registry, scope)?; - let right = evaluate_baseline_expr(right, registry, scope)?; + let left = evaluate_baseline_expr(&left, registry, scope).await?; + let right = evaluate_baseline_expr(&right, registry, scope).await?; let left_span = left.tag.span; let right_span = right.tag.span; @@ -74,7 +79,7 @@ pub(crate) fn evaluate_baseline_expr( let mut exprs = vec![]; for expr in list { - let expr = evaluate_baseline_expr(expr, registry, scope)?; + let expr = evaluate_baseline_expr(&expr, registry, scope).await?; exprs.push(expr); } @@ -82,7 +87,7 @@ pub(crate) fn evaluate_baseline_expr( } Expression::Block(block) => Ok(UntaggedValue::Block(block.clone()).into_value(&tag)), Expression::Path(path) => { - let value = evaluate_baseline_expr(&path.head, registry, scope)?; + let value = evaluate_baseline_expr(&path.head, registry, scope).await?; let mut item = value; for member in &path.tail { @@ -178,6 +183,28 @@ fn evaluate_external( )) } +async fn evaluate_invocation( + block: &hir::Block, + registry: &CommandRegistry, + scope: &Scope, +) -> Result { + // FIXME: we should use a real context here + let mut context = Context::basic()?; + context.registry = registry.clone(); + + let input = InputStream::one(scope.it.clone()); + + let result = run_block(&block, &mut context, input, &scope.clone()).await?; + + let output = result.into_vec().await; + + match output.len() { + x if x > 1 => Ok(UntaggedValue::Table(output).into_value(Tag::unknown())), + 1 => Ok(output[0].clone()), + _ => Ok(UntaggedValue::nothing().into_value(Tag::unknown())), + } +} + fn evaluate_command(tag: Tag, _scope: &Scope) -> Result { Err(ShellError::syntax_error( "Unexpected command".spanned(tag.span), diff --git a/crates/nu-cli/src/prelude.rs b/crates/nu-cli/src/prelude.rs index e17b97f77..73b358c1b 100644 --- a/crates/nu-cli/src/prelude.rs +++ b/crates/nu-cli/src/prelude.rs @@ -87,7 +87,7 @@ pub(crate) use crate::stream::{InputStream, InterruptibleStream, OutputStream}; pub(crate) use async_stream::stream as async_stream; pub(crate) use bigdecimal::BigDecimal; pub(crate) use futures::stream::BoxStream; -pub(crate) use futures::{FutureExt, Stream, StreamExt}; +pub(crate) use futures::{Stream, StreamExt}; pub(crate) use nu_protocol::MaybeOwned; pub(crate) use nu_source::{ b, AnchorLocation, DebugDocBuilder, PrettyDebug, PrettyDebugWithSource, Span, SpannedItem, Tag, diff --git a/crates/nu-cli/src/shell/filesystem_shell.rs b/crates/nu-cli/src/shell/filesystem_shell.rs index decb42c80..66c60953d 100644 --- a/crates/nu-cli/src/shell/filesystem_shell.rs +++ b/crates/nu-cli/src/shell/filesystem_shell.rs @@ -109,11 +109,9 @@ impl Shell for FilesystemShell { with_symlink_targets, du, }: LsArgs, - context: &RunnableContext, + name_tag: Tag, + ctrl_c: Arc, ) -> Result { - let ctrl_c = context.ctrl_c.clone(); - let name_tag = context.name.clone(); - let (path, p_tag) = match path { Some(p) => { let p_tag = p.tag; @@ -130,7 +128,7 @@ impl Shell for FilesystemShell { if is_empty_dir(&self.path()) { return Ok(OutputStream::empty()); } else { - (PathBuf::from("./*"), context.name.clone()) + (PathBuf::from("./*"), name_tag.clone()) } } }; diff --git a/crates/nu-cli/src/shell/help_shell.rs b/crates/nu-cli/src/shell/help_shell.rs index fe89a8a7c..42b6276e4 100644 --- a/crates/nu-cli/src/shell/help_shell.rs +++ b/crates/nu-cli/src/shell/help_shell.rs @@ -140,7 +140,12 @@ impl Shell for HelpShell { self.path = path; } - fn ls(&self, _args: LsArgs, _context: &RunnableContext) -> Result { + fn ls( + &self, + _args: LsArgs, + _name: Tag, + _ctrl_c: Arc, + ) -> Result { let output = self .commands() .into_iter() diff --git a/crates/nu-cli/src/shell/shell.rs b/crates/nu-cli/src/shell/shell.rs index c38d9b4b5..ceb53d741 100644 --- a/crates/nu-cli/src/shell/shell.rs +++ b/crates/nu-cli/src/shell/shell.rs @@ -14,7 +14,12 @@ pub trait Shell: std::fmt::Debug { fn name(&self) -> String; fn homedir(&self) -> Option; - fn ls(&self, args: LsArgs, context: &RunnableContext) -> Result; + fn ls( + &self, + args: LsArgs, + name: Tag, + ctrl_c: Arc, + ) -> Result; fn cd(&self, args: CdArgs, name: Tag) -> Result; fn cp(&self, args: CopyArgs, name: Tag, path: &str) -> Result; fn mkdir(&self, args: MkdirArgs, name: Tag, path: &str) -> Result; diff --git a/crates/nu-cli/src/shell/shell_manager.rs b/crates/nu-cli/src/shell/shell_manager.rs index 8c635f148..5a4c593e2 100644 --- a/crates/nu-cli/src/shell/shell_manager.rs +++ b/crates/nu-cli/src/shell/shell_manager.rs @@ -132,59 +132,48 @@ impl ShellManager { env[self.current_shell()].homedir() } - pub fn ls(&self, args: LsArgs, context: &RunnableContext) -> Result { + pub fn ls( + &self, + args: LsArgs, + name: Tag, + ctrl_c: Arc, + ) -> Result { let env = self.shells.lock(); - env[self.current_shell()].ls(args, context) + env[self.current_shell()].ls(args, name, ctrl_c) } - pub fn cd(&self, args: CdArgs, context: &RunnableContext) -> Result { + pub fn cd(&self, args: CdArgs, name: Tag) -> Result { let env = self.shells.lock(); - env[self.current_shell()].cd(args, context.name.clone()) + env[self.current_shell()].cd(args, name) } - pub fn cp( - &self, - args: CopyArgs, - context: &RunnableContext, - ) -> Result { + pub fn cp(&self, args: CopyArgs, name: Tag) -> Result { let shells = self.shells.lock(); let path = shells[self.current_shell()].path(); - shells[self.current_shell()].cp(args, context.name.clone(), &path) + shells[self.current_shell()].cp(args, name, &path) } - pub fn rm( - &self, - args: RemoveArgs, - context: &RunnableContext, - ) -> Result { + pub fn rm(&self, args: RemoveArgs, name: Tag) -> Result { let shells = self.shells.lock(); let path = shells[self.current_shell()].path(); - shells[self.current_shell()].rm(args, context.name.clone(), &path) + shells[self.current_shell()].rm(args, name, &path) } - pub fn mkdir( - &self, - args: MkdirArgs, - context: &RunnableContext, - ) -> Result { + pub fn mkdir(&self, args: MkdirArgs, name: Tag) -> Result { let shells = self.shells.lock(); let path = shells[self.current_shell()].path(); - shells[self.current_shell()].mkdir(args, context.name.clone(), &path) + shells[self.current_shell()].mkdir(args, name, &path) } - pub fn mv( - &self, - args: MoveArgs, - context: &RunnableContext, - ) -> Result { + pub fn mv(&self, args: MoveArgs, name: Tag) -> Result { let shells = self.shells.lock(); let path = shells[self.current_shell()].path(); - shells[self.current_shell()].mv(args, context.name.clone(), &path) + shells[self.current_shell()].mv(args, name, &path) } } diff --git a/crates/nu-cli/src/shell/value_shell.rs b/crates/nu-cli/src/shell/value_shell.rs index ab54e6ffa..e101fb474 100644 --- a/crates/nu-cli/src/shell/value_shell.rs +++ b/crates/nu-cli/src/shell/value_shell.rs @@ -95,10 +95,10 @@ impl Shell for ValueShell { fn ls( &self, LsArgs { path, .. }: LsArgs, - context: &RunnableContext, + name_tag: Tag, + _ctrl_c: Arc, ) -> Result { let mut full_path = PathBuf::from(self.path()); - let name_tag = context.name.clone(); if let Some(value) = &path { full_path.push(value.as_ref()); diff --git a/crates/nu-cli/src/stream/input.rs b/crates/nu-cli/src/stream/input.rs index 6159b6417..ade98828f 100644 --- a/crates/nu-cli/src/stream/input.rs +++ b/crates/nu-cli/src/stream/input.rs @@ -19,6 +19,12 @@ impl InputStream { } } + pub fn one(item: impl Into) -> InputStream { + let mut v: VecDeque = VecDeque::new(); + v.push_back(item.into()); + v.into() + } + pub fn into_vec(self) -> impl Future> { self.values.collect() } diff --git a/crates/nu-cli/tests/commands/cal.rs b/crates/nu-cli/tests/commands/cal.rs index 4007a07ca..692c1bd54 100644 --- a/crates/nu-cli/tests/commands/cal.rs +++ b/crates/nu-cli/tests/commands/cal.rs @@ -37,7 +37,7 @@ fn cal_friday_the_thirteenths_in_2015() { "# )); - assert!(actual.out.contains("3")); + assert!(actual.out.contains('3')); } #[test] diff --git a/crates/nu-parser/src/parse.rs b/crates/nu-parser/src/parse.rs index b2796e2be..3b9a60779 100644 --- a/crates/nu-parser/src/parse.rs +++ b/crates/nu-parser/src/parse.rs @@ -73,13 +73,17 @@ fn parse_simple_column_path(lite_arg: &Spanned) -> (SpannedExpression, O } /// Parses a column path, adding in the preceding reference to $it if it's elided -fn parse_full_column_path(lite_arg: &Spanned) -> (SpannedExpression, Option) { +fn parse_full_column_path( + lite_arg: &Spanned, + registry: &dyn SignatureRegistry, +) -> (SpannedExpression, Option) { let mut delimiter = '.'; let mut inside_delimiter = false; let mut output = vec![]; let mut current_part = String::new(); let mut start_index = 0; let mut last_index = 0; + let mut error = None; let mut head = None; @@ -98,7 +102,28 @@ fn parse_full_column_path(lite_arg: &Spanned) -> (SpannedExpression, Opt lite_arg.span.start() + idx, ); - if head.is_none() && current_part.clone().starts_with('$') { + if head.is_none() && current_part.starts_with("$(") && current_part.ends_with(')') { + // We have a command invocation + let string: String = current_part + .chars() + .skip(2) + .take(current_part.len() - 3) + .collect(); + + // We haven't done much with the inner string, so let's go ahead and work with it + let lite_block = match lite_parse(&string, lite_arg.span.start() + 2) { + Ok(lp) => lp, + Err(e) => return (garbage(lite_arg.span), Some(e)), + }; + + let classified_block = classify_block(&lite_block, registry); + let err = classified_block.failed; + + if error.is_none() { + error = err; + } + head = Some(Expression::Invocation(classified_block.block)) + } else if head.is_none() && current_part.starts_with('$') { // We have the variable head head = Some(Expression::variable(current_part.clone(), part_span)) } else if let Ok(row_number) = current_part.parse::() { @@ -127,7 +152,28 @@ fn parse_full_column_path(lite_arg: &Spanned) -> (SpannedExpression, Opt ); if head.is_none() { - if current_part.starts_with('$') { + if current_part.starts_with("$(") && current_part.ends_with(')') { + // We have a command invocation + let string: String = current_part + .chars() + .skip(2) + .take(current_part.len() - 3) + .collect(); + + // We haven't done much with the inner string, so let's go ahead and work with it + let lite_block = match lite_parse(&string, lite_arg.span.start() + 2) { + Ok(lp) => lp, + Err(e) => return (garbage(lite_arg.span), Some(e)), + }; + + let classified_block = classify_block(&lite_block, registry); + let err = classified_block.failed; + + if error.is_none() { + error = err; + } + head = Some(Expression::Invocation(classified_block.block)); + } else if current_part.starts_with('$') { // We have the variable head head = Some(Expression::variable(current_part, lite_arg.span)); } else if let Ok(row_number) = current_part.parse::() { @@ -154,7 +200,7 @@ fn parse_full_column_path(lite_arg: &Spanned) -> (SpannedExpression, Opt Expression::path(SpannedExpression::new(head, lite_arg.span), output), lite_arg.span, ), - None, + error, ) } else { ( @@ -168,7 +214,7 @@ fn parse_full_column_path(lite_arg: &Spanned) -> (SpannedExpression, Opt ), lite_arg.span, ), - None, + error, ) } } @@ -310,7 +356,7 @@ fn parse_arg( lite_arg: &Spanned, ) -> (SpannedExpression, Option) { if lite_arg.item.starts_with('$') { - return parse_full_column_path(&lite_arg); + return parse_full_column_path(&lite_arg, registry); } match expected_type { @@ -374,7 +420,7 @@ fn parse_arg( ) } SyntaxShape::ColumnPath => parse_simple_column_path(lite_arg), - SyntaxShape::FullColumnPath => parse_full_column_path(lite_arg), + SyntaxShape::FullColumnPath => parse_full_column_path(lite_arg, registry), SyntaxShape::Any => { let shapes = vec![ SyntaxShape::Int, diff --git a/crates/nu-parser/src/shapes.rs b/crates/nu-parser/src/shapes.rs index d7ae07b72..a39729e92 100644 --- a/crates/nu-parser/src/shapes.rs +++ b/crates/nu-parser/src/shapes.rs @@ -6,6 +6,7 @@ use nu_source::{Spanned, SpannedItem}; pub fn expression_to_flat_shape(e: &SpannedExpression) -> Vec> { match &e.expr { Expression::Block(exprs) => shapes(exprs), + Expression::Invocation(exprs) => shapes(exprs), Expression::FilePath(_) => vec![FlatShape::Path.spanned(e.span)], Expression::Garbage => vec![FlatShape::Garbage.spanned(e.span)], Expression::List(exprs) => { diff --git a/crates/nu-protocol/src/hir.rs b/crates/nu-protocol/src/hir.rs index e72cf7fc2..6f57460d6 100644 --- a/crates/nu-protocol/src/hir.rs +++ b/crates/nu-protocol/src/hir.rs @@ -567,6 +567,16 @@ impl SpannedExpression { } Expression::Variable(Variable::It(_)) => true, Expression::Path(path) => path.head.has_shallow_it_usage(), + Expression::Invocation(block) => { + for commands in block.block.iter() { + for command in commands.list.iter() { + if command.has_it_iteration() { + return true; + } + } + } + false + } _ => false, } } @@ -614,6 +624,7 @@ impl PrettyDebugWithSource for SpannedExpression { Expression::Binary(binary) => binary.pretty_debug(source), Expression::Range(range) => range.pretty_debug(source), Expression::Block(_) => b::opaque("block"), + Expression::Invocation(_) => b::opaque("invocation"), Expression::Garbage => b::opaque("garbage"), Expression::List(list) => b::delimit( "[", @@ -654,6 +665,7 @@ impl PrettyDebugWithSource for SpannedExpression { Expression::Binary(binary) => binary.pretty_debug(source), Expression::Range(range) => range.pretty_debug(source), Expression::Block(_) => b::opaque("block"), + Expression::Invocation(_) => b::opaque("invocation"), Expression::Garbage => b::opaque("garbage"), Expression::List(list) => b::delimit( "[", @@ -874,6 +886,7 @@ pub enum Expression { FilePath(PathBuf), ExternalCommand(ExternalStringCommand), Command(Span), + Invocation(hir::Block), Boolean(bool), @@ -896,6 +909,7 @@ impl ShellTypeName for Expression { Expression::Binary(..) => "binary", Expression::Range(..) => "range", Expression::Block(..) => "block", + Expression::Invocation(..) => "command invocation", Expression::Path(..) => "variable path", Expression::Boolean(..) => "boolean", Expression::ExternalCommand(..) => "external", diff --git a/crates/nu_plugin_parse/Cargo.toml b/crates/nu_plugin_parse/Cargo.toml new file mode 100644 index 000000000..258526d68 --- /dev/null +++ b/crates/nu_plugin_parse/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "nu_plugin_parse" +version = "0.14.1" +authors = ["The Nu Project Contributors"] +edition = "2018" +description = "A string parsing plugin for Nushell" +license = "MIT" + +[lib] +doctest = false + +[dependencies] +nu-plugin = { path = "../nu-plugin", version = "0.14.1" } +nu-protocol = { path = "../nu-protocol", version = "0.14.1" } +nu-source = { path = "../nu-source", version = "0.14.1" } +nu-errors = { path = "../nu-errors", version = "0.14.1" } +futures = { version = "0.3", features = ["compat", "io-compat"] } +regex = "1" + +[build-dependencies] +nu-build = { version = "0.14.1", path = "../nu-build" } diff --git a/crates/nu_plugin_parse/build.rs b/crates/nu_plugin_parse/build.rs new file mode 100644 index 000000000..b7511cfc6 --- /dev/null +++ b/crates/nu_plugin_parse/build.rs @@ -0,0 +1,3 @@ +fn main() -> Result<(), Box> { + nu_build::build() +} diff --git a/crates/nu_plugin_parse/src/lib.rs b/crates/nu_plugin_parse/src/lib.rs new file mode 100644 index 000000000..b5bd5842d --- /dev/null +++ b/crates/nu_plugin_parse/src/lib.rs @@ -0,0 +1,4 @@ +mod nu; +mod parse; + +pub use parse::Parse; diff --git a/crates/nu_plugin_parse/src/main.rs b/crates/nu_plugin_parse/src/main.rs new file mode 100644 index 000000000..4a7d5ee3c --- /dev/null +++ b/crates/nu_plugin_parse/src/main.rs @@ -0,0 +1,7 @@ +use nu_plugin::serve_plugin; +use nu_plugin_parse::Parse; + +fn main() -> Result<(), Box> { + serve_plugin(&mut Parse::new()?); + Ok(()) +} diff --git a/crates/nu_plugin_parse/src/nu/mod.rs b/crates/nu_plugin_parse/src/nu/mod.rs new file mode 100644 index 000000000..bc6a1b781 --- /dev/null +++ b/crates/nu_plugin_parse/src/nu/mod.rs @@ -0,0 +1,153 @@ +use nu_errors::ShellError; +use nu_plugin::Plugin; +use nu_protocol::{ + CallInfo, Primitive, ReturnSuccess, ReturnValue, Signature, SyntaxShape, TaggedDictBuilder, + UntaggedValue, Value, +}; + +use crate::Parse; +use regex::Regex; + +impl Plugin for Parse { + fn config(&mut self) -> Result { + Ok(Signature::build("parse") + .required( + "pattern", + SyntaxShape::String, + "the pattern to match. Eg) \"{foo}: {bar}\"", + ) + .filter()) + } + + fn begin_filter(&mut self, call_info: CallInfo) -> Result, ShellError> { + if let Some(args) = call_info.args.positional { + match &args[0] { + Value { + value: UntaggedValue::Primitive(Primitive::String(s)), + tag, + } => { + let parse_pattern = parse(&s); + let parse_regex = build_regex(&parse_pattern); + self.column_names = column_names(&parse_pattern); + + self.regex = Regex::new(&parse_regex).map_err(|_| { + ShellError::labeled_error( + "Could not parse regex", + "could not parse regex", + tag.span, + ) + })?; + } + Value { tag, .. } => { + return Err(ShellError::labeled_error( + "Unrecognized type in params", + "unexpected value", + tag, + )); + } + } + } + Ok(vec![]) + } + + fn filter(&mut self, input: Value) -> Result, ShellError> { + match &input.as_string() { + Ok(s) => { + let mut output = vec![]; + for cap in self.regex.captures_iter(&s) { + let mut dict = TaggedDictBuilder::new(&input.tag); + for (idx, column_name) in self.column_names.iter().enumerate() { + dict.insert_untagged( + column_name, + UntaggedValue::string(cap[idx + 1].to_string()), + ); + } + output.push(Ok(ReturnSuccess::Value(dict.into_value()))); + } + Ok(output) + } + _ => Err(ShellError::labeled_error_with_secondary( + "Expected string input", + "expected string input", + &self.name, + "value originated here", + input.tag, + )), + } + } +} + +fn parse(input: &str) -> Vec { + let mut output = vec![]; + + //let mut loop_input = input; + let mut loop_input = input.chars(); + loop { + let mut before = String::new(); + + while let Some(c) = loop_input.next() { + if c == '{' { + break; + } + before.push(c); + } + + if !before.is_empty() { + output.push(ParseCommand::Text(before.to_string())); + } + // Look for column as we're now at one + let mut column = String::new(); + + while let Some(c) = loop_input.next() { + if c == '}' { + break; + } + column.push(c); + } + + if !column.is_empty() { + output.push(ParseCommand::Column(column.to_string())); + } + + if before.is_empty() && column.is_empty() { + break; + } + } + + output +} + +fn column_names(commands: &[ParseCommand]) -> Vec { + let mut output = vec![]; + + for command in commands { + if let ParseCommand::Column(c) = command { + output.push(c.clone()); + } + } + + output +} + +fn build_regex(commands: &[ParseCommand]) -> String { + let mut output = String::new(); + + for command in commands { + match command { + ParseCommand::Text(s) => { + output.push_str(&s.replace("(", "\\(")); + } + ParseCommand::Column(_) => { + output.push_str("(.*)"); + } + } + } + + output +} + +#[derive(Debug)] +enum ParseCommand { + Text(String), + Column(String), +} diff --git a/crates/nu_plugin_parse/src/parse.rs b/crates/nu_plugin_parse/src/parse.rs new file mode 100644 index 000000000..82d1b090a --- /dev/null +++ b/crates/nu_plugin_parse/src/parse.rs @@ -0,0 +1,19 @@ +use nu_source::Tag; +use regex::Regex; + +pub struct Parse { + pub regex: Regex, + pub name: Tag, + pub column_names: Vec, +} + +impl Parse { + #[allow(clippy::trivial_regex)] + pub fn new() -> Result> { + Ok(Parse { + regex: Regex::new("")?, + name: Tag::unknown(), + column_names: vec![], + }) + } +} diff --git a/src/plugins/nu_plugin_stable_parse.rs b/src/plugins/nu_plugin_stable_parse.rs new file mode 100644 index 000000000..4a7d5ee3c --- /dev/null +++ b/src/plugins/nu_plugin_stable_parse.rs @@ -0,0 +1,7 @@ +use nu_plugin::serve_plugin; +use nu_plugin_parse::Parse; + +fn main() -> Result<(), Box> { + serve_plugin(&mut Parse::new()?); + Ok(()) +} diff --git a/tests/shell/pipeline/commands/internal.rs b/tests/shell/pipeline/commands/internal.rs index 144bdab03..69ee3c265 100644 --- a/tests/shell/pipeline/commands/internal.rs +++ b/tests/shell/pipeline/commands/internal.rs @@ -162,4 +162,16 @@ mod tilde_expansion { ); }) } + + #[test] + fn argument_invocation() { + let actual = nu!( + cwd: ".", + r#" + echo "foo" | echo $(echo $it) + "# + ); + + assert_eq!(actual.out, "foo"); + } }