Compare commits

...

12 Commits

Author SHA1 Message Date
a30837298d Bump version (#2791) 2020-12-16 06:30:50 +13:00
f377a3a7b4 Added math abs command. (#2789) 2020-12-16 05:37:12 +13:00
83c874666a Date utility commands (#2780)
* updated & added date related commands based on the new design

* added proper error handling when date format string is invalid

* fixed format issue

* fixed an issue caused due to the change in primitive Date type

* added `date list-timezone` command to list all supported time zones and updated `date to-timezone` accordingly
2020-12-12 12:18:03 -06:00
e000ed47cd Fix Gitpod dev setup by forcing a dev image rebuild (#2783) 2020-12-09 06:44:23 +13:00
af2f064f42 Add random chars cmd (#2782) 2020-12-09 06:43:46 +13:00
9c7b25134b Parsing: Explain parsing errors and show sample lines. (#2774)
This makes the errors slightly better. It took me a while to realize I was missing the `--raw` flag.

```
open "data.csv" | from csv --separator ';'
```

    error: Could not parse as CSV split by ',' (Line 1: expected 1 fields, found 14)
      ┌─ shell:1:1
      │
    1 │ open "data.csv" | from csv --separator ';'
      │ ^^^^ ------------------------------------------------- value originates from here
      │ │
      │ input cannot be parsed as CSV split by ','. Sample input:
    Name;Data
    Ugly;row
    AnotherUgly;row

I think this still needs some refinement. Maybe we don't want to show
the separator all the time, omitting the defaults or the separator
on other formats.
2020-12-07 07:19:04 +13:00
2d15df9e6c Revert "Bump Rustyline to 7.0.0 (#2776)" (#2778)
This reverts commit e73278990c.
2020-12-05 17:12:42 +13:00
d2ab287756 Tell Nu to look for hash's rest columns paths first. (#2777) 2020-12-04 13:49:58 -05:00
e73278990c Bump Rustyline to 7.0.0 (#2776)
* Bump Rustyline to 7.0.0

* Append history instead of always save

* Add associated type to Hinter

* Convert to using Rustyline KeyEvent

* Use AcceptOrInsertLine as struct

* Cargo fmt

* Make convert_keyevent pub

* Better naming for RL conversion
2020-12-05 06:29:40 +13:00
12bc92df35 Make run_block public (#2772) 2020-12-02 23:00:30 +13:00
f19a801022 enhanced version command with more info (#2773) 2020-12-01 13:57:49 -06:00
b193303aa3 Add hash command with base64 subcommand (#2769)
* WIP try testing hash command

Ensure test worked

fmt

WIP get it working for other types of base64

Use optional named arg

WIP

* rebased and refactored a little with encoding and decoding

Fix some typos

Add some more charactersets

refactor several args into the encoding config struct and fix character_set arg. It needs to match the field

Add main hash command so it can be found via help

Added tests for running the whole pipeline

* add test case to cover invalid character sets

* clippy and fmt
2020-12-01 06:47:35 +13:00
72 changed files with 1808 additions and 554 deletions

6
.gitpod.Dockerfile vendored
View File

@ -1,5 +1,9 @@
FROM gitpod/workspace-full
# Gitpod will not rebuild Nushell's dev image unless *some* change is made to this Dockerfile.
# To force a rebuild, simply increase this counter:
ENV TRIGGER_REBUILD 1
USER gitpod
RUN sudo apt-get update && \
@ -11,4 +15,4 @@ RUN sudo apt-get update && \
rust-lldb \
&& sudo rm -rf /var/lib/apt/lists/*
ENV RUST_LLDB=/usr/bin/lldb-8
ENV RUST_LLDB=/usr/bin/lldb-11

173
Cargo.lock generated
View File

@ -206,7 +206,7 @@ dependencies = [
"async-io",
"async-mutex",
"blocking 1.0.2",
"crossbeam-utils 0.8.0",
"crossbeam-utils 0.8.1",
"futures-channel",
"futures-core",
"futures-io",
@ -885,7 +885,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775"
dependencies = [
"cfg-if 1.0.0",
"crossbeam-utils 0.8.0",
"crossbeam-utils 0.8.1",
]
[[package]]
@ -906,8 +906,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9"
dependencies = [
"cfg-if 1.0.0",
"crossbeam-epoch 0.9.0",
"crossbeam-utils 0.8.0",
"crossbeam-epoch 0.9.1",
"crossbeam-utils 0.8.1",
]
[[package]]
@ -921,21 +921,21 @@ dependencies = [
"crossbeam-utils 0.7.2",
"lazy_static 1.4.0",
"maybe-uninit",
"memoffset",
"memoffset 0.5.6",
"scopeguard",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.0"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0f606a85340376eef0d6d8fec399e6d4a544d648386c6645eb6d0653b27d9f"
checksum = "a1aaa739f95311c2c7887a76863f500026092fb1dce0161dab577e559ef3569d"
dependencies = [
"cfg-if 1.0.0",
"const_fn",
"crossbeam-utils 0.8.0",
"crossbeam-utils 0.8.1",
"lazy_static 1.4.0",
"memoffset",
"memoffset 0.6.1",
"scopeguard",
]
@ -973,13 +973,12 @@ dependencies = [
[[package]]
name = "crossbeam-utils"
version = "0.8.0"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec91540d98355f690a86367e566ecad2e9e579f230230eb7c21398372be73ea5"
checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d"
dependencies = [
"autocfg",
"cfg-if 1.0.0",
"const_fn",
"lazy_static 1.4.0",
]
@ -1063,9 +1062,9 @@ dependencies = [
[[package]]
name = "csv"
version = "1.1.4"
version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc4666154fd004af3fd6f1da2e81a96fd5a81927fe8ddb6ecc79e2aa6e138b54"
checksum = "f9d58633299b24b515ac72a3f869f8b91306a3cec616a602843a383acd6f9e97"
dependencies = [
"bstr",
"csv-core",
@ -2575,9 +2574,9 @@ dependencies = [
[[package]]
name = "libnghttp2-sys"
version = "0.1.4+1.41.0"
version = "0.1.5+1.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03624ec6df166e79e139a2310ca213283d6b3c30810c54844f307086d4488df1"
checksum = "9657455ff47889b70ffd37c3e118e8cdd23fd1f9f3293a285f141070621c4c79"
dependencies = [
"cc",
"libc",
@ -2596,9 +2595,9 @@ dependencies = [
[[package]]
name = "libssh2-sys"
version = "0.2.19"
version = "0.2.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca46220853ba1c512fc82826d0834d87b06bcd3c2a42241b7de72f3d2fe17056"
checksum = "df40b13fe7ea1be9b9dffa365a51273816c345fc1811478b57ed7d964fbfc4ce"
dependencies = [
"cc",
"libc",
@ -2831,6 +2830,15 @@ dependencies = [
"autocfg",
]
[[package]]
name = "memoffset"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87"
dependencies = [
"autocfg",
]
[[package]]
name = "meval"
version = "0.2.0"
@ -2889,7 +2897,7 @@ dependencies = [
"kernel32-sys",
"libc",
"log 0.4.11",
"miow 0.2.1",
"miow 0.2.2",
"net2",
"slab 0.4.2",
"winapi 0.2.8",
@ -2921,9 +2929,9 @@ dependencies = [
[[package]]
name = "miow"
version = "0.2.1"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d"
dependencies = [
"kernel32-sys",
"net2",
@ -2985,9 +2993,9 @@ dependencies = [
[[package]]
name = "net2"
version = "0.2.35"
version = "0.2.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ebc3ec692ed7c9a255596c67808dee269f64655d8baf7b4f0638e51ba1d6853"
checksum = "d7cf75f38f16cb05ea017784dc6dbfd354f76c223dba37701734c4f5a9337d02"
dependencies = [
"cfg-if 0.1.10",
"libc",
@ -3084,7 +3092,7 @@ dependencies = [
[[package]]
name = "nu"
version = "0.23.0"
version = "0.24.0"
dependencies = [
"clap",
"ctrlc",
@ -3124,18 +3132,19 @@ dependencies = [
[[package]]
name = "nu-cli"
version = "0.23.0"
version = "0.24.0"
dependencies = [
"Inflector",
"ansi_term 0.12.1",
"async-recursion",
"async-trait",
"base64 0.12.3",
"base64 0.13.0",
"bigdecimal",
"byte-unit",
"bytes 0.5.6",
"calamine",
"chrono",
"chrono-tz",
"clap",
"clipboard",
"codespan-reporting",
@ -3200,6 +3209,7 @@ dependencies = [
"serde_urlencoded 0.7.0",
"serde_yaml",
"sha2 0.9.2",
"shadow-rs",
"shellexpand",
"strip-ansi-escapes",
"sxd-document",
@ -3208,6 +3218,7 @@ dependencies = [
"term",
"term_size",
"termcolor",
"titlecase",
"toml",
"trash",
"umask",
@ -3222,7 +3233,7 @@ dependencies = [
[[package]]
name = "nu-data"
version = "0.23.0"
version = "0.24.0"
dependencies = [
"ansi_term 0.12.1",
"bigdecimal",
@ -3252,7 +3263,7 @@ dependencies = [
[[package]]
name = "nu-errors"
version = "0.23.0"
version = "0.24.0"
dependencies = [
"ansi_term 0.12.1",
"bigdecimal",
@ -3271,7 +3282,7 @@ dependencies = [
[[package]]
name = "nu-json"
version = "0.23.0"
version = "0.24.0"
dependencies = [
"lazy_static 1.4.0",
"num-traits 0.1.43",
@ -3281,7 +3292,7 @@ dependencies = [
[[package]]
name = "nu-parser"
version = "0.23.0"
version = "0.24.0"
dependencies = [
"bigdecimal",
"codespan-reporting",
@ -3299,7 +3310,7 @@ dependencies = [
[[package]]
name = "nu-plugin"
version = "0.23.0"
version = "0.24.0"
dependencies = [
"bigdecimal",
"indexmap",
@ -3315,7 +3326,7 @@ dependencies = [
[[package]]
name = "nu-protocol"
version = "0.23.0"
version = "0.24.0"
dependencies = [
"bigdecimal",
"byte-unit",
@ -3338,7 +3349,7 @@ dependencies = [
[[package]]
name = "nu-source"
version = "0.23.0"
version = "0.24.0"
dependencies = [
"derive-new",
"getset",
@ -3349,7 +3360,7 @@ dependencies = [
[[package]]
name = "nu-table"
version = "0.23.0"
version = "0.24.0"
dependencies = [
"ansi_term 0.12.1",
"unicode-width",
@ -3357,7 +3368,7 @@ dependencies = [
[[package]]
name = "nu-test-support"
version = "0.23.0"
version = "0.24.0"
dependencies = [
"bigdecimal",
"chrono",
@ -3375,7 +3386,7 @@ dependencies = [
[[package]]
name = "nu-value-ext"
version = "0.23.0"
version = "0.24.0"
dependencies = [
"indexmap",
"itertools",
@ -3387,7 +3398,7 @@ dependencies = [
[[package]]
name = "nu_plugin_binaryview"
version = "0.23.0"
version = "0.24.0"
dependencies = [
"ansi_term 0.12.1",
"crossterm 0.18.2",
@ -3403,7 +3414,7 @@ dependencies = [
[[package]]
name = "nu_plugin_chart"
version = "0.23.0"
version = "0.24.0"
dependencies = [
"crossterm 0.18.2",
"nu-cli",
@ -3418,7 +3429,7 @@ dependencies = [
[[package]]
name = "nu_plugin_fetch"
version = "0.23.0"
version = "0.24.0"
dependencies = [
"base64 0.12.3",
"futures 0.3.8",
@ -3432,7 +3443,7 @@ dependencies = [
[[package]]
name = "nu_plugin_from_bson"
version = "0.23.0"
version = "0.24.0"
dependencies = [
"bigdecimal",
"bson",
@ -3446,7 +3457,7 @@ dependencies = [
[[package]]
name = "nu_plugin_from_sqlite"
version = "0.23.0"
version = "0.24.0"
dependencies = [
"bigdecimal",
"nu-errors",
@ -3461,7 +3472,7 @@ dependencies = [
[[package]]
name = "nu_plugin_inc"
version = "0.23.0"
version = "0.24.0"
dependencies = [
"nu-errors",
"nu-plugin",
@ -3474,7 +3485,7 @@ dependencies = [
[[package]]
name = "nu_plugin_match"
version = "0.23.0"
version = "0.24.0"
dependencies = [
"nu-errors",
"nu-plugin",
@ -3485,7 +3496,7 @@ dependencies = [
[[package]]
name = "nu_plugin_post"
version = "0.23.0"
version = "0.24.0"
dependencies = [
"base64 0.12.3",
"futures 0.3.8",
@ -3501,7 +3512,7 @@ dependencies = [
[[package]]
name = "nu_plugin_ps"
version = "0.23.0"
version = "0.24.0"
dependencies = [
"futures 0.3.8",
"futures-timer",
@ -3515,7 +3526,7 @@ dependencies = [
[[package]]
name = "nu_plugin_s3"
version = "0.23.0"
version = "0.24.0"
dependencies = [
"futures 0.3.8",
"nu-errors",
@ -3527,7 +3538,7 @@ dependencies = [
[[package]]
name = "nu_plugin_selector"
version = "0.23.0"
version = "0.24.0"
dependencies = [
"nipper",
"nu-errors",
@ -3539,7 +3550,7 @@ dependencies = [
[[package]]
name = "nu_plugin_start"
version = "0.23.0"
version = "0.24.0"
dependencies = [
"glob",
"nu-errors",
@ -3552,7 +3563,7 @@ dependencies = [
[[package]]
name = "nu_plugin_sys"
version = "0.23.0"
version = "0.24.0"
dependencies = [
"battery",
"futures 0.3.8",
@ -3567,7 +3578,7 @@ dependencies = [
[[package]]
name = "nu_plugin_textview"
version = "0.23.0"
version = "0.24.0"
dependencies = [
"ansi_term 0.12.1",
"bat",
@ -3582,7 +3593,7 @@ dependencies = [
[[package]]
name = "nu_plugin_to_bson"
version = "0.23.0"
version = "0.24.0"
dependencies = [
"bson",
"nu-errors",
@ -3595,7 +3606,7 @@ dependencies = [
[[package]]
name = "nu_plugin_to_sqlite"
version = "0.23.0"
version = "0.24.0"
dependencies = [
"hex 0.4.2",
"nu-errors",
@ -3610,7 +3621,7 @@ dependencies = [
[[package]]
name = "nu_plugin_tree"
version = "0.23.0"
version = "0.24.0"
dependencies = [
"derive-new",
"nu-errors",
@ -3622,7 +3633,7 @@ dependencies = [
[[package]]
name = "nu_plugin_xpath"
version = "0.23.0"
version = "0.24.0"
dependencies = [
"bigdecimal",
"indexmap",
@ -3797,9 +3808,9 @@ checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0"
[[package]]
name = "onig"
version = "6.1.0"
version = "6.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a155d13862da85473665694f4c05d77fb96598bdceeaf696433c84ea9567e20"
checksum = "30b46fd9edbc018f0be4e366c24c46db44fac49cd01c039ae85308088b089dd5"
dependencies = [
"bitflags",
"lazy_static 1.4.0",
@ -3809,9 +3820,9 @@ dependencies = [
[[package]]
name = "onig_sys"
version = "69.5.1"
version = "69.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9bff06597a6b17855040955cae613af000fc0bfc8ad49ea68b9479a74e59292d"
checksum = "ed063c96cf4c0f2e5d09324409d158b38a0a85a7b90fbd68c8cad75c495d5775"
dependencies = [
"cc",
"pkg-config",
@ -4549,7 +4560,7 @@ checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a"
dependencies = [
"crossbeam-channel 0.5.0",
"crossbeam-deque 0.8.0",
"crossbeam-utils 0.8.0",
"crossbeam-utils 0.8.1",
"lazy_static 1.4.0",
"num_cpus",
]
@ -4721,14 +4732,14 @@ dependencies = [
[[package]]
name = "rust-argon2"
version = "0.8.2"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9dab61250775933275e84053ac235621dfb739556d5c54a2f2e9313b7cf43a19"
checksum = "4b18820d944b33caa75a71378964ac46f58517c92b6ae5f762636247c09e78fb"
dependencies = [
"base64 0.12.3",
"base64 0.13.0",
"blake2b_simd",
"constant_time_eq",
"crossbeam-utils 0.7.2",
"crossbeam-utils 0.8.1",
]
[[package]]
@ -5172,6 +5183,16 @@ dependencies = [
"opaque-debug 0.3.0",
]
[[package]]
name = "shadow-rs"
version = "0.3.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa99d59fca26677e3582f69069226abb6b2ce7e02d1068bcfd57510fa16ab87"
dependencies = [
"chrono",
"git2",
]
[[package]]
name = "shell-words"
version = "1.0.0"
@ -5393,9 +5414,9 @@ dependencies = [
[[package]]
name = "syn"
version = "1.0.48"
version = "1.0.52"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc371affeffc477f42a221a1e4297aedcea33d47d19b61455588bd9d8f6b19ac"
checksum = "6c1e438504729046a5cfae47f97c30d6d083c7d91d94603efdae3477fc070d4c"
dependencies = [
"proc-macro2",
"quote",
@ -5605,6 +5626,16 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]]
name = "titlecase"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f565e410cfc24c2f2a89960b023ca192689d7f77d3f8d4f4af50c2d8affe1117"
dependencies = [
"lazy_static 1.4.0",
"regex 1.4.2",
]
[[package]]
name = "tokio"
version = "0.1.22"
@ -5892,13 +5923,13 @@ checksum = "e987b6bf443f4b5b3b6f38704195592cca41c5bb7aedd3c3693c7081f8289860"
[[package]]
name = "tracing"
version = "0.1.21"
version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0987850db3733619253fe60e17cb59b82d37c7e6c0236bb81e4d6b87c879f27"
checksum = "9f47026cdc4080c07e49b37087de021820269d996f581aac150ef9e5583eefe3"
dependencies = [
"cfg-if 0.1.10",
"cfg-if 1.0.0",
"log 0.4.11",
"pin-project-lite 0.1.11",
"pin-project-lite 0.2.0",
"tracing-core",
]
@ -6014,9 +6045,9 @@ dependencies = [
[[package]]
name = "unicode-segmentation"
version = "1.7.0"
version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db8716a166f290ff49dabc18b44aa407cb7c6dbe1aa0971b44b8a24b0ca35aae"
checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796"
[[package]]
name = "unicode-width"

View File

@ -10,7 +10,7 @@ license = "MIT"
name = "nu"
readme = "README.md"
repository = "https://github.com/nushell/nushell"
version = "0.23.0"
version = "0.24.0"
[workspace]
members = ["crates/*/"]
@ -18,33 +18,33 @@ members = ["crates/*/"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
nu-cli = {version = "0.23.0", path = "./crates/nu-cli"}
nu-data = {version = "0.23.0", path = "./crates/nu-data"}
nu-errors = {version = "0.23.0", path = "./crates/nu-errors"}
nu-parser = {version = "0.23.0", path = "./crates/nu-parser"}
nu-plugin = {version = "0.23.0", path = "./crates/nu-plugin"}
nu-protocol = {version = "0.23.0", path = "./crates/nu-protocol"}
nu-source = {version = "0.23.0", path = "./crates/nu-source"}
nu-value-ext = {version = "0.23.0", path = "./crates/nu-value-ext"}
nu-cli = {version = "0.24.0", path = "./crates/nu-cli"}
nu-data = {version = "0.24.0", path = "./crates/nu-data"}
nu-errors = {version = "0.24.0", path = "./crates/nu-errors"}
nu-parser = {version = "0.24.0", path = "./crates/nu-parser"}
nu-plugin = {version = "0.24.0", path = "./crates/nu-plugin"}
nu-protocol = {version = "0.24.0", path = "./crates/nu-protocol"}
nu-source = {version = "0.24.0", path = "./crates/nu-source"}
nu-value-ext = {version = "0.24.0", path = "./crates/nu-value-ext"}
nu_plugin_binaryview = {version = "0.23.0", path = "./crates/nu_plugin_binaryview", optional = true}
nu_plugin_chart = {version = "0.23.0", path = "./crates/nu_plugin_chart", optional = true}
nu_plugin_fetch = {version = "0.23.0", path = "./crates/nu_plugin_fetch", optional = true}
nu_plugin_from_bson = {version = "0.23.0", path = "./crates/nu_plugin_from_bson", optional = true}
nu_plugin_from_sqlite = {version = "0.23.0", path = "./crates/nu_plugin_from_sqlite", optional = true}
nu_plugin_inc = {version = "0.23.0", path = "./crates/nu_plugin_inc", optional = true}
nu_plugin_match = {version = "0.23.0", path = "./crates/nu_plugin_match", optional = true}
nu_plugin_post = {version = "0.23.0", path = "./crates/nu_plugin_post", optional = true}
nu_plugin_ps = {version = "0.23.0", path = "./crates/nu_plugin_ps", optional = true}
nu_plugin_s3 = {version = "0.23.0", path = "./crates/nu_plugin_s3", optional = true}
nu_plugin_start = {version = "0.23.0", path = "./crates/nu_plugin_start", optional = true}
nu_plugin_sys = {version = "0.23.0", path = "./crates/nu_plugin_sys", optional = true}
nu_plugin_textview = {version = "0.23.0", path = "./crates/nu_plugin_textview", optional = true}
nu_plugin_to_bson = {version = "0.23.0", path = "./crates/nu_plugin_to_bson", optional = true}
nu_plugin_to_sqlite = {version = "0.23.0", path = "./crates/nu_plugin_to_sqlite", optional = true}
nu_plugin_tree = {version = "0.23.0", path = "./crates/nu_plugin_tree", optional = true}
nu_plugin_xpath = {version = "0.23.0", path = "./crates/nu_plugin_xpath", optional = true}
nu_plugin_selector = {version = "0.23.0", path = "./crates/nu_plugin_selector", optional = true}
nu_plugin_binaryview = {version = "0.24.0", path = "./crates/nu_plugin_binaryview", optional = true}
nu_plugin_chart = {version = "0.24.0", path = "./crates/nu_plugin_chart", optional = true}
nu_plugin_fetch = {version = "0.24.0", path = "./crates/nu_plugin_fetch", optional = true}
nu_plugin_from_bson = {version = "0.24.0", path = "./crates/nu_plugin_from_bson", optional = true}
nu_plugin_from_sqlite = {version = "0.24.0", path = "./crates/nu_plugin_from_sqlite", optional = true}
nu_plugin_inc = {version = "0.24.0", path = "./crates/nu_plugin_inc", optional = true}
nu_plugin_match = {version = "0.24.0", path = "./crates/nu_plugin_match", optional = true}
nu_plugin_post = {version = "0.24.0", path = "./crates/nu_plugin_post", optional = true}
nu_plugin_ps = {version = "0.24.0", path = "./crates/nu_plugin_ps", optional = true}
nu_plugin_s3 = {version = "0.24.0", path = "./crates/nu_plugin_s3", optional = true}
nu_plugin_start = {version = "0.24.0", path = "./crates/nu_plugin_start", optional = true}
nu_plugin_sys = {version = "0.24.0", path = "./crates/nu_plugin_sys", optional = true}
nu_plugin_textview = {version = "0.24.0", path = "./crates/nu_plugin_textview", optional = true}
nu_plugin_to_bson = {version = "0.24.0", path = "./crates/nu_plugin_to_bson", optional = true}
nu_plugin_to_sqlite = {version = "0.24.0", path = "./crates/nu_plugin_to_sqlite", optional = true}
nu_plugin_tree = {version = "0.24.0", path = "./crates/nu_plugin_tree", optional = true}
nu_plugin_xpath = {version = "0.24.0", path = "./crates/nu_plugin_xpath", optional = true}
nu_plugin_selector = {version = "0.24.0", path = "./crates/nu_plugin_selector", optional = true}
# Required to bootstrap the main binary
clap = "2.33.3"
@ -56,7 +56,7 @@ itertools = "0.9.0"
[dev-dependencies]
dunce = "1.0.1"
nu-test-support = {version = "0.23.0", path = "./crates/nu-test-support"}
nu-test-support = {version = "0.24.0", path = "./crates/nu-test-support"}
[build-dependencies]

View File

@ -4,33 +4,36 @@ description = "CLI for nushell"
edition = "2018"
license = "MIT"
name = "nu-cli"
version = "0.23.0"
version = "0.24.0"
build = "build.rs"
[lib]
doctest = false
[dependencies]
nu-data = {version = "0.23.0", path = "../nu-data"}
nu-errors = {version = "0.23.0", path = "../nu-errors"}
nu-json = {version = "0.23.0", path = "../nu-json"}
nu-parser = {version = "0.23.0", path = "../nu-parser"}
nu-plugin = {version = "0.23.0", path = "../nu-plugin"}
nu-protocol = {version = "0.23.0", path = "../nu-protocol"}
nu-source = {version = "0.23.0", path = "../nu-source"}
nu-table = {version = "0.23.0", path = "../nu-table"}
nu-test-support = {version = "0.23.0", path = "../nu-test-support"}
nu-value-ext = {version = "0.23.0", path = "../nu-value-ext"}
nu-data = {version = "0.24.0", path = "../nu-data"}
nu-errors = {version = "0.24.0", path = "../nu-errors"}
nu-json = {version = "0.24.0", path = "../nu-json"}
nu-parser = {version = "0.24.0", path = "../nu-parser"}
nu-plugin = {version = "0.24.0", path = "../nu-plugin"}
nu-protocol = {version = "0.24.0", path = "../nu-protocol"}
nu-source = {version = "0.24.0", path = "../nu-source"}
nu-table = {version = "0.24.0", path = "../nu-table"}
nu-test-support = {version = "0.24.0", path = "../nu-test-support"}
nu-value-ext = {version = "0.24.0", path = "../nu-value-ext"}
ansi_term = "0.12.1"
async-recursion = "0.3.1"
async-trait = "0.1.40"
base64 = "0.12.3"
base64 = "0.13.0"
bigdecimal = {version = "0.2.0", features = ["serde"]}
byte-unit = "4.0.9"
bytes = "0.5.6"
calamine = "0.16.1"
chrono = {version = "0.4.15", features = ["serde"]}
chrono-tz = "0.5.3"
clap = "2.33.3"
clipboard = {version = "0.5.0", optional = true}
codespan-reporting = "0.9.5"
csv = "1.1.3"
ctrlc = {version = "3.1.6", optional = true}
@ -40,11 +43,12 @@ dirs = {version = "3.0.1", optional = true}
dtparse = "1.2.0"
dunce = "1.0.1"
eml-parser = "0.1.0"
encoding_rs = "0.8.24"
filesize = "0.2.0"
fs_extra = "1.2.0"
futures = {version = "0.3.5", features = ["compat", "io-compat"]}
futures-util = "0.3.5"
futures_codec = "0.4.1"
futures-util = "0.3.5"
getset = "0.1.1"
git2 = {version = "0.13.11", default_features = false, optional = true}
glob = "0.3.0"
@ -53,7 +57,9 @@ htmlescape = "0.3.1"
ical = "0.6.0"
ichwh = {version = "0.3.4", optional = true}
indexmap = {version = "1.6.0", features = ["serde-1"]}
Inflector = "0.11"
itertools = "0.9.0"
lazy_static = "1.*"
log = "0.4.11"
meval = "0.2.0"
num-bigint = {version = "0.3.0", features = ["serde"]}
@ -66,6 +72,7 @@ ptree = {version = "0.3.0", optional = true}
query_interface = "0.3.5"
quick-xml = "0.18.1"
rand = "0.7.3"
rayon = "1.4.0"
regex = "1.3.9"
roxmltree = "0.13.0"
rust-embed = "5.6.0"
@ -85,20 +92,15 @@ tempfile = "3.1.0"
term = {version = "0.6.1", optional = true}
term_size = "0.3.2"
termcolor = "1.1.0"
titlecase = "1.0"
toml = "0.5.6"
trash = {version = "1.2.0", optional = true}
unicode-segmentation = "1.6.0"
uom = {version = "0.28.0", features = ["f64", "try-from"]}
url = "2.1.1"
uuid_crate = {package = "uuid", version = "0.8.1", features = ["v4"], optional = true}
which = {version = "4.0.2", optional = true}
zip = {version = "0.5.7", optional = true}
lazy_static = "1.*"
Inflector = "0.11"
clipboard = {version = "0.5.0", optional = true}
encoding_rs = "0.8.24"
rayon = "1.4.0"
trash = {version = "1.2.0", optional = true}
url = "2.1.1"
[target.'cfg(unix)'.dependencies]
umask = "1.0.0"
@ -116,7 +118,7 @@ optional = true
version = "0.24.0"
[build-dependencies]
git2 = {version = "0.13.11", optional = true}
shadow-rs = "0.3.20"
[dev-dependencies]
quickcheck = "0.9.2"

View File

@ -1,36 +1,6 @@
use std::path::Path;
use std::{env, fs, io};
fn main() -> Result<(), io::Error> {
let out_dir = env::var_os("OUT_DIR").expect(
"\
OUT_DIR environment variable not found. \
OUT_DIR is guaranteed to exist in a build script by cargo - see \
https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts\
");
let latest_commit_hash = latest_commit_hash(env::current_dir()?).unwrap_or_default();
let commit_hash_path = Path::new(&out_dir).join("git_commit_hash");
fs::write(commit_hash_path, latest_commit_hash)?;
fn main() -> shadow_rs::SdResult<()> {
let src_path = std::env::var("CARGO_MANIFEST_DIR")?;
let out_path = std::env::var("OUT_DIR")?;
shadow_rs::Shadow::build(src_path, out_path)?;
Ok(())
}
#[allow(unused_variables)]
fn latest_commit_hash<P: AsRef<Path>>(dir: P) -> Result<String, Box<dyn std::error::Error>> {
#[cfg(feature = "git2")]
{
use git2::Repository;
let dir = dir.as_ref();
Ok(Repository::discover(dir)?
.head()?
.peel_to_commit()?
.id()
.to_string())
}
#[cfg(not(feature = "git2"))]
{
Ok(String::new())
}
}

View File

@ -86,8 +86,10 @@ pub fn create_default_context(interactive: bool) -> Result<EvaluationContext, Bo
whole_stream_command(Touch),
whole_stream_command(Cpy),
whole_stream_command(Date),
whole_stream_command(DateListTimeZone),
whole_stream_command(DateNow),
whole_stream_command(DateUTC),
whole_stream_command(DateToTable),
whole_stream_command(DateToTimeZone),
whole_stream_command(DateFormat),
whole_stream_command(Cal),
whole_stream_command(Mkdir),
@ -120,6 +122,8 @@ pub fn create_default_context(interactive: bool) -> Result<EvaluationContext, Bo
whole_stream_command(Autoview),
whole_stream_command(Table),
// Text manipulation
whole_stream_command(Hash),
whole_stream_command(HashBase64),
whole_stream_command(Split),
whole_stream_command(SplitColumn),
whole_stream_command(SplitRow),
@ -213,6 +217,7 @@ pub fn create_default_context(interactive: bool) -> Result<EvaluationContext, Bo
whole_stream_command(AutoenvTrust),
whole_stream_command(AutoenvUnTrust),
whole_stream_command(Math),
whole_stream_command(MathAbs),
whole_stream_command(MathAverage),
whole_stream_command(MathEval),
whole_stream_command(MathMedian),
@ -264,6 +269,7 @@ pub fn create_default_context(interactive: bool) -> Result<EvaluationContext, Bo
whole_stream_command(RandomUUID),
whole_stream_command(RandomInteger),
whole_stream_command(RandomDecimal),
whole_stream_command(RandomChars),
// Path
whole_stream_command(PathBasename),
whole_stream_command(PathCommand),

View File

@ -62,6 +62,7 @@ pub(crate) mod from_yaml;
pub(crate) mod get;
pub(crate) mod group_by;
pub(crate) mod group_by_date;
pub(crate) mod hash_;
pub(crate) mod headers;
pub(crate) mod help;
pub(crate) mod histogram;
@ -153,7 +154,7 @@ pub(crate) use config::{
};
pub(crate) use count::Count;
pub(crate) use cp::Cpy;
pub(crate) use date::{Date, DateFormat, DateNow, DateUTC};
pub(crate) use date::{Date, DateFormat, DateListTimeZone, DateNow, DateToTable, DateToTimeZone};
pub(crate) use debug::Debug;
pub(crate) use default::Default;
pub(crate) use describe::Describe;
@ -199,6 +200,7 @@ pub(crate) use from_yaml::FromYML;
pub(crate) use get::Get;
pub(crate) use group_by::Command as GroupBy;
pub(crate) use group_by_date::GroupByDate;
pub(crate) use hash_::{Hash, HashBase64};
pub(crate) use headers::Headers;
pub(crate) use help::Help;
pub(crate) use histogram::Histogram;
@ -210,8 +212,8 @@ pub(crate) use last::Last;
pub(crate) use lines::Lines;
pub(crate) use ls::Ls;
pub(crate) use math::{
Math, MathAverage, MathCeil, MathEval, MathFloor, MathMaximum, MathMedian, MathMinimum,
MathMode, MathProduct, MathRound, MathStddev, MathSummation, MathVariance,
Math, MathAbs, MathAverage, MathCeil, MathEval, MathFloor, MathMaximum, MathMedian,
MathMinimum, MathMode, MathProduct, MathRound, MathStddev, MathSummation, MathVariance,
};
pub(crate) use merge::Merge;
pub(crate) use mkdir::Mkdir;
@ -230,7 +232,9 @@ pub(crate) use prev::Previous;
pub(crate) use pwd::Pwd;
#[cfg(feature = "uuid_crate")]
pub(crate) use random::RandomUUID;
pub(crate) use random::{Random, RandomBool, RandomDecimal, RandomDice, RandomInteger};
pub(crate) use random::{
Random, RandomBool, RandomChars, RandomDecimal, RandomDice, RandomInteger,
};
pub(crate) use range::Range;
pub(crate) use reduce::Reduce;
pub(crate) use reject::Reject;

View File

@ -9,7 +9,7 @@ use nu_protocol::hir::{Block, ClassifiedCommand, Commands};
use nu_protocol::{ReturnSuccess, Scope, UntaggedValue, Value};
use std::sync::atomic::Ordering;
pub(crate) async fn run_block(
pub async fn run_block(
block: &Block,
ctx: &mut EvaluationContext,
mut input: InputStream,

View File

@ -1,18 +1,18 @@
use crate::prelude::*;
use chrono::{DateTime, Local};
use nu_errors::ShellError;
use crate::commands::date::utils::{date_to_value, date_to_value_raw};
use crate::commands::WholeStreamCommand;
use nu_protocol::{Signature, SyntaxShape, UntaggedValue};
use crate::prelude::*;
use nu_errors::ShellError;
use nu_protocol::{
Dictionary, Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value,
};
use nu_source::Tagged;
use std::fmt::{self, write};
pub struct Date;
#[derive(Deserialize)]
pub struct FormatArgs {
format: Tagged<String>,
raw: Option<bool>,
table: bool,
}
#[async_trait]
@ -24,11 +24,11 @@ impl WholeStreamCommand for Date {
fn signature(&self) -> Signature {
Signature::build("date format")
.required("format", SyntaxShape::String, "strftime format")
.switch("raw", "print date without tables", Some('r'))
.switch("table", "print date in a table", Some('t'))
}
fn usage(&self) -> &str {
"format the current date using the given format string."
"Format a given date using the given format string."
}
async fn run(
@ -38,6 +38,21 @@ impl WholeStreamCommand for Date {
) -> Result<OutputStream, ShellError> {
format(args, registry).await
}
fn examples(&self) -> Vec<Example> {
vec![
Example {
description: "Format the current date",
example: "date now | date format '%Y.%m.%d_%H %M %S,%z'",
result: None,
},
Example {
description: "Format the current date and print in a table",
example: "date now | date format -t '%Y-%m-%d_%H:%M:%S %z'",
result: None,
},
]
}
}
pub async fn format(
@ -46,20 +61,46 @@ pub async fn format(
) -> Result<OutputStream, ShellError> {
let registry = registry.clone();
let tag = args.call_info.name_tag.clone();
let (FormatArgs { format, raw }, _) = args.process(&registry).await?;
let (FormatArgs { format, table }, input) = args.process(&registry).await?;
let dt_fmt = format.to_string();
Ok(input
.map(move |value| match value {
Value {
value: UntaggedValue::Primitive(Primitive::Date(dt)),
..
} => {
let mut output = String::new();
if let Err(fmt::Error) =
write(&mut output, format_args!("{}", dt.format(&format.item)))
{
Err(ShellError::labeled_error(
"The date format is invalid",
"invalid strftime format",
&format.tag,
))
} else {
let value = if table {
let mut indexmap = IndexMap::new();
indexmap.insert(
"formatted".to_string(),
UntaggedValue::string(&output).into_value(&tag),
);
let value = {
let local: DateTime<Local> = Local::now();
if let Some(true) = raw {
UntaggedValue::string(date_to_value_raw(local, dt_fmt)).into_untagged_value()
} else {
date_to_value(local, tag, dt_fmt)
}
};
UntaggedValue::Row(Dictionary::from(indexmap)).into_value(&tag)
} else {
UntaggedValue::string(&output).into_value(&tag)
};
Ok(OutputStream::one(value))
ReturnSuccess::value(value)
}
}
_ => Err(ShellError::labeled_error(
"Expected a date from pipeline",
"requires date input",
&tag,
)),
})
.to_output_stream())
}
#[cfg(test)]

View File

@ -0,0 +1,82 @@
use crate::commands::WholeStreamCommand;
use crate::prelude::*;
use chrono_tz::TZ_VARIANTS;
use indexmap::IndexMap;
use nu_errors::ShellError;
use nu_protocol::{Dictionary, ReturnSuccess, Signature, UntaggedValue};
pub struct Date;
#[async_trait]
impl WholeStreamCommand for Date {
fn name(&self) -> &str {
"date list-timezone"
}
fn signature(&self) -> Signature {
Signature::build("date list-timezone")
}
fn usage(&self) -> &str {
"List supported time zones."
}
async fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
list_timezone(args, registry).await
}
fn examples(&self) -> Vec<Example> {
vec![
Example {
description: "List all supported time zones",
example: "date list-timezone",
result: None,
},
Example {
description: "List all supported European time zones",
example: "date list-timezone | where timezone =~ Europe",
result: None,
},
]
}
}
async fn list_timezone(
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
let args = args.evaluate_once(&registry).await?;
let tag = args.call_info.name_tag.clone();
let list = TZ_VARIANTS.iter().map(move |tz| {
let mut entries = IndexMap::new();
entries.insert(
"timezone".to_string(),
UntaggedValue::string(tz.name()).into_value(&tag),
);
Ok(ReturnSuccess::Value(
UntaggedValue::Row(Dictionary { entries }).into_value(&tag),
))
});
Ok(futures::stream::iter(list).to_output_stream())
}
#[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

@ -1,11 +1,15 @@
pub mod command;
pub mod format;
pub mod list_timezone;
pub mod now;
pub mod utc;
pub mod to_table;
pub mod to_timezone;
mod utils;
mod parser;
pub use command::Command as Date;
pub use format::Date as DateFormat;
pub use list_timezone::Date as DateListTimeZone;
pub use now::Date as DateNow;
pub use utc::Date as DateUTC;
pub use to_table::Date as DateToTable;
pub use to_timezone::Date as DateToTimeZone;

View File

@ -1,10 +1,8 @@
use crate::commands::WholeStreamCommand;
use crate::prelude::*;
use chrono::{DateTime, Local};
use nu_errors::ShellError;
use crate::commands::date::utils::date_to_value;
use crate::commands::WholeStreamCommand;
use nu_protocol::Signature;
use nu_protocol::{Signature, UntaggedValue};
pub struct Date;
@ -19,7 +17,7 @@ impl WholeStreamCommand for Date {
}
fn usage(&self) -> &str {
"return the current date."
"Get the current date."
}
async fn run(
@ -35,16 +33,12 @@ pub async fn now(
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
let registry = registry.clone();
let args = args.evaluate_once(&registry).await?;
let tag = args.call_info.name_tag.clone();
let no_fmt = "".to_string();
let now: DateTime<Local> = Local::now();
let value = {
let local: DateTime<Local> = Local::now();
date_to_value(local, tag, no_fmt)
};
let value = UntaggedValue::date(now.with_timezone(now.offset())).into_value(&tag);
Ok(OutputStream::one(value))
}

View File

@ -0,0 +1,107 @@
// Modified from chrono::format::scan
use chrono::{DateTime, FixedOffset, Local, Offset, TimeZone};
use chrono_tz::Tz;
use titlecase::titlecase;
#[derive(Debug, Clone, PartialEq, Eq, Copy)]
pub enum ParseErrorKind {
/// Given field is out of permitted range.
OutOfRange,
/// The input string has some invalid character sequence for given formatting items.
Invalid,
/// The input string has been prematurely ended.
TooShort,
}
pub fn datetime_in_timezone(
dt: &DateTime<FixedOffset>,
s: &str,
) -> Result<DateTime<FixedOffset>, ParseErrorKind> {
match timezone_offset_internal(s, true, true) {
Ok(offset) => match FixedOffset::east_opt(offset) {
Some(offset) => Ok(dt.with_timezone(&offset)),
None => Err(ParseErrorKind::OutOfRange),
},
Err(ParseErrorKind::Invalid) => {
if s.to_lowercase() == "local" {
Ok(dt.with_timezone(Local::now().offset()))
} else {
let tz: Tz = parse_timezone_internal(s)?;
let offset = tz.offset_from_utc_datetime(&dt.naive_utc()).fix();
Ok(dt.with_timezone(&offset))
}
}
Err(e) => Err(e),
}
}
fn parse_timezone_internal(s: &str) -> Result<Tz, ParseErrorKind> {
if let Ok(tz) = s.parse() {
Ok(tz)
} else if let Ok(tz) = titlecase(s).parse() {
Ok(tz)
} else if let Ok(tz) = s.to_uppercase().parse() {
Ok(tz)
} else {
Err(ParseErrorKind::Invalid)
}
}
fn timezone_offset_internal(
mut s: &str,
consume_colon: bool,
allow_missing_minutes: bool,
) -> Result<i32, ParseErrorKind> {
fn digits(s: &str) -> Result<(u8, u8), ParseErrorKind> {
let b = s.as_bytes();
if b.len() < 2 {
Err(ParseErrorKind::TooShort)
} else {
Ok((b[0], b[1]))
}
}
let negative = match s.as_bytes().first() {
Some(&b'+') => false,
Some(&b'-') => true,
Some(_) => return Err(ParseErrorKind::Invalid),
None => return Err(ParseErrorKind::TooShort),
};
s = &s[1..];
// hours (00--99)
let hours = match digits(s)? {
(h1 @ b'0'..=b'9', h2 @ b'0'..=b'9') => i32::from((h1 - b'0') * 10 + (h2 - b'0')),
_ => return Err(ParseErrorKind::Invalid),
};
s = &s[2..];
// colons (and possibly other separators)
if consume_colon {
s = s.trim_start_matches(|c: char| c == ':' || c.is_whitespace());
}
// minutes (00--59)
// if the next two items are digits then we have to add minutes
let minutes = if let Ok(ds) = digits(s) {
match ds {
(m1 @ b'0'..=b'5', m2 @ b'0'..=b'9') => i32::from((m1 - b'0') * 10 + (m2 - b'0')),
(b'6'..=b'9', b'0'..=b'9') => return Err(ParseErrorKind::OutOfRange),
_ => return Err(ParseErrorKind::Invalid),
}
} else if allow_missing_minutes {
0
} else {
return Err(ParseErrorKind::TooShort);
};
match s.len() {
len if len >= 2 => &s[2..],
len if len == 0 => s,
_ => return Err(ParseErrorKind::TooShort),
};
let seconds = hours * 3600 + minutes * 60;
Ok(if negative { -seconds } else { seconds })
}

View File

@ -0,0 +1,113 @@
use crate::commands::WholeStreamCommand;
use crate::prelude::*;
use chrono::{Datelike, Timelike};
use indexmap::IndexMap;
use nu_errors::ShellError;
use nu_protocol::{Dictionary, Primitive, ReturnSuccess, Signature, UntaggedValue, Value};
pub struct Date;
#[async_trait]
impl WholeStreamCommand for Date {
fn name(&self) -> &str {
"date to-table"
}
fn signature(&self) -> Signature {
Signature::build("date to-table")
}
fn usage(&self) -> &str {
"Print the date in a structured table."
}
async fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
to_table(args, registry).await
}
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Print the current date in a table",
example: "date now | date to-table",
result: None,
}]
}
}
async fn to_table(
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
let registry = registry.clone();
let args = args.evaluate_once(&registry).await?;
let tag = args.call_info.name_tag.clone();
let input = args.input;
Ok(input
.map(move |value| match value {
Value {
value: UntaggedValue::Primitive(Primitive::Date(dt)),
..
} => {
let mut indexmap = IndexMap::new();
indexmap.insert(
"year".to_string(),
UntaggedValue::int(dt.year()).into_value(&tag),
);
indexmap.insert(
"month".to_string(),
UntaggedValue::int(dt.month()).into_value(&tag),
);
indexmap.insert(
"day".to_string(),
UntaggedValue::int(dt.day()).into_value(&tag),
);
indexmap.insert(
"hour".to_string(),
UntaggedValue::int(dt.hour()).into_value(&tag),
);
indexmap.insert(
"minute".to_string(),
UntaggedValue::int(dt.minute()).into_value(&tag),
);
indexmap.insert(
"second".to_string(),
UntaggedValue::int(dt.second()).into_value(&tag),
);
let tz = dt.offset();
indexmap.insert(
"timezone".to_string(),
UntaggedValue::string(format!("{}", tz)).into_value(&tag),
);
let value = UntaggedValue::Row(Dictionary::from(indexmap)).into_value(&tag);
ReturnSuccess::value(value)
}
_ => Err(ShellError::labeled_error(
"Expected a date from pipeline",
"requires date input",
&tag,
)),
})
.to_output_stream())
}
#[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

@ -0,0 +1,118 @@
use crate::commands::date::parser::{datetime_in_timezone, ParseErrorKind};
use crate::commands::WholeStreamCommand;
use crate::prelude::*;
use nu_errors::ShellError;
use nu_protocol::{Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
use nu_source::Tagged;
pub struct Date;
#[derive(Deserialize)]
struct DateToTimeZoneArgs {
timezone: Tagged<String>,
}
#[async_trait]
impl WholeStreamCommand for Date {
fn name(&self) -> &str {
"date to-timezone"
}
fn signature(&self) -> Signature {
Signature::build("date to-timezone").required(
"time zone",
SyntaxShape::String,
"time zone description",
)
}
fn usage(&self) -> &str {
"Convert a date to a given time zone.
Use `date list-timezone` to list all supported time zones.
"
}
async fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
to_timezone(args, registry).await
}
fn examples(&self) -> Vec<Example> {
vec![
Example {
description: "Get the current date in UTC+05:00",
example: "date now | date to-timezone +0500",
result: None,
},
Example {
description: "Get the current local date",
example: "date now | date to-timezone local",
result: None,
},
Example {
description: "Get the current date in Hawaii",
example: "date now | date to-timezone US/Hawaii",
result: None,
},
]
}
}
async fn to_timezone(
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
let registry = registry.clone();
let tag = args.call_info.name_tag.clone();
let (DateToTimeZoneArgs { timezone }, input) = args.process(&registry).await?;
Ok(input
.map(move |value| match value {
Value {
value: UntaggedValue::Primitive(Primitive::Date(dt)),
..
} => match datetime_in_timezone(&dt, &timezone.item) {
Ok(dt) => {
let value = UntaggedValue::date(dt).into_value(&tag);
ReturnSuccess::value(value)
}
Err(e) => Err(ShellError::labeled_error(
error_message(e),
"invalid time zone",
&timezone.tag,
)),
},
_ => Err(ShellError::labeled_error(
"Expected a date from pipeline",
"requires date input",
&tag,
)),
})
.to_output_stream())
}
fn error_message(err: ParseErrorKind) -> &'static str {
match err {
ParseErrorKind::Invalid => "The time zone description is invalid",
ParseErrorKind::OutOfRange => "The time zone offset is out of range",
ParseErrorKind::TooShort => "The format of the time zone is invalid",
}
}
#[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

@ -1,63 +0,0 @@
use crate::prelude::*;
use chrono::{DateTime, Utc};
use nu_errors::ShellError;
use crate::commands::date::utils::date_to_value;
use crate::commands::WholeStreamCommand;
use nu_protocol::Signature;
pub struct Date;
#[async_trait]
impl WholeStreamCommand for Date {
fn name(&self) -> &str {
"date utc"
}
fn signature(&self) -> Signature {
Signature::build("date utc")
}
fn usage(&self) -> &str {
"return the current date in utc."
}
async fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
utc(args, registry).await
}
}
pub async fn utc(
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
let registry = registry.clone();
let args = args.evaluate_once(&registry).await?;
let tag = args.call_info.name_tag.clone();
let no_fmt = "".to_string();
let value = {
let local: DateTime<Utc> = Utc::now();
date_to_value(local, tag, no_fmt)
};
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

@ -1,64 +0,0 @@
use crate::prelude::*;
use chrono::DateTime;
use nu_protocol::{Dictionary, Value};
use chrono::{Datelike, TimeZone, Timelike};
use core::fmt::Display;
use indexmap::IndexMap;
use nu_protocol::UntaggedValue;
pub fn date_to_value_raw<T: TimeZone>(dt: DateTime<T>, dt_format: String) -> String
where
T::Offset: Display,
{
let result = dt.format(&dt_format);
format!("{}", result)
}
pub fn date_to_value<T: TimeZone>(dt: DateTime<T>, tag: Tag, dt_format: String) -> Value
where
T::Offset: Display,
{
let mut indexmap = IndexMap::new();
if dt_format.is_empty() {
indexmap.insert(
"year".to_string(),
UntaggedValue::int(dt.year()).into_value(&tag),
);
indexmap.insert(
"month".to_string(),
UntaggedValue::int(dt.month()).into_value(&tag),
);
indexmap.insert(
"day".to_string(),
UntaggedValue::int(dt.day()).into_value(&tag),
);
indexmap.insert(
"hour".to_string(),
UntaggedValue::int(dt.hour()).into_value(&tag),
);
indexmap.insert(
"minute".to_string(),
UntaggedValue::int(dt.minute()).into_value(&tag),
);
indexmap.insert(
"second".to_string(),
UntaggedValue::int(dt.second()).into_value(&tag),
);
let tz = dt.offset();
indexmap.insert(
"timezone".to_string(),
UntaggedValue::string(format!("{}", tz)).into_value(&tag),
);
} else {
let result = dt.format(&dt_format);
indexmap.insert(
"formatted".to_string(),
UntaggedValue::string(format!("{}", result)).into_value(&tag),
);
}
UntaggedValue::Row(Dictionary::from(indexmap)).into_value(&tag)
}

View File

@ -54,6 +54,7 @@ pub async fn from_delimited_data(
) -> Result<OutputStream, ShellError> {
let name_tag = name;
let concat_string = input.collect_string(name_tag.clone()).await?;
let sample_lines = concat_string.item.lines().take(3).collect_vec().join("\n");
match from_delimited_string_to_value(concat_string.item, headerless, sep, name_tag.clone()) {
Ok(x) => match x {
@ -65,10 +66,16 @@ pub async fn from_delimited_data(
},
Err(err) => {
let line_one = match pretty_csv_error(err) {
Some(pretty) => format!("Could not parse as {} ({})", format_name, pretty),
None => format!("Could not parse as {}", format_name),
Some(pretty) => format!(
"Could not parse as {} split by '{}' ({})",
format_name, sep, pretty
),
None => format!("Could not parse as {} split by '{}'", format_name, sep),
};
let line_two = format!("input cannot be parsed as {}", format_name);
let line_two = format!(
"input cannot be parsed as {} split by '{}'. Input's first lines:\n{}",
format_name, sep, sample_lines
);
Err(ShellError::labeled_error_with_secondary(
line_one,

View File

@ -0,0 +1,314 @@
use crate::commands::WholeStreamCommand;
use crate::prelude::*;
use nu_errors::ShellError;
use nu_protocol::ShellTypeName;
use nu_protocol::{
ColumnPath, Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value,
};
use nu_source::{Tag, Tagged};
use base64::{decode_config, encode_config};
#[derive(Deserialize)]
pub struct Arguments {
pub rest: Vec<ColumnPath>,
pub character_set: Option<Tagged<String>>,
pub encode: Tagged<bool>,
pub decode: Tagged<bool>,
}
#[derive(Clone)]
pub struct Base64Config {
pub character_set: String,
pub action_type: ActionType,
}
#[derive(Clone, Copy, PartialEq)]
pub enum ActionType {
Encode,
Decode,
}
pub struct SubCommand;
#[async_trait]
impl WholeStreamCommand for SubCommand {
fn name(&self) -> &str {
"hash base64"
}
fn signature(&self) -> Signature {
Signature::build("hash base64")
.named(
"character_set",
SyntaxShape::String,
"specify the character rules for encoding the input.\n\
\tValid values are 'standard', 'standard-no-padding', 'url-safe', 'url-safe-no-padding',\
'binhex', 'bcrypt', 'crypt'",
Some('c'),
)
.switch(
"encode",
"encode the input as base64. This is the default behavior if not specified.",
Some('e')
)
.switch(
"decode",
"decode the input from base64",
Some('d'))
.rest(
SyntaxShape::ColumnPath,
"optionally base64 encode / decode data by column paths",
)
}
fn usage(&self) -> &str {
"base64 encode or decode a value"
}
async fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
operate(args, registry).await
}
fn examples(&self) -> Vec<Example> {
vec![
Example {
description: "Base64 encode a string with default settings",
example: "echo 'username:password' | hash base64",
result: Some(vec![
UntaggedValue::string("dXNlcm5hbWU6cGFzc3dvcmQ=").into_untagged_value()
]),
},
Example {
description: "Base64 encode a string with the binhex character set",
example: "echo 'username:password' | hash base64 --character_set binhex --encode",
result: Some(vec![
UntaggedValue::string("F@0NEPjJD97kE'&bEhFZEP3").into_untagged_value()
]),
},
Example {
description: "Base64 decode a value",
example: "echo 'dXNlcm5hbWU6cGFzc3dvcmQ=' | hash base64 --decode",
result: Some(vec![
UntaggedValue::string("username:password").into_untagged_value()
]),
},
]
}
}
async fn operate(
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
let registry = registry.clone();
let name_tag = &args.call_info.name_tag.clone();
let (
Arguments {
encode,
decode,
character_set,
rest,
},
input,
) = args.process(&registry).await?;
if encode.item && decode.item {
return Ok(OutputStream::one(Err(ShellError::labeled_error(
"only one of --decode and --encode flags can be used",
"conflicting flags",
name_tag,
))));
}
// Default the action to be encoding if no flags are specified.
let action_type = if *decode.item() {
ActionType::Decode
} else {
ActionType::Encode
};
// Default the character set to standard if the argument is not specified.
let character_set = match character_set {
Some(inner_tag) => inner_tag.item().to_string(),
None => "standard".to_string(),
};
let encoding_config = Base64Config {
character_set,
action_type,
};
let column_paths: Vec<_> = rest;
Ok(input
.map(move |v| {
if column_paths.is_empty() {
ReturnSuccess::value(action(&v, &encoding_config, v.tag())?)
} else {
let mut ret = v;
for path in &column_paths {
let config = encoding_config.clone();
ret = ret.swap_data_by_column_path(
path,
Box::new(move |old| action(old, &config, old.tag())),
)?;
}
ReturnSuccess::value(ret)
}
})
.to_output_stream())
}
fn action(
input: &Value,
base64_config: &Base64Config,
tag: impl Into<Tag>,
) -> Result<Value, ShellError> {
match &input.value {
UntaggedValue::Primitive(Primitive::Line(s))
| UntaggedValue::Primitive(Primitive::String(s)) => {
let base64_config_enum: base64::Config = if &base64_config.character_set == "standard" {
base64::STANDARD
} else if &base64_config.character_set == "standard-no-padding" {
base64::STANDARD_NO_PAD
} else if &base64_config.character_set == "url-safe" {
base64::URL_SAFE
} else if &base64_config.character_set == "url-safe-no-padding" {
base64::URL_SAFE_NO_PAD
} else if &base64_config.character_set == "binhex" {
base64::BINHEX
} else if &base64_config.character_set == "bcrypt" {
base64::BCRYPT
} else if &base64_config.character_set == "crypt" {
base64::CRYPT
} else {
return Err(ShellError::labeled_error(
"value is not an accepted character set",
format!(
"{} is not a valid character-set.\nPlease use `help hash base64` to see a list of valid character sets.",
&base64_config.character_set
),
tag.into().span,
));
};
match base64_config.action_type {
ActionType::Encode => Ok(UntaggedValue::string(encode_config(
&s,
base64_config_enum,
))
.into_value(tag)),
ActionType::Decode => {
let decode_result = decode_config(&s, base64_config_enum);
match decode_result {
Ok(decoded_value) => Ok(UntaggedValue::string(
std::string::String::from_utf8_lossy(&decoded_value),
)
.into_value(tag)),
Err(_) => Err(ShellError::labeled_error(
"value could not be base64 decoded",
format!(
"invalid base64 input for character set {}",
&base64_config.character_set
),
tag.into().span,
)),
}
}
}
}
other => {
let got = format!("got {}", other.type_name());
Err(ShellError::labeled_error(
"value is not string",
got,
tag.into().span,
))
}
}
}
#[cfg(test)]
mod tests {
use super::{action, ActionType, Base64Config};
use nu_protocol::UntaggedValue;
use nu_source::Tag;
use nu_test_support::value::string;
#[test]
fn base64_encode_standard() {
let word = string("username:password");
let expected = UntaggedValue::string("dXNlcm5hbWU6cGFzc3dvcmQ=").into_untagged_value();
let actual = action(
&word,
&Base64Config {
character_set: "standard".to_string(),
action_type: ActionType::Encode,
},
Tag::unknown(),
)
.unwrap();
assert_eq!(actual, expected);
}
#[test]
fn base64_encode_standard_no_padding() {
let word = string("username:password");
let expected = UntaggedValue::string("dXNlcm5hbWU6cGFzc3dvcmQ").into_untagged_value();
let actual = action(
&word,
&Base64Config {
character_set: "standard-no-padding".to_string(),
action_type: ActionType::Encode,
},
Tag::unknown(),
)
.unwrap();
assert_eq!(actual, expected);
}
#[test]
fn base64_encode_url_safe() {
let word = string("this is for url");
let expected = UntaggedValue::string("dGhpcyBpcyBmb3IgdXJs").into_untagged_value();
let actual = action(
&word,
&Base64Config {
character_set: "url-safe".to_string(),
action_type: ActionType::Encode,
},
Tag::unknown(),
)
.unwrap();
assert_eq!(actual, expected);
}
#[test]
fn base64_decode_binhex() {
let word = string("A5\"KC9jRB@IIF'8bF!");
let expected = UntaggedValue::string("a binhex test").into_untagged_value();
let actual = action(
&word,
&Base64Config {
character_set: "binhex".to_string(),
action_type: ActionType::Decode,
},
Tag::unknown(),
)
.unwrap();
assert_eq!(actual, expected);
}
}

View File

@ -0,0 +1,50 @@
use crate::commands::WholeStreamCommand;
use crate::prelude::*;
use nu_errors::ShellError;
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue};
pub struct Command;
#[async_trait]
impl WholeStreamCommand for Command {
fn name(&self) -> &str {
"hash"
}
fn signature(&self) -> Signature {
Signature::build("hash").rest(
SyntaxShape::ColumnPath,
"optionally convert by column paths",
)
}
fn usage(&self) -> &str {
"Apply hash function."
}
async fn run(
&self,
_args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
let registry = registry.clone();
Ok(OutputStream::one(ReturnSuccess::value(
UntaggedValue::string(crate::commands::help::get_help(&Command, &registry))
.into_value(Tag::unknown()),
)))
}
}
#[cfg(test)]
mod tests {
use super::Command;
use super::ShellError;
#[test]
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
Ok(test_examples(Command {})?)
}
}

View File

@ -0,0 +1,5 @@
mod base64_;
mod command;
pub use base64_::SubCommand as HashBase64;
pub use command::Command as Hash;

View File

@ -0,0 +1,73 @@
use crate::commands::WholeStreamCommand;
use crate::prelude::*;
use nu_errors::ShellError;
use nu_protocol::{Primitive, Signature, UntaggedValue, Value};
pub struct SubCommand;
#[async_trait]
impl WholeStreamCommand for SubCommand {
fn name(&self) -> &str {
"math abs"
}
fn signature(&self) -> Signature {
Signature::build("math abs")
}
fn usage(&self) -> &str {
"Returns absolute values of a list of numbers"
}
async fn run(
&self,
args: CommandArgs,
_: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
let mapped = args.input.map(move |val| match val.value {
UntaggedValue::Primitive(Primitive::Int(val)) => {
UntaggedValue::int(val.magnitude().clone()).into()
}
UntaggedValue::Primitive(Primitive::Decimal(val)) => {
UntaggedValue::decimal(val.abs()).into()
}
UntaggedValue::Primitive(Primitive::Duration(val)) => {
UntaggedValue::duration(val.magnitude().clone()).into()
}
other => abs_default(other),
});
Ok(OutputStream::from_input(mapped))
}
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Get absolute of each value in a list of numbers",
example: "echo [-50 -100.0 25] | math abs",
result: Some(vec![
UntaggedValue::int(50).into(),
UntaggedValue::decimal_from_float(100.0, Span::default()).into(),
UntaggedValue::int(25).into(),
]),
}]
}
}
fn abs_default(_: UntaggedValue) -> Value {
UntaggedValue::Error(ShellError::unexpected(
"Only numerical values are supported",
))
.into()
}
#[cfg(test)]
mod tests {
use super::ShellError;
use super::SubCommand;
#[test]
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
Ok(test_examples(SubCommand {})?)
}
}

View File

@ -1,3 +1,4 @@
pub mod abs;
pub mod avg;
pub mod ceil;
pub mod command;
@ -16,6 +17,7 @@ pub mod variance;
mod reducers;
mod utils;
pub use abs::SubCommand as MathAbs;
pub use avg::SubCommand as MathAverage;
pub use ceil::SubCommand as MathCeil;
pub use command::Command as Math;

View File

@ -0,0 +1,89 @@
use crate::commands::WholeStreamCommand;
use crate::prelude::*;
use nu_errors::ShellError;
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue};
use nu_source::Tagged;
use rand::distributions::Alphanumeric;
use rand::prelude::{thread_rng, Rng};
pub struct SubCommand;
#[derive(Deserialize)]
pub struct CharsArgs {
length: Option<Tagged<u32>>,
}
const DEFAULT_CHARS_LENGTH: u32 = 25;
#[async_trait]
impl WholeStreamCommand for SubCommand {
fn name(&self) -> &str {
"random chars"
}
fn signature(&self) -> Signature {
Signature::build("random chars").named(
"length",
SyntaxShape::Int,
"Number of chars",
Some('l'),
)
}
fn usage(&self) -> &str {
"Generate random chars"
}
async fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
chars(args, registry).await
}
fn examples(&self) -> Vec<Example> {
vec![
Example {
description: "Generate random chars",
example: "random chars",
result: None,
},
Example {
description: "Generate random chars with specified length",
example: "random chars -l 20",
result: None,
},
]
}
}
pub async fn chars(
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
let (CharsArgs { length }, _) = args.process(&registry).await?;
let chars_length = length.map_or(DEFAULT_CHARS_LENGTH, |l| l.item);
let random_string: String = thread_rng()
.sample_iter(&Alphanumeric)
.take(chars_length as usize)
.collect();
let result = UntaggedValue::string(random_string);
Ok(OutputStream::one(ReturnSuccess::value(result)))
}
#[cfg(test)]
mod tests {
use super::ShellError;
use super::SubCommand;
#[test]
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
Ok(test_examples(SubCommand {})?)
}
}

View File

@ -1,6 +1,7 @@
pub mod command;
pub mod bool;
pub mod chars;
pub mod decimal;
pub mod dice;
pub mod integer;
@ -10,6 +11,7 @@ pub mod uuid;
pub use command::Command as Random;
pub use self::bool::SubCommand as RandomBool;
pub use chars::SubCommand as RandomChars;
pub use decimal::SubCommand as RandomDecimal;
pub use dice::SubCommand as RandomDice;
pub use integer::SubCommand as RandomInteger;

View File

@ -1,12 +1,12 @@
use crate::commands::WholeStreamCommand;
use crate::prelude::*;
use indexmap::IndexMap;
use nu_data::TaggedListBuilder;
use nu_errors::ShellError;
use nu_protocol::{Dictionary, Signature, UntaggedValue};
const GIT_COMMIT_HASH: &str = include_str!(concat!(env!("OUT_DIR"), "/git_commit_hash"));
use nu_protocol::{value::StrExt, value::StringExt, Dictionary, Signature, UntaggedValue};
pub mod shadow {
include!(concat!(env!("OUT_DIR"), "/shadow.rs"));
}
pub struct Version;
#[async_trait]
@ -50,35 +50,277 @@ pub fn version(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputS
UntaggedValue::string(clap::crate_version!()).into_value(&tag),
);
let commit_hash = Some(GIT_COMMIT_HASH.trim()).filter(|x| !x.is_empty());
if let Some(commit_hash) = commit_hash {
let branch: Option<&str> = Some(shadow::BRANCH).filter(|x| !x.is_empty());
if let Some(branch) = branch {
indexmap.insert(
"commit_hash".to_string(),
UntaggedValue::string(commit_hash).into_value(&tag),
"branch".to_string(),
branch.to_pattern_untagged_value().into_value(&tag),
);
}
indexmap.insert("features".to_string(), features_enabled(&tag).into_value());
let short_commit: Option<&str> = Some(shadow::SHORT_COMMIT).filter(|x| !x.is_empty());
if let Some(short_commit) = short_commit {
indexmap.insert(
"short_commit".to_string(),
short_commit.to_pattern_untagged_value().into_value(&tag),
);
}
let commit_hash: Option<&str> = Some(shadow::COMMIT_HASH).filter(|x| !x.is_empty());
if let Some(commit_hash) = commit_hash {
indexmap.insert(
"commit_hash".to_string(),
commit_hash.to_pattern_untagged_value().into_value(&tag),
);
}
let commit_date: Option<&str> = Some(shadow::COMMIT_DATE).filter(|x| !x.is_empty());
if let Some(commit_date) = commit_date {
indexmap.insert(
"commit_date".to_string(),
commit_date.to_pattern_untagged_value().into_value(&tag),
);
}
// let commit_author: Option<&str> = Some(shadow::COMMIT_AUTHOR).filter(|x| !x.is_empty());
// if let Some(commit_author) = commit_author {
// indexmap.insert(
// "commit_author".to_string(),
// commit_author.to_pattern_untagged_value().into_value(&tag),
// );
// }
let _commit_autor = shadow::COMMIT_AUTHOR;
// let commit_email: Option<&str> = Some(shadow::COMMIT_EMAIL).filter(|x| !x.is_empty());
// if let Some(commit_email) = commit_email {
// indexmap.insert(
// "commit_email".to_string(),
// commit_email.to_pattern_untagged_value().into_value(&tag),
// );
// }
let _commit_email = shadow::COMMIT_EMAIL;
let build_os: Option<&str> = Some(shadow::BUILD_OS).filter(|x| !x.is_empty());
if let Some(build_os) = build_os {
indexmap.insert(
"build_os".to_string(),
build_os.to_pattern_untagged_value().into_value(&tag),
);
}
let rust_version: Option<&str> = Some(shadow::RUST_VERSION).filter(|x| !x.is_empty());
if let Some(rust_version) = rust_version {
indexmap.insert(
"rust_version".to_string(),
rust_version.to_pattern_untagged_value().into_value(&tag),
);
}
let rust_channel: Option<&str> = Some(shadow::RUST_CHANNEL).filter(|x| !x.is_empty());
if let Some(rust_channel) = rust_channel {
indexmap.insert(
"rust_channel".to_string(),
rust_channel.to_pattern_untagged_value().into_value(&tag),
);
}
let cargo_version: Option<&str> = Some(shadow::CARGO_VERSION).filter(|x| !x.is_empty());
if let Some(cargo_version) = cargo_version {
indexmap.insert(
"cargo_version".to_string(),
cargo_version.to_pattern_untagged_value().into_value(&tag),
);
}
let pkg_version: Option<&str> = Some(shadow::PKG_VERSION).filter(|x| !x.is_empty());
if let Some(pkg_version) = pkg_version {
indexmap.insert(
"pkg_version".to_string(),
pkg_version.to_pattern_untagged_value().into_value(&tag),
);
}
// let cargo_tree: Option<&str> = Some(shadow::CARGO_TREE).filter(|x| !x.is_empty());
// if let Some(cargo_tree) = cargo_tree {
// indexmap.insert(
// "cargo_tree".to_string(),
// cargo_tree.to_pattern_untagged_value().into_value(&tag),
// );
// }
let _cargo_tree = shadow::CARGO_TREE;
// let project_name: Option<&str> = Some(shadow::PROJECT_NAME).filter(|x| !x.is_empty());
// if let Some(project_name) = project_name {
// indexmap.insert(
// "project_name".to_string(),
// project_name.to_pattern_untagged_value().into_value(&tag),
// );
// }
let _project_name = shadow::PROJECT_NAME;
let build_time: Option<&str> = Some(shadow::BUILD_TIME).filter(|x| !x.is_empty());
if let Some(build_time) = build_time {
indexmap.insert(
"build_time".to_string(),
build_time.to_pattern_untagged_value().into_value(&tag),
);
}
let build_rust_channel: Option<&str> =
Some(shadow::BUILD_RUST_CHANNEL).filter(|x| !x.is_empty());
if let Some(build_rust_channel) = build_rust_channel {
indexmap.insert(
"build_rust_channel".to_string(),
build_rust_channel
.to_pattern_untagged_value()
.into_value(&tag),
);
}
indexmap.insert(
"features".to_string(),
features_enabled().join(", ").to_string_value_create_tag(),
);
let value = UntaggedValue::Row(Dictionary::from(indexmap)).into_value(&tag);
Ok(OutputStream::one(value))
}
fn features_enabled(tag: impl Into<Tag>) -> TaggedListBuilder {
let mut names = TaggedListBuilder::new(tag);
fn features_enabled() -> Vec<String> {
let mut names = vec![];
names.push_untagged(UntaggedValue::string("default"));
names.push("default".to_string());
#[cfg(feature = "ctrlc")]
{
names.push("ctrlc".to_string());
}
#[cfg(feature = "dirs")]
{
names.push("dirs".to_string());
}
#[cfg(feature = "directories")]
{
names.push("directories".to_string());
}
#[cfg(feature = "git2")]
{
names.push("git".to_string());
}
#[cfg(feature = "ptree")]
{
names.push("ptree".to_string());
}
#[cfg(feature = "rich-benchmark")]
{
names.push("rich-benchmark".to_string());
}
#[cfg(feature = "rustyline-support")]
{
names.push("rustyline".to_string());
}
#[cfg(feature = "term")]
{
names.push("term".to_string());
}
#[cfg(feature = "uuid_crate")]
{
names.push("uuid".to_string());
}
#[cfg(feature = "which")]
{
names.push("which".to_string());
}
#[cfg(feature = "ichwh")]
{
names.push("ichwh".to_string());
}
#[cfg(feature = "zip")]
{
names.push("zip".to_string());
}
#[cfg(feature = "clipboard-cli")]
{
names.push_untagged(UntaggedValue::string("clipboard"));
names.push("clipboard-cli".to_string());
}
#[cfg(feature = "trash-support")]
{
names.push_untagged(UntaggedValue::string("trash"));
names.push("trash".to_string());
}
// #[cfg(feature = "binaryview")]
// {
// names.push("binaryview".to_string());
// }
// #[cfg(feature = "start")]
// {
// names.push("start".to_string());
// }
// #[cfg(feature = "bson")]
// {
// names.push("bson".to_string());
// }
// #[cfg(feature = "sqlite")]
// {
// names.push("sqlite".to_string());
// }
// #[cfg(feature = "s3")]
// {
// names.push("s3".to_string());
// }
// #[cfg(feature = "chart")]
// {
// names.push("chart".to_string());
// }
// #[cfg(feature = "xpath")]
// {
// names.push("xpath".to_string());
// }
// #[cfg(feature = "selector")]
// {
// names.push("selector".to_string());
// }
// #[cfg(feature = "extra")]
// {
// names.push("extra".to_string());
// }
// #[cfg(feature = "preserve_order")]
// {
// names.push("preserve_order".to_string());
// }
// #[cfg(feature = "wee_alloc")]
// {
// names.push("wee_alloc".to_string());
// }
// #[cfg(feature = "console_error_panic_hook")]
// {
// names.push("console_error_panic_hook".to_string());
// }
names.sort();
names
}

View File

@ -27,7 +27,7 @@ pub struct EvaluationContext {
}
impl EvaluationContext {
pub(crate) fn registry(&self) -> &CommandRegistry {
pub fn registry(&self) -> &CommandRegistry {
&self.registry
}

View File

@ -47,6 +47,7 @@ pub use crate::cli::{
run_pipeline_standalone, run_vec_of_pipelines, LineResult,
};
pub use crate::command_registry::CommandRegistry;
pub use crate::commands::classified::block::run_block;
pub use crate::commands::command::{
whole_stream_command, CommandArgs, EvaluatedWholeStreamCommandArgs, Example, WholeStreamCommand,
};

View File

@ -765,60 +765,59 @@ impl VarSyntaxShapeDeductor {
)],
)?;
}
Operator::In | Operator::NotIn => {
match var_side {
BinarySide::Left => match &expr.expr {
Expression::List(list) => {
if !list.is_empty() {
let shapes_in_list = self
.get_shapes_in_list_or_insert_dependency(
Operator::In | Operator::NotIn => match var_side {
BinarySide::Left => match &expr.expr {
Expression::List(list) => {
if !list.is_empty() {
let shapes_in_list = self.get_shapes_in_list_or_insert_dependency(
var,
bin_spanned,
&list,
(pipeline_idx, pipeline),
registry,
);
match shapes_in_list {
None => {}
Some(shapes_in_list) => {
self.checked_insert(
var,
bin_spanned,
&list,
(pipeline_idx, pipeline),
registry,
);
match shapes_in_list {
None => {}
Some(shapes_in_list) => {
self.checked_insert(
var,
VarShapeDeduction::from_usage_with_alternatives(
&var.span,
&shapes_in_list,
),
)?;
}
VarShapeDeduction::from_usage_with_alternatives(
&var.span,
&shapes_in_list,
),
)?;
}
}
}
Expression::Table(_, _)
| Expression::Literal(_)
| Expression::ExternalWord
| Expression::Synthetic(_)
| Expression::Variable(_, _)
| Expression::Binary(_)
| Expression::Range(_)
| Expression::Block(_)
| Expression::Path(_)
| Expression::FilePath(_)
| Expression::ExternalCommand(_)
| Expression::Command
| Expression::Invocation(_)
| Expression::Boolean(_)
| Expression::Garbage => {unreachable!("Parser should have rejected code. In only applicable with rhs of type List")}
},
BinarySide::Right => {
self.checked_insert(
var,
VarShapeDeduction::from_usage_with_alternatives(
&var.span,
&[SyntaxShape::Table],
),
)?;
}
Expression::Table(_, _)
| Expression::Literal(_)
| Expression::ExternalWord
| Expression::Synthetic(_)
| Expression::Variable(_, _)
| Expression::Binary(_)
| Expression::Range(_)
| Expression::Block(_)
| Expression::Path(_)
| Expression::FilePath(_)
| Expression::ExternalCommand(_)
| Expression::Command
| Expression::Invocation(_)
| Expression::Boolean(_)
| Expression::Garbage => {
unreachable!("Parser should have rejected code. In only applicable with rhs of type List")
}
},
BinarySide::Right => {
self.checked_insert(
var,
VarShapeDeduction::from_usage_with_alternatives(
&var.span,
&[SyntaxShape::Table],
),
)?;
}
}
},
Operator::Modulo => {
self.checked_insert(
var,

View File

@ -0,0 +1,85 @@
use nu_test_support::{nu, pipeline};
#[test]
fn base64_defaults_to_encoding_with_standard_character_type() {
let actual = nu!(
cwd: ".", pipeline(
r#"
echo 'username:password' | hash base64
"#
)
);
assert_eq!(actual.out, "dXNlcm5hbWU6cGFzc3dvcmQ=");
}
#[test]
fn base64_encode_characterset_binhex() {
let actual = nu!(
cwd: ".", pipeline(
r#"
echo 'username:password' | hash base64 --character_set binhex --encode
"#
)
);
assert_eq!(actual.out, "F@0NEPjJD97kE\'&bEhFZEP3");
}
#[test]
fn error_when_invalid_character_set_given() {
let actual = nu!(
cwd: ".", pipeline(
r#"
echo 'username:password' | hash base64 --character_set 'this is invalid' --encode
"#
)
);
assert!(actual
.err
.contains("this is invalid is not a valid character-set"));
}
#[test]
fn base64_decode_characterset_binhex() {
let actual = nu!(
cwd: ".", pipeline(
r#"
echo "F@0NEPjJD97kE'&bEhFZEP3" | hash base64 --character_set binhex --decode
"#
)
);
assert_eq!(actual.out, "username:password");
}
#[test]
fn error_invalid_decode_value() {
let actual = nu!(
cwd: ".", pipeline(
r#"
echo "this should not be a valid encoded value" | hash base64 --character_set url-safe --decode
"#
)
);
assert!(actual
.err
.contains("invalid base64 input for character set url-safe"));
}
#[test]
fn error_use_both_flags() {
let actual = nu!(
cwd: ".", pipeline(
r#"
echo 'username:password' | hash base64 --encode --decode
"#
)
);
assert!(actual
.err
.contains("only one of --decode and --encode flags can be used"));
}

View File

@ -20,6 +20,7 @@ mod flatten;
mod format;
mod get;
mod group_by;
mod hash_;
mod headers;
mod histogram;
mod insert;

View File

@ -0,0 +1,14 @@
use nu_test_support::{nu, pipeline};
#[test]
fn generates_chars_of_specified_length() {
let actual = nu!(
cwd: ".", pipeline(
r#"
random chars -l 15 | size | get chars
"#
));
let result = actual.out;
assert_eq!(result, "15");
}

View File

@ -1,4 +1,5 @@
mod bool;
mod chars;
mod decimal;
mod dice;
mod integer;

View File

@ -4,7 +4,7 @@ description = "CLI for nushell"
edition = "2018"
license = "MIT"
name = "nu-data"
version = "0.23.0"
version = "0.24.0"
[lib]
doctest = false
@ -29,12 +29,12 @@ query_interface = "0.3.5"
serde = {version = "1.0.115", features = ["derive"]}
toml = "0.5.6"
nu-errors = {version = "0.23.0", path = "../nu-errors"}
nu-protocol = {version = "0.23.0", path = "../nu-protocol"}
nu-source = {version = "0.23.0", path = "../nu-source"}
nu-table = {version = "0.23.0", path = "../nu-table"}
nu-test-support = {version = "0.23.0", path = "../nu-test-support"}
nu-value-ext = {version = "0.23.0", path = "../nu-value-ext"}
nu-errors = {version = "0.24.0", path = "../nu-errors"}
nu-protocol = {version = "0.24.0", path = "../nu-protocol"}
nu-source = {version = "0.24.0", path = "../nu-source"}
nu-table = {version = "0.24.0", path = "../nu-table"}
nu-test-support = {version = "0.24.0", path = "../nu-test-support"}
nu-value-ext = {version = "0.24.0", path = "../nu-value-ext"}
[target.'cfg(unix)'.dependencies]
users = "0.10.0"

View File

@ -1,7 +1,7 @@
pub(crate) mod shape;
use bigdecimal::BigDecimal;
use chrono::{DateTime, Utc};
use chrono::{DateTime, FixedOffset, Utc};
use derive_new::new;
use nu_errors::ShellError;
use nu_protocol::{
@ -75,8 +75,8 @@ pub enum CompareValues {
Ints(BigInt, BigInt),
Decimals(BigDecimal, BigDecimal),
String(String, String),
Date(DateTime<Utc>, DateTime<Utc>),
DateDuration(DateTime<Utc>, BigInt),
Date(DateTime<FixedOffset>, DateTime<FixedOffset>),
DateDuration(DateTime<FixedOffset>, BigInt),
Booleans(bool, bool),
}
@ -94,9 +94,10 @@ impl CompareValues {
Span::unknown(),
)
.expect("Could not convert nushell Duration into chrono Duration.");
let right: DateTime<Utc> = Utc::now()
let right: DateTime<FixedOffset> = Utc::now()
.checked_sub_signed(duration)
.expect("Data overflow");
.expect("Data overflow")
.into();
right.cmp(left)
}
CompareValues::Booleans(left, right) => left.cmp(right),

View File

@ -1,6 +1,6 @@
// use crate::config::{Conf, NuConfig};
use bigdecimal::BigDecimal;
use chrono::{DateTime, Utc};
use chrono::{DateTime, FixedOffset};
use indexmap::map::IndexMap;
use nu_protocol::RangeInclusion;
use nu_protocol::{format_primitive, ColumnPath, Dictionary, Primitive, UntaggedValue, Value};
@ -31,7 +31,7 @@ pub enum InlineShape {
ColumnPath(ColumnPath),
Pattern(String),
Boolean(bool),
Date(DateTime<Utc>),
Date(DateTime<FixedOffset>),
Duration(BigInt),
Path(PathBuf),
Binary(usize),

View File

@ -25,7 +25,7 @@ impl Date {
let date = date.with_timezone(&chrono::offset::Utc);
Ok(UntaggedValue::Primitive(Primitive::Date(date)))
Ok(UntaggedValue::Primitive(Primitive::Date(date.into())))
}
pub fn naive_from_str(s: Tagged<&str>) -> Result<UntaggedValue, ShellError> {
@ -38,7 +38,7 @@ impl Date {
})?;
Ok(UntaggedValue::Primitive(Primitive::Date(
DateTime::<Utc>::from_utc(date.and_hms(12, 34, 56), Utc),
DateTime::<Utc>::from_utc(date.and_hms(12, 34, 56), Utc).into(),
)))
}
}

View File

@ -4,13 +4,13 @@ description = "Core error subsystem for Nushell"
edition = "2018"
license = "MIT"
name = "nu-errors"
version = "0.23.0"
version = "0.24.0"
[lib]
doctest = false
[dependencies]
nu-source = {path = "../nu-source", version = "0.23.0"}
nu-source = {path = "../nu-source", version = "0.24.0"}
ansi_term = "0.12.1"
bigdecimal = {version = "0.2.0", features = ["serde"]}

View File

@ -4,7 +4,7 @@ description = "Fork of serde-hjson"
edition = "2018"
license = "MIT"
name = "nu-json"
version = "0.23.0"
version = "0.24.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View File

@ -4,7 +4,7 @@ description = "Nushell parser"
edition = "2018"
license = "MIT"
name = "nu-parser"
version = "0.23.0"
version = "0.24.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -19,9 +19,9 @@ num-traits = "0.2.12"
serde = "1.0.115"
shellexpand = "2.0.0"
nu-errors = {version = "0.23.0", path = "../nu-errors"}
nu-protocol = {version = "0.23.0", path = "../nu-protocol"}
nu-source = {version = "0.23.0", path = "../nu-source"}
nu-errors = {version = "0.24.0", path = "../nu-errors"}
nu-protocol = {version = "0.24.0", path = "../nu-protocol"}
nu-source = {version = "0.24.0", path = "../nu-source"}
[features]
stable = []

View File

@ -4,17 +4,17 @@ description = "Nushell Plugin"
edition = "2018"
license = "MIT"
name = "nu-plugin"
version = "0.23.0"
version = "0.24.0"
[lib]
doctest = false
[dependencies]
nu-errors = {path = "../nu-errors", version = "0.23.0"}
nu-protocol = {path = "../nu-protocol", version = "0.23.0"}
nu-source = {path = "../nu-source", version = "0.23.0"}
nu-test-support = {path = "../nu-test-support", version = "0.23.0"}
nu-value-ext = {path = "../nu-value-ext", version = "0.23.0"}
nu-errors = {path = "../nu-errors", version = "0.24.0"}
nu-protocol = {path = "../nu-protocol", version = "0.24.0"}
nu-source = {path = "../nu-source", version = "0.24.0"}
nu-test-support = {path = "../nu-test-support", version = "0.24.0"}
nu-value-ext = {path = "../nu-value-ext", version = "0.24.0"}
bigdecimal = {version = "0.2.0", features = ["serde"]}
indexmap = {version = "1.6.0", features = ["serde-1"]}

View File

@ -4,7 +4,7 @@ description = "Core values and protocols for Nushell"
edition = "2018"
license = "MIT"
name = "nu-protocol"
version = "0.23.0"
version = "0.24.0"
[lib]
doctest = false
@ -17,8 +17,8 @@ derive-new = "0.5.8"
getset = "0.1.1"
indexmap = {version = "1.6.0", features = ["serde-1"]}
log = "0.4.11"
nu-errors = {path = "../nu-errors", version = "0.23.0"}
nu-source = {path = "../nu-source", version = "0.23.0"}
nu-errors = {path = "../nu-errors", version = "0.24.0"}
nu-source = {path = "../nu-source", version = "0.24.0"}
num-bigint = {version = "0.3.0", features = ["serde"]}
num-integer = "0.1.43"
num-traits = "0.2.12"

View File

@ -19,7 +19,7 @@ use crate::value::range::{Range, RangeInclusion};
use crate::ColumnPath;
use bigdecimal::BigDecimal;
use bigdecimal::FromPrimitive;
use chrono::{DateTime, Utc};
use chrono::{DateTime, FixedOffset, Utc};
use indexmap::IndexMap;
use nu_errors::ShellError;
use nu_source::{AnchorLocation, HasSpan, Span, Spanned, SpannedItem, Tag};
@ -242,16 +242,17 @@ impl UntaggedValue {
}
/// Helper for creating date duration values
pub fn duration(nanos: BigInt) -> UntaggedValue {
UntaggedValue::Primitive(Primitive::Duration(nanos))
pub fn duration(nanos: impl Into<BigInt>) -> UntaggedValue {
UntaggedValue::Primitive(Primitive::Duration(nanos.into()))
}
/// Helper for creating datatime values
pub fn system_date(s: SystemTime) -> UntaggedValue {
UntaggedValue::Primitive(Primitive::Date(s.into()))
let utc: DateTime<Utc> = s.into();
UntaggedValue::Primitive(Primitive::Date(utc.into()))
}
pub fn date(d: impl Into<DateTime<Utc>>) -> UntaggedValue {
pub fn date(d: impl Into<DateTime<FixedOffset>>) -> UntaggedValue {
UntaggedValue::Primitive(Primitive::Date(d.into()))
}
@ -924,7 +925,7 @@ pub trait DateTimeExt {
fn to_value_create_tag(&self) -> Value;
}
impl DateTimeExt for DateTime<Utc> {
impl DateTimeExt for DateTime<FixedOffset> {
fn to_value(&self, the_tag: Tag) -> Value {
Value {
value: UntaggedValue::Primitive(Primitive::Date(*self)),

View File

@ -3,7 +3,7 @@ use crate::value::column_path::ColumnPath;
use crate::value::range::{Range, RangeInclusion};
use crate::value::{serde_bigdecimal, serde_bigint};
use bigdecimal::BigDecimal;
use chrono::{DateTime, Utc};
use chrono::{DateTime, FixedOffset, Utc};
use nu_errors::{ExpectedRange, ShellError};
use nu_source::{PrettyDebug, Span, SpannedItem};
use num_bigint::BigInt;
@ -42,8 +42,8 @@ pub enum Primitive {
Pattern(String),
/// A boolean value
Boolean(bool),
/// A date value, in UTC
Date(DateTime<Utc>),
/// A date value
Date(DateTime<FixedOffset>),
/// A count in the number of nanoseconds
#[serde(with = "serde_bigint")]
Duration(BigInt),
@ -385,8 +385,8 @@ pub fn format_duration(duration: &BigInt) -> String {
}
#[allow(clippy::cognitive_complexity)]
/// Format a UTC date value into a humanized string (eg "1 week ago" instead of a formal date string)
pub fn format_date(d: &DateTime<Utc>) -> String {
/// Format a date value into a humanized string (eg "1 week ago" instead of a formal date string)
pub fn format_date(d: &DateTime<FixedOffset>) -> String {
let utc: DateTime<Utc> = Utc::now();
let duration = utc.signed_duration_since(*d);

View File

@ -4,7 +4,7 @@ description = "A source string characterizer for Nushell"
edition = "2018"
license = "MIT"
name = "nu-source"
version = "0.23.0"
version = "0.24.0"
[lib]
doctest = false

View File

@ -4,7 +4,7 @@ description = "Nushell table printing"
edition = "2018"
license = "MIT"
name = "nu-table"
version = "0.23.0"
version = "0.24.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[[bin]]

View File

@ -4,16 +4,16 @@ description = "Support for writing Nushell tests"
edition = "2018"
license = "MIT"
name = "nu-test-support"
version = "0.23.0"
version = "0.24.0"
[lib]
doctest = false
[dependencies]
nu-errors = {version = "0.23.0", path = "../nu-errors"}
nu-protocol = {path = "../nu-protocol", version = "0.23.0"}
nu-source = {path = "../nu-source", version = "0.23.0"}
nu-value-ext = {version = "0.23.0", path = "../nu-value-ext"}
nu-errors = {version = "0.24.0", path = "../nu-errors"}
nu-protocol = {path = "../nu-protocol", version = "0.24.0"}
nu-source = {path = "../nu-source", version = "0.24.0"}
nu-value-ext = {version = "0.24.0", path = "../nu-value-ext"}
bigdecimal = {version = "0.2.0", features = ["serde"]}
chrono = "0.4.15"

View File

@ -40,10 +40,9 @@ pub fn date(input: impl Into<String>) -> Value {
let date = NaiveDate::parse_from_str(key.borrow_tagged().item, "%Y-%m-%d")
.expect("date from string failed");
UntaggedValue::Primitive(Primitive::Date(DateTime::<Utc>::from_utc(
date.and_hms(12, 34, 56),
Utc,
)))
UntaggedValue::Primitive(Primitive::Date(
DateTime::<Utc>::from_utc(date.and_hms(12, 34, 56), Utc).into(),
))
.into_untagged_value()
}

View File

@ -4,15 +4,15 @@ description = "Extension traits for values in Nushell"
edition = "2018"
license = "MIT"
name = "nu-value-ext"
version = "0.23.0"
version = "0.24.0"
[lib]
doctest = false
[dependencies]
nu-errors = {path = "../nu-errors", version = "0.23.0"}
nu-protocol = {path = "../nu-protocol", version = "0.23.0"}
nu-source = {path = "../nu-source", version = "0.23.0"}
nu-errors = {path = "../nu-errors", version = "0.24.0"}
nu-protocol = {path = "../nu-protocol", version = "0.24.0"}
nu-source = {path = "../nu-source", version = "0.24.0"}
indexmap = {version = "1.6.0", features = ["serde-1"]}
itertools = "0.9.0"

View File

@ -4,7 +4,7 @@ description = "A binary viewer plugin for Nushell"
edition = "2018"
license = "MIT"
name = "nu_plugin_binaryview"
version = "0.23.0"
version = "0.24.0"
[lib]
doctest = false
@ -14,10 +14,10 @@ ansi_term = "0.12.1"
crossterm = "0.18"
image = {version = "0.22.4", default_features = false, features = ["png_codec", "jpeg"]}
neso = "0.5.0"
nu-errors = {path = "../nu-errors", version = "0.23.0"}
nu-plugin = {path = "../nu-plugin", version = "0.23.0"}
nu-protocol = {path = "../nu-protocol", version = "0.23.0"}
nu-source = {path = "../nu-source", version = "0.23.0"}
nu-errors = {path = "../nu-errors", version = "0.24.0"}
nu-plugin = {path = "../nu-plugin", version = "0.24.0"}
nu-protocol = {path = "../nu-protocol", version = "0.24.0"}
nu-source = {path = "../nu-source", version = "0.24.0"}
pretty-hex = "0.2.0"
rawkey = "0.1.3"

View File

@ -4,19 +4,19 @@ description = "A plugin to display charts"
edition = "2018"
license = "MIT"
name = "nu_plugin_chart"
version = "0.23.0"
version = "0.24.0"
[lib]
doctest = false
[dependencies]
nu-cli = {path = "../nu-cli", version = "0.23.0"}
nu-data = {path = "../nu-data", version = "0.23.0"}
nu-errors = {path = "../nu-errors", version = "0.23.0"}
nu-plugin = {path = "../nu-plugin", version = "0.23.0"}
nu-protocol = {path = "../nu-protocol", version = "0.23.0"}
nu-source = {path = "../nu-source", version = "0.23.0"}
nu-value-ext = {path = "../nu-value-ext", version = "0.23.0"}
nu-cli = {path = "../nu-cli", version = "0.24.0"}
nu-data = {path = "../nu-data", version = "0.24.0"}
nu-errors = {path = "../nu-errors", version = "0.24.0"}
nu-plugin = {path = "../nu-plugin", version = "0.24.0"}
nu-protocol = {path = "../nu-protocol", version = "0.24.0"}
nu-source = {path = "../nu-source", version = "0.24.0"}
nu-value-ext = {path = "../nu-value-ext", version = "0.24.0"}
crossterm = "0.18"
tui = {version = "0.12.0", default-features = false, features = ["crossterm"]}

View File

@ -4,7 +4,7 @@ description = "A URL fetch plugin for Nushell"
edition = "2018"
license = "MIT"
name = "nu_plugin_fetch"
version = "0.23.0"
version = "0.24.0"
[lib]
doctest = false
@ -12,10 +12,10 @@ doctest = false
[dependencies]
base64 = "0.12.3"
futures = {version = "0.3.5", features = ["compat", "io-compat"]}
nu-errors = {path = "../nu-errors", version = "0.23.0"}
nu-plugin = {path = "../nu-plugin", version = "0.23.0"}
nu-protocol = {path = "../nu-protocol", version = "0.23.0"}
nu-source = {path = "../nu-source", version = "0.23.0"}
nu-errors = {path = "../nu-errors", version = "0.24.0"}
nu-plugin = {path = "../nu-plugin", version = "0.24.0"}
nu-protocol = {path = "../nu-protocol", version = "0.24.0"}
nu-source = {path = "../nu-source", version = "0.24.0"}
surf = "1.0.3"
url = "2.1.1"

View File

@ -4,7 +4,7 @@ description = "A converter plugin to the bson format for Nushell"
edition = "2018"
license = "MIT"
name = "nu_plugin_from_bson"
version = "0.23.0"
version = "0.24.0"
[lib]
doctest = false
@ -12,11 +12,11 @@ doctest = false
[dependencies]
bigdecimal = "0.2.0"
bson = {version = "0.14.1", features = ["decimal128"]}
nu-errors = {path = "../nu-errors", version = "0.23.0"}
nu-plugin = {path = "../nu-plugin", version = "0.23.0"}
nu-protocol = {path = "../nu-protocol", version = "0.23.0"}
nu-source = {path = "../nu-source", version = "0.23.0"}
nu-value-ext = {path = "../nu-value-ext", version = "0.23.0"}
nu-errors = {path = "../nu-errors", version = "0.24.0"}
nu-plugin = {path = "../nu-plugin", version = "0.24.0"}
nu-protocol = {path = "../nu-protocol", version = "0.24.0"}
nu-source = {path = "../nu-source", version = "0.24.0"}
nu-value-ext = {path = "../nu-value-ext", version = "0.24.0"}
num-traits = "0.2.12"
[build-dependencies]

View File

@ -130,7 +130,9 @@ fn convert_bson_value_to_nu_value(v: &Bson, tag: impl Into<Tag>) -> Result<Value
);
collected.into_value()
}
Bson::UtcDatetime(dt) => UntaggedValue::Primitive(Primitive::Date(*dt)).into_value(&tag),
Bson::UtcDatetime(dt) => {
UntaggedValue::Primitive(Primitive::Date((*dt).into())).into_value(&tag)
}
Bson::Symbol(s) => {
let mut collected = TaggedDictBuilder::new(tag.clone());
collected.insert_value(

View File

@ -4,18 +4,18 @@ description = "A converter plugin to the bson format for Nushell"
edition = "2018"
license = "MIT"
name = "nu_plugin_from_sqlite"
version = "0.23.0"
version = "0.24.0"
[lib]
doctest = false
[dependencies]
bigdecimal = "0.2.0"
nu-errors = {path = "../nu-errors", version = "0.23.0"}
nu-plugin = {path = "../nu-plugin", version = "0.23.0"}
nu-protocol = {path = "../nu-protocol", version = "0.23.0"}
nu-source = {path = "../nu-source", version = "0.23.0"}
nu-value-ext = {path = "../nu-value-ext", version = "0.23.0"}
nu-errors = {path = "../nu-errors", version = "0.24.0"}
nu-plugin = {path = "../nu-plugin", version = "0.24.0"}
nu-protocol = {path = "../nu-protocol", version = "0.24.0"}
nu-source = {path = "../nu-source", version = "0.24.0"}
nu-value-ext = {path = "../nu-value-ext", version = "0.24.0"}
num-traits = "0.2.12"
tempfile = "3.1.0"

View File

@ -4,18 +4,18 @@ description = "A version incrementer plugin for Nushell"
edition = "2018"
license = "MIT"
name = "nu_plugin_inc"
version = "0.23.0"
version = "0.24.0"
[lib]
doctest = false
[dependencies]
nu-errors = {path = "../nu-errors", version = "0.23.0"}
nu-plugin = {path = "../nu-plugin", version = "0.23.0"}
nu-protocol = {path = "../nu-protocol", version = "0.23.0"}
nu-source = {path = "../nu-source", version = "0.23.0"}
nu-test-support = {path = "../nu-test-support", version = "0.23.0"}
nu-value-ext = {path = "../nu-value-ext", version = "0.23.0"}
nu-errors = {path = "../nu-errors", version = "0.24.0"}
nu-plugin = {path = "../nu-plugin", version = "0.24.0"}
nu-protocol = {path = "../nu-protocol", version = "0.24.0"}
nu-source = {path = "../nu-source", version = "0.24.0"}
nu-test-support = {path = "../nu-test-support", version = "0.24.0"}
nu-value-ext = {path = "../nu-value-ext", version = "0.24.0"}
semver = "0.10.0"

View File

@ -4,16 +4,16 @@ description = "A regex match plugin for Nushell"
edition = "2018"
license = "MIT"
name = "nu_plugin_match"
version = "0.23.0"
version = "0.24.0"
[lib]
doctest = false
[dependencies]
nu-errors = {path = "../nu-errors", version = "0.23.0"}
nu-plugin = {path = "../nu-plugin", version = "0.23.0"}
nu-protocol = {path = "../nu-protocol", version = "0.23.0"}
nu-source = {path = "../nu-source", version = "0.23.0"}
nu-errors = {path = "../nu-errors", version = "0.24.0"}
nu-plugin = {path = "../nu-plugin", version = "0.24.0"}
nu-protocol = {path = "../nu-protocol", version = "0.24.0"}
nu-source = {path = "../nu-source", version = "0.24.0"}
regex = "1.3.9"
[build-dependencies]

View File

@ -4,7 +4,7 @@ description = "An HTTP post plugin for Nushell"
edition = "2018"
license = "MIT"
name = "nu_plugin_post"
version = "0.23.0"
version = "0.24.0"
[lib]
doctest = false
@ -12,10 +12,10 @@ doctest = false
[dependencies]
base64 = "0.12.3"
futures = {version = "0.3.5", features = ["compat", "io-compat"]}
nu-errors = {path = "../nu-errors", version = "0.23.0"}
nu-plugin = {path = "../nu-plugin", version = "0.23.0"}
nu-protocol = {path = "../nu-protocol", version = "0.23.0"}
nu-source = {path = "../nu-source", version = "0.23.0"}
nu-errors = {path = "../nu-errors", version = "0.24.0"}
nu-plugin = {path = "../nu-plugin", version = "0.24.0"}
nu-protocol = {path = "../nu-protocol", version = "0.24.0"}
nu-source = {path = "../nu-source", version = "0.24.0"}
num-traits = "0.2.12"
serde_json = "1.0.57"
surf = "1.0.3"

View File

@ -4,16 +4,16 @@ description = "A process list plugin for Nushell"
edition = "2018"
license = "MIT"
name = "nu_plugin_ps"
version = "0.23.0"
version = "0.24.0"
[lib]
doctest = false
[dependencies]
nu-errors = {path = "../nu-errors", version = "0.23.0"}
nu-plugin = {path = "../nu-plugin", version = "0.23.0"}
nu-protocol = {path = "../nu-protocol", version = "0.23.0"}
nu-source = {path = "../nu-source", version = "0.23.0"}
nu-errors = {path = "../nu-errors", version = "0.24.0"}
nu-plugin = {path = "../nu-plugin", version = "0.24.0"}
nu-protocol = {path = "../nu-protocol", version = "0.24.0"}
nu-source = {path = "../nu-source", version = "0.24.0"}
num-bigint = "0.3.0"

View File

@ -4,17 +4,17 @@ description = "An S3 plugin for Nushell"
edition = "2018"
license = "MIT"
name = "nu_plugin_s3"
version = "0.23.0"
version = "0.24.0"
[lib]
doctest = false
[dependencies]
futures = {version = "0.3.5", features = ["compat", "io-compat"]}
nu-errors = {path = "../nu-errors", version = "0.23.0"}
nu-plugin = {path = "../nu-plugin", version = "0.23.0"}
nu-protocol = {path = "../nu-protocol", version = "0.23.0"}
nu-source = {path = "../nu-source", version = "0.23.0"}
nu-errors = {path = "../nu-errors", version = "0.24.0"}
nu-plugin = {path = "../nu-plugin", version = "0.24.0"}
nu-protocol = {path = "../nu-protocol", version = "0.24.0"}
nu-source = {path = "../nu-source", version = "0.24.0"}
s3handler = "0.5.0"
[build-dependencies]

View File

@ -4,17 +4,17 @@ description = "web scraping using css selector"
edition = "2018"
license = "MIT"
name = "nu_plugin_selector"
version = "0.23.0"
version = "0.24.0"
[lib]
doctest = false
[dependencies]
nu-errors = {version = "0.23.0", path = "../nu-errors"}
nu-plugin = {version = "0.23.0", path = "../nu-plugin"}
nu-protocol = {version = "0.23.0", path = "../nu-protocol"}
nu-source = {version = "0.23.0", path = "../nu-source"}
nu-errors = {version = "0.24.0", path = "../nu-errors"}
nu-plugin = {version = "0.24.0", path = "../nu-plugin"}
nu-protocol = {version = "0.24.0", path = "../nu-protocol"}
nu-source = {version = "0.24.0", path = "../nu-source"}
nipper = "0.1.8"
[dev-dependencies]
nu-test-support = {path = "../nu-test-support", version = "0.23.0"}
nu-test-support = {path = "../nu-test-support", version = "0.24.0"}

View File

@ -4,20 +4,20 @@ description = "A plugin to open files/URLs directly from Nushell"
edition = "2018"
license = "MIT"
name = "nu_plugin_start"
version = "0.23.0"
version = "0.24.0"
[lib]
doctest = false
[dependencies]
glob = "0.3.0"
nu-errors = {path = "../nu-errors", version = "0.23.0"}
nu-plugin = {path = "../nu-plugin", version = "0.23.0"}
nu-protocol = {path = "../nu-protocol", version = "0.23.0"}
nu-source = {path = "../nu-source", version = "0.23.0"}
nu-errors = {path = "../nu-errors", version = "0.24.0"}
nu-plugin = {path = "../nu-plugin", version = "0.24.0"}
nu-protocol = {path = "../nu-protocol", version = "0.24.0"}
nu-source = {path = "../nu-source", version = "0.24.0"}
open = "1.4.0"
url = "2.1.1"
[build-dependencies]
nu-errors = {version = "0.23.0", path = "../nu-errors"}
nu-source = {version = "0.23.0", path = "../nu-source"}
nu-errors = {version = "0.24.0", path = "../nu-errors"}
nu-source = {version = "0.24.0", path = "../nu-source"}

View File

@ -4,16 +4,16 @@ description = "A system info plugin for Nushell"
edition = "2018"
license = "MIT"
name = "nu_plugin_sys"
version = "0.23.0"
version = "0.24.0"
[lib]
doctest = false
[dependencies]
nu-errors = {path = "../nu-errors", version = "0.23.0"}
nu-plugin = {path = "../nu-plugin", version = "0.23.0"}
nu-protocol = {path = "../nu-protocol", version = "0.23.0"}
nu-source = {path = "../nu-source", version = "0.23.0"}
nu-errors = {path = "../nu-errors", version = "0.24.0"}
nu-plugin = {path = "../nu-plugin", version = "0.24.0"}
nu-protocol = {path = "../nu-protocol", version = "0.24.0"}
nu-source = {path = "../nu-source", version = "0.24.0"}
battery = "0.7.6"
futures = {version = "0.3.5", features = ["compat", "io-compat"]}

View File

@ -4,17 +4,17 @@ description = "Text viewer plugin for Nushell"
edition = "2018"
license = "MIT"
name = "nu_plugin_textview"
version = "0.23.0"
version = "0.24.0"
[lib]
doctest = false
[dependencies]
nu-data = {path = "../nu-data", version = "0.23.0"}
nu-errors = {path = "../nu-errors", version = "0.23.0"}
nu-plugin = {path = "../nu-plugin", version = "0.23.0"}
nu-protocol = {path = "../nu-protocol", version = "0.23.0"}
nu-source = {path = "../nu-source", version = "0.23.0"}
nu-data = {path = "../nu-data", version = "0.24.0"}
nu-errors = {path = "../nu-errors", version = "0.24.0"}
nu-plugin = {path = "../nu-plugin", version = "0.24.0"}
nu-protocol = {path = "../nu-protocol", version = "0.24.0"}
nu-source = {path = "../nu-source", version = "0.24.0"}
ansi_term = "0.12.1"
bat = {version = "0.15.4", features = ["regex-fancy", "paging"]}

View File

@ -4,18 +4,18 @@ description = "A converter plugin to the bson format for Nushell"
edition = "2018"
license = "MIT"
name = "nu_plugin_to_bson"
version = "0.23.0"
version = "0.24.0"
[lib]
doctest = false
[dependencies]
bson = "0.14.1"
nu-errors = {path = "../nu-errors", version = "0.23.0"}
nu-plugin = {path = "../nu-plugin", version = "0.23.0"}
nu-protocol = {path = "../nu-protocol", version = "0.23.0"}
nu-source = {path = "../nu-source", version = "0.23.0"}
nu-value-ext = {path = "../nu-value-ext", version = "0.23.0"}
nu-errors = {path = "../nu-errors", version = "0.24.0"}
nu-plugin = {path = "../nu-plugin", version = "0.24.0"}
nu-protocol = {path = "../nu-protocol", version = "0.24.0"}
nu-source = {path = "../nu-source", version = "0.24.0"}
nu-value-ext = {path = "../nu-value-ext", version = "0.24.0"}
num-traits = "0.2.12"
[build-dependencies]

View File

@ -29,7 +29,7 @@ pub fn value_to_bson_value(v: &Value) -> Result<Bson, ShellError> {
.expect("Unimplemented BUG: What about big decimals?"),
),
UntaggedValue::Primitive(Primitive::Duration(i)) => Bson::String(i.to_string()),
UntaggedValue::Primitive(Primitive::Date(d)) => Bson::UtcDatetime(*d),
UntaggedValue::Primitive(Primitive::Date(d)) => Bson::UtcDatetime((*d).into()),
UntaggedValue::Primitive(Primitive::EndOfStream) => Bson::Null,
UntaggedValue::Primitive(Primitive::BeginningOfStream) => Bson::Null,
UntaggedValue::Primitive(Primitive::Decimal(d)) => {

View File

@ -4,18 +4,18 @@ description = "A converter plugin to the bson format for Nushell"
edition = "2018"
license = "MIT"
name = "nu_plugin_to_sqlite"
version = "0.23.0"
version = "0.24.0"
[lib]
doctest = false
[dependencies]
hex = "0.4.2"
nu-errors = {path = "../nu-errors", version = "0.23.0"}
nu-plugin = {path = "../nu-plugin", version = "0.23.0"}
nu-protocol = {path = "../nu-protocol", version = "0.23.0"}
nu-source = {path = "../nu-source", version = "0.23.0"}
nu-value-ext = {path = "../nu-value-ext", version = "0.23.0"}
nu-errors = {path = "../nu-errors", version = "0.24.0"}
nu-plugin = {path = "../nu-plugin", version = "0.24.0"}
nu-protocol = {path = "../nu-protocol", version = "0.24.0"}
nu-source = {path = "../nu-source", version = "0.24.0"}
nu-value-ext = {path = "../nu-value-ext", version = "0.24.0"}
num-traits = "0.2.12"
tempfile = "3.1.0"

View File

@ -4,17 +4,17 @@ description = "Tree viewer plugin for Nushell"
edition = "2018"
license = "MIT"
name = "nu_plugin_tree"
version = "0.23.0"
version = "0.24.0"
[lib]
doctest = false
[dependencies]
derive-new = "0.5.8"
nu-errors = {path = "../nu-errors", version = "0.23.0"}
nu-plugin = {path = "../nu-plugin", version = "0.23.0"}
nu-protocol = {path = "../nu-protocol", version = "0.23.0"}
nu-source = {path = "../nu-source", version = "0.23.0"}
nu-errors = {path = "../nu-errors", version = "0.24.0"}
nu-plugin = {path = "../nu-plugin", version = "0.24.0"}
nu-protocol = {path = "../nu-protocol", version = "0.24.0"}
nu-source = {path = "../nu-source", version = "0.24.0"}
ptree = "0.3.0"
[build-dependencies]

View File

@ -4,16 +4,16 @@ description = "Traverses xml"
edition = "2018"
license = "MIT"
name = "nu_plugin_xpath"
version = "0.23.0"
version = "0.24.0"
[lib]
doctest = false
[dependencies]
nu-errors = {version = "0.23.0", path = "../nu-errors"}
nu-plugin = {path = "../nu-plugin", version = "0.23.0"}
nu-protocol = {version = "0.23.0", path = "../nu-protocol"}
nu-source = {version = "0.23.0", path = "../nu-source"}
nu-errors = {version = "0.24.0", path = "../nu-errors"}
nu-plugin = {path = "../nu-plugin", version = "0.24.0"}
nu-protocol = {version = "0.24.0", path = "../nu-protocol"}
nu-source = {version = "0.24.0", path = "../nu-source"}
bigdecimal = {version = "0.2.0", features = ["serde"]}
indexmap = {version = "1.6.0", features = ["serde-1"]}
@ -21,4 +21,4 @@ sxd-document = "0.3.2"
sxd-xpath = "0.4.2"
[dev-dependencies]
nu-test-support = {path = "../nu-test-support", version = "0.23.0"}
nu-test-support = {path = "../nu-test-support", version = "0.24.0"}

View File

@ -3,6 +3,7 @@
Mathematical functions that generally only operate on a list of numbers (integers, decimals, bytes) and tables.
Currently the following functions are implemented:
* `math abs`: Returns absolute values of a list of numbers
* `math avg`: Finds the average of a list of numbers or tables
* `math ceil`: Applies the ceil function to a list of numbers
* [`math eval`](math-eval.md): Evaluates a list of math expressions into numbers
@ -147,6 +148,15 @@ To get the average of the file sizes in a directory, simply pipe the size column
───┴────
```
```shell
> echo [1 -2 -3.0] | math abs
───┬────────
01
12
2 │ 3.0000
───┴────────
```
### Dates
```shell

View File

@ -119,3 +119,10 @@ true
> random integer 100000..200000
173400
```
### chars Examples
Generate a random password of length 15
```shell
> random chars -l 15
fWBSbE7QtaoJGeo
```

View File

@ -88,7 +88,7 @@ version = "0.4.6"
[dependencies.cursive]
default-features = false
features = ["pancurses-backend"]
version = "0.23.0"
version = "0.24.0"
[dependencies.futures-preview]
features = ["compat", "io-compat"]