Compare commits

...

55 Commits

Author SHA1 Message Date
2df8775b48 Include chart binaries. (#2667) 2020-10-13 17:04:27 -05:00
e02b4f1443 Update wix plugin check with base test. (#2666) 2020-10-13 16:22:49 -05:00
194782215f Update main.wxs
Rename the plugins to be the production names
2020-10-14 09:01:13 +13:00
df17d28c0f Create README.build.txt 2020-10-14 07:14:47 +13:00
5f43c8f024 Update lib.rs 2020-10-14 06:45:04 +13:00
1a18734f9a Update Cargo.toml 2020-10-14 06:44:06 +13:00
4a70c1ff4f Update Cargo.toml
Get around the mutual dependency?
2020-10-14 06:42:24 +13:00
770e5d89f2 Bump to 0.21 (#2663) 2020-10-14 06:19:09 +13:00
cfac8e84dd Disable rustyline bracketed paste mode by default (#2659)
Multiline pastes wait for the user to hit enter before running,
because they enter a special paste mode in rustyline called
'bracketed paste' by default. This commit disables that mode
by default for nushell, causing multiline pastes to be executed
immediately, treating each new line as a separate command.
2020-10-13 19:33:36 +13:00
43d90c1745 Root level cleanup (#2654)
* Remove unused files from rootdir

* Remove unused build deps
2020-10-12 22:47:46 -05:00
38bdb053d2 Add tests for get_data_by_key (#2658)
* Add test for get_data_by_key

* Apply same order for ValuExt impl

* Nothing helper for tests

* Use get_data_by_key from ValueExt
2020-10-12 22:46:58 -05:00
95e61773a5 Restore bigint/bigdecimal serialization. (#2662) 2020-10-12 21:44:28 -05:00
4e931fa73f Extract out xpath to a plugin. (#2661) 2020-10-12 18:18:39 -05:00
2573441e28 xpath command for nushell (#2656)
* xpath prototype

* new xpath engine is finally working

* nearly there

* closer

* working with list, started to add test, code cleanup

* broken again

* working again - time for some cleanup

* cleaned up code, added error handling and test

* update example, fix clippy

* removed commented char
2020-10-12 08:03:00 -05:00
5770b15270 Use iterator chain instead of string concat. (#2655)
* Use iterator chain instead of string concat

* Add regression test for multi-value lines
2020-10-10 18:30:48 +13:00
6817b472d0 Handle inf/nan in delimited data (#2652) 2020-10-09 19:27:01 +13:00
2b076369e0 handle duration overflow error (#2616)
* handle duration overflow error

* handle checked_add_signed result
2020-10-09 14:51:47 +13:00
973a8ee8f3 Allow config to work with column paths. (#2653)
Nu has many commands that allow the nuño to customize behavior such
as UI and behavior. Today, coloring can be customized, the line editor,
and other things. The more options there are, the higher the complexity
in managing them.

To mitigate this Nu can store configuration options as nested properties.

But to add and edit them can be taxing. With column path support we can
work with them easier.
2020-10-08 20:04:19 -05:00
1159d3365a Fix clippy lints (#2651) 2020-10-09 10:47:51 +13:00
152ba32eb7 Debugging tips for contributors (#2647) 2020-10-08 15:14:59 +13:00
153320ef33 Added -1 back when determining term_width (#2646)
* Added -1 back

* retrigger checks

* removed the max

* fixed a mistake
2020-10-07 12:45:57 -05:00
ff236da72c [wasi] Update time & instant crates (#2645)
* [wasi] Update time & instant crates

In https://github.com/nushell/nushell/pull/2643 instant was updated by adding it as a hard dependency in Cargo.toml, but it's better to avoid it and only update in Cargo.lock via `cargo update -p ...`.

Additionally, updated `time` crate so that now some basic commands like `ls` work too, although formatting is pretty bad.

* Update default terminal width to 80

If termsize can't return anything, use 80 chars (e.g. on WASI).
2020-10-07 15:26:16 +13:00
54326869e4 Parse decimals as BigDecimal (#2644)
Use implicit serde from BigDecimal crate
2020-10-07 14:01:40 +13:00
f14f4e39c5 Begin adding wasi support (#2643)
* Begin adding wasi support

* Now it builds and runs but needs more help
2020-10-07 11:21:24 +13:00
a18b2702ca Parse integers as BigInt (#2642)
* Parse integer shape as BigInt

* Use implicit serde from BigInt crate
2020-10-07 06:30:18 +13:00
93410c470e Bump dtparse to fix panic (#2632) 2020-10-07 06:27:06 +13:00
5d945ef869 empty? rewrite. (#2641) 2020-10-06 05:21:20 -05:00
df07be6a42 Fix to_md function name (#2636)
* Fix to_md function name

* rustfmt
2020-10-05 18:13:27 -05:00
3c32d4947c added blink and underline options to coloring (#2638) 2020-10-05 18:12:56 -05:00
2ea5235aea Ensure Wix lists Nu plugin binaries. (#2637) 2020-10-05 14:29:04 -05:00
c096f031ce update wix to include _core_ and _extra_ plugins + s3, chart, line (#2634) 2020-10-04 05:56:33 +13:00
ae1d4bdb4c Nushell internal commands. Anchor locations tracker surveying. (#2635) 2020-10-03 09:06:02 -05:00
0adf2accdd Fix defaulting alias var values (#2631) 2020-10-03 09:18:23 +13:00
4201f48be5 Left Pad and Right Pad String (#2630)
* WIP

* left and right pad strings

* fixed some tests
2020-10-02 14:45:59 -05:00
b076e375ca Fix broken removal of sockets (#2629)
* make sort-by fail gracefully if mismatched types are compared

* Added a test to check if sorted-by with invalid types exists gracefully

* Linter changes

* removed redundant pattern matching

* Changed the error message

* Added a comma after every argument

* Changed the test to accomodate the new err messages

* Err message for sort-by invalid types now shows the mismatched types

* Lints problems

* Changed unwrap to expect

* Added the -f flag to rm command

Now when you a use rm -f there will be no error message, even if the
file doesnt actually exist

* Lint problems

* Fixed the wrong line

* Removed println

* Spelling mistake

* Fix problems when you mv a file into itself

* Lint mistakes

* Remove unecessary filtering in most cases

* Allow the removal of sockets

* Conditional compilations to systems without socket
2020-10-02 17:50:55 +13:00
2f1016d44f Add examples to update cmd (#2628) 2020-10-01 20:13:42 -05:00
ddf9d61346 Line charts. Chart plugin sub command extraction. (#2627) 2020-10-01 19:23:10 -05:00
f0b7ab5ecc chart tweaks for windows (#2626) 2020-10-01 14:48:57 -05:00
e4c6336bd4 Convert to string before clip (#2624) 2020-10-01 18:22:19 +13:00
66061192f8 Fix "mv allows moving a directory into itself" (#2619)
* make sort-by fail gracefully if mismatched types are compared

* Added a test to check if sorted-by with invalid types exists gracefully

* Linter changes

* removed redundant pattern matching

* Changed the error message

* Added a comma after every argument

* Changed the test to accomodate the new err messages

* Err message for sort-by invalid types now shows the mismatched types

* Lints problems

* Changed unwrap to expect

* Added the -f flag to rm command

Now when you a use rm -f there will be no error message, even if the
file doesnt actually exist

* Lint problems

* Fixed the wrong line

* Removed println

* Spelling mistake

* Fix problems when you mv a file into itself

* Lint mistakes

* Remove unecessary filtering in most cases
2020-10-01 14:01:05 +13:00
b7bc4c1f80 Exit bar visualization if any key is pressed other than left and right arrow keys. (#2623) 2020-09-30 14:34:29 -05:00
a56abb6502 Bar Chart baseline. (#2621)
Bar Chart ready.
2020-09-30 13:27:52 -05:00
892a416211 Move BTreeMap to IndexMap to preserve order (#2617) 2020-09-30 19:49:40 +13:00
f45adecd01 fix select for column names with spaces (#2613) 2020-09-30 10:00:07 +13:00
bd015e82dc Tidy up crates in nu-protocol (#2611)
* Remove unneeded crates from nu-protocol

* Simplify join, use std fn
2020-09-29 16:33:43 +13:00
cf43b74f26 did_you_mean without dependency (#2610) 2020-09-29 16:32:29 +13:00
18909ec14a Describe object now matches cmd name (#2603) 2020-09-27 14:54:47 +13:00
ed243c88d2 Move non-essential deps into specific crates (#2601) 2020-09-26 18:32:52 +12:00
cb7723f423 Refactor scope (#2602)
* Refactor scope to have parents

* Refactor scope to have parents

* Refactor scope to have parents

* Clippy

Co-authored-by: Jonathan Turner <jonathan@pop-os.localdomain>
2020-09-26 11:40:02 +12:00
9dc88f8a95 Add env var during benchmark to randomize stack (#2600) 2020-09-26 10:57:48 +12:00
0a439fe52f Removed unused files in nu-data (#2598) 2020-09-25 15:44:59 +12:00
a8b65e35ec Consolidate suggestions code (#2597) 2020-09-25 15:44:24 +12:00
bd9e598bf0 did_you_mean returns just the word matches (#2595) 2020-09-24 15:56:19 +12:00
75f8247af1 added .cargo/config.toml to build with bigger stack on windows (#2594)
* added .cargo/config.toml to build with bigger stack on windows

* updated comments
2020-09-24 15:55:33 +12:00
e8ec5027ff remove without check path exist, rm -f (#2590) 2020-09-22 17:11:31 -04:00
295 changed files with 5229 additions and 2047 deletions

6
.cargo/config.toml Normal file
View File

@ -0,0 +1,6 @@
# use LLD as linker on Windows because it could be faster
# for full and incremental builds compared to default
[target.x86_64-pc-windows-msvc]
#linker = "lld-link.exe"
rustflags = ["-C", "link-args=-stack:10000000"]

View File

@ -31,6 +31,11 @@ cargo build
cargo build --release && cargo run --release
```
- Build and run with extra features:
```shell
cargo build --release --features=extra && cargo run --release --features=extra
```
- Run Clippy on Nushell:
```shell
@ -60,3 +65,11 @@ cargo build
```shell
cargo fmt --all
```
### Debugging Tips
- To view verbose logs when developing, enable the `trace` log level.
```shell
cargo build --release --features=extra && cargo run --release --features=extra -- --loglevel trace
```

209
Cargo.lock generated
View File

@ -607,6 +607,12 @@ dependencies = [
"zip",
]
[[package]]
name = "cassowary"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53"
[[package]]
name = "cc"
version = "1.0.59"
@ -940,6 +946,22 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "crossterm"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2fcdc3c9cf8ee446222e8ee8691a6d21b563b8fe1a64b1873080db7b5b23cf0"
dependencies = [
"bitflags",
"crossterm_winapi",
"lazy_static 1.4.0",
"libc",
"mio 0.7.0",
"parking_lot 0.11.0",
"signal-hook",
"winapi 0.3.9",
]
[[package]]
name = "crossterm_winapi"
version = "0.6.1"
@ -1185,9 +1207,9 @@ checksum = "134951f4028bdadb9b84baf4232681efbf277da25144b9b0ad65df75946c422b"
[[package]]
name = "dtparse"
version = "1.1.0"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9713da7ca51bcd8ecbaedbd6309110eb1ca930d2109ef595a125f84fa1bc608b"
checksum = "13276c5dbd7f365e00efe6631242772fe6615e1899df84d1f6ce3ae7b48209f6"
dependencies = [
"chrono",
"chrono-tz",
@ -1725,7 +1747,7 @@ checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb"
dependencies = [
"cfg-if",
"libc",
"wasi",
"wasi 0.9.0+wasi-snapshot-preview1",
]
[[package]]
@ -2206,9 +2228,12 @@ dependencies = [
[[package]]
name = "instant"
version = "0.1.6"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b141fdc7836c525d4d594027d318c84161ca17aaf8113ab1f81ab93ae897485"
checksum = "63312a18f7ea8760cdd0a7c5aac1a619752a246b833545e3e36d1f81f7cd9e66"
dependencies = [
"cfg-if",
]
[[package]]
name = "iovec"
@ -2749,15 +2774,6 @@ dependencies = [
"tempfile",
]
[[package]]
name = "natural"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65e6b44f8ddc659cde3555e0140d3441ad26cb03a1410774af1f9a19097c1867"
dependencies = [
"rust-stemmers",
]
[[package]]
name = "neso"
version = "0.5.0"
@ -2842,10 +2858,9 @@ dependencies = [
[[package]]
name = "nu"
version = "0.20.0"
version = "0.21.0"
dependencies = [
"clap",
"crossterm",
"ctrlc",
"dunce",
"futures 0.3.5",
@ -2860,6 +2875,7 @@ dependencies = [
"nu-test-support",
"nu-value-ext",
"nu_plugin_binaryview",
"nu_plugin_chart",
"nu_plugin_fetch",
"nu_plugin_from_bson",
"nu_plugin_from_sqlite",
@ -2874,17 +2890,13 @@ dependencies = [
"nu_plugin_to_bson",
"nu_plugin_to_sqlite",
"nu_plugin_tree",
"nu_plugin_xpath",
"pretty_env_logger",
"quick-xml 0.18.1",
"semver 0.10.0",
"serde 1.0.115",
"toml",
"url 2.1.1",
]
[[package]]
name = "nu-cli"
version = "0.20.0"
version = "0.21.0"
dependencies = [
"Inflector",
"ansi_term 0.12.1",
@ -2924,7 +2936,6 @@ dependencies = [
"itertools",
"log 0.4.11",
"meval",
"natural",
"nu-data",
"nu-errors",
"nu-parser",
@ -2962,6 +2973,8 @@ dependencies = [
"sha2 0.9.1",
"shellexpand",
"strip-ansi-escapes",
"sxd-document",
"sxd-xpath",
"tempfile",
"term",
"term_size",
@ -2980,7 +2993,7 @@ dependencies = [
[[package]]
name = "nu-data"
version = "0.20.0"
version = "0.21.0"
dependencies = [
"ansi_term 0.12.1",
"bigdecimal",
@ -2996,6 +3009,7 @@ dependencies = [
"nu-protocol",
"nu-source",
"nu-table",
"nu-test-support",
"nu-value-ext",
"num-bigint 0.3.0",
"num-traits 0.2.12",
@ -3008,7 +3022,7 @@ dependencies = [
[[package]]
name = "nu-errors"
version = "0.20.0"
version = "0.21.0"
dependencies = [
"ansi_term 0.12.1",
"bigdecimal",
@ -3027,7 +3041,7 @@ dependencies = [
[[package]]
name = "nu-parser"
version = "0.20.0"
version = "0.21.0"
dependencies = [
"bigdecimal",
"codespan-reporting",
@ -3045,7 +3059,7 @@ dependencies = [
[[package]]
name = "nu-plugin"
version = "0.20.0"
version = "0.21.0"
dependencies = [
"bigdecimal",
"indexmap",
@ -3060,19 +3074,15 @@ dependencies = [
[[package]]
name = "nu-protocol"
version = "0.20.0"
version = "0.21.0"
dependencies = [
"ansi_term 0.12.1",
"bigdecimal",
"byte-unit",
"chrono",
"codespan-reporting",
"derive-new",
"getset",
"indexmap",
"itertools",
"log 0.4.11",
"natural",
"nu-errors",
"nu-source",
"num-bigint 0.3.0",
@ -3087,7 +3097,7 @@ dependencies = [
[[package]]
name = "nu-source"
version = "0.20.0"
version = "0.21.0"
dependencies = [
"derive-new",
"getset",
@ -3098,7 +3108,7 @@ dependencies = [
[[package]]
name = "nu-table"
version = "0.20.0"
version = "0.21.0"
dependencies = [
"ansi_term 0.12.1",
"unicode-width",
@ -3106,20 +3116,24 @@ dependencies = [
[[package]]
name = "nu-test-support"
version = "0.20.0"
version = "0.21.0"
dependencies = [
"chrono",
"dunce",
"getset",
"glob",
"indexmap",
"nu-errors",
"nu-protocol",
"nu-source",
"nu-value-ext",
"num-bigint 0.3.0",
"tempfile",
]
[[package]]
name = "nu-value-ext"
version = "0.20.0"
version = "0.21.0"
dependencies = [
"indexmap",
"itertools",
@ -3131,10 +3145,10 @@ dependencies = [
[[package]]
name = "nu_plugin_binaryview"
version = "0.20.0"
version = "0.21.0"
dependencies = [
"ansi_term 0.12.1",
"crossterm",
"crossterm 0.18.0",
"image",
"neso",
"nu-errors",
@ -3145,9 +3159,24 @@ dependencies = [
"rawkey",
]
[[package]]
name = "nu_plugin_chart"
version = "0.21.0"
dependencies = [
"crossterm 0.18.0",
"nu-cli",
"nu-data",
"nu-errors",
"nu-plugin",
"nu-protocol",
"nu-source",
"nu-value-ext",
"tui",
]
[[package]]
name = "nu_plugin_fetch"
version = "0.20.0"
version = "0.21.0"
dependencies = [
"base64 0.12.3",
"futures 0.3.5",
@ -3161,7 +3190,7 @@ dependencies = [
[[package]]
name = "nu_plugin_from_bson"
version = "0.20.0"
version = "0.21.0"
dependencies = [
"bigdecimal",
"bson",
@ -3175,7 +3204,7 @@ dependencies = [
[[package]]
name = "nu_plugin_from_sqlite"
version = "0.20.0"
version = "0.21.0"
dependencies = [
"bigdecimal",
"nu-errors",
@ -3190,7 +3219,7 @@ dependencies = [
[[package]]
name = "nu_plugin_inc"
version = "0.20.0"
version = "0.21.0"
dependencies = [
"nu-errors",
"nu-plugin",
@ -3202,7 +3231,7 @@ dependencies = [
[[package]]
name = "nu_plugin_match"
version = "0.20.0"
version = "0.21.0"
dependencies = [
"nu-errors",
"nu-plugin",
@ -3213,7 +3242,7 @@ dependencies = [
[[package]]
name = "nu_plugin_post"
version = "0.20.0"
version = "0.21.0"
dependencies = [
"base64 0.12.3",
"futures 0.3.5",
@ -3229,7 +3258,7 @@ dependencies = [
[[package]]
name = "nu_plugin_ps"
version = "0.20.0"
version = "0.21.0"
dependencies = [
"futures 0.3.5",
"futures-timer",
@ -3243,7 +3272,7 @@ dependencies = [
[[package]]
name = "nu_plugin_s3"
version = "0.20.0"
version = "0.21.0"
dependencies = [
"futures 0.3.5",
"nu-errors",
@ -3255,7 +3284,7 @@ dependencies = [
[[package]]
name = "nu_plugin_start"
version = "0.20.0"
version = "0.21.0"
dependencies = [
"glob",
"nu-errors",
@ -3268,7 +3297,7 @@ dependencies = [
[[package]]
name = "nu_plugin_sys"
version = "0.20.0"
version = "0.21.0"
dependencies = [
"battery",
"futures 0.3.5",
@ -3283,7 +3312,7 @@ dependencies = [
[[package]]
name = "nu_plugin_textview"
version = "0.20.0"
version = "0.21.0"
dependencies = [
"ansi_term 0.12.1",
"bat",
@ -3298,7 +3327,7 @@ dependencies = [
[[package]]
name = "nu_plugin_to_bson"
version = "0.20.0"
version = "0.21.0"
dependencies = [
"bson",
"nu-errors",
@ -3311,7 +3340,7 @@ dependencies = [
[[package]]
name = "nu_plugin_to_sqlite"
version = "0.20.0"
version = "0.21.0"
dependencies = [
"hex 0.4.2",
"nu-errors",
@ -3326,7 +3355,7 @@ dependencies = [
[[package]]
name = "nu_plugin_tree"
version = "0.20.0"
version = "0.21.0"
dependencies = [
"derive-new",
"nu-errors",
@ -3336,6 +3365,21 @@ dependencies = [
"ptree",
]
[[package]]
name = "nu_plugin_xpath"
version = "0.21.0"
dependencies = [
"bigdecimal",
"indexmap",
"nu-errors",
"nu-plugin",
"nu-protocol",
"nu-source",
"nu-test-support",
"sxd-document",
"sxd-xpath",
]
[[package]]
name = "num"
version = "0.2.1"
@ -3699,6 +3743,12 @@ version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
[[package]]
name = "peresil"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f658886ed52e196e850cfbbfddab9eaa7f6d90dd0929e264c31e5cec07e09e57"
[[package]]
name = "pest"
version = "2.1.3"
@ -4482,16 +4532,6 @@ version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e52c148ef37f8c375d49d5a73aa70713125b7f19095948a923f80afdeb22ec2"
[[package]]
name = "rust-stemmers"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e46a2036019fdb888131db7a4c847a1063a7493f971ed94ea82c67eada63ca54"
dependencies = [
"serde 1.0.115",
"serde_derive",
]
[[package]]
name = "rust_decimal"
version = "0.10.2"
@ -5034,6 +5074,27 @@ dependencies = [
"web-sys",
]
[[package]]
name = "sxd-document"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94d82f37be9faf1b10a82c4bd492b74f698e40082f0f40de38ab275f31d42078"
dependencies = [
"peresil",
"typed-arena",
]
[[package]]
name = "sxd-xpath"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36e39da5d30887b5690e29de4c5ebb8ddff64ebd9933f98a01daaa4fd11b36ea"
dependencies = [
"peresil",
"quick-error",
"sxd-document",
]
[[package]]
name = "syn"
version = "1.0.39"
@ -5198,11 +5259,12 @@ dependencies = [
[[package]]
name = "time"
version = "0.1.43"
version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438"
checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
dependencies = [
"libc",
"wasi 0.10.0+wasi-snapshot-preview1",
"winapi 0.3.9",
]
@ -5499,6 +5561,19 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "tui"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2eaeee894a1e9b90f80aa466fe59154fdb471980b5e104d8836fcea309ae17e"
dependencies = [
"bitflags",
"cassowary",
"crossterm 0.17.8",
"unicode-segmentation",
"unicode-width",
]
[[package]]
name = "typed-arena"
version = "1.7.0"
@ -5778,6 +5853,12 @@ version = "0.9.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
[[package]]
name = "wasi"
version = "0.10.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
[[package]]
name = "wasm-bindgen"
version = "0.2.67"

View File

@ -10,7 +10,7 @@ license = "MIT"
name = "nu"
readme = "README.md"
repository = "https://github.com/nushell/nushell"
version = "0.20.0"
version = "0.21.0"
[workspace]
members = ["crates/*/"]
@ -18,51 +18,57 @@ members = ["crates/*/"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
nu-cli = {version = "0.20.0", path = "./crates/nu-cli"}
nu-data = {version = "0.20.0", path = "./crates/nu-data"}
nu-errors = {version = "0.20.0", path = "./crates/nu-errors"}
nu-parser = {version = "0.20.0", path = "./crates/nu-parser"}
nu-plugin = {version = "0.20.0", path = "./crates/nu-plugin"}
nu-protocol = {version = "0.20.0", path = "./crates/nu-protocol"}
nu-source = {version = "0.20.0", path = "./crates/nu-source"}
nu-value-ext = {version = "0.20.0", path = "./crates/nu-value-ext"}
nu-cli = {version = "0.21.0", path = "./crates/nu-cli"}
nu-data = {version = "0.21.0", path = "./crates/nu-data"}
nu-errors = {version = "0.21.0", path = "./crates/nu-errors"}
nu-parser = {version = "0.21.0", path = "./crates/nu-parser"}
nu-plugin = {version = "0.21.0", path = "./crates/nu-plugin"}
nu-protocol = {version = "0.21.0", path = "./crates/nu-protocol"}
nu-source = {version = "0.21.0", path = "./crates/nu-source"}
nu-value-ext = {version = "0.21.0", path = "./crates/nu-value-ext"}
nu_plugin_binaryview = {version = "0.20.0", path = "./crates/nu_plugin_binaryview", optional = true}
nu_plugin_fetch = {version = "0.20.0", path = "./crates/nu_plugin_fetch", optional = true}
nu_plugin_from_bson = {version = "0.20.0", path = "./crates/nu_plugin_from_bson", optional = true}
nu_plugin_from_sqlite = {version = "0.20.0", path = "./crates/nu_plugin_from_sqlite", optional = true}
nu_plugin_inc = {version = "0.20.0", path = "./crates/nu_plugin_inc", optional = true}
nu_plugin_match = {version = "0.20.0", path = "./crates/nu_plugin_match", optional = true}
nu_plugin_post = {version = "0.20.0", path = "./crates/nu_plugin_post", optional = true}
nu_plugin_ps = {version = "0.20.0", path = "./crates/nu_plugin_ps", optional = true}
nu_plugin_s3 = {version = "0.20.0", path = "./crates/nu_plugin_s3", optional = true}
nu_plugin_start = {version = "0.20.0", path = "./crates/nu_plugin_start", optional = true}
nu_plugin_sys = {version = "0.20.0", path = "./crates/nu_plugin_sys", optional = true}
nu_plugin_textview = {version = "0.20.0", path = "./crates/nu_plugin_textview", optional = true}
nu_plugin_to_bson = {version = "0.20.0", path = "./crates/nu_plugin_to_bson", optional = true}
nu_plugin_to_sqlite = {version = "0.20.0", path = "./crates/nu_plugin_to_sqlite", optional = true}
nu_plugin_tree = {version = "0.20.0", path = "./crates/nu_plugin_tree", optional = true}
crossterm = {version = "0.17", optional = true}
semver = {version = "0.10.0", optional = true}
url = {version = "2.1.1", optional = true}
nu_plugin_binaryview = {version = "0.21.0", path = "./crates/nu_plugin_binaryview", optional = true}
nu_plugin_chart = {version = "0.21.0", path = "./crates/nu_plugin_chart", optional = true}
nu_plugin_fetch = {version = "0.21.0", path = "./crates/nu_plugin_fetch", optional = true}
nu_plugin_from_bson = {version = "0.21.0", path = "./crates/nu_plugin_from_bson", optional = true}
nu_plugin_from_sqlite = {version = "0.21.0", path = "./crates/nu_plugin_from_sqlite", optional = true}
nu_plugin_inc = {version = "0.21.0", path = "./crates/nu_plugin_inc", optional = true}
nu_plugin_match = {version = "0.21.0", path = "./crates/nu_plugin_match", optional = true}
nu_plugin_post = {version = "0.21.0", path = "./crates/nu_plugin_post", optional = true}
nu_plugin_ps = {version = "0.21.0", path = "./crates/nu_plugin_ps", optional = true}
nu_plugin_s3 = {version = "0.21.0", path = "./crates/nu_plugin_s3", optional = true}
nu_plugin_start = {version = "0.21.0", path = "./crates/nu_plugin_start", optional = true}
nu_plugin_sys = {version = "0.21.0", path = "./crates/nu_plugin_sys", optional = true}
nu_plugin_textview = {version = "0.21.0", path = "./crates/nu_plugin_textview", optional = true}
nu_plugin_to_bson = {version = "0.21.0", path = "./crates/nu_plugin_to_bson", optional = true}
nu_plugin_to_sqlite = {version = "0.21.0", path = "./crates/nu_plugin_to_sqlite", optional = true}
nu_plugin_tree = {version = "0.21.0", path = "./crates/nu_plugin_tree", optional = true}
nu_plugin_xpath = {version = "0.21.0", path = "./crates/nu_plugin_xpath", optional = true}
# Required to bootstrap the main binary
clap = "2.33.3"
ctrlc = "3.1.6"
dunce = "1.0.1"
ctrlc = {version = "3.1.6", optional = true}
futures = {version = "0.3.5", features = ["compat", "io-compat"]}
log = "0.4.11"
pretty_env_logger = "0.4.0"
quick-xml = "0.18.1"
[dev-dependencies]
nu-test-support = {version = "0.20.0", path = "./crates/nu-test-support"}
dunce = "1.0.1"
nu-test-support = {version = "0.21.0", path = "./crates/nu-test-support"}
[build-dependencies]
serde = {version = "1.0.115", features = ["derive"]}
toml = "0.5.6"
[features]
ctrlc-support = ["nu-cli/ctrlc"]
directories-support = ["nu-cli/directories", "nu-cli/dirs", "nu-data/directories", "nu-data/dirs"]
git-support = ["nu-cli/git2"]
ptree-support = ["nu-cli/ptree"]
rich-benchmark = ["nu-cli/rich-benchmark"]
rustyline-support = ["nu-cli/rustyline-support"]
term-support = ["nu-cli/term"]
uuid-support = ["nu-cli/uuid_crate"]
which-support = ["nu-cli/ichwh", "nu-cli/which"]
default = [
"sys",
"ps",
@ -81,38 +87,33 @@ default = [
"fetch",
"rich-benchmark",
]
extra = ["default", "binaryview", "tree", "clipboard-cli", "trash-support", "start", "bson", "sqlite", "s3"]
extra = ["default", "binaryview", "tree", "clipboard-cli", "trash-support", "start", "bson", "sqlite", "s3", "chart", "xpath"]
stable = ["default"]
# Default
inc = ["semver", "nu_plugin_inc"]
ps = ["nu_plugin_ps"]
sys = ["nu_plugin_sys"]
textview = ["crossterm", "url", "nu_plugin_textview"]
wasi = ["inc", "match", "directories-support", "ptree-support", "match", "tree", "rustyline-support"]
# Stable
binaryview = ["nu_plugin_binaryview"]
bson = ["nu_plugin_from_bson", "nu_plugin_to_bson"]
trace = ["nu-parser/trace"]
# Stable (Default)
fetch = ["nu_plugin_fetch"]
inc = ["nu_plugin_inc"]
match = ["nu_plugin_match"]
post = ["nu_plugin_post"]
ps = ["nu_plugin_ps"]
sys = ["nu_plugin_sys"]
textview = ["nu_plugin_textview"]
# Extra
binaryview = ["nu_plugin_binaryview"]
bson = ["nu_plugin_from_bson", "nu_plugin_to_bson"]
chart = ["nu_plugin_chart"]
clipboard-cli = ["nu-cli/clipboard-cli"]
s3 = ["nu_plugin_s3"]
sqlite = ["nu_plugin_from_sqlite", "nu_plugin_to_sqlite"]
start = ["nu_plugin_start"]
trace = ["nu-parser/trace"]
tree = ["nu_plugin_tree"]
clipboard-cli = ["nu-cli/clipboard-cli"]
ctrlc-support = ["nu-cli/ctrlc"]
directories-support = ["nu-cli/directories", "nu-cli/dirs", "nu-data/directories", "nu-data/dirs"]
git-support = ["nu-cli/git2"]
ptree-support = ["nu-cli/ptree"]
rich-benchmark = ["nu-cli/rich-benchmark"]
rustyline-support = ["nu-cli/rustyline-support"]
term-support = ["nu-cli/term"]
trash-support = ["nu-cli/trash-support"]
uuid-support = ["nu-cli/uuid_crate"]
which-support = ["nu-cli/ichwh", "nu-cli/which"]
tree = ["nu_plugin_tree"]
xpath = ["nu_plugin_xpath"]
# Core plugins that ship with `cargo install nu` by default
# Currently, Cargo limits us to installing only one binary
@ -174,6 +175,21 @@ name = "nu_plugin_extra_s3"
path = "src/plugins/nu_plugin_extra_s3.rs"
required-features = ["s3"]
[[bin]]
name = "nu_plugin_extra_chart_bar"
path = "src/plugins/nu_plugin_extra_chart_bar.rs"
required-features = ["chart"]
[[bin]]
name = "nu_plugin_extra_chart_line"
path = "src/plugins/nu_plugin_extra_chart_line.rs"
required-features = ["chart"]
[[bin]]
name = "nu_plugin_extra_xpath"
path = "src/plugins/nu_plugin_extra_xpath.rs"
required-features = ["xpath"]
# Main nu binary
[[bin]]
name = "nu"

View File

View File

@ -4,21 +4,21 @@ description = "CLI for nushell"
edition = "2018"
license = "MIT"
name = "nu-cli"
version = "0.20.0"
version = "0.21.0"
[lib]
doctest = false
[dependencies]
nu-data = {version = "0.20.0", path = "../nu-data"}
nu-errors = {version = "0.20.0", path = "../nu-errors"}
nu-parser = {version = "0.20.0", path = "../nu-parser"}
nu-plugin = {version = "0.20.0", path = "../nu-plugin"}
nu-protocol = {version = "0.20.0", path = "../nu-protocol"}
nu-source = {version = "0.20.0", path = "../nu-source"}
nu-table = {version = "0.20.0", path = "../nu-table"}
nu-test-support = {version = "0.20.0", path = "../nu-test-support"}
nu-value-ext = {version = "0.20.0", path = "../nu-value-ext"}
nu-data = {version = "0.21.0", path = "../nu-data"}
nu-errors = {version = "0.21.0", path = "../nu-errors"}
nu-parser = {version = "0.21.0", path = "../nu-parser"}
nu-plugin = {version = "0.21.0", path = "../nu-plugin"}
nu-protocol = {version = "0.21.0", path = "../nu-protocol"}
nu-source = {version = "0.21.0", path = "../nu-source"}
nu-table = {version = "0.21.0", path = "../nu-table"}
nu-test-support = {version = "0.21.0", path = "../nu-test-support"}
nu-value-ext = {version = "0.21.0", path = "../nu-value-ext"}
ansi_term = "0.12.1"
async-recursion = "0.3.1"
@ -36,7 +36,7 @@ ctrlc = {version = "3.1.6", optional = true}
derive-new = "0.5.8"
directories = {version = "3.0.1", optional = true}
dirs = {version = "3.0.1", optional = true}
dtparse = "1.1.0"
dtparse = "1.2.0"
dunce = "1.0.1"
eml-parser = "0.1.0"
filesize = "0.2.0"
@ -55,7 +55,6 @@ indexmap = {version = "1.6.0", features = ["serde-1"]}
itertools = "0.9.0"
log = "0.4.11"
meval = "0.2.0"
natural = "0.5.0"
num-bigint = {version = "0.3.0", features = ["serde"]}
num-format = {version = "0.4.0", features = ["with-num-bigint"]}
num-traits = "0.2.12"
@ -64,6 +63,7 @@ pin-utils = "0.1.0"
pretty-hex = "0.2.0"
ptree = {version = "0.3.0", optional = true}
query_interface = "0.3.5"
quick-xml = "0.18.1"
rand = "0.7.3"
regex = "1.3.9"
roxmltree = "0.13.0"
@ -79,6 +79,8 @@ serde_yaml = "0.8.13"
sha2 = "0.9.1"
shellexpand = "2.0.0"
strip-ansi-escapes = "0.1.0"
sxd-document = "0.3.2"
sxd-xpath = "0.4.2"
tempfile = "3.1.0"
term = {version = "0.6.1", optional = true}
term_size = "0.3.2"
@ -93,7 +95,6 @@ zip = {version = "0.5.7", optional = true}
Inflector = "0.11"
clipboard = {version = "0.5.0", optional = true}
encoding_rs = "0.8.24"
quick-xml = "0.18.1"
rayon = "1.4.0"
trash = {version = "1.1.1", optional = true}
url = "2.1.1"

View File

@ -9,7 +9,7 @@ use crate::EnvironmentSyncer;
use futures_codec::FramedRead;
use nu_errors::ShellError;
use nu_protocol::hir::{ClassifiedCommand, Expression, InternalCommand, Literal, NamedArguments};
use nu_protocol::{Primitive, ReturnSuccess, UntaggedValue, Value};
use nu_protocol::{Primitive, ReturnSuccess, Scope, UntaggedValue, Value};
use log::{debug, trace};
#[cfg(feature = "rustyline-support")]
@ -95,7 +95,7 @@ pub fn create_default_context(interactive: bool) -> Result<EvaluationContext, Bo
whole_stream_command(Kill),
whole_stream_command(Version),
whole_stream_command(Clear),
whole_stream_command(What),
whole_stream_command(Describe),
whole_stream_command(Which),
whole_stream_command(Debug),
whole_stream_command(Alias),
@ -114,6 +114,8 @@ pub fn create_default_context(interactive: bool) -> Result<EvaluationContext, Bo
whole_stream_command(Shells),
whole_stream_command(Enter),
whole_stream_command(Exit),
// Viz
whole_stream_command(Chart),
// Viewers
whole_stream_command(Autoview),
whole_stream_command(Table),
@ -145,7 +147,9 @@ pub fn create_default_context(interactive: bool) -> Result<EvaluationContext, Bo
whole_stream_command(StrEndsWith),
whole_stream_command(StrCollect),
whole_stream_command(StrLength),
whole_stream_command(StrLPad),
whole_stream_command(StrReverse),
whole_stream_command(StrRPad),
whole_stream_command(StrCamelCase),
whole_stream_command(StrPascalCase),
whole_stream_command(StrKebabCase),
@ -192,7 +196,7 @@ pub fn create_default_context(interactive: bool) -> Result<EvaluationContext, Bo
whole_stream_command(Each),
whole_stream_command(EachGroup),
whole_stream_command(EachWindow),
whole_stream_command(IsEmpty),
whole_stream_command(Empty),
// Table manipulation
whole_stream_command(Move),
whole_stream_command(Merge),
@ -395,9 +399,7 @@ pub async fn cli(mut context: EvaluationContext) -> Result<(), Box<dyn Error>> {
&prompt_block.block,
&mut context,
InputStream::empty(),
&Value::nothing(),
&IndexMap::new(),
&env,
Scope::from_env(env),
)
.await
{
@ -667,6 +669,9 @@ fn default_rustyline_editor_configuration() -> Editor<Helper> {
Cmd::Move(Movement::ForwardWord(1, At::AfterEnd, Word::Vi)),
);
// workaround for multiline-paste hang in rustyline (see https://github.com/kkawakam/rustyline/issues/202)
rl.bind_sequence(KeyPress::BracketedPasteStart, rustyline::Cmd::Noop);
// Let's set the defaults up front and then override them later if the user indicates
// defaults taken from here https://github.com/kkawakam/rustyline/blob/2fe886c9576c1ea13ca0e5808053ad491a6fe049/src/config.rs#L150-L167
rl.set_max_history_size(100);
@ -862,9 +867,7 @@ pub async fn parse_and_eval(line: &str, ctx: &mut EvaluationContext) -> Result<S
&classified_block.block,
ctx,
input_stream,
&Value::nothing(),
&IndexMap::new(),
&env,
Scope::from_env(env),
)
.await?
.collect_string(Tag::unknown())
@ -1021,9 +1024,7 @@ pub async fn process_line(
&classified_block.block,
ctx,
input_stream,
&Value::nothing(),
&IndexMap::new(),
&env,
Scope::from_env(env),
)
.await
{

View File

@ -17,6 +17,7 @@ pub(crate) mod build_string;
pub(crate) mod cal;
pub(crate) mod cd;
pub(crate) mod char_;
pub(crate) mod chart;
pub(crate) mod classified;
#[cfg(feature = "clipboard-cli")]
pub(crate) mod clip;
@ -29,11 +30,13 @@ pub(crate) mod cp;
pub(crate) mod date;
pub(crate) mod debug;
pub(crate) mod default;
pub(crate) mod describe;
pub(crate) mod do_;
pub(crate) mod drop;
pub(crate) mod du;
pub(crate) mod each;
pub(crate) mod echo;
pub(crate) mod empty;
pub(crate) mod enter;
pub(crate) mod every;
pub(crate) mod exec;
@ -65,7 +68,6 @@ pub(crate) mod history;
pub(crate) mod if_;
pub(crate) mod insert;
pub(crate) mod into_int;
pub(crate) mod is_empty;
pub(crate) mod keep;
pub(crate) mod last;
pub(crate) mod lines;
@ -120,7 +122,6 @@ pub(crate) mod uniq;
pub(crate) mod update;
pub(crate) mod url_;
pub(crate) mod version;
pub(crate) mod what;
pub(crate) mod where_;
pub(crate) mod which_;
pub(crate) mod with_env;
@ -134,7 +135,7 @@ pub(crate) use command::{
pub(crate) use alias::Alias;
pub(crate) use ansi::Ansi;
pub(crate) use append::Append;
pub(crate) use append::Command as Append;
pub(crate) use autoenv::Autoenv;
pub(crate) use autoenv_trust::AutoenvTrust;
pub(crate) use autoenv_untrust::AutoenvUnTrust;
@ -142,6 +143,7 @@ pub(crate) use benchmark::Benchmark;
pub(crate) use build_string::BuildString;
pub(crate) use cal::Cal;
pub(crate) use char_::Char;
pub(crate) use chart::Chart;
pub(crate) use compact::Compact;
pub(crate) use config::{
Config, ConfigClear, ConfigGet, ConfigLoad, ConfigPath, ConfigRemove, ConfigSet, ConfigSetInto,
@ -151,6 +153,7 @@ pub(crate) use cp::Cpy;
pub(crate) use date::{Date, DateFormat, DateNow, DateUTC};
pub(crate) use debug::Debug;
pub(crate) use default::Default;
pub(crate) use describe::Describe;
pub(crate) use do_::Do;
pub(crate) use drop::Drop;
pub(crate) use du::Du;
@ -158,10 +161,10 @@ pub(crate) use each::Each;
pub(crate) use each::EachGroup;
pub(crate) use each::EachWindow;
pub(crate) use echo::Echo;
pub(crate) use empty::Command as Empty;
pub(crate) use if_::If;
pub(crate) use is_empty::IsEmpty;
pub(crate) use nu::NuPlugin;
pub(crate) use update::Update;
pub(crate) use update::Command as Update;
pub(crate) mod kill;
pub(crate) use kill::Kill;
pub(crate) mod clear;
@ -190,13 +193,13 @@ pub(crate) use from_xml::FromXML;
pub(crate) use from_yaml::FromYAML;
pub(crate) use from_yaml::FromYML;
pub(crate) use get::Get;
pub(crate) use group_by::GroupBy;
pub(crate) use group_by::Command as GroupBy;
pub(crate) use group_by_date::GroupByDate;
pub(crate) use headers::Headers;
pub(crate) use help::Help;
pub(crate) use histogram::Histogram;
pub(crate) use history::History;
pub(crate) use insert::Insert;
pub(crate) use insert::Command as Insert;
pub(crate) use into_int::IntoInt;
pub(crate) use keep::{Keep, KeepUntil, KeepWhile};
pub(crate) use last::Last;
@ -243,9 +246,9 @@ pub(crate) use split::{Split, SplitChars, SplitColumn, SplitRow};
pub(crate) use split_by::SplitBy;
pub(crate) use str_::{
Str, StrCamelCase, StrCapitalize, StrCollect, StrContains, StrDowncase, StrEndsWith,
StrFindReplace, StrFrom, StrIndexOf, StrKebabCase, StrLength, StrPascalCase, StrReverse,
StrScreamingSnakeCase, StrSet, StrSnakeCase, StrStartsWith, StrSubstring, StrToDatetime,
StrToDecimal, StrToInteger, StrTrim, StrTrimLeft, StrTrimRight, StrUpcase,
StrFindReplace, StrFrom, StrIndexOf, StrKebabCase, StrLPad, StrLength, StrPascalCase, StrRPad,
StrReverse, StrScreamingSnakeCase, StrSet, StrSnakeCase, StrStartsWith, StrSubstring,
StrToDatetime, StrToDecimal, StrToInteger, StrTrim, StrTrimLeft, StrTrimRight, StrUpcase,
};
pub(crate) use table::Table;
pub(crate) use tags::Tags;
@ -263,8 +266,43 @@ pub(crate) use touch::Touch;
pub(crate) use uniq::Uniq;
pub(crate) use url_::{UrlCommand, UrlHost, UrlPath, UrlQuery, UrlScheme};
pub(crate) use version::Version;
pub(crate) use what::What;
pub(crate) use where_::Where;
pub(crate) use which_::Which;
pub(crate) use with_env::WithEnv;
pub(crate) use wrap::Wrap;
#[cfg(test)]
mod tests {
use super::*;
use crate::commands::whole_stream_command;
use crate::examples::{test_anchors, test_examples};
use nu_errors::ShellError;
fn commands() -> Vec<Command> {
vec![
whole_stream_command(Append),
whole_stream_command(GroupBy),
whole_stream_command(Insert),
whole_stream_command(Update),
whole_stream_command(Empty),
]
}
#[test]
fn examples_work_as_expected() -> Result<(), ShellError> {
for cmd in commands() {
test_examples(cmd)?;
}
Ok(())
}
#[test]
fn tracks_metadata() -> Result<(), ShellError> {
for cmd in commands() {
test_anchors(cmd)?;
}
Ok(())
}
}

View File

@ -340,11 +340,12 @@ fn find_block_shapes(block: &Block, registry: &CommandRegistry) -> Result<ShapeM
#[cfg(test)]
mod tests {
use super::Alias;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(Alias {})
Ok(test_examples(Alias {})?)
}
}

View File

@ -135,11 +135,12 @@ pub fn str_to_ansi_color(s: String) -> Option<String> {
#[cfg(test)]
mod tests {
use super::Ansi;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(Ansi {})
Ok(test_examples(Ansi {})?)
}
}

View File

@ -2,17 +2,17 @@ use crate::command_registry::CommandRegistry;
use crate::commands::WholeStreamCommand;
use crate::prelude::*;
use nu_errors::ShellError;
use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value};
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
#[derive(Deserialize)]
struct AppendArgs {
struct Arguments {
row: Value,
}
pub struct Append;
pub struct Command;
#[async_trait]
impl WholeStreamCommand for Append {
impl WholeStreamCommand for Command {
fn name(&self) -> &str {
"append"
}
@ -34,11 +34,18 @@ impl WholeStreamCommand for Append {
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
let (AppendArgs { row }, input) = args.process(registry).await?;
let (Arguments { mut row }, input) = args.process(registry).await?;
let eos = futures::stream::iter(vec![row]);
let input: Vec<Value> = input.collect().await;
Ok(input.chain(eos).to_output_stream())
if let Some(first) = input.get(0) {
row.tag = first.tag();
}
Ok(
futures::stream::iter(input.into_iter().chain(vec![row]).map(ReturnSuccess::value))
.to_output_stream(),
)
}
fn examples(&self) -> Vec<Example> {
@ -54,15 +61,3 @@ impl WholeStreamCommand for Append {
}]
}
}
#[cfg(test)]
mod tests {
use super::Append;
#[test]
fn examples_work_as_expected() {
use crate::examples::test as test_examples;
test_examples(Append {})
}
}

View File

@ -318,7 +318,7 @@ fn create_default_command_args(context: &RunnableContextWithoutInput) -> RawComm
external_redirection: ExternalRedirection::Stdout,
},
name_tag: context.name.clone(),
scope: Scope::new(),
scope: Scope::create(),
},
}
}
@ -326,11 +326,12 @@ fn create_default_command_args(context: &RunnableContextWithoutInput) -> RawComm
#[cfg(test)]
mod tests {
use super::Command;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(Command {})
Ok(test_examples(Command {})?)
}
}

View File

@ -10,25 +10,16 @@ pub enum AutoPivotMode {
impl AutoPivotMode {
pub fn is_auto(&self) -> bool {
match &self {
AutoPivotMode::Auto => true,
_ => false,
}
matches!(self, AutoPivotMode::Auto)
}
pub fn is_always(&self) -> bool {
match &self {
AutoPivotMode::Always => true,
_ => false,
}
matches!(self, AutoPivotMode::Always)
}
#[allow(unused)]
pub fn is_never(&self) -> bool {
match &self {
AutoPivotMode::Never => true,
_ => false,
}
matches!(self, AutoPivotMode::Never)
}
}

View File

@ -8,6 +8,10 @@ use nu_protocol::{
hir::{Block, ClassifiedCommand, Commands, InternalCommand},
Dictionary, Scope, Signature, SyntaxShape, UntaggedValue, Value,
};
use rand::{
distributions::Alphanumeric,
prelude::{thread_rng, Rng},
};
use std::convert::TryInto;
use std::time::{Duration, Instant};
@ -79,20 +83,18 @@ async fn benchmark(
let scope = raw_args.call_info.scope.clone();
let (BenchmarkArgs { block, passthrough }, input) = raw_args.process(&registry).await?;
let env = scope.env();
let name = generate_free_name(&env);
let mut env = IndexMap::new();
env.insert(name, generate_random_env_value());
let scope = Scope::append_env(scope, env);
let start_time = Instant::now();
#[cfg(feature = "rich-benchmark")]
let start = time().await;
let result = run_block(
&block,
&mut context,
input,
&scope.it,
&scope.vars,
&scope.env,
)
.await;
let result = run_block(&block, &mut context, input, scope.clone()).await;
let output = result?.into_vec().await;
#[cfg(feature = "rich-benchmark")]
@ -108,7 +110,7 @@ async fn benchmark(
let real_time = into_big_int(end_time - start_time);
indexmap.insert("real time".to_string(), real_time);
benchmark_output(indexmap, output, passthrough, &tag, &mut context, &scope).await
benchmark_output(indexmap, output, passthrough, &tag, &mut context, scope).await
}
// return advanced stats
#[cfg(feature = "rich-benchmark")]
@ -127,7 +129,7 @@ async fn benchmark(
let idle_time = into_big_int(end.idle() - start.idle());
indexmap.insert("idle time".to_string(), idle_time);
benchmark_output(indexmap, output, passthrough, &tag, &mut context, &scope).await
benchmark_output(indexmap, output, passthrough, &tag, &mut context, scope).await
} else {
Err(ShellError::untagged_runtime_error(
"Could not retreive CPU time",
@ -141,7 +143,7 @@ async fn benchmark_output<T, Output>(
passthrough: Option<Block>,
tag: T,
context: &mut EvaluationContext,
scope: &Scope,
scope: Arc<Scope>,
) -> Result<OutputStream, ShellError>
where
T: Into<Tag> + Copy,
@ -161,15 +163,7 @@ where
// add autoview for an empty block
let time_block = add_implicit_autoview(time_block);
let _ = run_block(
&time_block,
context,
benchmark_output,
&scope.it,
&scope.vars,
&scope.env,
)
.await?;
let _ = run_block(&time_block, context, benchmark_output, scope).await?;
context.clear_errors();
Ok(block_output.into())
@ -200,3 +194,19 @@ fn into_big_int<T: TryInto<Duration>>(time: T) -> BigInt {
.as_nanos()
.into()
}
fn generate_random_env_value() -> String {
let mut thread_rng = thread_rng();
let len = thread_rng.gen_range(1, 16 * 1024);
thread_rng.sample_iter(&Alphanumeric).take(len).collect()
}
fn generate_free_name(env: &indexmap::IndexMap<String, String>) -> String {
let mut thread_rng = thread_rng();
loop {
let candidate_name = format!("NU_RANDOM_VALUE_{}", thread_rng.gen::<usize>());
if !env.contains_key(&candidate_name) {
return candidate_name;
}
}
}

View File

@ -339,11 +339,12 @@ fn add_month_to_table(
#[cfg(test)]
mod tests {
use super::Cal;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(Cal {})
Ok(test_examples(Cal {})?)
}
}

View File

@ -72,11 +72,12 @@ impl WholeStreamCommand for Cd {
#[cfg(test)]
mod tests {
use super::Cd;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(Cd {})
Ok(test_examples(Cd {})?)
}
}

View File

@ -130,11 +130,12 @@ fn str_to_character(s: &str) -> Option<String> {
#[cfg(test)]
mod tests {
use super::Char;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(Char {})
Ok(test_examples(Char {})?)
}
}

View File

@ -0,0 +1,53 @@
use crate::commands::WholeStreamCommand;
use crate::prelude::*;
use nu_errors::ShellError;
use nu_protocol::{ReturnSuccess, Signature, UntaggedValue};
#[derive(Clone)]
pub struct Chart;
#[async_trait]
impl WholeStreamCommand for Chart {
fn name(&self) -> &str {
"chart"
}
fn signature(&self) -> Signature {
Signature::build("chart")
}
fn usage(&self) -> &str {
"Displays charts."
}
async fn run(
&self,
_args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
if registry.get_command("chart bar").is_none() {
return Err(ShellError::untagged_runtime_error(
"nu_plugin_chart not installed.",
));
}
let registry = registry.clone();
Ok(OutputStream::one(Ok(ReturnSuccess::Value(
UntaggedValue::string(crate::commands::help::get_help(&Chart, &registry))
.into_value(Tag::unknown()),
))))
}
}
#[cfg(test)]
mod tests {
use super::Chart;
use super::ShellError;
#[test]
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
Ok(test_examples(Chart {})?)
}
}

View File

@ -6,16 +6,14 @@ use crate::stream::InputStream;
use futures::stream::TryStreamExt;
use nu_errors::ShellError;
use nu_protocol::hir::{Block, ClassifiedCommand, Commands};
use nu_protocol::{ReturnSuccess, UntaggedValue, Value};
use nu_protocol::{ReturnSuccess, Scope, UntaggedValue, Value};
use std::sync::atomic::Ordering;
pub(crate) async fn run_block(
block: &Block,
ctx: &mut EvaluationContext,
mut input: InputStream,
it: &Value,
vars: &IndexMap<String, Value>,
env: &IndexMap<String, String>,
scope: Arc<Scope>,
) -> Result<InputStream, ShellError> {
let mut output: Result<InputStream, ShellError> = Ok(InputStream::empty());
for pipeline in &block.block {
@ -54,7 +52,7 @@ pub(crate) async fn run_block(
return Err(e);
}
}
output = run_pipeline(pipeline, ctx, input, it, vars, env).await;
output = run_pipeline(pipeline, ctx, input, scope.clone()).await;
input = InputStream::empty();
}
@ -66,9 +64,7 @@ async fn run_pipeline(
commands: &Commands,
ctx: &mut EvaluationContext,
mut input: InputStream,
it: &Value,
vars: &IndexMap<String, Value>,
env: &IndexMap<String, String>,
scope: Arc<Scope>,
) -> Result<InputStream, ShellError> {
for item in commands.list.clone() {
input = match item {
@ -77,13 +73,13 @@ async fn run_pipeline(
}
ClassifiedCommand::Expr(expr) => {
run_expression_block(*expr, ctx, it, vars, env).await?
run_expression_block(*expr, ctx, scope.clone()).await?
}
ClassifiedCommand::Error(err) => return Err(err.into()),
ClassifiedCommand::Internal(left) => {
run_internal_command(left, ctx, input, it, vars, env).await?
run_internal_command(left, ctx, input, scope.clone()).await?
}
};
}

View File

@ -6,14 +6,12 @@ use log::{log_enabled, trace};
use futures::stream::once;
use nu_errors::ShellError;
use nu_protocol::hir::SpannedExpression;
use nu_protocol::Value;
use nu_protocol::Scope;
pub(crate) async fn run_expression_block(
expr: SpannedExpression,
context: &mut EvaluationContext,
it: &Value,
vars: &IndexMap<String, Value>,
env: &IndexMap<String, String>,
scope: Arc<Scope>,
) -> Result<InputStream, ShellError> {
if log_enabled!(log::Level::Trace) {
trace!(target: "nu::run::expr", "->");
@ -21,7 +19,7 @@ pub(crate) async fn run_expression_block(
}
let registry = context.registry().clone();
let output = evaluate_baseline_expr(&expr, &registry, it, vars, env).await?;
let output = evaluate_baseline_expr(&expr, &registry, scope).await?;
Ok(once(async { Ok(output) }).to_input_stream())
}

View File

@ -21,7 +21,7 @@ pub(crate) async fn run_external_command(
command: ExternalCommand,
context: &mut EvaluationContext,
input: InputStream,
scope: &Scope,
scope: Arc<Scope>,
external_redirection: ExternalRedirection,
) -> Result<InputStream, ShellError> {
trace!(target: "nu::run::external", "-> {}", command.name);
@ -41,7 +41,7 @@ async fn run_with_stdin(
command: ExternalCommand,
context: &mut EvaluationContext,
input: InputStream,
scope: &Scope,
scope: Arc<Scope>,
external_redirection: ExternalRedirection,
) -> Result<InputStream, ShellError> {
let path = context.shell_manager.path();
@ -50,9 +50,7 @@ async fn run_with_stdin(
let mut command_args = vec![];
for arg in command.args.iter() {
let value =
evaluate_baseline_expr(arg, &context.registry, &scope.it, &scope.vars, &scope.env)
.await?;
let value = evaluate_baseline_expr(arg, &context.registry, scope.clone()).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
@ -138,7 +136,7 @@ fn spawn(
args: &[String],
input: InputStream,
external_redirection: ExternalRedirection,
scope: &Scope,
scope: Arc<Scope>,
) -> Result<InputStream, ShellError> {
let command = command.clone();
@ -169,7 +167,7 @@ fn spawn(
trace!(target: "nu::run::external", "cwd = {:?}", &path);
process.env_clear();
process.envs(scope.env.iter());
process.envs(scope.env());
// We want stdout regardless of what
// we are doing ($it case or pipe stdin)
@ -580,7 +578,7 @@ mod tests {
cmd,
&mut ctx,
input,
&Scope::new(),
Scope::create(),
ExternalRedirection::Stdout
)
.await

View File

@ -11,20 +11,13 @@ pub(crate) async fn run_internal_command(
command: InternalCommand,
context: &mut EvaluationContext,
input: InputStream,
it: &Value,
vars: &IndexMap<String, Value>,
env: &IndexMap<String, String>,
scope: Arc<Scope>,
) -> Result<InputStream, ShellError> {
if log_enabled!(log::Level::Trace) {
trace!(target: "nu::run::internal", "->");
trace!(target: "nu::run::internal", "{}", command.name);
}
let scope = Scope {
it: it.clone(),
vars: vars.clone(),
env: env.clone(),
};
let objects: InputStream = trace_stream!(target: "nu::trace_stream::internal", "input" = input);
let internal_command = context.expect_command(&command.name);
@ -38,7 +31,7 @@ pub(crate) async fn run_internal_command(
internal_command?,
Tag::unknown_anchor(command.name_span),
command.args.clone(),
&scope,
scope.clone(),
objects,
)
.await?
@ -48,8 +41,6 @@ pub(crate) async fn run_internal_command(
//let context = Arc::new(context.clone());
let context = context.clone();
let command = Arc::new(command);
let scope = Arc::new(scope);
// let scope = scope.clone();
Ok(InputStream::from_stream(
result
@ -90,7 +81,7 @@ pub(crate) async fn run_internal_command(
external_redirection: ExternalRedirection::Stdout,
},
name_tag: Tag::unknown_anchor(command.name_span),
scope: (&*scope).clone(),
scope,
},
};
let result = converter

View File

@ -130,7 +130,7 @@ async fn run_filter(
UntaggedValue::Primitive(Primitive::EndOfStream).into_untagged_value()
]);
let args = args.evaluate_once_with_scope(&registry, &scope).await?;
let args = args.evaluate_once_with_scope(&registry, scope).await?;
let real_path = Path::new(&path);
let ext = real_path.extension();

View File

@ -43,15 +43,3 @@ impl WholeStreamCommand for Clear {
}]
}
}
#[cfg(test)]
mod tests {
use super::Clear;
#[test]
fn examples_work_as_expected() {
use crate::examples::test as test_examples;
test_examples(Clear {})
}
}

View File

@ -32,11 +32,18 @@ impl WholeStreamCommand for Clip {
}
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Save text to the clipboard",
example: "echo 'secret value' | clip",
result: None,
}]
vec![
Example {
description: "Save text to the clipboard",
example: "echo 'secret value' | clip",
result: None,
},
Example {
description: "Save numbers to the clipboard",
example: "random integer 10000000..99999999 | clip",
result: None,
},
]
}
}
@ -61,16 +68,14 @@ pub async fn clip(
first = false;
}
let string: String = match i.as_string() {
Ok(string) => string.to_string(),
Err(_) => {
return Err(ShellError::labeled_error(
"Given non-string data",
"expected strings from pipeline",
name,
))
}
};
let string: String = i.convert_to_string();
if string.is_empty() {
return Err(ShellError::labeled_error(
"Unable to convert to string",
"Unable to convert to string",
name,
));
}
new_copy_data.push_str(&string);
}
@ -99,11 +104,12 @@ pub async fn clip(
#[cfg(test)]
mod tests {
use super::Clip;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(Clip {})
Ok(test_examples(Clip {})?)
}
}

View File

@ -17,27 +17,12 @@ use std::sync::atomic::AtomicBool;
pub struct UnevaluatedCallInfo {
pub args: hir::Call,
pub name_tag: Tag,
pub scope: Scope,
pub scope: Arc<Scope>,
}
impl UnevaluatedCallInfo {
pub async fn evaluate(self, registry: &CommandRegistry) -> Result<CallInfo, ShellError> {
let args = evaluate_args(&self.args, registry, &self.scope).await?;
Ok(CallInfo {
args,
name_tag: self.name_tag,
})
}
pub async fn evaluate_with_new_it(
self,
registry: &CommandRegistry,
it: &Value,
) -> Result<CallInfo, ShellError> {
let mut scope = self.scope.clone();
scope.it = it.clone();
let args = evaluate_args(&self.args, registry, &scope).await?;
let args = evaluate_args(&self.args, registry, self.scope.clone()).await?;
Ok(CallInfo {
args,
@ -115,7 +100,7 @@ impl CommandArgs {
pub async fn evaluate_once_with_scope(
self,
registry: &CommandRegistry,
scope: &Scope,
scope: Arc<Scope>,
) -> Result<EvaluatedWholeStreamCommandArgs, ShellError> {
let host = self.host.clone();
let ctrl_c = self.ctrl_c.clone();
@ -215,37 +200,6 @@ impl EvaluatedWholeStreamCommandArgs {
}
}
#[derive(Getters)]
#[get = "pub"]
pub struct EvaluatedFilterCommandArgs {
args: EvaluatedCommandArgs,
}
impl Deref for EvaluatedFilterCommandArgs {
type Target = EvaluatedCommandArgs;
fn deref(&self) -> &Self::Target {
&self.args
}
}
impl EvaluatedFilterCommandArgs {
pub fn new(
host: Arc<parking_lot::Mutex<dyn Host>>,
ctrl_c: Arc<AtomicBool>,
shell_manager: ShellManager,
call_info: CallInfo,
) -> EvaluatedFilterCommandArgs {
EvaluatedFilterCommandArgs {
args: EvaluatedCommandArgs {
host,
ctrl_c,
shell_manager,
call_info,
},
}
}
}
#[derive(Getters, new)]
#[get = "pub(crate)"]
pub struct EvaluatedCommandArgs {
@ -381,69 +335,6 @@ impl Command {
}
}
pub struct FnFilterCommand {
name: String,
func: fn(EvaluatedFilterCommandArgs) -> Result<OutputStream, ShellError>,
}
#[async_trait]
impl WholeStreamCommand for FnFilterCommand {
fn name(&self) -> &str {
&self.name
}
fn usage(&self) -> &str {
"usage"
}
async fn run(
&self,
CommandArgs {
host,
ctrl_c,
shell_manager,
call_info,
input,
..
}: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
let registry = Arc::new(registry.clone());
let func = self.func;
Ok(input
.then(move |it| {
let host = host.clone();
let registry = registry.clone();
let ctrl_c = ctrl_c.clone();
let shell_manager = shell_manager.clone();
let call_info = call_info.clone();
async move {
let call_info = match call_info.evaluate_with_new_it(&*registry, &it).await {
Err(err) => {
return OutputStream::one(Err(err));
}
Ok(args) => args,
};
let args = EvaluatedFilterCommandArgs::new(
host.clone(),
ctrl_c.clone(),
shell_manager.clone(),
call_info,
);
match func(args) {
Err(err) => return OutputStream::one(Err(err)),
Ok(stream) => stream,
}
}
})
.flatten()
.to_output_stream())
}
}
pub fn whole_stream_command(command: impl WholeStreamCommand + 'static) -> Command {
Command(Arc::new(command))
}

View File

@ -37,22 +37,11 @@ impl WholeStreamCommand for Compact {
}
fn examples(&self) -> Vec<Example> {
vec![
Example {
description: "Filter out all null entries in a list",
example: "echo [1 2 $null 3 $null $null] | compact",
result: Some(vec![
UntaggedValue::int(1).into(),
UntaggedValue::int(2).into(),
UntaggedValue::int(3).into(),
]),
},
Example {
description: "Filter out all directory entries having no 'target'",
example: "ls -la | compact target",
result: None,
},
]
vec![Example {
description: "Filter out all directory entries having no 'target'",
example: "ls -la | compact target",
result: None,
}]
}
}
@ -95,11 +84,12 @@ pub async fn compact(
#[cfg(test)]
mod tests {
use super::Compact;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(Compact {})
Ok(test_examples(Compact {})?)
}
}

View File

@ -2,14 +2,13 @@ use crate::command_registry::CommandRegistry;
use crate::commands::WholeStreamCommand;
use crate::prelude::*;
use nu_errors::ShellError;
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
use nu_source::Tagged;
use nu_protocol::{ColumnPath, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
pub struct SubCommand;
#[derive(Deserialize)]
pub struct GetArgs {
get: Tagged<String>,
path: ColumnPath,
}
#[async_trait]
@ -21,7 +20,7 @@ impl WholeStreamCommand for SubCommand {
fn signature(&self) -> Signature {
Signature::build("config get").required(
"get",
SyntaxShape::Any,
SyntaxShape::ColumnPath,
"value to get from the config",
)
}
@ -51,17 +50,14 @@ pub async fn get(
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
let name_span = args.call_info.name_tag.clone();
let (GetArgs { get }, _) = args.process(&registry).await?;
let name_tag = args.call_info.name_tag.clone();
let (GetArgs { path }, _) = args.process(&registry).await?;
// NOTE: None because we are not loading a new config file, we just want to read from the
// existing config
let result = nu_data::config::read(name_span, &None)?;
let result = UntaggedValue::row(nu_data::config::read(&name_tag, &None)?).into_value(&name_tag);
let key = get.to_string();
let value = result
.get(&key)
.ok_or_else(|| ShellError::labeled_error("Missing key in config", "key", get.tag()))?;
let value = crate::commands::get::get_column_path(&path, &result)?;
Ok(match value {
Value {
@ -75,9 +71,6 @@ pub async fn get(
futures::stream::iter(list).to_output_stream()
}
x => {
let x = x.clone();
OutputStream::one(ReturnSuccess::value(x))
}
x => OutputStream::one(ReturnSuccess::value(x)),
})
}

View File

@ -2,14 +2,13 @@ use crate::command_registry::CommandRegistry;
use crate::commands::WholeStreamCommand;
use crate::prelude::*;
use nu_errors::ShellError;
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
use nu_source::Tagged;
use nu_protocol::{ColumnPath, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
pub struct SubCommand;
#[derive(Deserialize)]
pub struct SetArgs {
key: Tagged<String>,
path: ColumnPath,
value: Value,
}
@ -21,7 +20,7 @@ impl WholeStreamCommand for SubCommand {
fn signature(&self) -> Signature {
Signature::build("config set")
.required("key", SyntaxShape::String, "variable name to set")
.required("key", SyntaxShape::ColumnPath, "variable name to set")
.required("value", SyntaxShape::Any, "value to use")
}
@ -38,11 +37,28 @@ impl WholeStreamCommand for SubCommand {
}
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Set nonzero_exit_errors to true",
example: "config set nonzero_exit_errors $true",
result: None,
}]
vec![
Example {
description: "Set auto pivoting",
example: "config set pivot_mode always",
result: None,
},
Example {
description: "Set line editor options",
example: "config set line_editor [[edit_mode, completion_type]; [emacs circular]]",
result: None,
},
Example {
description: "Set coloring options",
example: "config set color_config [[header_align header_bold]; [left $true]]",
result: None,
},
Example {
description: "Set nested options",
example: "config set color_config.header_color white",
result: None,
},
]
}
}
@ -50,18 +66,32 @@ pub async fn set(
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
let name_span = args.call_info.name_tag.clone();
let (SetArgs { key, value }, _) = args.process(&registry).await?;
let name_tag = args.call_info.name_tag.clone();
let (SetArgs { path, mut value }, _) = args.process(&registry).await?;
// NOTE: None because we are not loading a new config file, we just want to read from the
// existing config
let mut result = nu_data::config::read(name_span, &None)?;
let raw_entries = nu_data::config::read(&name_tag, &None)?;
let configuration = UntaggedValue::row(raw_entries).into_value(&name_tag);
result.insert(key.to_string(), value.clone());
if let UntaggedValue::Table(rows) = &value.value {
if rows.len() == 1 && rows[0].is_row() {
value = rows[0].clone();
}
}
config::write(&result, &None)?;
match configuration.forgiving_insert_data_at_column_path(&path, value) {
Ok(Value {
value: UntaggedValue::Row(changes),
..
}) => {
config::write(&changes.entries, &None)?;
Ok(OutputStream::one(ReturnSuccess::value(
UntaggedValue::Row(result.into()).into_value(&value.tag),
)))
Ok(OutputStream::one(ReturnSuccess::value(
UntaggedValue::Row(changes).into_value(name_tag),
)))
}
Ok(_) => Ok(OutputStream::empty()),
Err(reason) => Err(reason),
}
}

View File

@ -80,11 +80,12 @@ impl WholeStreamCommand for Count {
#[cfg(test)]
mod tests {
use super::Count;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(Count {})
Ok(test_examples(Count {})?)
}
}

View File

@ -66,11 +66,12 @@ impl WholeStreamCommand for Cpy {
#[cfg(test)]
mod tests {
use super::Cpy;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(Cpy {})
Ok(test_examples(Cpy {})?)
}
}

View File

@ -36,11 +36,12 @@ impl WholeStreamCommand for Command {
#[cfg(test)]
mod tests {
use super::Command;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(Command {})
Ok(test_examples(Command {})?)
}
}

View File

@ -61,3 +61,16 @@ pub async fn format(
Ok(OutputStream::one(value))
}
#[cfg(test)]
mod tests {
use super::Date;
use super::ShellError;
#[test]
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
Ok(test_examples(Date {})?)
}
}

View File

@ -48,3 +48,16 @@ pub async fn now(
Ok(OutputStream::one(value))
}
#[cfg(test)]
mod tests {
use super::Date;
use super::ShellError;
#[test]
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
Ok(test_examples(Date {})?)
}
}

View File

@ -48,3 +48,16 @@ pub async fn utc(
Ok(OutputStream::one(value))
}
#[cfg(test)]
mod tests {
use super::Date;
use super::ShellError;
#[test]
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
Ok(test_examples(Date {})?)
}
}

View File

@ -55,11 +55,12 @@ async fn debug_value(
#[cfg(test)]
mod tests {
use super::Debug;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(Debug {})
Ok(test_examples(Debug {})?)
}
}

View File

@ -83,11 +83,12 @@ async fn default(
#[cfg(test)]
mod tests {
use super::Default;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(Default {})
Ok(test_examples(Default {})?)
}
}

View File

@ -4,13 +4,13 @@ use crate::prelude::*;
use nu_errors::ShellError;
use nu_protocol::{ReturnSuccess, Signature, UntaggedValue};
pub struct What;
pub struct Describe;
#[derive(Deserialize)]
pub struct WhatArgs {}
pub struct DescribeArgs {}
#[async_trait]
impl WholeStreamCommand for What {
impl WholeStreamCommand for Describe {
fn name(&self) -> &str {
"describe"
}
@ -28,11 +28,11 @@ impl WholeStreamCommand for What {
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
what(args, registry).await
describe(args, registry).await
}
}
pub async fn what(
pub async fn describe(
args: CommandArgs,
_registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
@ -49,12 +49,13 @@ pub async fn what(
#[cfg(test)]
mod tests {
use super::What;
use super::Describe;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(What {})
Ok(test_examples(Describe {})?)
}
}

View File

@ -95,15 +95,7 @@ async fn do_(
block.set_redirect(block_redirection);
let result = run_block(
&block,
&mut context,
input,
&scope.it,
&scope.vars,
&scope.env,
)
.await;
let result = run_block(&block, &mut context, input, scope).await;
if ignore_errors {
// To properly ignore errors we need to redirect stderr, consume it, and remove
@ -125,11 +117,12 @@ async fn do_(
#[cfg(test)]
mod tests {
use super::Do;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(Do {})
Ok(test_examples(Do {})?)
}
}

View File

@ -85,11 +85,12 @@ async fn drop(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStr
#[cfg(test)]
mod tests {
use super::Drop;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(Drop {})
Ok(test_examples(Drop {})?)
}
}

View File

@ -427,11 +427,12 @@ impl From<FileInfo> for Value {
#[cfg(test)]
mod tests {
use super::Du;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(Du {})
Ok(test_examples(Du {})?)
}
}

View File

@ -97,9 +97,7 @@ pub async fn process_row(
&block,
Arc::make_mut(&mut context),
input_stream,
&input,
&scope.vars,
&scope.env,
Scope::append_it(scope, input),
)
.await?
.to_output_stream())
@ -119,7 +117,7 @@ async fn each(
) -> Result<OutputStream, ShellError> {
let registry = registry.clone();
let head = Arc::new(raw_args.call_info.args.head.clone());
let scope = Arc::new(raw_args.call_info.scope.clone());
let scope = raw_args.call_info.scope.clone();
let context = Arc::new(EvaluationContext::from_raw(&raw_args, &registry));
let (each_args, input): (EachArgs, _) = raw_args.process(&registry).await?;
let block = Arc::new(each_args.block);
@ -166,11 +164,12 @@ async fn each(
#[cfg(test)]
mod tests {
use super::Each;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(Each {})
Ok(test_examples(Each {})?)
}
}

View File

@ -53,7 +53,7 @@ impl WholeStreamCommand for EachGroup {
) -> Result<OutputStream, ShellError> {
let registry = registry.clone();
let head = Arc::new(raw_args.call_info.args.head.clone());
let scope = Arc::new(raw_args.call_info.scope.clone());
let scope = raw_args.call_info.scope.clone();
let context = Arc::new(EvaluationContext::from_raw(&raw_args, &registry));
let (each_args, input): (EachGroupArgs, _) = raw_args.process(&registry).await?;
let block = Arc::new(each_args.block);
@ -123,11 +123,12 @@ pub(crate) fn run_block_on_vec(
#[cfg(test)]
mod tests {
use super::EachGroup;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(EachGroup {})
Ok(test_examples(EachGroup {})?)
}
}

View File

@ -57,7 +57,7 @@ impl WholeStreamCommand for EachWindow {
) -> Result<OutputStream, ShellError> {
let registry = registry.clone();
let head = Arc::new(raw_args.call_info.args.head.clone());
let scope = Arc::new(raw_args.call_info.scope.clone());
let scope = raw_args.call_info.scope.clone();
let context = Arc::new(EvaluationContext::from_raw(&raw_args, &registry));
let (each_args, mut input): (EachWindowArgs, _) = raw_args.process(&registry).await?;
let block = Arc::new(each_args.block);
@ -103,11 +103,12 @@ impl WholeStreamCommand for EachWindow {
#[cfg(test)]
mod tests {
use super::EachWindow;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(EachWindow {})
Ok(test_examples(EachWindow {})?)
}
}

View File

@ -162,11 +162,12 @@ impl Iterator for RangeIterator {
#[cfg(test)]
mod tests {
use super::Echo;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(Echo {})
Ok(test_examples(Echo {})?)
}
}

View File

@ -0,0 +1,288 @@
use crate::command_registry::CommandRegistry;
use crate::commands::classified::block::run_block;
use crate::commands::WholeStreamCommand;
use crate::prelude::*;
use nu_errors::ShellError;
use nu_protocol::{
hir::Block, ColumnPath, Primitive, ReturnSuccess, Scope, Signature, SyntaxShape, UntaggedValue,
Value,
};
use nu_source::Tagged;
use nu_value_ext::{as_string, ValueExt};
use futures::stream::once;
use indexmap::indexmap;
#[derive(Deserialize)]
pub struct Arguments {
rest: Vec<Value>,
}
pub struct Command;
#[async_trait]
impl WholeStreamCommand for Command {
fn name(&self) -> &str {
"empty?"
}
fn signature(&self) -> Signature {
Signature::build("empty?").rest(
SyntaxShape::Any,
"the names of the columns to check emptiness. Pass an optional block to replace if empty",
)
}
fn usage(&self) -> &str {
"Check for empty values"
}
async fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
is_empty(args, registry).await
}
fn examples(&self) -> Vec<Example> {
vec![
Example {
description: "Check if a value is empty",
example: "echo '' | empty?",
result: Some(vec![UntaggedValue::boolean(true).into()]),
},
Example {
description: "more than one column",
example: "echo [[meal size]; [arepa small] [taco '']] | empty? meal size",
result: Some(
vec![
UntaggedValue::row(indexmap! {
"meal".to_string() => Value::from(false),
"size".to_string() => Value::from(false),
})
.into(),
UntaggedValue::row(indexmap! {
"meal".to_string() => Value::from(false),
"size".to_string() => Value::from(true),
})
.into(),
],
),
},Example {
description: "use a block if setting the empty cell contents is wanted",
example: "echo [[2020/04/16 2020/07/10 2020/11/16]; ['' [27] [37]]] | empty? 2020/04/16 { = [33 37] }",
result: Some(
vec![
UntaggedValue::row(indexmap! {
"2020/04/16".to_string() => UntaggedValue::table(&[UntaggedValue::int(33).into(), UntaggedValue::int(37).into()]).into(),
"2020/07/10".to_string() => UntaggedValue::table(&[UntaggedValue::int(27).into()]).into(),
"2020/11/16".to_string() => UntaggedValue::table(&[UntaggedValue::int(37).into()]).into(),
})
.into(),
],
),
},
]
}
}
async fn is_empty(
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
let tag = args.call_info.name_tag.clone();
let name_tag = Arc::new(args.call_info.name_tag.clone());
let context = Arc::new(EvaluationContext::from_raw(&args, &registry));
let scope = args.call_info.scope.clone();
let (Arguments { rest }, input) = args.process(&registry).await?;
let (columns, default_block): (Vec<ColumnPath>, Option<Block>) = arguments(rest)?;
let default_block = Arc::new(default_block);
if input.is_empty() {
let stream = futures::stream::iter(vec![
UntaggedValue::Primitive(Primitive::Nothing).into_value(tag)
]);
return Ok(InputStream::from_stream(stream)
.then(move |input| {
let tag = name_tag.clone();
let scope = scope.clone();
let context = context.clone();
let block = default_block.clone();
let columns = vec![];
async {
match process_row(scope, context, input, block, columns, tag).await {
Ok(s) => s,
Err(e) => OutputStream::one(Err(e)),
}
}
})
.flatten()
.to_output_stream());
}
Ok(input
.then(move |input| {
let tag = name_tag.clone();
let scope = scope.clone();
let context = context.clone();
let block = default_block.clone();
let columns = columns.clone();
async {
match process_row(scope, context, input, block, columns, tag).await {
Ok(s) => s,
Err(e) => OutputStream::one(Err(e)),
}
}
})
.flatten()
.to_output_stream())
}
fn arguments(rest: Vec<Value>) -> Result<(Vec<ColumnPath>, Option<Block>), ShellError> {
let mut rest = rest;
let mut columns = vec![];
let mut default = None;
let last_argument = rest.pop();
match last_argument {
Some(Value {
value: UntaggedValue::Block(call),
..
}) => default = Some(call),
Some(other) => {
let Tagged { item: path, .. } = other.as_column_path()?;
columns = vec![path];
}
None => {}
};
for argument in rest {
let Tagged { item: path, .. } = argument.as_column_path()?;
columns.push(path);
}
Ok((columns, default))
}
async fn process_row(
scope: Arc<Scope>,
mut context: Arc<EvaluationContext>,
input: Value,
default_block: Arc<Option<Block>>,
column_paths: Vec<ColumnPath>,
tag: Arc<Tag>,
) -> Result<OutputStream, ShellError> {
let _tag = &*tag;
let mut out = Arc::new(None);
let results = Arc::make_mut(&mut out);
if let Some(default_block) = &*default_block {
let for_block = input.clone();
let input_stream = once(async { Ok(for_block) }).to_input_stream();
let scope = Scope::append_it(scope, input.clone());
let mut stream = run_block(
&default_block,
Arc::make_mut(&mut context),
input_stream,
scope,
)
.await?;
*results = Some({
let values = stream.drain_vec().await;
let errors = context.get_errors();
if let Some(error) = errors.first() {
return Err(error.clone());
}
if values.len() == 1 {
let value = values
.get(0)
.ok_or_else(|| ShellError::unexpected("No value."))?;
Value {
value: value.value.clone(),
tag: input.tag.clone(),
}
} else if values.is_empty() {
UntaggedValue::nothing().into_value(&input.tag)
} else {
UntaggedValue::table(&values).into_value(&input.tag)
}
});
}
match input {
Value {
value: UntaggedValue::Row(ref r),
ref tag,
} => {
if column_paths.is_empty() {
Ok(OutputStream::one(ReturnSuccess::value({
let is_empty = input.is_empty();
if default_block.is_some() {
if is_empty {
results
.clone()
.unwrap_or_else(|| UntaggedValue::boolean(true).into_value(tag))
} else {
input.clone()
}
} else {
UntaggedValue::boolean(is_empty).into_value(tag)
}
})))
} else {
let mut obj = input.clone();
for column in column_paths.clone() {
let path = UntaggedValue::Primitive(Primitive::ColumnPath(column.clone()))
.into_value(tag);
let data = r.get_data(&as_string(&path)?).borrow().clone();
let is_empty = data.is_empty();
let default = if default_block.is_some() {
if is_empty {
results
.clone()
.unwrap_or_else(|| UntaggedValue::boolean(true).into_value(tag))
} else {
data.clone()
}
} else {
UntaggedValue::boolean(is_empty).into_value(tag)
};
if let Ok(value) =
obj.swap_data_by_column_path(&column, Box::new(move |_| Ok(default)))
{
obj = value;
}
}
Ok(OutputStream::one(ReturnSuccess::value(obj)))
}
}
other => Ok(OutputStream::one(ReturnSuccess::value({
if other.is_empty() {
results
.clone()
.unwrap_or_else(|| UntaggedValue::boolean(true).into_value(other.tag))
} else {
UntaggedValue::boolean(false).into_value(other.tag)
}
}))),
}
}

View File

@ -191,11 +191,12 @@ async fn enter(
#[cfg(test)]
mod tests {
use super::Enter;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(Enter {})
Ok(test_examples(Enter {})?)
}
}

View File

@ -93,11 +93,12 @@ async fn every(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputSt
#[cfg(test)]
mod tests {
use super::Every;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(Every {})
Ok(test_examples(Every {})?)
}
}

View File

@ -63,11 +63,12 @@ pub async fn exit(
#[cfg(test)]
mod tests {
use super::Exit;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(Exit {})
Ok(test_examples(Exit {})?)
}
}

View File

@ -72,11 +72,12 @@ async fn first(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputSt
#[cfg(test)]
mod tests {
use super::First;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(First {})
Ok(test_examples(First {})?)
}
}

View File

@ -3,7 +3,7 @@ use crate::commands::WholeStreamCommand;
use crate::evaluate::evaluate_baseline_expr;
use crate::prelude::*;
use nu_errors::ShellError;
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue};
use nu_protocol::{ReturnSuccess, Scope, Signature, SyntaxShape, UntaggedValue};
use nu_source::Tagged;
use std::borrow::Borrow;
@ -54,7 +54,7 @@ async fn format_command(
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
let registry = Arc::new(registry.clone());
let scope = Arc::new(args.call_info.scope.clone());
let scope = args.call_info.scope.clone();
let (FormatArgs { pattern }, input) = args.process(&registry).await?;
let format_pattern = format(&pattern);
@ -83,9 +83,7 @@ async fn format_command(
let result = evaluate_baseline_expr(
&full_column_path.0,
&registry,
&value,
&scope.vars,
&scope.env,
Scope::append_it(scope.clone(), value.clone()),
)
.await;
@ -153,11 +151,12 @@ fn format(input: &str) -> Vec<FormatCommand> {
#[cfg(test)]
mod tests {
use super::Format;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(Format {})
Ok(test_examples(Format {})?)
}
}

View File

@ -35,11 +35,12 @@ impl WholeStreamCommand for From {
#[cfg(test)]
mod tests {
use super::From;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(From {})
Ok(test_examples(From {})?)
}
}

View File

@ -109,11 +109,12 @@ async fn from_csv(
#[cfg(test)]
mod tests {
use super::FromCSV;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(FromCSV {})
Ok(test_examples(FromCSV {})?)
}
}

View File

@ -130,11 +130,12 @@ async fn from_eml(
#[cfg(test)]
mod tests {
use super::FromEML;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(FromEML {})
Ok(test_examples(FromEML {})?)
}
}

View File

@ -249,11 +249,12 @@ fn params_to_value(params: Vec<(String, Vec<String>)>, tag: Tag) -> Value {
#[cfg(test)]
mod tests {
use super::FromIcs;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(FromIcs {})
Ok(test_examples(FromIcs {})?)
}
}

View File

@ -95,11 +95,12 @@ async fn from_ini(
#[cfg(test)]
mod tests {
use super::FromINI;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(FromINI {})
Ok(test_examples(FromINI {})?)
}
}

View File

@ -144,11 +144,12 @@ async fn from_json(
#[cfg(test)]
mod tests {
use super::FromJSON;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(FromJSON {})
Ok(test_examples(FromJSON {})?)
}
}

View File

@ -102,11 +102,12 @@ async fn from_ods(
#[cfg(test)]
mod tests {
use super::FromODS;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(FromODS {})
Ok(test_examples(FromODS {})?)
}
}

View File

@ -135,7 +135,7 @@ fn parse_aligned_columns<'a>(
.flat_map(|s| find_indices(*s))
.collect::<Vec<usize>>();
indices.sort();
indices.sort_unstable();
indices.dedup();
let headers: Vec<(String, usize)> = indices
@ -302,7 +302,9 @@ async fn from_ssv(
#[cfg(test)]
mod tests {
use super::ShellError;
use super::*;
fn owned(x: &str, y: &str) -> (String, String) {
(String::from(x), String::from(y))
}
@ -504,10 +506,10 @@ mod tests {
}
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use super::FromSSV;
use crate::examples::test as test_examples;
test_examples(FromSSV {})
Ok(test_examples(FromSSV {})?)
}
}

View File

@ -101,11 +101,12 @@ pub async fn from_toml(
#[cfg(test)]
mod tests {
use super::FromTOML;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(FromTOML {})
Ok(test_examples(FromTOML {})?)
}
}

View File

@ -52,11 +52,12 @@ async fn from_tsv(
#[cfg(test)]
mod tests {
use super::FromTSV;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(FromTSV {})
Ok(test_examples(FromTSV {})?)
}
}

View File

@ -64,11 +64,12 @@ async fn from_url(
#[cfg(test)]
mod tests {
use super::FromURL;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(FromURL {})
Ok(test_examples(FromURL {})?)
}
}

View File

@ -104,11 +104,12 @@ fn params_to_value(params: Vec<(String, Vec<String>)>, tag: Tag) -> Value {
#[cfg(test)]
mod tests {
use super::FromVcf;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(FromVcf {})
Ok(test_examples(FromVcf {})?)
}
}

View File

@ -102,11 +102,12 @@ async fn from_xlsx(
#[cfg(test)]
mod tests {
use super::FromXLSX;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(FromXLSX {})
Ok(test_examples(FromXLSX {})?)
}
}

View File

@ -135,6 +135,7 @@ async fn from_xml(
#[cfg(test)]
mod tests {
use super::ShellError;
use crate::commands::from_xml;
use indexmap::IndexMap;
use nu_protocol::{UntaggedValue, Value};
@ -304,10 +305,10 @@ mod tests {
}
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use super::FromXML;
use crate::examples::test as test_examples;
test_examples(FromXML {})
Ok(test_examples(FromXML {})?)
}
}

View File

@ -173,15 +173,16 @@ async fn from_yaml(
#[cfg(test)]
mod tests {
use super::ShellError;
use super::*;
use nu_plugin::row;
use nu_plugin::test_helpers::value::string;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(FromYAML {})
Ok(test_examples(FromYAML {})?)
}
#[test]

View File

@ -129,10 +129,10 @@ pub fn get_column_path(path: &ColumnPath, obj: &Value) -> Result<Value, ShellErr
_ => {}
}
if let Some(suggestions) = did_you_mean(&obj_source, column_path_tried) {
if let Some(suggestions) = did_you_mean(&obj_source, column_path_tried.as_string()) {
ShellError::labeled_error(
"Unknown column",
format!("did you mean '{}'?", suggestions[0].1),
format!("did you mean '{}'?", suggestions[0]),
column_path_tried.span.since(path_members_span),
)
} else {
@ -155,8 +155,8 @@ pub fn get_column_path_from_table_error(
let suggestions: IndexSet<_> = rows
.iter()
.filter_map(|r| did_you_mean(&r, &column_path_tried))
.map(|s| s[0].1.to_owned())
.filter_map(|r| did_you_mean(&r, column_path_tried.as_string()))
.map(|s| s[0].to_owned())
.collect();
let mut existing_columns: IndexSet<_> = IndexSet::default();
let mut names: Vec<String> = vec![];
@ -232,14 +232,14 @@ pub fn get_column_from_row_error(
} => {
let primary_label = format!("There isn't a column named '{}'", &column);
if let Some(suggestions) = did_you_mean(&obj_source, column_path_tried) {
if let Some(suggestions) = did_you_mean(&obj_source, column_path_tried.as_string()) {
Some(ShellError::labeled_error_with_secondary(
"Unknown column",
primary_label,
column_path_tried.span,
format!(
"Perhaps you meant '{}'? Columns available: {}",
suggestions[0].1,
suggestions[0],
&obj_source.data_descriptors().join(", ")
),
column_path_tried.span.since(path_members_span),
@ -267,11 +267,12 @@ pub fn get_column_from_row_error(
#[cfg(test)]
mod tests {
use super::Get;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(Get {})
Ok(test_examples(Get {})?)
}
}

View File

@ -1,20 +1,21 @@
use crate::commands::WholeStreamCommand;
use crate::prelude::*;
use crate::utils::suggestions::suggestions;
use indexmap::indexmap;
use nu_errors::ShellError;
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
use nu_source::Tagged;
use nu_value_ext::as_string;
pub struct GroupBy;
pub struct Command;
#[derive(Deserialize)]
pub struct GroupByArgs {
pub struct Arguments {
grouper: Option<Value>,
}
#[async_trait]
impl WholeStreamCommand for GroupBy {
impl WholeStreamCommand for Command {
fn name(&self) -> &str {
"group-by"
}
@ -39,17 +40,45 @@ impl WholeStreamCommand for GroupBy {
group_by(args, registry).await
}
#[allow(clippy::unwrap_used)]
fn examples(&self) -> Vec<Example> {
use nu_data::value::date_naive_from_str as date;
vec![
Example {
description: "group items by column named \"type\"",
example: r#"ls | group-by type"#,
result: None,
},
Example {
description: "blocks can be used for generating a grouping key (same as above)",
example: r#"ls | group-by { get type }"#,
result: None,
result: Some(vec![UntaggedValue::row(indexmap! {
"File".to_string() => UntaggedValue::Table(vec![
UntaggedValue::row(indexmap! {
"modified".to_string() => date("2019-07-23".tagged_unknown()).unwrap().into(),
"name".to_string() => UntaggedValue::string("Andrés.txt").into(),
"type".to_string() => UntaggedValue::string("File").into(),
"chickens".to_string() => UntaggedValue::int(10).into(),
}).into(),
UntaggedValue::row(indexmap! {
"modified".to_string() => date("2019-09-24".tagged_unknown()).unwrap().into(),
"name".to_string() => UntaggedValue::string("Andrés.txt").into(),
"type".to_string() => UntaggedValue::string("File").into(),
"chickens".to_string() => UntaggedValue::int(20).into(),
}).into(),
]).into(),
"Dir".to_string() => UntaggedValue::Table(vec![
UntaggedValue::row(indexmap! {
"modified".to_string() => date("2019-07-23".tagged_unknown()).unwrap().into(),
"name".to_string() => UntaggedValue::string("Jonathan").into(),
"type".to_string() => UntaggedValue::string("Dir").into(),
"chickens".to_string() => UntaggedValue::int(5).into(),
}).into(),
UntaggedValue::row(indexmap! {
"modified".to_string() => date("2019-09-24".tagged_unknown()).unwrap().into(),
"name".to_string() => UntaggedValue::string("Yehuda").into(),
"type".to_string() => UntaggedValue::string("Dir").into(),
"chickens".to_string() => UntaggedValue::int(4).into(),
}).into(),
]).into(),
})
.into()]),
},
Example {
description: "you can also group by raw values by leaving out the argument",
@ -74,10 +103,26 @@ impl WholeStreamCommand for GroupBy {
.into()]),
},
Example {
description: "write pipelines for a more involved grouping key",
example:
"echo [1 3 1 3 2 1 1] | group-by { echo `({{$it}} - 1) % 3` | calc | str from }",
result: None,
description:
"use the block form to generate a grouping key when each row gets processed",
example: "echo [1 3 1 3 2 1 1] | group-by { = ($it - 1) mod 3 }",
result: Some(vec![UntaggedValue::row(indexmap! {
"0".to_string() => UntaggedValue::Table(vec![
UntaggedValue::int(1).into(),
UntaggedValue::int(1).into(),
UntaggedValue::int(1).into(),
UntaggedValue::int(1).into(),
]).into(),
"2".to_string() => UntaggedValue::Table(vec![
UntaggedValue::int(3).into(),
UntaggedValue::int(3).into(),
]).into(),
"1".to_string() => UntaggedValue::Table(vec![
UntaggedValue::int(2).into(),
]).into(),
})
.into()]),
},
]
}
@ -95,9 +140,9 @@ pub async fn group_by(
let name = args.call_info.name_tag.clone();
let registry = registry.clone();
let head = Arc::new(args.call_info.args.head.clone());
let scope = Arc::new(args.call_info.scope.clone());
let scope = args.call_info.scope.clone();
let context = Arc::new(EvaluationContext::from_raw(&args, &registry));
let (GroupByArgs { grouper }, input) = args.process(&registry).await?;
let (Arguments { grouper }, input) = args.process(&registry).await?;
let values: Vec<Value> = input.collect().await;
let mut keys: Vec<Result<String, ShellError>> = vec![];
@ -167,6 +212,14 @@ pub async fn group_by(
));
}
let first = values[0].clone();
let name = if first.tag.anchor().is_some() {
first.tag
} else {
name
};
let values = UntaggedValue::table(&values).into_value(&name);
let group_value = match group_strategy {
@ -179,39 +232,14 @@ pub async fn group_by(
None => as_string(row),
});
nu_data::utils::group(&values, &Some(block), &name)
nu_data::utils::group(&values, &Some(block), name)
}
Grouper::ByColumn(column_name) => group(&column_name, &values, name),
Grouper::ByColumn(column_name) => group(&column_name, &values, &name),
};
Ok(OutputStream::one(ReturnSuccess::value(group_value?)))
}
pub fn suggestions(tried: Tagged<&str>, for_value: &Value) -> ShellError {
let possibilities = for_value.data_descriptors();
let mut possible_matches: Vec<_> = possibilities
.iter()
.map(|x| (natural::distance::levenshtein_distance(x, &tried), x))
.collect();
possible_matches.sort();
if !possible_matches.is_empty() {
ShellError::labeled_error(
"Unknown column",
format!("did you mean '{}'?", possible_matches[0].1),
tried.tag(),
)
} else {
ShellError::labeled_error(
"Unknown column",
"row does not contain this column",
tried.tag(),
)
}
}
pub fn group(
column_name: &Option<Tagged<String>>,
values: &Value,
@ -311,12 +339,4 @@ mod tests {
Ok(())
}
#[test]
fn examples_work_as_expected() {
use super::GroupBy;
use crate::examples::test as test_examples;
test_examples(GroupBy {})
}
}

View File

@ -1,5 +1,6 @@
use crate::commands::WholeStreamCommand;
use crate::prelude::*;
use crate::utils::suggestions::suggestions;
use nu_errors::ShellError;
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
use nu_source::Tagged;
@ -137,39 +138,15 @@ pub async fn group_by_date(
}
}
pub fn suggestions(tried: Tagged<&str>, for_value: &Value) -> ShellError {
let possibilities = for_value.data_descriptors();
let mut possible_matches: Vec<_> = possibilities
.iter()
.map(|x| (natural::distance::levenshtein_distance(x, &tried), x))
.collect();
possible_matches.sort();
if !possible_matches.is_empty() {
ShellError::labeled_error(
"Unknown column",
format!("did you mean '{}'?", possible_matches[0].1),
tried.tag(),
)
} else {
ShellError::labeled_error(
"Unknown column",
"row does not contain this column",
tried.tag(),
)
}
}
#[cfg(test)]
mod tests {
use super::GroupByDate;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(GroupByDate {})
Ok(test_examples(GroupByDate {})?)
}
}

View File

@ -116,11 +116,12 @@ pub async fn headers(
#[cfg(test)]
mod tests {
use super::Headers;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(Headers {})
Ok(test_examples(Headers {})?)
}
}

View File

@ -6,7 +6,7 @@ use nu_data::command::signature_dict;
use nu_errors::ShellError;
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, TaggedDictBuilder, UntaggedValue, Value};
use nu_source::{SpannedItem, Tagged};
use nu_value_ext::get_data_by_key;
use nu_value_ext::ValueExt;
pub struct Help;
@ -96,7 +96,8 @@ async fn help(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStr
dict.insert_untagged("name", cmd_name);
dict.insert_untagged(
"description",
get_data_by_key(&value, "usage".spanned_unknown())
value
.get_data_by_key("usage".spanned_unknown())
.ok_or_else(|| {
ShellError::labeled_error(
"Expected a usage key",
@ -234,11 +235,12 @@ pub fn get_help(cmd: &dyn WholeStreamCommand, registry: &CommandRegistry) -> Str
#[cfg(test)]
mod tests {
use super::Help;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(Help {})
Ok(test_examples(Help {})?)
}
}

View File

@ -112,8 +112,9 @@ pub async fn histogram(
nu_data::utils::Operation {
grouper: Some(Box::new(move |_, _| Ok(String::from("frequencies")))),
splitter: Some(splitter(column_grouper)),
format: None,
format: &None,
eval: &evaluate_with,
reduction: &nu_data::utils::Reduction::Count,
},
&name,
)?;
@ -123,17 +124,33 @@ pub async fn histogram(
Ok(futures::stream::iter(
results
.percentages
.data
.table_entries()
.map(move |value| {
let values = value.table_entries().cloned().collect::<Vec<_>>();
let occurrences = values.len();
(occurrences, values[occurrences - 1].clone())
})
.cloned()
.collect::<Vec<_>>()
.into_iter()
.map(move |(occurrences, value)| {
.zip(
results
.percentages
.table_entries()
.cloned()
.collect::<Vec<_>>()
.into_iter(),
)
.map(move |(counts, percentages)| {
let percentage = percentages
.table_entries()
.cloned()
.last()
.unwrap_or_else(|| {
UntaggedValue::decimal_from_float(0.0, name.span).into_value(&name)
});
let value = counts
.table_entries()
.cloned()
.last()
.unwrap_or_else(|| UntaggedValue::int(0).into_value(&name));
let mut fact = TaggedDictBuilder::new(&name);
let column_value = labels
.get(idx)
@ -147,19 +164,19 @@ pub async fn histogram(
.clone();
fact.insert_value(&column.item, column_value);
fact.insert_untagged("occurrences", UntaggedValue::int(occurrences));
fact.insert_untagged("count", value);
let percentage = format!(
let fmt_percentage = format!(
"{}%",
// Some(2) < the number of digits
// true < group the digits
crate::commands::str_::from::action(&value, &name, Some(2), true)?
crate::commands::str_::from::action(&percentage, &name, Some(2), true)?
.as_string()?
);
fact.insert_untagged("percentage", UntaggedValue::string(percentage));
fact.insert_untagged("percentage", UntaggedValue::string(fmt_percentage));
let string = std::iter::repeat("*")
.take(value.as_u64().map_err(|_| {
.take(percentage.as_u64().map_err(|_| {
ShellError::labeled_error("expected a number", "expected a number", &name)
})? as usize)
.collect::<String>();
@ -210,11 +227,12 @@ fn splitter(
#[cfg(test)]
mod tests {
use super::Histogram;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(Histogram {})
Ok(test_examples(Histogram {})?)
}
}

View File

@ -79,11 +79,12 @@ fn history(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStrea
#[cfg(test)]
mod tests {
use super::History;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(History {})
Ok(test_examples(History {})?)
}
}

View File

@ -4,7 +4,9 @@ use crate::commands::WholeStreamCommand;
use crate::evaluate::evaluate_baseline_expr;
use crate::prelude::*;
use nu_errors::ShellError;
use nu_protocol::{hir::Block, hir::ClassifiedCommand, Signature, SyntaxShape, UntaggedValue};
use nu_protocol::{
hir::Block, hir::ClassifiedCommand, Scope, Signature, SyntaxShape, UntaggedValue,
};
pub struct If;
@ -72,7 +74,7 @@ async fn if_command(
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
let registry = Arc::new(registry.clone());
let scope = Arc::new(raw_args.call_info.scope.clone());
let scope = raw_args.call_info.scope.clone();
let tag = raw_args.call_info.name_tag.clone();
let context = Arc::new(EvaluationContext::from_raw(&raw_args, &registry));
@ -119,14 +121,12 @@ async fn if_command(
let then_case = then_case.clone();
let else_case = else_case.clone();
let registry = registry.clone();
let scope = scope.clone();
let scope = Scope::append_it(scope.clone(), input);
let mut context = context.clone();
async move {
//FIXME: should we use the scope that's brought in as well?
let condition =
evaluate_baseline_expr(&condition, &*registry, &input, &scope.vars, &scope.env)
.await;
let condition = evaluate_baseline_expr(&condition, &*registry, scope.clone()).await;
match condition {
Ok(condition) => match condition.as_bool() {
@ -136,9 +136,7 @@ async fn if_command(
&then_case,
Arc::make_mut(&mut context),
InputStream::empty(),
&input,
&scope.vars,
&scope.env,
scope,
)
.await
{
@ -151,9 +149,7 @@ async fn if_command(
&else_case,
Arc::make_mut(&mut context),
InputStream::empty(),
&input,
&scope.vars,
&scope.env,
scope,
)
.await
{
@ -178,11 +174,12 @@ async fn if_command(
#[cfg(test)]
mod tests {
use super::If;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(If {})
Ok(test_examples(If {})?)
}
}

View File

@ -9,16 +9,18 @@ use nu_protocol::{
use nu_value_ext::ValueExt;
use futures::stream::once;
pub struct Insert;
use indexmap::indexmap;
pub struct Command;
#[derive(Deserialize)]
pub struct InsertArgs {
pub struct Arguments {
column: ColumnPath,
value: Value,
}
#[async_trait]
impl WholeStreamCommand for Insert {
impl WholeStreamCommand for Command {
fn name(&self) -> &str {
"insert"
}
@ -44,6 +46,28 @@ impl WholeStreamCommand for Insert {
) -> Result<OutputStream, ShellError> {
insert(args, registry).await
}
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Insert a column with a value",
example: "echo [[author, commits]; ['Andrés', 1]] | insert branches 5",
result: Some(vec![UntaggedValue::row(indexmap! {
"author".to_string() => Value::from("Andrés"),
"commits".to_string() => UntaggedValue::int(1).into(),
"branches".to_string() => UntaggedValue::int(5).into(),
})
.into()]),
},Example {
description: "Use in block form for more involved insertion logic",
example: "echo [[author, lucky_number]; ['Yehuda', 4]] | insert success { = $it.lucky_number * 10 }",
result: Some(vec![UntaggedValue::row(indexmap! {
"author".to_string() => Value::from("Yehuda"),
"lucky_number".to_string() => UntaggedValue::int(4).into(),
"success".to_string() => UntaggedValue::int(40).into(),
})
.into()]),
}]
}
}
async fn process_row(
@ -63,15 +87,9 @@ async fn process_row(
let for_block = input.clone();
let input_stream = once(async { Ok(for_block) }).to_input_stream();
let result = run_block(
&block,
Arc::make_mut(&mut context),
input_stream,
&input,
&scope.vars,
&scope.env,
)
.await;
let scope = Scope::append_it(scope, input.clone());
let result = run_block(&block, Arc::make_mut(&mut context), input_stream, scope).await;
match result {
Ok(mut stream) => {
@ -85,13 +103,16 @@ async fn process_row(
let result = if values.len() == 1 {
let value = values
.get(0)
.ok_or_else(|| ShellError::unexpected("No value to insert with"))?;
.ok_or_else(|| ShellError::unexpected("No value to insert with."))?;
value.clone()
Value {
value: value.value.clone(),
tag: input.tag.clone(),
}
} else if values.is_empty() {
UntaggedValue::nothing().into_untagged_value()
UntaggedValue::nothing().into_value(&input.tag)
} else {
UntaggedValue::table(&values).into_untagged_value()
UntaggedValue::table(&values).into_value(&input.tag)
};
match input {
@ -118,7 +139,11 @@ async fn process_row(
Value {
value: UntaggedValue::Primitive(Primitive::Nothing),
..
} => match scope.it.insert_data_at_column_path(&field, value.clone()) {
} => match scope
.it()
.unwrap_or_else(|| UntaggedValue::nothing().into_untagged_value())
.insert_data_at_column_path(&field, value.clone())
{
Ok(v) => OutputStream::one(ReturnSuccess::value(v)),
Err(e) => OutputStream::one(Err(e)),
},
@ -135,9 +160,9 @@ async fn insert(
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
let registry = registry.clone();
let scope = Arc::new(raw_args.call_info.scope.clone());
let scope = raw_args.call_info.scope.clone();
let context = Arc::new(EvaluationContext::from_raw(&raw_args, &registry));
let (InsertArgs { column, value }, input) = raw_args.process(&registry).await?;
let (Arguments { column, value }, input) = raw_args.process(&registry).await?;
let value = Arc::new(value);
let column = Arc::new(column);
@ -158,15 +183,3 @@ async fn insert(
.flatten()
.to_output_stream())
}
#[cfg(test)]
mod tests {
use super::Insert;
#[test]
fn examples_work_as_expected() {
use crate::examples::test as test_examples;
test_examples(Insert {})
}
}

View File

@ -78,11 +78,12 @@ async fn into_int(
#[cfg(test)]
mod tests {
use super::IntoInt;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(IntoInt {})
Ok(test_examples(IntoInt {})?)
}
}

View File

@ -1,217 +0,0 @@
use crate::command_registry::CommandRegistry;
use crate::commands::WholeStreamCommand;
use crate::prelude::*;
use nu_errors::ShellError;
use nu_protocol::{ColumnPath, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
use nu_source::Tagged;
use nu_value_ext::ValueExt;
enum IsEmptyFor {
Value,
RowWithFieldsAndFallback(Vec<Tagged<ColumnPath>>, Value),
RowWithField(Tagged<ColumnPath>),
RowWithFieldAndFallback(Box<Tagged<ColumnPath>>, Value),
}
pub struct IsEmpty;
#[derive(Deserialize)]
pub struct IsEmptyArgs {
rest: Vec<Value>,
}
#[async_trait]
impl WholeStreamCommand for IsEmpty {
fn name(&self) -> &str {
"empty?"
}
fn signature(&self) -> Signature {
Signature::build("empty?").rest(
SyntaxShape::Any,
"the names of the columns to check emptiness followed by the replacement value.",
)
}
fn usage(&self) -> &str {
"Checks emptiness. The last value is the replacement value for any empty column(s) given to check against the table."
}
async fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
is_empty(args, registry).await
}
}
async fn is_empty(
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
let name_tag = args.call_info.name_tag.clone();
let registry = registry.clone();
let (IsEmptyArgs { rest }, input) = args.process(&registry).await?;
if input.is_empty() {
return Ok(OutputStream::one(ReturnSuccess::value(
UntaggedValue::boolean(true).into_value(name_tag),
)));
}
Ok(input
.map(move |value| {
let value_tag = value.tag();
let action = if rest.len() <= 2 {
let field = rest.get(0);
let replacement_if_true = rest.get(1);
match (field, replacement_if_true) {
(Some(field), Some(replacement_if_true)) => {
IsEmptyFor::RowWithFieldAndFallback(
Box::new(field.as_column_path()?),
replacement_if_true.clone(),
)
}
(Some(field), None) => IsEmptyFor::RowWithField(field.as_column_path()?),
(_, _) => IsEmptyFor::Value,
}
} else {
let mut arguments = rest.iter().rev();
let replacement_if_true = match arguments.next() {
Some(arg) => arg.clone(),
None => UntaggedValue::boolean(value.is_empty()).into_value(&value_tag),
};
IsEmptyFor::RowWithFieldsAndFallback(
arguments
.map(|a| a.as_column_path())
.filter_map(Result::ok)
.collect(),
replacement_if_true,
)
};
match action {
IsEmptyFor::Value => Ok(ReturnSuccess::Value(
UntaggedValue::boolean(value.is_empty()).into_value(value_tag),
)),
IsEmptyFor::RowWithFieldsAndFallback(fields, default) => {
let mut out = value;
for field in fields.iter() {
let val = crate::commands::get::get_column_path(&field, &out)?;
let emptiness_value = match out {
obj
@
Value {
value: UntaggedValue::Row(_),
..
} => {
if val.is_empty() {
obj.replace_data_at_column_path(&field, default.clone())
.ok_or_else(|| {
ShellError::labeled_error(
"empty? could not find place to check emptiness",
"column name",
&field.tag,
)
})
} else {
Ok(obj)
}
}
_ => Err(ShellError::labeled_error(
"Unrecognized type in stream",
"original value",
&value_tag,
)),
};
out = emptiness_value?;
}
Ok(ReturnSuccess::Value(out))
}
IsEmptyFor::RowWithField(field) => {
let val = crate::commands::get::get_column_path(&field, &value)?;
match &value {
obj
@
Value {
value: UntaggedValue::Row(_),
..
} => {
if val.is_empty() {
match obj.replace_data_at_column_path(
&field,
UntaggedValue::boolean(true).into_value(&value_tag),
) {
Some(v) => Ok(ReturnSuccess::Value(v)),
None => Err(ShellError::labeled_error(
"empty? could not find place to check emptiness",
"column name",
&field.tag,
)),
}
} else {
Ok(ReturnSuccess::Value(value))
}
}
_ => Err(ShellError::labeled_error(
"Unrecognized type in stream",
"original value",
&value_tag,
)),
}
}
IsEmptyFor::RowWithFieldAndFallback(field, default) => {
let val = crate::commands::get::get_column_path(&field, &value)?;
match &value {
obj
@
Value {
value: UntaggedValue::Row(_),
..
} => {
if val.is_empty() {
match obj.replace_data_at_column_path(&field, default) {
Some(v) => Ok(ReturnSuccess::Value(v)),
None => Err(ShellError::labeled_error(
"empty? could not find place to check emptiness",
"column name",
&field.tag,
)),
}
} else {
Ok(ReturnSuccess::Value(value))
}
}
_ => Err(ShellError::labeled_error(
"Unrecognized type in stream",
"original value",
&value_tag,
)),
}
}
}
})
.to_output_stream())
}
#[cfg(test)]
mod tests {
use super::IsEmpty;
#[test]
fn examples_work_as_expected() {
use crate::examples::test as test_examples;
test_examples(IsEmpty {})
}
}

View File

@ -74,11 +74,12 @@ async fn keep(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStr
#[cfg(test)]
mod tests {
use super::Command;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(Command {})
Ok(test_examples(Command {})?)
}
}

View File

@ -3,7 +3,7 @@ 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, Scope, Signature, SyntaxShape, UntaggedValue, Value};
pub struct SubCommand;
@ -33,7 +33,7 @@ impl WholeStreamCommand for SubCommand {
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
let registry = Arc::new(registry.clone());
let scope = Arc::new(args.call_info.scope.clone());
let scope = args.call_info.scope.clone();
let call_info = args.evaluate_once(&registry).await?;
@ -85,19 +85,11 @@ impl WholeStreamCommand for SubCommand {
.take_while(move |item| {
let condition = condition.clone();
let registry = registry.clone();
let scope = scope.clone();
let item = item.clone();
let scope = Scope::append_it(scope.clone(), item.clone());
trace!("ITEM = {:?}", item);
async move {
let result = evaluate_baseline_expr(
&*condition,
&registry,
&item,
&scope.vars,
&scope.env,
)
.await;
let result = evaluate_baseline_expr(&*condition, &registry, scope).await;
trace!("RESULT = {:?}", result);
!matches!(result, Ok(ref v) if v.is_true())
@ -109,12 +101,13 @@ impl WholeStreamCommand for SubCommand {
#[cfg(test)]
mod tests {
use super::ShellError;
use super::SubCommand;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(SubCommand {})
Ok(test_examples(SubCommand {})?)
}
}

View File

@ -3,7 +3,7 @@ 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, Scope, Signature, SyntaxShape, UntaggedValue, Value};
pub struct SubCommand;
@ -33,7 +33,7 @@ impl WholeStreamCommand for SubCommand {
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
let registry = Arc::new(registry.clone());
let scope = Arc::new(args.call_info.scope.clone());
let scope = args.call_info.scope.clone();
let call_info = args.evaluate_once(&registry).await?;
let block = call_info.args.expect_nth(0)?.clone();
@ -84,20 +84,11 @@ impl WholeStreamCommand for SubCommand {
.take_while(move |item| {
let condition = condition.clone();
let registry = registry.clone();
let scope = scope.clone();
let item = item.clone();
let scope = Scope::append_it(scope.clone(), item.clone());
trace!("ITEM = {:?}", item);
async move {
let result = evaluate_baseline_expr(
&*condition,
&registry,
&item,
&scope.vars,
&scope.env,
)
.await;
let result = evaluate_baseline_expr(&*condition, &registry, scope).await;
trace!("RESULT = {:?}", result);
matches!(result, Ok(ref v) if v.is_true())
@ -109,12 +100,13 @@ impl WholeStreamCommand for SubCommand {
#[cfg(test)]
mod tests {
use super::ShellError;
use super::SubCommand;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(SubCommand {})
Ok(test_examples(SubCommand {})?)
}
}

View File

@ -121,11 +121,12 @@ async fn kill(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStr
#[cfg(test)]
mod tests {
use super::Kill;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(Kill {})
Ok(test_examples(Kill {})?)
}
}

View File

@ -83,11 +83,12 @@ async fn last(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStr
#[cfg(test)]
mod tests {
use super::Last;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(Last {})
Ok(test_examples(Last {})?)
}
}

View File

@ -75,9 +75,9 @@ async fn lines(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputSt
} => {
let mut leftover_string = leftover_string.lock();
let st = (&*leftover_string).clone() + &st;
let mut lines: Vec<String> = st.lines().map(|x| x.to_string()).collect();
let lo_lines = (&*leftover_string).lines().map(|x| x.to_string());
let st_lines = st.lines().map(|x| x.to_string());
let mut lines: Vec<String> = lo_lines.chain(st_lines).collect();
leftover_string.clear();
@ -125,11 +125,12 @@ async fn lines(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputSt
#[cfg(test)]
mod tests {
use super::Lines;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(Lines {})
Ok(test_examples(Lines {})?)
}
}

View File

@ -89,11 +89,12 @@ impl WholeStreamCommand for Ls {
#[cfg(test)]
mod tests {
use super::Ls;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(Ls {})
Ok(test_examples(Ls {})?)
}
}

View File

@ -188,12 +188,13 @@ pub fn average(values: &[Value], name: &Tag) -> Result<Value, ShellError> {
#[cfg(test)]
mod tests {
use super::ShellError;
use super::SubCommand;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(SubCommand {})
Ok(test_examples(SubCommand {})?)
}
}

View File

@ -44,10 +44,10 @@ mod tests {
use std::str::FromStr;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(Command {})
Ok(test_examples(Command {})?)
}
#[test]

View File

@ -100,12 +100,13 @@ pub fn parse<T: Into<Tag>>(math_expression: &str, tag: T) -> Result<Value, Strin
#[cfg(test)]
mod tests {
use super::ShellError;
use super::SubCommand;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(SubCommand {})
Ok(test_examples(SubCommand {})?)
}
}

View File

@ -58,12 +58,13 @@ pub fn maximum(values: &[Value], _name: &Tag) -> Result<Value, ShellError> {
#[cfg(test)]
mod tests {
use super::ShellError;
use super::SubCommand;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(SubCommand {})
Ok(test_examples(SubCommand {})?)
}
}

View File

@ -186,12 +186,13 @@ fn compute_average(values: &[Value], name: impl Into<Tag>) -> Result<Value, Shel
#[cfg(test)]
mod tests {
use super::ShellError;
use super::SubCommand;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(SubCommand {})
Ok(test_examples(SubCommand {})?)
}
}

View File

@ -58,12 +58,13 @@ pub fn minimum(values: &[Value], _name: &Tag) -> Result<Value, ShellError> {
#[cfg(test)]
mod tests {
use super::ShellError;
use super::SubCommand;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(SubCommand {})
Ok(test_examples(SubCommand {})?)
}
}

View File

@ -83,12 +83,13 @@ pub fn mode(values: &[Value], name: &Tag) -> Result<Value, ShellError> {
#[cfg(test)]
mod tests {
use super::ShellError;
use super::SubCommand;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(SubCommand {})
Ok(test_examples(SubCommand {})?)
}
}

View File

@ -115,12 +115,13 @@ pub fn product(values: &[Value], name: &Tag) -> Result<Value, ShellError> {
#[cfg(test)]
mod tests {
use super::ShellError;
use super::SubCommand;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(SubCommand {})
Ok(test_examples(SubCommand {})?)
}
}

View File

@ -141,12 +141,13 @@ pub fn compute_stddev(values: &[Value], n: usize, name: &Tag) -> Result<Value, S
#[cfg(test)]
mod tests {
use super::ShellError;
use super::SubCommand;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(SubCommand {})
Ok(test_examples(SubCommand {})?)
}
}

View File

@ -125,12 +125,13 @@ pub fn summation(values: &[Value], name: &Tag) -> Result<Value, ShellError> {
#[cfg(test)]
mod tests {
use super::ShellError;
use super::SubCommand;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(SubCommand {})
Ok(test_examples(SubCommand {})?)
}
}

View File

@ -240,12 +240,13 @@ pub fn compute_variance(values: &[Value], n: usize, name: &Tag) -> Result<Value,
#[cfg(test)]
mod tests {
use super::ShellError;
use super::SubCommand;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(SubCommand {})
Ok(test_examples(SubCommand {})?)
}
}

View File

@ -60,21 +60,13 @@ async fn merge(
let (merge_args, input): (MergeArgs, _) = raw_args.process(&registry).await?;
let block = merge_args.block;
let table: Option<Vec<Value>> = match run_block(
&block,
&mut context,
InputStream::empty(),
&scope.it,
&scope.vars,
&scope.env,
)
.await
{
Ok(mut stream) => Some(stream.drain_vec().await),
Err(err) => {
return Err(err);
}
};
let table: Option<Vec<Value>> =
match run_block(&block, &mut context, InputStream::empty(), scope).await {
Ok(mut stream) => Some(stream.drain_vec().await),
Err(err) => {
return Err(err);
}
};
let table = table.unwrap_or_else(|| {
vec![Value {
@ -109,11 +101,12 @@ async fn merge(
#[cfg(test)]
mod tests {
use super::Merge;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(Merge {})
Ok(test_examples(Merge {})?)
}
}

View File

@ -60,11 +60,12 @@ async fn mkdir(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputSt
#[cfg(test)]
mod tests {
use super::Mkdir;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(Mkdir {})
Ok(test_examples(Mkdir {})?)
}
}

View File

@ -218,17 +218,13 @@ fn move_after(
));
};
let columns_moved = table
.data_descriptors()
.into_iter()
.map(|name| {
if columns.contains(&name) {
None
} else {
Some(name)
}
})
.collect::<Vec<_>>();
let columns_moved = table.data_descriptors().into_iter().map(|name| {
if columns.contains(&name) {
None
} else {
Some(name)
}
});
let mut reordered_columns = vec![];
let mut insert = false;
@ -281,17 +277,13 @@ fn move_before(
));
};
let columns_moved = table
.data_descriptors()
.into_iter()
.map(|name| {
if columns.contains(&name) {
None
} else {
Some(name)
}
})
.collect::<Vec<_>>();
let columns_moved = table.data_descriptors().into_iter().map(|name| {
if columns.contains(&name) {
None
} else {
Some(name)
}
});
let mut reordered_columns = vec![];
let mut inserted = false;
@ -324,12 +316,13 @@ fn move_before(
#[cfg(test)]
mod tests {
use super::ShellError;
use super::SubCommand;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(SubCommand {})
Ok(test_examples(SubCommand {})?)
}
}

View File

@ -36,11 +36,12 @@ impl WholeStreamCommand for Command {
#[cfg(test)]
mod tests {
use super::Command;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(Command {})
Ok(test_examples(Command {})?)
}
}

View File

@ -79,11 +79,12 @@ async fn mv(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStrea
#[cfg(test)]
mod tests {
use super::Mv;
use super::ShellError;
#[test]
fn examples_work_as_expected() {
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(Mv {})
Ok(test_examples(Mv {})?)
}
}

Some files were not shown because too many files have changed in this diff Show More