Compare commits

...

30 Commits

Author SHA1 Message Date
JT
e1ebd461d2 Bump to 0.28 (#4064) 2021-10-06 06:35:25 +13:00
JT
f000d5d0a1 Remove the broken scrolling support (#4063)
* Remove the broken scrolling support

* Remove the broken scrolling support
2021-10-06 05:57:14 +13:00
574c5961c8 Add -c flag to select command (#4062)
See cc3653cfd9 for more on the `-c` flag.

Co-authored-by: Andrés N. Robalino <andres@androbtech.com>

Co-authored-by: Andrés N. Robalino <andres@androbtech.com>
2021-10-05 13:23:37 +13:00
JT
69708f7244 update wasm deps (#4061) 2021-10-03 07:19:54 +13:00
62c5df5fc6 expand tilde when reading plugin_dirs (#4052) 2021-10-02 21:38:21 +13:00
92c855a412 Fixed two typos in the tutor. (#4051) 2021-10-02 21:37:59 +13:00
d395816929 remove ansi colors if this is not a tty (#4058) 2021-10-01 09:00:08 -05:00
5e34ef6dff new command: into column_path (#4048) 2021-09-29 07:23:34 -05:00
d567c58cc1 Add -c flag to update cells subcommand (#4039)
* Add `-c` flag to `update cells` subcommand

* Fix lints
2021-09-27 21:18:50 -05:00
4e0d7bc77c Less deps (#4038)
* compiles on nightly now. (breaking change)

* less deps

* Switch over to new resolver

(it's been stable for a while.)

* let's leave num-format for another PR
2021-09-28 07:17:00 +13:00
32581497ef Fix 90 degrees tables problem (#4043)
* fix 90 degrees tables problem

* linting

* clippy

* linting
2021-09-25 14:05:45 -05:00
d6df367c6b Corrected typo (#4040)
It is not BSON but SQLite
2021-09-25 04:25:00 -05:00
4e6327de1d Added BigInt handling to the delimited file format for the 'to' command (#4034)
Co-authored-by: patrick <patrick@spol42069.hitronhub.home>
2021-09-25 09:47:16 +12:00
b3d8666db0 compiles on nightly now. (breaking change) (#4037) 2021-09-25 09:46:48 +12:00
1de7c3d033 Scraping multiple tables (#4036)
* Output error when ls into a file without permission

* math sqrt

* added test to check fails when ls into prohibited dir

* fix lint

* math sqrt with tests and doc

* trigger wasm build

* Update filesystem_shell.rs

* Fix Running echo .. starts printing integers forever

* Allow for multiple table scraping

* linting

* Fix clippy

* linting

Co-authored-by: Jonathan Turner <jonathandturner@users.noreply.github.com>
2021-09-24 08:08:13 -05:00
962b258cc6 merge span (#4031) 2021-09-23 07:48:05 +12:00
59697cab63 force rebuild of dev container (#4033) 2021-09-23 07:47:28 +12:00
349af05da8 Do not throw error for files not found in lib_dirs (#4029) 2021-09-20 13:44:47 -05:00
JT
b3b3cf0689 Remove the docker instructions
Docker has been out of date for a long time, go ahead and remove.
2021-09-20 19:33:49 +12:00
5d59234f8d Flexibility updating table's cells. (#4027)
Very often we need to work with tables (say extracted from unstructured data or some
kind of final report, timeseries, and the like).

It's inevitable we will be having columns that we can't know beforehand what their names
will be, or how many.

Also, we may end up with certain cells having values we may want to remove as we explore.

Here, `update cells` fundamentally goes over every cell in the table coming in and updates
the cell's contents with the output of the block passed. Basic example here:

```
> [

    [   ty1,       t2,       ty];

    [     1,        a, $nothing]
    [(wrap), (0..<10),      1Mb]
    [    1s,     ({}),  1000000]
    [ $true,   $false,   ([[]])]

] | update cells { describe }

───┬───────────────────────┬───────────────────────────┬──────────
 # │          ty1          │            t2             │    ty
───┼───────────────────────┼───────────────────────────┼──────────
 0 │ integer               │ string                    │ nothing
 1 │ row Column(table of ) │ range[[integer, integer)] │ filesize
 2 │ string                │ nothing                   │ integer
 3 │ boolean               │ boolean                   │ table of
───┴───────────────────────┴───────────────────────────┴──────────
```

and another one (in the examples) for cases, say we have a timeseries table generated and
we want to remove the zeros and have empty strings and save it out to something like CSV.

```
> [
    [2021-04-16, 2021-06-10, 2021-09-18, 2021-10-15, 2021-11-16, 2021-11-17, 2021-11-18];
    [        37,          0,          0,          0,         37,          0,          0]
] | update cells {|value| i
  if ($value | into int) == 0 {
    ""
  } {
    $value
  }
}

───┬────────────┬────────────┬────────────┬────────────┬────────────┬────────────┬────────────
 # │ 2021-04-16 │ 2021-06-10 │ 2021-09-18 │ 2021-10-15 │ 2021-11-16 │ 2021-11-17 │ 2021-11-18
───┼────────────┼────────────┼────────────┼────────────┼────────────┼────────────┼────────────
 0 │         37 │            │            │            │         37 │            │
───┴────────────┴────────────┴────────────┴────────────┴────────────┴────────────┴────────────
```
2021-09-19 15:37:54 -05:00
Tw
4f7b423f36 Support completion when cursor inside an argument (#4023)
* Support completion when cursor inside an argument

Bash supports completion even when cursor is in an argument, this is very useful for some fixup after the initial completion.
Let add this feature as well.

Signed-off-by: Tw <wei.tan@intel.com>

* Add test for when cursor inside an argument

To support test this case, let's also take the position into account.

Signed-off-by: Tw <wei.tan@intel.com>
2021-09-19 17:23:05 +12:00
f7043bf690 Fix #3090: let binding in command leaks when error occurs (#4022) 2021-09-19 14:57:20 +12:00
Tw
1297499d7a add command g to switch shell quickly (#4014)
Signed-off-by: Tw <tw19881113@gmail.com>
2021-09-17 10:39:14 +01:00
bd0baa961c add table selector for downloading web tables (#4004)
* add table selector for downloading web tables

* type-o

* updated debug mode to inspect mode
2021-09-16 09:02:30 -05:00
4ee536f044 fix: enable SIMD (#4021) 2021-09-16 20:01:42 +12:00
JT
8581bec891 bump 0.37.1 (#4019) 2021-09-16 13:32:22 +12:00
8bcbc8eeb3 Move nu-path tests to integration tests (#4015)
* Move nu-path tests to integration tests

To prevent circular dependency between nu-path and nu-test-support crates.

* Fmt
2021-09-16 07:11:28 +12:00
c164ef5489 Update to polars 0.16 (#4013)
* update to polars 0.16

* enabled features for polars
2021-09-16 07:10:12 +12:00
cc3653cfd9 Path commands: Put column path args behid flag; Allow path join appending without flag (#4008)
* Change path join signature

* Appending now works without flag
* Column path operation is behind a -c flag

* Move column path arg retrieval to a function

Also improves errors

* Fix path join tests

* Propagate column path changes to all path commands

* Update path command examples with columns paths

* Modernize path command examples by removing "echo"

* Improve structured path error message

* Fix typo
2021-09-15 21:03:51 +03:00
JT
7fc65067cf Temporarily remove the circular dep (#4009) 2021-09-15 09:17:31 +12:00
93 changed files with 2717 additions and 1228 deletions

2
.gitpod.Dockerfile vendored
View File

@ -2,7 +2,7 @@ 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
ENV TRIGGER_REBUILD 2
USER gitpod

489
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -10,7 +10,7 @@ license = "MIT"
name = "nu"
readme = "README.md"
repository = "https://github.com/nushell/nushell"
version = "0.37.0"
version = "0.38.0"
[workspace]
members = ["crates/*/"]
@ -18,34 +18,34 @@ members = ["crates/*/"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
nu-cli = { version = "0.37.0", path="./crates/nu-cli", default-features=false }
nu-command = { version = "0.37.0", path="./crates/nu-command" }
nu-completion = { version = "0.37.0", path="./crates/nu-completion" }
nu-data = { version = "0.37.0", path="./crates/nu-data" }
nu-engine = { version = "0.37.0", path="./crates/nu-engine" }
nu-errors = { version = "0.37.0", path="./crates/nu-errors" }
nu-parser = { version = "0.37.0", path="./crates/nu-parser" }
nu-path = { version = "0.37.0", path="./crates/nu-path" }
nu-plugin = { version = "0.37.0", path="./crates/nu-plugin" }
nu-protocol = { version = "0.37.0", path="./crates/nu-protocol" }
nu-source = { version = "0.37.0", path="./crates/nu-source" }
nu-value-ext = { version = "0.37.0", path="./crates/nu-value-ext" }
nu-cli = { version = "0.38.0", path="./crates/nu-cli", default-features=false }
nu-command = { version = "0.38.0", path="./crates/nu-command" }
nu-completion = { version = "0.38.0", path="./crates/nu-completion" }
nu-data = { version = "0.38.0", path="./crates/nu-data" }
nu-engine = { version = "0.38.0", path="./crates/nu-engine" }
nu-errors = { version = "0.38.0", path="./crates/nu-errors" }
nu-parser = { version = "0.38.0", path="./crates/nu-parser" }
nu-path = { version = "0.38.0", path="./crates/nu-path" }
nu-plugin = { version = "0.38.0", path="./crates/nu-plugin" }
nu-protocol = { version = "0.38.0", path="./crates/nu-protocol" }
nu-source = { version = "0.38.0", path="./crates/nu-source" }
nu-value-ext = { version = "0.38.0", path="./crates/nu-value-ext" }
nu_plugin_binaryview = { version = "0.37.0", path="./crates/nu_plugin_binaryview", optional=true }
nu_plugin_chart = { version = "0.37.0", path="./crates/nu_plugin_chart", optional=true }
nu_plugin_from_bson = { version = "0.37.0", path="./crates/nu_plugin_from_bson", optional=true }
nu_plugin_from_sqlite = { version = "0.37.0", path="./crates/nu_plugin_from_sqlite", optional=true }
nu_plugin_inc = { version = "0.37.0", path="./crates/nu_plugin_inc", optional=true }
nu_plugin_match = { version = "0.37.0", path="./crates/nu_plugin_match", optional=true }
nu_plugin_query_json = { version = "0.37.0", path="./crates/nu_plugin_query_json", optional=true }
nu_plugin_s3 = { version = "0.37.0", path="./crates/nu_plugin_s3", optional=true }
nu_plugin_selector = { version = "0.37.0", path="./crates/nu_plugin_selector", optional=true }
nu_plugin_start = { version = "0.37.0", path="./crates/nu_plugin_start", optional=true }
nu_plugin_textview = { version = "0.37.0", path="./crates/nu_plugin_textview", optional=true }
nu_plugin_to_bson = { version = "0.37.0", path="./crates/nu_plugin_to_bson", optional=true }
nu_plugin_to_sqlite = { version = "0.37.0", path="./crates/nu_plugin_to_sqlite", optional=true }
nu_plugin_tree = { version = "0.37.0", path="./crates/nu_plugin_tree", optional=true }
nu_plugin_xpath = { version = "0.37.0", path="./crates/nu_plugin_xpath", optional=true }
nu_plugin_binaryview = { version = "0.38.0", path="./crates/nu_plugin_binaryview", optional=true }
nu_plugin_chart = { version = "0.38.0", path="./crates/nu_plugin_chart", optional=true }
nu_plugin_from_bson = { version = "0.38.0", path="./crates/nu_plugin_from_bson", optional=true }
nu_plugin_from_sqlite = { version = "0.38.0", path="./crates/nu_plugin_from_sqlite", optional=true }
nu_plugin_inc = { version = "0.38.0", path="./crates/nu_plugin_inc", optional=true }
nu_plugin_match = { version = "0.38.0", path="./crates/nu_plugin_match", optional=true }
nu_plugin_query_json = { version = "0.38.0", path="./crates/nu_plugin_query_json", optional=true }
nu_plugin_s3 = { version = "0.38.0", path="./crates/nu_plugin_s3", optional=true }
nu_plugin_selector = { version = "0.38.0", path="./crates/nu_plugin_selector", optional=true }
nu_plugin_start = { version = "0.38.0", path="./crates/nu_plugin_start", optional=true }
nu_plugin_textview = { version = "0.38.0", path="./crates/nu_plugin_textview", optional=true }
nu_plugin_to_bson = { version = "0.38.0", path="./crates/nu_plugin_to_bson", optional=true }
nu_plugin_to_sqlite = { version = "0.38.0", path="./crates/nu_plugin_to_sqlite", optional=true }
nu_plugin_tree = { version = "0.38.0", path="./crates/nu_plugin_tree", optional=true }
nu_plugin_xpath = { version = "0.38.0", path="./crates/nu_plugin_xpath", optional=true }
# Required to bootstrap the main binary
ctrlc = { version="3.1.7", optional=true }
@ -53,7 +53,7 @@ futures = { version="0.3.12", features=["compat", "io-compat"] }
itertools = "0.10.0"
[dev-dependencies]
nu-test-support = { version = "0.37.0", path="./crates/nu-test-support" }
nu-test-support = { version = "0.38.0", path="./crates/nu-test-support" }
serial_test = "0.5.1"
hamcrest2 = "0.3.0"
rstest = "0.10.0"
@ -127,9 +127,6 @@ tree = ["nu_plugin_tree"]
xpath = ["nu_plugin_xpath"]
zip-support = ["nu-command/zip"]
#This is disabled in extra for now
table-pager = ["nu-command/table-pager"]
#dataframe feature for nushell
dataframe = [
"nu-engine/dataframe",
@ -141,7 +138,7 @@ dataframe = [
]
[profile.release]
opt-level = "z" # Optimize for size.
opt-level = "s" # Optimize for size.
# Core plugins that ship with `cargo install nu` by default
# Currently, Cargo limits us to installing only one binary

View File

@ -76,53 +76,6 @@ You can also build Nu yourself with all the bells and whistles (be sure to have
```shell
cargo build --workspace --features=extra
```
### Docker
#### Quickstart
Want to try Nu right away? Execute the following to get started.
```shell
docker run -it quay.io/nushell/nu:latest
```
#### Guide
If you want to pull a pre-built container, you can browse tags for the [nushell organization](https://quay.io/organization/nushell)
on Quay.io. Pulling a container would come down to:
```shell
docker pull quay.io/nushell/nu
docker pull quay.io/nushell/nu-base
```
Both "nu-base" and "nu" provide the nu binary, however, nu-base also includes the source code at `/code`
in the container and all dependencies.
Optionally, you can also build the containers locally using the [dockerfiles provided](docker):
To build the base image:
```shell
docker build -f docker/Dockerfile.nu-base -t nushell/nu-base .
```
And then to build the smaller container (using a Multistage build):
```shell
docker build -f docker/Dockerfile -t nushell/nu .
```
Either way, you can run either container as follows:
```shell
docker run -it nushell/nu-base
docker run -it nushell/nu
/> exit
```
The second container is a bit smaller if the size is important to you.
### Packaging status
[![Packaging status](https://repology.org/badge/vertical-allrepos/nushell.svg)](https://repology.org/project/nushell/versions)

View File

@ -9,7 +9,7 @@ description = "Library for ANSI terminal colors and styles (bold, underline)"
edition = "2018"
license = "MIT"
name = "nu-ansi-term"
version = "0.37.0"
version = "0.38.0"
[lib]
doctest = false
@ -21,7 +21,6 @@ derive_serde_style = ["serde"]
[dependencies]
overload = "0.1.1"
serde = { version="1.0.90", features=["derive"], optional=true }
itertools = "0.10.0"
# [dependencies.serde]
# version = "1.0.90"

View File

@ -4,23 +4,24 @@ description = "CLI for nushell"
edition = "2018"
license = "MIT"
name = "nu-cli"
version = "0.37.0"
version = "0.38.0"
build = "build.rs"
[lib]
doctest = false
[dependencies]
nu-completion = { version = "0.37.0", path="../nu-completion" }
nu-command = { version = "0.37.0", path="../nu-command" }
nu-data = { version = "0.37.0", path="../nu-data" }
nu-engine = { version = "0.37.0", path="../nu-engine" }
nu-errors = { version = "0.37.0", path="../nu-errors" }
nu-parser = { version = "0.37.0", path="../nu-parser" }
nu-protocol = { version = "0.37.0", path="../nu-protocol" }
nu-source = { version = "0.37.0", path="../nu-source" }
nu-stream = { version = "0.37.0", path="../nu-stream" }
nu-ansi-term = { version = "0.37.0", path="../nu-ansi-term" }
nu-completion = { version = "0.38.0", path="../nu-completion" }
nu-command = { version = "0.38.0", path="../nu-command" }
nu-data = { version = "0.38.0", path="../nu-data" }
nu-engine = { version = "0.38.0", path="../nu-engine" }
nu-errors = { version = "0.38.0", path="../nu-errors" }
nu-parser = { version = "0.38.0", path="../nu-parser" }
nu-protocol = { version = "0.38.0", path="../nu-protocol" }
nu-source = { version = "0.38.0", path="../nu-source" }
nu-stream = { version = "0.38.0", path="../nu-stream" }
nu-ansi-term = { version = "0.38.0", path="../nu-ansi-term" }
nu-path = { version = "0.38.0", path="../nu-path" }
indexmap ="1.6.1"
log = "0.4.14"

View File

@ -24,6 +24,7 @@ use rustyline::{self, error::ReadlineError};
use nu_errors::ShellError;
use nu_parser::ParserScope;
use nu_path::expand_tilde;
use nu_protocol::{hir::ExternalRedirection, ConfigPath, UntaggedValue, Value};
use log::trace;
@ -54,7 +55,7 @@ pub fn search_paths() -> Vec<std::path::PathBuf> {
{
for pipeline in pipelines {
if let Ok(plugin_dir) = pipeline.as_string() {
search_paths.push(PathBuf::from(plugin_dir));
search_paths.push(expand_tilde(plugin_dir));
}
}
}

View File

@ -5,28 +5,28 @@ description = "CLI for nushell"
edition = "2018"
license = "MIT"
name = "nu-command"
version = "0.37.0"
version = "0.38.0"
[lib]
doctest = false
[dependencies]
nu-data = { version = "0.37.0", path="../nu-data" }
nu-engine = { version = "0.37.0", path="../nu-engine" }
nu-errors = { version = "0.37.0", path="../nu-errors" }
nu-json = { version = "0.37.0", path="../nu-json" }
nu-path = { version = "0.37.0", path="../nu-path" }
nu-parser = { version = "0.37.0", path="../nu-parser" }
nu-plugin = { version = "0.37.0", path="../nu-plugin" }
nu-protocol = { version = "0.37.0", path="../nu-protocol" }
nu-serde = { version = "0.37.0", path="../nu-serde" }
nu-source = { version = "0.37.0", path="../nu-source" }
nu-stream = { version = "0.37.0", path="../nu-stream" }
nu-table = { version = "0.37.0", path="../nu-table" }
nu-test-support = { version = "0.37.0", path="../nu-test-support" }
nu-value-ext = { version = "0.37.0", path="../nu-value-ext" }
nu-ansi-term = { version = "0.37.0", path="../nu-ansi-term" }
nu-pretty-hex = { version = "0.37.0", path="../nu-pretty-hex" }
nu-data = { version = "0.38.0", path="../nu-data" }
nu-engine = { version = "0.38.0", path="../nu-engine" }
nu-errors = { version = "0.38.0", path="../nu-errors" }
nu-json = { version = "0.38.0", path="../nu-json" }
nu-path = { version = "0.38.0", path="../nu-path" }
nu-parser = { version = "0.38.0", path="../nu-parser" }
nu-plugin = { version = "0.38.0", path="../nu-plugin" }
nu-protocol = { version = "0.38.0", path="../nu-protocol" }
nu-serde = { version = "0.38.0", path="../nu-serde" }
nu-source = { version = "0.38.0", path="../nu-source" }
nu-stream = { version = "0.38.0", path="../nu-stream" }
nu-table = { version = "0.38.0", path="../nu-table" }
nu-test-support = { version = "0.38.0", path="../nu-test-support" }
nu-value-ext = { version = "0.38.0", path="../nu-value-ext" }
nu-ansi-term = { version = "0.38.0", path="../nu-ansi-term" }
nu-pretty-hex = { version = "0.38.0", path="../nu-pretty-hex" }
url = "2.2.1"
mime = "0.3.16"
@ -34,25 +34,19 @@ Inflector = "0.11"
arboard = { version="1.1.0", optional=true }
base64 = "0.13.0"
bigdecimal = { package = "bigdecimal-rs", version = "0.2.1", features = ["serde"] }
byte-unit = "4.0.9"
bytes = "1.0.1"
calamine = "0.18.0"
chrono = { version="0.4.19", features=["serde"] }
chrono-tz = "0.5.3"
codespan-reporting = "0.11.0"
crossterm = { version="0.19.0", optional=true }
csv = "1.1.3"
ctrlc = { version="3.1.7", optional=true }
derive-new = "0.5.8"
directories-next = "2.0.0"
dirs-next = "2.0.0"
dtparse = "1.2.0"
eml-parser = "0.1.0"
encoding_rs = "0.8.28"
filesize = "0.2.0"
fs_extra = "1.2.0"
futures = { version="0.3.12", features=["compat", "io-compat"] }
getset = "0.1.1"
glob = "0.3.0"
htmlescape = "0.3.1"
ical = "0.7.0"
@ -62,37 +56,28 @@ lazy_static = "1.*"
log = "0.4.14"
md-5 = "0.9.1"
meval = "0.2.0"
minus = { version="3.4.0", optional=true, features=["async_std_lib", "search"] }
num-bigint = { version="0.3.1", features=["serde"] }
num-format = { version="0.4.0", features=["with-num-bigint"] }
num-traits = "0.2.14"
parking_lot = "0.11.1"
pin-utils = "0.1.0"
query_interface = "0.3.5"
quick-xml = "0.22"
rand = "0.8"
rayon = "1.5.0"
regex = "1.4.3"
reqwest = {version = "0.11", optional = true }
roxmltree = "0.14.0"
rust-embed = "5.9.0"
rustyline = { version="9.0.0", optional=true }
serde = { version="1.0.123", features=["derive"] }
serde_bytes = "0.11.5"
serde_ini = "0.2.0"
serde_json = "1.0.61"
serde_urlencoded = "0.7.0"
serde_yaml = "0.8.16"
sha2 = "0.9.3"
strip-ansi-escapes = "0.1.0"
sxd-document = "0.3.2"
sxd-xpath = "0.4.2"
sysinfo = { version = "0.20.2", optional = true }
thiserror = "1.0.26"
tempfile = "3.2.0"
term = { version="0.7.0", optional=true }
term_size = "0.3.2"
termcolor = "1.1.2"
titlecase = "1.1.0"
tokio = { version = "1", features = ["rt-multi-thread"], optional = true }
toml = "0.5.8"
@ -104,9 +89,9 @@ zip = { version="0.5.9", optional=true }
digest = "0.9.0"
[dependencies.polars]
version = "0.15.1"
version = "0.16.0"
optional = true
features = ["parquet", "json", "random", "pivot", "strings", "is_in", "temporal"]
features = ["parquet", "json", "random", "pivot", "strings", "is_in", "temporal", "cum_agg", "rolling_window"]
[target.'cfg(unix)'.dependencies]
umask = "1.0.0"
@ -115,13 +100,8 @@ users = "0.11.0"
# TODO this will be possible with new dependency resolver
# (currently on nightly behind -Zfeatures=itarget):
# https://github.com/rust-lang/cargo/issues/7914
#[target.'cfg(not(windows))'.dependencies]
#num-format = {version = "0.4", features = ["with-system-locale"]}
[dependencies.rusqlite]
features = ["bundled", "blob"]
optional = true
version = "0.25.3"
# [target.'cfg(not(windows))'.dependencies]
# num-format = { version = "0.4", features = ["with-system-locale"] }
[build-dependencies]
shadow-rs = "0.6"
@ -136,9 +116,8 @@ clipboard-cli = ["arboard"]
rustyline-support = ["rustyline"]
stable = []
trash-support = ["trash"]
table-pager = ["minus", "crossterm"]
dataframe = ["nu-protocol/dataframe", "polars"]
fetch = ["reqwest", "tokio"]
post = ["reqwest", "tokio"]
sys = ["sysinfo"]
ps = ["sysinfo"]
ps = ["sysinfo"]

View File

@ -0,0 +1,118 @@
use crate::prelude::*;
use nu_engine::WholeStreamCommand;
use nu_errors::ShellError;
use nu_protocol::{ColumnPath, Primitive, Signature, SyntaxShape, UntaggedValue, Value};
pub struct SubCommand;
impl WholeStreamCommand for SubCommand {
fn name(&self) -> &str {
"into column_path"
}
fn signature(&self) -> Signature {
Signature::build("into column_path").rest(
"rest",
SyntaxShape::ColumnPath,
"values to convert to column_path",
)
}
fn usage(&self) -> &str {
"Convert value to column path"
}
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
into_filepath(args)
}
fn examples(&self) -> Vec<Example> {
vec![
Example {
description: "Convert string to column_path in table",
example: "echo [[name]; ['/dev/null'] ['C:\\Program Files'] ['../../Cargo.toml']] | into column_path name",
result: Some(vec![
UntaggedValue::row(indexmap! {
"name".to_string() => UntaggedValue::column_path("/dev/null", Span::unknown()).into(),
})
.into(),
UntaggedValue::row(indexmap! {
"name".to_string() => UntaggedValue::column_path("C:\\Program Files", Span::unknown()).into(),
})
.into(),
UntaggedValue::row(indexmap! {
"name".to_string() => UntaggedValue::column_path("../../Cargo.toml", Span::unknown()).into(),
})
.into(),
]),
},
Example {
description: "Convert string to column_path",
example: "echo 'Cargo.toml' | into column_path",
result: Some(vec![UntaggedValue::column_path("Cargo.toml", Span::unknown()).into()]),
},
]
}
}
fn into_filepath(args: CommandArgs) -> Result<OutputStream, ShellError> {
let column_paths: Vec<ColumnPath> = args.rest(0)?;
Ok(args
.input
.map(move |v| {
if column_paths.is_empty() {
action(&v, v.tag())
} else {
let mut ret = v;
for path in &column_paths {
ret = ret.swap_data_by_column_path(
path,
Box::new(move |old| action(old, old.tag())),
)?;
}
Ok(ret)
}
})
.into_input_stream())
}
pub fn action(input: &Value, tag: impl Into<Tag>) -> Result<Value, ShellError> {
let tag = tag.into();
match &input.value {
UntaggedValue::Primitive(prim) => Ok(UntaggedValue::column_path(
match prim {
Primitive::String(a_string) => a_string,
_ => {
return Err(ShellError::unimplemented(
"'into column_path' for non-string primitives",
))
}
},
Span::unknown(),
)
.into_value(&tag)),
UntaggedValue::Row(_) => Err(ShellError::labeled_error(
"specify column name to use, with 'into column_path COLUMN'",
"found table",
tag,
)),
_ => Err(ShellError::unimplemented(
"'into column_path' for unsupported type",
)),
}
}
#[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;
test_examples(SubCommand {})
}
}

View File

@ -1,4 +1,5 @@
mod binary;
mod column_path;
mod command;
mod filepath;
mod filesize;
@ -7,6 +8,7 @@ pub mod string;
pub use self::filesize::SubCommand as IntoFilesize;
pub use binary::SubCommand as IntoBinary;
pub use column_path::SubCommand as IntoColumnPath;
pub use command::Command as Into;
pub use filepath::SubCommand as IntoFilepath;
pub use int::SubCommand as IntoInt;

View File

@ -101,17 +101,14 @@ fn if_command(args: CommandArgs) -> Result<OutputStream, ShellError> {
//FIXME: should we use the scope that's brought in as well?
let condition = evaluate_baseline_expr(cond, &context);
match condition {
let result = match condition {
Ok(condition) => match condition.as_bool() {
Ok(b) => {
let result = if b {
if b {
run_block(&then_case.block, &context, input, external_redirection)
} else {
run_block(&else_case.block, &context, input, external_redirection)
};
context.scope.exit_scope();
result
}
}
Err(e) => Ok(OutputStream::from_stream(
vec![UntaggedValue::Error(e).into_untagged_value()].into_iter(),
@ -120,13 +117,16 @@ fn if_command(args: CommandArgs) -> Result<OutputStream, ShellError> {
Err(e) => Ok(OutputStream::from_stream(
vec![UntaggedValue::Error(e).into_untagged_value()].into_iter(),
)),
}
};
context.scope.exit_scope();
result
}
#[cfg(test)]
mod tests {
use super::If;
use super::ShellError;
use nu_test_support::nu;
#[test]
fn examples_work_as_expected() -> Result<(), ShellError> {
@ -134,4 +134,21 @@ mod tests {
test_examples(If {})
}
#[test]
fn if_doesnt_leak_on_error() {
let actual = nu!(
".",
r#"
def test-leak [] {
let var = "hello"
if 0 == "" {echo ok} {echo not}
}
test-leak
echo $var
"#
);
assert!(actual.err.contains("unknown variable"));
}
}

View File

@ -69,13 +69,11 @@ pub fn source(args: CommandArgs) -> Result<OutputStream, ShellError> {
for lib_path in dir {
match lib_path {
Ok(name) => {
let path = canonicalize_with(&source_file, name).map_err(|e| {
ShellError::labeled_error(
format!("Can't load source file. Reason: {}", e.to_string()),
"Can't load this file",
filename.span(),
)
})?;
let path = if let Ok(p) = canonicalize_with(&source_file, name) {
p
} else {
continue;
};
if let Ok(contents) = std::fs::read_to_string(path) {
let result = script::run_script_standalone(contents, true, ctx, false);

View File

@ -166,7 +166,7 @@ This will get the 3rd (note that `nth` is zero-based) row in the table created
by the `ls` command. You can use `nth` on any table created by other commands
as well.
You can also access the column of data in one of two ways. If you want to want
You can also access the column of data in one of two ways. If you want
to keep the column as part of a new table, you can use `select`.
```
ls | select name
@ -274,7 +274,7 @@ This can be helpful if you want to later processes these values.
The `echo` command can pair well with the `each` command which can run
code on each row, or item, of input.
You can continue to learn more about the `echo` command by running:
You can continue to learn more about the `each` command by running:
```
tutor each
```

View File

@ -8,7 +8,7 @@ use nu_protocol::{
};
use nu_source::Tagged;
use polars::prelude::{CsvEncoding, CsvReader, JsonReader, ParquetReader, PolarsError, SerReader};
use polars::prelude::{CsvEncoding, CsvReader, JsonReader, ParquetReader, SerReader};
use std::fs::File;
pub struct DataFrame;
@ -206,15 +206,6 @@ fn from_csv(args: CommandArgs) -> Result<polars::prelude::DataFrame, ShellError>
match csv_reader.finish() {
Ok(df) => Ok(df),
Err(e) => match e {
PolarsError::Other(_) => Err(ShellError::labeled_error_with_secondary(
"Schema error",
"Error with the inferred schema",
&file.tag.span,
"You can use the argument 'infer_schema' with a number of rows large enough to better infer the schema",
&file.tag.span,
)),
_ => Err(parse_polars_error::<&str>(&e, &file.tag.span, None)),
},
Err(e) => Err(parse_polars_error::<&str>(&e, &file.tag.span, None)),
}
}

View File

@ -101,9 +101,9 @@ fn command(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
let cum_type = CumType::from_str(&cum_type.item, &cum_type.tag.span)?;
let mut res = match cum_type {
CumType::Max => series.cum_max(reverse),
CumType::Min => series.cum_min(reverse),
CumType::Sum => series.cum_sum(reverse),
CumType::Max => series.cummax(reverse),
CumType::Min => series.cummin(reverse),
CumType::Sum => series.cumsum(reverse),
};
let name = format!("{}_{}", series.name(), cum_type.to_str());

View File

@ -53,13 +53,12 @@ pub(crate) fn parse_polars_error<T: AsRef<str>>(
PolarsError::DataTypeMisMatch(_) => "Data Type Mismatch",
PolarsError::NotFound(_) => "Not Found",
PolarsError::ShapeMisMatch(_) => "Shape Mismatch",
PolarsError::Other(_) => "Other",
PolarsError::ComputeError(_) => "Computer error",
PolarsError::OutOfBounds(_) => "Out Of Bounds",
PolarsError::NoSlice => "No Slice",
PolarsError::NoData(_) => "No Data",
PolarsError::ValueError(_) => "Value Error",
PolarsError::MemoryNotAligned => "Memory Not Aligned",
PolarsError::ParquetError(_) => "Parquet Error",
PolarsError::RandError(_) => "Rand Error",
PolarsError::HasNullValues(_) => "Has Null Values",
PolarsError::UnknownSchema(_) => "Unknown Schema",

View File

@ -36,6 +36,7 @@ mod skip;
pub(crate) mod sort_by;
mod uniq;
mod update;
mod update_cells;
mod where_;
mod wrap;
mod zip_;
@ -78,6 +79,7 @@ pub use skip::{Skip, SkipUntil, SkipWhile};
pub use sort_by::SortBy;
pub use uniq::Uniq;
pub use update::Command as Update;
pub use update_cells::SubCommand as UpdateCells;
pub use where_::Command as Where;
pub use wrap::Wrap;
pub use zip_::Command as Zip;

View File

@ -15,11 +15,18 @@ impl WholeStreamCommand for Command {
}
fn signature(&self) -> Signature {
Signature::build("select").rest(
"rest",
SyntaxShape::ColumnPath,
"the columns to select from the table",
)
Signature::build("select")
.named(
"columns",
SyntaxShape::Table,
"Optionally operate by column path",
Some('c'),
)
.rest(
"rest",
SyntaxShape::ColumnPath,
"the columns to select from the table",
)
}
fn usage(&self) -> &str {
@ -27,10 +34,10 @@ impl WholeStreamCommand for Command {
}
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
let columns: Vec<ColumnPath> = args.rest(0)?;
let mut columns = args.rest(0)?;
columns.extend(column_paths_from_args(&args)?);
let input = args.input;
let name = args.call_info.name_tag;
select(name, columns, input)
}
@ -46,10 +53,51 @@ impl WholeStreamCommand for Command {
example: "ls | select name size",
result: None,
},
Example {
description: "Select columns dynamically",
example: "[[a b]; [1 2]] | select -c [a]",
result: Some(vec![UntaggedValue::row(indexmap! {
"a".to_string() => UntaggedValue::int(1).into(),
})
.into()]),
},
]
}
}
fn column_paths_from_args(args: &CommandArgs) -> Result<Vec<ColumnPath>, ShellError> {
let column_paths: Option<Vec<Value>> = args.get_flag("columns")?;
let has_columns = column_paths.is_some();
let column_paths = match column_paths {
Some(cols) => {
let mut c = Vec::new();
for col in cols {
let colpath = ColumnPath::build(&col.convert_to_string().spanned_unknown());
if !colpath.is_empty() {
c.push(colpath)
}
}
c
}
None => Vec::new(),
};
if has_columns && column_paths.is_empty() {
let colval: Option<Value> = args.get_flag("columns")?;
let colspan = match colval {
Some(v) => v.tag.span,
None => Span::unknown(),
};
return Err(ShellError::labeled_error(
"Requires a list of columns",
"must be a list of columns",
colspan,
));
}
Ok(column_paths)
}
fn select(
name: Tag,
columns: Vec<ColumnPath>,

View File

@ -0,0 +1,211 @@
use crate::prelude::*;
use nu_engine::run_block;
use nu_engine::WholeStreamCommand;
use nu_errors::ShellError;
use nu_protocol::{
hir::{CapturedBlock, ExternalRedirection},
Signature, SyntaxShape, TaggedDictBuilder, UntaggedValue, Value,
};
use std::collections::HashSet;
use std::iter::FromIterator;
pub struct SubCommand;
impl WholeStreamCommand for SubCommand {
fn name(&self) -> &str {
"update cells"
}
fn signature(&self) -> Signature {
Signature::build("update cells")
.required(
"block",
SyntaxShape::Block,
"the block to run an update for each cell",
)
.named(
"columns",
SyntaxShape::Table,
"list of columns to update",
Some('c'),
)
}
fn usage(&self) -> &str {
"Update the table cells."
}
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
update_cells(args)
}
fn examples(&self) -> Vec<Example> {
vec![
Example {
description: "Update the zero value cells to empty strings.",
example: r#"[
[2021-04-16, 2021-06-10, 2021-09-18, 2021-10-15, 2021-11-16, 2021-11-17, 2021-11-18];
[ 37, 0, 0, 0, 37, 0, 0]
] | update cells {|value|
if ($value | into int) == 0 {
""
} {
$value
}
}"#,
result: Some(vec![UntaggedValue::row(indexmap! {
"2021-04-16".to_string() => UntaggedValue::int(37).into(),
"2021-06-10".to_string() => Value::from(""),
"2021-09-18".to_string() => Value::from(""),
"2021-10-15".to_string() => Value::from(""),
"2021-11-16".to_string() => UntaggedValue::int(37).into(),
"2021-11-17".to_string() => Value::from(""),
"2021-11-18".to_string() => Value::from(""),
})
.into()]),
},
Example {
description: "Update the zero value cells to empty strings in 2 last columns.",
example: r#"[
[2021-04-16, 2021-06-10, 2021-09-18, 2021-10-15, 2021-11-16, 2021-11-17, 2021-11-18];
[ 37, 0, 0, 0, 37, 0, 0]
] | update cells -c ["2021-11-18", "2021-11-17"] {|value|
if ($value | into int) == 0 {
""
} {
$value
}
}"#,
result: Some(vec![UntaggedValue::row(indexmap! {
"2021-04-16".to_string() => UntaggedValue::int(37).into(),
"2021-06-10".to_string() => UntaggedValue::int(0).into(),
"2021-09-18".to_string() => UntaggedValue::int(0).into(),
"2021-10-15".to_string() => UntaggedValue::int(0).into(),
"2021-11-16".to_string() => UntaggedValue::int(37).into(),
"2021-11-17".to_string() => Value::from(""),
"2021-11-18".to_string() => Value::from(""),
})
.into()]),
},
]
}
}
fn update_cells(args: CommandArgs) -> Result<OutputStream, ShellError> {
let context = Arc::new(args.context.clone());
let external_redirection = args.call_info.args.external_redirection;
let block: CapturedBlock = args.req(0)?;
let block = Arc::new(block);
let columns = args
.get_flag("columns")?
.map(|x: Value| HashSet::from_iter(x.table_entries().map(|val| val.convert_to_string())));
let columns = Arc::new(columns);
Ok(args
.input
.flat_map(move |input| {
let block = block.clone();
let context = context.clone();
if input.is_row() {
OutputStream::one(process_cells(
block,
columns.clone(),
context,
input,
external_redirection,
))
} else {
match process_input(block, context, input, external_redirection) {
Ok(s) => s,
Err(e) => OutputStream::one(Value::error(e)),
}
}
})
.into_output_stream())
}
pub fn process_input(
captured_block: Arc<CapturedBlock>,
context: Arc<EvaluationContext>,
input: Value,
external_redirection: ExternalRedirection,
) -> Result<OutputStream, ShellError> {
let input_clone = input.clone();
// When we process a row, we need to know whether the block wants to have the contents of the row as
// a parameter to the block (so it gets assigned to a variable that can be used inside the block) or
// if it wants the contents as as an input stream
let input_stream = if !captured_block.block.params.positional.is_empty() {
InputStream::empty()
} else {
vec![Ok(input_clone)].into_iter().into_input_stream()
};
context.scope.enter_scope();
context.scope.add_vars(&captured_block.captured.entries);
if let Some((arg, _)) = captured_block.block.params.positional.first() {
context.scope.add_var(arg.name(), input);
} else {
context.scope.add_var("$it", input);
}
let result = run_block(
&captured_block.block,
&context,
input_stream,
external_redirection,
);
context.scope.exit_scope();
result
}
pub fn process_cells(
captured_block: Arc<CapturedBlock>,
columns: Arc<Option<HashSet<String>>>,
context: Arc<EvaluationContext>,
input: Value,
external_redirection: ExternalRedirection,
) -> Value {
TaggedDictBuilder::build(input.tag(), |row| {
input.row_entries().for_each(|(column, cell_value)| {
match &*columns {
Some(col) if !col.contains(column) => {
row.insert_value(column, cell_value.clone());
return;
}
_ => {}
};
let cell_processed = process_input(
captured_block.clone(),
context.clone(),
cell_value.clone(),
external_redirection,
)
.map(|it| it.into_vec())
.map_err(Value::error);
match cell_processed {
Ok(value) => {
match value.get(0) {
Some(one) => {
row.insert_value(column, one.clone());
}
None => {
row.insert_untagged(column, UntaggedValue::nothing());
}
};
}
Err(reason) => {
row.insert_value(column, reason);
}
}
});
})
}

View File

@ -136,7 +136,8 @@ fn to_string_tagged_value(v: &Value) -> Result<String, ShellError> {
| Primitive::Boolean(_)
| Primitive::Decimal(_)
| Primitive::FilePath(_)
| Primitive::Int(_),
| Primitive::Int(_)
| Primitive::BigInt(_),
) => as_string(v),
UntaggedValue::Primitive(Primitive::Date(d)) => Ok(d.to_string()),
UntaggedValue::Primitive(Primitive::Nothing) => Ok(String::new()),

View File

@ -112,7 +112,11 @@ mod tests {
fn only_examples() -> Vec<Command> {
let mut commands = full_tests();
commands.extend([whole_stream_command(Zip), whole_stream_command(Flatten)]);
commands.extend([
whole_stream_command(UpdateCells),
whole_stream_command(Zip),
whole_stream_command(Flatten),
]);
commands
}

View File

@ -1,4 +1,4 @@
use super::{operate, PathSubcommandArguments};
use super::{column_paths_from_args, operate, PathSubcommandArguments};
use crate::prelude::*;
use nu_engine::WholeStreamCommand;
use nu_errors::ShellError;
@ -9,13 +9,13 @@ use std::path::Path;
pub struct PathBasename;
struct PathBasenameArguments {
rest: Vec<ColumnPath>,
columns: Vec<ColumnPath>,
replace: Option<Tagged<String>>,
}
impl PathSubcommandArguments for PathBasenameArguments {
fn get_column_paths(&self) -> &Vec<ColumnPath> {
&self.rest
&self.columns
}
}
@ -26,10 +26,11 @@ impl WholeStreamCommand for PathBasename {
fn signature(&self) -> Signature {
Signature::build("path basename")
.rest(
"rest",
SyntaxShape::ColumnPath,
.named(
"columns",
SyntaxShape::Table,
"Optionally operate by column path",
Some('c'),
)
.named(
"replace",
@ -46,7 +47,7 @@ impl WholeStreamCommand for PathBasename {
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
let tag = args.call_info.name_tag.clone();
let cmd_args = Arc::new(PathBasenameArguments {
rest: args.rest(0)?,
columns: column_paths_from_args(&args)?,
replace: args.get_flag("replace")?,
});
@ -58,12 +59,17 @@ impl WholeStreamCommand for PathBasename {
vec![
Example {
description: "Get basename of a path",
example: "echo 'C:\\Users\\joe\\test.txt' | path basename",
example: "'C:\\Users\\joe\\test.txt' | path basename",
result: Some(vec![Value::from("test.txt")]),
},
Example {
description: "Get basename of a path in a column",
example: "ls .. | path basename -c [ name ]",
result: None,
},
Example {
description: "Replace basename of a path",
example: "echo 'C:\\Users\\joe\\test.txt' | path basename -r 'spam.png'",
example: "'C:\\Users\\joe\\test.txt' | path basename -r 'spam.png'",
result: Some(vec![Value::from(UntaggedValue::filepath(
"C:\\Users\\joe\\spam.png",
))]),
@ -76,12 +82,17 @@ impl WholeStreamCommand for PathBasename {
vec![
Example {
description: "Get basename of a path",
example: "echo '/home/joe/test.txt' | path basename",
example: "'/home/joe/test.txt' | path basename",
result: Some(vec![Value::from("test.txt")]),
},
Example {
description: "Get basename of a path in a column",
example: "ls .. | path basename -c [ name ]",
result: None,
},
Example {
description: "Replace basename of a path",
example: "echo '/home/joe/test.txt' | path basename -r 'spam.png'",
example: "'/home/joe/test.txt' | path basename -r 'spam.png'",
result: Some(vec![Value::from(UntaggedValue::filepath(
"/home/joe/spam.png",
))]),

View File

@ -1,4 +1,4 @@
use super::{operate, PathSubcommandArguments};
use super::{column_paths_from_args, operate, PathSubcommandArguments};
use crate::prelude::*;
use nu_engine::WholeStreamCommand;
use nu_errors::ShellError;
@ -9,14 +9,14 @@ use std::path::Path;
pub struct PathDirname;
struct PathDirnameArguments {
rest: Vec<ColumnPath>,
columns: Vec<ColumnPath>,
replace: Option<Tagged<String>>,
num_levels: Option<Tagged<u32>>,
}
impl PathSubcommandArguments for PathDirnameArguments {
fn get_column_paths(&self) -> &Vec<ColumnPath> {
&self.rest
&self.columns
}
}
@ -27,10 +27,11 @@ impl WholeStreamCommand for PathDirname {
fn signature(&self) -> Signature {
Signature::build("path dirname")
.rest(
"rest",
SyntaxShape::ColumnPath,
.named(
"columns",
SyntaxShape::Table,
"Optionally operate by column path",
Some('c'),
)
.named(
"replace",
@ -53,7 +54,7 @@ impl WholeStreamCommand for PathDirname {
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
let tag = args.call_info.name_tag.clone();
let cmd_args = Arc::new(PathDirnameArguments {
rest: args.rest(0)?,
columns: column_paths_from_args(&args)?,
replace: args.get_flag("replace")?,
num_levels: args.get_flag("num-levels")?,
});
@ -66,20 +67,25 @@ impl WholeStreamCommand for PathDirname {
vec![
Example {
description: "Get dirname of a path",
example: "echo 'C:\\Users\\joe\\code\\test.txt' | path dirname",
example: "'C:\\Users\\joe\\code\\test.txt' | path dirname",
result: Some(vec![Value::from(UntaggedValue::filepath(
"C:\\Users\\joe\\code",
))]),
},
Example {
description: "Get dirname of a path in a column",
example: "ls ('.' | path expand) | path dirname -c [ name ]",
result: None,
},
Example {
description: "Walk up two levels",
example: "echo 'C:\\Users\\joe\\code\\test.txt' | path dirname -n 2",
example: "'C:\\Users\\joe\\code\\test.txt' | path dirname -n 2",
result: Some(vec![Value::from(UntaggedValue::filepath("C:\\Users\\joe"))]),
},
Example {
description: "Replace the part that would be returned with a custom path",
example:
"echo 'C:\\Users\\joe\\code\\test.txt' | path dirname -n 2 -r C:\\Users\\viking",
"'C:\\Users\\joe\\code\\test.txt' | path dirname -n 2 -r C:\\Users\\viking",
result: Some(vec![Value::from(UntaggedValue::filepath(
"C:\\Users\\viking\\code\\test.txt",
))]),
@ -92,17 +98,22 @@ impl WholeStreamCommand for PathDirname {
vec![
Example {
description: "Get dirname of a path",
example: "echo '/home/joe/code/test.txt' | path dirname",
example: "'/home/joe/code/test.txt' | path dirname",
result: Some(vec![Value::from(UntaggedValue::filepath("/home/joe/code"))]),
},
Example {
description: "Get dirname of a path in a column",
example: "ls ('.' | path expand) | path dirname -c [ name ]",
result: None,
},
Example {
description: "Walk up two levels",
example: "echo '/home/joe/code/test.txt' | path dirname -n 2",
example: "'/home/joe/code/test.txt' | path dirname -n 2",
result: Some(vec![Value::from(UntaggedValue::filepath("/home/joe"))]),
},
Example {
description: "Replace the part that would be returned with a custom path",
example: "echo '/home/joe/code/test.txt' | path dirname -n 2 -r /home/viking",
example: "'/home/joe/code/test.txt' | path dirname -n 2 -r /home/viking",
result: Some(vec![Value::from(UntaggedValue::filepath(
"/home/viking/code/test.txt",
))]),

View File

@ -1,4 +1,4 @@
use super::{operate, PathSubcommandArguments};
use super::{column_paths_from_args, operate, PathSubcommandArguments};
use crate::prelude::*;
use nu_engine::WholeStreamCommand;
use nu_errors::ShellError;
@ -8,12 +8,12 @@ use std::path::Path;
pub struct PathExists;
struct PathExistsArguments {
rest: Vec<ColumnPath>,
columns: Vec<ColumnPath>,
}
impl PathSubcommandArguments for PathExistsArguments {
fn get_column_paths(&self) -> &Vec<ColumnPath> {
&self.rest
&self.columns
}
}
@ -23,10 +23,11 @@ impl WholeStreamCommand for PathExists {
}
fn signature(&self) -> Signature {
Signature::build("path exists").rest(
"rest",
SyntaxShape::ColumnPath,
Signature::build("path exists").named(
"columns",
SyntaxShape::Table,
"Optionally operate by column path",
Some('c'),
)
}
@ -37,7 +38,7 @@ impl WholeStreamCommand for PathExists {
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
let tag = args.call_info.name_tag.clone();
let cmd_args = Arc::new(PathExistsArguments {
rest: args.rest(0)?,
columns: column_paths_from_args(&args)?,
});
Ok(operate(args.input, &action, tag.span, cmd_args))
@ -45,20 +46,34 @@ impl WholeStreamCommand for PathExists {
#[cfg(windows)]
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Check if a file exists",
example: "echo 'C:\\Users\\joe\\todo.txt' | path exists",
result: Some(vec![Value::from(UntaggedValue::boolean(false))]),
}]
vec![
Example {
description: "Check if a file exists",
example: "'C:\\Users\\joe\\todo.txt' | path exists",
result: Some(vec![Value::from(UntaggedValue::boolean(false))]),
},
Example {
description: "Check if a file exists in a column",
example: "ls | path exists -c [ name ]",
result: None,
},
]
}
#[cfg(not(windows))]
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Check if a file exists",
example: "echo '/home/joe/todo.txt' | path exists",
result: Some(vec![Value::from(UntaggedValue::boolean(false))]),
}]
vec![
Example {
description: "Check if a file exists",
example: "'/home/joe/todo.txt' | path exists",
result: Some(vec![Value::from(UntaggedValue::boolean(false))]),
},
Example {
description: "Check if a file exists in a column",
example: "ls | path exists -c [ name ]",
result: None,
},
]
}
}

View File

@ -1,4 +1,4 @@
use super::{operate, PathSubcommandArguments};
use super::{column_paths_from_args, operate, PathSubcommandArguments};
use crate::prelude::*;
use nu_engine::WholeStreamCommand;
use nu_errors::ShellError;
@ -11,12 +11,12 @@ pub struct PathExpand;
struct PathExpandArguments {
strict: bool,
rest: Vec<ColumnPath>,
columns: Vec<ColumnPath>,
}
impl PathSubcommandArguments for PathExpandArguments {
fn get_column_paths(&self) -> &Vec<ColumnPath> {
&self.rest
&self.columns
}
}
@ -32,10 +32,11 @@ impl WholeStreamCommand for PathExpand {
"Throw an error if the path could not be expanded",
Some('s'),
)
.rest(
"rest",
SyntaxShape::ColumnPath,
.named(
"columns",
SyntaxShape::Table,
"Optionally operate by column path",
Some('c'),
)
}
@ -47,7 +48,7 @@ impl WholeStreamCommand for PathExpand {
let tag = args.call_info.name_tag.clone();
let cmd_args = Arc::new(PathExpandArguments {
strict: args.has_flag("strict"),
rest: args.rest(0)?,
columns: column_paths_from_args(&args)?,
});
Ok(operate(args.input, &action, tag.span, cmd_args))
@ -63,6 +64,11 @@ impl WholeStreamCommand for PathExpand {
UntaggedValue::filepath(r"C:\Users\joe\bar").into_value(Span::new(0, 25))
]),
},
Example {
description: "Expand a path in a column",
example: "ls | path expand -c [ name ]",
result: None,
},
Example {
description: "Expand a relative path",
example: r"'foo\..\bar' | path expand",
@ -83,6 +89,11 @@ impl WholeStreamCommand for PathExpand {
UntaggedValue::filepath("/home/joe/bar").into_value(Span::new(0, 22))
]),
},
Example {
description: "Expand a path in a column",
example: "ls | path expand -c [ name ]",
result: None,
},
Example {
description: "Expand a relative path",
example: "'foo/../bar' | path expand",

View File

@ -1,4 +1,6 @@
use super::{handle_value, join_path, operate_column_paths, PathSubcommandArguments};
use super::{
column_paths_from_args, handle_value, join_path, operate_column_paths, PathSubcommandArguments,
};
use crate::prelude::*;
use nu_engine::WholeStreamCommand;
use nu_errors::ShellError;
@ -9,13 +11,13 @@ use std::path::{Path, PathBuf};
pub struct PathJoin;
struct PathJoinArguments {
rest: Vec<ColumnPath>,
columns: Vec<ColumnPath>,
append: Option<Tagged<PathBuf>>,
}
impl PathSubcommandArguments for PathJoinArguments {
fn get_column_paths(&self) -> &Vec<ColumnPath> {
&self.rest
&self.columns
}
}
@ -26,16 +28,16 @@ impl WholeStreamCommand for PathJoin {
fn signature(&self) -> Signature {
Signature::build("path join")
.rest(
"rest",
SyntaxShape::ColumnPath,
"Optionally operate by column path",
)
.named(
"columns",
SyntaxShape::Table,
"Optionally operate by column path",
Some('c'),
)
.optional(
"append",
SyntaxShape::FilePath,
"Path to append to the input",
Some('a'),
)
}
@ -50,9 +52,10 @@ the output of 'path parse' and 'path split' subcommands."#
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
let tag = args.call_info.name_tag.clone();
let cmd_args = Arc::new(PathJoinArguments {
rest: args.rest(0)?,
append: args.get_flag("append")?,
columns: column_paths_from_args(&args)?,
append: args.opt(0)?,
});
Ok(operate_join(args.input, &action, tag, cmd_args))
@ -63,21 +66,26 @@ the output of 'path parse' and 'path split' subcommands."#
vec![
Example {
description: "Append a filename to a path",
example: r"echo 'C:\Users\viking' | path join -a spam.txt",
example: r"'C:\Users\viking' | path join spam.txt",
result: Some(vec![Value::from(UntaggedValue::filepath(
r"C:\Users\viking\spam.txt",
))]),
},
Example {
description: "Append a filename to a path inside a column",
example: r"ls | path join spam.txt -c [ name ]",
result: None,
},
Example {
description: "Join a list of parts into a path",
example: r"echo [ 'C:' '\' 'Users' 'viking' 'spam.txt' ] | path join",
example: r"[ 'C:' '\' 'Users' 'viking' 'spam.txt' ] | path join",
result: Some(vec![Value::from(UntaggedValue::filepath(
r"C:\Users\viking\spam.txt",
))]),
},
Example {
description: "Join a structured path into a path",
example: r"echo [ [parent stem extension]; ['C:\Users\viking' 'spam' 'txt']] | path join",
example: r"[ [parent stem extension]; ['C:\Users\viking' 'spam' 'txt']] | path join",
result: Some(vec![Value::from(UntaggedValue::filepath(
r"C:\Users\viking\spam.txt",
))]),
@ -90,21 +98,26 @@ the output of 'path parse' and 'path split' subcommands."#
vec![
Example {
description: "Append a filename to a path",
example: r"echo '/home/viking' | path join -a spam.txt",
example: r"'/home/viking' | path join spam.txt",
result: Some(vec![Value::from(UntaggedValue::filepath(
r"/home/viking/spam.txt",
))]),
},
Example {
description: "Append a filename to a path inside a column",
example: r"ls | path join spam.txt -c [ name ]",
result: None,
},
Example {
description: "Join a list of parts into a path",
example: r"echo [ '/' 'home' 'viking' 'spam.txt' ] | path join",
example: r"[ '/' 'home' 'viking' 'spam.txt' ] | path join",
result: Some(vec![Value::from(UntaggedValue::filepath(
r"/home/viking/spam.txt",
))]),
},
Example {
description: "Join a structured path into a path",
example: r"echo [[ parent stem extension ]; [ '/home/viking' 'spam' 'txt' ]] | path join",
example: r"[[ parent stem extension ]; [ '/home/viking' 'spam' 'txt' ]] | path join",
result: Some(vec![Value::from(UntaggedValue::filepath(
r"/home/viking/spam.txt",
))]),

View File

@ -61,7 +61,7 @@ fn encode_path(
ALLOWED_COLUMNS.join(", ")
);
return Err(ShellError::labeled_error_with_secondary(
"Invalid column name",
"Expected structured path table",
msg,
new_span,
"originates from here",
@ -216,3 +216,36 @@ where
operate_column_paths(input, action, span, args)
}
}
fn column_paths_from_args(args: &CommandArgs) -> Result<Vec<ColumnPath>, ShellError> {
let column_paths: Option<Vec<Value>> = args.get_flag("columns")?;
let has_columns = column_paths.is_some();
let column_paths = match column_paths {
Some(cols) => {
let mut c = Vec::new();
for col in cols {
let colpath = ColumnPath::build(&col.convert_to_string().spanned_unknown());
if !colpath.is_empty() {
c.push(colpath)
}
}
c
}
None => Vec::new(),
};
if has_columns && column_paths.is_empty() {
let colval: Option<Value> = args.get_flag("columns")?;
let colspan = match colval {
Some(v) => v.tag.span,
None => Span::unknown(),
};
return Err(ShellError::labeled_error(
"Requires a list of columns",
"must be a list of columns",
colspan,
));
}
Ok(column_paths)
}

View File

@ -1,4 +1,4 @@
use super::{operate, PathSubcommandArguments};
use super::{column_paths_from_args, operate, PathSubcommandArguments};
use crate::prelude::*;
use nu_engine::WholeStreamCommand;
use nu_errors::ShellError;
@ -11,13 +11,13 @@ use std::path::Path;
pub struct PathParse;
struct PathParseArguments {
rest: Vec<ColumnPath>,
columns: Vec<ColumnPath>,
extension: Option<Tagged<String>>,
}
impl PathSubcommandArguments for PathParseArguments {
fn get_column_paths(&self) -> &Vec<ColumnPath> {
&self.rest
&self.columns
}
}
@ -28,10 +28,11 @@ impl WholeStreamCommand for PathParse {
fn signature(&self) -> Signature {
Signature::build("path parse")
.rest(
"rest",
SyntaxShape::ColumnPath,
.named(
"columns",
SyntaxShape::Table,
"Optionally operate by column path",
Some('c'),
)
.named(
"extension",
@ -53,7 +54,7 @@ On Windows, an extra 'prefix' column is added."#
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
let tag = args.call_info.name_tag.clone();
let cmd_args = Arc::new(PathParseArguments {
rest: args.rest(0)?,
columns: column_paths_from_args(&args)?,
extension: args.get_flag("extension")?,
});
@ -65,22 +66,22 @@ On Windows, an extra 'prefix' column is added."#
vec![
Example {
description: "Parse a single path",
example: r"echo 'C:\Users\viking\spam.txt' | path parse",
example: r"'C:\Users\viking\spam.txt' | path parse",
result: None,
},
Example {
description: "Replace a complex extension",
example: r"echo 'C:\Users\viking\spam.tar.gz' | path parse -e tar.gz | update extension { 'txt' }",
example: r"'C:\Users\viking\spam.tar.gz' | path parse -e tar.gz | update extension { 'txt' }",
result: None,
},
Example {
description: "Ignore the extension",
example: r"echo 'C:\Users\viking.d' | path parse -e ''",
example: r"'C:\Users\viking.d' | path parse -e ''",
result: None,
},
Example {
description: "Parse all paths under the 'name' column",
example: r"ls | path parse name",
example: r"ls | path parse -c [ name ]",
result: None,
},
]
@ -91,22 +92,22 @@ On Windows, an extra 'prefix' column is added."#
vec![
Example {
description: "Parse a path",
example: r"echo '/home/viking/spam.txt' | path parse",
example: r"'/home/viking/spam.txt' | path parse",
result: None,
},
Example {
description: "Replace a complex extension",
example: r"echo '/home/viking/spam.tar.gz' | path parse -e tar.gz | update extension { 'txt' }",
example: r"'/home/viking/spam.tar.gz' | path parse -e tar.gz | update extension { 'txt' }",
result: None,
},
Example {
description: "Ignore the extension",
example: r"echo '/etc/conf.d' | path parse -e ''",
example: r"'/etc/conf.d' | path parse -e ''",
result: None,
},
Example {
description: "Parse all paths under the 'name' column",
example: r"ls | path parse name",
example: r"ls | path parse -c [ name ]",
result: None,
},
]

View File

@ -1,4 +1,4 @@
use super::{operate, PathSubcommandArguments};
use super::{column_paths_from_args, operate, PathSubcommandArguments};
use crate::prelude::*;
use nu_engine::WholeStreamCommand;
use nu_errors::ShellError;
@ -10,12 +10,12 @@ pub struct PathRelativeTo;
struct PathRelativeToArguments {
path: Tagged<PathBuf>,
rest: Vec<ColumnPath>,
columns: Vec<ColumnPath>,
}
impl PathSubcommandArguments for PathRelativeToArguments {
fn get_column_paths(&self) -> &Vec<ColumnPath> {
&self.rest
&self.columns
}
}
@ -31,10 +31,11 @@ impl WholeStreamCommand for PathRelativeTo {
SyntaxShape::FilePath,
"Parent shared with the input path",
)
.rest(
"rest",
SyntaxShape::ColumnPath,
.named(
"columns",
SyntaxShape::Table,
"Optionally operate by column path",
Some('c'),
)
}
@ -52,7 +53,7 @@ path."#
let tag = args.call_info.name_tag.clone();
let cmd_args = Arc::new(PathRelativeToArguments {
path: args.req(0)?,
rest: args.rest(1)?,
columns: column_paths_from_args(&args)?,
});
Ok(operate(args.input, &action, tag.span, cmd_args))
@ -66,6 +67,11 @@ path."#
example: r"'C:\Users\viking' | path relative-to 'C:\Users'",
result: Some(vec![Value::from(UntaggedValue::filepath(r"viking"))]),
},
Example {
description: "Find a relative path from two absolute paths in a column",
example: "ls ~ | path relative-to ~ -c [ name ]",
result: None,
},
Example {
description: "Find a relative path from two relative paths",
example: r"'eggs\bacon\sausage\spam' | path relative-to 'eggs\bacon\sausage'",
@ -82,6 +88,11 @@ path."#
example: r"'/home/viking' | path relative-to '/home'",
result: Some(vec![Value::from(UntaggedValue::filepath(r"viking"))]),
},
Example {
description: "Find a relative path from two absolute paths in a column",
example: "ls ~ | path relative-to ~ -c [ name ]",
result: None,
},
Example {
description: "Find a relative path from two relative paths",
example: r"'eggs/bacon/sausage/spam' | path relative-to 'eggs/bacon/sausage'",

View File

@ -1,4 +1,4 @@
use super::{handle_value, operate_column_paths, PathSubcommandArguments};
use super::{column_paths_from_args, handle_value, operate_column_paths, PathSubcommandArguments};
use crate::prelude::*;
use nu_engine::WholeStreamCommand;
use nu_errors::ShellError;
@ -8,12 +8,12 @@ use std::path::Path;
pub struct PathSplit;
struct PathSplitArguments {
rest: Vec<ColumnPath>,
columns: Vec<ColumnPath>,
}
impl PathSubcommandArguments for PathSplitArguments {
fn get_column_paths(&self) -> &Vec<ColumnPath> {
&self.rest
&self.columns
}
}
@ -23,10 +23,11 @@ impl WholeStreamCommand for PathSplit {
}
fn signature(&self) -> Signature {
Signature::build("path split").rest(
"rest",
SyntaxShape::ColumnPath,
Signature::build("path split").named(
"columns",
SyntaxShape::Table,
"Optionally operate by column path",
Some('c'),
)
}
@ -37,7 +38,7 @@ impl WholeStreamCommand for PathSplit {
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
let tag = args.call_info.name_tag.clone();
let cmd_args = Arc::new(PathSplitArguments {
rest: args.rest(0)?,
columns: column_paths_from_args(&args)?,
});
Ok(operate_split(args.input, &action, tag.span, cmd_args))
@ -48,7 +49,7 @@ impl WholeStreamCommand for PathSplit {
vec![
Example {
description: "Split a path into parts",
example: r"echo 'C:\Users\viking\spam.txt' | path split",
example: r"'C:\Users\viking\spam.txt' | path split",
result: Some(vec![
Value::from(UntaggedValue::string("C:")),
Value::from(UntaggedValue::string(r"\")),
@ -59,7 +60,7 @@ impl WholeStreamCommand for PathSplit {
},
Example {
description: "Split all paths under the 'name' column",
example: r"ls | path split name",
example: r"ls ('.' | path expand) | path split -c [ name ]",
result: None,
},
]
@ -70,7 +71,7 @@ impl WholeStreamCommand for PathSplit {
vec![
Example {
description: "Split a path into parts",
example: r"echo '/home/viking/spam.txt' | path split",
example: r"'/home/viking/spam.txt' | path split",
result: Some(vec![
Value::from(UntaggedValue::string("/")),
Value::from(UntaggedValue::string("home")),
@ -80,7 +81,7 @@ impl WholeStreamCommand for PathSplit {
},
Example {
description: "Split all paths under the 'name' column",
example: r"ls | path split name",
example: r"ls ('.' | path expand) | path split -c [ name ]",
result: None,
},
]

View File

@ -1,4 +1,4 @@
use super::{operate, PathSubcommandArguments};
use super::{column_paths_from_args, operate, PathSubcommandArguments};
use crate::prelude::*;
use nu_engine::filesystem::filesystem_shell::get_file_type;
use nu_engine::WholeStreamCommand;
@ -9,12 +9,12 @@ use std::path::Path;
pub struct PathType;
struct PathTypeArguments {
rest: Vec<ColumnPath>,
columns: Vec<ColumnPath>,
}
impl PathSubcommandArguments for PathTypeArguments {
fn get_column_paths(&self) -> &Vec<ColumnPath> {
&self.rest
&self.columns
}
}
@ -24,10 +24,11 @@ impl WholeStreamCommand for PathType {
}
fn signature(&self) -> Signature {
Signature::build("path type").rest(
"rest",
SyntaxShape::ColumnPath,
Signature::build("path type").named(
"columns",
SyntaxShape::Table,
"Optionally operate by column path",
Some('c'),
)
}
@ -38,18 +39,25 @@ impl WholeStreamCommand for PathType {
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
let tag = args.call_info.name_tag.clone();
let cmd_args = Arc::new(PathTypeArguments {
rest: args.rest(0)?,
columns: column_paths_from_args(&args)?,
});
Ok(operate(args.input, &action, tag.span, cmd_args))
}
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Show type of a filepath",
example: "echo '.' | path type",
result: Some(vec![Value::from("Dir")]),
}]
vec![
Example {
description: "Show type of a filepath",
example: "'.' | path type",
result: Some(vec![Value::from("Dir")]),
},
Example {
description: "Show type of a filepath in a column",
example: "ls | path type -c [ name ]",
result: None,
},
]
}
}

View File

@ -0,0 +1,51 @@
use crate::prelude::*;
use nu_engine::WholeStreamCommand;
use nu_errors::ShellError;
use nu_protocol::{CommandAction, ReturnSuccess, Signature, SyntaxShape};
pub struct Goto;
impl WholeStreamCommand for Goto {
fn name(&self) -> &str {
"g"
}
fn signature(&self) -> Signature {
Signature::build("g").required("index", SyntaxShape::Int, "the shell's index to go to")
}
fn usage(&self) -> &str {
"Go to specified shell."
}
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
goto(args)
}
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Enter the first shell",
example: "g 0",
result: None,
}]
}
}
fn goto(args: CommandArgs) -> Result<ActionStream, ShellError> {
Ok(ActionStream::one(ReturnSuccess::action(
CommandAction::GotoShell(args.req(0)?),
)))
}
#[cfg(test)]
mod tests {
use super::Goto;
use super::ShellError;
#[test]
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(Goto {})
}
}

View File

@ -1,11 +1,13 @@
mod command;
mod enter;
mod exit;
mod goto;
mod next;
mod prev;
pub use command::Shells;
pub use enter::Enter;
pub use exit::Exit;
pub use goto::Goto;
pub use next::Next;
pub use prev::Previous;

View File

@ -11,13 +11,6 @@ use std::collections::HashMap;
use std::sync::atomic::Ordering;
use std::time::Instant;
#[cfg(feature = "table-pager")]
use {
futures::future::join,
minus::{ExitStrategy, Pager},
std::fmt::Write,
};
const STREAM_PAGE_SIZE: usize = 1000;
const STREAM_TIMEOUT_CHECK_INTERVAL: usize = 100;
@ -186,28 +179,9 @@ fn table(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
let term_width = args.host().lock().width();
#[cfg(feature = "table-pager")]
let pager = Pager::new()
.set_exit_strategy(ExitStrategy::PagerQuit)
.set_searchable(true)
.set_page_if_havent_overflowed(false)
.set_input_handler(Box::new(input_handling::MinusInputHandler {}))
.finish();
let stream_data = async {
let finished = Arc::new(AtomicBool::new(false));
// we are required to clone finished, for use within the callback, otherwise we get borrow errors
#[cfg(feature = "table-pager")]
let finished_within_callback = finished.clone();
#[cfg(feature = "table-pager")]
{
// This is called when the pager finishes, to indicate to the
// while loop below to finish, in case of long running InputStream consumer
// that doesn't finish by the time the user quits out of the pager
pager.lock().await.add_exit_callback(move || {
finished_within_callback.store(true, Ordering::Relaxed);
});
}
while !finished.clone().load(Ordering::Relaxed) {
let mut new_input: VecDeque<Value> = VecDeque::new();
@ -263,161 +237,22 @@ fn table(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
if !input.is_empty() {
let t = from_list(&input, &configuration, start_number, &color_hm);
let output = draw_table(&t, term_width, &color_hm);
#[cfg(feature = "table-pager")]
{
let mut pager = pager.lock().await;
writeln!(pager.lines, "{}", output).map_err(|_| {
ShellError::untagged_runtime_error("Error writing to pager")
})?;
}
#[cfg(not(feature = "table-pager"))]
println!("{}", output);
}
start_number += input.len();
}
#[cfg(feature = "table-pager")]
{
let mut pager_lock = pager.lock().await;
pager_lock.data_finished();
}
Result::<_, ShellError>::Ok(())
};
#[cfg(feature = "table-pager")]
{
let (minus_result, streaming_result) =
block_on(join(minus::async_std_updating(pager.clone()), stream_data));
minus_result.map_err(|_| ShellError::untagged_runtime_error("Error paging data"))?;
streaming_result?;
}
#[cfg(not(feature = "table-pager"))]
block_on(stream_data)
.map_err(|_| ShellError::untagged_runtime_error("Error streaming data"))?;
Ok(OutputStream::empty())
}
#[cfg(feature = "table-pager")]
mod input_handling {
use crossterm::event::{Event, KeyCode, KeyEvent, KeyModifiers, MouseEvent, MouseEventKind};
use minus::{InputEvent, InputHandler, LineNumbers, SearchMode};
pub struct MinusInputHandler;
impl InputHandler for MinusInputHandler {
fn handle_input(
&self,
ev: Event,
upper_mark: usize,
search_mode: SearchMode,
ln: LineNumbers,
rows: usize,
) -> Option<InputEvent> {
match ev {
// Scroll up by one.
Event::Key(KeyEvent {
code: KeyCode::Up,
modifiers: KeyModifiers::NONE,
}) => Some(InputEvent::UpdateUpperMark(upper_mark.saturating_sub(1))),
// Scroll down by one.
Event::Key(KeyEvent {
code: KeyCode::Down,
modifiers: KeyModifiers::NONE,
}) => Some(InputEvent::UpdateUpperMark(upper_mark.saturating_add(1))),
// Mouse scroll up/down
Event::Mouse(MouseEvent {
kind: MouseEventKind::ScrollUp,
..
}) => Some(InputEvent::UpdateUpperMark(upper_mark.saturating_sub(5))),
Event::Mouse(MouseEvent {
kind: MouseEventKind::ScrollDown,
..
}) => Some(InputEvent::UpdateUpperMark(upper_mark.saturating_add(5))),
// Go to top.
Event::Key(KeyEvent {
code: KeyCode::Home,
modifiers: KeyModifiers::NONE,
}) => Some(InputEvent::UpdateUpperMark(0)),
// Go to bottom.
Event::Key(KeyEvent {
code: KeyCode::End,
modifiers: KeyModifiers::NONE,
}) => Some(InputEvent::UpdateUpperMark(usize::MAX)),
// Page Up/Down
Event::Key(KeyEvent {
code: KeyCode::PageUp,
modifiers: KeyModifiers::NONE,
}) => Some(InputEvent::UpdateUpperMark(
upper_mark.saturating_sub(rows - 1),
)),
Event::Key(KeyEvent {
code: KeyCode::PageDown,
modifiers: KeyModifiers::NONE,
}) => Some(InputEvent::UpdateUpperMark(
upper_mark.saturating_add(rows - 1),
)),
// Resize event from the terminal.
Event::Resize(_, height) => Some(InputEvent::UpdateRows(height as usize)),
// Switch line number display.
Event::Key(KeyEvent {
code: KeyCode::Char('l'),
modifiers: KeyModifiers::CONTROL,
}) => Some(InputEvent::UpdateLineNumber(!ln)),
// Quit.
Event::Key(KeyEvent {
code: KeyCode::Char('q'),
modifiers: KeyModifiers::NONE,
})
| Event::Key(KeyEvent {
code: KeyCode::Char('Q'),
modifiers: KeyModifiers::SHIFT,
})
| Event::Key(KeyEvent {
code: KeyCode::Esc,
modifiers: KeyModifiers::NONE,
})
| Event::Key(KeyEvent {
code: KeyCode::Char('c'),
modifiers: KeyModifiers::CONTROL,
}) => Some(InputEvent::Exit),
Event::Key(KeyEvent {
code: KeyCode::Char('/'),
modifiers: KeyModifiers::NONE,
}) => Some(InputEvent::Search(SearchMode::Unknown)),
Event::Key(KeyEvent {
code: KeyCode::Down,
modifiers: KeyModifiers::CONTROL,
}) => {
if search_mode == SearchMode::Unknown {
Some(InputEvent::NextMatch)
} else {
None
}
}
Event::Key(KeyEvent {
code: KeyCode::Up,
modifiers: KeyModifiers::CONTROL,
}) => {
if search_mode == SearchMode::Unknown {
Some(InputEvent::PrevMatch)
} else {
None
}
}
_ => None,
}
}
}
}
#[cfg(test)]
mod tests {
use super::Command;

View File

@ -77,6 +77,7 @@ pub fn create_default_context(interactive: bool) -> Result<EvaluationContext, Bo
// Shells
whole_stream_command(Next),
whole_stream_command(Previous),
whole_stream_command(Goto),
whole_stream_command(Shells),
whole_stream_command(Enter),
whole_stream_command(Exit),
@ -133,9 +134,11 @@ pub fn create_default_context(interactive: bool) -> Result<EvaluationContext, Bo
whole_stream_command(Select),
whole_stream_command(Get),
whole_stream_command(Update),
whole_stream_command(UpdateCells),
whole_stream_command(Insert),
whole_stream_command(Into),
whole_stream_command(IntoBinary),
whole_stream_command(IntoColumnPath),
whole_stream_command(IntoInt),
whole_stream_command(IntoFilepath),
whole_stream_command(IntoFilesize),

View File

@ -21,8 +21,8 @@ use crate::commands::{
};
use crate::commands::{
Append, BuildString, Collect, Each, Echo, First, Get, Keep, Last, Let, Math, MathMode, Nth,
Select, StrCollect, Wrap,
Append, BuildString, Collect, Each, Echo, First, Get, If, IntoInt, Keep, Last, Let, Math,
MathMode, Nth, Select, StrCollect, Wrap,
};
use nu_engine::{run_block, whole_stream_command, Command, EvaluationContext, WholeStreamCommand};
use nu_stream::InputStream;
@ -41,6 +41,8 @@ pub fn test_examples(cmd: Command) -> Result<(), ShellError> {
whole_stream_command(BuildString {}),
whole_stream_command(First {}),
whole_stream_command(Get {}),
whole_stream_command(If {}),
whole_stream_command(IntoInt {}),
whole_stream_command(Keep {}),
whole_stream_command(Each {}),
whole_stream_command(Last {}),
@ -253,6 +255,8 @@ pub fn test_anchors(cmd: Command) -> Result<(), ShellError> {
whole_stream_command(BuildString {}),
whole_stream_command(First {}),
whole_stream_command(Get {}),
whole_stream_command(If {}),
whole_stream_command(IntoInt {}),
whole_stream_command(Keep {}),
whole_stream_command(Each {}),
whole_stream_command(Last {}),

View File

@ -8,7 +8,7 @@ fn returns_path_joined_with_column_path() {
cwd: "tests", pipeline(
r#"
echo [ [name]; [eggs] ]
| path join -a spam.txt name
| path join spam.txt -c [ name ]
| get name
"#
));
@ -23,7 +23,7 @@ fn returns_path_joined_from_list() {
cwd: "tests", pipeline(
r#"
echo [ home viking spam.txt ]
| path join
| path join
"#
));
@ -37,7 +37,7 @@ fn appends_slash_when_joined_with_empty_path() {
cwd: "tests", pipeline(
r#"
echo "/some/dir"
| path join -a ''
| path join ''
"#
));
@ -51,7 +51,7 @@ fn returns_joined_path_when_joining_empty_path() {
cwd: "tests", pipeline(
r#"
echo ""
| path join -a foo.txt
| path join foo.txt
"#
));

View File

@ -48,7 +48,7 @@ fn parses_custom_extension_gets_extension() {
let actual = nu!(
cwd: "tests", pipeline(
r#"
echo 'home/viking/spam.tar.gz'
echo 'home/viking/spam.tar.gz'
| path parse -e tar.gz
| get extension
"#
@ -62,7 +62,7 @@ fn parses_custom_extension_gets_stem() {
let actual = nu!(
cwd: "tests", pipeline(
r#"
echo 'home/viking/spam.tar.gz'
echo 'home/viking/spam.tar.gz'
| path parse -e tar.gz
| get stem
"#
@ -76,7 +76,7 @@ fn parses_ignoring_extension_gets_extension() {
let actual = nu!(
cwd: "tests", pipeline(
r#"
echo 'home/viking/spam.tar.gz'
echo 'home/viking/spam.tar.gz'
| path parse -e ''
| get extension
"#
@ -90,7 +90,7 @@ fn parses_ignoring_extension_gets_stem() {
let actual = nu!(
cwd: "tests", pipeline(
r#"
echo 'home/viking/spam.tar.gz'
echo 'home/viking/spam.tar.gz'
| path parse -e ""
| get stem
"#
@ -105,7 +105,7 @@ fn parses_column_path_extension() {
cwd: "tests", pipeline(
r#"
echo [[home, barn]; ['home/viking/spam.txt', 'barn/cow/moo.png']]
| path parse home barn
| path parse -c [ home barn ]
| get barn
| get extension
"#

View File

@ -18,7 +18,7 @@ fn splits_correctly_single_path() {
cwd: "tests", pipeline(
r#"
echo ['home/viking/spam.txt']
| path split
| path split
| last
"#
));
@ -37,7 +37,7 @@ fn splits_correctly_with_column_path() {
['home/viking/spam.txt', 'barn/cow/moo.png']
['home/viking/eggs.txt', 'barn/goat/cheese.png']
]
| path split home barn
| path split -c [ home barn ]
| get barn
| length
"#

View File

@ -4,22 +4,19 @@ description = "Completions for nushell"
edition = "2018"
license = "MIT"
name = "nu-completion"
version = "0.37.0"
version = "0.38.0"
[lib]
doctest = false
[dependencies]
nu-engine = { version = "0.37.0", path="../nu-engine" }
nu-data = { version = "0.37.0", path="../nu-data" }
nu-errors = { version = "0.37.0", path="../nu-errors" }
nu-parser = { version = "0.37.0", path="../nu-parser" }
nu-path = { version = "0.37.0", path="../nu-path" }
nu-protocol = { version = "0.37.0", path="../nu-protocol" }
nu-source = { version = "0.37.0", path="../nu-source" }
nu-test-support = { version = "0.37.0", path="../nu-test-support" }
dirs-next = "2.0.0"
nu-engine = { version = "0.38.0", path="../nu-engine" }
nu-data = { version = "0.38.0", path="../nu-data" }
nu-parser = { version = "0.38.0", path="../nu-parser" }
nu-path = { version = "0.38.0", path="../nu-path" }
nu-protocol = { version = "0.38.0", path="../nu-protocol" }
nu-source = { version = "0.38.0", path="../nu-source" }
nu-test-support = { version = "0.38.0", path="../nu-test-support" }
indexmap = { version="1.6.1", features=["serde-1"] }
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]

View File

@ -238,11 +238,19 @@ pub fn completion_location(line: &str, block: &Block, pos: usize) -> Vec<Complet
}
}
output.push(loc.clone());
output.push({
let mut partial_loc = loc.clone();
partial_loc.span = Span::new(loc.span.start(), pos);
partial_loc
});
output
}
}
_ => vec![loc.clone()],
_ => vec![{
let mut partial_loc = loc.clone();
partial_loc.span = Span::new(loc.span.start(), pos);
partial_loc
}],
};
} else if pos < loc.span.start() {
break;
@ -339,7 +347,7 @@ mod tests {
line: &str,
scope: &dyn ParserScope,
pos: usize,
) -> Vec<LocationType> {
) -> Vec<CompletionLocation> {
let (tokens, _) = lex(line, 0, nu_parser::NewlineMode::Normal);
let (lite_block, _) = parse_block(tokens);
@ -348,9 +356,6 @@ mod tests {
scope.exit_scope();
super::completion_location(line, &block, pos)
.into_iter()
.map(|v| v.item)
.collect()
}
#[test]
@ -362,7 +367,7 @@ mod tests {
assert_eq!(
completion_location(line, &registry, 10),
vec![LocationType::Command],
vec![LocationType::Command.spanned(Span::new(9, 10)),],
);
}
@ -373,7 +378,7 @@ mod tests {
assert_eq!(
completion_location(line, &registry, 10),
vec![LocationType::Command],
vec![LocationType::Command.spanned(Span::new(9, 10)),],
);
}
@ -384,7 +389,7 @@ mod tests {
assert_eq!(
completion_location(line, &registry, 4),
vec![LocationType::Command],
vec![LocationType::Command.spanned(Span::new(0, 4)),],
);
}
@ -395,7 +400,7 @@ mod tests {
assert_eq!(
completion_location(line, &registry, 13),
vec![LocationType::Variable],
vec![LocationType::Variable.spanned(Span::new(5, 13)),],
);
}
@ -410,7 +415,7 @@ mod tests {
assert_eq!(
completion_location(line, &registry, 7),
vec![LocationType::Flag("du".to_string())],
vec![LocationType::Flag("du".to_string()).spanned(Span::new(3, 7)),],
);
}
@ -421,7 +426,7 @@ mod tests {
assert_eq!(
completion_location(line, &registry, 8),
vec![LocationType::Command],
vec![LocationType::Command.spanned(Span::new(6, 8)),],
);
}
@ -433,8 +438,8 @@ mod tests {
assert_eq!(
completion_location(line, &registry, 3),
vec![
LocationType::Command,
LocationType::Argument(Some("cd".to_string()), None)
LocationType::Command.spanned(Span::new(0, 3)),
LocationType::Argument(Some("cd".to_string()), None).spanned(Span::new(3, 3)),
],
);
}
@ -451,8 +456,8 @@ mod tests {
assert_eq!(
completion_location(line, &registry, 3),
vec![
LocationType::Argument(Some("du".to_string()), None),
LocationType::Flag("du".to_string()),
LocationType::Argument(Some("du".to_string()), None).spanned(Span::new(3, 4)),
LocationType::Flag("du".to_string()).spanned(Span::new(3, 4)),
],
);
}
@ -467,8 +472,24 @@ mod tests {
assert_eq!(
completion_location(line, &registry, 6),
vec![
LocationType::Command,
LocationType::Argument(Some("echo".to_string()), None)
LocationType::Command.spanned(Span::new(0, 6)),
LocationType::Argument(Some("echo".to_string()), None).spanned(Span::new(5, 6)),
],
);
}
#[test]
fn completes_argument_when_cursor_inside_argument() {
let registry: VecRegistry =
vec![Signature::build("echo").rest("rest", SyntaxShape::Any, "the values to echo")]
.into();
let line = "echo 123";
assert_eq!(
completion_location(line, &registry, 6),
vec![
LocationType::Command.spanned(Span::new(0, 6)),
LocationType::Argument(Some("echo".to_string()), None).spanned(Span::new(5, 6)),
],
);
}

View File

@ -4,7 +4,7 @@ description = "CLI for nushell"
edition = "2018"
license = "MIT"
name = "nu-data"
version = "0.37.0"
version = "0.38.0"
[lib]
doctest = false
@ -16,27 +16,25 @@ chrono = "0.4.19"
common-path = "1.0.0"
derive-new = "0.5.8"
directories-next = "2.0.0"
dirs-next = "2.0.0"
getset = "0.1.1"
indexmap = { version="1.6.1", features=["serde-1"] }
log = "0.4.14"
num-bigint = { version="0.3.1", features=["serde"] }
num-format = "0.4.0"
num-traits = "0.2.14"
query_interface = "0.3.5"
serde = { version="1.0.123", features=["derive"] }
sha2 = "0.9.3"
sys-locale = "0.1.0"
toml = "0.5.8"
nu-errors = { version = "0.37.0", path="../nu-errors" }
nu-path = { version = "0.37.0", path="../nu-path" }
nu-protocol = { version = "0.37.0", path="../nu-protocol" }
nu-source = { version = "0.37.0", path="../nu-source" }
nu-table = { version = "0.37.0", path="../nu-table" }
nu-test-support = { version = "0.37.0", path="../nu-test-support" }
nu-value-ext = { version = "0.37.0", path="../nu-value-ext" }
nu-ansi-term = { version = "0.37.0", path="../nu-ansi-term" }
nu-errors = { version = "0.38.0", path="../nu-errors" }
nu-path = { version = "0.38.0", path="../nu-path" }
nu-protocol = { version = "0.38.0", path="../nu-protocol" }
nu-source = { version = "0.38.0", path="../nu-source" }
nu-table = { version = "0.38.0", path="../nu-table" }
nu-test-support = { version = "0.38.0", path="../nu-test-support" }
nu-value-ext = { version = "0.38.0", path="../nu-value-ext" }
nu-ansi-term = { version = "0.38.0", path="../nu-ansi-term" }
[target.'cfg(unix)'.dependencies]
users = "0.11.0"

View File

@ -4,28 +4,25 @@ description = "Core commands for nushell"
edition = "2018"
license = "MIT"
name = "nu-engine"
version = "0.37.0"
version = "0.38.0"
[dependencies]
nu-data = { version = "0.37.0", path="../nu-data" }
nu-errors = { version = "0.37.0", path="../nu-errors" }
nu-parser = { version = "0.37.0", path="../nu-parser" }
nu-plugin = { version = "0.37.0", path="../nu-plugin" }
nu-protocol = { version = "0.37.0", path="../nu-protocol" }
nu-source = { version = "0.37.0", path="../nu-source" }
nu-stream = { version = "0.37.0", path="../nu-stream" }
nu-value-ext = { version = "0.37.0", path="../nu-value-ext" }
nu-ansi-term = { version = "0.37.0", path="../nu-ansi-term" }
nu-test-support = { version = "0.37.0", path="../nu-test-support" }
nu-path = { version = "0.37.0", path="../nu-path" }
nu-data = { version = "0.38.0", path="../nu-data" }
nu-errors = { version = "0.38.0", path="../nu-errors" }
nu-parser = { version = "0.38.0", path="../nu-parser" }
nu-plugin = { version = "0.38.0", path="../nu-plugin" }
nu-protocol = { version = "0.38.0", path="../nu-protocol" }
nu-source = { version = "0.38.0", path="../nu-source" }
nu-stream = { version = "0.38.0", path="../nu-stream" }
nu-value-ext = { version = "0.38.0", path="../nu-value-ext" }
nu-ansi-term = { version = "0.38.0", path="../nu-ansi-term" }
nu-test-support = { version = "0.38.0", path="../nu-test-support" }
nu-path = { version = "0.38.0", path="../nu-path" }
trash = { version="1.3.0", optional=true }
which = { version="4.0.2", optional=true }
codespan-reporting = "0.11.0"
dyn-clone = "1.0.4"
ansi_term = "0.12.1"
async-recursion = "0.3.2"
async-trait = "0.1.42"
bigdecimal = { package = "bigdecimal-rs", version = "0.2.1", features = ["serde"] }
bytes = "0.5.6"
chrono = { version="0.4.19", features=["serde"] }
@ -34,9 +31,6 @@ dirs-next = "2.0.0"
encoding_rs = "0.8.28"
filesize = "0.2.0"
fs_extra = "1.2.0"
futures = { version="0.3.12", features=["compat", "io-compat"] }
futures-util = "0.3.12"
futures_codec = "0.4.1"
getset = "0.1.1"
glob = "0.3.0"
indexmap = { version="1.6.1", features=["serde-1"] }
@ -44,8 +38,6 @@ itertools = "0.10.0"
lazy_static = "1.*"
log = "0.4.14"
num-bigint = { version="0.3.1", features=["serde"] }
num-format = "0.4.0"
num-traits = "0.2.14"
parking_lot = "0.11.1"
rayon = "1.5.0"
serde = { version="1.0.123", features=["derive"] }
@ -59,7 +51,7 @@ umask = "1.0.0"
users = "0.11.0"
[dev-dependencies]
nu-test-support = { version = "0.37.0", path="../nu-test-support" }
nu-test-support = { version = "0.38.0", path="../nu-test-support" }
hamcrest2 = "0.3.0"
[features]

View File

@ -177,6 +177,9 @@ impl Iterator for InternalIterator {
CommandAction::NextShell => {
self.context.shell_manager().next();
}
CommandAction::GotoShell(i) => {
self.context.shell_manager().goto(i);
}
CommandAction::LeaveShell(code) => {
self.context.shell_manager().remove_at_current();
if self.context.shell_manager().is_empty() {

View File

@ -101,6 +101,7 @@ impl FromValue for i64 {
v.as_i64()
}
}
impl FromValue for Tagged<i64> {
fn from_value(v: &Value) -> Result<Self, ShellError> {
let tag = v.tag.clone();

View File

@ -136,6 +136,16 @@ impl ShellManager {
self.set_path(self.path())
}
pub fn goto(&self, i: usize) {
{
let shell_len = self.shells.lock().len();
if i < shell_len {
self.current_shell.store(i, Ordering::SeqCst);
}
}
self.set_path(self.path())
}
pub fn homedir(&self) -> Option<PathBuf> {
let env = self.shells.lock();

View File

@ -4,14 +4,14 @@ description = "Core error subsystem for Nushell"
edition = "2018"
license = "MIT"
name = "nu-errors"
version = "0.37.0"
version = "0.38.0"
[lib]
doctest = false
[dependencies]
nu-source = { path="../nu-source", version = "0.37.0" }
nu-ansi-term = { version = "0.37.0", path="../nu-ansi-term" }
nu-source = { path="../nu-source", version = "0.38.0" }
nu-ansi-term = { version = "0.38.0", path="../nu-ansi-term" }
bigdecimal = { package = "bigdecimal-rs", version = "0.2.1", features = ["serde"] }
codespan-reporting = { version="0.11.0", features=["serialization"] }

View File

@ -4,7 +4,7 @@ description = "Fork of serde-hjson"
edition = "2018"
license = "MIT"
name = "nu-json"
version = "0.37.0"
version = "0.38.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -20,6 +20,6 @@ lazy_static = "1"
linked-hash-map = { version="0.5", optional=true }
[dev-dependencies]
nu-path = { version = "0.37.0", path="../nu-path" }
nu-test-support = { version = "0.37.0", path="../nu-test-support" }
nu-path = { version = "0.38.0", path="../nu-path" }
nu-test-support = { version = "0.38.0", path="../nu-test-support" }
serde_json = "1.0.39"

View File

@ -4,26 +4,23 @@ description = "Nushell parser"
edition = "2018"
license = "MIT"
name = "nu-parser"
version = "0.37.0"
version = "0.38.0"
[dependencies]
bigdecimal = { package = "bigdecimal-rs", version = "0.2.1", features = ["serde"] }
codespan-reporting = "0.11.0"
derive-new = "0.5.8"
indexmap = { version="1.6.1", features=["serde-1"] }
log = "0.4"
num-bigint = { version="0.3.1", features=["serde"] }
num-traits = "0.2.14"
serde = "1.0"
itertools = "0.10.0"
smart-default = "0.6.0"
nu-errors = { version = "0.37.0", path="../nu-errors" }
nu-data = { version = "0.37.0", path="../nu-data" }
nu-path = { version = "0.37.0", path="../nu-path" }
nu-protocol = { version = "0.37.0", path="../nu-protocol" }
nu-source = { version = "0.37.0", path="../nu-source" }
nu-test-support = { version = "0.37.0", path="../nu-test-support" }
nu-errors = { version = "0.38.0", path="../nu-errors" }
nu-data = { version = "0.38.0", path="../nu-data" }
nu-path = { version = "0.38.0", path="../nu-path" }
nu-protocol = { version = "0.38.0", path="../nu-protocol" }
nu-source = { version = "0.38.0", path="../nu-source" }
nu-test-support = { version = "0.38.0", path="../nu-test-support" }
[features]
stable = []

View File

@ -61,12 +61,11 @@ fn find_source_file(
if let Some(dir) = lib_dirs {
for lib_path in dir.into_iter().flatten() {
let path = canonicalize_with(&file, lib_path).map_err(|e| {
ParseError::general_error(
format!("Can't load source file. Reason: {}", e.to_string()),
"Can't load this file".spanned(file_span),
)
})?;
let path = if let Ok(p) = canonicalize_with(&file, lib_path) {
p
} else {
continue;
};
if let Ok(contents) = std::fs::read_to_string(&path) {
return parse(&contents, 0, scope);

View File

@ -4,11 +4,9 @@ description = "Path handling library for Nushell"
edition = "2018"
license = "MIT"
name = "nu-path"
version = "0.37.0"
version = "0.38.0"
[dependencies]
dirs-next = "2.0.0"
dunce = "1.0.1"
[dev-dependencies]
nu-test-support = { version = "0.37.0", path="../nu-test-support" }

View File

@ -1,3 +1 @@
mod canonicalize;
mod expand_path;
mod util;

View File

@ -4,21 +4,18 @@ description = "Nushell Plugin"
edition = "2018"
license = "MIT"
name = "nu-plugin"
version = "0.37.0"
version = "0.38.0"
[lib]
doctest = false
[dependencies]
nu-errors = { path="../nu-errors", version = "0.37.0" }
nu-protocol = { path="../nu-protocol", version = "0.37.0" }
nu-source = { path="../nu-source", version = "0.37.0" }
nu-test-support = { path="../nu-test-support", version = "0.37.0" }
nu-value-ext = { path="../nu-value-ext", version = "0.37.0" }
bigdecimal = { package = "bigdecimal-rs", version = "0.2.1", features = ["serde"] }
nu-errors = { path="../nu-errors", version = "0.38.0" }
nu-protocol = { path="../nu-protocol", version = "0.38.0" }
nu-source = { path="../nu-source", version = "0.38.0" }
nu-test-support = { path="../nu-test-support", version = "0.38.0" }
nu-value-ext = { path="../nu-value-ext", version = "0.38.0" }
indexmap = { version="1.6.1", features=["serde-1"] }
num-bigint = { version="0.3.1", features=["serde"] }
serde = { version="1.0", features=["derive"] }
serde_json = "1.0"

View File

@ -4,7 +4,7 @@ description = "Pretty hex dump of bytes slice in the common style."
edition = "2018"
license = "MIT"
name = "nu-pretty-hex"
version = "0.37.0"
version = "0.38.0"
[lib]
doctest = false
@ -16,7 +16,7 @@ name = "nu_pretty_hex"
path = "src/main.rs"
[dependencies]
nu-ansi-term = { path="../nu-ansi-term", version = "0.37.0" }
nu-ansi-term = { path="../nu-ansi-term", version = "0.38.0" }
rand = "0.8.3"
[dev-dependencies]

View File

@ -4,7 +4,7 @@ description = "Core values and protocols for Nushell"
edition = "2018"
license = "MIT"
name = "nu-protocol"
version = "0.37.0"
version = "0.38.0"
[lib]
doctest = false
@ -18,21 +18,16 @@ derive-new = "0.5.8"
getset = "0.1.1"
indexmap = { version="1.6.1", features=["serde-1"] }
log = "0.4.14"
nu-errors = { path="../nu-errors", version = "0.37.0" }
nu-source = { path="../nu-source", version = "0.37.0" }
nu-errors = { path="../nu-errors", version = "0.38.0" }
nu-source = { path="../nu-source", version = "0.38.0" }
num-bigint = { version="0.3.1", features=["serde"] }
num-integer = "0.1.44"
num-traits = "0.2.14"
serde = { version="1.0", features=["derive"] }
serde_bytes = "0.11.5"
# implement conversions
serde_json = "1.0"
serde_yaml = "0.8.16"
toml = "0.5.8"
[dependencies.polars]
version = "0.15.1"
version = "0.16.0"
optional = true
features = ["default", "serde", "rows", "strings", "checked_arithmetic", "object", "dtype-duration-ns"]

View File

@ -21,7 +21,7 @@ pub fn compute_between_dataframes(
if let (UntaggedValue::DataFrame(lhs), UntaggedValue::DataFrame(rhs)) =
(&left.value, &right.value)
{
let operation_span = left.tag.span.until(right.tag.span);
let operation_span = right.tag.span.merge(left.tag.span);
match (lhs.is_series(), rhs.is_series()) {
(true, true) => {
let lhs = &lhs

View File

@ -28,6 +28,8 @@ pub enum CommandAction {
PreviousShell,
/// Go to the next shell in the shell ring buffer
NextShell,
/// Jump to the specified shell in the shell ring buffer
GotoShell(usize),
/// Leave the current shell. If it's the last shell, exit out of Nu
LeaveShell(i32),
}
@ -51,6 +53,7 @@ impl PrettyDebug for CommandAction {
CommandAction::AddPlugins(..) => DbgDocBldr::description("add plugins"),
CommandAction::PreviousShell => DbgDocBldr::description("previous shell"),
CommandAction::NextShell => DbgDocBldr::description("next shell"),
CommandAction::GotoShell(_) => DbgDocBldr::description("goto shell"),
CommandAction::LeaveShell(_) => DbgDocBldr::description("leave shell"),
CommandAction::UnloadConfig(cfg) => {
DbgDocBldr::description(format!("unload config {:?}", cfg))

View File

@ -1,6 +1,6 @@
[package]
name = "nu-serde"
version = "0.37.0"
version = "0.38.0"
edition = "2018"
authors = ["The Nu Project Contributors"]
description = "Turn any value into a nu-protocol::Value with serde"
@ -10,8 +10,8 @@ documentation = "https://docs.rs/nu-serde"
[dependencies]
bigdecimal = { package = "bigdecimal-rs", version = "0.2.1", features = ["serde"] }
nu-protocol = { version = "0.37.0", path = "../nu-protocol" }
nu-source = { version = "0.37.0", path = "../nu-source" }
nu-protocol = { version = "0.38.0", path = "../nu-protocol" }
nu-source = { version = "0.38.0", path = "../nu-source" }
serde = "1"
thiserror = "1"

View File

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

View File

@ -605,6 +605,16 @@ impl Span {
Span::new(self.start, other.end)
}
pub fn merge(&self, other: impl Into<Span>) -> Span {
let other = other.into();
if other.end < self.start {
other.until(self)
} else {
self.until(other)
}
}
/// Returns a new Span by merging a later Span with the current Span.
///
/// If the given Span is of the None variant,

View File

@ -4,14 +4,12 @@ description = "Nushell stream"
edition = "2018"
license = "MIT"
name = "nu-stream"
version = "0.37.0"
version = "0.38.0"
[dependencies]
nu-errors = { version = "0.37.0", path="../nu-errors" }
nu-protocol = { version = "0.37.0", path="../nu-protocol" }
nu-source = { version = "0.37.0", path="../nu-source" }
futures = { version="0.3.12", features=["compat", "io-compat"] }
nu-errors = { version = "0.38.0", path="../nu-errors" }
nu-protocol = { version = "0.38.0", path="../nu-protocol" }
nu-source = { version = "0.38.0", path="../nu-source" }
[features]
stable = []

View File

@ -4,7 +4,7 @@ description = "Nushell table printing"
edition = "2018"
license = "MIT"
name = "nu-table"
version = "0.37.0"
version = "0.38.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[[bin]]
@ -12,7 +12,9 @@ name = "table"
path = "src/main.rs"
[dependencies]
nu-ansi-term = { version = "0.37.0", path="../nu-ansi-term" }
atty = "0.2.14"
nu-ansi-term = { version = "0.38.0", path="../nu-ansi-term" }
regex = "1.4"
strip-ansi-escapes = "0.1.1"
unicode-width = "0.1.8"

View File

@ -27,8 +27,18 @@ fn main() {
let color_hm: HashMap<String, nu_ansi_term::Style> = HashMap::new();
// Capture the table as a string
let output_table = draw_table(&table, width, &color_hm);
// Draw the table
println!("{}", output_table)
if atty::is(atty::Stream::Stdout) {
// Draw the table with ansi colors
println!("{}", output_table)
} else {
// Draw the table without ansi colors
if let Ok(bytes) = strip_ansi_escapes::strip(&output_table) {
println!("{}", String::from_utf8_lossy(&bytes))
} else {
println!("{}", output_table)
}
}
}
fn make_table_data() -> (Vec<&'static str>, Vec<&'static str>) {

View File

@ -918,7 +918,17 @@ impl WrappedTable {
output.push_str(&self.print_separator(SeparatorPosition::Bottom, color_hm));
}
output
if atty::is(atty::Stream::Stdout) {
// Draw the table with ansi colors
output
} else {
// Draw the table without ansi colors
if let Ok(bytes) = strip_ansi_escapes::strip(&output) {
String::from_utf8_lossy(&bytes).to_string()
} else {
output
}
}
}
}

View File

@ -4,21 +4,19 @@ description = "Support for writing Nushell tests"
edition = "2018"
license = "MIT"
name = "nu-test-support"
version = "0.37.0"
version = "0.38.0"
[lib]
doctest = false
[dependencies]
nu-errors = { version = "0.37.0", path="../nu-errors" }
nu-path = { version = "0.37.0", path="../nu-path" }
nu-protocol = { path="../nu-protocol", version = "0.37.0" }
nu-source = { path="../nu-source", version = "0.37.0" }
nu-value-ext = { version = "0.37.0", path="../nu-value-ext" }
nu-errors = { version = "0.38.0", path="../nu-errors" }
nu-path = { version = "0.38.0", path="../nu-path" }
nu-protocol = { path="../nu-protocol", version = "0.38.0" }
nu-source = { path="../nu-source", version = "0.38.0" }
bigdecimal = { package = "bigdecimal-rs", version = "0.2.1", features = ["serde"] }
chrono = "0.4.19"
dunce = "1.0.1"
getset = "0.1.1"
glob = "0.3.0"
indexmap = { version="1.6.1", features=["serde-1"] }

View File

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

View File

@ -698,6 +698,7 @@ pub fn as_string(value: &Value) -> Result<String, ShellError> {
UntaggedValue::Primitive(Primitive::Int(x)) => Ok(x.to_string()),
UntaggedValue::Primitive(Primitive::Filesize(x)) => Ok(x.to_string()),
UntaggedValue::Primitive(Primitive::FilePath(x)) => Ok(x.display().to_string()),
UntaggedValue::Primitive(Primitive::BigInt(x)) => Ok(x.to_string()),
UntaggedValue::Primitive(Primitive::ColumnPath(path)) => Ok(path
.iter()
.map(|member| match &member.unspanned {

View File

@ -4,7 +4,7 @@ description = "A binary viewer plugin for Nushell"
edition = "2018"
license = "MIT"
name = "nu_plugin_binaryview"
version = "0.37.0"
version = "0.38.0"
[lib]
doctest = false
@ -13,12 +13,12 @@ doctest = false
crossterm = "0.19"
image = { version="0.22.4", default_features=false, features=["png_codec", "jpeg"] }
neso = "0.5.0"
nu-errors = { path="../nu-errors", version = "0.37.0" }
nu-plugin = { path="../nu-plugin", version = "0.37.0" }
nu-protocol = { path="../nu-protocol", version = "0.37.0" }
nu-source = { path="../nu-source", version = "0.37.0" }
nu-ansi-term = { version = "0.37.0", path="../nu-ansi-term" }
nu-pretty-hex = { version = "0.37.0", path="../nu-pretty-hex" }
nu-errors = { path="../nu-errors", version = "0.38.0" }
nu-plugin = { path="../nu-plugin", version = "0.38.0" }
nu-protocol = { path="../nu-protocol", version = "0.38.0" }
nu-source = { path="../nu-source", version = "0.38.0" }
nu-ansi-term = { version = "0.38.0", path="../nu-ansi-term" }
nu-pretty-hex = { version = "0.38.0", path="../nu-pretty-hex" }
rawkey = "0.1.3"
[build-dependencies]

View File

@ -4,18 +4,18 @@ description = "A plugin to display charts"
edition = "2018"
license = "MIT"
name = "nu_plugin_chart"
version = "0.37.0"
version = "0.38.0"
[lib]
doctest = false
[dependencies]
nu-data = { path="../nu-data", version = "0.37.0" }
nu-errors = { path="../nu-errors", version = "0.37.0" }
nu-plugin = { path="../nu-plugin", version = "0.37.0" }
nu-protocol = { path="../nu-protocol", version = "0.37.0" }
nu-source = { path="../nu-source", version = "0.37.0" }
nu-value-ext = { path="../nu-value-ext", version = "0.37.0" }
nu-data = { path="../nu-data", version = "0.38.0" }
nu-errors = { path="../nu-errors", version = "0.38.0" }
nu-plugin = { path="../nu-plugin", version = "0.38.0" }
nu-protocol = { path="../nu-protocol", version = "0.38.0" }
nu-source = { path="../nu-source", version = "0.38.0" }
nu-value-ext = { path="../nu-value-ext", version = "0.38.0" }
crossterm = "0.19.0"
tui = { version="0.15.0", default-features=false, features=["crossterm"] }

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.37.0"
version = "0.38.0"
[lib]
doctest = false
@ -12,11 +12,9 @@ doctest = false
[dependencies]
bigdecimal = { package = "bigdecimal-rs", version = "0.2.1", features = ["serde"] }
bson = { version="0.14.1", features=["decimal128"] }
nu-errors = { path="../nu-errors", version = "0.37.0" }
nu-plugin = { path="../nu-plugin", version = "0.37.0" }
nu-protocol = { path="../nu-protocol", version = "0.37.0" }
nu-source = { path="../nu-source", version = "0.37.0" }
nu-value-ext = { path="../nu-value-ext", version = "0.37.0" }
num-traits = "0.2.14"
nu-errors = { path="../nu-errors", version = "0.38.0" }
nu-plugin = { path="../nu-plugin", version = "0.38.0" }
nu-protocol = { path="../nu-protocol", version = "0.38.0" }
nu-source = { path="../nu-source", version = "0.38.0" }
[build-dependencies]

View File

@ -10,10 +10,10 @@ version = "0.1.0"
doctest = false
[dependencies]
nu-errors = { path="../nu-errors", version = "0.37.0" }
nu-plugin = { path="../nu-plugin", version = "0.37.0" }
nu-protocol = { path="../nu-protocol", version = "0.37.0" }
nu-source = { path="../nu-source", version = "0.37.0" }
nu-errors = { path="../nu-errors", version = "0.38.0" }
nu-plugin = { path="../nu-plugin", version = "0.38.0" }
nu-protocol = { path="../nu-protocol", version = "0.38.0" }
nu-source = { path="../nu-source", version = "0.38.0" }
tempfile = "3.2.0"
mp4 = "0.8.2"

View File

@ -4,19 +4,17 @@ description = "A converter plugin to the bson format for Nushell"
edition = "2018"
license = "MIT"
name = "nu_plugin_from_sqlite"
version = "0.37.0"
version = "0.38.0"
[lib]
doctest = false
[dependencies]
bigdecimal = { package = "bigdecimal-rs", version = "0.2.1", features = ["serde"] }
nu-errors = { path="../nu-errors", version = "0.37.0" }
nu-plugin = { path="../nu-plugin", version = "0.37.0" }
nu-protocol = { path="../nu-protocol", version = "0.37.0" }
nu-source = { path="../nu-source", version = "0.37.0" }
nu-value-ext = { path="../nu-value-ext", version = "0.37.0" }
num-traits = "0.2.14"
nu-errors = { path="../nu-errors", version = "0.38.0" }
nu-plugin = { path="../nu-plugin", version = "0.38.0" }
nu-protocol = { path="../nu-protocol", version = "0.38.0" }
nu-source = { path="../nu-source", version = "0.38.0" }
tempfile = "3.2.0"
[dependencies.rusqlite]

View File

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

View File

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

View File

@ -4,17 +4,14 @@ description = "query json files with gjson"
edition = "2018"
license = "MIT"
name = "nu_plugin_query_json"
version = "0.37.0"
version = "0.38.0"
[lib]
doctest = false
[dependencies]
gjson = "0.7.1"
nu-errors = { version = "0.37.0", path="../nu-errors" }
nu-plugin = { version = "0.37.0", path="../nu-plugin" }
nu-protocol = { version = "0.37.0", path="../nu-protocol" }
nu-source = { version = "0.37.0", path="../nu-source" }
[dev-dependencies]
nu-test-support = { path="../nu-test-support", version = "0.37.0" }
nu-errors = { version = "0.38.0", path="../nu-errors" }
nu-plugin = { version = "0.38.0", path="../nu-plugin" }
nu-protocol = { version = "0.38.0", path="../nu-protocol" }
nu-source = { version = "0.38.0", path="../nu-source" }

View File

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

View File

@ -4,17 +4,18 @@ description = "web scraping using css selector"
edition = "2018"
license = "MIT"
name = "nu_plugin_selector"
version = "0.37.0"
version = "0.38.0"
[lib]
doctest = false
[dependencies]
nipper = "0.1.9"
nu-errors = { version = "0.37.0", path="../nu-errors" }
nu-plugin = { version = "0.37.0", path="../nu-plugin" }
nu-protocol = { version = "0.37.0", path="../nu-protocol" }
nu-source = { version = "0.37.0", path="../nu-source" }
scraper = "0.12.0"
nu-errors = { version = "0.38.0", path="../nu-errors" }
nu-plugin = { version = "0.38.0", path="../nu-plugin" }
nu-protocol = { version = "0.38.0", path="../nu-protocol" }
nu-source = { version = "0.38.0", path="../nu-source" }
[dev-dependencies]
nu-test-support = { path="../nu-test-support", version = "0.37.0" }
indexmap = { version="1.7", features=["serde-1"] }

View File

@ -1,4 +1,6 @@
mod nu;
mod selector;
mod tables;
pub use selector::Selector;
pub use tables::Table;

View File

@ -10,34 +10,55 @@ impl Plugin for Selector {
fn config(&mut self) -> Result<Signature, ShellError> {
Ok(Signature::build("selector")
.desc("execute selector query on html/web")
.required("query", SyntaxShape::String, "selector query")
.switch("as_html", "return the query output as html", Some('a'))
.named("query", SyntaxShape::String, "selector query", Some('q'))
.switch("as_html", "return the query output as html", Some('m'))
.named(
"attribute",
SyntaxShape::String,
"downselect based on the given attribute",
Some('a'),
)
.named(
"as_table",
SyntaxShape::Table,
"find table based on column header list",
Some('t'),
)
.switch(
"inspect",
"run in inspect mode to provide more information for determining column headers",
Some('i'),
)
.filter())
}
fn begin_filter(&mut self, call_info: CallInfo) -> Result<Vec<ReturnValue>, ShellError> {
let tag = call_info.name_tag;
let query = call_info.args.nth(0).ok_or_else(|| {
ShellError::labeled_error(
"selector query not passed",
"selector query not passed",
&tag,
)
})?;
// let query = call_info.args.nth(0).ok_or_else(|| {
// ShellError::labeled_error(
// "selector query not passed",
// "selector query not passed",
// &tag,
// )
// })?;
self.query = query.as_string()?;
// self.query = query.as_string()?;
self.query = if let Some(qtext) = call_info.args.get("query") {
qtext.convert_to_string()
} else {
"".to_string()
};
self.tag = tag;
self.as_html = call_info.args.has("as_html");
if call_info.args.has("attribute") {
self.attribute = call_info.args.expect_get("attribute")?.convert_to_string();
}
if call_info.args.has("as_table") {
self.as_table = call_info.args.expect_get("as_table")?.clone();
}
self.inspect = call_info.args.has("inspect");
Ok(vec![])
}

View File

@ -1,5 +1,6 @@
use crate::Table;
use nipper::Document;
use nu_protocol::{value::StringExt, Value};
use nu_protocol::{value::StringExt, Primitive, TaggedDictBuilder, UntaggedValue, Value};
use nu_source::Tag;
pub struct Selector {
@ -7,6 +8,8 @@ pub struct Selector {
pub tag: Tag,
pub as_html: bool,
pub attribute: String,
pub as_table: Value,
pub inspect: bool,
}
impl Selector {
@ -16,6 +19,11 @@ impl Selector {
tag: Tag::unknown(),
as_html: false,
attribute: String::new(),
as_table: Value::new(
UntaggedValue::Primitive(Primitive::String("".to_string())),
Tag::unknown(),
),
inspect: false,
}
}
}
@ -27,14 +35,132 @@ impl Default for Selector {
}
pub fn begin_selector_query(input_html: String, selector: &Selector) -> Vec<Value> {
match selector.attribute.is_empty() {
true => execute_selector_query(&input_html, &selector.query, selector.as_html),
false => {
execute_selector_query_with_attribute(&input_html, &selector.query, &selector.attribute)
if selector.as_table.is_some() {
retrieve_tables(input_html.as_str(), &selector.as_table, selector.inspect)
} else {
match selector.attribute.is_empty() {
true => execute_selector_query(
input_html.as_str(),
selector.query.as_str(),
selector.as_html,
),
false => execute_selector_query_with_attribute(
input_html.as_str(),
selector.query.as_str(),
selector.attribute.as_str(),
),
}
}
}
pub fn retrieve_tables(input_string: &str, columns: &Value, inspect_mode: bool) -> Vec<Value> {
let html = input_string;
let mut cols = Vec::new();
if let UntaggedValue::Table(t) = &columns.value {
for x in t {
cols.push(x.convert_to_string());
}
}
if inspect_mode {
eprintln!("Passed in Column Headers = {:#?}", &cols,);
}
let tables = match Table::find_by_headers(html, &cols) {
Some(t) => {
if inspect_mode {
eprintln!("Table Found = {:#?}", &t);
}
t
}
None => vec![Table::empty()],
};
if tables.len() == 1 {
return retrieve_table(
tables
.into_iter()
.next()
.expect("This should never trigger"),
columns,
);
}
tables
.into_iter()
.map(move |table| {
UntaggedValue::Table(retrieve_table(table, columns)).into_value(Tag::unknown())
})
.collect()
}
fn retrieve_table(mut table: Table, columns: &Value) -> Vec<Value> {
let mut cols = Vec::new();
if let UntaggedValue::Table(t) = &columns.value {
for x in t {
cols.push(x.convert_to_string());
}
}
if cols.is_empty() && !table.headers().is_empty() {
for col in table.headers().keys() {
cols.push(col.to_string());
}
}
let mut table_out = Vec::new();
// sometimes there are tables where the first column is the headers, kind of like
// a table has ben rotated ccw 90 degrees, in these cases all columns will be missing
// we keep track of this with this variable so we can deal with it later
let mut at_least_one_row_filled = false;
// if columns are still empty, let's just make a single column table with the data
if cols.is_empty() {
at_least_one_row_filled = true;
let table_with_no_empties: Vec<_> = table.iter().filter(|item| !item.is_empty()).collect();
for row in &table_with_no_empties {
let mut dict = TaggedDictBuilder::new(Tag::unknown());
for (counter, cell) in row.iter().enumerate() {
let col_name = format!("Column{}", counter);
dict.insert_value(
col_name,
UntaggedValue::Primitive(Primitive::String(cell.to_string()))
.into_value(Tag::unknown()),
);
}
table_out.push(dict.into_value());
}
} else {
for row in &table {
let mut dict = TaggedDictBuilder::new(Tag::unknown());
// eprintln!("row={:?}", &row);
for col in &cols {
//eprintln!("col={:?}", &col);
let key = col.to_string();
let val = row
.get(col)
.unwrap_or(&format!("Missing column: '{}'", &col))
.to_string();
if !at_least_one_row_filled && val != format!("Missing column: '{}'", &col) {
at_least_one_row_filled = true;
}
dict.insert_value(
key,
UntaggedValue::Primitive(Primitive::String(val)).into_value(Tag::unknown()),
);
}
table_out.push(dict.into_value());
}
}
if !at_least_one_row_filled {
let mut data2 = Vec::new();
for x in &table.data {
data2.push(x.join(", "));
}
table.data = vec![data2];
return retrieve_table(table, columns);
}
table_out
}
fn execute_selector_query_with_attribute(
input_string: &str,
query_string: &str,

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -4,18 +4,17 @@ description = "Text viewer plugin for Nushell"
edition = "2018"
license = "MIT"
name = "nu_plugin_textview"
version = "0.37.0"
version = "0.38.0"
[lib]
doctest = false
[dependencies]
nu-data = { path="../nu-data", version = "0.37.0" }
nu-errors = { path="../nu-errors", version = "0.37.0" }
nu-plugin = { path="../nu-plugin", version = "0.37.0" }
nu-protocol = { path="../nu-protocol", version = "0.37.0" }
nu-source = { path="../nu-source", version = "0.37.0" }
nu-ansi-term = { version = "0.37.0", path="../nu-ansi-term" }
nu-data = { path="../nu-data", version = "0.38.0" }
nu-errors = { path="../nu-errors", version = "0.38.0" }
nu-plugin = { path="../nu-plugin", version = "0.38.0" }
nu-protocol = { path="../nu-protocol", version = "0.38.0" }
nu-source = { path="../nu-source", version = "0.38.0" }
bat = { version="0.18", features=["regex-fancy", "paging", "git"] }
term_size = "0.3.2"

View File

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

View File

@ -1,22 +1,20 @@
[package]
authors = ["The Nu Project Contributors"]
description = "A converter plugin to the bson format for Nushell"
description = "A converter plugin to the SQLite format for Nushell"
edition = "2018"
license = "MIT"
name = "nu_plugin_to_sqlite"
version = "0.37.0"
version = "0.38.0"
[lib]
doctest = false
[dependencies]
hex = "0.4.2"
nu-errors = { path="../nu-errors", version = "0.37.0" }
nu-plugin = { path="../nu-plugin", version = "0.37.0" }
nu-protocol = { path="../nu-protocol", version = "0.37.0" }
nu-source = { path="../nu-source", version = "0.37.0" }
nu-value-ext = { path="../nu-value-ext", version = "0.37.0" }
num-traits = "0.2.14"
nu-errors = { path="../nu-errors", version = "0.38.0" }
nu-plugin = { path="../nu-plugin", version = "0.38.0" }
nu-protocol = { path="../nu-protocol", version = "0.38.0" }
nu-source = { path="../nu-source", version = "0.38.0" }
tempfile = "3.2.0"
[dependencies.rusqlite]

View File

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

View File

@ -4,16 +4,16 @@ description = "Traverses xml"
edition = "2018"
license = "MIT"
name = "nu_plugin_xpath"
version = "0.37.0"
version = "0.38.0"
[lib]
doctest = false
[dependencies]
nu-errors = { version = "0.37.0", path="../nu-errors" }
nu-plugin = { path="../nu-plugin", version = "0.37.0" }
nu-protocol = { version = "0.37.0", path="../nu-protocol" }
nu-source = { version = "0.37.0", path="../nu-source" }
nu-errors = { version = "0.38.0", path="../nu-errors" }
nu-plugin = { path="../nu-plugin", version = "0.38.0" }
nu-protocol = { version = "0.38.0", path="../nu-protocol" }
nu-source = { version = "0.38.0", path="../nu-source" }
bigdecimal = { package = "bigdecimal-rs", version = "0.2.1", features = ["serde"] }
indexmap = { version="1.6.1", 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.37.0" }
nu-test-support = { path="../nu-test-support", version = "0.38.0" }

View File

@ -86,7 +86,7 @@ version = "0.4.6"
[dependencies.cursive]
default-features = false
features = ["pancurses-backend"]
version = "0.37.0"
version = "0.38.0"
[dependencies.futures-preview]
features = ["compat", "io-compat"]

View File

@ -1,250 +1,13 @@
{
"name": "wasm",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"dependencies": {
"wasm-pack": "^0.10.0"
}
},
"node_modules/axios": {
"version": "0.21.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
"integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
"dependencies": {
"follow-redirects": "^1.10.0"
}
},
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
},
"node_modules/binary-install": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/binary-install/-/binary-install-0.1.1.tgz",
"integrity": "sha512-DqED0D/6LrS+BHDkKn34vhRqOGjy5gTMgvYZsGK2TpNbdPuz4h+MRlNgGv5QBRd7pWq/jylM4eKNCizgAq3kNQ==",
"dependencies": {
"axios": "^0.21.1",
"rimraf": "^3.0.2",
"tar": "^6.1.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"node_modules/chownr": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
"integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
"engines": {
"node": ">=10"
}
},
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
},
"node_modules/follow-redirects": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz",
"integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==",
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/RubenVerborgh"
}
],
"engines": {
"node": ">=4.0"
},
"peerDependenciesMeta": {
"debug": {
"optional": true
}
}
},
"node_modules/fs-minipass": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
"integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
"dependencies": {
"minipass": "^3.0.0"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
},
"node_modules/glob": {
"version": "7.1.7",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
"integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
},
"engines": {
"node": "*"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"dependencies": {
"once": "^1.3.0",
"wrappy": "1"
}
},
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"node_modules/minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"dependencies": {
"brace-expansion": "^1.1.7"
},
"engines": {
"node": "*"
}
},
"node_modules/minipass": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz",
"integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==",
"dependencies": {
"yallist": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/minizlib": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
"integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
"dependencies": {
"minipass": "^3.0.0",
"yallist": "^4.0.0"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/mkdirp": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
"bin": {
"mkdirp": "bin/cmd.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dependencies": {
"wrappy": "1"
}
},
"node_modules/path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/rimraf": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"dependencies": {
"glob": "^7.1.3"
},
"bin": {
"rimraf": "bin.js"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/tar": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz",
"integrity": "sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==",
"dependencies": {
"chownr": "^2.0.0",
"fs-minipass": "^2.0.0",
"minipass": "^3.0.0",
"minizlib": "^2.1.1",
"mkdirp": "^1.0.3",
"yallist": "^4.0.0"
},
"engines": {
"node": ">= 10"
}
},
"node_modules/wasm-pack": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/wasm-pack/-/wasm-pack-0.10.0.tgz",
"integrity": "sha512-E+bs6Bh5mmSPT5lqEsyhEsFSVIIGYFEq96oG+SfQqY8gv8Hvn7TB3FGD+gVL5On5TCOgPQb7Sr2dbLkj9cN0QQ==",
"hasInstallScript": true,
"dependencies": {
"binary-install": "^0.1.0"
},
"bin": {
"wasm-pack": "run.js"
}
},
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
},
"node_modules/yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
}
},
"lockfileVersion": 1,
"dependencies": {
"axios": {
"version": "0.21.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
"integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
"version": "0.21.4",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
"integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
"requires": {
"follow-redirects": "^1.10.0"
"follow-redirects": "^1.14.0"
}
},
"balanced-match": {
@ -282,9 +45,9 @@
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
},
"follow-redirects": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz",
"integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg=="
"version": "1.14.4",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.4.tgz",
"integrity": "sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g=="
},
"fs-minipass": {
"version": "2.1.0",
@ -300,9 +63,9 @@
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
},
"glob": {
"version": "7.1.7",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
"integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
"integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
@ -335,9 +98,9 @@
}
},
"minipass": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz",
"integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==",
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.5.tgz",
"integrity": "sha512-+8NzxD82XQoNKNrl1d/FSi+X8wAEWR+sbYAfIvub4Nz0d22plFG72CEVVaufV8PNf4qSslFTD8VMOxNVhHCjTw==",
"requires": {
"yallist": "^4.0.0"
}
@ -378,9 +141,9 @@
}
},
"tar": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz",
"integrity": "sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==",
"version": "6.1.11",
"resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz",
"integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==",
"requires": {
"chownr": "^2.0.0",
"fs-minipass": "^2.0.0",
@ -391,9 +154,9 @@
}
},
"wasm-pack": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/wasm-pack/-/wasm-pack-0.10.0.tgz",
"integrity": "sha512-E+bs6Bh5mmSPT5lqEsyhEsFSVIIGYFEq96oG+SfQqY8gv8Hvn7TB3FGD+gVL5On5TCOgPQb7Sr2dbLkj9cN0QQ==",
"version": "0.10.1",
"resolved": "https://registry.npmjs.org/wasm-pack/-/wasm-pack-0.10.1.tgz",
"integrity": "sha512-bw480KaaJQhL6UX8wAm6YCO497uaULDrsvUey3EB86dKAfFc6qCGVN1kItcwUklEeufonwo9mwz9/fy9xLOPtQ==",
"requires": {
"binary-install": "^0.1.0"
}

View File

@ -1,4 +1,5 @@
extern crate nu_test_support;
mod path;
mod plugins;
mod shell;

2
tests/path/mod.rs Normal file
View File

@ -0,0 +1,2 @@
mod canonicalize;
mod expand_path;