Compare commits

...

24 Commits

Author SHA1 Message Date
JT
f9ae882012 Update main.wxs (#4007)
Remove references to the old binaries
2021-09-15 07:45:30 +12:00
JT
1d80a68f4c bump to 0.37 (#4006) 2021-09-15 06:44:24 +12:00
fda69354db change name to command_prompt (#4003) 2021-09-14 08:02:10 +12:00
cc5c4d38bb Small fixes and refactors to paths & source command (#3998)
* Expand path when converting value -> PathBuf

Also includes Tagged<PathBuf>.

Fixes #3605

* Expand path for PATH env. variable

Fixes #1834

* Remove leftover Cows after nu-path refactor

There were some unnecessary Cow conversions leftover from the old
nu-path implementation.

* Use canonicalize in source command; Improve errors

Previously, `source` used `expand_path()` which does not follow
symlinks.

As a follow up, I improved the source error messages so they now tell
why the source file could not be canonicalized or read into string.
2021-09-12 02:36:14 +03:00
JT
0fa0c25fb3 Fix clippy warnings (#3997) 2021-09-10 13:13:11 +12:00
55eafadf02 Improve error message when bash-style alias syntax is mistakenly used (#3995) 2021-09-10 10:44:55 +12:00
51c74eebd0 Add general refactorings (#3996) 2021-09-10 10:44:22 +12:00
Tw
ae9f4135c0 support appending when saving file (#3992)
This patch implements `>>` operation in bash.

Signed-off-by: Tw <tw19881113@gmail.com>
2021-09-05 06:12:08 +12:00
4e2d3ceaaf Allow knowing the command name tag given no input. (#3988)
```
tags
```
2021-09-03 01:46:15 -05:00
c9c6bd4836 Create errors from tables. (#3986)
```
> [
  [          msg,                 labels,                      span];
  ["The message", "Helpful message here", ([[start, end]; [0, 141]])]
] | error make

error: The message
  ┌─ shell:1:1
  │
1 │ ╭ [
2 │ │   [          msg,                 labels,                      span];
3 │ │   ["The message", "Helpful message here", ([[start, end]; [0, 141]])]
  │ ╰─────────────────────────────────────────────────────────────────────^ Helpful message here
```

Adding a more flexible approach for creating error values. One use case, for instance is the
idea of a test framework. A failed assertion instead of printing to the screen it could create
tables with more details of the failed assertion and pass it to this command for making a full
fledge error that Nu can show. This can (and should) be extended for capturing error values as well
in the pipeline. One could also use it for inspection.

For example: `.... | error inspect { # inspection here }`

or "error handling" as well, like so: `.... | error capture { fix here }`

However, we start here only with `error make` that creates an error value for you with limited support for the time being.
2021-09-02 21:07:26 -05:00
d90420ac4c Add subcommand into filesize (#3987)
* Add subcommand `into filesize`

It's currently not possible to convert a number or a string containing a number
into a filesize. The only way to create an instance of filesize type today is
with a literal in nushell syntax. This commit adds the `into filesize`
subcommand so that file sizes can be created from the outputs of programs
producing numbers or strings, like standard unix tools.

There is a limitation with this - it doesn't currently parse values like `10 MB`
or `10 MiB`, it can only look at the number itself. If the desire is there, more
flexible parsing can be added.

* fixup! Add subcommand `into filesize`

* fixup! Add subcommand `into filesize`
2021-09-02 18:19:54 -05:00
260ff99710 feat: spawn the executables directly if possible (#3974)
* feat: spawn the executables directly if possible

This pull request changes nu-command so that it spawns the process directly if:
- They are a `.exe` on Windows
- They are not a `.sh` or `.bash` on not windows.

Benefits:
- As I explained in [this comment](https://github.com/nushell/nushell/issues/3898#issuecomment-894000812), this is another step towards making Nushell a standalone shell, that doesn't need to shell out unless it is running a script for a particular shell (cmd, sh, ps1, etc.).
- Fixes the bug with multiline strings
- Better performance due to direct spawning.

For example, this script shows ~20 ms less latency.
After:
```nu
C:\> benchmark { node -e 'console.log("sssss")' }
───┬──────────────────
 # │    real time
───┼──────────────────
 0 │ 63ms 921us 600ns
───┴──────────────────
```
Before
```nu
C:\> benchmark { node -e 'console.log("sssss")' }
───┬──────────────────
 # │    real time
───┼──────────────────
 0 │ 79ms 136us 800ns
───┴──────────────────
```

Fixes #3898

* fix: make which dependency optional

Also fixes clippy warnings

* refactor: refactor spawn_exe, spawn_cmd, spawn_sh, and spawn_any

* fix: use which feature instead of which-support

* fix: use which_in to use the cwd of nu

* fix: use case insensitive comparison of the extensions

Sometimes the case of the extension is uppercased by the "which_in" function

Also use unix instead of not windows. Some os might not have sh support
2021-09-01 09:38:52 -05:00
JT
08014c6a98 Move sys, ps, fetch, post to internal commands (#3983)
* Move sys, ps, fetch, post to internal commands

* Remove old plugins

* clippy

Co-authored-by: JT <jonatha.d.turner@gmail.com>
2021-09-01 14:29:09 +12:00
66cedf0b3a Update char_.rs (#3975)
added a few more chars and abbreviations
2021-08-29 08:40:28 -05:00
707a4ebc15 added more escapes to support ansi art (#3973)
* added more escapes to support ansi art

* fixed some bugs
2021-08-28 14:58:59 -05:00
d95375d494 nu-path crate refactor (#3730)
* Resolve rebase artifacts

* Remove leftover dependencies on removed feature

* Remove unnecessary 'pub'

* Start taking notes and fooling around

* Split canonicalize to two versions; Add TODOs

One that takes `relative_to` and one that doesn't.
More TODO notes.

* Merge absolutize to and rename resolve_dots

* Add custom absolutize fn and use it in path expand

* Convert a couple of dunce::canonicalize to ours

* Update nu-path description

* Replace all canonicalize with nu-path version

* Remove leftover dunce dependencies

* Fix broken autocd with trailing slash

Trailing slash is preserved *only* in paths that do not contain "." or
"..". This should be fixed in the future to cover all paths but for now
it at least covers basic cases.

* Use dunce::canonicalize for canonicalizing

* Alow cd recovery from non-existent cwd

* Disable removed canonicalize functionality tests

Remove unused import

* Break down nu-path into separate modules

* Remove unused public imports

* Remove abundant cow mapping

* Fix clippy warning

* Reformulate old canonicalize tests to expand_path

They wouldn't work with the new canonicalize.

* Canonicalize also ~ and ndots; Unify path joining

Also, add doc comments in nu_path::expansions.

* Add comment

* Avoid expanding ndots if path is not valid UTF-8

With this change, no lossy path->string conversion should happen in the
nu-path crate.

* Fmt

* Slight expand_tilde refactor; Add doc comments

* Start nu-path integration tests

* Add tests TODO

* Fix docstring typo

* Fix some doc strings

* Add README for nu-path crate

* Add a couple of canonicalize tests

* Add nu-path integration tests

* Add trim trailing slashes tests

* Update nu-path dependency

* Remove unused import

* Regenerate lockfile
2021-08-28 15:59:09 +03:00
1c1c58e802 Remove duplicate dependencies (#3961)
* chore: Replace surf with reqwest

Removes a lot of older, duplication versions of some dependencies
(roughtly 90 dependencies removed in total)

* chore: Remove syn 0.11

* chore: Remove unnecessary features from ptree

Removes some more duplicate dependencies

* cargo update

* Ensure we run the fetch and post plugins on the tokio runtime

* Fix clippy warning

* fix: Github requires a user agent on requests

Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2021-08-28 15:34:11 +12:00
JT
7fe05b8296 bump to 0.36.1 (#3972) 2021-08-27 20:48:58 +12:00
17ef531905 introducing the find command (#3971)
* introducing the `find` command

* added tests

* merged main to accomodate "rest" changes

* test fix
2021-08-27 20:48:41 +12:00
b8e2bdd6b1 Allow different names for ...rest (#3954)
* Allow different names for ...rest

* Resolves #3945

* This change requires an explicit name for the rest argument in `WholeStreamCommand`,
  which is why there are so many changed files.

* Remove redundant clone

* Add tests
2021-08-27 05:58:53 +12:00
88817a8f10 Allow environment variables to be hidden (#3950)
* Allow environment variables to be hidden

This change allows environment variables in Nushell to have a value of
`Nothing`, which can be set by the user by passing `$nothing` to
`let-env` and friends.

Environment variables with a value of Nothing behave as if they are not
set at all. This allows a user to shadow the value of an environment
variable in a parent scope, effectively removing it from their current
scope. This was not possible before, because a scope can not affect its
parent scopes.

This is a workaround for issues like #3920.

Additionally, this allows a user to simultaneously set, change and
remove multiple environment variables via `load-env`. Any environment
variables set to $nothing will be hidden and thus act as if they are
removed. This simplifies working with virtual environments, which rely
on setting multiple environment variables, including PATH, to specific
values, and remove/change them on deactivation.

One surprising behavior is that an environment variable set to $nothing
will act as if it is not set when querying it (via $nu.env.X), but it is
still possible to remove it entirely via `unlet-env`. If the same
environment variable is present in the parent scope, the value in the
parent scope will be visible to the user. This might be surprising
behavior to users who are not familiar with the implementation details.

An additional corner case is the the shorthand form of `with-env` does
not work with this feature. Using `X=$nothing` will set $nu.env.X to the
string "$nothing". The long-form works as expected: `with-env [X
$nothing] {...}`.

* Remove unused import

* Allow all primitives to be convert to strings
2021-08-26 08:15:58 -05:00
3e8ce43dcb rename command and rename for melt (#3968) 2021-08-26 08:13:54 -05:00
9d8845d7ad Allow custom lib dir path for sourcing nu script libraries. (#3940)
Given we can write nu scripts. As the codebase grows, splitting into many smaller nu scripts is necessary.

In general, when we work with paths and files we seem to face quite a few difficulties. Here we just tackle one of them and it involves sourcing
files that also source other nu files and so forth. The current working directory becomes important here and being on a different directory
when sourcing scripts will not work. Mostly because we expand the path on the current working directory and parse the files when a source command
call is done.

For the moment, we introduce a `lib_dirs` configuration value and, unfortunately, introduce a new dependency in `nu-parser` (`nu-data`) to get
a handle of the configuration file to retrieve it. This should give clues and ideas as the new parser engine continues (introduce a way to also know paths)

With this PR we can do the following:

Let's assume we want to write a nu library called `my_library`. We will have the code in a directory called `project`: The file structure will looks like this:

```
project/my_library.nu
project/my_library/hello.nu
project/my_library/name.nu
```

This "pattern" works well, that is, when creating a library have a directory named `my_library` and next to it a `my_library.nu` file. Filling them like this:

```

source my_library/hello.nu
source my_library/name.nu
```

```

def hello [] {
  "hello world"
}
```

```

def name [] {
  "Nu"
end
```

Assuming this `project` directory is stored at `/path/to/lib/project`, we can do:

```
config set lib_dirs ['path/to/lib/project']
```

Given we have this `lib_dirs` configuration value, we can be anywhere while using Nu and do the following:

```
source my_library.nu

echo (hello) (name)

```
2021-08-26 02:04:04 -05:00
52578ba483 tweak the version | pivot instructions (#3964) 2021-08-24 19:03:07 -05:00
352 changed files with 4864 additions and 4247 deletions

View File

@ -38,7 +38,7 @@ body:
id: config
attributes:
label: Configuration
description: "Please run `> version | pivot` and paste the output to show OS, features, etc"
description: "Please run `> version | pivot key value | to md` and paste the output to show OS, features, etc"
placeholder: |
> version | pivot key value | to md
╭───┬────────────────────┬───────────────────────────────────────────────────────────────────────╮

2345
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.36.0"
version = "0.37.0"
[workspace]
members = ["crates/*/"]
@ -18,38 +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.36.0", path="./crates/nu-cli", default-features=false }
nu-command = { version = "0.36.0", path="./crates/nu-command" }
nu-completion = { version = "0.36.0", path="./crates/nu-completion" }
nu-data = { version = "0.36.0", path="./crates/nu-data" }
nu-engine = { version = "0.36.0", path="./crates/nu-engine" }
nu-errors = { version = "0.36.0", path="./crates/nu-errors" }
nu-parser = { version = "0.36.0", path="./crates/nu-parser" }
nu-path = { version = "0.36.0", path="./crates/nu-path" }
nu-plugin = { version = "0.36.0", path="./crates/nu-plugin" }
nu-protocol = { version = "0.36.0", path="./crates/nu-protocol" }
nu-source = { version = "0.36.0", path="./crates/nu-source" }
nu-value-ext = { version = "0.36.0", path="./crates/nu-value-ext" }
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_plugin_binaryview = { version = "0.36.0", path="./crates/nu_plugin_binaryview", optional=true }
nu_plugin_chart = { version = "0.36.0", path="./crates/nu_plugin_chart", optional=true }
nu_plugin_fetch = { version = "0.36.0", path="./crates/nu_plugin_fetch", optional=true }
nu_plugin_from_bson = { version = "0.36.0", path="./crates/nu_plugin_from_bson", optional=true }
nu_plugin_from_sqlite = { version = "0.36.0", path="./crates/nu_plugin_from_sqlite", optional=true }
nu_plugin_inc = { version = "0.36.0", path="./crates/nu_plugin_inc", optional=true }
nu_plugin_match = { version = "0.36.0", path="./crates/nu_plugin_match", optional=true }
nu_plugin_post = { version = "0.36.0", path="./crates/nu_plugin_post", optional=true }
nu_plugin_ps = { version = "0.36.0", path="./crates/nu_plugin_ps", optional=true }
nu_plugin_query_json = { version = "0.36.0", path="./crates/nu_plugin_query_json", optional=true }
nu_plugin_s3 = { version = "0.36.0", path="./crates/nu_plugin_s3", optional=true }
nu_plugin_selector = { version = "0.36.0", path="./crates/nu_plugin_selector", optional=true }
nu_plugin_start = { version = "0.36.0", path="./crates/nu_plugin_start", optional=true }
nu_plugin_sys = { version = "0.36.0", path="./crates/nu_plugin_sys", optional=true }
nu_plugin_textview = { version = "0.36.0", path="./crates/nu_plugin_textview", optional=true }
nu_plugin_to_bson = { version = "0.36.0", path="./crates/nu_plugin_to_bson", optional=true }
nu_plugin_to_sqlite = { version = "0.36.0", path="./crates/nu_plugin_to_sqlite", optional=true }
nu_plugin_tree = { version = "0.36.0", path="./crates/nu_plugin_tree", optional=true }
nu_plugin_xpath = { version = "0.36.0", path="./crates/nu_plugin_xpath", optional=true }
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 }
# Required to bootstrap the main binary
ctrlc = { version="3.1.7", optional=true }
@ -57,8 +53,7 @@ futures = { version="0.3.12", features=["compat", "io-compat"] }
itertools = "0.10.0"
[dev-dependencies]
nu-test-support = { version = "0.36.0", path="./crates/nu-test-support" }
dunce = "1.0.1"
nu-test-support = { version = "0.37.0", path="./crates/nu-test-support" }
serial_test = "0.5.1"
hamcrest2 = "0.3.0"
rstest = "0.10.0"
@ -66,6 +61,8 @@ rstest = "0.10.0"
[build-dependencies]
[features]
fetch-support = ["nu-command/fetch", "nu-command/post"]
sys-support = ["nu-command/sys", "nu-command/ps"]
ctrlc-support = ["nu-cli/ctrlc", "nu-command/ctrlc"]
rustyline-support = ["nu-cli/rustyline-support", "nu-command/rustyline-support"]
term-support = ["nu-command/term"]
@ -74,15 +71,13 @@ which-support = ["nu-command/which", "nu-engine/which"]
default = [
"nu-cli/shadow-rs",
"sys",
"ps",
"sys-support",
"ctrlc-support",
"which-support",
"term-support",
"rustyline-support",
"match",
"post",
"fetch",
"fetch-support",
"zip-support",
"dataframe",
]
@ -110,12 +105,8 @@ extra = [
wasi = ["inc", "match", "match", "tree", "rustyline-support"]
# Stable (Default)
fetch = ["nu_plugin_fetch"]
inc = ["nu_plugin_inc"]
match = ["nu_plugin_match"]
post = ["nu_plugin_post"]
ps = ["nu_plugin_ps"]
sys = ["nu_plugin_sys"]
textview = ["nu_plugin_textview"]
# Extra
@ -146,7 +137,6 @@ dataframe = [
"nu-command/dataframe",
"nu-value-ext/dataframe",
"nu-data/dataframe",
"nu_plugin_post/dataframe",
"nu_plugin_to_bson/dataframe",
]
@ -166,31 +156,11 @@ name = "nu_plugin_core_inc"
path = "src/plugins/nu_plugin_core_inc.rs"
required-features = ["inc"]
[[bin]]
name = "nu_plugin_core_ps"
path = "src/plugins/nu_plugin_core_ps.rs"
required-features = ["ps"]
[[bin]]
name = "nu_plugin_core_sys"
path = "src/plugins/nu_plugin_core_sys.rs"
required-features = ["sys"]
[[bin]]
name = "nu_plugin_core_fetch"
path = "src/plugins/nu_plugin_core_fetch.rs"
required-features = ["fetch"]
[[bin]]
name = "nu_plugin_core_match"
path = "src/plugins/nu_plugin_core_match.rs"
required-features = ["match"]
[[bin]]
name = "nu_plugin_core_post"
path = "src/plugins/nu_plugin_core_post.rs"
required-features = ["post"]
# Extra plugins
[[bin]]

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.36.0"
version = "0.37.0"
[lib]
doctest = false

View File

@ -93,7 +93,7 @@ pub static RESET: &str = "\x1B[0m";
impl Color {
fn write_foreground_code<W: AnyWrite + ?Sized>(&self, f: &mut W) -> Result<(), W::Error> {
match *self {
match self {
Color::Black => write!(f, "30"),
Color::Red => write!(f, "31"),
Color::Green => write!(f, "32"),
@ -103,8 +103,8 @@ impl Color {
Color::Magenta => write!(f, "35"),
Color::Cyan => write!(f, "36"),
Color::White => write!(f, "37"),
Color::Fixed(num) => write!(f, "38;5;{}", &num),
Color::Rgb(r, g, b) => write!(f, "38;2;{};{};{}", &r, &g, &b),
Color::Fixed(num) => write!(f, "38;5;{}", num),
Color::Rgb(r, g, b) => write!(f, "38;2;{};{};{}", r, g, b),
Color::DarkGray => write!(f, "90"),
Color::LightRed => write!(f, "91"),
Color::LightGreen => write!(f, "92"),
@ -118,7 +118,7 @@ impl Color {
}
fn write_background_code<W: AnyWrite + ?Sized>(&self, f: &mut W) -> Result<(), W::Error> {
match *self {
match self {
Color::Black => write!(f, "40"),
Color::Red => write!(f, "41"),
Color::Green => write!(f, "42"),
@ -128,8 +128,8 @@ impl Color {
Color::Magenta => write!(f, "45"),
Color::Cyan => write!(f, "46"),
Color::White => write!(f, "47"),
Color::Fixed(num) => write!(f, "48;5;{}", &num),
Color::Rgb(r, g, b) => write!(f, "48;2;{};{};{}", &r, &g, &b),
Color::Fixed(num) => write!(f, "48;5;{}", num),
Color::Rgb(r, g, b) => write!(f, "48;2;{};{};{}", r, g, b),
Color::DarkGray => write!(f, "100"),
Color::LightRed => write!(f, "101"),
Color::LightGreen => write!(f, "102"),

View File

@ -297,7 +297,7 @@ mod tests {
fn no_control_codes_for_plain() {
let one = Style::default().paint("one");
let two = Style::default().paint("two");
let output = format!("{}", AnsiStrings(&[one, two]));
assert_eq!(&*output, "onetwo");
let output = AnsiStrings(&[one, two]).to_string();
assert_eq!(output, "onetwo");
}
}

View File

@ -602,14 +602,14 @@ mod serde_json_tests {
#[test]
fn color_deserialization() {
let colors = &[
let colors = [
Color::Red,
Color::Blue,
Color::Rgb(123, 123, 123),
Color::Fixed(255),
];
for color in colors.iter() {
for color in colors {
let serialized = serde_json::to_string(&color).unwrap();
let deserialized: Color = serde_json::from_str(&serialized).unwrap();

View File

@ -75,6 +75,6 @@ mod test {
assert_eq!(unstyled_len(&a), 18);
let l2 = [Black.paint("st"), Red.paint("-second"), White.paint("-t")];
assert_eq!(sub_string(3, 11, &a).as_slice(), &l2);
assert_eq!(sub_string(3, 11, &a), l2);
}
}

View File

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

View File

@ -508,14 +508,14 @@ mod tests {
#[test]
fn can_use_loglevels() -> Result<(), ShellError> {
for level in &["error", "warn", "info", "debug", "trace"] {
for level in ["error", "warn", "info", "debug", "trace"] {
let ui = cli_app();
let args = format!("nu --loglevel={}", *level);
let args = format!("nu --loglevel={}", level);
ui.parse(&args)?;
assert_eq!(ui.loglevel().unwrap(), Ok(level.to_string()));
let ui = cli_app();
let args = format!("nu -l {}", *level);
let args = format!("nu -l {}", level);
ui.parse(&args)?;
assert_eq!(ui.loglevel().unwrap(), Ok(level.to_string()));
}
@ -541,11 +541,11 @@ mod tests {
#[test]
fn can_use_test_binaries() -> Result<(), ShellError> {
for binarie_name in &[
for binarie_name in [
"echo_env", "cococo", "iecho", "fail", "nonu", "chop", "repeater", "meow",
] {
let ui = cli_app();
let args = format!("nu --testbin={}", *binarie_name);
let args = format!("nu --testbin={}", binarie_name);
ui.parse(&args)?;
assert_eq!(ui.testbin().unwrap(), Ok(binarie_name.to_string()));
}

View File

@ -44,7 +44,7 @@ impl Options {
}
pub fn get(&self, key: &str) -> Option<Value> {
self.inner.borrow().get(key).map(Clone::clone)
self.inner.borrow().get(key).cloned()
}
pub fn put(&self, key: &str, value: Value) {

View File

@ -67,48 +67,37 @@ impl OptionsParser for NuParser {
}
};
let value =
value
.map(|v| match k.as_ref() {
"testbin" => {
if let Ok(name) = v.as_string() {
if testbins().iter().any(|n| name == *n) {
Some(v)
} else {
Some(
UntaggedValue::Error(
ShellError::untagged_runtime_error(
format!("{} is not supported.", name),
),
)
.into_value(v.tag),
)
}
} else {
Some(v)
}
let value = value.map(|v| match k.as_ref() {
"testbin" => {
if let Ok(name) = v.as_string() {
if testbins().iter().any(|n| name == *n) {
v
} else {
UntaggedValue::Error(ShellError::untagged_runtime_error(
format!("{} is not supported.", name),
))
.into_value(v.tag)
}
"loglevel" => {
if let Ok(name) = v.as_string() {
if loglevels().iter().any(|n| name == *n) {
Some(v)
} else {
Some(
UntaggedValue::Error(
ShellError::untagged_runtime_error(
format!("{} is not supported.", name),
),
)
.into_value(v.tag),
)
}
} else {
Some(v)
}
} else {
v
}
}
"loglevel" => {
if let Ok(name) = v.as_string() {
if loglevels().iter().any(|n| name == *n) {
v
} else {
UntaggedValue::Error(ShellError::untagged_runtime_error(
format!("{} is not supported.", name),
))
.into_value(v.tag)
}
_ => Some(v),
})
.flatten();
} else {
v
}
}
_ => v,
});
if let Some(value) = value {
options.put(k, value);

View File

@ -33,7 +33,7 @@ use std::path::PathBuf;
// Name of environment variable where the prompt could be stored
#[cfg(feature = "rustyline-support")]
const PROMPT_STRING: &str = "PROMPT_STRING";
const PROMPT_COMMAND: &str = "PROMPT_COMMAND";
pub fn search_paths() -> Vec<std::path::PathBuf> {
use std::env;
@ -165,7 +165,10 @@ pub fn cli(
// Store cmd duration in an env var
context.scope.add_env_var(
"CMD_DURATION_MS",
format!("{}", startup_commands_start_time.elapsed().as_millis()),
startup_commands_start_time
.elapsed()
.as_millis()
.to_string(),
);
if options.perf {
@ -298,9 +301,9 @@ pub fn cli(
let cwd = context.shell_manager().path();
// Check if the PROMPT_STRING env variable is set. This env variable
// Check if the PROMPT_COMMAND env variable is set. This env variable
// contains nu code that is used to overwrite the prompt
let colored_prompt = match context.scope.get_env(PROMPT_STRING) {
let colored_prompt = match context.scope.get_env(PROMPT_COMMAND) {
Some(env_prompt) => evaluate_prompt_string(&env_prompt, &context, &cwd),
None => {
if let Some(prompt) = &prompt {
@ -353,7 +356,7 @@ pub fn cli(
// Store cmd duration in an env var
context.scope.add_env_var(
"CMD_DURATION_MS",
format!("{}", cmd_start_time.elapsed().as_millis()),
cmd_start_time.elapsed().as_millis().to_string(),
);
match line {
@ -397,8 +400,7 @@ pub fn cli(
.lock()
.global_config
.as_ref()
.map(|cfg| cfg.var("ctrlc_exit"))
.flatten()
.and_then(|cfg| cfg.var("ctrlc_exit"))
.map(|ctrl_c| ctrl_c.is_true())
.unwrap_or(false); // default behavior is to allow CTRL-C spamming similar to other shells

View File

@ -461,7 +461,7 @@ pub(crate) fn load_keybindings(
if let Ok(contents) = contents {
let keybindings: Keybindings = serde_yaml::from_str(&contents)?;
// eprintln!("{:#?}", keybindings);
for keybinding in keybindings.into_iter() {
for keybinding in keybindings {
let (k, b) = convert_keybinding(keybinding);
// eprintln!("{:?} {:?}", k, b);

View File

@ -5,29 +5,31 @@ description = "CLI for nushell"
edition = "2018"
license = "MIT"
name = "nu-command"
version = "0.36.0"
version = "0.37.0"
[lib]
doctest = false
[dependencies]
nu-data = { version = "0.36.0", path="../nu-data" }
nu-engine = { version = "0.36.0", path="../nu-engine" }
nu-errors = { version = "0.36.0", path="../nu-errors" }
nu-json = { version = "0.36.0", path="../nu-json" }
nu-path = { version = "0.36.0", path="../nu-path" }
nu-parser = { version = "0.36.0", path="../nu-parser" }
nu-plugin = { version = "0.36.0", path="../nu-plugin" }
nu-protocol = { version = "0.36.0", path="../nu-protocol" }
nu-serde = { version = "0.36.0", path="../nu-serde" }
nu-source = { version = "0.36.0", path="../nu-source" }
nu-stream = { version = "0.36.0", path="../nu-stream" }
nu-table = { version = "0.36.0", path="../nu-table" }
nu-test-support = { version = "0.36.0", path="../nu-test-support" }
nu-value-ext = { version = "0.36.0", path="../nu-value-ext" }
nu-ansi-term = { version = "0.36.0", path="../nu-ansi-term" }
nu-pretty-hex = { version = "0.36.0", path="../nu-pretty-hex" }
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" }
url = "2.2.1"
mime = "0.3.16"
Inflector = "0.11"
arboard = { version="1.1.0", optional=true }
base64 = "0.13.0"
@ -45,7 +47,6 @@ derive-new = "0.5.8"
directories-next = "2.0.0"
dirs-next = "2.0.0"
dtparse = "1.2.0"
dunce = "1.0.1"
eml-parser = "0.1.0"
encoding_rs = "0.8.28"
filesize = "0.2.0"
@ -72,6 +73,7 @@ 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 }
@ -85,16 +87,17 @@ 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"
trash = { version="1.3.0", optional=true }
unicode-segmentation = "1.8"
url = "2.2.0"
uuid_crate = { package="uuid", version="0.8.2", features=["v4"], optional=true }
which = { version="4.1.0", optional=true }
zip = { version="0.5.9", optional=true }
@ -135,3 +138,7 @@ stable = []
trash-support = ["trash"]
table-pager = ["minus", "crossterm"]
dataframe = ["nu-protocol/dataframe", "polars"]
fetch = ["reqwest", "tokio"]
post = ["reqwest", "tokio"]
sys = ["sysinfo"]
ps = ["sysinfo"]

View File

@ -4,7 +4,10 @@ use nu_engine::{MaybeTextCodec, StringOrBinary};
use nu_test_support::NATIVE_PATH_ENV_VAR;
use parking_lot::Mutex;
#[allow(unused)]
use std::env;
use std::io::Write;
use std::path::PathBuf;
use std::process::{Command, Stdio};
use std::sync::mpsc;
use std::{borrow::Cow, io::BufReader};
@ -17,6 +20,9 @@ use nu_protocol::hir::{ExternalCommand, ExternalRedirection};
use nu_protocol::{Primitive, ShellTypeName, UntaggedValue, Value};
use nu_source::Tag;
#[cfg(feature = "which")]
use which::which_in;
pub(crate) fn run_external_command(
command: ExternalCommand,
context: &mut EvaluationContext,
@ -104,7 +110,7 @@ fn run_with_stdin(
let process_args = command_args
.iter()
.map(|(arg, _is_literal)| {
let arg = nu_path::expand_tilde_string(Cow::Borrowed(arg));
let arg = nu_path::expand_tilde(arg).to_string_lossy().to_string();
#[cfg(not(windows))]
{
@ -141,6 +147,79 @@ fn run_with_stdin(
)
}
/// Spawn a direct exe
#[allow(unused)]
fn spawn_exe(full_path: PathBuf, args: &[String]) -> Command {
let mut process = Command::new(full_path);
for arg in args {
process.arg(&arg);
}
process
}
/// Spawn a cmd command with `cmd /c args...`
fn spawn_cmd_command(command: &ExternalCommand, args: &[String]) -> Command {
let mut process = Command::new("cmd");
process.arg("/c");
process.arg(&command.name);
for arg in args {
// Clean the args before we use them:
// https://stackoverflow.com/questions/1200235/how-to-pass-a-quoted-pipe-character-to-cmd-exe
// cmd.exe needs to have a caret to escape a pipe
let arg = arg.replace("|", "^|");
process.arg(&arg);
}
process
}
/// Spawn a sh command with `sh -c args...`
fn spawn_sh_command(command: &ExternalCommand, args: &[String]) -> Command {
let cmd_with_args = vec![command.name.clone(), args.join(" ")].join(" ");
let mut process = Command::new("sh");
process.arg("-c").arg(cmd_with_args);
process
}
/// a function to spawn any external command
#[allow(unused)] // for minimal builds cwd is unused
fn spawn_any(command: &ExternalCommand, args: &[String], cwd: &str) -> Command {
// resolve the executable name if it is spawnable directly
#[cfg(feature = "which")]
// TODO add more available paths to `env::var_os("PATH")`?
if let Result::Ok(full_path) = which_in(&command.name, env::var_os("PATH"), cwd) {
if let Some(extension) = full_path.extension() {
#[cfg(windows)]
if extension.eq_ignore_ascii_case("exe") {
// if exe spawn it directly
return spawn_exe(full_path, args);
} else {
// TODO implement special care for various executable types such as .bat, .ps1, .cmd, etc
// https://github.com/mklement0/Native/blob/e0e0b8785cad39a73053e35084d1f60d87fbac58/Native.psm1#L749
// otherwise shell out to cmd
return spawn_cmd_command(command, args);
}
#[cfg(not(windows))]
if !["sh", "bash"]
.iter()
.any(|ext| extension.eq_ignore_ascii_case(ext))
{
// if exe spawn it directly
return spawn_exe(full_path, args);
} else {
// otherwise shell out to sh
return spawn_sh_command(command, args);
}
}
}
// in all the other cases shell out
if cfg!(windows) {
spawn_cmd_command(command, args)
} else {
// TODO what happens if that os doesn't support spawning sh?
spawn_sh_command(command, args)
}
}
fn spawn(
command: &ExternalCommand,
path: &str,
@ -151,31 +230,7 @@ fn spawn(
) -> Result<InputStream, ShellError> {
let command = command.clone();
let mut process = {
#[cfg(windows)]
{
let mut process = Command::new("cmd");
process.arg("/c");
process.arg(&command.name);
for arg in args {
// Clean the args before we use them:
// https://stackoverflow.com/questions/1200235/how-to-pass-a-quoted-pipe-character-to-cmd-exe
// cmd.exe needs to have a caret to escape a pipe
let arg = arg.replace("|", "^|");
process.arg(&arg);
}
process
}
#[cfg(not(windows))]
{
let cmd_with_args = vec![command.name.clone(), args.join(" ")].join(" ");
let mut process = Command::new("sh");
process.arg("-c").arg(cmd_with_args);
process
}
};
let mut process = spawn_any(&command, args, path);
process.current_dir(path);
trace!(target: "nu::run::external", "cwd = {:?}", &path);
@ -454,7 +509,7 @@ fn spawn(
Ok(stream.into_input_stream())
}
Err(e) => Err(ShellError::labeled_error(
format!("{}", e),
e.to_string(),
"failed to spawn",
&command.name_tag,
)),

View File

@ -22,6 +22,7 @@ impl WholeStreamCommand for Histogram {
None,
)
.rest(
"rest",
SyntaxShape::ColumnPath,
"column name to give the histogram's frequency column",
)

View File

@ -13,6 +13,7 @@ impl WholeStreamCommand for SubCommand {
fn signature(&self) -> Signature {
Signature::build("into binary").rest(
"rest",
SyntaxShape::ColumnPath,
"column paths to convert to binary (for table input)",
)

View File

@ -14,6 +14,7 @@ impl WholeStreamCommand for SubCommand {
fn signature(&self) -> Signature {
Signature::build("into path").rest(
"rest",
SyntaxShape::ColumnPath,
"column paths to convert to filepath (for table input)",
)

View File

@ -0,0 +1,182 @@
use std::convert::TryInto;
use crate::prelude::*;
use nu_engine::WholeStreamCommand;
use nu_errors::ShellError;
use nu_protocol::{ColumnPath, Primitive, Signature, SyntaxShape, UntaggedValue, Value};
use num_bigint::ToBigInt;
pub struct SubCommand;
impl WholeStreamCommand for SubCommand {
fn name(&self) -> &str {
"into filesize"
}
fn signature(&self) -> Signature {
Signature::build("into filesize").rest(
"rest",
SyntaxShape::ColumnPath,
"column paths to convert to filesize (for table input)",
)
}
fn usage(&self) -> &str {
"Convert value to filesize"
}
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
into_filesize(args)
}
fn examples(&self) -> Vec<Example> {
vec![
Example {
description: "Convert string to filesize in table",
example: "echo [[bytes]; ['5'] [3.2] [4] [2kb]] | into filesize bytes",
result: Some(vec![
UntaggedValue::row(indexmap! {
"bytes".to_string() => UntaggedValue::filesize(5).into(),
})
.into(),
UntaggedValue::row(indexmap! {
"bytes".to_string() => UntaggedValue::filesize(3).into(),
})
.into(),
UntaggedValue::row(indexmap! {
"bytes".to_string() => UntaggedValue::filesize(4).into(),
})
.into(),
UntaggedValue::row(indexmap! {
"bytes".to_string() => UntaggedValue::filesize(2000).into(),
})
.into(),
]),
},
Example {
description: "Convert string to filesize",
example: "echo '2' | into filesize",
result: Some(vec![UntaggedValue::filesize(2).into()]),
},
Example {
description: "Convert decimal to filesize",
example: "echo 8.3 | into filesize",
result: Some(vec![UntaggedValue::filesize(8).into()]),
},
Example {
description: "Convert int to filesize",
example: "echo 5 | into filesize",
result: Some(vec![UntaggedValue::filesize(5).into()]),
},
Example {
description: "Convert file size to filesize",
example: "echo 4KB | into filesize",
result: Some(vec![UntaggedValue::filesize(4000).into()]),
},
]
}
}
fn into_filesize(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::filesize(match prim {
Primitive::String(a_string) => match int_from_string(a_string.trim(), &tag) {
Ok(n) => n,
Err(e) => {
return Err(e);
}
},
Primitive::Decimal(dec) => match dec.to_bigint() {
Some(n) => match n.to_u64() {
Some(i) => i,
None => {
return Err(ShellError::unimplemented(
"failed to convert decimal to filesize",
));
}
},
None => {
return Err(ShellError::unimplemented(
"failed to convert decimal to filesize",
));
}
},
Primitive::Int(n_ref) => (*n_ref).try_into().map_err(|_| {
ShellError::unimplemented("cannot convert negative integer to filesize")
})?,
Primitive::Filesize(a_filesize) => *a_filesize,
_ => {
return Err(ShellError::unimplemented(
"'into filesize' for non-numeric primitives",
))
}
})
.into_value(&tag)),
UntaggedValue::Row(_) => Err(ShellError::labeled_error(
"specify column name to use, with 'into filesize COLUMN'",
"found table",
tag,
)),
_ => Err(ShellError::unimplemented(
"'into filesize' for unsupported type",
)),
}
}
fn int_from_string(a_string: &str, tag: &Tag) -> Result<u64, ShellError> {
match a_string.parse::<u64>() {
Ok(n) => Ok(n),
Err(_) => match a_string.parse::<f64>() {
Ok(f) => match f.to_u64() {
Some(i) => Ok(i),
None => Err(ShellError::labeled_error(
"Could not convert string value to filesize",
"original value",
tag.clone(),
)),
},
Err(_) => Err(ShellError::labeled_error(
"Could not convert string value to filesize",
"original value",
tag.clone(),
)),
},
}
}
#[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

@ -13,6 +13,7 @@ impl WholeStreamCommand for SubCommand {
fn signature(&self) -> Signature {
Signature::build("into int").rest(
"rest",
SyntaxShape::ColumnPath,
"column paths to convert to int (for table input)",
)

View File

@ -1,9 +1,11 @@
mod binary;
mod command;
mod filepath;
mod filesize;
mod int;
pub mod string;
pub use self::filesize::SubCommand as IntoFilesize;
pub use binary::SubCommand as IntoBinary;
pub use command::Command as Into;
pub use filepath::SubCommand as IntoFilepath;

View File

@ -20,6 +20,7 @@ impl WholeStreamCommand for SubCommand {
fn signature(&self) -> Signature {
Signature::build("into string")
.rest(
"rest",
SyntaxShape::ColumnPath,
"column paths to convert to string (for table input)",
)
@ -158,7 +159,7 @@ pub fn action(
}
fn format_int(int: i64) -> String {
format!("{}", int)
int.to_string()
// TODO once platform-specific dependencies are stable (see Cargo.toml)
// #[cfg(windows)]
@ -175,7 +176,7 @@ fn format_int(int: i64) -> String {
}
fn format_bigint(int: &BigInt) -> String {
format!("{}", int)
int.to_string()
// TODO once platform-specific dependencies are stable (see Cargo.toml)
// #[cfg(windows)]
@ -229,7 +230,7 @@ fn format_decimal(mut decimal: BigDecimal, digits: Option<u64>, group_digits: bo
let format_default_loc = |int_part: BigInt| {
let loc = Locale::en;
//TODO: when num_format is available for recent bigint, replace this with the locale-based format
let (int_str, sep) = (format!("{}", int_part), String::from(loc.decimal()));
let (int_str, sep) = (int_part.to_string(), String::from(loc.decimal()));
format!("{}{}{}", int_str, sep, dec_str)
};

View File

@ -15,7 +15,7 @@ impl WholeStreamCommand for Alias {
Signature::build("alias")
.required("name", SyntaxShape::String, "the name of the alias")
.required("equals", SyntaxShape::String, "the equals sign")
.rest(SyntaxShape::Any, "the expansion for the alias")
.rest("rest", SyntaxShape::Any, "the expansion for the alias")
}
fn usage(&self) -> &str {

View File

@ -27,7 +27,7 @@ impl WholeStreamCommand for Do {
"ignore errors as the block runs",
Some('i'),
)
.rest(SyntaxShape::Any, "the parameter(s) for the block")
.rest("rest", SyntaxShape::Any, "the parameter(s) for the block")
}
fn usage(&self) -> &str {

View File

@ -12,7 +12,7 @@ impl WholeStreamCommand for Echo {
}
fn signature(&self) -> Signature {
Signature::build("echo").rest(SyntaxShape::Any, "the values to echo")
Signature::build("echo").rest("rest", SyntaxShape::Any, "the values to echo")
}
fn usage(&self) -> &str {

View File

@ -0,0 +1,109 @@
use crate::prelude::*;
use nu_engine::WholeStreamCommand;
use nu_errors::ShellError;
use nu_protocol::{Primitive, Signature, UntaggedValue, Value};
pub struct SubCommand;
impl WholeStreamCommand for SubCommand {
fn name(&self) -> &str {
"error make"
}
fn signature(&self) -> Signature {
Signature::build("error make")
}
fn usage(&self) -> &str {
"Create an error."
}
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
let input = args.input;
Ok(input
.map(|value| {
make_error(&value)
.map(|err| UntaggedValue::Error(err).into_value(value.tag()))
.unwrap_or_else(|| {
UntaggedValue::Error(ShellError::untagged_runtime_error(
"Creating error value not supported.",
))
.into_value(value.tag())
})
})
.into_output_stream())
}
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Creates a labeled error",
example: r#"[
[ msg, labels, span];
["The message", "Helpful message here", ([[start, end]; [0, 141]])]
] | error make"#,
result: None,
}]
}
}
fn make_error(value: &Value) -> Option<ShellError> {
if let Value {
value: UntaggedValue::Row(dict),
..
} = value
{
let msg = dict.get_data_by_key("msg".spanned_unknown());
let labels =
dict.get_data_by_key("labels".spanned_unknown())
.and_then(|table| match &table.value {
UntaggedValue::Table(_) => table
.table_entries()
.map(|value| value.as_string().ok())
.collect(),
UntaggedValue::Primitive(Primitive::String(label)) => {
Some(vec![label.to_string()])
}
_ => None,
});
let _anchor = dict.get_data_by_key("tag".spanned_unknown());
let span = dict.get_data_by_key("span".spanned_unknown());
if msg.is_none() || labels.is_none() || span.is_none() {
return None;
}
let msg = msg.and_then(|msg| msg.as_string().ok());
if let Some(labels) = labels {
if labels.is_empty() {
return None;
}
return Some(ShellError::labeled_error(
msg.expect("Message will always be present."),
&labels[0],
span.map(|data| match data {
Value {
value: UntaggedValue::Row(vals),
..
} => match (vals.entries.get("start"), vals.entries.get("end")) {
(Some(start), Some(end)) => {
let start = start.as_usize().ok().unwrap_or(0);
let end = end.as_usize().ok().unwrap_or(0);
Span::new(start, end)
}
(_, _) => Span::unknown(),
},
_ => Span::unknown(),
})
.unwrap_or_else(Span::unknown),
));
}
}
None
}

View File

@ -0,0 +1,3 @@
mod make;
pub use make::SubCommand as ErrorMake;

View File

@ -0,0 +1,110 @@
use crate::prelude::*;
use nu_engine::WholeStreamCommand;
use nu_errors::ShellError;
use nu_protocol::{Dictionary, Signature, SyntaxShape, UntaggedValue, Value};
pub struct Find;
impl WholeStreamCommand for Find {
fn name(&self) -> &str {
"find"
}
fn signature(&self) -> Signature {
Signature::build("find").rest("rest", SyntaxShape::String, "search term")
}
fn usage(&self) -> &str {
"Find text in the output of a previous command"
}
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
find(args)
}
fn examples(&self) -> Vec<Example> {
vec![
Example {
description: "Search pipeline output for multiple terms",
example: r#"ls | find toml md sh"#,
result: None,
},
Example {
description: "Search strings for term(s)",
example: r#"echo Cargo.toml | find toml"#,
result: Some(vec![Value::from("Cargo.toml")]),
},
Example {
description: "Search a number list for term(s)",
example: r#"[1 2 3 4 5] | find 5"#,
result: Some(vec![UntaggedValue::int(5).into()]),
},
Example {
description: "Search string list for term(s)",
example: r#"[moe larry curly] | find l"#,
result: Some(vec![Value::from("larry"), Value::from("curly")]),
},
]
}
}
fn row_contains(row: &Dictionary, search_terms: Vec<String>) -> bool {
for term in search_terms {
for (k, v) in &row.entries {
let key = k.to_string().trim().to_lowercase();
let value = v.convert_to_string().trim().to_lowercase();
if key.contains(&term) || value.contains(&term) {
return true;
}
}
}
false
}
fn find(args: CommandArgs) -> Result<OutputStream, ShellError> {
let rest: Vec<Value> = args.rest(0)?;
Ok(args
.input
.filter(move |row| match &row.value {
UntaggedValue::Row(row) => {
let sterms: Vec<String> = rest
.iter()
.map(|t| t.convert_to_string().trim().to_lowercase())
.collect();
row_contains(row, sterms)
}
UntaggedValue::Primitive(_p) => {
// eprint!("prim {}", p.type_name());
let sterms: Vec<String> = rest
.iter()
.map(|t| t.convert_to_string().trim().to_lowercase())
.collect();
let prim_string = &row.convert_to_string().trim().to_lowercase();
for term in sterms {
if prim_string.contains(&term) {
return true;
}
}
false
}
_ => false,
})
.into_output_stream())
}
#[cfg(test)]
mod tests {
use super::Find;
use super::ShellError;
#[test]
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(Find {})
}
}

View File

@ -18,7 +18,11 @@ impl WholeStreamCommand for Help {
fn signature(&self) -> Signature {
Signature::build("help")
.rest(SyntaxShape::String, "the name of command to get help on")
.rest(
"rest",
SyntaxShape::String,
"the name of command to get help on",
)
.named(
"find",
SyntaxShape::String,
@ -298,7 +302,7 @@ pub fn signature_dict(signature: Signature, tag: impl Into<Tag>) -> Value {
let tag = tag.into();
let mut sig = TaggedListBuilder::new(&tag);
for arg in signature.positional.iter() {
for arg in &signature.positional {
let is_required = matches!(arg.0, PositionalType::Mandatory(_, _));
sig.push_value(for_spec(arg.0.name(), "argument", is_required, &tag));
@ -309,7 +313,7 @@ pub fn signature_dict(signature: Signature, tag: impl Into<Tag>) -> Value {
sig.push_value(for_spec("rest", "argument", is_required, &tag));
}
for (name, ty) in signature.named.iter() {
for (name, ty) in &signature.named {
match ty.0 {
NamedType::Mandatory(_, _) => sig.push_value(for_spec(name, "flag", true, &tag)),
NamedType::Optional(_, _) => sig.push_value(for_spec(name, "flag", false, &tag)),

View File

@ -100,14 +100,14 @@ fn if_command(args: CommandArgs) -> Result<OutputStream, ShellError> {
context.scope.add_vars(&condition.captured.entries);
//FIXME: should we use the scope that's brought in as well?
let condition = evaluate_baseline_expr(cond, &*context);
let condition = evaluate_baseline_expr(cond, &context);
match condition {
Ok(condition) => match condition.as_bool() {
Ok(b) => {
let result = if b {
run_block(&then_case.block, &*context, input, external_redirection)
run_block(&then_case.block, &context, input, external_redirection)
} else {
run_block(&else_case.block, &*context, input, external_redirection)
run_block(&else_case.block, &context, input, external_redirection)
};
context.scope.exit_scope();

View File

@ -4,6 +4,8 @@ mod def;
mod describe;
mod do_;
pub(crate) mod echo;
mod error;
mod find;
mod help;
mod history;
mod if_;
@ -27,6 +29,8 @@ pub use def::Def;
pub use describe::Describe;
pub use do_::Do;
pub use echo::Echo;
pub use error::*;
pub use find::Find;
pub use help::Help;
pub use history::History;
pub use if_::If;

View File

@ -4,7 +4,7 @@ use crate::prelude::*;
use nu_engine::WholeStreamCommand;
use nu_errors::ShellError;
use nu_path::canonicalize;
use nu_path::canonicalize_with;
use nu_protocol::{CommandAction, ReturnSuccess, Signature, SyntaxShape, UntaggedValue};
use nu_source::Tagged;
@ -56,7 +56,7 @@ impl WholeStreamCommand for SubCommand {
tag,
}) = load_path
{
let path = canonicalize(shell_manager.path(), load_path).map_err(|_| {
let path = canonicalize_with(load_path, shell_manager.path()).map_err(|_| {
ShellError::labeled_error(
"Cannot load plugins from directory",
"directory not found",

View File

@ -41,7 +41,7 @@ impl WholeStreamCommand for Command {
"custom configuration source file",
None,
)
.rest(SyntaxShape::String, "source file(s) to run")
.rest("rest", SyntaxShape::String, "source file(s) to run")
}
fn usage(&self) -> &str {

View File

@ -2,11 +2,11 @@ use crate::prelude::*;
use nu_engine::{script, WholeStreamCommand};
use nu_errors::ShellError;
use nu_path::expand_path;
use nu_path::{canonicalize, canonicalize_with};
use nu_protocol::{Signature, SyntaxShape};
use nu_source::Tagged;
use std::{borrow::Cow, path::Path};
use std::path::Path;
pub struct Source;
@ -32,7 +32,7 @@ impl WholeStreamCommand for Source {
"Runs a script file in the current context."
}
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
source(args)
}
@ -41,14 +41,68 @@ impl WholeStreamCommand for Source {
}
}
pub fn source(args: CommandArgs) -> Result<ActionStream, ShellError> {
pub fn source(args: CommandArgs) -> Result<OutputStream, ShellError> {
let ctx = &args.context;
let filename: Tagged<String> = args.req(0)?;
let source_file = Path::new(&filename.item);
// Note: this is a special case for setting the context from a command
// In this case, if we don't set it now, we'll lose the scope that this
// variable should be set into.
let contents = std::fs::read_to_string(&expand_path(Cow::Borrowed(Path::new(&filename.item))));
let lib_dirs = &ctx
.configs()
.lock()
.global_config
.as_ref()
.map(|configuration| match configuration.var("lib_dirs") {
Some(paths) => paths
.table_entries()
.cloned()
.map(|path| path.as_string())
.collect(),
None => vec![],
});
if let Some(dir) = lib_dirs {
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(),
)
})?;
if let Ok(contents) = std::fs::read_to_string(path) {
let result = script::run_script_standalone(contents, true, ctx, false);
if let Err(err) = result {
ctx.error(err);
}
return Ok(OutputStream::empty());
}
}
Err(reason) => {
ctx.error(reason.clone());
}
}
}
}
let path = canonicalize(source_file).map_err(|e| {
ShellError::labeled_error(
format!("Can't load source file. Reason: {}", e.to_string()),
"Can't load this file",
filename.span(),
)
})?;
let contents = std::fs::read_to_string(path);
match contents {
Ok(contents) => {
let result = script::run_script_standalone(contents, true, ctx, false);
@ -56,16 +110,16 @@ pub fn source(args: CommandArgs) -> Result<ActionStream, ShellError> {
if let Err(err) = result {
ctx.error(err);
}
Ok(ActionStream::empty())
Ok(OutputStream::empty())
}
Err(_) => {
Err(e) => {
ctx.error(ShellError::labeled_error(
"Can't load file to source",
"can't load file",
format!("Can't load source file. Reason: {}", e.to_string()),
"Can't load this file",
filename.span(),
));
Ok(ActionStream::empty())
Ok(OutputStream::empty())
}
}
}

View File

@ -1,7 +1,7 @@
use crate::prelude::*;
use nu_engine::WholeStreamCommand;
use nu_errors::ShellError;
use nu_protocol::{Signature, TaggedDictBuilder, UntaggedValue};
use nu_protocol::{Primitive, Signature, TaggedDictBuilder, UntaggedValue, Value};
pub struct Tags;
@ -18,37 +18,64 @@ impl WholeStreamCommand for Tags {
"Read the tags (metadata) for values."
}
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
Ok(tags(args))
}
}
fn tags(args: CommandArgs) -> ActionStream {
args.input
.map(move |v| {
let mut tags = TaggedDictBuilder::new(v.tag());
{
let anchor = v.anchor();
let span = v.tag.span;
let mut dict = TaggedDictBuilder::new(v.tag());
dict.insert_untagged("start", UntaggedValue::int(span.start() as i64));
dict.insert_untagged("end", UntaggedValue::int(span.end() as i64));
tags.insert_value("span", dict.into_value());
fn build_tag_table(tag: impl Into<Tag>) -> Value {
let tag = tag.into();
let span = tag.span;
match anchor {
Some(AnchorLocation::File(source)) => {
tags.insert_untagged("anchor", UntaggedValue::string(source));
}
Some(AnchorLocation::Url(source)) => {
tags.insert_untagged("anchor", UntaggedValue::string(source));
}
_ => {}
}
TaggedDictBuilder::build(tag.clone(), |tags| {
if let Some(anchor) = anchor_as_value(&tag) {
tags.insert_value("anchor", anchor);
}
tags.insert_value(
"span",
TaggedDictBuilder::build(tag.clone(), |span_dict| {
span_dict.insert_untagged("start", UntaggedValue::int(span.start() as i64));
span_dict.insert_untagged("end", UntaggedValue::int(span.end() as i64));
}),
);
})
}
fn tags(args: CommandArgs) -> OutputStream {
if args.input.is_empty() {
OutputStream::one(build_tag_table(&args.name_tag()))
} else {
args.input
.map(move |v| build_tag_table(v.tag()))
.into_output_stream()
}
}
fn anchor_as_value(tag: &Tag) -> Option<Value> {
let anchor = tag.anchor.as_ref();
anchor.as_ref()?;
Some(TaggedDictBuilder::build(tag, |table| {
let value = match anchor {
Some(AnchorLocation::File(path)) => {
Some(("file", UntaggedValue::from(path.to_string())))
}
Some(AnchorLocation::Url(destination)) => {
Some(("url", UntaggedValue::from(destination.to_string())))
}
Some(AnchorLocation::Source(text)) => Some((
"source",
UntaggedValue::Primitive(Primitive::String(text.to_string())),
)),
None => None,
};
tags.into_value()
})
.into_action_stream()
if let Some((key, value)) = value {
table.insert_untagged(key, value);
}
}))
}
#[cfg(test)]

View File

@ -56,7 +56,7 @@ fn tutor(args: CommandArgs) -> Result<OutputStream, ShellError> {
let search: Option<String> = args.opt(0).unwrap_or(None);
let find: Option<String> = args.get_flag("find")?;
let search_space = vec![
let search_space = [
(vec!["begin"], begin_tutor()),
(
vec!["table", "tables", "row", "rows", "column", "columns"],
@ -88,7 +88,7 @@ fn tutor(args: CommandArgs) -> Result<OutputStream, ShellError> {
if let Some(find) = find {
let mut results = vec![];
for search_group in search_space {
if search_group.1.contains(&find.as_str()) {
if search_group.1.contains(&find) {
results.push(search_group.0[0].to_string())
}
}
@ -383,7 +383,7 @@ fn display(tag: Tag, scope: &Scope, help: &str) -> OutputStream {
//TODO: support no-color mode
let colored_example = nu_engine::Painter::paint_string(item, scope, &palette);
build.push_str(&format!("{}", colored_example));
build.push_str(&colored_example);
} else {
code_mode = true;
build.push_str(item);

View File

@ -245,7 +245,7 @@ fn perform_groupby_aggregation(
None => &col[..],
};
res.rename(col.as_str(), new_col)
res.rename(&col, new_col)
.expect("Column is always there. Looping with known names");
}
}

View File

@ -107,7 +107,7 @@ fn command(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
let other: Value = args.req_named("other")?;
let axis: Tagged<String> = args.req_named("axis")?;
let axis = Axis::try_from_str(axis.item.as_str(), &axis.tag.span)?;
let axis = Axis::try_from_str(&axis.item, &axis.tag.span)?;
let df_other = match other.value {
UntaggedValue::DataFrame(df) => Ok(df),

View File

@ -53,7 +53,7 @@ fn command(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
let res = df
.as_ref()
.column(column.item.as_ref())
.column(&column.item)
.map_err(|e| parse_polars_error::<&str>(&e, &column.tag.span, None))?;
let df = NuDataFrame::try_from_series(vec![res.clone()], &tag.span)?;

View File

@ -195,7 +195,7 @@ fn command(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
let name = format!("{} ({})", col.name(), col.dtype());
ChunkedArray::<Float64Type>::new_from_opt_slice(
name.as_str(),
&name,
&[
Some(count),
sum,

View File

@ -20,7 +20,11 @@ impl WholeStreamCommand for DataFrame {
}
fn signature(&self) -> Signature {
Signature::build("dataframe drop").rest(SyntaxShape::Any, "column names to be dropped")
Signature::build("dataframe drop").rest(
"rest",
SyntaxShape::Any,
"column names to be dropped",
)
}
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {

View File

@ -72,7 +72,7 @@ fn command(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
.expect("using name from list of names from dataframe")
.dtype();
let dtype_str = format!("{}", dtype);
let dtype_str = dtype.to_string();
dtypes.push(Value {
value: dtype_str.into(),
tag: Tag::default(),

View File

@ -19,7 +19,11 @@ impl WholeStreamCommand for DataFrame {
}
fn signature(&self) -> Signature {
Signature::build("dataframe get").rest(SyntaxShape::Any, "column names to sort dataframe")
Signature::build("dataframe get").rest(
"rest",
SyntaxShape::Any,
"column names to sort dataframe",
)
}
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {

View File

@ -20,7 +20,7 @@ impl WholeStreamCommand for DataFrame {
}
fn signature(&self) -> Signature {
Signature::build("dataframe group-by").rest(SyntaxShape::Any, "groupby columns")
Signature::build("dataframe group-by").rest("rest", SyntaxShape::Any, "groupby columns")
}
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {

View File

@ -177,7 +177,7 @@ fn check_column_datatypes<T: AsRef<str>>(
));
}
for (l, r) in l_cols.iter().zip(r_cols.iter()) {
for (l, r) in l_cols.iter().zip(r_cols) {
let l_series = df_l
.column(l.as_ref())
.map_err(|e| parse_polars_error::<&str>(&e, l_col_span, None))?;

View File

@ -5,6 +5,7 @@ use nu_protocol::{
dataframe::{Column, NuDataFrame},
Signature, SyntaxShape, UntaggedValue, Value,
};
use nu_source::Tagged;
use super::utils::convert_columns;
@ -33,6 +34,18 @@ impl WholeStreamCommand for DataFrame {
"column names used as value columns",
Some('v'),
)
.named(
"variable_name",
SyntaxShape::String,
"optional name for variable column",
Some('r'),
)
.named(
"value_name",
SyntaxShape::String,
"optional name for value column",
Some('l'),
)
}
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
@ -105,6 +118,9 @@ fn command(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
let id_col: Vec<Value> = args.req_named("columns")?;
let val_col: Vec<Value> = args.req_named("values")?;
let value_name: Option<Tagged<String>> = args.get_flag("value_name")?;
let variable_name: Option<Tagged<String>> = args.get_flag("variable_name")?;
let (id_col_string, id_col_span) = convert_columns(&id_col, &tag)?;
let (val_col_string, val_col_span) = convert_columns(&val_col, &tag)?;
@ -113,11 +129,21 @@ fn command(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
check_column_datatypes(df.as_ref(), &id_col_string, &id_col_span)?;
check_column_datatypes(df.as_ref(), &val_col_string, &val_col_span)?;
let res = df
let mut res = df
.as_ref()
.melt(&id_col_string, &val_col_string)
.map_err(|e| parse_polars_error::<&str>(&e, &tag.span, None))?;
if let Some(name) = &variable_name {
res.rename("variable", &name.item)
.map_err(|e| parse_polars_error::<&str>(&e, &name.tag.span, None))?;
}
if let Some(name) = &value_name {
res.rename("value", &name.item)
.map_err(|e| parse_polars_error::<&str>(&e, &name.tag.span, None))?;
}
Ok(OutputStream::one(NuDataFrame::dataframe_to_value(res, tag)))
}

View File

@ -18,6 +18,7 @@ pub mod list;
pub mod melt;
pub mod open;
pub mod pivot;
pub mod rename;
pub mod sample;
pub mod select;
pub mod shape;
@ -52,6 +53,7 @@ pub use list::DataFrame as DataFrameList;
pub use melt::DataFrame as DataFrameMelt;
pub use open::DataFrame as DataFrameOpen;
pub use pivot::DataFrame as DataFramePivot;
pub use rename::DataFrame as DataFrameRename;
pub use sample::DataFrame as DataFrameSample;
pub use select::DataFrame as DataFrameSelect;
pub use shape::DataFrame as DataFrameShape;

View File

@ -100,7 +100,7 @@ fn command(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
let mut groupby = nu_groupby.to_groupby()?;
let pivot = groupby.pivot(pivot_col.item.as_ref(), value_col.item.as_ref());
let pivot = groupby.pivot(&pivot_col.item, &value_col.item);
let res = match op {
Operation::Mean => pivot.mean(),
@ -120,7 +120,7 @@ fn check_pivot_column(
col: &Tagged<String>,
) -> Result<(), ShellError> {
let series = df
.column(col.item.as_ref())
.column(&col.item)
.map_err(|e| parse_polars_error::<&str>(&e, &col.tag.span, None))?;
match series.dtype() {
@ -146,7 +146,7 @@ fn check_value_column(
col: &Tagged<String>,
) -> Result<(), ShellError> {
let series = df
.column(col.item.as_ref())
.column(&col.item)
.map_err(|e| parse_polars_error::<&str>(&e, &col.tag.span, None))?;
match series.dtype() {

View File

@ -0,0 +1,81 @@
use crate::prelude::*;
use nu_engine::WholeStreamCommand;
use nu_errors::ShellError;
use nu_protocol::{
dataframe::{Column, NuDataFrame},
Signature, SyntaxShape, UntaggedValue,
};
use nu_source::Tagged;
use super::utils::parse_polars_error;
pub struct DataFrame;
impl WholeStreamCommand for DataFrame {
fn name(&self) -> &str {
"dataframe rename-col"
}
fn usage(&self) -> &str {
"[DataFrame] rename a dataframe column"
}
fn signature(&self) -> Signature {
Signature::build("dataframe rename-col")
.required("from", SyntaxShape::String, "column name to be renamed")
.required("to", SyntaxShape::String, "new column name")
}
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
command(args)
}
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Renames a dataframe column",
example: "[[a b]; [1 2] [3 4]] | dataframe to-df | dataframe rename-col a ab",
result: Some(vec![NuDataFrame::try_from_columns(
vec![
Column::new(
"ab".to_string(),
vec![UntaggedValue::int(1).into(), UntaggedValue::int(3).into()],
),
Column::new(
"b".to_string(),
vec![UntaggedValue::int(2).into(), UntaggedValue::int(4).into()],
),
],
&Span::default(),
)
.expect("simple df for test should not fail")
.into_value(Tag::default())]),
}]
}
}
fn command(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
let tag = args.call_info.name_tag.clone();
let from: Tagged<String> = args.req(0)?;
let to: Tagged<String> = args.req(1)?;
let (mut df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?;
df.as_mut()
.rename(&from.item, &to.item)
.map_err(|e| parse_polars_error::<&str>(&e, &df_tag.span, None))?;
Ok(OutputStream::one(df.into_value(tag)))
}
#[cfg(test)]
mod tests {
use super::DataFrame;
use super::ShellError;
#[test]
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test_dataframe as test_examples;
test_examples(DataFrame {})
}
}

View File

@ -20,7 +20,7 @@ impl WholeStreamCommand for DataFrame {
}
fn signature(&self) -> Signature {
Signature::build("dataframe select").rest(SyntaxShape::Any, "selected column names")
Signature::build("dataframe select").rest("rest", SyntaxShape::Any, "selected column names")
}
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {

View File

@ -68,7 +68,7 @@ fn command(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
})?;
let res = chunked
.contains(pattern.as_str())
.contains(&pattern.item)
.map_err(|e| parse_polars_error::<&str>(&e, &tag.span, None))?;
let df = NuDataFrame::try_from_series(vec![res.into_series()], &tag.span)?;

View File

@ -99,7 +99,7 @@ fn command(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
));
}
let cum_type = CumType::from_str(cum_type.item.as_str(), &cum_type.tag.span)?;
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),

View File

@ -60,7 +60,7 @@ fn command(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
let mut series = df.as_series(&df_tag.span)?;
series.rename(name.item.as_ref());
series.rename(&name.item);
let df = NuDataFrame::try_from_series(vec![series], &tag.span)?;
Ok(OutputStream::one(df.into_value(df_tag)))

View File

@ -77,7 +77,7 @@ fn command(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
})?;
let mut res = chunked
.replace(pattern.as_str(), replace.as_str())
.replace(&pattern.item, &replace.item)
.map_err(|e| parse_polars_error::<&str>(&e, &tag.span, None))?;
res.rename(series.name());

View File

@ -77,7 +77,7 @@ fn command(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
})?;
let mut res = chunked
.replace_all(pattern.as_str(), replace.as_str())
.replace_all(&pattern.item, &replace.item)
.map_err(|e| parse_polars_error::<&str>(&e, &tag.span, None))?;
res.rename(series.name());

View File

@ -125,7 +125,7 @@ fn command(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
));
}
let roll_type = RollType::from_str(roll_type.item.as_str(), &roll_type.tag.span)?;
let roll_type = RollType::from_str(&roll_type.item, &roll_type.tag.span)?;
let res = match roll_type {
RollType::Max => series.rolling_max(
window_size.item as u32,

View File

@ -61,7 +61,7 @@ fn command(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
.date64()
.map_err(|e| parse_polars_error::<&str>(&e, &df_tag.span, None))?;
let res = casted.strftime(fmt.item.as_str()).into_series();
let res = casted.strftime(&fmt.item).into_series();
let df = NuDataFrame::try_from_series(vec![res], &tag.span)?;
Ok(OutputStream::one(df.into_value(df_tag)))
}

View File

@ -21,7 +21,7 @@ impl WholeStreamCommand for DataFrame {
fn signature(&self) -> Signature {
Signature::build("dataframe sort")
.switch("reverse", "invert sort", Some('r'))
.rest(SyntaxShape::Any, "column names to sort dataframe")
.rest("rest", SyntaxShape::Any, "column names to sort dataframe")
}
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {

View File

@ -64,14 +64,10 @@ fn command(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
let delimiter: Option<Tagged<String>> = args.get_flag("delimiter")?;
let no_header: bool = args.has_flag("no_header");
let (mut df, _) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?;
let (df, _) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?;
let mut file = File::create(&file_name.item).map_err(|e| {
ShellError::labeled_error(
"Error with file name",
format!("{}", e),
&file_name.tag.span,
)
ShellError::labeled_error("Error with file name", e.to_string(), &file_name.tag.span)
})?;
let writer = CsvWriter::new(&mut file);
@ -103,7 +99,7 @@ fn command(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
};
writer
.finish(df.as_mut())
.finish(df.as_ref())
.map_err(|e| parse_polars_error::<&str>(&e, &file_name.tag.span, None))?;
let tagged_value = Value {

View File

@ -48,18 +48,14 @@ fn command(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
let tag = args.call_info.name_tag.clone();
let file_name: Tagged<PathBuf> = args.req(0)?;
let (mut df, _) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?;
let (df, _) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?;
let file = File::create(&file_name.item).map_err(|e| {
ShellError::labeled_error(
"Error with file name",
format!("{}", e),
&file_name.tag.span,
)
ShellError::labeled_error("Error with file name", e.to_string(), &file_name.tag.span)
})?;
ParquetWriter::new(file)
.finish(df.as_mut())
.finish(df.as_ref())
.map_err(|e| parse_polars_error::<&str>(&e, &file_name.tag.span, None))?;
let tagged_value = Value {

View File

@ -46,30 +46,32 @@ pub(crate) fn parse_polars_error<T: AsRef<str>>(
span: &Span,
secondary: Option<T>,
) -> ShellError {
let (msg, label) = match e {
PolarsError::PolarsArrowError(_) => ("PolarsArrow Error", format!("{}", e)),
PolarsError::ArrowError(_) => ("Arrow Error", format!("{}", e)),
PolarsError::InvalidOperation(_) => ("Invalid Operation", format!("{}", e)),
PolarsError::DataTypeMisMatch(_) => ("Data Type Mismatch", format!("{}", e)),
PolarsError::NotFound(_) => ("Not Found", format!("{}", e)),
PolarsError::ShapeMisMatch(_) => ("Shape Mismatch", format!("{}", e)),
PolarsError::Other(_) => ("Other", format!("{}", e)),
PolarsError::OutOfBounds(_) => ("Out Of Bounds", format!("{}", e)),
PolarsError::NoSlice => ("No Slice", format!("{}", e)),
PolarsError::NoData(_) => ("No Data", format!("{}", e)),
PolarsError::ValueError(_) => ("Value Error", format!("{}", e)),
PolarsError::MemoryNotAligned => ("Memory Not Aligned", format!("{}", e)),
PolarsError::ParquetError(_) => ("Parquet Error", format!("{}", e)),
PolarsError::RandError(_) => ("Rand Error", format!("{}", e)),
PolarsError::HasNullValues(_) => ("Has Null Values", format!("{}", e)),
PolarsError::UnknownSchema(_) => ("Unknown Schema", format!("{}", e)),
PolarsError::Various(_) => ("Various", format!("{}", e)),
PolarsError::Io(_) => ("Io Error", format!("{}", e)),
PolarsError::Regex(_) => ("Regex Error", format!("{}", e)),
PolarsError::Duplicate(_) => ("Duplicate Error", format!("{}", e)),
PolarsError::ImplementationError => ("Implementation Error", format!("{}", e)),
let msg = match e {
PolarsError::PolarsArrowError(_) => "PolarsArrow Error",
PolarsError::ArrowError(_) => "Arrow Error",
PolarsError::InvalidOperation(_) => "Invalid Operation",
PolarsError::DataTypeMisMatch(_) => "Data Type Mismatch",
PolarsError::NotFound(_) => "Not Found",
PolarsError::ShapeMisMatch(_) => "Shape Mismatch",
PolarsError::Other(_) => "Other",
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",
PolarsError::Various(_) => "Various",
PolarsError::Io(_) => "Io Error",
PolarsError::Regex(_) => "Regex Error",
PolarsError::Duplicate(_) => "Duplicate Error",
PolarsError::ImplementationError => "Implementation Error",
};
let label = e.to_string();
match secondary {
None => ShellError::labeled_error(msg, label, span),
Some(s) => ShellError::labeled_error_with_secondary(msg, label, span, s.as_ref(), span),

View File

@ -82,7 +82,7 @@ fn command(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
let mut series = df.as_series(&value.tag.span)?;
let series = series.rename(name.item.as_ref()).clone();
let series = series.rename(&name.item).clone();
let (mut df, _) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?;

View File

@ -31,12 +31,12 @@ impl WholeStreamCommand for AutoenvTrust {
value: UntaggedValue::Primitive(Primitive::String(ref path)),
tag: _,
}) => {
let mut dir = fs::canonicalize(path)?;
let mut dir = nu_path::canonicalize(path)?;
dir.push(".nu-env");
dir
}
_ => {
let mut dir = fs::canonicalize(std::env::current_dir()?)?;
let mut dir = nu_path::canonicalize(std::env::current_dir()?)?;
dir.push(".nu-env");
dir
}

View File

@ -30,7 +30,7 @@ impl WholeStreamCommand for AutoenvUntrust {
value: UntaggedValue::Primitive(Primitive::String(ref path)),
tag: _,
}) => {
let mut dir = fs::canonicalize(path)?;
let mut dir = nu_path::canonicalize(path)?;
dir.push(".nu-env");
dir
}
@ -61,7 +61,7 @@ impl WholeStreamCommand for AutoenvUntrust {
let mut doc = String::new();
file.read_to_string(&mut doc)?;
let mut allowed: Trusted = toml::from_str(doc.as_str()).unwrap_or_else(|_| Trusted::new());
let mut allowed: Trusted = toml::from_str(&doc).unwrap_or_else(|_| Trusted::new());
let file_to_untrust = file_to_untrust.to_string_lossy().to_string();

View File

@ -1,5 +1,7 @@
use std::convert::TryInto;
use crate::prelude::*;
use nu_engine::{evaluate_baseline_expr, WholeStreamCommand};
use nu_engine::{evaluate_baseline_expr, EnvVar, WholeStreamCommand};
use nu_errors::ShellError;
use nu_protocol::{hir::CapturedBlock, hir::ClassifiedCommand, Signature, SyntaxShape};
@ -90,9 +92,7 @@ pub fn set_env(args: CommandArgs) -> Result<ActionStream, ShellError> {
ctx.scope.exit_scope();
let value = value?;
let value = value.as_string()?;
let value: EnvVar = value?.try_into()?;
let name = name.item;
// Note: this is a special case for setting the context from a command

View File

@ -1,5 +1,7 @@
use std::convert::TryInto;
use crate::prelude::*;
use nu_engine::WholeStreamCommand;
use nu_engine::{EnvVar, WholeStreamCommand};
use nu_errors::ShellError;
use nu_protocol::{Signature, SyntaxShape, Value};
@ -60,14 +62,17 @@ fn load_env_from_table(
for (key, value) in value.row_entries() {
if key == "name" {
var_name = Some(value.as_string()?);
var_name = Some(value);
} else if key == "value" {
var_value = Some(value.as_string()?);
var_value = Some(value);
}
}
match (var_name, var_value) {
(Some(name), Some(value)) => ctx.scope.add_env_var(name, value),
(Some(name), Some(value)) => {
let env_var: EnvVar = value.try_into()?;
ctx.scope.add_env_var(name.as_string()?, env_var);
}
_ => {
return Err(ShellError::labeled_error(
r#"Expected each row in the table to have a "name" and "value" field."#,

View File

@ -1,5 +1,8 @@
use std::convert::TryInto;
use crate::prelude::*;
use nu_engine::run_block;
use nu_engine::EnvVar;
use nu_engine::WholeStreamCommand;
use nu_errors::ShellError;
use nu_protocol::{
@ -73,20 +76,20 @@ fn with_env(args: CommandArgs) -> Result<ActionStream, ShellError> {
let variable: Value = args.req(0)?;
let block: CapturedBlock = args.req(1)?;
let mut env = IndexMap::new();
let mut env: IndexMap<String, EnvVar> = IndexMap::new();
match &variable.value {
UntaggedValue::Table(table) => {
if table.len() == 1 {
// single row([[X W]; [Y Z]])
for (k, v) in table[0].row_entries() {
env.insert(k.clone(), v.convert_to_string());
env.insert(k.clone(), v.try_into()?);
}
} else {
// primitive values([X Y W Z])
for row in table.chunks(2) {
if row.len() == 2 && row[0].is_primitive() && row[1].is_primitive() {
env.insert(row[0].convert_to_string(), row[1].convert_to_string());
env.insert(row[0].convert_to_string(), (&row[1]).try_into()?);
}
}
}
@ -94,7 +97,7 @@ fn with_env(args: CommandArgs) -> Result<ActionStream, ShellError> {
// when get object by `open x.json` or `from json`
UntaggedValue::Row(row) => {
for (k, v) in &row.entries {
env.insert(k.clone(), v.convert_to_string());
env.insert(k.clone(), v.try_into()?);
}
}
_ => {

View File

@ -12,6 +12,7 @@ impl WholeStreamCommand for Mkdir {
fn signature(&self) -> Signature {
Signature::build("mkdir")
.rest(
"rest",
SyntaxShape::FilePath,
"the name(s) of the path(s) to create",
)

View File

@ -6,6 +6,7 @@ use log::debug;
use nu_engine::StringOrBinary;
use nu_engine::WholeStreamCommand;
use nu_errors::ShellError;
use nu_path::canonicalize;
use nu_protocol::{CommandAction, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
use nu_source::{AnchorLocation, Span, Tagged};
use std::path::{Path, PathBuf};
@ -172,9 +173,9 @@ fn open(args: CommandArgs) -> Result<ActionStream, ShellError> {
Ok(StringOrBinary::String(s)) => {
ReturnSuccess::value(UntaggedValue::string(s).into_value(file_tag))
}
Ok(StringOrBinary::Binary(b)) => ReturnSuccess::value(
UntaggedValue::binary(b.into_iter().collect()).into_value(file_tag),
),
Ok(StringOrBinary::Binary(b)) => {
ReturnSuccess::value(UntaggedValue::binary(b).into_value(file_tag))
}
Err(se) => Err(se),
}
});
@ -193,7 +194,7 @@ pub fn fetch(
// TODO: I don't understand the point of this? Maybe for better error reporting
let mut cwd = PathBuf::from(cwd);
cwd.push(location);
let nice_location = dunce::canonicalize(&cwd).map_err(|e| match e.kind() {
let nice_location = canonicalize(&cwd).map_err(|e| match e.kind() {
std::io::ErrorKind::NotFound => ShellError::labeled_error(
format!("Cannot find file {:?}", cwd),
"cannot find file",

View File

@ -26,7 +26,11 @@ impl WholeStreamCommand for Remove {
)
.switch("recursive", "delete subdirectories recursively", Some('r'))
.switch("force", "suppress error when no file", Some('f'))
.rest(SyntaxShape::GlobPattern, "the file path(s) to remove")
.rest(
"rest",
SyntaxShape::GlobPattern,
"the file path(s) to remove",
)
}
fn usage(&self) -> &str {

View File

@ -142,6 +142,7 @@ impl WholeStreamCommand for Save {
"treat values as-is rather than auto-converting based on file extension",
Some('r'),
)
.switch("append", "append values rather than overriding", Some('a'))
}
fn usage(&self) -> &str {
@ -165,6 +166,7 @@ fn save(args: CommandArgs) -> Result<OutputStream, ShellError> {
let path: Option<Tagged<PathBuf>> = args.opt(0)?;
let save_raw = args.has_flag("raw");
let append = args.has_flag("append");
let input: Vec<Value> = args.input.collect();
if path.is_none() {
@ -231,7 +233,7 @@ fn save(args: CommandArgs) -> Result<OutputStream, ShellError> {
};
};
shell_manager.save(&full_path, &content?, name.span)
shell_manager.save(&full_path, &content?, name.span, append)
}
fn string_from(input: &[Value]) -> String {
@ -239,7 +241,7 @@ fn string_from(input: &[Value]) -> String {
if !input.is_empty() {
let mut first = true;
for i in input.iter() {
for i in input {
if !first {
save_data.push('\n');
} else {

View File

@ -19,7 +19,7 @@ impl WholeStreamCommand for Touch {
SyntaxShape::FilePath,
"the path of the file you want to create",
)
.rest(SyntaxShape::FilePath, "additional files to create")
.rest("rest", SyntaxShape::FilePath, "additional files to create")
}
fn usage(&self) -> &str {
"Creates one or more files."
@ -48,7 +48,7 @@ fn touch(args: CommandArgs) -> Result<ActionStream, ShellError> {
let target: Tagged<PathBuf> = args.req(0)?;
let rest: Vec<Tagged<PathBuf>> = args.rest(1)?;
for item in vec![target].into_iter().chain(rest.into_iter()) {
for item in vec![target].into_iter().chain(rest) {
match OpenOptions::new().write(true).create(true).open(&item) {
Ok(_) => continue,
Err(err) => {

View File

@ -45,7 +45,7 @@ impl WholeStreamCommand for Command {
Ok(prepend
.into_iter()
.chain(args.input.into_iter().chain(vec![value]))
.chain(args.input.into_iter().chain([value]))
.into_output_stream())
}

View File

@ -17,7 +17,11 @@ impl WholeStreamCommand for Compact {
}
fn signature(&self) -> Signature {
Signature::build("compact").rest(SyntaxShape::Any, "the columns to compact from the table")
Signature::build("compact").rest(
"rest",
SyntaxShape::Any,
"the columns to compact from the table",
)
}
fn usage(&self) -> &str {

View File

@ -18,7 +18,7 @@ impl WholeStreamCommand for SubCommand {
SyntaxShape::Int,
"the number of the row to drop",
)
.rest(SyntaxShape::Any, "Optionally drop more rows")
.rest("rest", SyntaxShape::Any, "Optionally drop more rows")
}
fn usage(&self) -> &str {

View File

@ -69,7 +69,7 @@ impl WholeStreamCommand for Each {
}
pub fn process_row(
captured_block: Arc<Box<CapturedBlock>>,
captured_block: Arc<CapturedBlock>,
context: Arc<EvaluationContext>,
input: Value,
external_redirection: ExternalRedirection,
@ -96,7 +96,7 @@ pub fn process_row(
let result = run_block(
&captured_block.block,
&*context,
&context,
input_stream,
external_redirection,
);
@ -121,13 +121,13 @@ fn each(args: CommandArgs) -> Result<OutputStream, ShellError> {
let block: CapturedBlock = args.req(0)?;
let numbered: bool = args.has_flag("numbered");
let block = Arc::new(Box::new(block));
let block = Arc::new(block);
if numbered {
Ok(args
.input
.enumerate()
.map(move |input| {
.flat_map(move |input| {
let block = block.clone();
let context = context.clone();
let row = make_indexed_item(input.0, input.1);
@ -137,12 +137,11 @@ fn each(args: CommandArgs) -> Result<OutputStream, ShellError> {
Err(e) => OutputStream::one(Value::error(e)),
}
})
.flatten()
.into_output_stream())
} else {
Ok(args
.input
.map(move |input| {
.flat_map(move |input| {
let block = block.clone();
let context = context.clone();
@ -151,7 +150,6 @@ fn each(args: CommandArgs) -> Result<OutputStream, ShellError> {
Err(e) => OutputStream::one(Value::error(e)),
}
})
.flatten()
.into_output_stream())
}
}

View File

@ -43,7 +43,7 @@ impl WholeStreamCommand for EachGroup {
let group_size: Tagged<usize> = args.req(0)?;
let block: CapturedBlock = args.req(1)?;
let block = Arc::new(Box::new(block));
let block = Arc::new(block);
let each_group_iterator = EachGroupIterator {
block,
@ -58,7 +58,7 @@ impl WholeStreamCommand for EachGroup {
}
struct EachGroupIterator {
block: Arc<Box<CapturedBlock>>,
block: Arc<CapturedBlock>,
context: Arc<EvaluationContext>,
group_size: usize,
input: InputStream,
@ -96,7 +96,7 @@ impl Iterator for EachGroupIterator {
pub(crate) fn run_block_on_vec(
input: Vec<Value>,
block: Arc<Box<CapturedBlock>>,
block: Arc<CapturedBlock>,
context: Arc<EvaluationContext>,
external_redirection: ExternalRedirection,
) -> OutputStream {

View File

@ -49,7 +49,7 @@ impl WholeStreamCommand for EachWindow {
let block: CapturedBlock = args.req(1)?;
let stride: Option<Tagged<usize>> = args.get_flag("stride")?;
let block = Arc::new(Box::new(block));
let block = Arc::new(block);
let mut window: Vec<_> = args
.input
@ -64,7 +64,7 @@ impl WholeStreamCommand for EachWindow {
Ok(args
.input
.enumerate()
.map(move |(i, input)| {
.flat_map(move |(i, input)| {
// This would probably be more efficient if `last` was a VecDeque
// But we can't have that because it needs to be put into a Table
window.remove(0);
@ -86,7 +86,6 @@ impl WholeStreamCommand for EachWindow {
}
})
.flatten()
.flatten()
.map(Ok)
.into_input_stream())
}

View File

@ -19,6 +19,7 @@ impl WholeStreamCommand for Command {
fn signature(&self) -> Signature {
Signature::build("empty?")
.rest(
"rest",
SyntaxShape::ColumnPath,
"the names of the columns to check emptiness",
)
@ -139,7 +140,7 @@ fn process_row(
let stream = run_block(
&default_block.block,
&*context,
context,
input_stream,
ExternalRedirection::Stdout,
);

View File

@ -14,7 +14,11 @@ impl WholeStreamCommand for Command {
}
fn signature(&self) -> Signature {
Signature::build("flatten").rest(SyntaxShape::String, "optionally flatten data by column")
Signature::build("flatten").rest(
"rest",
SyntaxShape::String,
"optionally flatten data by column",
)
}
fn usage(&self) -> &str {
@ -52,8 +56,7 @@ fn flatten(args: CommandArgs) -> Result<ActionStream, ShellError> {
let input = args.input;
Ok(input
.map(move |item| flat_value(&columns, &item, &tag).into_iter())
.flatten()
.flat_map(move |item| flat_value(&columns, &item, &tag))
.into_action_stream())
}
@ -92,7 +95,7 @@ fn flat_value(
continue;
}
for (k, v) in mapa.into_iter() {
for (k, v) in mapa {
if out.contains_key(k) {
out.insert_value(format!("{}_{}", column, k), v.clone());
} else {
@ -155,7 +158,7 @@ fn flat_value(
let mut expanded = vec![];
if let Some(TableInside::Entries(column, _, entries)) = a_table {
for entry in entries.into_iter() {
for entry in entries {
let mut base = out.clone();
base.insert_value(column, entry.clone());
expanded.push(base.into_value());
@ -166,7 +169,7 @@ fn flat_value(
expanded
} else if item.is_table() {
item.table_entries().map(Clone::clone).collect()
item.table_entries().cloned().collect()
} else {
vec![item.clone()]
}

View File

@ -19,6 +19,7 @@ impl WholeStreamCommand for Command {
fn signature(&self) -> Signature {
Signature::build("get").rest(
"rest",
SyntaxShape::ColumnPath,
"optionally return additional data by path",
)
@ -64,14 +65,12 @@ pub fn get(args: CommandArgs) -> Result<ActionStream, ShellError> {
} else {
trace!("get {:?}", column_paths);
let output_stream = input
.map(move |item| {
.flat_map(move |item| {
column_paths
.iter()
.map(move |path| get_output(&item, path))
.flatten()
.flat_map(move |path| get_output(&item, path))
.collect::<Vec<_>>()
})
.flatten()
.into_action_stream();
Ok(output_stream)
}

View File

@ -137,10 +137,10 @@ pub fn group_by(args: CommandArgs) -> Result<OutputStream, ShellError> {
value: UntaggedValue::Block(block_given),
..
}) => {
let block = Arc::new(block_given);
let block = Arc::new(*block_given);
let error_key = "error";
for value in values.iter() {
for value in &values {
let run = block.clone();
let context = context.clone();

View File

@ -80,7 +80,7 @@ fn process_row(
let result = run_block(
&block.block,
&*context,
&context,
input_stream,
ExternalRedirection::Stdout,
);
@ -162,7 +162,7 @@ fn insert(args: CommandArgs) -> Result<ActionStream, ShellError> {
let column = Arc::new(column);
Ok(input
.map(move |input| {
.flat_map(move |input| {
let context = context.clone();
let value = value.clone();
let column = column.clone();
@ -172,6 +172,5 @@ fn insert(args: CommandArgs) -> Result<ActionStream, ShellError> {
Err(e) => ActionStream::one(Err(e)),
}
})
.flatten()
.into_action_stream())
}

View File

@ -74,7 +74,7 @@ impl WholeStreamCommand for SubCommand {
ctx.scope.add_var(arg.name(), item.clone());
}
let result = evaluate_baseline_expr(&*condition, &*ctx);
let result = evaluate_baseline_expr(&condition, &ctx);
ctx.scope.exit_scope();
!matches!(result, Ok(ref v) if v.is_true())

View File

@ -76,7 +76,7 @@ impl WholeStreamCommand for SubCommand {
}
trace!("ITEM = {:?}", item);
let result = evaluate_baseline_expr(&*condition, &*ctx);
let result = evaluate_baseline_expr(&condition, &ctx);
ctx.scope.exit_scope();
trace!("RESULT = {:?}", result);

View File

@ -14,7 +14,7 @@ impl WholeStreamCommand for Command {
fn signature(&self) -> Signature {
Signature::build("move")
.rest(SyntaxShape::ColumnPath, "the columns to move")
.rest("rest", SyntaxShape::ColumnPath, "the columns to move")
.named(
"after",
SyntaxShape::ColumnPath,
@ -242,7 +242,7 @@ fn move_after(table: &Value, columns: &[String], from: &ColumnPath) -> Result<Va
let mut insert = false;
let mut inserted = false;
for name in columns_moved.into_iter() {
for name in columns_moved {
if let Some(name) = name {
reordered_columns.push(Some(name.clone()));
@ -291,7 +291,7 @@ fn move_before(table: &Value, columns: &[String], from: &ColumnPath) -> Result<V
let mut reordered_columns = vec![];
let mut inserted = false;
for name in columns_moved.into_iter() {
for name in columns_moved {
if let Some(name) = name {
if !inserted && name == from {
for column in columns {

View File

@ -18,7 +18,7 @@ impl WholeStreamCommand for Nth {
SyntaxShape::Int,
"the number of the row to return",
)
.rest(SyntaxShape::Any, "Optionally return more rows")
.rest("rest", SyntaxShape::Any, "Optionally return more rows")
.switch("skip", "Skip the rows instead of selecting them", Some('s'))
}

View File

@ -36,6 +36,7 @@ impl WholeStreamCommand for Pivot {
Some('i'),
)
.rest(
"rest",
SyntaxShape::String,
"the names to give columns once pivoted",
)

View File

@ -163,7 +163,7 @@ fn reduce(args: CommandArgs) -> Result<ActionStream, ShellError> {
context.scope.enter_scope();
context.scope.add_var("$acc", f);
let result = process_row(block, &*context, row);
let result = process_row(block, &context, row);
context.scope.exit_scope();
// we make sure that result is an indexed item
@ -201,7 +201,7 @@ fn reduce(args: CommandArgs) -> Result<ActionStream, ShellError> {
context.scope.enter_scope();
context.scope.add_var("$acc", f);
let result = process_row(block, &*context, row);
let result = process_row(block, &context, row);
context.scope.exit_scope();
result
})?

View File

@ -13,7 +13,11 @@ impl WholeStreamCommand for Reject {
}
fn signature(&self) -> Signature {
Signature::build("reject").rest(SyntaxShape::String, "the names of columns to remove")
Signature::build("reject").rest(
"rest",
SyntaxShape::String,
"the names of columns to remove",
)
}
fn usage(&self) -> &str {

View File

@ -19,7 +19,11 @@ impl WholeStreamCommand for Rename {
SyntaxShape::String,
"the new name for the first column",
)
.rest(SyntaxShape::String, "the new name for additional columns")
.rest(
"rest",
SyntaxShape::String,
"the new name for additional columns",
)
}
fn usage(&self) -> &str {

View File

@ -59,14 +59,12 @@ pub fn roll(args: CommandArgs) -> Result<OutputStream, ShellError> {
Ok(args
.input
.map(move |value| {
.flat_map(move |value| {
let tag = value.tag();
roll_by(value, &options)
.unwrap_or_else(|| vec![UntaggedValue::nothing().into_value(tag)])
.into_iter()
})
.flatten()
.into_output_stream())
}
@ -84,8 +82,7 @@ fn roll_by(value: Value, options: &Arguments) -> Option<Vec<Value>> {
let values_rotated = rotate(
value
.row_entries()
.map(|(_, value)| value)
.map(Clone::clone)
.map(|(_, value)| value.clone())
.collect::<Vec<_>>(),
&options.by,
direction,
@ -94,7 +91,7 @@ fn roll_by(value: Value, options: &Arguments) -> Option<Vec<Value>> {
if let Some(ref values) = values_rotated {
let mut out = TaggedDictBuilder::new(&tag);
for (k, v) in columns.iter().zip(values.iter()) {
for (k, v) in columns.iter().zip(values) {
out.insert_value(k, v.clone());
}
@ -104,7 +101,7 @@ fn roll_by(value: Value, options: &Arguments) -> Option<Vec<Value>> {
None
} else if value.is_table() {
rotate(
value.table_entries().map(Clone::clone).collect(),
value.table_entries().cloned().collect(),
&options.by,
direction,
)

View File

@ -17,6 +17,7 @@ impl WholeStreamCommand for Command {
fn signature(&self) -> Signature {
Signature::build("rotate").rest(
"rest",
SyntaxShape::String,
"the names to give columns once rotated",
)

View File

@ -17,6 +17,7 @@ impl WholeStreamCommand for SubCommand {
fn signature(&self) -> Signature {
Signature::build("rotate counter-clockwise").rest(
"rest",
SyntaxShape::String,
"the names to give columns once rotated",
)

View File

@ -16,6 +16,7 @@ impl WholeStreamCommand for Command {
fn signature(&self) -> Signature {
Signature::build("select").rest(
"rest",
SyntaxShape::ColumnPath,
"the columns to select from the table",
)

View File

@ -76,7 +76,7 @@ impl WholeStreamCommand for SubCommand {
}
trace!("ITEM = {:?}", item);
let result = evaluate_baseline_expr(&*condition, &*ctx);
let result = evaluate_baseline_expr(&condition, &ctx);
ctx.scope.exit_scope();
trace!("RESULT = {:?}", result);

View File

@ -77,7 +77,7 @@ impl WholeStreamCommand for SubCommand {
}
trace!("ITEM = {:?}", item);
let result = evaluate_baseline_expr(&*condition, &*ctx);
let result = evaluate_baseline_expr(&condition, &ctx);
ctx.scope.exit_scope();
trace!("RESULT = {:?}", result);

View File

@ -21,7 +21,7 @@ impl WholeStreamCommand for SortBy {
Some('i'),
)
.switch("reverse", "Sort in reverse order", Some('r'))
.rest(SyntaxShape::String, "the column(s) to sort by")
.rest("rest", SyntaxShape::String, "the column(s) to sort by")
}
fn usage(&self) -> &str {
@ -118,7 +118,7 @@ fn sort_by(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
vec.reverse()
}
Ok((vec.into_iter()).into_output_stream())
Ok(vec.into_iter().into_output_stream())
}
pub fn sort(
@ -137,7 +137,7 @@ pub fn sort(
));
}
for sort_arg in keys.iter() {
for sort_arg in keys {
let match_test = &vec[0].get_data_by_key(sort_arg.borrow_spanned());
if match_test.is_none() {
return Err(ShellError::labeled_error(

View File

@ -66,7 +66,6 @@ fn process_row(
field: Arc<ColumnPath>,
tag: Arc<Tag>,
) -> Result<ActionStream, ShellError> {
let tag = &*tag;
let replacement = Arc::make_mut(&mut replacement);
Ok(match replacement {
@ -86,7 +85,7 @@ fn process_row(
let result = run_block(
&captured_block.block,
&*context,
&context,
input_stream,
ExternalRedirection::Stdout,
);
@ -184,7 +183,7 @@ fn update(args: CommandArgs) -> Result<ActionStream, ShellError> {
let field = Arc::new(field);
Ok(input
.map(move |input| {
.flat_map(move |input| {
let tag = name_tag.clone();
let context = context.clone();
let replacement = replacement.clone();
@ -195,6 +194,5 @@ fn update(args: CommandArgs) -> Result<ActionStream, ShellError> {
Err(e) => ActionStream::one(Err(e)),
}
})
.flatten()
.into_action_stream())
}

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