Compare commits

...

132 Commits

Author SHA1 Message Date
JT
1291b647ae bump to 0.73 (#7542)
# Description

_(Thank you for improving Nushell. Please, check our [contributing
guide](../CONTRIBUTING.md) and talk to the core team before making major
changes.)_

_(Description of your pull request goes here. **Provide examples and/or
screenshots** if your changes affect the user experience.)_

# User-Facing Changes

_(List of all changes that impact the user experience here. This helps
us keep track of breaking changes.)_

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-20 21:58:48 +13:00
91df6c236f Remove unused deps or move to devdeps (#7537)
# Description

General tree shaking through `cargo +nightly udeps` and moving mentions
of `nu-test-support` to the dev deps.

Also since #7488 no separate import of `nu-path` necessary

cc @webbedspace
2022-12-20 12:53:17 +13:00
JT
58cea7e8b4 Turn off cd abbreviations by default (#7536)
# Description

This turns off `cd` abbreviations by default

# User-Facing Changes

`cd` goes back to requiring a name with the default configuration

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-19 13:32:24 -08:00
b01f50bd70 nu-explore/ Fix configuration issues (#7520)
close #7518

Signed-off-by: Maxim Zhiburt <zhiburt@gmail.com>
2022-12-19 11:34:21 -06:00
5f48452e3b some filesystem command signatures (#7464)
# Description

Signature for the following commands:

- `cd` 
- `cp` 
- `glob` 
- `ls` 
- `mkdir` 
- `mv` 
- `open`
- `rm`
- `save`
- `touch`

Related to https://github.com/nushell/nushell/issues/7320

Co-authored-by: sholderbach <sholderbach@users.noreply.github.com>
2022-12-19 13:40:57 +01:00
dae1b9a996 prevent panic with format command (#7522)
Related: #7211.

Prevents numeric underflow in span.

Co-authored-by: sholderbach <sholderbach@users.noreply.github.com>
2022-12-19 13:10:02 +01:00
a21af0ade4 Revert "into cellpath command (#7417)" (#7523)
This reverts commit f0e93c2fa9 (PR #7417).

I'm currently [working on improving cell
paths](https://github.com/nushell/nushell/issues/7498#issuecomment-1356834798),
and I realized that I would need to make several improvements to `into
cellpath` along the lines of Jakub's comment here:
https://github.com/nushell/nushell/pull/7417#issuecomment-1345264955

I don't think `into cellpath` is quite ready for prime-time, and I'd
like to remove it before the upcoming release.
2022-12-18 23:02:18 -08:00
28123841ba Patch explore 4 (#7517)
ref #7339 - This PR updates explore to take some of the colors from
nushell, namely the line colors and the ls_colors.

note: Not sure why this regression appeared maybe it's a feature or it's
no longer supposed to be supported?

Signed-off-by: Maxim Zhiburt <zhiburt@gmail.com>
Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2022-12-18 08:43:15 -06:00
183be911d0 Patch after fix after fix 7380 (#7501)
> I'm not sure how i feel about that. I mean if there are a lot of
columns, it should probably have a max width so 1 column doesn't take
the entire width of your screen. Ideally it would work closely like
table worked before we migrated to tabled, as far as how column widths
were allocated.

I believe it still not completely matched.
*To be honest I am not against the #7446 approach.

The PR makes a switch between logics on a premise of `termwidth`.
So if `termwidth > 120` we start prioritizing amount of columns we can
show (We try to show as many columns as we can).
Otherwise we do what I've described in #7446 (We show the least columns
but with least truncation involvement).

In case it's OK,
I guess we could make the value configurable.

cc @fdncred 
ref #7446

Signed-off-by: Maxim Zhiburt <zhiburt@gmail.com>
2022-12-17 16:16:32 -06:00
1966809502 explore tweaks Round 1 (#7511)
A few small tweaks to the new `explore` command:

1. Rewrote the help text a bit.
    1. I think it's important to mention `:try` up front.
2. Removed the info about `:help foo` because it's currently supported
by very few subcommands
2. Make `exit_esc` default to true. I want to avoid people getting stuck
in `explore` like they get stuck in Vim
3. ~~Always show the help message ("For help type :help") on startup~~
1. The message is small+unobtrusive and I don't this is worth a
configuration item
4. Exit the information view when Escape is pressed
5. General typo+grammar cleanup
    
cc: @zhiburt @fdncred
2022-12-17 12:05:41 -08:00
c3c41a61b0 replace lazy_static with once_cell (#7502)
replacing the dependence on `lazy_static` with `once_cell`, this will
ensure that variables are initialized when needed instead of startup
time.
2022-12-17 10:30:04 -08:00
90849a067f Fix encode base64 type signature and examples (#7515)
# Description

See title.

# User-Facing Changes

See title.

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-17 11:57:16 -06:00
705f12c1d9 Fix cell path when getting columns of non-records (#7508)
A follow-up to #7497. That change made it so that `get foo` would
eliminate non-record rows; I think that was an unintentional and
undesirable side-effect.

Before #7497:
```bash
〉[$nothing, { item: "foo" }] | get item
╭───┬─────╮
│ 0 │     │
│ 1 │ foo │
╰───┴─────╯
```
After #7497:
```bash
〉[$nothing, {item: "foo"}] | get item
╭───┬─────╮
│ 0 │ foo │
╰───┴─────╯
```

After this PR:
```bash
〉[$nothing, { item: "foo" }] | get item
╭───┬─────╮
│ 0 │     │
│ 1 │ foo │
╰───┴─────╯
```

cc: @merelymyself
2022-12-17 09:14:12 -08:00
0826e66fe0 add xterm color names to ansi --list (#7513)
# Description

Follow up to #7141 to map @webbedspace's rgb colors to xterm 256 color
indexes. Also added the xterm 256 named colors to `ansi --list` in the
process.

The few dozen or so names that were duplicate in the xterm 256 names
from [here](https://www.ditig.com/256-colors-cheat-sheet) were renamed
by appending a,b,c,d. So, instead of two blue3's there will be blue3a
and blue3b.

# User-Facing Changes

More colors.

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-17 11:10:14 -06:00
774769a7ad color_config now accepts closures as color values (#7141)
# Description

Closes #6909. You can now add closures to your `color_config` themes.
Whenever a value would be printed with `table`, the closure is run with
the value piped-in. The closure must return either a {fg,bg,attr} record
or a color name (`'light_red'` etc.). This returned style is used to
colour the value.

This is entirely backwards-compatible with existing config.nu files.

Example code excerpt:
```
let my_theme = {
    header: green_bold
    bool: { if $in { 'light_cyan' } else { 'light_red' } }
    int: purple_bold
    filesize: { |e| if $e == 0b { 'gray' } else if $e < 1mb { 'purple_bold' } else { 'cyan_bold' } }
    duration: purple_bold
    date: { (date now) - $in | if $in > 1wk { 'cyan_bold' } else if $in > 1day { 'green_bold' } else { 'yellow_bold' } }
    range: yellow_bold
    string: { if $in =~ '^#\w{6}$' { $in } else { 'white' } }
    nothing: white
```
Example output with this in effect:
![2022-11-16 12 47 23 AM - style_computer
rs_-_nushell_-_VSCodium](https://user-images.githubusercontent.com/83939/201952558-482de05d-69c7-4bf2-91fc-d0964bf71264.png)
![2022-11-16 12 39 41 AM - style_computer
rs_-_nushell_-_VSCodium](https://user-images.githubusercontent.com/83939/201952580-2384bb86-b680-40fe-8192-71bae396c738.png)
![2022-11-15 09 21 54 PM - run_external
rs_-_nushell_-_VSCodium](https://user-images.githubusercontent.com/83939/201952601-343fc15d-e4a8-4a92-ad89-9a7d17d42748.png)

Slightly important notes:

* Some color_config names, namely "separator", "empty" and "hints", pipe
in `null` instead of a value.
* Currently, doing anything non-trivial inside a closure has an
understandably big perf hit. I currently do not actually recommend
something like `string: { if $in =~ '^#\w{6}$' { $in } else { 'white' }
}` for serious work, mainly because of the abundance of string-type data
in the world. Nevertheless, lesser-used types like "date" and "duration"
work well with this.
* I had to do some reorganisation in order to make it possible to call
`eval_block()` that late in table rendering. I invented a new struct
called "StyleComputer" which holds the engine_state and stack of the
initial `table` command (implicit or explicit).
* StyleComputer has a `compute()` method which takes a color_config name
and a nu value, and always returns the correct Style, so you don't have
to worry about A) the color_config value was set at all, B) whether it
was set to a closure or not, or C) which default style to use in those
cases.
* Currently, errors encountered during execution of the closures are
thrown in the garbage. Any other ideas are welcome. (Nonetheless, errors
result in a huge perf hit when they are encountered. I think what should
be done is to assume something terrible happened to the user's config
and invalidate the StyleComputer for that `table` run, thus causing
subsequent output to just be Style::default().)
* More thorough tests are forthcoming - ran into some difficulty using
`nu!` to take an alternative config, and for some reason `let-env config
=` statements don't seem to work inside `nu!` pipelines(???)
* The default config.nu has not been updated to make use of this yet. Do
tell if you think I should incorporate that into this.

# User-Facing Changes

See above.

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace --features=extra -- -D warnings -D
clippy::unwrap_used -A clippy::needless_collect` to check that you're
using the standard code style
- `cargo test --workspace --features=extra` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-17 07:07:56 -06:00
e72cecf457 Remove unnecessary echo uses from examples (#7500)
`echo` tends to confuse new Nu users; they expect it to work like
`print` when it just passes a value to the next stage of the pipeline.

We haven't quite figured out what to do about `echo` in the long run,
but I think a good start is to remove `echo` from command examples where
it would be unnecessary and arguably unidiomatic.
2022-12-16 11:51:00 -05:00
9c1a3aa244 nu-explore/ A few things (#7339)
ref #7332

Signed-off-by: Maxim Zhiburt <zhiburt@gmail.com>
Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2022-12-16 09:47:07 -06:00
2d07c6eedb ensure get doesn't delve too deep in nested lists (#7497)
# Description

Fixes #7494.

```
/home/gabriel/CodingProjects/nushell〉[[{foo: bar}]] | get foo          12/16/2022 12:31:17 PM
Error: nu::parser::not_found (link)

  × Not found.
   ╭─[entry #1:1:1]
 1 │ [[{foo: bar}]] | get foo
   · ───────┬──────
   ·        ╰── did not find anything under this name
   ╰────

```

# User-Facing Changes

cell paths no longer drill into nested tables.

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-15 22:03:38 -08:00
JT
fdd92b2dda Update README.md 2022-12-16 18:50:37 +13:00
8c70189422 (nu_plugin_python): Send back the signature required fields. (#7489)
# Description

The `Signature` data structure has changed. We need to add the required
fields for the nu plugin in python to work well when registering it.

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass
2022-12-15 14:37:12 -06:00
075c83b3a1 add new plugins to script (#7493)
# Description

This PR adds more plugins to the match statement and documents the
plugin repos as comments.

# User-Facing Changes



# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-15 14:36:14 -06:00
d3a19c5ac7 (register-plugins.nu): Filter out files ending with .d on systems other than windows. (#7492) 2022-12-15 14:00:48 -06:00
080874df10 Fix #7486 (#7487)
close #7486

Signed-off-by: Maxim Zhiburt <zhiburt@gmail.com>
2022-12-15 09:55:15 -08:00
24848a1e35 Use nu-path correctly in nu! test macro to make dev-dependency transitive (#7488)
## Fix `nu-path` usage in `nu!` testing macro

The `nu-path` crate needs to be properly re-exported so the generated
code is valid if `nu-path` is not present among the dependencies of the
using crate.

Usage of crates in `macro_rules!` macros has to follow the
`$crate::symbol_in_crate` path pattern (With an absolute path-spec also
for macros defined in submodules)

## Move `nu-test-support` to devdeps in `nu-protocol`

Also remove the now unnecessary direct dependency on `nu-path`.
`nu!` macro had to be changed to make it a proper transitive dependency.
2022-12-15 18:53:26 +01:00
e215fbbd08 Add helper method to check whether ctrl+c was pressed, adopt it (#7482)
I've been working on streaming and pipeline interruption lately. It was
bothering me that checking ctrl+c (something we want to do often) always
requires a bunch of boilerplate like:
```rust
use std::sync::atomic::Ordering;

if let Some(ctrlc) = &engine_state.ctrlc {
     if ctrlc.load(Ordering::SeqCst) {
          ...
```
I added a helper method to cut that down to:

```rust
if nu_utils::ctrl_c::was_pressed(&engine_state.ctrlc) {
    ...
```
2022-12-15 09:39:24 -08:00
33aea56ccd Try to fix #7380 (#7446)
fix https://github.com/nushell/nushell/issues/7380
2022-12-15 08:47:04 -06:00
b6683a3010 add --long flag to history command for sqlite history (#7480) 2022-12-15 08:46:32 -06:00
578ef04988 remove output, append, bin flag from fetch command (#7468)
Closes https://github.com/nushell/nushell/issues/7439
2022-12-14 16:44:04 -06:00
735a7a21bd Add example showing first class closure to do (#7473)
# Description

Demonstrates that you can use `do` to execute stored closures and
evaluate their captures properly.

# Tests + Formatting

As an example test increases coverage of the usage to execute first
class closures.
Additional tests using that found in
`tests/shell/pipeline/commands/internal.rs`
2022-12-14 20:55:00 +01:00
80a69224f7 Handle ctrl-c in uniq and uniq-by (#7478)
A partial fix for #7477. `uniq` can be slow sometimes, so we should
check `ctrl-c` when it's running.

Tested on [this
file](https://home.treasury.gov/system/files/276/yield-curve-rates-1990-2021.csv),
I ran `open yield-curve-rates-1990-2021.csv | uniq` and confirmed that I
can now cancel the operation.

Future work is needed to figure out why `uniq` is so slow.
2022-12-14 11:31:54 -08:00
e0bf17930b refactor: introduce is_external_failed to PipelineData, and simplify try logic (#7476)
# Description

Just spot that there are some duplicate code about checking external
runs to failed, is pr is trying to refactor it and reduce lines of code

# User-Facing Changes

NaN

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-14 10:25:32 -08:00
db3177a5aa break for, loop, while execution when external command runs to failed (#7475)
Fixes: #7467

# User-Facing Changes

## for
```
❯ for i in 1..2 { echo 1;  ^false }
1
```

## loop
```
❯ loop { echo bb; ^false }
bb
```

## while
```
❯ mut x = 1; while $x < 3 { $x = $x + 1; echo bb; ^false }
bb
```
2022-12-14 16:20:18 +01:00
98b9839e3d Fix for escaping backslashes in interpolated strings (fixes #6737) (#7119)
Co-authored-by: Gavin Foley <gavinmfoley@gmail.com>
2022-12-14 07:54:13 -06:00
0db4d89838 add missing shapes to default_config (#7472)
# Description

We've added some shapes recently. This PR adds them to the
default_config and sorts them in order to make finding missing ones
easier.

# User-Facing Changes


# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-14 07:11:17 -06:00
52278f8562 Help messages: edit various instances of "block" to "closure" (#7470) 2022-12-14 14:02:41 +01:00
c19d9597fd Add riscv64 binary release target (#7469)
# Description

Add `riscv64gc-unknown-linux-gnu` release target

TEST release workflow:
https://github.com/hustcer/nu-release/actions/runs/3693191329
TEST release: https://github.com/hustcer/nu-release/releases/tag/v0.73.0

# User-Facing Changes

New `nu-*-riscv64gc-unknown-linux-gnu.tar.gz` package will be added to
the following release

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-14 23:09:39 +13:00
d9d9916ccc Fix streaming page missing newline (#7466)
Fixes #7342. `0..1000 | table` before this change:


![image](https://user-images.githubusercontent.com/26268125/207474492-dead4267-d828-4840-8da0-4edfda3e3916.png)

`0..1000 | table` after this change:


![image](https://user-images.githubusercontent.com/26268125/207474583-26633db0-46c5-4c30-8681-654855e7042b.png)

When piping data to `table`, pages were not getting a newline at the
end[^1]. This problem was uncovered and exacerbated by the new
`display_output` hook which implicitly piped _everything_ to `table`.

## The Fix

`PagingTableCreator` now adds a newline to each page instead of relying
on later code to do it.

## Tests

I spent a while trying to write a regression test for this behaviour but
I couldn't get the test to fail before my fix! I think the test
infrastructure does something special with newlines when it's checking
command output. I eventually ran out of steam trying to investigate
that, sorry.

[^1]: unless the pipe to table was the implicit one that's done when
there is no `display_output` hook set. That situation was still working
OK.
2022-12-14 16:45:37 +13:00
26759c4af2 mkdir change flag -s to -v (#7462)
Change in `mkdir` `-s` flag to `-v` to be similar to other commands


# Description

Other commands like `rm`, `mv`, `cp` have a `-v` (`--verbose`) flag.
`mkdir` has a `-s` (`--show-created-paths`), but should be consistent
with other commands.

# User-Facing Changes

- flag `-s` replaced by `-v` in `mkdir` command.


# Tests + Formatting
```
> mkdir -v new_dir
╭───┬───────────────────────────────────╮
│ 0 │ C:\Users\ricardo.monteiro\new_dir │
╰───┴───────────────────────────────────╯
```
2022-12-13 11:56:44 -05:00
e529746294 sort enums add missing items to parse_shape_name (#7450)
# Description

This PR adds missing items in `parse_shape_name`, sorts the
`SyntaxShape` enum and the `Type` enum. It's a pain to hunt around for
particular items in an enum when they're unsorted.

# User-Facing Changes


# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-13 10:46:22 -06:00
0c4d4632ef let UnknownFlag error list out available flags (#7443)
# Description
Fixes #6773.

```
/home/gabriel/CodingProjects/nushell〉ls -r                                                                                                                             12/12/2022 02:57:35 PM
Error: nu::parser::unknown_flag (link)

  × The `ls` command doesn't have flag `-r`.
   ╭─[entry #1:1:1]
 1 │ ls -r
   ·     ┬
   ·     ╰── unknown flag
   ╰────
  help: Available flags: --help(-h), --all(-a), --long(-l), --short-names(-s), --full-paths(-f), --du(-d), --directory(-D). Use `--help` for more information.
```

# User-Facing Changes

Different error for unknown flag.

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-13 06:45:33 -06:00
e2c1216c1b Fix du error message (#7460)
BEFORE:
```
〉du *.***
Error:
  × wildcards are either regular `*` or recursive `**`
   ╭─[entry #6:1:1]
 1 │ du *.***
   · ─┬
   ·  ╰── glob error
   ╰────
```
AFTER:
```
〉du *.***
Error:
  × glob error
   ╭─[entry #8:1:1]
 1 │ du *.***
   ·    ──┬──
   ·      ╰── wildcards are either regular `*` or recursive `**`
   ╰────

```
2022-12-13 13:11:55 +01:00
d83dbc3670 add input_output_types() to benchmark,cd and config reset (#7455)
# Description

add input_output_types() to benchmark, cd and config reset commands
It's an update to https://github.com/nushell/nushell/issues/7320


# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-13 06:10:55 -06:00
JT
0242b30027 Revert "Add pipeline operators to help" (#7454)
Reverts nushell/nushell#7449
2022-12-13 16:49:00 +13:00
JT
0c656fd276 Revert "Pipeline operators: && and ||" (#7452)
Reverts nushell/nushell#7448

Some surprising behavior in how we do this. For example:

```
〉if (true || false) { print "yes!" } else { print "no!" }
no!
〉if (true or false) { print "yes!" } else { print "no!" }
yes!
```

This means for folks who are using the old `||`, they possibly get the
wrong answer once they upgrade. I don't think we can ship with that as
it will catch too many people by surprise and just make it easier to
write buggy code.
2022-12-13 16:36:13 +13:00
b7a3e5989d Make hook execution stream instead of collecting (#7440)
Closes #7431. In a nutshell:
- `run_hook_block()` in repl.rs was collecting all input into a `Value`
instead of handling streaming input properly
- this was a problem because now we have a default `display_output` hook
that _everything_ gets piped to
- this PR fixes the problem by tweaking `run_hook_block()` to return a
`PipelineData` instead of a `Value`

After this change, individual pages are rendered as they finish. This is
a little easier to see if I tweak `STREAM_PAGE_SIZE` in table.rs to 10:

![image](https://user-images.githubusercontent.com/26268125/206935370-412b2ee9-9401-4222-bc93-5bd5a9adc13b.png)

## Future work

This does _not_ fix https://github.com/nushell/nushell/issues/7342.
2022-12-12 15:23:04 -08:00
JT
5b5f1d1b92 Add pipeline operators to help (#7449)
# Description

_(Thank you for improving Nushell. Please, check our [contributing
guide](../CONTRIBUTING.md) and talk to the core team before making major
changes.)_

_(Description of your pull request goes here. **Provide examples and/or
screenshots** if your changes affect the user experience.)_

# User-Facing Changes

_(List of all changes that impact the user experience here. This helps
us keep track of breaking changes.)_

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-13 11:31:03 +13:00
JT
35bea5e044 Pipeline operators: && and || (#7448)
# Description

We got some feedback from folks used to other shells that `try/catch`
isn't quite as convenient as things like `||`. This PR adds `&&` as a
synonym for `;` and `||` as equivalent to what `try/catch` would do.

# User-Facing Changes

Adds `&&` and `||` pipeline operators.

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-13 09:53:46 +13:00
7917cf9f00 Add config mutation tests (#7437)
# Description

Env config can be mutated by `=`, this pr is to add a few tests 

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-12 12:46:25 -06:00
5036672a58 add interact-once switch to rm (#7432)
# Description

Fixes: #7216 

Adds `interact-once` switch which numbers out the number of files to
delete and asks the user for confirmation.

```
/home/gabriel/test〉ls                                                                                                                                                  12/11/2022 11:25:42 AM
╭───┬───────┬──────┬──────┬──────────╮
│ # │ name  │ type │ size │ modified │
├───┼───────┼──────┼──────┼──────────┤
│ 0 │ a.txt │ file │  0 B │ now      │
│ 1 │ b.txt │ file │  0 B │ now      │
│ 2 │ c.txt │ file │  0 B │ now      │
╰───┴───────┴──────┴──────┴──────────╯
/home/gabriel/test〉rm *.txt -I                                                                                                                                         12/11/2022 11:25:42 AM
rm: remove 3 files? : y

/home/gabriel/test〉ls                                                                                                                                                  12/11/2022 11:25:51 AM
/home/gabriel/test〉                                                                                                                                                    12/11/2022 11:25:54 AM
```

# User-Facing Changes

_(List of all changes that impact the user experience here. This helps
us keep track of breaking changes.)_

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-11 13:22:27 -08:00
585ab56ea4 in for, loop, while, auto print final value in each iteration (#7433)
# Description

Fixes: #7404 
Fixes: #7402 

## About change
In `eval_block`, all pipelines(or called statements?) result will be
printed except the last one, the last one is returned by `eval_block`
function.

So if we want to print the last statement in eval block, we just need to
print that value.

# User-Facing Changes

### for
```
❯ for _ in 1..2 { echo "a" }
a
a
```

### while
```
❯ mut x = 1; while $x < 3 { $x = $x + 1; echo bb; }
bb
bb
```

### loop
```
❯ mut total = 0; loop {
∙     if $total > 1 {
∙         break
∙     } else {
∙         $total += 1
∙     }
∙     echo 3
∙ }
3
3
```

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
  - `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-12 05:46:03 +13:00
9009f68e09 Tweak "Cannot convert {x} to a string argument" error in run_external (#7434)
# Description

The message arrow is altered to show the external command name in case
it wasn't obvious. (See example for an occasion where it is
non-obvious).

BEFORE:
```
〉else if (2mb) > 4mb
Error: nu:🐚:external_command (link)

  × External command failed
   ╭─[entry #35:1:1]
 1 │ else if (2mb) > 4mb
   ·           ─┬
   ·            ╰── Cannot convert filesize to a string
   ╰────
  help: All arguments to an external command need to be string-compatible
```
AFTER:
```
〉else if (2mb) > 4mb
Error: nu:🐚:external_command (link)

  × External command failed
   ╭─[entry #3:1:1]
 1 │ else if (2mb) > 4mb
   ·           ─┬
   ·            ╰── Cannot convert filesize to a string argument for 'else'
   ╰────
  help: All arguments to an external command need to be string-compatible

```
# User-Facing Changes

See above.

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-11 08:39:51 -08:00
2bacc29d30 Replace row conditions with closures in commands (#7428)
# Description

This PR changes some commands that previously accepted row conditions
(like `$it > 5`) as parameter to accept closures instead. The reasons
are:
a) The commands would need to move into parser keywords in the future
while they feel more like commands to be implemented in Nushell code as
a part of standard library.
b) In scripts, it is useful to store the predicate condition in a
variable which you can't do with row conditions.
c) These commands are not used that often to benefit enough from the
shorter row condition syntax

# User-Facing Changes

The following commands now accept **closure** instead of a **row
condition**:
- `take until`
- `take while`
- `skip until`
- `skip while`
- `any`
- `all`

This is a part of an effort to move away from shape-directed parsing.
Related PR: https://github.com/nushell/nushell/pull/7365

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-10 19:24:06 +02:00
4d7d97e0e6 Simplify FILE_PWD setting in 'overlay use' (#7425)
# Description

Changes the `FILE_PWD` setting mechanism to match the one used in the
`use` command.

Fixes https://github.com/nushell/nushell/pull/7424

# User-Facing Changes

None

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-10 19:23:55 +02:00
f1000a17b4 Add FILE_PWD environment variable when running 'nu script.nu' (#7424)
# Description

When running `nu script.nu`, the `$env.FILE_PWD` will be set to the
directory where the script is.

Also makes the error message a bit nicer:
```
> target/debug/nu asdihga
Error: nu:🐚:file_not_found (link)

  × File not found
   ╭─[source:1:1]
 1 │ nu
   · ▲
   · ╰── Could not access file 'asdihga': "No such file or directory (os error 2)"
   ╰────

```

# User-Facing Changes

`FILE_PWD` environment variable is available when running a script as
`nu script.nu`.

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-10 19:23:44 +02:00
f43edbccdc Make env-related tests more resilient (#7423)
# Description

Fixes https://github.com/nushell/nushell/issues/6708

The error message of environment variable not found could change
depending on the `$env` content which can produce random failures on
different systems. This PR hopefully makes the tests more resilient.

# User-Facing Changes

None

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-10 19:23:34 +02:00
6b4282eadf Move 'where' to parser keywords; Add 'filter' command (#7365)
# Description

This PR moves the `where` command to a parser keyword. While it still
uses the shape-directed parsing dictated by the signature, we're free to
change the parsing code now to a custom one once we remove the syntax
shapes.

As a side effect, the `where -b` flag was removed and its functionality
has moved to the new `filter` command.

Just FYI, other commands that take row conditions:
- `take until`
- `take while`
- `skip until`
- `skip while`
- `any`
- `all`

We can either move these to the parser as well or make them accept a
closure instead of row condition.

# User-Facing Changes

New `filter` command which replaces `where -b` functionality.

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-10 19:23:24 +02:00
7e2781a2af fix docker build (#7422)
# Description

Docker build fails with the latest release 0.72.1
```bash
Sending build context to Docker daemon  3.072kB
Step 1/6 : FROM alpine
 ---> 49176f190c7e
Step 2/6 : LABEL maintainer=nushell
 ---> Using cache
 ---> 7afa6864f008
Step 3/6 : RUN echo '/usr/bin/nu' >> /etc/shells     && adduser -D -s /usr/bin/nu nushell     && mkdir -p /home/nushell/.config/nushell/     && wget -q https://raw.githubusercontent.com/nushell/nushell/main/crates/nu-utils/src/sample_config/default_config.nu -O /home/nushell/.config/nushell/config.nu     && wget -q https://raw.githubusercontent.com/nushell/nushell/main/crates/nu-utils/src/sample_config/default_env.nu -O /home/nushell/.config/nushell/env.nu     && cd /tmp     && wget -qO - https://api.github.com/repos/nushell/nushell/releases/latest     |grep browser_download_url     |grep musl     |cut -f4 -d '"'     |xargs -I{} wget {}     && tar -xzf nu*     && chmod +x nu     && mv nu /usr/bin/nu     && chown -R nushell:nushell /home/nushell/.config/nushell     && rm -rf /tmp/*
 ---> Running in fa544239a3ea
Connecting to github.com (140.82.121.4:443)
Connecting to objects.githubusercontent.com (185.199.108.133:443)
saving to 'nu-0.72.1-x86_64-unknown-linux-musl.tar.gz'
nu-0.72.1-x86_64-unk   3% |*                               |  552k  0:00:29 ETA
nu-0.72.1-x86_64-unk  93% |*****************************   | 15.2M  0:00:00 ETA
nu-0.72.1-x86_64-unk 100% |********************************| 16.2M  0:00:00 ETA
'nu-0.72.1-x86_64-unknown-linux-musl.tar.gz' saved
chmod: nu: No such file or directory
```
2022-12-10 09:22:23 -06:00
32a53450a6 make split row works like python and rust ways (#7413)
# Description

Fixes: #7389 

Make split row works more like python or rust, especially, when the
input string stars/ends with separator, append a empty string to result.
Here are examples:

python:
```python
In [6]: "\nasdf\nghi\n".split("\n")
Out[6]: ['', 'asdf', 'ghi', '']
```
rust:
```rust
fn main() {
    let x = "\nabc\ndef\n";
    let y = x.split("\n").collect::<Vec<&str>>();
    println!("{:?}", y);   // outputs: ["", "abc", "def", ""]
}
```
# User-Facing Changes

_(List of all changes that impact the user experience here. This helps
us keep track of breaking changes.)_

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-10 09:21:53 -06:00
ce78817f41 $env.config now always holds a record with only valid values (#7309)
# Description
Closes #7059. Rather than generate a new Record each time $env.config is
accessed (as described in that issue), instead `$env.config = ` now A)
parses the input record, then B) un-parses it into a clean Record with
only the valid values, and stores that as an env-var. The reasoning for
this is that I believe `config_to_nu_record()` (the method that performs
step B) will be useful in later PRs. (See below)

As a result, this also "fixes" the following "bug":
```
〉$env.config = 'butts'
$env.config is not a record
〉$env.config
butts
```
~~Instead, `$env.config = 'butts'` now turns `$env.config` into the
default (not the default config.nu, but `Config::default()`, which
notably has empty keybindings, color_config, menus and hooks vecs).~~

This doesn't attempt to fix #7110. cc @Kangaxx-0

# Example of new behaviour

OLD:
```
〉$env.config = ($env.config | merge { foo: 1 })
$env.config.foo is an unknown config setting
〉$env.config.foo
1
```
NEW:
```
〉$env.config = ($env.config | merge { foo: 1 })
Error:
  × Config record contains invalid values or unknown settings

Error:
  × Error while applying config changes
   ╭─[entry #1:1:1]
 1 │ $env.config = ($env.config | merge { foo: 1 })
   ·                                           ┬
   ·                                           ╰── $env.config.foo is an unknown config setting
   ╰────
  help: This value has been removed from your $env.config record.

〉$env.config.foo
Error: nu:🐚:column_not_found (link)

  × Cannot find column
   ╭─[entry #1:1:1]
 1 │ $env.config = ($env.config | merge { foo: 1 })
   ·                              ──┬──
   ·                                ╰── value originates here
   ╰────
   ╭─[entry #2:1:1]
 1 │ $env.config.foo
   ·             ─┬─
   ·              ╰── cannot find column 'foo'
   ╰────
```
# Example of new errors

OLD:
```
$env.config.cd.baz is an unknown config setting
$env.config.foo is an unknown config setting
$env.config.bar is an unknown config setting
$env.config.table.qux is an unknown config setting
$env.config.history.qux is an unknown config setting
```
NEW:
```
Error: 
  × Config record contains invalid values or unknown settings

Error:
  × Error while applying config changes
     ╭─[C:\Users\Leon\AppData\Roaming\nushell\config.nu:267:1]
 267 │     abbreviations: true # allows `cd s/o/f` to expand to `cd some/other/folder`
 268 │     baz: 3,
     ·          ┬
     ·          ╰── $env.config.cd.baz is an unknown config setting
 269 │   }
     ╰────
  help: This value has been removed from your $env.config record.

Error:
  × Error while applying config changes
     ╭─[C:\Users\Leon\AppData\Roaming\nushell\config.nu:269:1]
 269 │   }
 270 │   foo: 1,
     ·        ┬
     ·        ╰── $env.config.foo is an unknown config setting
 271 │   bar: 2,
     ╰────
  help: This value has been removed from your $env.config record.

Error:
  × Error while applying config changes
     ╭─[C:\Users\Leon\AppData\Roaming\nushell\config.nu:270:1]
 270 │   foo: 1,
 271 │   bar: 2,
     ·        ┬
     ·        ╰── $env.config.bar is an unknown config setting
     ╰────
  help: This value has been removed from your $env.config record.

Error:
  × Error while applying config changes
     ╭─[C:\Users\Leon\AppData\Roaming\nushell\config.nu:279:1]
 279 │     }
 280 │     qux: 4,
     ·          ┬
     ·          ╰── $env.config.table.qux is an unknown config setting
 281 │   }
     ╰────
  help: This value has been removed from your $env.config record.

Error:
  × Error while applying config changes
     ╭─[C:\Users\Leon\AppData\Roaming\nushell\config.nu:285:1]
 285 │     file_format: "plaintext" # "sqlite" or "plaintext"
 286 │  qux: 2
     ·       ┬
     ·       ╰── $env.config.history.qux is an unknown config setting
 287 │   }
     ╰────
  help: This value has been removed from your $env.config record.


```

# User-Facing Changes

See above.

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-10 15:34:46 +02:00
f0e93c2fa9 into cellpath command (#7417)
# Description

Address part of feature request #7337, add a small command `into
cellpath` to allow string -> cellpath auto-conversion, with this change,
we could run

```
let p = 'ls.use_ls_colors'
$env.config | upsert ($p | nito cellpath) false
```

<img width="710" alt="image"
src="https://user-images.githubusercontent.com/85712372/206782818-3024b34f-150b-482d-aebc-9426ef6a1cf9.png">

Note - This pr only covers `String` -> `CellPath`, any other conversions
should be considered as expected?

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- [x] `cargo fmt --all -- --check` to check standard code formatting
(`cargo fmt --all` applies these changes)
- [x] `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- [x] `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-10 15:26:42 +02:00
fa6bb147ea remove example missed from an earlier refactor (#7419)
# Description

When `seq date` was changed to remove the `-s` param, the example was
missed. This PR removes that example.

# User-Facing Changes


# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-09 20:04:14 -06:00
220b105efb Reduced LOC by replacing several instances of Value::Int {}, Value::Float{}, Value::Bool {}, and Value::String {} with Value::int(), Value::float(), Value::boolean() and Value::string() (#7412)
# Description

While perusing Value.rs, I noticed the `Value::int()`, `Value::float()`,
`Value::boolean()` and `Value::string()` constructors, which seem
designed to make it easier to construct various Values, but which aren't
used often at all in the codebase. So, using a few find-replaces
regexes, I increased their usage. This reduces overall LOC because
structures like this:
```
Value::Int {
  val: a,
  span: head
}
```
are changed into
```
Value::int(a, head)
```
and are respected as such by the project's formatter.
There are little readability concerns because the second argument to all
of these is `span`, and it's almost always extremely obvious which is
the span at every callsite.

# User-Facing Changes

None.

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-09 11:37:51 -05:00
b56ad92e25 ++= appendAssign operator (#7346) (#7354)
# Description

Closes  https://github.com/nushell/nushell/issues/7346



# Tests + Formatting
```
> mut a = [1 2 3]
> $a ++= [4 5 6]
> $a
[1 2 3 4 5 6]
```
2022-12-09 11:20:58 -05:00
fc5fe4b445 ensure error in else is forwarded appropriately (#7411)
# Description

Fixes #7407. 

```
/home/gabriel/CodingProjects/nushell〉if false { 'a' } else { $foo }    12/09/2022 08:14:48 PM
Error: nu::parser::variable_not_found (link)

  × Variable not found.
   ╭─[entry #1:1:1]
 1 │ if false { 'a' } else { $foo }
   ·                         ──┬─
   ·                           ╰── variable not found
   ╰────
```

# User-Facing Changes

_(List of all changes that impact the user experience here. This helps
us keep track of breaking changes.)_

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-09 15:48:12 +02:00
c01d44e37d Add arbitrary base math log (#7409)
Adds new command `math log` that takes as a required positional argument
a base.

Specialized for `math log 2` and `math log 10` for better performance
and precision that matches the expectations there. This leads to
discontinuities in numerical error but should make a better trade-off
for common usecases.


Example testing of the happy path
2022-12-09 11:20:42 +01:00
5a0e86aa70 fix external completions; add a caret when there is overlap (#7405)
# Description

Fixes #5424. Checking the code, apparently this was always supposed to
work; however, because it compared the `Suggestion`s directly, and
internal commands had descriptions while external commands did not, it
never did function properly.

# User-Facing Changes

Completing to external commands (with overlap) adds a caret so the
external command is actually run.

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-09 22:27:50 +13:00
b4529a20e8 Add math tau (#7408)
# Description

Prompted by
https://discord.com/channels/601130461678272522/615329862395101194/1050693116501426216

# User-Facing Changes

New command `math tau` and endless agony whether to use `math pi` or
`math tau`

# Tests + Formatting

Example test
2022-12-09 22:27:19 +13:00
b938adefaa Fix math e usage text (#7406)
Closes #7401

# Tests + Formatting

Doesn't apply, doc fix
2022-12-09 09:56:12 +01:00
b39d797c1f Add quotes to hash file autocomplete (#7398)
# Description

Fixes #6741. Autocompleting a dir/file named something like foo#bar will
now complete to \`foo#bar\`
2022-12-08 21:37:10 +01:00
4240bfb7b1 Fix tab not working in vi editor mode (#7396)
# Description

The "tab" key now cycles completions in all editor modes, not just
emacs.

# User-Facing Changes

Updated default config

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-08 11:07:40 +02:00
JT
b7572f107f Remove and/or from 'help operators' (#7388)
# Description

_(Thank you for improving Nushell. Please, check our [contributing
guide](../CONTRIBUTING.md) and talk to the core team before making major
changes.)_

_(Description of your pull request goes here. **Provide examples and/or
screenshots** if your changes affect the user experience.)_

# User-Facing Changes

_(List of all changes that impact the user experience here. This helps
us keep track of breaking changes.)_

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-07 18:05:51 -06:00
JT
379e3d70ca Better errors when bash-like operators are used (#7241)
# Description

Adds improved errors for when a user uses a bashism that nu doesn't
support.

fixes #7237 

Examples:

```
Error: nu::parser::shell_andand (link)

  × The '&&' operator is not supported in Nushell
   ╭─[entry #1:1:1]
 1 │ ls && ls
   ·    ─┬
   ·     ╰── instead of '&&', use ';' or 'and'
   ╰────
  help: use ';' instead of the shell '&&', or 'and' instead of the boolean '&&'
```

```
Error: nu::parser::shell_oror (link)

  × The '||' operator is not supported in Nushell
   ╭─[entry #8:1:1]
 1 │ ls || ls
   ·    ─┬
   ·     ╰── instead of '||', use 'try' or 'or'
   ╰────
  help: use 'try' instead of the shell '||', or 'or' instead of the boolean '||'
```

```
Error: nu::parser::shell_err (link)

  × The '2>' shell operation is 'err>' in Nushell.
   ╭─[entry #9:1:1]
 1 │ foo 2> bar.txt
   ·     ─┬
   ·      ╰── use 'err>' instead of '2>' in Nushell
   ╰────
```

```
Error: nu::parser::shell_outerr (link)

  × The '2>&1' shell operation is 'out+err>' in Nushell.
   ╭─[entry #10:1:1]
 1 │ foo 2>&1 bar.txt
   ·     ──┬─
   ·       ╰── use 'out+err>' instead of '2>&1' in Nushell
   ╰────
  help: Nushell redirection will write all of stdout before stderr.
```


# User-Facing Changes

**BREAKING CHANGES**

This removes the `&&` and `||` operators. We previously supported by
`&&`/`and` and `||`/`or`. With this change, only `and` and `or` are
valid boolean operators.

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-08 12:02:11 +13:00
JT
6fc87fad72 Fix input redirect for externals (#7387)
# Description

Ooops, fix the input redirection logic so we don't break vim.

# User-Facing Changes

_(List of all changes that impact the user experience here. This helps
us keep track of breaking changes.)_

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-08 11:33:42 +13:00
JT
fa15a2856a Add OneOf shape to fix else (#7385)
# Description

fixes #7384 

This is a stop-gap fix until we remove type-directed parsing. With this,
you can create a `OneOf` shape that can be one of a list of syntax
shapes. This gives you a little more control than you get with `Any`,
allowing you to add `Block` without breaking other parsing rules.

# User-Facing Changes

`else` block will no longer capture variables as it will now use a block
instead of a closure.

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-08 08:58:54 +13:00
JT
eaec480f42 Improve empty pipelines (#7383)
# Description

This fix changes pipelines to allow them to actually be empty. Mapping
over empty pipelines gives empty pipelines. Empty pipelines immediately
return `None` when iterated.

This removes a some of where `Span::new(0, 0)` was coming from, though
there are other cases where we still use it.

# User-Facing Changes

None

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-08 07:31:57 +13:00
d18587330a fix semicolon doesn't work for some commands (#7373)
# Description

Fix semicolon working for the following commands which runs to failed:

1. into record (example: `into record; echo 'aa'`) -- the final aa
shouldn't be printed
2. save ( example: `touch a; chmod a-w a; echo 'aa' | save a; echo asdf`
) -- the final asdf shouldn't be printed
3. fetch ( example: `touch a; chmod a-w a; fetch https://www.google.com
-o a; echo asdf` ) -- the final asdf shouldn't be printed
4. registry_query (I don't have window machine, sorry for that I can't
demo for it)

I've reviewed most of built-in commands, and it seems that other
commands works fine.

# User-Facing Changes

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-06 19:48:39 -08:00
5114dfca7d Remove use of deprecated actions-rs/cargo GH action (#7375)
Our CI actions have a lot of warnings like this:

>  nu-fmt-clippy (ubuntu-20.04, stable)
> Node.js 12 actions are deprecated. For more information see:
https://github.blog/changelog/2022-09-22-github-actions-all-actions-will-begin-running-on-node16-instead-of-node12/.
Please update the following actions to use Node.js 16:
actions-rs/cargo@v1.0.1

[It looks like `actions-rs/cargo` is
abandoned](https://github.com/actions-rs/toolchain/issues/216). But the
good news is we don't actually need it, we can just run `cargo`
subcommands without a special action because we've already installed
`cargo` with `actions-rust-lang/setup-rust-toolchain`.
2022-12-06 18:57:07 -08:00
3395beaa56 Make seq return a ListStream where possible (#7367)
# Description

Title.

# User-Facing Changes

Faster seq that works better with functions that take in `ListStream`s.

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-06 18:48:03 -08:00
df66d9fcdf Fix watch for block+closure split (#7374)
The block+closure split broke `watch` for some use cases. Fixed.

We should eventually add some tests for `watch` but it's a little tricky
since it's an interactive command.

Closes #7362.
2022-12-06 18:20:20 -08:00
1af1e0b5a3 fix upsert index of zero (#7350)
# Description

Try to fix #7347, this pr does not fix the error message to `upserting
beyond 1 + the list's length doesn't work,`, I feel this is still not
explicit or general engouh, if we want to change, what would be the best
message to be printed out ?

Add tests too

# User-Facing Changes

_(List of all changes that impact the user experience here. This helps
us keep track of breaking changes.)_

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- [x] `cargo fmt --all -- --check` to check standard code formatting
(`cargo fmt --all` applies these changes)
- [x] `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- [x] `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-06 15:26:27 -05:00
9b41f9ecb8 Allow $env and mutable records to be mutated by = (closes #7110) (#7318)
# Description

Closes #7110. ~~Note that unlike "real" `mut` vars, $env can be deeply
mutated via stuff like `$env.PYTHON_IO_ENCODING = utf8` or
`$env.config.history.max_size = 2000`. So, it's a slightly awkward
special case, arguably justifiable because of what $env represents (the
environment variables of your system, which is essentially "outside"
normal Nushell regulations).~~
EDIT: Now allows all `mut` vars to be deeply mutated using `=`, on
request.

# User-Facing Changes

See above.

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-06 19:51:55 +02:00
48ade4993d remove redundant code mentioning ToCsv (#7370)
# Description

```rust
ToCsv
```

ToCsv was in there twice so I removed the 2nd reference...

_(Thank you for improving Nushell. Please, check our [contributing
guide](../CONTRIBUTING.md) and talk to the core team before making major
changes.)_

_(Description of your pull request goes here. **Provide examples and/or
screenshots** if your changes affect the user experience.)_

# User-Facing Changes

_(List of all changes that impact the user experience here. This helps
us keep track of breaking changes.)_

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-06 09:42:12 -08:00
4ecc807dbb fix split list when separater is the first element of list (#7355)
# Description

Fixes: #7278

# User-Facing Changes

_(List of all changes that impact the user experience here. This helps
us keep track of breaking changes.)_

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-06 08:51:38 -06:00
86b69cc5d1 add input_output_types() to ansi gradient (#7357)
# Description

Add the input_output_types() to the ansi gradient command in support of
#7320

# User-Facing Changes


# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-06 08:51:18 -06:00
017a13fa3f bump to dev build v0.72.2 (#7360)
# Description

After the 0.72.1 hotfix, let's bump our dev builds to 0.72.2.

# User-Facing Changes



# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-05 14:18:06 -06:00
ca12b2e30e Pin CI jobs to Ubuntu 20.04 (#7359)
The release job was pinned to Ubuntu 20.04 to avoid glibc breakage in
https://github.com/nushell/nushell/pull/7290. This PR updates the CI
jobs to keep things consistent (it would sure be unpleasant if things
worked in CI but not at release time).
2022-12-05 10:12:36 -08:00
db6c804b17 fix menus in default config (#7352)
Simply fixes menus commands_with_description, commands_menu
2022-12-04 19:23:58 -08:00
57ff668d2e Make SQLite queries cancellable (#7351)
This change makes SQLite queries (`open foo.db`, `open foo.db | query db
"select ..."`) cancellable using `ctrl+c`. Previously they were not
cancellable, which made it unpleasant to accidentally open a very large
database or run an unexpectedly slow query!

UX-wise there's not too much to show:


![image](https://user-images.githubusercontent.com/26268125/205519205-e1f2ab58-c92d-4b96-9f80-eb123f678ec3.png)

## Notes

I was hoping to make SQLite queries streamable as part of this work, but
I ran into 2 problems:
1. `rusqlite` lifetimes are nightmarishly complex and they make it hard
to create a `ListStream` iterator
2. The functions on Nu's `CustomValue` trait return `Value` not
`PipelineData` and so `CustomValue` implementations can't stream data
AFAICT.
2022-12-04 16:49:47 -08:00
9fb9b16b38 kill: don't show signal example on windows (#7353)
# Description

Windows doesn't support the --signal(-s) option, so don't show the
example in help.

# User-Facing Changes

N/A

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-04 16:39:54 -08:00
41178dff90 Try to fix #7338 (#7343)
Signed-off-by: Maxim Zhiburt <zhiburt@gmail.com>
2022-12-04 17:47:46 -06:00
12deff5d1b Add comments for nu syntax shape (#7349)
# Description

FIx the typo of `List` and also add more comments to other variants


# User-Facing Changes

_(List of all changes that impact the user experience here. This helps
us keep track of breaking changes.)_

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-04 11:20:47 -08:00
21a645b1a9 Improve error message for illegal filenames on Windows (#7348)
`ls` can fail when a directory contains a file that violates [the
Windows file naming
conventions](https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file#naming-conventions).
This PR tweaks the error message so we tell the user _which_ file caused
the problem.

Closes #7345.

### Before:

![image](https://user-images.githubusercontent.com/26268125/205508355-2875f851-6b61-4897-97b8-9094b24ea197.png)

### After:


![image](https://user-images.githubusercontent.com/26268125/205508325-0b4efd25-b454-4d1b-b8e9-cb26803fbcff.png)


## Future Work

Like Chris said in the linked issue, it would be even better if Nu could
just handle these naughty files like cmd.exe and pwsh do. If someone has
the time to dive into how PowerShell does this, that would be much
appreciated.
2022-12-04 10:33:30 -08:00
e8a55aa647 Overhaul schema command, remove database name (#7344)
This PR changes the `schema` command for viewing the schema of a SQLite
database file. It removes 1 level of nesting (intended to handle
multiple databases in the same connection) that I believe is
unnecessary.

### Before

![image](https://user-images.githubusercontent.com/26268125/205467643-05df0f64-bc8f-4135-9ff1-f978cc7a12bd.png)

### After

![image](https://user-images.githubusercontent.com/26268125/205467655-c4783184-9bde-46e2-9316-0f06acd1abe1.png)

## Rationale

A SQLite database connection can technically be associated with multiple
non-temporary databases using [the ATTACH DATABASE
command](https://www.sqlite.org/lang_attach.html). But it's not possible
to do that _in the context of Nushell_, and so I believe that there is
no benefit to displaying the schema as if there could be multiple
databases.

I initially raised this concern back in April, but we decided to keep
the database nesting because at the time we were still looking into more
generalized database functionality (i.e. not just SQLite). I believe
that rationale no longer applies.

Also, the existing code would not have worked correctly even if a
connection had multiple databases; for every database, it was looking up
tables without filtering them by database:

6295b20545/crates/nu-command/src/database/values/sqlite.rs (L104-L118)

## Future Work

I'd like to add information on views+triggers to the `schema` output.
I'm also working on making it possible to `ctrl+c` reading from a
database (which is turning into a massive yak shave).
2022-12-03 18:16:57 -08:00
6295b20545 add background colors to the ansi command (#7312)
# Description

This PR adds the ability to easily specific background colors using the
ansi command. It also allows you to use attributes.

![image](https://user-images.githubusercontent.com/343840/205151594-968cc7a6-f1d8-406e-aa8b-cb67e8487563.png)

I also updated the grid output to be clear that the output includes an
escape character, represented here by `\e`.

![image](https://user-images.githubusercontent.com/343840/205151066-09966f90-6341-4eeb-83c1-df3d169cfbf6.png)

# User-Facing Changes

You can see a list of these new items with `ansi --list` with their long
and short names.

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-03 13:08:51 -06:00
850ecf648a Protocol: debug_assert!() Span to reflect a valid slice (#6806)
Also enforce this by #[non_exhaustive] span such that going forward we
cannot, in debug builds (1), construct invalid spans.

The motivation for this stems from #6431 where I've seen crashes due to
invalid slice indexing.

My hope is this will mitigate such senarios

1. https://github.com/nushell/nushell/pull/6431#issuecomment-1278147241

# Description

(description of your pull request here)

# Tests

Make sure you've done the following:

- [ ] Add tests that cover your changes, either in the command examples,
the crate/tests folder, or in the /tests folder.
- [ ] Try to think about corner cases and various ways how your changes
could break. Cover them with tests.
- [ ] If adding tests is not possible, please document in the PR body a
minimal example with steps on how to reproduce so one can verify your
change works.

Make sure you've run and fixed any issues with these commands:

- [x] `cargo fmt --all -- --check` to check standard code formatting
(`cargo fmt --all` applies these changes)
- [ ] `cargo clippy --workspace --features=extra -- -D warnings -D
clippy::unwrap_used -A clippy::needless_collect` to check that you're
using the standard code style
- [ ] `cargo test --workspace --features=extra` to check that all the
tests pass

# Documentation

- [ ] If your PR touches a user-facing nushell feature then make sure
that there is an entry in the documentation
(https://github.com/nushell/nushell.github.io) for the feature, and
update it if necessary.
2022-12-03 11:44:12 +02:00
e6cf18ea43 nu-explore/ A few fixes. (#7334)
close #7322
close #7323

Signed-off-by: Maxim Zhiburt <zhiburt@gmail.com>
2022-12-03 00:12:33 +02:00
d28624796c make histogram sorted (#7267)
# Description

Closes:  #7208

After this pr, histogram will output by count descending

# User-Facing Changes

_(List of all changes that impact the user experience here. This helps
us keep track of breaking changes.)_

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-02 09:29:19 -08:00
380c216d77 Fix documentation for merge (#7329)
# Description

`merge` no longer accepts blocks as arguments.
2022-12-02 11:35:28 -05:00
ee5a387300 Handle mixed LF+CRLF in lines (#7316)
This closes #4989. Previously `lines` was unable to handle text input
with CRLF line breaks _and_ LF line breaks.

### Before:

![image](https://user-images.githubusercontent.com/26268125/205207685-b25da9e1-19fa-4abb-8ab2-0dd216c63fc0.png)

### After:


![image](https://user-images.githubusercontent.com/26268125/205207808-9f687242-a8c2-4b79-a12c-38b0583d8d52.png)
2022-12-02 11:30:26 -05:00
3ac36879e0 Handle ctrl-c in RawStream iterator (#7314)
Fixes #7246 and #1898.

Darren noticed that `open /dev/random` could not be interrupted by
`ctrl+c`. Thankfully the solution was very simple; it looks like we just
forgot to check `ctrlc` in the `impl Iterator for RawStream`!

To reproduce this, just run `open /dev/random` and then cancel it with
`ctrl+c`.
2022-12-02 08:00:56 -08:00
bc0c9ab698 add :q! alias to explore command (#7326)
# Description

This simply adds an alias to the explore quit command in order to quit
out of explore. `:q` and `:q!` work now.

# User-Facing Changes

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-02 08:13:19 -06:00
5762489070 Edited help text and examples in explore for readability (#7324)
# Description

* Various help messages were edited for clarity/grammar/etc.
* Some examples were made more interesting or relevant

# User-Facing Changes

See above.

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-02 08:01:02 -06:00
fcdc474731 uniq-by command (#7295)
New command `uniq-by` to get uniq results by column.

Closes https://github.com/nushell/nushell/issues/7109
2022-12-02 11:36:01 +01:00
f491d3e1e1 Rename $env.config.explore_config to $env.config.explore (for consistency with $env.config.ls, $env.config.table etc.) (#7317)
# Description

* `$env.config.explore_config` renamed to `$env.config.explore`. This
follows the principle that config subrecords relating to single commands
(as this relates to `explore`) should be exactly named after the command
(see `ls`, `rm`, `table` etc.)
* In `into_config()`, moved the match arm relating to
`$env.config.explore` out of the "legacy options" section (which is
slated for removal in a later version).

# User-Facing Changes

`explore` is not in any public releases yet, so this has no end-user
impact.

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-02 01:42:18 -05:00
94c89eb623 Use setup-rust-toolchain for release workflow (#7315)
# Description

Use setup-rust-toolchain for release workflow to inline with the CI
workflow

Test workflow:
https://github.com/hustcer/nu-release/actions/runs/3598316520
Demo Release: https://github.com/hustcer/nu-release/releases/tag/v0.72.8
2022-12-01 19:23:29 -08:00
cf0a18be51 Fix where -b flag (#7313)
# Description

The `where -b` flag was broken. The following now works:
```
let cond = {|x| $x.name !~ 'foo'}; ls | where -b $cond
```

This is just a quick fix. Ultimately, the `where` command shouldn't need
the flag and `where $cond` should work. The first step, however, is to
move `where` away from shape-directed parsing and make it a parser
keyword.

# User-Facing Changes

`where -b` is not broken

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-01 15:11:03 -08:00
JT
0621ab6652 couple minor updates to xml deps (#7311)
# Description

Just some minor updates to xml deps

# User-Facing Changes

_(List of all changes that impact the user experience here. This helps
us keep track of breaking changes.)_

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-02 08:25:13 +13:00
64a028cc76 Deliver a few fixes for explore command (#7310)
ref #6984

Signed-off-by: Maxim Zhiburt <zhiburt@gmail.com>
2022-12-01 12:14:56 -06:00
f71a45235a fix try for external command runs to failed (#7300)
# Description

Fixes: #7298

So `try .. catch` works better on external command failed.

# User-Facing Changes

```
try {nu --testbin fail} catch {print "fail"}
```

After this pr, it will output "fail"

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.

Co-authored-by: JT <547158+jntrnr@users.noreply.github.com>
2022-12-02 05:58:32 +13:00
718ee3d545 [MVP][WIP] less like pager (#6984)
Run it as `explore`.

#### example

```nu
ls | explore
```

Configuration points in `config.nu` file.
```
  # A 'explore' utility config
   explore_config: {
     highlight: { bg: 'yellow', fg: 'black' }
     status_bar: { bg: '#C4C9C6', fg: '#1D1F21' }
     command_bar: { fg: '#C4C9C6' }
     split_line: '#404040'
     cursor: true
     # selected_column: 'blue'
     # selected_row: { fg: 'yellow', bg: '#C1C2A3' }
     # selected_cell: { fg: 'white', bg: '#777777' }
     # line_shift: false,
     # line_index: false,
     # line_head_top: false,
     # line_head_bottom: false,
   }
```

You can start without a pipeline and type `explore` and it'll give you a
few tips.

![image](https://user-images.githubusercontent.com/343840/205088971-a8c0262f-f222-4641-b13a-027fbd4f5e1a.png)

If you type `:help` you an see the help screen with some information on
what tui keybindings are available.

![image](https://user-images.githubusercontent.com/343840/205089461-c4c54217-7ec4-4fa0-96c0-643d68dc0062.png)

From the `:help` screen you can now hit `i` and that puts you in
`cursor` aka `inspection` mode and you can move the cursor left right up
down and it you put it on an area such as `[table 5 rows]` and hit the
enter key, you'll see something like this, which shows all the `:`
commands. If you hit `esc` it will take you to the previous screen.

![image](https://user-images.githubusercontent.com/343840/205090155-3558a14b-87b7-4072-8dfb-dc8cc2ef4943.png)

If you then type `:try` you'll get this type of window where you can
type in the top portion and see results in the bottom.

![image](https://user-images.githubusercontent.com/343840/205089185-3c065551-0792-43d6-a13c-a52762856209.png)

The `:nu` command is interesting because you can type pipelines like
`:nu ls | sort-by type size` or another pipeline of your choosing such
as `:nu sys` and that will show the table that looks like this, which
we're calling "table mode".

![image](https://user-images.githubusercontent.com/343840/205090809-e686ff0f-6d0b-4347-8ed0-8c59adfbd741.png)

If you hit the `t` key it will now transpose the view to look like this.

![image](https://user-images.githubusercontent.com/343840/205090948-a834d7f2-1713-4dfe-92fe-5432f287df3d.png)

In table mode or transposed table mode you can use the `i` key to
inspect any collapsed field like `{record 8 fields}`, `[table 16 rows]`,
`[list x]`, etc.

One of the original benefits was that when you're in a view that has a
lot of columns, `explore` gives you the ability to scroll left, right,
up, and down.

`explore` is also smart enough to know when you're in table mode versus
preview mode. If you do `open Cargo.toml | explore` you get this.

![image](https://user-images.githubusercontent.com/343840/205091822-cac79130-3a52-4ca8-9210-eba5be30ed58.png)

If you type `open --raw Cargo.toml | explore` you get this where you can
scroll left, right, up, down. This is called preview mode.

![image](https://user-images.githubusercontent.com/343840/205091990-69455191-ab78-4fea-a961-feafafc16d70.png)

When you're in table mode, you can also type `:preview`. So, with `open
--raw Cargo.toml | explore`, if you type `:preview`, it will look like
this.

![image](https://user-images.githubusercontent.com/343840/205092569-436aa55a-0474-48d5-ab71-baddb1f43027.png)

Signed-off-by: Maxim Zhiburt <zhiburt@gmail.com>
Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2022-12-01 09:32:10 -06:00
e92678ea2c Add a deprecation note for removed build-string (#7307)
Build string was removed for 0.72 by #7144

Adds a deprecation message
2022-12-01 16:26:59 +01:00
1f175d4c98 Add natural logarithm (#7258)
- `math ln`
2022-12-01 15:58:05 +01:00
4d6ccf2540 Add inverse hyperbolic functions (#7258)
- `math arcsinh`
- `math arccosh`
- `math arctanh`
2022-12-01 15:58:05 +01:00
aa6c3936d2 Add inverse for trigonometric functions (#7258)
- `math arcsin`
- `math arccos`
- `math arctan`

Again include `--degrees` or `-d` for convenient output in degrees
2022-12-01 15:58:05 +01:00
4f05994b36 Add basic hyperbolic functions (#7258)
`math sinh`
`math cosh`
`math tanh`
2022-12-01 15:58:05 +01:00
b27d6b2cb1 Add basic trigonometric functions (#7258)
`math sin`
`math cos`
`math tan`

Support degrees with the flag `--degrees`/`-d`
2022-12-01 15:58:05 +01:00
64f226f7da Add math pi and math e constants (#7258)
Currently implemented as commands

Work towards #7073

Add them to the example test harness together with `math round`
2022-12-01 15:58:05 +01:00
5c1606ed82 Add -n flag to sort (formerly only available on sort-by) (#7293)
# Description

* `-n`, `--natural` flag from `sort-by` is now on the plain `sort`.
* The `-i`, `-n` and `-r` flags now work with single record sorting
(formerly they didn't)

# User-Facing Changes

See above.

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-01 07:11:30 -06:00
11977759ce fix cal input_output_types signature (#7306)
# Description

This is one of many commands that needs the `input_output_types()` part
of the signature filled in so that `$nu.scope.commands` shows the
signature properly which leads to the documentation being updated
properly.

TIL that when commands like `cal` don't have Example tests that can
easily be expressed and require the use of `None` results that we need
to use this as part of the signature.

```rust
.allow_variants_without_examples(true) // TODO: supply exhaustive examples
```

Related to https://github.com/nushell/nushell/issues/7287

# User-Facing Changes



# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-01 07:10:49 -06:00
bc3dc98b34 add -f, --force for save command (#7262)
# Description

Closes: #6920 

# User-Facing Changes

```
❯ "asdf" | save dump.rdb
Error:
  × Destination file already exists
   ╭─[entry #21:1:1]
 1 │ "asdf" | save dump.rdb
   ·               ────┬───
   ·                   ╰── Destination file '/tmp/dump.rdb' already exists
   ╰────
  help: you can use -f, --force to force overwriting the destination
```
# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-01 06:26:17 -06:00
6fadc72553 Remove unused dev-dependencies (#7285)
Warning: the `nu-json` crate seems to be undertested as the main test
code is commented out. Thus the unused dependencies there were just
commented out
2022-12-01 11:53:24 +01:00
a9e6b1ec6b Add did-you-mean suggestions for bitwise ops (#7252)
Continues work from #7251 to include the bitwise operations.
Covers the C style conventions as well as the typo `bits-*` instead of
`bit-*`
2022-12-01 11:34:41 +01:00
cbc7b94b02 Remove inactive actions-rs/toolchain@v1.0.6 for release workflow (#7302)
# Description

Remove inactive actions-rs/toolchain@v1.0.6 for release workflow,
https://github.com/actions-rs/toolchain is inactive for more than two
years, and have lots of unfixed warnings:
https://github.com/actions-rs/toolchain/issues?q=is%3Aissue+is%3Aopen+warning

After this PR:

Workflow running result:
https://github.com/hustcer/nu-release/actions/runs/3590194180
Release Test: https://github.com/hustcer/nu-release/releases/tag/v0.72.7
2022-12-01 16:30:25 +08:00
45c66e2090 Update release script to nu v0.71 and use ubuntu-20.04 to build nu binary (#7290)
# Description

1. Update nu to v0.71 for release script
2. Remove the usage of `set-output` see:
https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/
3. Use `ubuntu-20.04` instead of `ubuntu-latest` to fix #7282 

To check the workflow running result see:
https://github.com/hustcer/nu-release/actions/runs/3588720720/jobs/6040412953

# User-Facing Changes

_(List of all changes that impact the user experience here. This helps
us keep track of breaking changes.)_

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-01 10:44:21 +08:00
11b2423544 add comments to release-pkg for manual running (#7277)
# Description

This PR is just some comments in the release-pkg.nu script. We had to
figure out how to run it manually so I thought it would be good to
document those requirements just in case we need to do it again
sometime.

# User-Facing Changes

N/A

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-11-30 20:18:28 -06:00
1f9907d2ff Fix failing test after #7051 (#7299)
Numerics as record names have to be quoted
Changed to string
2022-12-01 00:48:02 +01:00
fd503fceaf allow tables in ++ operator (#7051)
This PR closes #6916, which now allows table/table operations on the
`++` operator.
```
[[a b]; [1 2]] ++ [[a b]; [1 3]]
╭───┬───┬───╮
│ # │ a │ b │
├───┼───┼───┤
│ 0 │ 1 │ 2 │
│ 1 │ 1 │ 3 │
╰───┴───┴───╯
```
2022-12-01 00:21:59 +01:00
b7e5790cd1 fix dfr datetime conversion (#7264)
# Description

Closes #7257

This fixes an issue where dataframes would always try to convert
datetimes with milliseconds. Since the timeunit is passed in, I make use
of it and try to choose the appropriate divisor.


# User-Facing Changes


# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-11-30 17:10:28 -06:00
3caab5de36 bump to dev release v0.72.1 (#7281)
# Description

Just bumping to the next dev version. Submitting as a draft until we're
ready.

# User-Facing Changes



# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-11-30 16:06:22 -06:00
fa97e819eb Suggest using float on Value::Int overflow (#7253)
# Description

Suggest that floats support a larger range of values but warn about the
loss in precision.


![image](https://user-images.githubusercontent.com/15833959/204114339-c987cd47-f035-4c01-853f-e9a00441bf49.png)


(Doesn't apply to the types with associated units)

# Tests + Formatting

(-)
2022-11-29 13:30:02 -08:00
bdc4bf97a7 Upgrade windows and trash crates (#7259)
This upgrades the `windows` and `trash` crates so we are only compiling
1 version of the `windows` crate ([I recently upgraded the version used
in `trash`](https://github.com/Byron/trash-rs/pull/58)).

I was hoping that this would lead to some decent compile time
improvements, but unfortunately it did not. Compiling 1 version of
`windows` with all the features unified is about as slow as compiling 2
versions with distinct feature sets. Still, might as well upgrade.
2022-11-29 13:05:32 -08:00
JT
cfb0f3961b Simple README updates (#7279)
# Description

_(Thank you for improving Nushell. Please, check our [contributing
guide](../CONTRIBUTING.md) and talk to the core team before making major
changes.)_

_(Description of your pull request goes here. **Provide examples and/or
screenshots** if your changes affect the user experience.)_

# User-Facing Changes

_(List of all changes that impact the user experience here. This helps
us keep track of breaking changes.)_

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-11-30 08:10:11 +13:00
444 changed files with 18931 additions and 6486 deletions

View File

@ -11,7 +11,10 @@ jobs:
strategy:
fail-fast: true
matrix:
platform: [windows-latest, macos-latest, ubuntu-latest]
# Pinning to Ubuntu 20.04 because building on newer Ubuntu versions causes linux-gnu
# builds to link against a too-new-for-many-Linux-installs glibc version. Consider
# revisiting this when 20.04 is closer to EOL (April 2025)
platform: [windows-latest, macos-latest, ubuntu-20.04]
rust:
- stable
@ -25,17 +28,11 @@ jobs:
- name: Setup Rust toolchain and cache
uses: actions-rust-lang/setup-rust-toolchain@v1.3.4
- name: Rustfmt
uses: actions-rs/cargo@v1.0.1
with:
command: fmt
args: --all -- --check
- name: cargo fmt
run: cargo fmt --all -- --check
- name: Clippy
uses: actions-rs/cargo@v1.0.1
with:
command: clippy
args: --workspace --exclude nu_plugin_* -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect
run: cargo clippy --workspace --exclude nu_plugin_* -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect
nu-tests:
env:
@ -44,7 +41,7 @@ jobs:
strategy:
fail-fast: true
matrix:
platform: [windows-latest, macos-latest, ubuntu-latest]
platform: [windows-latest, macos-latest, ubuntu-20.04]
style: [default, dataframe]
rust:
- stable
@ -69,10 +66,7 @@ jobs:
uses: actions-rust-lang/setup-rust-toolchain@v1.3.4
- name: Tests
uses: actions-rs/cargo@v1.0.1
with:
command: test
args: --workspace --profile ci --exclude nu_plugin_* ${{ matrix.flags }}
run: cargo test --workspace --profile ci --exclude nu_plugin_* ${{ matrix.flags }}
python-virtualenv:
env:
@ -81,7 +75,7 @@ jobs:
strategy:
fail-fast: true
matrix:
platform: [ubuntu-latest, macos-latest, windows-latest]
platform: [ubuntu-20.04, macos-latest, windows-latest]
rust:
- stable
py:
@ -96,10 +90,7 @@ jobs:
uses: actions-rust-lang/setup-rust-toolchain@v1.3.4
- name: Install Nushell
uses: actions-rs/cargo@v1.0.1
with:
command: install
args: --locked --path=. --profile ci --no-default-features
run: cargo install --locked --path=. --profile ci --no-default-features
- name: Setup Python
uses: actions/setup-python@v4
@ -125,7 +116,7 @@ jobs:
strategy:
fail-fast: true
matrix:
platform: [windows-latest, macos-latest, ubuntu-latest]
platform: [windows-latest, macos-latest, ubuntu-20.04]
rust:
- stable
@ -138,13 +129,7 @@ jobs:
uses: actions-rust-lang/setup-rust-toolchain@v1.3.4
- name: Clippy
uses: actions-rs/cargo@v1.0.1
with:
command: clippy
args: --package nu_plugin_* ${{ matrix.flags }} -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect
run: cargo clippy --package nu_plugin_* ${{ matrix.flags }} -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect
- name: Tests
uses: actions-rs/cargo@v1.0.1
with:
command: test
args: --profile ci --package nu_plugin_*
run: cargo test --profile ci --package nu_plugin_*

View File

@ -6,6 +6,21 @@
# REF:
# 1. https://github.com/volks73/cargo-wix
# Added 2022-11-29 when Windows packaging wouldn't work
# because softprops/action-gh-release was broken
# To run this manual for windows
# let-env TARGET = 'x86_64-pc-windows-msvc'
# let-env TARGET_RUSTFLAGS = ''
# let-env GITHUB_WORKSPACE = 'C:\Users\dschroeder\source\repos\forks\nushell'
# Pass 1 let-env _EXTRA_ = 'bin'
# Pass 2 let-env _EXTRA_ = 'msi'
# make sure 7z.exe is in your path https://www.7-zip.org/download.html
# make sure aria2c.exe is in your path https://github.com/aria2/aria2
# make sure you have the wixtools installed https://wixtoolset.org/
# set os below like this because it's what github's runner is named
# let os = 'windows-latest'
# The main binary file to be released
let bin = 'nu'
let os = $env.OS
@ -16,8 +31,13 @@ let flags = $env.TARGET_RUSTFLAGS
let dist = $'($env.GITHUB_WORKSPACE)/output'
let version = (open Cargo.toml | get package.version)
$'Debugging info:'
print { version: $version, bin: $bin, os: $os, target: $target, src: $src, flags: $flags, dist: $dist }; hr-line -b
# $env
let USE_UBUNTU = 'ubuntu-20.04'
$'(char nl)Packaging ($bin) v($version) for ($target) in ($src)...'; hr-line -b
if not ('Cargo.lock' | path exists) { cargo generate-lockfile }
@ -26,8 +46,9 @@ $'Start building ($bin)...'; hr-line
# ----------------------------------------------------------------------------
# Build for Ubuntu and macOS
# ----------------------------------------------------------------------------
if $os in ['ubuntu-latest', 'macos-latest'] {
if $os == 'ubuntu-latest' {
if $os in [$USE_UBUNTU, 'macos-latest'] {
if $os == $USE_UBUNTU {
sudo apt update
sudo apt-get install libxcb-composite0-dev -y
}
if $target == 'aarch64-unknown-linux-gnu' {
@ -38,10 +59,14 @@ if $os in ['ubuntu-latest', 'macos-latest'] {
sudo apt-get install pkg-config gcc-arm-linux-gnueabihf -y
let-env CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_LINKER = 'arm-linux-gnueabihf-gcc'
cargo-build-nu $flags
} else if $target == 'riscv64gc-unknown-linux-gnu' {
sudo apt-get install gcc-riscv64-linux-gnu -y
let-env CARGO_TARGET_RISCV64GC_UNKNOWN_LINUX_GNU_LINKER = 'riscv64-linux-gnu-gcc'
cargo-build-nu $flags
} else {
# musl-tools to fix 'Failed to find tool. Is `musl-gcc` installed?'
# Actually just for x86_64-unknown-linux-musl target
if $os == 'ubuntu-latest' { sudo apt install musl-tools -y }
if $os == $USE_UBUNTU { sudo apt install musl-tools -y }
cargo-build-nu $flags
}
}
@ -88,7 +113,7 @@ if ($ver | str trim | is-empty) {
# Create a release archive and send it to output for the following steps
# ----------------------------------------------------------------------------
cd $dist; $'(char nl)Creating release archive...'; hr-line
if $os in ['ubuntu-latest', 'macos-latest'] {
if $os in [$USE_UBUNTU, 'macos-latest'] {
let files = (ls | get name)
let dest = $'($bin)-($version)-($target)'
@ -101,7 +126,8 @@ if $os in ['ubuntu-latest', 'macos-latest'] {
tar -czf $archive $dest
print $'archive: ---> ($archive)'; ls $archive
echo $'::set-output name=archive::($archive)'
# REF: https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/
echo $"archive=($archive)" | save --append $env.GITHUB_OUTPUT
} else if $os == 'windows-latest' {
@ -121,7 +147,8 @@ if $os in ['ubuntu-latest', 'macos-latest'] {
cp -r $'($dist)/*' target/release/
cargo install cargo-wix --version 0.3.3
cargo wix --no-build --nocapture --package nu --output $wixRelease
echo $'::set-output name=archive::($wixRelease)'
print $'archive: ---> ($wixRelease)';
echo $"archive=($wixRelease)" | save --append $env.GITHUB_OUTPUT
} else {
@ -131,7 +158,7 @@ if $os in ['ubuntu-latest', 'macos-latest'] {
print $'archive: ---> ($archive)';
let pkg = (ls -f $archive | get name)
if not ($pkg | is-empty) {
echo $'::set-output name=archive::($pkg | get 0)'
echo $"archive=($pkg | get 0)" | save --append $env.GITHUB_OUTPUT
}
}
}

View File

@ -27,6 +27,7 @@ jobs:
- x86_64-unknown-linux-musl
- aarch64-unknown-linux-gnu
- armv7-unknown-linux-gnueabihf
- riscv64gc-unknown-linux-gnu
extra: ['bin']
include:
- target: aarch64-apple-darwin
@ -44,35 +45,37 @@ jobs:
os: windows-latest
target_rustflags: ''
- target: x86_64-unknown-linux-gnu
os: ubuntu-latest
os: ubuntu-20.04
target_rustflags: ''
- target: x86_64-unknown-linux-musl
os: ubuntu-latest
os: ubuntu-20.04
target_rustflags: ''
- target: aarch64-unknown-linux-gnu
os: ubuntu-latest
os: ubuntu-20.04
target_rustflags: ''
- target: armv7-unknown-linux-gnueabihf
os: ubuntu-latest
os: ubuntu-20.04
target_rustflags: ''
- target: riscv64gc-unknown-linux-gnu
os: ubuntu-20.04
target_rustflags: ''
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v3.0.2
- uses: actions/checkout@v3.1.0
- name: Install Rust Toolchain Components
uses: actions-rs/toolchain@v1.0.6
with:
override: true
profile: minimal
toolchain: stable
target: ${{ matrix.target }}
- name: Update Rust Toolchain Target
run: |
echo "targets = ['${{matrix.target}}']" >> rust-toolchain.toml
- name: Setup Rust toolchain and cache
uses: actions-rust-lang/setup-rust-toolchain@v1.3.4
- name: Setup Nushell
uses: hustcer/setup-nu@v2.1
uses: hustcer/setup-nu@v3
with:
version: 0.69.1
version: 0.72.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

267
Cargo.lock generated
View File

@ -89,6 +89,15 @@ dependencies = [
"ansitok",
]
[[package]]
name = "ansi-str"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21b1ed1c166829a0ccb5d79caa0f75cb4abd4adb2ce2c096755b7ad5ffdb0990"
dependencies = [
"ansitok",
]
[[package]]
name = "ansitok"
version = "0.2.0"
@ -101,9 +110,9 @@ dependencies = [
[[package]]
name = "anyhow"
version = "1.0.65"
version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98161a4e3e2184da77bb14f02184cdd111e83bbbcc9979dfee3c44b9a85f5602"
checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6"
[[package]]
name = "array-init-cursor"
@ -430,19 +439,25 @@ checksum = "6c58ec36aac5066d5ca17df51b3e70279f5670a72102f5752cb7e7c856adfc70"
[[package]]
name = "calamine"
version = "0.18.0"
version = "0.19.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b86ca78da4bdce5ac0f0bdbc0218ad14232f1e668376e044233f64c527cf5abb"
checksum = "6381d1037ee9b8a6c8eb97936add0331a1aabd148d5b6f35f1cda6e5dec44f40"
dependencies = [
"byteorder",
"codepage",
"encoding_rs",
"log",
"quick-xml 0.19.0",
"quick-xml",
"serde",
"zip",
]
[[package]]
name = "cassowary"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53"
[[package]]
name = "cast"
version = "0.3.0"
@ -1256,12 +1271,6 @@ dependencies = [
"libc",
]
[[package]]
name = "fuchsia-cprng"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
[[package]]
name = "fuchsia-zircon"
version = "0.3.3"
@ -1880,9 +1889,9 @@ dependencies = [
[[package]]
name = "json_to_table"
version = "0.2.0"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "408f09e42613f7a9902ecf2f30bcd053cf9f5668d0b1493ae1669070338d661b"
checksum = "a0be33515faeb3773f550c80fd7a889148164e58f7e3cf36467718c8ce71ee55"
dependencies = [
"serde_json",
"tabled",
@ -2469,7 +2478,7 @@ dependencies = [
[[package]]
name = "nu"
version = "0.72.0"
version = "0.73.0"
dependencies = [
"assert_cmd",
"atty",
@ -2523,7 +2532,7 @@ dependencies = [
[[package]]
name = "nu-cli"
version = "0.72.0"
version = "0.73.0"
dependencies = [
"atty",
"chrono",
@ -2531,7 +2540,6 @@ dependencies = [
"fancy-regex",
"fuzzy-matcher",
"is_executable",
"lazy_static",
"log",
"miette",
"nu-ansi-term",
@ -2543,6 +2551,7 @@ dependencies = [
"nu-protocol",
"nu-test-support",
"nu-utils",
"once_cell",
"percent-encoding",
"reedline",
"rstest",
@ -2552,21 +2561,25 @@ dependencies = [
[[package]]
name = "nu-color-config"
version = "0.72.0"
version = "0.73.0"
dependencies = [
"nu-ansi-term",
"nu-engine",
"nu-json",
"nu-protocol",
"nu-table",
"nu-test-support",
"nu-utils",
"serde",
"tabled",
]
[[package]]
name = "nu-command"
version = "0.72.0"
version = "0.73.0"
dependencies = [
"Inflector",
"alphanumeric-sort",
"atty",
"base64",
"byteorder",
"bytesize",
@ -2592,7 +2605,6 @@ dependencies = [
"indexmap",
"is-root",
"itertools",
"lazy_static",
"libc",
"log",
"lscolors",
@ -2603,6 +2615,7 @@ dependencies = [
"nu-ansi-term",
"nu-color-config",
"nu-engine",
"nu-explore",
"nu-glob",
"nu-json",
"nu-parser",
@ -2622,12 +2635,13 @@ dependencies = [
"polars",
"powierza-coefficient",
"proptest",
"quick-xml 0.23.1",
"quick-xml",
"quickcheck",
"quickcheck_macros",
"rand 0.8.5",
"rayon",
"reedline",
"regex",
"reqwest",
"roxmltree",
"rstest",
@ -2654,13 +2668,13 @@ dependencies = [
"uuid",
"wax",
"which",
"windows 0.42.0",
"windows",
"winreg",
]
[[package]]
name = "nu-engine"
version = "0.72.0"
version = "0.73.0"
dependencies = [
"chrono",
"nu-glob",
@ -2670,30 +2684,45 @@ dependencies = [
"sysinfo",
]
[[package]]
name = "nu-explore"
version = "0.73.0"
dependencies = [
"ansi-str 0.7.2",
"crossterm 0.24.0",
"lscolors",
"nu-ansi-term",
"nu-color-config",
"nu-engine",
"nu-json",
"nu-parser",
"nu-protocol",
"nu-table",
"nu-utils",
"strip-ansi-escapes",
"terminal_size 0.2.1",
"tui",
]
[[package]]
name = "nu-glob"
version = "0.72.0"
version = "0.73.0"
dependencies = [
"doc-comment",
"tempdir",
]
[[package]]
name = "nu-json"
version = "0.72.0"
version = "0.73.0"
dependencies = [
"fancy-regex",
"lazy_static",
"linked-hash-map",
"nu-path",
"num-traits",
"serde",
"serde_json",
]
[[package]]
name = "nu-parser"
version = "0.72.0"
version = "0.73.0"
dependencies = [
"bytesize",
"chrono",
@ -2710,7 +2739,7 @@ dependencies = [
[[package]]
name = "nu-path"
version = "0.72.0"
version = "0.73.0"
dependencies = [
"dirs-next",
"omnipath",
@ -2719,7 +2748,7 @@ dependencies = [
[[package]]
name = "nu-plugin"
version = "0.72.0"
version = "0.73.0"
dependencies = [
"bincode",
"criterion",
@ -2733,7 +2762,7 @@ dependencies = [
[[package]]
name = "nu-pretty-hex"
version = "0.72.0"
version = "0.73.0"
dependencies = [
"heapless",
"nu-ansi-term",
@ -2742,7 +2771,7 @@ dependencies = [
[[package]]
name = "nu-protocol"
version = "0.72.0"
version = "0.73.0"
dependencies = [
"byte-unit",
"chrono",
@ -2751,6 +2780,7 @@ dependencies = [
"indexmap",
"miette",
"nu-json",
"nu-test-support",
"nu-utils",
"num-format",
"serde",
@ -2764,7 +2794,7 @@ dependencies = [
[[package]]
name = "nu-system"
version = "0.72.0"
version = "0.73.0"
dependencies = [
"atty",
"chrono",
@ -2782,12 +2812,15 @@ dependencies = [
[[package]]
name = "nu-table"
version = "0.72.0"
version = "0.73.0"
dependencies = [
"atty",
"json_to_table",
"nu-ansi-term",
"nu-color-config",
"nu-engine",
"nu-protocol",
"nu-test-support",
"nu-utils",
"serde_json",
"tabled",
@ -2795,7 +2828,7 @@ dependencies = [
[[package]]
name = "nu-term-grid"
version = "0.72.0"
version = "0.73.0"
dependencies = [
"nu-utils",
"unicode-width",
@ -2803,21 +2836,21 @@ dependencies = [
[[package]]
name = "nu-test-support"
version = "0.72.0"
version = "0.73.0"
dependencies = [
"getset",
"hamcrest2",
"lazy_static",
"nu-glob",
"nu-path",
"nu-utils",
"num-format",
"once_cell",
"tempfile",
]
[[package]]
name = "nu-utils"
version = "0.72.0"
version = "0.73.0"
dependencies = [
"crossterm_winapi",
"lscolors",
@ -2838,7 +2871,7 @@ dependencies = [
[[package]]
name = "nu_plugin_example"
version = "0.72.0"
version = "0.73.0"
dependencies = [
"nu-plugin",
"nu-protocol",
@ -2846,7 +2879,7 @@ dependencies = [
[[package]]
name = "nu_plugin_gstat"
version = "0.72.0"
version = "0.73.0"
dependencies = [
"git2",
"nu-engine",
@ -2856,7 +2889,7 @@ dependencies = [
[[package]]
name = "nu_plugin_inc"
version = "0.72.0"
version = "0.73.0"
dependencies = [
"nu-plugin",
"nu-protocol",
@ -2865,7 +2898,7 @@ dependencies = [
[[package]]
name = "nu_plugin_query"
version = "0.72.0"
version = "0.73.0"
dependencies = [
"gjson",
"nu-engine",
@ -3138,7 +3171,7 @@ version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1526bb6aa9f10ec339fb10360f22c57edf81d5678d0278e93bc12a47ffbe4b01"
dependencies = [
"ansi-str",
"ansi-str 0.5.0",
"ansitok",
"bytecount",
"fnv",
@ -3771,23 +3804,14 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"
[[package]]
name = "quick-xml"
version = "0.19.0"
version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3d72d5477478f85bd00b6521780dfba1ec6cdaadcf90b8b181c36d7de561f9b"
checksum = "58e21a144a0ffb5fad7b464babcdab934a325ad69b7c0373bcfef5cbd9799ca9"
dependencies = [
"encoding_rs",
"memchr",
]
[[package]]
name = "quick-xml"
version = "0.23.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11bafc859c6815fbaffbbbf4229ecb767ac913fecb27f9ad4343662e9ef099ea"
dependencies = [
"memchr",
]
[[package]]
name = "quickcheck"
version = "1.0.3"
@ -3819,19 +3843,6 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
dependencies = [
"fuchsia-cprng",
"libc",
"rand_core 0.3.1",
"rdrand",
"winapi 0.3.9",
]
[[package]]
name = "rand"
version = "0.7.3"
@ -3877,21 +3888,6 @@ dependencies = [
"rand_core 0.6.4",
]
[[package]]
name = "rand_core"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
dependencies = [
"rand_core 0.4.2",
]
[[package]]
name = "rand_core"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
[[package]]
name = "rand_core"
version = "0.5.1"
@ -3971,15 +3967,6 @@ dependencies = [
"num_cpus",
]
[[package]]
name = "rdrand"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "redox_syscall"
version = "0.2.16"
@ -4142,9 +4129,9 @@ dependencies = [
[[package]]
name = "roxmltree"
version = "0.14.1"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "921904a62e410e37e215c40381b7117f830d9d89ba60ab5236170541dd25646b"
checksum = "fb6d47b59770b0ae88c7f270c68502832ec14d8c7ab5f7a584f204bb76dbfd8e"
dependencies = [
"xmlparser",
]
@ -4877,7 +4864,7 @@ version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56c3ee73732ffceaea7b8f6b719ce3bb17f253fa27461ffeaf568ebd0cdb4b85"
dependencies = [
"ansi-str",
"ansi-str 0.5.0",
"papergrid",
"tabled_derive",
"unicode-width",
@ -4896,16 +4883,6 @@ dependencies = [
"syn",
]
[[package]]
name = "tempdir"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8"
dependencies = [
"rand 0.4.6",
"remove_dir_all",
]
[[package]]
name = "tempfile"
version = "3.3.0"
@ -5164,9 +5141,9 @@ dependencies = [
[[package]]
name = "trash"
version = "2.1.5"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe090367848cd40c4230ff3ce4e2ff6a2fd511c1e14ae047a4a4c37ef7965236"
checksum = "6f74274f95c7e7340d7c5bcd4863af87a9ed6a117cf73cf483c71cb4d744a948"
dependencies = [
"chrono",
"libc",
@ -5175,7 +5152,7 @@ dependencies = [
"once_cell",
"scopeguard",
"url",
"windows 0.37.0",
"windows",
]
[[package]]
@ -5184,6 +5161,19 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
[[package]]
name = "tui"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccdd26cbd674007e649a272da4475fb666d3aa0ad0531da7136db6fab0e5bad1"
dependencies = [
"bitflags",
"cassowary",
"crossterm 0.25.0",
"unicode-segmentation",
"unicode-width",
]
[[package]]
name = "typed-arena"
version = "1.7.0"
@ -5618,22 +5608,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows"
version = "0.37.0"
version = "0.43.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57b543186b344cc61c85b5aab0d2e3adf4e0f99bc076eff9aa5927bcc0b8a647"
dependencies = [
"windows_aarch64_msvc 0.37.0",
"windows_i686_gnu 0.37.0",
"windows_i686_msvc 0.37.0",
"windows_x86_64_gnu 0.37.0",
"windows_x86_64_msvc 0.37.0",
]
[[package]]
name = "windows"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0286ba339aa753e70765d521bb0242cc48e1194562bfa2a2ad7ac8a6de28f5d5"
checksum = "04662ed0e3e5630dfa9b26e4cb823b817f1a9addda855d973a9458c236556244"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc 0.42.0",
@ -5669,12 +5646,6 @@ version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
[[package]]
name = "windows_aarch64_msvc"
version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2623277cb2d1c216ba3b578c0f3cf9cdebeddb6e66b1b218bb33596ea7769c3a"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.0"
@ -5687,12 +5658,6 @@ version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
[[package]]
name = "windows_i686_gnu"
version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3925fd0b0b804730d44d4b6278c50f9699703ec49bcd628020f46f4ba07d9e1"
[[package]]
name = "windows_i686_gnu"
version = "0.42.0"
@ -5705,12 +5670,6 @@ version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
[[package]]
name = "windows_i686_msvc"
version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce907ac74fe331b524c1298683efbf598bb031bc84d5e274db2083696d07c57c"
[[package]]
name = "windows_i686_msvc"
version = "0.42.0"
@ -5723,12 +5682,6 @@ version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
[[package]]
name = "windows_x86_64_gnu"
version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2babfba0828f2e6b32457d5341427dcbb577ceef556273229959ac23a10af33d"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.0"
@ -5747,12 +5700,6 @@ version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
[[package]]
name = "windows_x86_64_msvc"
version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4dd6dc7df2d84cf7b33822ed5b86318fb1781948e9663bacd047fc9dd52259d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.0"
@ -5789,9 +5736,9 @@ dependencies = [
[[package]]
name = "xmlparser"
version = "0.13.3"
version = "0.13.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "114ba2b24d2167ef6d67d7d04c8cc86522b87f490025f39f0303b7db5bf5e3d8"
checksum = "4d25c75bf9ea12c4040a97f829154768bbbce366287e2dc044af160cd79a13fd"
[[package]]
name = "yansi"
@ -5801,14 +5748,14 @@ checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
[[package]]
name = "zip"
version = "0.5.13"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93ab48844d61251bb3835145c521d88aa4031d7139e8485990f60ca911fa0815"
checksum = "537ce7411d25e54e8ae21a7ce0b15840e7bfcff15b51d697ec3266cc76bdf080"
dependencies = [
"byteorder",
"crc32fast",
"crossbeam-utils",
"flate2",
"thiserror",
]
[[package]]

View File

@ -10,7 +10,7 @@ license = "MIT"
name = "nu"
repository = "https://github.com/nushell/nushell"
rust-version = "1.60"
version = "0.72.0"
version = "0.73.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -45,20 +45,20 @@ ctrlc = "3.2.1"
log = "0.4"
miette = { version = "5.1.0", features = ["fancy-no-backtrace"] }
nu-ansi-term = "0.46.0"
nu-cli = { path="./crates/nu-cli", version = "0.72.0" }
nu-color-config = { path = "./crates/nu-color-config", version = "0.72.0" }
nu-command = { path="./crates/nu-command", version = "0.72.0" }
nu-engine = { path="./crates/nu-engine", version = "0.72.0" }
nu-json = { path="./crates/nu-json", version = "0.72.0" }
nu-parser = { path="./crates/nu-parser", version = "0.72.0" }
nu-path = { path="./crates/nu-path", version = "0.72.0" }
nu-plugin = { path = "./crates/nu-plugin", optional = true, version = "0.72.0" }
nu-pretty-hex = { path = "./crates/nu-pretty-hex", version = "0.72.0" }
nu-protocol = { path = "./crates/nu-protocol", version = "0.72.0" }
nu-system = { path = "./crates/nu-system", version = "0.72.0" }
nu-table = { path = "./crates/nu-table", version = "0.72.0" }
nu-term-grid = { path = "./crates/nu-term-grid", version = "0.72.0" }
nu-utils = { path = "./crates/nu-utils", version = "0.72.0" }
nu-cli = { path="./crates/nu-cli", version = "0.73.0" }
nu-color-config = { path = "./crates/nu-color-config", version = "0.73.0" }
nu-command = { path="./crates/nu-command", version = "0.73.0" }
nu-engine = { path="./crates/nu-engine", version = "0.73.0" }
nu-json = { path="./crates/nu-json", version = "0.73.0" }
nu-parser = { path="./crates/nu-parser", version = "0.73.0" }
nu-path = { path="./crates/nu-path", version = "0.73.0" }
nu-plugin = { path = "./crates/nu-plugin", optional = true, version = "0.73.0" }
nu-pretty-hex = { path = "./crates/nu-pretty-hex", version = "0.73.0" }
nu-protocol = { path = "./crates/nu-protocol", version = "0.73.0" }
nu-system = { path = "./crates/nu-system", version = "0.73.0" }
nu-table = { path = "./crates/nu-table", version = "0.73.0" }
nu-term-grid = { path = "./crates/nu-term-grid", version = "0.73.0" }
nu-utils = { path = "./crates/nu-utils", version = "0.73.0" }
reedline = { version = "0.14.0", features = ["bashisms", "sqlite"]}
rayon = "1.5.1"
@ -80,7 +80,7 @@ nix = { version = "0.25", default-features = false, features = ["signal", "proce
atty = "0.2"
[dev-dependencies]
nu-test-support = { path="./crates/nu-test-support", version = "0.72.0" }
nu-test-support = { path="./crates/nu-test-support", version = "0.73.0" }
tempfile = "3.2.0"
assert_cmd = "2.0.2"
pretty_assertions = "1.0.0"

View File

@ -1,6 +1,6 @@
# Nushell <!-- omit in toc -->
[![Crates.io](https://img.shields.io/crates/v/nu.svg)](https://crates.io/crates/nu)
![Build Status](https://img.shields.io/github/workflow/status/nushell/nushell/continuous-integration)
![Build Status](https://img.shields.io/github/actions/workflow/status/nushell/nushell/ci.yml?branch=main)
[![Discord](https://img.shields.io/discord/601130461678272522.svg?logo=discord)](https://discord.gg/NtAbbGn)
[![The Changelog #363](https://img.shields.io/badge/The%20Changelog-%23363-61c192.svg)](https://changelog.com/podcast/363)
[![@nu_shell](https://img.shields.io/badge/twitter-@nu_shell-1DA1F3?style=flat-square)](https://twitter.com/nu_shell)
@ -126,12 +126,13 @@ For example, you can load a .toml file as structured data and explore it:
> open Cargo.toml
╭──────────────────┬────────────────────╮
│ bin │ [table 1 row]
│ dependencies │ {record 24 fields}
│ dependencies │ {record 25 fields}
│ dev-dependencies │ {record 8 fields}
│ features │ {record 10 fields}
│ package │ {record 13 fields}
│ patch │ {record 1 field}
│ profile │ {record 3 fields}
│ target │ {record 2 fields}
│ target │ {record 3 fields}
│ workspace │ {record 1 field}
╰──────────────────┴────────────────────╯
```
@ -149,11 +150,11 @@ We can pipe this into a command that gets the contents of one of the columns:
│ exclude │ [list 1 item]
│ homepage │ https://www.nushell.sh │
│ license │ MIT │
│ metadata │ {record 1 field}
│ name │ nu │
│ readme │ README.md │
│ repository │ https://github.com/nushell/nushell │
│ rust-version │ 1.60 │
│ version │ 0.63.1
│ version │ 0.72.0
╰───────────────┴────────────────────────────────────╯
```
@ -161,7 +162,7 @@ And if needed we can drill down further:
```shell
> open Cargo.toml | get package.version
0.63.1
0.72.0
```
### Plugins

View File

@ -5,21 +5,21 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cli"
edition = "2021"
license = "MIT"
name = "nu-cli"
version = "0.72.0"
version = "0.73.0"
[dev-dependencies]
nu-test-support = { path="../nu-test-support", version = "0.72.0" }
nu-command = { path = "../nu-command", version = "0.72.0" }
nu-test-support = { path="../nu-test-support", version = "0.73.0" }
nu-command = { path = "../nu-command", version = "0.73.0" }
rstest = {version = "0.15.0", default-features = false}
[dependencies]
nu-engine = { path = "../nu-engine", version = "0.72.0" }
nu-path = { path = "../nu-path", version = "0.72.0" }
nu-parser = { path = "../nu-parser", version = "0.72.0" }
nu-protocol = { path = "../nu-protocol", version = "0.72.0" }
nu-utils = { path = "../nu-utils", version = "0.72.0" }
nu-engine = { path = "../nu-engine", version = "0.73.0" }
nu-path = { path = "../nu-path", version = "0.73.0" }
nu-parser = { path = "../nu-parser", version = "0.73.0" }
nu-protocol = { path = "../nu-protocol", version = "0.73.0" }
nu-utils = { path = "../nu-utils", version = "0.73.0" }
nu-ansi-term = "0.46.0"
nu-color-config = { path = "../nu-color-config", version = "0.72.0" }
nu-color-config = { path = "../nu-color-config", version = "0.73.0" }
reedline = { version = "0.14.0", features = ["bashisms", "sqlite"]}
atty = "0.2.14"
@ -28,7 +28,7 @@ crossterm = "0.24.0"
fancy-regex = "0.10.0"
fuzzy-matcher = "0.3.7"
is_executable = "1.0.1"
lazy_static = "1.4.0"
once_cell = "1.16.0"
log = "0.4"
miette = { version = "5.1.0", features = ["fancy-no-backtrace"] }
percent-encoding = "2"

View File

@ -94,10 +94,7 @@ impl CommandCompletion {
value: String::from_utf8_lossy(&x.0).to_string(),
description: x.1,
extra: None,
span: reedline::Span {
start: span.start - offset,
end: span.end - offset,
},
span: reedline::Span::new(span.start - offset, span.end - offset),
append_whitespace: true,
});
@ -108,10 +105,7 @@ impl CommandCompletion {
value: String::from_utf8_lossy(&x).to_string(),
description: None,
extra: None,
span: reedline::Span {
start: span.start - offset,
end: span.end - offset,
},
span: reedline::Span::new(span.start - offset, span.end - offset),
append_whitespace: true,
});
@ -128,15 +122,15 @@ impl CommandCompletion {
value: x,
description: None,
extra: None,
span: reedline::Span {
start: span.start - offset,
end: span.end - offset,
},
span: reedline::Span::new(span.start - offset, span.end - offset),
append_whitespace: true,
});
let results_strings: Vec<String> =
results.clone().into_iter().map(|x| x.value).collect();
for external in results_external {
if results.contains(&external) {
if results_strings.contains(&external.value) {
results.push(Suggestion {
value: format!("^{}", external.value),
description: None,
@ -187,10 +181,7 @@ impl Completer for CommandCompletion {
let subcommands = if let Some(last) = last {
self.complete_commands(
working_set,
Span {
start: last.0.start,
end: pos,
},
Span::new(last.0.start, pos),
offset,
false,
options.match_algorithm,

View File

@ -77,10 +77,7 @@ impl NuCompleter {
Value::List {
vals: spans
.iter()
.map(|it| Value::String {
val: it.to_string(),
span: Span::unknown(),
})
.map(|it| Value::string(it, Span::unknown()))
.collect(),
span: Span::unknown(),
},
@ -92,7 +89,7 @@ impl NuCompleter {
&self.engine_state,
&mut callee_stack,
block,
PipelineData::new(span),
PipelineData::empty(),
true,
true,
);
@ -101,14 +98,8 @@ impl NuCompleter {
Ok(pd) => {
let value = pd.into_value(span);
if let Value::List { vals, span: _ } = value {
let result = map_value_completions(
vals.iter(),
Span {
start: span.start,
end: span.end,
},
offset,
);
let result =
map_value_completions(vals.iter(), Span::new(span.start, span.end), offset);
return Some(result);
}
@ -165,15 +156,12 @@ impl NuCompleter {
// Create a new span
let new_span = if flat_idx == 0 {
Span {
start: flat.0.start,
end: flat.0.end - 1 - span_offset,
}
Span::new(flat.0.start, flat.0.end - 1 - span_offset)
} else {
Span {
start: flat.0.start - span_offset,
end: flat.0.end - 1 - span_offset,
}
Span::new(
flat.0.start - span_offset,
flat.0.end - 1 - span_offset,
)
};
// Parses the prefix. Completion should look up to the cursor position, not after.

View File

@ -52,13 +52,13 @@ impl Completer for CustomCompletion {
head: span,
arguments: vec![
Argument::Positional(Expression {
span: Span { start: 0, end: 0 },
span: Span::unknown(),
ty: Type::String,
expr: Expr::String(self.line.clone()),
custom_completion: None,
}),
Argument::Positional(Expression {
span: Span { start: 0, end: 0 },
span: Span::unknown(),
ty: Type::Int,
expr: Expr::Int(line_pos as i64),
custom_completion: None,
@ -67,7 +67,7 @@ impl Completer for CustomCompletion {
redirect_stdout: true,
redirect_stderr: true,
},
PipelineData::new(span),
PipelineData::empty(),
);
let mut custom_completion_options = None;

View File

@ -136,8 +136,12 @@ pub fn directory_completion(
file_name.push(SEP);
}
// Fix files or folders with quotes
if path.contains('\'') || path.contains('"') || path.contains(' ') {
// Fix files or folders with quotes or hash
if path.contains('\'')
|| path.contains('"')
|| path.contains(' ')
|| path.contains('#')
{
path = format!("`{}`", path);
}

View File

@ -141,8 +141,12 @@ pub fn file_path_completion(
file_name.push(SEP);
}
// Fix files or folders with quotes
if path.contains('\'') || path.contains('"') || path.contains(' ') {
// Fix files or folders with quotes or hashes
if path.contains('\'')
|| path.contains('"')
|| path.contains(' ')
|| path.contains('#')
{
path = format!("`{}`", path);
}

View File

@ -111,10 +111,7 @@ impl Completer for VariableCompletion {
&self.engine_state,
&self.stack,
nu_protocol::NU_VARIABLE_ID,
nu_protocol::Span {
start: current_span.start,
end: current_span.end,
},
nu_protocol::Span::new(current_span.start, current_span.end),
) {
for suggestion in
nested_suggestions(nuval, self.var_context.1.clone(), current_span)
@ -134,13 +131,7 @@ impl Completer for VariableCompletion {
// Completion other variable types
if let Some(var_id) = var_id {
// Extract the variable value from the stack
let var = self.stack.get_var(
var_id,
Span {
start: span.start,
end: span.end,
},
);
let var = self.stack.get_var(var_id, Span::new(span.start, span.end));
// If the value exists and it's of type Record
if let Ok(value) = var {
@ -281,7 +272,7 @@ fn recursive_value(val: Value, sublevels: Vec<Vec<u8>>) -> Value {
// Current sublevel value not found
return Value::Nothing {
span: Span { start: 0, end: 0 },
span: Span::unknown(),
};
}
_ => return val,

View File

@ -8,7 +8,7 @@ use nu_path::canonicalize_with;
use nu_protocol::engine::{EngineState, Stack, StateWorkingSet};
#[cfg(feature = "plugin")]
use nu_protocol::Spanned;
use nu_protocol::{HistoryFileFormat, PipelineData, Span};
use nu_protocol::{HistoryFileFormat, PipelineData};
use std::path::PathBuf;
#[cfg(feature = "plugin")]
@ -38,7 +38,7 @@ pub fn read_plugin_file(
stack,
&contents,
&plugin_filename,
PipelineData::new(Span::new(0, 0)),
PipelineData::empty(),
);
}
}
@ -85,7 +85,7 @@ pub fn eval_config_contents(
stack,
&contents,
&config_filename,
PipelineData::new(Span::new(0, 0)),
PipelineData::empty(),
);
// Merge the environment in case env vars changed in the config

View File

@ -2,13 +2,13 @@ use crate::util::{eval_source, report_error};
use log::info;
use log::trace;
use miette::{IntoDiagnostic, Result};
use nu_engine::convert_env_values;
use nu_engine::{convert_env_values, current_dir};
use nu_parser::parse;
use nu_protocol::Type;
use nu_path::canonicalize_with;
use nu_protocol::{
ast::Call,
engine::{EngineState, Stack, StateWorkingSet},
Config, PipelineData, Span, Value,
Config, PipelineData, ShellError, Span, Type, Value,
};
use nu_utils::stdout_write_all_and_flush;
@ -27,14 +27,75 @@ pub fn evaluate_file(
std::process::exit(1);
}
let file = std::fs::read(&path).into_diagnostic()?;
let cwd = current_dir(engine_state, stack)?;
engine_state.start_in_file(Some(&path));
let file_path = {
match canonicalize_with(&path, &cwd) {
Ok(p) => p,
Err(e) => {
let working_set = StateWorkingSet::new(engine_state);
report_error(
&working_set,
&ShellError::FileNotFoundCustom(
format!("Could not access file '{}': {:?}", path, e.to_string()),
Span::unknown(),
),
);
std::process::exit(1);
}
}
};
let file_path_str = match file_path.to_str() {
Some(s) => s,
None => {
let working_set = StateWorkingSet::new(engine_state);
report_error(
&working_set,
&ShellError::NonUtf8Custom(
format!(
"Input file name '{}' is not valid UTF8",
file_path.to_string_lossy()
),
Span::unknown(),
),
);
std::process::exit(1);
}
};
let file = match std::fs::read(&file_path).into_diagnostic() {
Ok(p) => p,
Err(e) => {
let working_set = StateWorkingSet::new(engine_state);
report_error(
&working_set,
&ShellError::FileNotFoundCustom(
format!(
"Could not read file '{}': {:?}",
file_path_str,
e.to_string()
),
Span::unknown(),
),
);
std::process::exit(1);
}
};
engine_state.start_in_file(Some(file_path_str));
let mut parent = file_path.clone();
parent.pop();
stack.add_env_var(
"FILE_PWD".to_string(),
Value::string(parent.to_string_lossy(), Span::unknown()),
);
let mut working_set = StateWorkingSet::new(engine_state);
trace!("parsing file: {}", path);
let _ = parse(&mut working_set, Some(&path), &file, false, &[]);
trace!("parsing file: {}", file_path_str);
let _ = parse(&mut working_set, Some(file_path_str), &file, false, &[]);
if working_set.find_decl(b"main", &Type::Any).is_some() {
let args = format!("main {}", args.join(" "));
@ -43,15 +104,15 @@ pub fn evaluate_file(
engine_state,
stack,
&file,
&path,
PipelineData::new(Span::new(0, 0)),
file_path_str,
PipelineData::empty(),
) {
std::process::exit(1);
}
if !eval_source(engine_state, stack, args.as_bytes(), "<commandline>", input) {
std::process::exit(1);
}
} else if !eval_source(engine_state, stack, &file, &path, input) {
} else if !eval_source(engine_state, stack, &file, file_path_str, input) {
std::process::exit(1);
}

View File

@ -42,20 +42,14 @@ impl Completer for NuMenuCompleter {
if let Some(buffer) = block.signature.get_positional(0) {
if let Some(buffer_id) = &buffer.var_id {
let line_buffer = Value::String {
val: parsed.remainder.to_string(),
span: self.span,
};
let line_buffer = Value::string(parsed.remainder, self.span);
self.stack.add_var(*buffer_id, line_buffer);
}
}
if let Some(position) = block.signature.get_positional(1) {
if let Some(position_id) = &position.var_id {
let line_buffer = Value::Int {
val: pos as i64,
span: self.span,
};
let line_buffer = Value::int(pos as i64, self.span);
self.stack.add_var(*position_id, line_buffer);
}
}

View File

@ -50,14 +50,13 @@ Since this command has no output, there is no point in piping it with other comm
let args: Vec<Value> = call.rest(engine_state, stack, 0)?;
let no_newline = call.has_flag("no-newline");
let to_stderr = call.has_flag("stderr");
let head = call.head;
for arg in args {
arg.into_pipeline_data()
.print(engine_state, stack, no_newline, to_stderr)?;
}
Ok(PipelineData::new(head))
Ok(PipelineData::empty())
}
fn examples(&self) -> Vec<Example> {

View File

@ -4,7 +4,7 @@ use log::info;
use nu_engine::eval_subexpression;
use nu_protocol::{
engine::{EngineState, Stack, StateWorkingSet},
Config, PipelineData, Span, Value,
Config, PipelineData, Value,
};
use reedline::Prompt;
@ -37,12 +37,8 @@ fn get_prompt_string(
let block = engine_state.get_block(block_id);
let mut stack = stack.captures_to_stack(&captures);
// Use eval_subexpression to force a redirection of output, so we can use everything in prompt
let ret_val = eval_subexpression(
engine_state,
&mut stack,
block,
PipelineData::new(Span::new(0, 0)), // Don't try this at home, 0 span is ignored
);
let ret_val =
eval_subexpression(engine_state, &mut stack, block, PipelineData::empty());
info!(
"get_prompt_string (block) {}:{}:{}",
file!(),
@ -62,12 +58,7 @@ fn get_prompt_string(
Value::Block { val: block_id, .. } => {
let block = engine_state.get_block(block_id);
// Use eval_subexpression to force a redirection of output, so we can use everything in prompt
let ret_val = eval_subexpression(
engine_state,
stack,
block,
PipelineData::new(Span::new(0, 0)), // Don't try this at home, 0 span is ignored
);
let ret_val = eval_subexpression(engine_state, stack, block, PipelineData::empty());
info!(
"get_prompt_string (block) {}:{}:{}",
file!(),

View File

@ -1,11 +1,11 @@
use super::DescriptionMenu;
use crate::{menus::NuMenuCompleter, NuHelpCompleter};
use crossterm::event::{KeyCode, KeyModifiers};
use nu_color_config::lookup_ansi_color_style;
use nu_color_config::{color_record_to_nustyle, lookup_ansi_color_style};
use nu_engine::eval_block;
use nu_parser::parse;
use nu_protocol::{
color_value_string, create_menus,
create_menus,
engine::{EngineState, Stack, StateWorkingSet},
extract_value, Config, IntoPipelineData, ParsedKeybinding, ParsedMenu, PipelineData,
ShellError, Span, Value,
@ -159,14 +159,11 @@ macro_rules! add_style {
($name:expr, $cols: expr, $vals:expr, $span:expr, $config: expr, $menu:expr, $f:expr) => {
$menu = match extract_value($name, $cols, $vals, $span) {
Ok(text) => {
let text = match text {
Value::String { val, .. } => val.clone(),
Value::Record { cols, vals, span } => {
color_value_string(span, cols, vals, $config).into_string("", $config)
}
_ => "green".to_string(),
let style = match text {
Value::String { val, .. } => lookup_ansi_color_style(&val),
Value::Record { .. } => color_record_to_nustyle(&text),
_ => lookup_ansi_color_style("green"),
};
let style = lookup_ansi_color_style(&text);
$f($menu, style)
}
Err(_) => $menu,
@ -993,10 +990,7 @@ mod test {
#[test]
fn test_send_event() {
let cols = vec!["send".to_string()];
let vals = vec![Value::String {
val: "Enter".to_string(),
span: Span::test_data(),
}];
let vals = vec![Value::string("Enter", Span::test_data())];
let span = Span::test_data();
let b = EventType::try_from_columns(&cols, &vals, &span).unwrap();
@ -1016,10 +1010,7 @@ mod test {
#[test]
fn test_edit_event() {
let cols = vec!["edit".to_string()];
let vals = vec![Value::String {
val: "Clear".to_string(),
span: Span::test_data(),
}];
let vals = vec![Value::string("Clear", Span::test_data())];
let span = Span::test_data();
let b = EventType::try_from_columns(&cols, &vals, &span).unwrap();
@ -1043,14 +1034,8 @@ mod test {
fn test_send_menu() {
let cols = vec!["send".to_string(), "name".to_string()];
let vals = vec![
Value::String {
val: "Menu".to_string(),
span: Span::test_data(),
},
Value::String {
val: "history_menu".to_string(),
span: Span::test_data(),
},
Value::string("Menu", Span::test_data()),
Value::string("history_menu", Span::test_data()),
];
let span = Span::test_data();
@ -1076,14 +1061,8 @@ mod test {
// Menu event
let cols = vec!["send".to_string(), "name".to_string()];
let vals = vec![
Value::String {
val: "Menu".to_string(),
span: Span::test_data(),
},
Value::String {
val: "history_menu".to_string(),
span: Span::test_data(),
},
Value::string("Menu", Span::test_data()),
Value::string("history_menu", Span::test_data()),
];
let menu_event = Value::Record {
@ -1094,10 +1073,7 @@ mod test {
// Enter event
let cols = vec!["send".to_string()];
let vals = vec![Value::String {
val: "Enter".to_string(),
span: Span::test_data(),
}];
let vals = vec![Value::string("Enter", Span::test_data())];
let enter_event = Value::Record {
cols,
@ -1138,14 +1114,8 @@ mod test {
// Menu event
let cols = vec!["send".to_string(), "name".to_string()];
let vals = vec![
Value::String {
val: "Menu".to_string(),
span: Span::test_data(),
},
Value::String {
val: "history_menu".to_string(),
span: Span::test_data(),
},
Value::string("Menu", Span::test_data()),
Value::string("history_menu", Span::test_data()),
];
let menu_event = Value::Record {
@ -1156,10 +1126,7 @@ mod test {
// Enter event
let cols = vec!["send".to_string()];
let vals = vec![Value::String {
val: "Enter".to_string(),
span: Span::test_data(),
}];
let vals = vec![Value::string("Enter", Span::test_data())];
let enter_event = Value::Record {
cols,
@ -1187,10 +1154,7 @@ mod test {
#[test]
fn test_error() {
let cols = vec!["not_exist".to_string()];
let vals = vec![Value::String {
val: "Enter".to_string(),
span: Span::test_data(),
}];
let vals = vec![Value::string("Enter", Span::test_data())];
let span = Span::test_data();
let b = EventType::try_from_columns(&cols, &vals, &span);

View File

@ -5,11 +5,9 @@ use crate::{
util::{eval_source, get_guaranteed_cwd, report_error, report_error_new},
NuHighlighter, NuValidator, NushellPrompt,
};
use fancy_regex::Regex;
use lazy_static::lazy_static;
use log::{info, trace, warn};
use miette::{IntoDiagnostic, Result};
use nu_color_config::get_color_config;
use nu_color_config::StyleComputer;
use nu_engine::{convert_env_values, eval_block, eval_block_with_early_return};
use nu_parser::{lex, parse, trim_quotes_str};
use nu_protocol::{
@ -74,19 +72,10 @@ pub fn evaluate_repl(
// seed env vars
stack.add_env_var(
"CMD_DURATION_MS".into(),
Value::String {
val: "0823".to_string(),
span: Span { start: 0, end: 0 },
},
Value::string("0823", Span::unknown()),
);
stack.add_env_var(
"LAST_EXIT_CODE".into(),
Value::Int {
val: 0,
span: Span { start: 0, end: 0 },
},
);
stack.add_env_var("LAST_EXIT_CODE".into(), Value::int(0, Span::unknown()));
info!(
"load config initially {}:{}:{}",
@ -149,7 +138,7 @@ pub fn evaluate_repl(
stack,
s.item.as_bytes(),
&format!("entry #{}", entry_num),
PipelineData::new(Span::new(0, 0)),
PipelineData::empty(),
);
engine_state.merge_env(stack, get_guaranteed_cwd(engine_state, stack))?;
}
@ -183,8 +172,6 @@ pub fn evaluate_repl(
info!("setup colors {}:{}:{}", file!(), line!(), column!());
let color_hm = get_color_config(config);
info!("update reedline {}:{}:{}", file!(), line!(), column!());
let engine_reference = std::sync::Arc::new(engine_state.clone());
line_editor = line_editor
@ -203,10 +190,14 @@ pub fn evaluate_repl(
.with_partial_completions(config.partial_completions)
.with_ansi_colors(config.use_ansi_coloring);
let style_computer = StyleComputer::from_config(engine_state, stack);
line_editor = if config.use_ansi_coloring {
line_editor.with_hinter(Box::new(
DefaultHinter::default().with_style(color_hm["hints"]),
))
line_editor.with_hinter(Box::new({
// As of Nov 2022, "hints" color_config closures only get `null` passed in.
let style = style_computer.compute("hints", &Value::nothing(Span::unknown()));
DefaultHinter::default().with_style(style)
}))
} else {
line_editor.disable_hints()
};
@ -375,7 +366,7 @@ pub fn evaluate_repl(
"OLDPWD".into(),
Value::String {
val: cwd.clone(),
span: Span { start: 0, end: 0 },
span: Span::unknown(),
},
);
@ -385,7 +376,7 @@ pub fn evaluate_repl(
"PWD".into(),
Value::String {
val: path.clone(),
span: Span { start: 0, end: 0 },
span: Span::unknown(),
},
);
let cwd = Value::String { val: cwd, span };
@ -431,7 +422,7 @@ pub fn evaluate_repl(
stack,
s.as_bytes(),
&format!("entry #{}", entry_num),
PipelineData::new(Span::new(0, 0)),
PipelineData::empty(),
);
}
let cmd_duration = start_time.elapsed();
@ -440,7 +431,7 @@ pub fn evaluate_repl(
"CMD_DURATION_MS".into(),
Value::String {
val: format!("{}", cmd_duration.as_millis()),
span: Span { start: 0, end: 0 },
span: Span::unknown(),
},
);
@ -637,7 +628,7 @@ pub fn eval_string_with_input(
let input_as_pipeline_data = match input {
Some(input) => PipelineData::Value(input, None),
None => PipelineData::new(Span::test_data()),
None => PipelineData::empty(),
};
eval_block(
@ -718,11 +709,18 @@ pub fn eval_hook(
) -> Result<PipelineData, ShellError> {
let value_span = value.span()?;
// Hooks can optionally be a record in this form:
// {
// condition: {|before, after| ... } # block that evaluates to true/false
// code: # block or a string
// }
// The condition block will be run to check whether the main hook (in `code`) should be run.
// If it returns true (the default if a condition block is not specified), the hook should be run.
let condition_path = PathMember::String {
val: "condition".to_string(),
span: value_span,
};
let mut output = PipelineData::new(Span::new(0, 0));
let mut output = PipelineData::empty();
let code_path = PathMember::String {
val: "code".to_string(),
@ -757,16 +755,19 @@ pub fn eval_hook(
arguments.clone(),
block_span,
) {
Ok(value) => match value {
Value::Bool { val, .. } => val,
other => {
Ok(pipeline_data) => {
if let PipelineData::Value(Value::Bool { val, .. }, ..) =
pipeline_data
{
val
} else {
return Err(ShellError::UnsupportedConfigValue(
"boolean output".to_string(),
format!("{}", other.get_type()),
other.span()?,
"other PipelineData variant".to_string(),
block_span,
));
}
},
}
Err(err) => {
return Err(err);
}
@ -823,7 +824,7 @@ pub fn eval_hook(
};
engine_state.merge_delta(delta)?;
let input = PipelineData::new(value_span);
let input = PipelineData::empty();
let var_ids: Vec<VarId> = vars
.into_iter()
@ -889,34 +890,28 @@ pub fn eval_hook(
span: block_span,
..
} => {
output = PipelineData::Value(
run_hook_block(
engine_state,
stack,
*block_id,
input,
arguments,
*block_span,
)?,
None,
);
output = run_hook_block(
engine_state,
stack,
*block_id,
input,
arguments,
*block_span,
)?;
}
Value::Closure {
val: block_id,
span: block_span,
..
} => {
output = PipelineData::Value(
run_hook_block(
engine_state,
stack,
*block_id,
input,
arguments,
*block_span,
)?,
None,
);
output = run_hook_block(
engine_state,
stack,
*block_id,
input,
arguments,
*block_span,
)?;
}
other => {
return Err(ShellError::UnsupportedConfigValue(
@ -933,17 +928,17 @@ pub fn eval_hook(
Ok(output)
}
pub fn run_hook_block(
fn run_hook_block(
engine_state: &EngineState,
stack: &mut Stack,
block_id: BlockId,
optional_input: Option<PipelineData>,
arguments: Vec<(String, Value)>,
span: Span,
) -> Result<Value, ShellError> {
) -> Result<PipelineData, ShellError> {
let block = engine_state.get_block(block_id);
let input = optional_input.unwrap_or_else(|| PipelineData::new(span));
let input = optional_input.unwrap_or_else(PipelineData::empty);
let mut callee_stack = stack.gather_captures(&block.captures);
@ -964,28 +959,28 @@ pub fn run_hook_block(
match eval_block_with_early_return(engine_state, &mut callee_stack, block, input, false, false)
{
Ok(pipeline_data) => match pipeline_data.into_value(span) {
Value::Error { error } => Err(error),
val => {
// If all went fine, preserve the environment of the called block
let caller_env_vars = stack.get_env_var_names(engine_state);
// remove env vars that are present in the caller but not in the callee
// (the callee hid them)
for var in caller_env_vars.iter() {
if !callee_stack.has_env_var(engine_state, var) {
stack.remove_env_var(engine_state, var);
}
}
// add new env vars from callee to caller
for (var, value) in callee_stack.get_stack_env_vars() {
stack.add_env_var(var, value);
}
Ok(val)
Ok(pipeline_data) => {
if let PipelineData::Value(Value::Error { error }, _) = pipeline_data {
return Err(error);
}
},
// If all went fine, preserve the environment of the called block
let caller_env_vars = stack.get_env_var_names(engine_state);
// remove env vars that are present in the caller but not in the callee
// (the callee hid them)
for var in caller_env_vars.iter() {
if !callee_stack.has_env_var(engine_state, var) {
stack.remove_env_var(engine_state, var);
}
}
// add new env vars from callee to caller
for (var, value) in callee_stack.get_stack_env_vars() {
stack.add_env_var(var, value);
}
Ok(pipeline_data)
}
Err(err) => Err(err),
}
}
@ -997,7 +992,7 @@ fn run_ansi_sequence(seq: &str) -> Result<(), ShellError> {
return Err(ShellError::GenericError(
"Error writing ansi sequence".into(),
err.to_string(),
Some(Span { start: 0, end: 0 }),
Some(Span::unknown()),
None,
Vec::new(),
));
@ -1007,18 +1002,19 @@ fn run_ansi_sequence(seq: &str) -> Result<(), ShellError> {
ShellError::GenericError(
"Error flushing stdio".into(),
e.to_string(),
Some(Span { start: 0, end: 0 }),
Some(Span::unknown()),
None,
Vec::new(),
)
})
}
lazy_static! {
// Absolute paths with a drive letter, like 'C:', 'D:\', 'E:\foo'
static ref DRIVE_PATH_REGEX: Regex =
Regex::new(r"^[a-zA-Z]:[/\\]?").expect("Internal error: regex creation");
}
// Absolute paths with a drive letter, like 'C:', 'D:\', 'E:\foo'
#[cfg(windows)]
static DRIVE_PATH_REGEX: once_cell::sync::Lazy<fancy_regex::Regex> =
once_cell::sync::Lazy::new(|| {
fancy_regex::Regex::new(r"^[a-zA-Z]:[/\\]?").expect("Internal error: regex creation")
});
// A best-effort "does this string look kinda like a path?" function to determine whether to auto-cd
fn looks_like_path(orig: &str) -> bool {

View File

@ -149,7 +149,7 @@ fn split_span_by_highlight_positions(
for pos in highlight_positions {
if start <= *pos && pos < &span.end {
if start < *pos {
result.push((Span { start, end: *pos }, false));
result.push((Span::new(start, *pos), false));
}
let span_str = &line[pos - global_span_offset..span.end - global_span_offset];
let end = span_str
@ -157,18 +157,12 @@ fn split_span_by_highlight_positions(
.next()
.map(|c| pos + get_char_length(c))
.unwrap_or(pos + 1);
result.push((Span { start: *pos, end }, true));
result.push((Span::new(*pos, end), true));
start = end;
}
}
if start < span.end {
result.push((
Span {
start,
end: span.end,
},
false,
));
result.push((Span::new(start, span.end), false));
}
result
}

View File

@ -250,7 +250,7 @@ pub fn eval_source(
}
}
} else {
result = pipeline_data.print(engine_state, stack, false, false);
result = pipeline_data.print(engine_state, stack, true, false);
}
match result {
@ -289,10 +289,7 @@ pub fn eval_source(
fn set_last_exit_code(stack: &mut Stack, exit_code: i64) {
stack.add_env_var(
"LAST_EXIT_CODE".to_string(),
Value::Int {
val: exit_code,
span: Span { start: 0, end: 0 },
},
Value::int(exit_code, Span::unknown()),
);
}

View File

@ -5,7 +5,7 @@ use nu_parser::parse;
use nu_protocol::engine::StateWorkingSet;
use reedline::{Completer, Suggestion};
use rstest::{fixture, rstest};
use support::{file, folder, match_suggestions, new_engine};
use support::{completions_helpers::new_quote_engine, file, folder, match_suggestions, new_engine};
#[fixture]
fn completer() -> NuCompleter {
@ -411,6 +411,24 @@ fn command_watch_with_filecompletion() {
match_suggestions(expected_paths, suggestions)
}
#[test]
fn file_completion_quoted() {
let (_, _, engine, stack) = new_quote_engine();
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack);
let target_dir = "open ";
let suggestions = completer.complete(target_dir, target_dir.len());
let expected_paths: Vec<String> = vec![
"`te st.txt`".to_string(),
"`te#st.txt`".to_string(),
"`te'st.txt`".to_string(),
];
match_suggestions(expected_paths, suggestions)
}
#[test]
fn flag_completions() {
// Create a new engine

View File

@ -33,20 +33,53 @@ pub fn new_engine() -> (PathBuf, String, EngineState, Stack) {
"PWD".to_string(),
Value::String {
val: dir_str.clone(),
span: nu_protocol::Span {
start: 0,
end: dir_str.len(),
},
span: nu_protocol::Span::new(0, dir_str.len()),
},
);
stack.add_env_var(
"TEST".to_string(),
Value::String {
val: "NUSHELL".to_string(),
span: nu_protocol::Span {
start: 0,
end: dir_str.len(),
},
span: nu_protocol::Span::new(0, dir_str.len()),
},
);
// Merge environment into the permanent state
let merge_result = engine_state.merge_env(&mut stack, &dir);
assert!(merge_result.is_ok());
(dir, dir_str, engine_state, stack)
}
pub fn new_quote_engine() -> (PathBuf, String, EngineState, Stack) {
// Target folder inside assets
let dir = fs::fixtures().join("quoted_completions");
let mut dir_str = dir
.clone()
.into_os_string()
.into_string()
.unwrap_or_default();
dir_str.push(SEP);
// Create a new engine with default context
let mut engine_state = create_default_context();
// New stack
let mut stack = Stack::new();
// Add pwd as env var
stack.add_env_var(
"PWD".to_string(),
Value::String {
val: dir_str.clone(),
span: nu_protocol::Span::new(0, dir_str.len()),
},
);
stack.add_env_var(
"TEST".to_string(),
Value::String {
val: "NUSHELL".to_string(),
span: nu_protocol::Span::new(0, dir_str.len()),
},
);
@ -112,7 +145,7 @@ pub fn merge_input(
&block,
PipelineData::Value(
Value::Nothing {
span: Span { start: 0, end: 0 },
span: Span::unknown(),
},
None
),

View File

@ -5,11 +5,18 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-color-confi
edition = "2021"
license = "MIT"
name = "nu-color-config"
version = "0.72.0"
version = "0.73.0"
[dependencies]
nu-protocol = { path = "../nu-protocol", version = "0.72.0" }
nu-ansi-term = "0.46.0"
nu-json = { path = "../nu-json", version = "0.72.0" }
nu-table = { path = "../nu-table", version = "0.72.0" }
serde = { version="1.0.123", features=["derive"] }
# used only for text_style Alignments
tabled = { version = "0.10.0", features = ["color"], default-features = false }
nu-protocol = { path = "../nu-protocol", version = "0.73.0" }
nu-ansi-term = "0.46.0"
nu-utils = { path = "../nu-utils", version = "0.73.0" }
nu-engine = { path = "../nu-engine", version = "0.73.0" }
nu-json = { path="../nu-json", version = "0.73.0" }
[dev-dependencies]
nu-test-support = { path="../nu-test-support", version = "0.73.0" }

View File

@ -1,413 +1,89 @@
use crate::nu_style::{color_from_hex, color_string_to_nustyle};
use nu_ansi_term::{Color, Style};
use nu_protocol::Config;
use nu_table::{Alignment, TextStyle};
use crate::{
nu_style::{color_from_hex, lookup_style},
parse_nustyle, NuStyle,
};
use nu_ansi_term::Style;
use nu_protocol::Value;
use std::collections::HashMap;
pub fn lookup_ansi_color_style(s: &str) -> Style {
if s.starts_with('#') {
match color_from_hex(s) {
Ok(c) => match c {
Some(c) => c.normal(),
None => Style::default(),
},
Err(_) => Style::default(),
}
color_from_hex(s)
.ok()
.and_then(|c| c.map(|c| c.normal()))
.unwrap_or_default()
} else if s.starts_with('{') {
color_string_to_nustyle(s.to_string())
} else {
match s {
"g" | "green" => Color::Green.normal(),
"gb" | "green_bold" => Color::Green.bold(),
"gu" | "green_underline" => Color::Green.underline(),
"gi" | "green_italic" => Color::Green.italic(),
"gd" | "green_dimmed" => Color::Green.dimmed(),
"gr" | "green_reverse" => Color::Green.reverse(),
"gbl" | "green_blink" => Color::Green.blink(),
"gst" | "green_strike" => Color::Green.strikethrough(),
"lg" | "light_green" => Color::LightGreen.normal(),
"lgb" | "light_green_bold" => Color::LightGreen.bold(),
"lgu" | "light_green_underline" => Color::LightGreen.underline(),
"lgi" | "light_green_italic" => Color::LightGreen.italic(),
"lgd" | "light_green_dimmed" => Color::LightGreen.dimmed(),
"lgr" | "light_green_reverse" => Color::LightGreen.reverse(),
"lgbl" | "light_green_blink" => Color::LightGreen.blink(),
"lgst" | "light_green_strike" => Color::LightGreen.strikethrough(),
"r" | "red" => Color::Red.normal(),
"rb" | "red_bold" => Color::Red.bold(),
"ru" | "red_underline" => Color::Red.underline(),
"ri" | "red_italic" => Color::Red.italic(),
"rd" | "red_dimmed" => Color::Red.dimmed(),
"rr" | "red_reverse" => Color::Red.reverse(),
"rbl" | "red_blink" => Color::Red.blink(),
"rst" | "red_strike" => Color::Red.strikethrough(),
"lr" | "light_red" => Color::LightRed.normal(),
"lrb" | "light_red_bold" => Color::LightRed.bold(),
"lru" | "light_red_underline" => Color::LightRed.underline(),
"lri" | "light_red_italic" => Color::LightRed.italic(),
"lrd" | "light_red_dimmed" => Color::LightRed.dimmed(),
"lrr" | "light_red_reverse" => Color::LightRed.reverse(),
"lrbl" | "light_red_blink" => Color::LightRed.blink(),
"lrst" | "light_red_strike" => Color::LightRed.strikethrough(),
"u" | "blue" => Color::Blue.normal(),
"ub" | "blue_bold" => Color::Blue.bold(),
"uu" | "blue_underline" => Color::Blue.underline(),
"ui" | "blue_italic" => Color::Blue.italic(),
"ud" | "blue_dimmed" => Color::Blue.dimmed(),
"ur" | "blue_reverse" => Color::Blue.reverse(),
"ubl" | "blue_blink" => Color::Blue.blink(),
"ust" | "blue_strike" => Color::Blue.strikethrough(),
"lu" | "light_blue" => Color::LightBlue.normal(),
"lub" | "light_blue_bold" => Color::LightBlue.bold(),
"luu" | "light_blue_underline" => Color::LightBlue.underline(),
"lui" | "light_blue_italic" => Color::LightBlue.italic(),
"lud" | "light_blue_dimmed" => Color::LightBlue.dimmed(),
"lur" | "light_blue_reverse" => Color::LightBlue.reverse(),
"lubl" | "light_blue_blink" => Color::LightBlue.blink(),
"lust" | "light_blue_strike" => Color::LightBlue.strikethrough(),
"b" | "black" => Color::Black.normal(),
"bb" | "black_bold" => Color::Black.bold(),
"bu" | "black_underline" => Color::Black.underline(),
"bi" | "black_italic" => Color::Black.italic(),
"bd" | "black_dimmed" => Color::Black.dimmed(),
"br" | "black_reverse" => Color::Black.reverse(),
"bbl" | "black_blink" => Color::Black.blink(),
"bst" | "black_strike" => Color::Black.strikethrough(),
"ligr" | "light_gray" => Color::LightGray.normal(),
"ligrb" | "light_gray_bold" => Color::LightGray.bold(),
"ligru" | "light_gray_underline" => Color::LightGray.underline(),
"ligri" | "light_gray_italic" => Color::LightGray.italic(),
"ligrd" | "light_gray_dimmed" => Color::LightGray.dimmed(),
"ligrr" | "light_gray_reverse" => Color::LightGray.reverse(),
"ligrbl" | "light_gray_blink" => Color::LightGray.blink(),
"ligrst" | "light_gray_strike" => Color::LightGray.strikethrough(),
"y" | "yellow" => Color::Yellow.normal(),
"yb" | "yellow_bold" => Color::Yellow.bold(),
"yu" | "yellow_underline" => Color::Yellow.underline(),
"yi" | "yellow_italic" => Color::Yellow.italic(),
"yd" | "yellow_dimmed" => Color::Yellow.dimmed(),
"yr" | "yellow_reverse" => Color::Yellow.reverse(),
"ybl" | "yellow_blink" => Color::Yellow.blink(),
"yst" | "yellow_strike" => Color::Yellow.strikethrough(),
"ly" | "light_yellow" => Color::LightYellow.normal(),
"lyb" | "light_yellow_bold" => Color::LightYellow.bold(),
"lyu" | "light_yellow_underline" => Color::LightYellow.underline(),
"lyi" | "light_yellow_italic" => Color::LightYellow.italic(),
"lyd" | "light_yellow_dimmed" => Color::LightYellow.dimmed(),
"lyr" | "light_yellow_reverse" => Color::LightYellow.reverse(),
"lybl" | "light_yellow_blink" => Color::LightYellow.blink(),
"lyst" | "light_yellow_strike" => Color::LightYellow.strikethrough(),
"p" | "purple" => Color::Purple.normal(),
"pb" | "purple_bold" => Color::Purple.bold(),
"pu" | "purple_underline" => Color::Purple.underline(),
"pi" | "purple_italic" => Color::Purple.italic(),
"pd" | "purple_dimmed" => Color::Purple.dimmed(),
"pr" | "purple_reverse" => Color::Purple.reverse(),
"pbl" | "purple_blink" => Color::Purple.blink(),
"pst" | "purple_strike" => Color::Purple.strikethrough(),
"lp" | "light_purple" => Color::LightPurple.normal(),
"lpb" | "light_purple_bold" => Color::LightPurple.bold(),
"lpu" | "light_purple_underline" => Color::LightPurple.underline(),
"lpi" | "light_purple_italic" => Color::LightPurple.italic(),
"lpd" | "light_purple_dimmed" => Color::LightPurple.dimmed(),
"lpr" | "light_purple_reverse" => Color::LightPurple.reverse(),
"lpbl" | "light_purple_blink" => Color::LightPurple.blink(),
"lpst" | "light_purple_strike" => Color::LightPurple.strikethrough(),
"c" | "cyan" => Color::Cyan.normal(),
"cb" | "cyan_bold" => Color::Cyan.bold(),
"cu" | "cyan_underline" => Color::Cyan.underline(),
"ci" | "cyan_italic" => Color::Cyan.italic(),
"cd" | "cyan_dimmed" => Color::Cyan.dimmed(),
"cr" | "cyan_reverse" => Color::Cyan.reverse(),
"cbl" | "cyan_blink" => Color::Cyan.blink(),
"cst" | "cyan_strike" => Color::Cyan.strikethrough(),
"lc" | "light_cyan" => Color::LightCyan.normal(),
"lcb" | "light_cyan_bold" => Color::LightCyan.bold(),
"lcu" | "light_cyan_underline" => Color::LightCyan.underline(),
"lci" | "light_cyan_italic" => Color::LightCyan.italic(),
"lcd" | "light_cyan_dimmed" => Color::LightCyan.dimmed(),
"lcr" | "light_cyan_reverse" => Color::LightCyan.reverse(),
"lcbl" | "light_cyan_blink" => Color::LightCyan.blink(),
"lcst" | "light_cyan_strike" => Color::LightCyan.strikethrough(),
"w" | "white" => Color::White.normal(),
"wb" | "white_bold" => Color::White.bold(),
"wu" | "white_underline" => Color::White.underline(),
"wi" | "white_italic" => Color::White.italic(),
"wd" | "white_dimmed" => Color::White.dimmed(),
"wr" | "white_reverse" => Color::White.reverse(),
"wbl" | "white_blink" => Color::White.blink(),
"wst" | "white_strike" => Color::White.strikethrough(),
"dgr" | "dark_gray" => Color::DarkGray.normal(),
"dgrb" | "dark_gray_bold" => Color::DarkGray.bold(),
"dgru" | "dark_gray_underline" => Color::DarkGray.underline(),
"dgri" | "dark_gray_italic" => Color::DarkGray.italic(),
"dgrd" | "dark_gray_dimmed" => Color::DarkGray.dimmed(),
"dgrr" | "dark_gray_reverse" => Color::DarkGray.reverse(),
"dgrbl" | "dark_gray_blink" => Color::DarkGray.blink(),
"dgrst" | "dark_gray_strike" => Color::DarkGray.strikethrough(),
"def" | "default" => Color::Default.normal(),
"defb" | "default_bold" => Color::Default.bold(),
"defu" | "default_underline" => Color::Default.underline(),
"defi" | "default_italic" => Color::Default.italic(),
"defd" | "default_dimmed" => Color::Default.dimmed(),
"defr" | "default_reverse" => Color::Default.reverse(),
_ => Color::White.normal(),
}
lookup_style(s)
}
}
fn update_hashmap(key: &str, val: &str, hm: &mut HashMap<String, Style>) {
// eprintln!("key: {}, val: {}", &key, &val);
let color = lookup_ansi_color_style(val);
if let Some(v) = hm.get_mut(key) {
*v = color;
} else {
hm.insert(key.to_string(), color);
}
}
pub fn get_color_config(config: &Config) -> HashMap<String, Style> {
let config = config;
// create the hashmap
pub fn get_color_map(colors: &HashMap<String, Value>) -> HashMap<String, Style> {
let mut hm: HashMap<String, Style> = HashMap::new();
// set some defaults
// hm.insert("primitive_line".to_string(), Color::White.normal());
// hm.insert("primitive_pattern".to_string(), Color::White.normal());
// hm.insert("primitive_path".to_string(), Color::White.normal());
hm.insert("separator".to_string(), Color::White.normal());
hm.insert(
"leading_trailing_space_bg".to_string(),
Style::default().on(Color::Rgb(128, 128, 128)),
);
hm.insert("header".to_string(), Color::Green.bold());
hm.insert("empty".to_string(), Color::Blue.normal());
hm.insert("bool".to_string(), Color::White.normal());
hm.insert("int".to_string(), Color::White.normal());
hm.insert("filesize".to_string(), Color::White.normal());
hm.insert("duration".to_string(), Color::White.normal());
hm.insert("date".to_string(), Color::White.normal());
hm.insert("range".to_string(), Color::White.normal());
hm.insert("float".to_string(), Color::White.normal());
hm.insert("string".to_string(), Color::White.normal());
hm.insert("nothing".to_string(), Color::White.normal());
hm.insert("binary".to_string(), Color::White.normal());
hm.insert("cellpath".to_string(), Color::White.normal());
hm.insert("row_index".to_string(), Color::Green.bold());
hm.insert("record".to_string(), Color::White.normal());
hm.insert("list".to_string(), Color::White.normal());
hm.insert("block".to_string(), Color::White.normal());
hm.insert("hints".to_string(), Color::DarkGray.normal());
for (key, value) in &config.color_config {
match value.as_string() {
Ok(value) => update_hashmap(key, &value, &mut hm),
Err(_) => continue,
}
for (key, value) in colors {
parse_map_entry(&mut hm, key, value);
}
hm
}
// This function will assign a text style to a primitive, or really any string that's
// in the hashmap. The hashmap actually contains the style to be applied.
pub fn style_primitive(primitive: &str, color_hm: &HashMap<String, Style>) -> TextStyle {
match primitive {
"bool" => {
let style = color_hm.get(primitive);
match style {
Some(s) => TextStyle::with_style(Alignment::Left, *s),
None => TextStyle::basic_left(),
}
}
"int" => {
let style = color_hm.get(primitive);
match style {
Some(s) => TextStyle::with_style(Alignment::Right, *s),
None => TextStyle::basic_right(),
}
}
"filesize" => {
let style = color_hm.get(primitive);
match style {
Some(s) => TextStyle::with_style(Alignment::Right, *s),
None => TextStyle::basic_right(),
}
}
"duration" => {
let style = color_hm.get(primitive);
match style {
Some(s) => TextStyle::with_style(Alignment::Left, *s),
None => TextStyle::basic_left(),
}
}
"date" => {
let style = color_hm.get(primitive);
match style {
Some(s) => TextStyle::with_style(Alignment::Left, *s),
None => TextStyle::basic_left(),
}
}
"range" => {
let style = color_hm.get(primitive);
match style {
Some(s) => TextStyle::with_style(Alignment::Left, *s),
None => TextStyle::basic_left(),
}
}
"float" => {
let style = color_hm.get(primitive);
match style {
Some(s) => TextStyle::with_style(Alignment::Right, *s),
None => TextStyle::basic_right(),
}
}
"string" => {
let style = color_hm.get(primitive);
match style {
Some(s) => TextStyle::with_style(Alignment::Left, *s),
None => TextStyle::basic_left(),
}
}
"nothing" => {
let style = color_hm.get(primitive);
match style {
Some(s) => TextStyle::with_style(Alignment::Left, *s),
None => TextStyle::basic_left(),
}
}
// not sure what to do with error
// "error" => {}
"binary" => {
let style = color_hm.get(primitive);
match style {
Some(s) => TextStyle::with_style(Alignment::Left, *s),
None => TextStyle::basic_left(),
}
}
"cellpath" => {
let style = color_hm.get(primitive);
match style {
Some(s) => TextStyle::with_style(Alignment::Left, *s),
None => TextStyle::basic_left(),
}
}
"row_index" => {
let style = color_hm.get(primitive);
match style {
Some(s) => TextStyle::with_style(Alignment::Right, *s),
None => TextStyle::new()
.alignment(Alignment::Right)
.fg(Color::Green)
.bold(Some(true)),
}
}
"record" | "list" | "block" => {
let style = color_hm.get(primitive);
match style {
Some(s) => TextStyle::with_style(Alignment::Left, *s),
None => TextStyle::basic_left(),
}
}
// types in nushell but not in engine-q
// "Line" => {
// let style = color_hm.get("Primitive::Line");
// match style {
// Some(s) => TextStyle::with_style(Alignment::Left, *s),
// None => TextStyle::basic_left(),
// }
// }
// "GlobPattern" => {
// let style = color_hm.get("Primitive::GlobPattern");
// match style {
// Some(s) => TextStyle::with_style(Alignment::Left, *s),
// None => TextStyle::basic_left(),
// }
// }
// "FilePath" => {
// let style = color_hm.get("Primitive::FilePath");
// match style {
// Some(s) => TextStyle::with_style(Alignment::Left, *s),
// None => TextStyle::basic_left(),
// }
// }
// "BeginningOfStream" => {
// let style = color_hm.get("Primitive::BeginningOfStream");
// match style {
// Some(s) => TextStyle::with_style(Alignment::Left, *s),
// None => TextStyle::basic_left(),
// }
// }
// "EndOfStream" => {
// let style = color_hm.get("Primitive::EndOfStream");
// match style {
// Some(s) => TextStyle::with_style(Alignment::Left, *s),
// None => TextStyle::basic_left(),
// }
// }
_ => TextStyle::basic_left(),
fn parse_map_entry(hm: &mut HashMap<String, Style>, key: &str, value: &Value) {
let value = match value {
Value::String { val, .. } => Some(lookup_ansi_color_style(val)),
Value::Record { cols, vals, .. } => get_style_from_value(cols, vals).map(parse_nustyle),
_ => None,
};
if let Some(value) = value {
hm.entry(key.to_owned()).or_insert(value);
}
}
#[test]
fn test_hm() {
use nu_ansi_term::{Color, Style};
fn get_style_from_value(cols: &[String], vals: &[Value]) -> Option<NuStyle> {
let mut was_set = false;
let mut style = NuStyle::from(Style::default());
for (col, val) in cols.iter().zip(vals) {
match col.as_str() {
"bg" => {
if let Value::String { val, .. } = val {
style.bg = Some(val.clone());
was_set = true;
}
}
"fg" => {
if let Value::String { val, .. } = val {
style.fg = Some(val.clone());
was_set = true;
}
}
"attr" => {
if let Value::String { val, .. } = val {
style.attr = Some(val.clone());
was_set = true;
}
}
_ => (),
}
}
let mut hm: HashMap<String, Style> = HashMap::new();
hm.insert("primitive_int".to_string(), Color::White.normal());
hm.insert("primitive_decimal".to_string(), Color::White.normal());
hm.insert("primitive_filesize".to_string(), Color::White.normal());
hm.insert("primitive_string".to_string(), Color::White.normal());
hm.insert("primitive_line".to_string(), Color::White.normal());
hm.insert("primitive_columnpath".to_string(), Color::White.normal());
hm.insert("primitive_pattern".to_string(), Color::White.normal());
hm.insert("primitive_boolean".to_string(), Color::White.normal());
hm.insert("primitive_date".to_string(), Color::White.normal());
hm.insert("primitive_duration".to_string(), Color::White.normal());
hm.insert("primitive_range".to_string(), Color::White.normal());
hm.insert("primitive_path".to_string(), Color::White.normal());
hm.insert("primitive_binary".to_string(), Color::White.normal());
hm.insert("separator".to_string(), Color::White.normal());
hm.insert("header_align".to_string(), Color::Green.bold());
hm.insert("header".to_string(), Color::Green.bold());
hm.insert("header_style".to_string(), Style::default());
hm.insert("row_index".to_string(), Color::Green.bold());
hm.insert(
"leading_trailing_space_bg".to_string(),
Style::default().on(Color::Rgb(128, 128, 128)),
);
update_hashmap("primitive_int", "green", &mut hm);
assert_eq!(hm["primitive_int"], Color::Green.normal());
if was_set {
Some(style)
} else {
None
}
}
fn color_string_to_nustyle(color_string: String) -> Style {
// eprintln!("color_string: {}", &color_string);
if color_string.is_empty() {
return Style::default();
}
let nu_style = match nu_json::from_str::<NuStyle>(&color_string) {
Ok(s) => s,
Err(_) => return Style::default(),
};
parse_nustyle(nu_style)
}

View File

@ -2,8 +2,12 @@ mod color_config;
mod matching_brackets_style;
mod nu_style;
mod shape_color;
mod style_computer;
mod text_style;
pub use color_config::*;
pub use matching_brackets_style::*;
pub use nu_style::*;
pub use shape_color::*;
pub use style_computer::*;
pub use text_style::*;

View File

@ -1,88 +1,113 @@
use nu_ansi_term::{Color, Style};
use serde::Deserialize;
use nu_protocol::Value;
use serde::{Deserialize, Serialize};
#[derive(Deserialize, PartialEq, Eq, Debug)]
#[derive(Deserialize, Serialize, PartialEq, Eq, Debug)]
pub struct NuStyle {
pub fg: Option<String>,
pub bg: Option<String>,
pub attr: Option<String>,
}
pub fn parse_nustyle(nu_style: NuStyle) -> Style {
// get the nu_ansi_term::Color foreground color
let fg_color = match nu_style.fg {
Some(fg) => color_from_hex(&fg).unwrap_or_default(),
_ => None,
};
// get the nu_ansi_term::Color background color
let bg_color = match nu_style.bg {
Some(bg) => color_from_hex(&bg).unwrap_or_default(),
_ => None,
};
// get the attributes
let color_attr = match nu_style.attr {
Some(attr) => attr,
_ => "".to_string(),
};
// setup the attributes available in nu_ansi_term::Style
let mut bold = false;
let mut dimmed = false;
let mut italic = false;
let mut underline = false;
let mut blink = false;
let mut reverse = false;
let mut hidden = false;
let mut strikethrough = false;
// since we can combine styles like bold-italic, iterate through the chars
// and set the bools for later use in the nu_ansi_term::Style application
for ch in color_attr.to_lowercase().chars() {
match ch {
'l' => blink = true,
'b' => bold = true,
'd' => dimmed = true,
'h' => hidden = true,
'i' => italic = true,
'r' => reverse = true,
's' => strikethrough = true,
'u' => underline = true,
'n' => (),
_ => (),
impl From<Style> for NuStyle {
fn from(s: Style) -> Self {
Self {
bg: s.background.and_then(color_to_string),
fg: s.foreground.and_then(color_to_string),
attr: style_get_attr(s),
}
}
// here's where we build the nu_ansi_term::Style
Style {
foreground: fg_color,
background: bg_color,
is_blink: blink,
is_bold: bold,
is_dimmed: dimmed,
is_hidden: hidden,
is_italic: italic,
is_reverse: reverse,
is_strikethrough: strikethrough,
is_underline: underline,
}
}
pub fn color_string_to_nustyle(color_string: String) -> Style {
// eprintln!("color_string: {}", &color_string);
if color_string.chars().count() < 1 {
Style::default()
} else {
let nu_style = match nu_json::from_str::<NuStyle>(&color_string) {
Ok(s) => s,
Err(_) => NuStyle {
fg: None,
bg: None,
attr: None,
},
fn style_get_attr(s: Style) -> Option<String> {
macro_rules! check {
($attrs:expr, $b:expr, $c:expr) => {
if $b {
$attrs.push($c);
}
};
parse_nustyle(nu_style)
}
let mut attrs = String::new();
check!(attrs, s.is_blink, 'l');
check!(attrs, s.is_bold, 'b');
check!(attrs, s.is_dimmed, 'd');
check!(attrs, s.is_reverse, 'r');
check!(attrs, s.is_strikethrough, 's');
check!(attrs, s.is_underline, 'u');
if attrs.is_empty() {
None
} else {
Some(attrs)
}
}
fn color_to_string(color: Color) -> Option<String> {
match color {
Color::Black => Some(String::from("black")),
Color::DarkGray => Some(String::from("dark_gray")),
Color::Red => Some(String::from("red")),
Color::LightRed => Some(String::from("light_red")),
Color::Green => Some(String::from("green")),
Color::LightGreen => Some(String::from("light_green")),
Color::Yellow => Some(String::from("yellow")),
Color::LightYellow => Some(String::from("light_yellow")),
Color::Blue => Some(String::from("blue")),
Color::LightBlue => Some(String::from("light_blue")),
Color::Purple => Some(String::from("purple")),
Color::LightPurple => Some(String::from("light_purple")),
Color::Magenta => Some(String::from("magenta")),
Color::LightMagenta => Some(String::from("light_magenta")),
Color::Cyan => Some(String::from("cyan")),
Color::LightCyan => Some(String::from("light_cyan")),
Color::White => Some(String::from("white")),
Color::LightGray => Some(String::from("light_gray")),
Color::Default => Some(String::from("default")),
Color::Rgb(r, g, b) => Some(format!("#{:X}{:X}{:X}", r, g, b)),
Color::Fixed(_) => None,
}
}
pub fn parse_nustyle(nu_style: NuStyle) -> Style {
let mut style = Style {
foreground: nu_style.fg.and_then(|fg| lookup_color_str(&fg)),
background: nu_style.bg.and_then(|bg| lookup_color_str(&bg)),
..Default::default()
};
if let Some(attrs) = nu_style.attr {
fill_modifiers(&attrs, &mut style)
}
style
}
// Converts the color_config records, { fg, bg, attr }, into a Style.
pub fn color_record_to_nustyle(value: &Value) -> Style {
let mut fg = None;
let mut bg = None;
let mut attr = None;
let v = value.as_record();
if let Ok((cols, inner_vals)) = v {
for (k, v) in cols.iter().zip(inner_vals) {
// Because config already type-checked the color_config records, this doesn't bother giving errors
// if there are unrecognised keys or bad values.
if let Ok(v) = v.as_string() {
match k.as_str() {
"fg" => fg = Some(v),
"bg" => bg = Some(v),
"attr" => attr = Some(v),
_ => (),
}
}
}
}
parse_nustyle(NuStyle { fg, bg, attr })
}
pub fn color_from_hex(
@ -101,3 +126,471 @@ pub fn color_from_hex(
)))
}
}
pub fn lookup_style(s: &str) -> Style {
match s {
"g" | "green" => Color::Green.normal(),
"gb" | "green_bold" => Color::Green.bold(),
"gu" | "green_underline" => Color::Green.underline(),
"gi" | "green_italic" => Color::Green.italic(),
"gd" | "green_dimmed" => Color::Green.dimmed(),
"gr" | "green_reverse" => Color::Green.reverse(),
"gbl" | "green_blink" => Color::Green.blink(),
"gst" | "green_strike" => Color::Green.strikethrough(),
"lg" | "light_green" => Color::LightGreen.normal(),
"lgb" | "light_green_bold" => Color::LightGreen.bold(),
"lgu" | "light_green_underline" => Color::LightGreen.underline(),
"lgi" | "light_green_italic" => Color::LightGreen.italic(),
"lgd" | "light_green_dimmed" => Color::LightGreen.dimmed(),
"lgr" | "light_green_reverse" => Color::LightGreen.reverse(),
"lgbl" | "light_green_blink" => Color::LightGreen.blink(),
"lgst" | "light_green_strike" => Color::LightGreen.strikethrough(),
"r" | "red" => Color::Red.normal(),
"rb" | "red_bold" => Color::Red.bold(),
"ru" | "red_underline" => Color::Red.underline(),
"ri" | "red_italic" => Color::Red.italic(),
"rd" | "red_dimmed" => Color::Red.dimmed(),
"rr" | "red_reverse" => Color::Red.reverse(),
"rbl" | "red_blink" => Color::Red.blink(),
"rst" | "red_strike" => Color::Red.strikethrough(),
"lr" | "light_red" => Color::LightRed.normal(),
"lrb" | "light_red_bold" => Color::LightRed.bold(),
"lru" | "light_red_underline" => Color::LightRed.underline(),
"lri" | "light_red_italic" => Color::LightRed.italic(),
"lrd" | "light_red_dimmed" => Color::LightRed.dimmed(),
"lrr" | "light_red_reverse" => Color::LightRed.reverse(),
"lrbl" | "light_red_blink" => Color::LightRed.blink(),
"lrst" | "light_red_strike" => Color::LightRed.strikethrough(),
"u" | "blue" => Color::Blue.normal(),
"ub" | "blue_bold" => Color::Blue.bold(),
"uu" | "blue_underline" => Color::Blue.underline(),
"ui" | "blue_italic" => Color::Blue.italic(),
"ud" | "blue_dimmed" => Color::Blue.dimmed(),
"ur" | "blue_reverse" => Color::Blue.reverse(),
"ubl" | "blue_blink" => Color::Blue.blink(),
"ust" | "blue_strike" => Color::Blue.strikethrough(),
"lu" | "light_blue" => Color::LightBlue.normal(),
"lub" | "light_blue_bold" => Color::LightBlue.bold(),
"luu" | "light_blue_underline" => Color::LightBlue.underline(),
"lui" | "light_blue_italic" => Color::LightBlue.italic(),
"lud" | "light_blue_dimmed" => Color::LightBlue.dimmed(),
"lur" | "light_blue_reverse" => Color::LightBlue.reverse(),
"lubl" | "light_blue_blink" => Color::LightBlue.blink(),
"lust" | "light_blue_strike" => Color::LightBlue.strikethrough(),
"b" | "black" => Color::Black.normal(),
"bb" | "black_bold" => Color::Black.bold(),
"bu" | "black_underline" => Color::Black.underline(),
"bi" | "black_italic" => Color::Black.italic(),
"bd" | "black_dimmed" => Color::Black.dimmed(),
"br" | "black_reverse" => Color::Black.reverse(),
"bbl" | "black_blink" => Color::Black.blink(),
"bst" | "black_strike" => Color::Black.strikethrough(),
"ligr" | "light_gray" => Color::LightGray.normal(),
"ligrb" | "light_gray_bold" => Color::LightGray.bold(),
"ligru" | "light_gray_underline" => Color::LightGray.underline(),
"ligri" | "light_gray_italic" => Color::LightGray.italic(),
"ligrd" | "light_gray_dimmed" => Color::LightGray.dimmed(),
"ligrr" | "light_gray_reverse" => Color::LightGray.reverse(),
"ligrbl" | "light_gray_blink" => Color::LightGray.blink(),
"ligrst" | "light_gray_strike" => Color::LightGray.strikethrough(),
"y" | "yellow" => Color::Yellow.normal(),
"yb" | "yellow_bold" => Color::Yellow.bold(),
"yu" | "yellow_underline" => Color::Yellow.underline(),
"yi" | "yellow_italic" => Color::Yellow.italic(),
"yd" | "yellow_dimmed" => Color::Yellow.dimmed(),
"yr" | "yellow_reverse" => Color::Yellow.reverse(),
"ybl" | "yellow_blink" => Color::Yellow.blink(),
"yst" | "yellow_strike" => Color::Yellow.strikethrough(),
"ly" | "light_yellow" => Color::LightYellow.normal(),
"lyb" | "light_yellow_bold" => Color::LightYellow.bold(),
"lyu" | "light_yellow_underline" => Color::LightYellow.underline(),
"lyi" | "light_yellow_italic" => Color::LightYellow.italic(),
"lyd" | "light_yellow_dimmed" => Color::LightYellow.dimmed(),
"lyr" | "light_yellow_reverse" => Color::LightYellow.reverse(),
"lybl" | "light_yellow_blink" => Color::LightYellow.blink(),
"lyst" | "light_yellow_strike" => Color::LightYellow.strikethrough(),
"p" | "purple" => Color::Purple.normal(),
"pb" | "purple_bold" => Color::Purple.bold(),
"pu" | "purple_underline" => Color::Purple.underline(),
"pi" | "purple_italic" => Color::Purple.italic(),
"pd" | "purple_dimmed" => Color::Purple.dimmed(),
"pr" | "purple_reverse" => Color::Purple.reverse(),
"pbl" | "purple_blink" => Color::Purple.blink(),
"pst" | "purple_strike" => Color::Purple.strikethrough(),
"lp" | "light_purple" => Color::LightPurple.normal(),
"lpb" | "light_purple_bold" => Color::LightPurple.bold(),
"lpu" | "light_purple_underline" => Color::LightPurple.underline(),
"lpi" | "light_purple_italic" => Color::LightPurple.italic(),
"lpd" | "light_purple_dimmed" => Color::LightPurple.dimmed(),
"lpr" | "light_purple_reverse" => Color::LightPurple.reverse(),
"lpbl" | "light_purple_blink" => Color::LightPurple.blink(),
"lpst" | "light_purple_strike" => Color::LightPurple.strikethrough(),
"c" | "cyan" => Color::Cyan.normal(),
"cb" | "cyan_bold" => Color::Cyan.bold(),
"cu" | "cyan_underline" => Color::Cyan.underline(),
"ci" | "cyan_italic" => Color::Cyan.italic(),
"cd" | "cyan_dimmed" => Color::Cyan.dimmed(),
"cr" | "cyan_reverse" => Color::Cyan.reverse(),
"cbl" | "cyan_blink" => Color::Cyan.blink(),
"cst" | "cyan_strike" => Color::Cyan.strikethrough(),
"lc" | "light_cyan" => Color::LightCyan.normal(),
"lcb" | "light_cyan_bold" => Color::LightCyan.bold(),
"lcu" | "light_cyan_underline" => Color::LightCyan.underline(),
"lci" | "light_cyan_italic" => Color::LightCyan.italic(),
"lcd" | "light_cyan_dimmed" => Color::LightCyan.dimmed(),
"lcr" | "light_cyan_reverse" => Color::LightCyan.reverse(),
"lcbl" | "light_cyan_blink" => Color::LightCyan.blink(),
"lcst" | "light_cyan_strike" => Color::LightCyan.strikethrough(),
"w" | "white" => Color::White.normal(),
"wb" | "white_bold" => Color::White.bold(),
"wu" | "white_underline" => Color::White.underline(),
"wi" | "white_italic" => Color::White.italic(),
"wd" | "white_dimmed" => Color::White.dimmed(),
"wr" | "white_reverse" => Color::White.reverse(),
"wbl" | "white_blink" => Color::White.blink(),
"wst" | "white_strike" => Color::White.strikethrough(),
"dgr" | "dark_gray" => Color::DarkGray.normal(),
"dgrb" | "dark_gray_bold" => Color::DarkGray.bold(),
"dgru" | "dark_gray_underline" => Color::DarkGray.underline(),
"dgri" | "dark_gray_italic" => Color::DarkGray.italic(),
"dgrd" | "dark_gray_dimmed" => Color::DarkGray.dimmed(),
"dgrr" | "dark_gray_reverse" => Color::DarkGray.reverse(),
"dgrbl" | "dark_gray_blink" => Color::DarkGray.blink(),
"dgrst" | "dark_gray_strike" => Color::DarkGray.strikethrough(),
"def" | "default" => Color::Default.normal(),
"defb" | "default_bold" => Color::Default.bold(),
"defu" | "default_underline" => Color::Default.underline(),
"defi" | "default_italic" => Color::Default.italic(),
"defd" | "default_dimmed" => Color::Default.dimmed(),
"defr" | "default_reverse" => Color::Default.reverse(),
// Add xterm 256 colors adding an x prefix where the name conflicts
"xblack" | "xterm_black" => Color::Fixed(0).normal(),
"maroon" | "xterm_maroon" => Color::Fixed(1).normal(),
"xgreen" | "xterm_green" => Color::Fixed(2).normal(),
"olive" | "xterm_olive" => Color::Fixed(3).normal(),
"navy" | "xterm_navy" => Color::Fixed(4).normal(),
"xpurplea" | "xterm_purplea" => Color::Fixed(5).normal(),
"teal" | "xterm_teal" => Color::Fixed(6).normal(),
"silver" | "xterm_silver" => Color::Fixed(7).normal(),
"grey" | "xterm_grey" => Color::Fixed(8).normal(),
"xred" | "xterm_red" => Color::Fixed(9).normal(),
"lime" | "xterm_lime" => Color::Fixed(10).normal(),
"xyellow" | "xterm_yellow" => Color::Fixed(11).normal(),
"xblue" | "xterm_blue" => Color::Fixed(12).normal(),
"fuchsia" | "xterm_fuchsia" => Color::Fixed(13).normal(),
"aqua" | "xterm_aqua" => Color::Fixed(14).normal(),
"xwhite" | "xterm_white" => Color::Fixed(15).normal(),
"grey0" | "xterm_grey0" => Color::Fixed(16).normal(),
"navyblue" | "xterm_navyblue" => Color::Fixed(17).normal(),
"darkblue" | "xterm_darkblue" => Color::Fixed(18).normal(),
"blue3a" | "xterm_blue3a" => Color::Fixed(19).normal(),
"blue3b" | "xterm_blue3b" => Color::Fixed(20).normal(),
"blue1" | "xterm_blue1" => Color::Fixed(21).normal(),
"darkgreen" | "xterm_darkgreen" => Color::Fixed(22).normal(),
"deepskyblue4a" | "xterm_deepskyblue4a" => Color::Fixed(23).normal(),
"deepskyblue4b" | "xterm_deepskyblue4b" => Color::Fixed(24).normal(),
"deepskyblue4c" | "xterm_deepskyblue4c" => Color::Fixed(25).normal(),
"dodgerblue3" | "xterm_dodgerblue3" => Color::Fixed(26).normal(),
"dodgerblue2" | "xterm_dodgerblue2" => Color::Fixed(27).normal(),
"green4" | "xterm_green4" => Color::Fixed(28).normal(),
"springgreen4" | "xterm_springgreen4" => Color::Fixed(29).normal(),
"turquoise4" | "xterm_turquoise4" => Color::Fixed(30).normal(),
"deepskyblue3a" | "xterm_deepskyblue3a" => Color::Fixed(31).normal(),
"deepskyblue3b" | "xterm_deepskyblue3b" => Color::Fixed(32).normal(),
"dodgerblue1" | "xterm_dodgerblue1" => Color::Fixed(33).normal(),
"green3a" | "xterm_green3a" => Color::Fixed(34).normal(),
"springgreen3a" | "xterm_springgreen3a" => Color::Fixed(35).normal(),
"darkcyan" | "xterm_darkcyan" => Color::Fixed(36).normal(),
"lightseagreen" | "xterm_lightseagreen" => Color::Fixed(37).normal(),
"deepskyblue2" | "xterm_deepskyblue2" => Color::Fixed(38).normal(),
"deepskyblue1" | "xterm_deepskyblue1" => Color::Fixed(39).normal(),
"green3b" | "xterm_green3b" => Color::Fixed(40).normal(),
"springgreen3b" | "xterm_springgreen3b" => Color::Fixed(41).normal(),
"springgreen2a" | "xterm_springgreen2a" => Color::Fixed(42).normal(),
"cyan3" | "xterm_cyan3" => Color::Fixed(43).normal(),
"darkturquoise" | "xterm_darkturquoise" => Color::Fixed(44).normal(),
"turquoise2" | "xterm_turquoise2" => Color::Fixed(45).normal(),
"green1" | "xterm_green1" => Color::Fixed(46).normal(),
"springgreen2b" | "xterm_springgreen2b" => Color::Fixed(47).normal(),
"springgreen1" | "xterm_springgreen1" => Color::Fixed(48).normal(),
"mediumspringgreen" | "xterm_mediumspringgreen" => Color::Fixed(49).normal(),
"cyan2" | "xterm_cyan2" => Color::Fixed(50).normal(),
"cyan1" | "xterm_cyan1" => Color::Fixed(51).normal(),
"darkreda" | "xterm_darkreda" => Color::Fixed(52).normal(),
"deeppink4a" | "xterm_deeppink4a" => Color::Fixed(53).normal(),
"purple4a" | "xterm_purple4a" => Color::Fixed(54).normal(),
"purple4b" | "xterm_purple4b" => Color::Fixed(55).normal(),
"purple3" | "xterm_purple3" => Color::Fixed(56).normal(),
"blueviolet" | "xterm_blueviolet" => Color::Fixed(57).normal(),
"orange4a" | "xterm_orange4a" => Color::Fixed(58).normal(),
"grey37" | "xterm_grey37" => Color::Fixed(59).normal(),
"mediumpurple4" | "xterm_mediumpurple4" => Color::Fixed(60).normal(),
"slateblue3a" | "xterm_slateblue3a" => Color::Fixed(61).normal(),
"slateblue3b" | "xterm_slateblue3b" => Color::Fixed(62).normal(),
"royalblue1" | "xterm_royalblue1" => Color::Fixed(63).normal(),
"chartreuse4" | "xterm_chartreuse4" => Color::Fixed(64).normal(),
"darkseagreen4a" | "xterm_darkseagreen4a" => Color::Fixed(65).normal(),
"paleturquoise4" | "xterm_paleturquoise4" => Color::Fixed(66).normal(),
"steelblue" | "xterm_steelblue" => Color::Fixed(67).normal(),
"steelblue3" | "xterm_steelblue3" => Color::Fixed(68).normal(),
"cornflowerblue" | "xterm_cornflowerblue" => Color::Fixed(69).normal(),
"chartreuse3a" | "xterm_chartreuse3a" => Color::Fixed(70).normal(),
"darkseagreen4b" | "xterm_darkseagreen4b" => Color::Fixed(71).normal(),
"cadetbluea" | "xterm_cadetbluea" => Color::Fixed(72).normal(),
"cadetblueb" | "xterm_cadetblueb" => Color::Fixed(73).normal(),
"skyblue3" | "xterm_skyblue3" => Color::Fixed(74).normal(),
"steelblue1a" | "xterm_steelblue1a" => Color::Fixed(75).normal(),
"chartreuse3b" | "xterm_chartreuse3b" => Color::Fixed(76).normal(),
"palegreen3a" | "xterm_palegreen3a" => Color::Fixed(77).normal(),
"seagreen3" | "xterm_seagreen3" => Color::Fixed(78).normal(),
"aquamarine3" | "xterm_aquamarine3" => Color::Fixed(79).normal(),
"mediumturquoise" | "xterm_mediumturquoise" => Color::Fixed(80).normal(),
"steelblue1b" | "xterm_steelblue1b" => Color::Fixed(81).normal(),
"chartreuse2a" | "xterm_chartreuse2a" => Color::Fixed(82).normal(),
"seagreen2" | "xterm_seagreen2" => Color::Fixed(83).normal(),
"seagreen1a" | "xterm_seagreen1a" => Color::Fixed(84).normal(),
"seagreen1b" | "xterm_seagreen1b" => Color::Fixed(85).normal(),
"aquamarine1a" | "xterm_aquamarine1a" => Color::Fixed(86).normal(),
"darkslategray2" | "xterm_darkslategray2" => Color::Fixed(87).normal(),
"darkredb" | "xterm_darkredb" => Color::Fixed(88).normal(),
"deeppink4b" | "xterm_deeppink4b" => Color::Fixed(89).normal(),
"darkmagentaa" | "xterm_darkmagentaa" => Color::Fixed(90).normal(),
"darkmagentab" | "xterm_darkmagentab" => Color::Fixed(91).normal(),
"darkvioleta" | "xterm_darkvioleta" => Color::Fixed(92).normal(),
"xpurpleb" | "xterm_purpleb" => Color::Fixed(93).normal(),
"orange4b" | "xterm_orange4b" => Color::Fixed(94).normal(),
"lightpink4" | "xterm_lightpink4" => Color::Fixed(95).normal(),
"plum4" | "xterm_plum4" => Color::Fixed(96).normal(),
"mediumpurple3a" | "xterm_mediumpurple3a" => Color::Fixed(97).normal(),
"mediumpurple3b" | "xterm_mediumpurple3b" => Color::Fixed(98).normal(),
"slateblue1" | "xterm_slateblue1" => Color::Fixed(99).normal(),
"yellow4a" | "xterm_yellow4a" => Color::Fixed(100).normal(),
"wheat4" | "xterm_wheat4" => Color::Fixed(101).normal(),
"grey53" | "xterm_grey53" => Color::Fixed(102).normal(),
"lightslategrey" | "xterm_lightslategrey" => Color::Fixed(103).normal(),
"mediumpurple" | "xterm_mediumpurple" => Color::Fixed(104).normal(),
"lightslateblue" | "xterm_lightslateblue" => Color::Fixed(105).normal(),
"yellow4b" | "xterm_yellow4b" => Color::Fixed(106).normal(),
"darkolivegreen3a" | "xterm_darkolivegreen3a" => Color::Fixed(107).normal(),
"darkseagreen" | "xterm_darkseagreen" => Color::Fixed(108).normal(),
"lightskyblue3a" | "xterm_lightskyblue3a" => Color::Fixed(109).normal(),
"lightskyblue3b" | "xterm_lightskyblue3b" => Color::Fixed(110).normal(),
"skyblue2" | "xterm_skyblue2" => Color::Fixed(111).normal(),
"chartreuse2b" | "xterm_chartreuse2b" => Color::Fixed(112).normal(),
"darkolivegreen3b" | "xterm_darkolivegreen3b" => Color::Fixed(113).normal(),
"palegreen3b" | "xterm_palegreen3b" => Color::Fixed(114).normal(),
"darkseagreen3a" | "xterm_darkseagreen3a" => Color::Fixed(115).normal(),
"darkslategray3" | "xterm_darkslategray3" => Color::Fixed(116).normal(),
"skyblue1" | "xterm_skyblue1" => Color::Fixed(117).normal(),
"chartreuse1" | "xterm_chartreuse1" => Color::Fixed(118).normal(),
"lightgreena" | "xterm_lightgreena" => Color::Fixed(119).normal(),
"lightgreenb" | "xterm_lightgreenb" => Color::Fixed(120).normal(),
"palegreen1a" | "xterm_palegreen1a" => Color::Fixed(121).normal(),
"aquamarine1b" | "xterm_aquamarine1b" => Color::Fixed(122).normal(),
"darkslategray1" | "xterm_darkslategray1" => Color::Fixed(123).normal(),
"red3a" | "xterm_red3a" => Color::Fixed(124).normal(),
"deeppink4c" | "xterm_deeppink4c" => Color::Fixed(125).normal(),
"mediumvioletred" | "xterm_mediumvioletred" => Color::Fixed(126).normal(),
"magenta3" | "xterm_magenta3" => Color::Fixed(127).normal(),
"darkvioletb" | "xterm_darkvioletb" => Color::Fixed(128).normal(),
"purplec" | "xterm_purplec" => Color::Fixed(129).normal(),
"darkorange3a" | "xterm_darkorange3a" => Color::Fixed(130).normal(),
"indianreda" | "xterm_indianreda" => Color::Fixed(131).normal(),
"hotpink3a" | "xterm_hotpink3a" => Color::Fixed(132).normal(),
"mediumorchid3" | "xterm_mediumorchid3" => Color::Fixed(133).normal(),
"mediumorchid" | "xterm_mediumorchid" => Color::Fixed(134).normal(),
"mediumpurple2a" | "xterm_mediumpurple2a" => Color::Fixed(135).normal(),
"darkgoldenrod" | "xterm_darkgoldenrod" => Color::Fixed(136).normal(),
"lightsalmon3a" | "xterm_lightsalmon3a" => Color::Fixed(137).normal(),
"rosybrown" | "xterm_rosybrown" => Color::Fixed(138).normal(),
"grey63" | "xterm_grey63" => Color::Fixed(139).normal(),
"mediumpurple2b" | "xterm_mediumpurple2b" => Color::Fixed(140).normal(),
"mediumpurple1" | "xterm_mediumpurple1" => Color::Fixed(141).normal(),
"gold3a" | "xterm_gold3a" => Color::Fixed(142).normal(),
"darkkhaki" | "xterm_darkkhaki" => Color::Fixed(143).normal(),
"navajowhite3" | "xterm_navajowhite3" => Color::Fixed(144).normal(),
"grey69" | "xterm_grey69" => Color::Fixed(145).normal(),
"lightsteelblue3" | "xterm_lightsteelblue3" => Color::Fixed(146).normal(),
"lightsteelblue" | "xterm_lightsteelblue" => Color::Fixed(147).normal(),
"yellow3a" | "xterm_yellow3a" => Color::Fixed(148).normal(),
"darkolivegreen3c" | "xterm_darkolivegreen3c" => Color::Fixed(149).normal(),
"darkseagreen3b" | "xterm_darkseagreen3b" => Color::Fixed(150).normal(),
"darkseagreen2a" | "xterm_darkseagreen2a" => Color::Fixed(151).normal(),
"lightcyan3" | "xterm_lightcyan3" => Color::Fixed(152).normal(),
"lightskyblue1" | "xterm_lightskyblue1" => Color::Fixed(153).normal(),
"greenyellow" | "xterm_greenyellow" => Color::Fixed(154).normal(),
"darkolivegreen2" | "xterm_darkolivegreen2" => Color::Fixed(155).normal(),
"palegreen1b" | "xterm_palegreen1b" => Color::Fixed(156).normal(),
"darkseagreen2b" | "xterm_darkseagreen2b" => Color::Fixed(157).normal(),
"darkseagreen1a" | "xterm_darkseagreen1a" => Color::Fixed(158).normal(),
"paleturquoise1" | "xterm_paleturquoise1" => Color::Fixed(159).normal(),
"red3b" | "xterm_red3b" => Color::Fixed(160).normal(),
"deeppink3a" | "xterm_deeppink3a" => Color::Fixed(161).normal(),
"deeppink3b" | "xterm_deeppink3b" => Color::Fixed(162).normal(),
"magenta3a" | "xterm_magenta3a" => Color::Fixed(163).normal(),
"magenta3b" | "xterm_magenta3b" => Color::Fixed(164).normal(),
"magenta2a" | "xterm_magenta2a" => Color::Fixed(165).normal(),
"darkorange3b" | "xterm_darkorange3b" => Color::Fixed(166).normal(),
"indianredb" | "xterm_indianredb" => Color::Fixed(167).normal(),
"hotpink3b" | "xterm_hotpink3b" => Color::Fixed(168).normal(),
"hotpink2" | "xterm_hotpink2" => Color::Fixed(169).normal(),
"orchid" | "xterm_orchid" => Color::Fixed(170).normal(),
"mediumorchid1a" | "xterm_mediumorchid1a" => Color::Fixed(171).normal(),
"orange3" | "xterm_orange3" => Color::Fixed(172).normal(),
"lightsalmon3b" | "xterm_lightsalmon3b" => Color::Fixed(173).normal(),
"lightpink3" | "xterm_lightpink3" => Color::Fixed(174).normal(),
"pink3" | "xterm_pink3" => Color::Fixed(175).normal(),
"plum3" | "xterm_plum3" => Color::Fixed(176).normal(),
"violet" | "xterm_violet" => Color::Fixed(177).normal(),
"gold3b" | "xterm_gold3b" => Color::Fixed(178).normal(),
"lightgoldenrod3" | "xterm_lightgoldenrod3" => Color::Fixed(179).normal(),
"tan" | "xterm_tan" => Color::Fixed(180).normal(),
"mistyrose3" | "xterm_mistyrose3" => Color::Fixed(181).normal(),
"thistle3" | "xterm_thistle3" => Color::Fixed(182).normal(),
"plum2" | "xterm_plum2" => Color::Fixed(183).normal(),
"yellow3b" | "xterm_yellow3b" => Color::Fixed(184).normal(),
"khaki3" | "xterm_khaki3" => Color::Fixed(185).normal(),
"lightgoldenrod2" | "xterm_lightgoldenrod2" => Color::Fixed(186).normal(),
"lightyellow3" | "xterm_lightyellow3" => Color::Fixed(187).normal(),
"grey84" | "xterm_grey84" => Color::Fixed(188).normal(),
"lightsteelblue1" | "xterm_lightsteelblue1" => Color::Fixed(189).normal(),
"yellow2" | "xterm_yellow2" => Color::Fixed(190).normal(),
"darkolivegreen1a" | "xterm_darkolivegreen1a" => Color::Fixed(191).normal(),
"darkolivegreen1b" | "xterm_darkolivegreen1b" => Color::Fixed(192).normal(),
"darkseagreen1b" | "xterm_darkseagreen1b" => Color::Fixed(193).normal(),
"honeydew2" | "xterm_honeydew2" => Color::Fixed(194).normal(),
"lightcyan1" | "xterm_lightcyan1" => Color::Fixed(195).normal(),
"red1" | "xterm_red1" => Color::Fixed(196).normal(),
"deeppink2" | "xterm_deeppink2" => Color::Fixed(197).normal(),
"deeppink1a" | "xterm_deeppink1a" => Color::Fixed(198).normal(),
"deeppink1b" | "xterm_deeppink1b" => Color::Fixed(199).normal(),
"magenta2b" | "xterm_magenta2b" => Color::Fixed(200).normal(),
"magenta1" | "xterm_magenta1" => Color::Fixed(201).normal(),
"orangered1" | "xterm_orangered1" => Color::Fixed(202).normal(),
"indianred1a" | "xterm_indianred1a" => Color::Fixed(203).normal(),
"indianred1b" | "xterm_indianred1b" => Color::Fixed(204).normal(),
"hotpinka" | "xterm_hotpinka" => Color::Fixed(205).normal(),
"hotpinkb" | "xterm_hotpinkb" => Color::Fixed(206).normal(),
"mediumorchid1b" | "xterm_mediumorchid1b" => Color::Fixed(207).normal(),
"darkorange" | "xterm_darkorange" => Color::Fixed(208).normal(),
"salmon1" | "xterm_salmon1" => Color::Fixed(209).normal(),
"lightcoral" | "xterm_lightcoral" => Color::Fixed(210).normal(),
"palevioletred1" | "xterm_palevioletred1" => Color::Fixed(211).normal(),
"orchid2" | "xterm_orchid2" => Color::Fixed(212).normal(),
"orchid1" | "xterm_orchid1" => Color::Fixed(213).normal(),
"orange1" | "xterm_orange1" => Color::Fixed(214).normal(),
"sandybrown" | "xterm_sandybrown" => Color::Fixed(215).normal(),
"lightsalmon1" | "xterm_lightsalmon1" => Color::Fixed(216).normal(),
"lightpink1" | "xterm_lightpink1" => Color::Fixed(217).normal(),
"pink1" | "xterm_pink1" => Color::Fixed(218).normal(),
"plum1" | "xterm_plum1" => Color::Fixed(219).normal(),
"gold1" | "xterm_gold1" => Color::Fixed(220).normal(),
"lightgoldenrod2a" | "xterm_lightgoldenrod2a" => Color::Fixed(221).normal(),
"lightgoldenrod2b" | "xterm_lightgoldenrod2b" => Color::Fixed(222).normal(),
"navajowhite1" | "xterm_navajowhite1" => Color::Fixed(223).normal(),
"mistyrose1" | "xterm_mistyrose1" => Color::Fixed(224).normal(),
"thistle1" | "xterm_thistle1" => Color::Fixed(225).normal(),
"yellow1" | "xterm_yellow1" => Color::Fixed(226).normal(),
"lightgoldenrod1" | "xterm_lightgoldenrod1" => Color::Fixed(227).normal(),
"khaki1" | "xterm_khaki1" => Color::Fixed(228).normal(),
"wheat1" | "xterm_wheat1" => Color::Fixed(229).normal(),
"cornsilk1" | "xterm_cornsilk1" => Color::Fixed(230).normal(),
"grey100" | "xterm_grey100" => Color::Fixed(231).normal(),
"grey3" | "xterm_grey3" => Color::Fixed(232).normal(),
"grey7" | "xterm_grey7" => Color::Fixed(233).normal(),
"grey11" | "xterm_grey11" => Color::Fixed(234).normal(),
"grey15" | "xterm_grey15" => Color::Fixed(235).normal(),
"grey19" | "xterm_grey19" => Color::Fixed(236).normal(),
"grey23" | "xterm_grey23" => Color::Fixed(237).normal(),
"grey27" | "xterm_grey27" => Color::Fixed(238).normal(),
"grey30" | "xterm_grey30" => Color::Fixed(239).normal(),
"grey35" | "xterm_grey35" => Color::Fixed(240).normal(),
"grey39" | "xterm_grey39" => Color::Fixed(241).normal(),
"grey42" | "xterm_grey42" => Color::Fixed(242).normal(),
"grey46" | "xterm_grey46" => Color::Fixed(243).normal(),
"grey50" | "xterm_grey50" => Color::Fixed(244).normal(),
"grey54" | "xterm_grey54" => Color::Fixed(245).normal(),
"grey58" | "xterm_grey58" => Color::Fixed(246).normal(),
"grey62" | "xterm_grey62" => Color::Fixed(247).normal(),
"grey66" | "xterm_grey66" => Color::Fixed(248).normal(),
"grey70" | "xterm_grey70" => Color::Fixed(249).normal(),
"grey74" | "xterm_grey74" => Color::Fixed(250).normal(),
"grey78" | "xterm_grey78" => Color::Fixed(251).normal(),
"grey82" | "xterm_grey82" => Color::Fixed(252).normal(),
"grey85" | "xterm_grey85" => Color::Fixed(253).normal(),
"grey89" | "xterm_grey89" => Color::Fixed(254).normal(),
"grey93" | "xterm_grey93" => Color::Fixed(255).normal(),
_ => Color::White.normal(),
}
}
pub fn lookup_color(s: &str) -> Option<Color> {
let color = match s {
"g" | "green" => Color::Green,
"lg" | "light_green" => Color::LightGreen,
"r" | "red" => Color::Red,
"lr" | "light_red" => Color::LightRed,
"u" | "blue" => Color::Blue,
"lu" | "light_blue" => Color::LightBlue,
"b" | "black" => Color::Black,
"ligr" | "light_gray" => Color::LightGray,
"y" | "yellow" => Color::Yellow,
"ly" | "light_yellow" => Color::LightYellow,
"p" | "purple" => Color::Purple,
"lp" | "light_purple" => Color::LightPurple,
"c" | "cyan" => Color::Cyan,
"lc" | "light_cyan" => Color::LightCyan,
"w" | "white" => Color::White,
"dgr" | "dark_gray" => Color::DarkGray,
"def" | "default" => Color::Default,
_ => return None,
};
Some(color)
}
fn fill_modifiers(attrs: &str, style: &mut Style) {
// setup the attributes available in nu_ansi_term::Style
//
// since we can combine styles like bold-italic, iterate through the chars
// and set the bools for later use in the nu_ansi_term::Style application
for ch in attrs.to_lowercase().chars() {
match ch {
'l' => style.is_blink = true,
'b' => style.is_bold = true,
'd' => style.is_dimmed = true,
'h' => style.is_hidden = true,
'i' => style.is_italic = true,
'r' => style.is_reverse = true,
's' => style.is_strikethrough = true,
'u' => style.is_underline = true,
'n' => (),
_ => (),
}
}
}
fn lookup_color_str(s: &str) -> Option<Color> {
if s.starts_with('#') {
color_from_hex(s).ok().and_then(|c| c)
} else {
lookup_color(s)
}
}

View File

@ -9,36 +9,36 @@ pub fn get_shape_color(shape: String, conf: &Config) -> Style {
Err(_) => Style::default(),
},
None => match shape.as_ref() {
"shape_garbage" => Style::new().fg(Color::White).on(Color::Red).bold(),
"shape_and" => Style::new().fg(Color::Purple).bold(),
"shape_binary" => Style::new().fg(Color::Purple).bold(),
"shape_block" => Style::new().fg(Color::Blue).bold(),
"shape_bool" => Style::new().fg(Color::LightCyan),
"shape_int" => Style::new().fg(Color::Purple).bold(),
"shape_float" => Style::new().fg(Color::Purple).bold(),
"shape_range" => Style::new().fg(Color::Yellow).bold(),
"shape_internalcall" => Style::new().fg(Color::Cyan).bold(),
"shape_custom" => Style::new().fg(Color::Green),
"shape_datetime" => Style::new().fg(Color::Cyan).bold(),
"shape_directory" => Style::new().fg(Color::Cyan),
"shape_external" => Style::new().fg(Color::Cyan),
"shape_externalarg" => Style::new().fg(Color::Green).bold(),
"shape_filepath" => Style::new().fg(Color::Cyan),
"shape_flag" => Style::new().fg(Color::Blue).bold(),
"shape_float" => Style::new().fg(Color::Purple).bold(),
"shape_garbage" => Style::new().fg(Color::White).on(Color::Red).bold(),
"shape_globpattern" => Style::new().fg(Color::Cyan).bold(),
"shape_int" => Style::new().fg(Color::Purple).bold(),
"shape_internalcall" => Style::new().fg(Color::Cyan).bold(),
"shape_list" => Style::new().fg(Color::Cyan).bold(),
"shape_literal" => Style::new().fg(Color::Blue),
"shape_nothing" => Style::new().fg(Color::LightCyan),
"shape_operator" => Style::new().fg(Color::Yellow),
"shape_or" => Style::new().fg(Color::Purple).bold(),
"shape_pipe" => Style::new().fg(Color::Purple).bold(),
"shape_range" => Style::new().fg(Color::Yellow).bold(),
"shape_record" => Style::new().fg(Color::Cyan).bold(),
"shape_redirection" => Style::new().fg(Color::Purple).bold(),
"shape_signature" => Style::new().fg(Color::Green).bold(),
"shape_string" => Style::new().fg(Color::Green),
"shape_string_interpolation" => Style::new().fg(Color::Cyan).bold(),
"shape_datetime" => Style::new().fg(Color::Cyan).bold(),
"shape_list" => Style::new().fg(Color::Cyan).bold(),
"shape_table" => Style::new().fg(Color::Blue).bold(),
"shape_record" => Style::new().fg(Color::Cyan).bold(),
"shape_block" => Style::new().fg(Color::Blue).bold(),
"shape_filepath" => Style::new().fg(Color::Cyan),
"shape_directory" => Style::new().fg(Color::Cyan),
"shape_globpattern" => Style::new().fg(Color::Cyan).bold(),
"shape_variable" => Style::new().fg(Color::Purple),
"shape_flag" => Style::new().fg(Color::Blue).bold(),
"shape_custom" => Style::new().fg(Color::Green),
"shape_pipe" => Style::new().fg(Color::Purple).bold(),
"shape_redirection" => Style::new().fg(Color::Purple).bold(),
"shape_and" => Style::new().fg(Color::Purple).bold(),
"shape_or" => Style::new().fg(Color::Purple).bold(),
"shape_nothing" => Style::new().fg(Color::LightCyan),
_ => Style::default(),
},
}

View File

@ -0,0 +1,285 @@
use crate::{color_record_to_nustyle, lookup_ansi_color_style, TextStyle};
use nu_ansi_term::{Color, Style};
use nu_engine::eval_block;
use nu_protocol::{
engine::{EngineState, Stack, StateWorkingSet},
CliError, IntoPipelineData, Value,
};
use tabled::alignment::AlignmentHorizontal;
use std::{
collections::HashMap,
fmt::{Debug, Formatter, Result},
};
// ComputableStyle represents the valid user style types: a single color value, or a closure which
// takes an input value and produces a color value. The latter represents a value which
// is computed at use-time.
#[derive(Debug, Clone)]
pub enum ComputableStyle {
Static(Style),
Closure(Value),
}
// macro used for adding initial values to the style hashmap
macro_rules! initial {
($a:expr, $b:expr) => {
($a.to_string(), ComputableStyle::Static($b))
};
}
// An alias for the mapping used internally by StyleComputer.
pub type StyleMapping = HashMap<String, ComputableStyle>;
//
// A StyleComputer is an all-in-one way to compute styles. A nu command can
// simply create it with from_config(), and then use it with compute().
// It stores the engine state and stack needed to run closures that
// may be defined as a user style.
//
pub struct StyleComputer<'a> {
engine_state: &'a EngineState,
stack: &'a Stack,
map: StyleMapping,
}
impl<'a> StyleComputer<'a> {
// This is NOT meant to be used in most cases - please use from_config() instead.
// This only exists for testing purposes.
pub fn new(
engine_state: &'a EngineState,
stack: &'a Stack,
map: StyleMapping,
) -> StyleComputer<'a> {
StyleComputer {
engine_state,
stack,
map,
}
}
// The main method. Takes a string name which maps to a color_config style name,
// and a Nu value to pipe into any closures that may have been defined there.
pub fn compute(&self, style_name: &str, value: &Value) -> Style {
match self.map.get(style_name) {
// Static values require no computation.
Some(ComputableStyle::Static(s)) => *s,
// Closures are run here.
Some(ComputableStyle::Closure(Value::Closure {
val: block_id,
captures,
span,
})) => {
let block = self.engine_state.get_block(*block_id).clone();
// Because captures_to_stack() clones, we don't need to use with_env() here
// (contrast with_env() usage in `each` or `do`).
let mut stack = self.stack.captures_to_stack(captures);
// Support 1-argument blocks as well as 0-argument blocks.
if let Some(var) = block.signature.get_positional(0) {
if let Some(var_id) = &var.var_id {
stack.add_var(*var_id, value.clone());
}
}
// Run the block.
match eval_block(
self.engine_state,
&mut stack,
&block,
value.clone().into_pipeline_data(),
false,
false,
) {
Ok(v) => {
let value = v.into_value(*span);
// These should be the same color data forms supported by color_config.
match value {
Value::Record { .. } => color_record_to_nustyle(&value),
Value::String { val, .. } => lookup_ansi_color_style(&val),
_ => Style::default(),
}
}
// This is basically a copy of nu_cli::report_error(), but that isn't usable due to
// dependencies. While crudely spitting out a bunch of errors like this is not ideal,
// currently hook closure errors behave roughly the same.
Err(e) => {
eprintln!(
"Error: {:?}",
CliError(&e, &StateWorkingSet::new(self.engine_state))
);
Style::default()
}
}
}
// There should be no other kinds of values (due to create_map() in config.rs filtering them out)
// so this is just a fallback.
_ => Style::default(),
}
}
// Used only by the `table` command.
pub fn style_primitive(&self, value: &Value) -> TextStyle {
let s = self.compute(&value.get_type().to_string(), value);
match *value {
Value::Bool { .. } => TextStyle::with_style(AlignmentHorizontal::Left, s),
Value::Int { .. } => TextStyle::with_style(AlignmentHorizontal::Right, s),
Value::Filesize { .. } => TextStyle::with_style(AlignmentHorizontal::Right, s),
Value::Duration { .. } => TextStyle::with_style(AlignmentHorizontal::Left, s),
Value::Date { .. } => TextStyle::with_style(AlignmentHorizontal::Left, s),
Value::Range { .. } => TextStyle::with_style(AlignmentHorizontal::Left, s),
Value::Float { .. } => TextStyle::with_style(AlignmentHorizontal::Right, s),
Value::String { .. } => TextStyle::with_style(AlignmentHorizontal::Left, s),
Value::Nothing { .. } => TextStyle::with_style(AlignmentHorizontal::Left, s),
Value::Binary { .. } => TextStyle::with_style(AlignmentHorizontal::Left, s),
Value::CellPath { .. } => TextStyle::with_style(AlignmentHorizontal::Left, s),
Value::Record { .. } | Value::List { .. } | Value::Block { .. } => {
TextStyle::with_style(AlignmentHorizontal::Left, s)
}
_ => TextStyle::basic_left(),
}
}
// The main constructor.
pub fn from_config(engine_state: &'a EngineState, stack: &'a Stack) -> StyleComputer<'a> {
let config = engine_state.get_config();
// Create the hashmap
let mut map: StyleMapping = HashMap::from([
initial!("separator", Color::White.normal()),
initial!(
"leading_trailing_space_bg",
Style::default().on(Color::Rgb(128, 128, 128))
),
initial!("header", Color::White.normal()),
initial!("empty", Color::White.normal()),
initial!("bool", Color::White.normal()),
initial!("int", Color::White.normal()),
initial!("filesize", Color::White.normal()),
initial!("duration", Color::White.normal()),
initial!("date", Color::White.normal()),
initial!("range", Color::White.normal()),
initial!("float", Color::White.normal()),
initial!("string", Color::White.normal()),
initial!("nothing", Color::White.normal()),
initial!("binary", Color::White.normal()),
initial!("cellpath", Color::White.normal()),
initial!("row_index", Color::Green.bold()),
initial!("record", Color::White.normal()),
initial!("list", Color::White.normal()),
initial!("block", Color::White.normal()),
initial!("hints", Color::DarkGray.normal()),
]);
for (key, value) in &config.color_config {
match value {
Value::Closure { .. } => {
map.insert(key.to_string(), ComputableStyle::Closure(value.clone()));
}
Value::Record { .. } => {
map.insert(
key.to_string(),
ComputableStyle::Static(color_record_to_nustyle(value)),
);
}
Value::String { val, .. } => {
// update the stylemap with the found key
let color = lookup_ansi_color_style(val.as_str());
if let Some(v) = map.get_mut(key) {
*v = ComputableStyle::Static(color);
} else {
map.insert(key.to_string(), ComputableStyle::Static(color));
}
}
// This should never occur.
_ => (),
}
}
StyleComputer::new(engine_state, stack, map)
}
}
// Because EngineState doesn't have Debug (Dec 2022),
// this incomplete representation must be used.
impl<'a> Debug for StyleComputer<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
f.debug_struct("StyleComputer")
.field("map", &self.map)
.finish()
}
}
#[test]
fn test_computable_style_static() {
use nu_protocol::Span;
let style1 = Style::default().italic();
let style2 = Style::default().underline();
// Create a "dummy" style_computer for this test.
let dummy_engine_state = EngineState::new();
let mut dummy_stack = Stack::new();
let style_computer = StyleComputer::new(
&dummy_engine_state,
&mut dummy_stack,
HashMap::from([
("string".into(), ComputableStyle::Static(style1)),
("row_index".into(), ComputableStyle::Static(style2)),
]),
);
assert_eq!(
style_computer.compute("string", &Value::nothing(Span::unknown())),
style1
);
assert_eq!(
style_computer.compute("row_index", &Value::nothing(Span::unknown())),
style2
);
}
// Because each closure currently runs in a separate environment, checks that the closures have run
// must use the filesystem.
#[test]
fn test_computable_style_closure_basic() {
use nu_test_support::{nu, nu_repl_code, playground::Playground};
Playground::setup("computable_style_closure_basic", |dirs, _| {
let inp = [
r#"let-env config = {
color_config: {
string: {|e| touch ($e + '.obj'); 'red' }
}
};"#,
"[bell book candle] | table | ignore",
"ls | get name | to nuon",
];
let actual_repl = nu!(cwd: dirs.test(), nu_repl_code(&inp));
assert_eq!(actual_repl.err, "");
assert_eq!(actual_repl.out, "[bell.obj, book.obj, candle.obj]");
});
}
#[test]
fn test_computable_style_closure_errors() {
use nu_test_support::{nu, nu_repl_code};
let inp = [
r#"let-env config = {
color_config: {
string: {|e| $e + 2 }
}
};"#,
"[bell] | table",
];
let actual_repl = nu!(cwd: ".", nu_repl_code(&inp));
// Check that the error was printed
assert!(actual_repl.err.contains("type mismatch for operator"));
// Check that the value was printed
assert!(actual_repl.out.contains("bell"));
}

View File

@ -1,4 +1,5 @@
use nu_ansi_term::{Color, Style};
use std::fmt::Display;
pub type Alignment = tabled::alignment::AlignmentHorizontal;
@ -239,3 +240,23 @@ impl Default for TextStyle {
Self::new()
}
}
impl tabled::papergrid::Color for TextStyle {
fn fmt_prefix(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if let Some(color) = &self.color_style {
color.prefix().fmt(f)?;
}
Ok(())
}
fn fmt_suffix(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if let Some(color) = &self.color_style {
if !color.is_plain() {
f.write_str("\u{1b}[0m")?;
}
}
Ok(())
}
}

View File

@ -5,33 +5,35 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-command"
edition = "2021"
license = "MIT"
name = "nu-command"
version = "0.72.0"
version = "0.73.0"
build = "build.rs"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
nu-color-config = { path = "../nu-color-config", version = "0.72.0" }
nu-engine = { path = "../nu-engine", version = "0.72.0" }
nu-glob = { path = "../nu-glob", version = "0.72.0" }
nu-json = { path = "../nu-json", version = "0.72.0" }
nu-parser = { path = "../nu-parser", version = "0.72.0" }
nu-path = { path = "../nu-path", version = "0.72.0" }
nu-pretty-hex = { path = "../nu-pretty-hex", version = "0.72.0" }
nu-protocol = { path = "../nu-protocol", version = "0.72.0" }
nu-system = { path = "../nu-system", version = "0.72.0" }
nu-table = { path = "../nu-table", version = "0.72.0" }
nu-term-grid = { path = "../nu-term-grid", version = "0.72.0" }
nu-utils = { path = "../nu-utils", version = "0.72.0" }
nu-color-config = { path = "../nu-color-config", version = "0.73.0" }
nu-engine = { path = "../nu-engine", version = "0.73.0" }
nu-glob = { path = "../nu-glob", version = "0.73.0" }
nu-json = { path = "../nu-json", version = "0.73.0" }
nu-parser = { path = "../nu-parser", version = "0.73.0" }
nu-path = { path = "../nu-path", version = "0.73.0" }
nu-pretty-hex = { path = "../nu-pretty-hex", version = "0.73.0" }
nu-protocol = { path = "../nu-protocol", version = "0.73.0" }
nu-system = { path = "../nu-system", version = "0.73.0" }
nu-table = { path = "../nu-table", version = "0.73.0" }
nu-term-grid = { path = "../nu-term-grid", version = "0.73.0" }
nu-utils = { path = "../nu-utils", version = "0.73.0" }
nu-explore = { path = "../nu-explore", version = "0.73.0" }
nu-ansi-term = "0.46.0"
num-format = { version = "0.4.3" }
# Potential dependencies for extras
alphanumeric-sort = "1.4.4"
atty = "0.2.14"
base64 = "0.13.0"
byteorder = "1.4.3"
bytesize = "1.1.0"
calamine = "0.18.0"
calamine = "0.19.1"
chrono = { version = "0.4.23", features = ["unstable-locales", "std"], default-features = false }
chrono-humanize = "0.2.1"
chrono-tz = "0.6.3"
@ -52,7 +54,6 @@ indexmap = { version="1.7", features=["serde-1"] }
Inflector = "0.11"
is-root = "0.1.2"
itertools = "0.10.0"
lazy_static = "1.4.0"
log = "0.4.14"
lscolors = { version = "0.12.0", features = ["crossterm"], default-features = false }
md5 = { package = "md-5", version = "0.10.0" }
@ -64,11 +65,12 @@ num-traits = "0.2.14"
once_cell = "1.0"
pathdiff = "0.2.1"
powierza-coefficient = "1.0.1"
quick-xml = "0.23.0"
quick-xml = "0.25"
rand = "0.8"
rayon = "1.5.1"
regex = "1.6.0"
reqwest = {version = "0.11", features = ["blocking", "json"] }
roxmltree = "0.14.0"
roxmltree = "0.16.0"
rust-embed = "6.3.0"
same-file = "1.0.6"
serde = { version="1.0.123", features=["derive"] }
@ -101,7 +103,7 @@ users = "0.11.0"
libc = "0.2"
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies.trash]
version = "2.1.3"
version = "3.0.0"
optional = true
[dependencies.polars]
@ -136,7 +138,7 @@ features = [
]
[target.'cfg(windows)'.dependencies.windows]
version = "0.42.0"
version = "0.43.0"
features = [
"Win32_Foundation",
"Win32_Storage_FileSystem",
@ -154,7 +156,7 @@ sqlite = ["rusqlite"] # TODO: given that rusqlite is included in reedline, shoul
shadow-rs = { version = "0.16.1", default-features = false }
[dev-dependencies]
nu-test-support = { path = "../nu-test-support", version = "0.72.0" }
nu-test-support = { path = "../nu-test-support", version = "0.73.0" }
hamcrest2 = "0.3.0"
dirs-next = "2.0.0"

View File

@ -54,10 +54,7 @@ impl Command for SubCommand {
Example {
description: "Apply bits and to two numbers",
example: "2 | bits and 2",
result: Some(Value::Int {
val: 2,
span: Span::test_data(),
}),
result: Some(Value::int(2, Span::test_data())),
},
Example {
description: "Apply logical and to a list of numbers",

View File

@ -54,10 +54,7 @@ impl Command for SubCommand {
Example {
description: "Apply bits or to two numbers",
example: "2 | bits or 6",
result: Some(Value::Int {
val: 6,
span: Span::test_data(),
}),
result: Some(Value::int(6, Span::test_data())),
},
Example {
description: "Apply logical or to a list of numbers",

View File

@ -76,10 +76,7 @@ impl Command for SubCommand {
Example {
description: "Rotate left a number with 2 bits",
example: "17 | bits rol 2",
result: Some(Value::Int {
val: 68,
span: Span::test_data(),
}),
result: Some(Value::int(68, Span::test_data())),
},
Example {
description: "Rotate left a list of numbers with 2 bits",

View File

@ -76,10 +76,7 @@ impl Command for SubCommand {
Example {
description: "Rotate right a number with 60 bits",
example: "17 | bits ror 60",
result: Some(Value::Int {
val: 272,
span: Span::test_data(),
}),
result: Some(Value::int(272, Span::test_data())),
},
Example {
description: "Rotate right a list of numbers of one byte",

View File

@ -76,26 +76,17 @@ impl Command for SubCommand {
Example {
description: "Shift left a number by 7 bits",
example: "2 | bits shl 7",
result: Some(Value::Int {
val: 256,
span: Span::test_data(),
}),
result: Some(Value::int(256, Span::test_data())),
},
Example {
description: "Shift left a number with 1 byte by 7 bits",
example: "2 | bits shl 7 -n 1",
result: Some(Value::Int {
val: 0,
span: Span::test_data(),
}),
result: Some(Value::int(0, Span::test_data())),
},
Example {
description: "Shift left a signed number by 1 bit",
example: "0x7F | bits shl 1 -s",
result: Some(Value::Int {
val: 254,
span: Span::test_data(),
}),
result: Some(Value::int(254, Span::test_data())),
},
Example {
description: "Shift left a list of numbers",

View File

@ -76,10 +76,7 @@ impl Command for SubCommand {
Example {
description: "Shift right a number with 2 bits",
example: "8 | bits shr 2",
result: Some(Value::Int {
val: 2,
span: Span::test_data(),
}),
result: Some(Value::int(2, Span::test_data())),
},
Example {
description: "Shift right a list of numbers",

View File

@ -54,10 +54,7 @@ impl Command for SubCommand {
Example {
description: "Apply bits xor to two numbers",
example: "2 | bits xor 2",
result: Some(Value::Int {
val: 0,
span: Span::test_data(),
}),
result: Some(Value::int(0, Span::test_data())),
},
Example {
description: "Apply logical xor to a list of numbers",

View File

@ -68,26 +68,17 @@ impl Command for BytesEndsWith {
Example {
description: "Checks if binary ends with `0x[AA]`",
example: "0x[1F FF AA AA] | bytes ends-with 0x[AA]",
result: Some(Value::Bool {
val: true,
span: Span::test_data(),
}),
result: Some(Value::boolean(true, Span::test_data())),
},
Example {
description: "Checks if binary ends with `0x[FF AA AA]`",
example: "0x[1F FF AA AA] | bytes ends-with 0x[FF AA AA]",
result: Some(Value::Bool {
val: true,
span: Span::test_data(),
}),
result: Some(Value::boolean(true, Span::test_data())),
},
Example {
description: "Checks if binary ends with `0x[11]`",
example: "0x[1F FF AA AA] | bytes ends-with 0x[11]",
result: Some(Value::Bool {
val: false,
span: Span::test_data(),
}),
result: Some(Value::boolean(false, Span::test_data())),
},
]
}
@ -98,10 +89,7 @@ fn ends_with(val: &Value, args: &Arguments, span: Span) -> Value {
Value::Binary {
val,
span: val_span,
} => Value::Bool {
val: val.ends_with(&args.pattern),
span: *val_span,
},
} => Value::boolean(val.ends_with(&args.pattern), *val_span),
other => Value::Error {
error: ShellError::UnsupportedInput(
format!(

View File

@ -70,10 +70,7 @@ fn length(val: &Value, _args: &CellPathOnlyArgs, span: Span) -> Value {
Value::Binary {
val,
span: val_span,
} => Value::Int {
val: val.len() as i64,
span: *val_span,
},
} => Value::int(val.len() as i64, *val_span),
other => Value::Error {
error: ShellError::UnsupportedInput(
format!(

View File

@ -74,26 +74,17 @@ impl Command for BytesStartsWith {
Example {
description: "Checks if binary starts with `0x[1F FF AA]`",
example: "0x[1F FF AA AA] | bytes starts-with 0x[1F FF AA]",
result: Some(Value::Bool {
val: true,
span: Span::test_data(),
}),
result: Some(Value::boolean(true, Span::test_data())),
},
Example {
description: "Checks if binary starts with `0x[1F]`",
example: "0x[1F FF AA AA] | bytes starts-with 0x[1F]",
result: Some(Value::Bool {
val: true,
span: Span::test_data(),
}),
result: Some(Value::boolean(true, Span::test_data())),
},
Example {
description: "Checks if binary starts with `0x[1F]`",
example: "0x[1F FF AA AA] | bytes starts-with 0x[11]",
result: Some(Value::Bool {
val: false,
span: Span::test_data(),
}),
result: Some(Value::boolean(false, Span::test_data())),
},
]
}
@ -104,10 +95,7 @@ fn starts_with(val: &Value, args: &Arguments, span: Span) -> Value {
Value::Binary {
val,
span: val_span,
} => Value::Bool {
val: val.starts_with(&args.pattern),
span: *val_span,
},
} => Value::boolean(val.starts_with(&args.pattern), *val_span),
other => Value::Error {
error: ShellError::UnsupportedInput(
format!(

View File

@ -53,7 +53,7 @@ impl Default for HashableValue {
fn default() -> Self {
HashableValue::Bool {
val: false,
span: Span { start: 0, end: 0 },
span: Span::unknown(),
}
}
}
@ -214,7 +214,7 @@ mod test {
];
for (val, expect_hashable_val) in values.into_iter() {
assert_eq!(
HashableValue::from_value(val, Span { start: 0, end: 0 }).unwrap(),
HashableValue::from_value(val, Span::unknown()).unwrap(),
expect_hashable_val
);
}
@ -245,7 +245,7 @@ mod test {
},
];
for v in values {
assert!(HashableValue::from_value(v, Span { start: 0, end: 0 }).is_err())
assert!(HashableValue::from_value(v, Span::unknown()).is_err())
}
}
@ -266,7 +266,7 @@ mod test {
for val in values.into_iter() {
let expected_val = val.clone();
assert_eq!(
HashableValue::from_value(val, Span { start: 0, end: 0 })
HashableValue::from_value(val, Span::unknown())
.unwrap()
.into_value(),
expected_val
@ -279,14 +279,11 @@ mod test {
assert_eq!(
HashableValue::Bool {
val: true,
span: Span { start: 0, end: 1 }
span: Span::new(0, 1)
},
HashableValue::Bool {
val: true,
span: Span {
start: 90,
end: 1000
}
span: Span::new(90, 1000)
}
)
}
@ -299,7 +296,7 @@ mod test {
assert!(set.contains(&HashableValue::Bool { val: true, span }));
// hashable value doesn't care about span.
let diff_span = Span { start: 1, end: 2 };
let diff_span = Span::new(1, 2);
set.insert(HashableValue::Bool {
val: true,
span: diff_span,

View File

@ -50,7 +50,7 @@ impl Command for Histogram {
},
Example {
description: "Compute a histogram for a list of numbers",
example: "echo [1 2 1] | histogram",
example: "[1 2 1] | histogram",
result: Some(Value::List {
vals: vec![Value::Record {
cols: vec!["value".to_string(), "count".to_string(), "quantile".to_string(), "percentage".to_string(), "frequency".to_string()],
@ -80,7 +80,7 @@ impl Command for Histogram {
},
Example {
description: "Compute a histogram for a list of numbers, and percentage is based on the maximum value",
example: "echo [1 2 3 1 1 1 2 2 1 1] | histogram --percentage-type relative",
example: "[1 2 3 1 1 1 2 2 1 1] | histogram --percentage-type relative",
result: None,
}
]
@ -249,25 +249,33 @@ fn histogram_impl(
let percentage = format!("{:.2}%", quantile * 100_f64);
let freq = "*".repeat((MAX_FREQ_COUNT * quantile).floor() as usize);
result.push(Value::Record {
cols: result_cols.clone(),
vals: vec![
val.into_value(),
Value::Int { val: count, span },
Value::Float {
val: quantile,
span,
},
Value::String {
val: percentage,
span,
},
Value::String { val: freq, span },
],
span,
});
result.push((
count, // attach count first for easily sorting.
Value::Record {
cols: result_cols.clone(),
vals: vec![
val.into_value(),
Value::Int { val: count, span },
Value::Float {
val: quantile,
span,
},
Value::String {
val: percentage,
span,
},
Value::String { val: freq, span },
],
span,
},
));
}
Value::List { vals: result, span }.into_pipeline_data()
result.sort_by(|a, b| b.0.cmp(&a.0));
Value::List {
vals: result.into_iter().map(|x| x.1).collect(),
span,
}
.into_pipeline_data()
}
#[cfg(test)]

View File

@ -44,38 +44,14 @@ impl Command for Fmt {
"upperhex".into(),
],
vals: vec![
Value::String {
val: "0b101010".to_string(),
span: Span::test_data(),
},
Value::String {
val: "42".to_string(),
span: Span::test_data(),
},
Value::String {
val: "42".to_string(),
span: Span::test_data(),
},
Value::String {
val: "4.2e1".to_string(),
span: Span::test_data(),
},
Value::String {
val: "0x2a".to_string(),
span: Span::test_data(),
},
Value::String {
val: "0o52".to_string(),
span: Span::test_data(),
},
Value::String {
val: "4.2E1".to_string(),
span: Span::test_data(),
},
Value::String {
val: "0x2A".to_string(),
span: Span::test_data(),
},
Value::string("0b101010", Span::test_data()),
Value::string("42", Span::test_data()),
Value::string("42", Span::test_data()),
Value::string("4.2e1", Span::test_data()),
Value::string("0x2a", Span::test_data()),
Value::string("0o52", Span::test_data()),
Value::string("4.2E1", Span::test_data()),
Value::string("0x2A", Span::test_data()),
],
span: Span::test_data(),
}),

View File

@ -54,7 +54,7 @@ impl Command for SubCommand {
vec![
Example {
description: "Convert value to boolean in table",
example: "echo [[value]; ['false'] ['1'] [0] [1.0] [true]] | into bool value",
example: "[[value]; ['false'] ['1'] [0] [1.0] [true]] | into bool value",
result: Some(Value::List {
vals: vec![
Value::Record {

View File

@ -86,7 +86,7 @@ fn action(input: &Value, _args: &CellPathOnlyArgs, head: Span) -> Value {
let other = s.trim();
match other.parse::<f64>() {
Ok(x) => Value::Float { val: x, span: head },
Ok(x) => Value::float(x, head),
Err(reason) => Value::Error {
error: ShellError::CantConvert(
"float".to_string(),
@ -97,10 +97,7 @@ fn action(input: &Value, _args: &CellPathOnlyArgs, head: Span) -> Value {
},
}
}
Value::Int { val: v, span } => Value::Float {
val: *v as f64,
span: *span,
},
Value::Int { val: v, span } => Value::float(*v as f64, *span),
Value::Bool { val: b, span } => Value::Float {
val: match b {
true => 1.0,

View File

@ -65,7 +65,8 @@ impl Command for SubCommand {
vec![
Example {
description: "Convert string to duration in table",
example: "echo [[value]; ['1sec'] ['2min'] ['3hr'] ['4day'] ['5wk']] | into duration value",
example:
"[[value]; ['1sec'] ['2min'] ['3hr'] ['4day'] ['5wk']] | into duration value",
result: Some(Value::List {
vals: vec![
Value::Record {
@ -502,7 +503,7 @@ mod test {
#[test]
fn turns_ns_to_duration() {
let span = Span::test_data();
let span = Span::new(0, 2);
let word = Value::test_string("3ns");
let expected = Value::Duration { val: 3, span };
let convert_duration = None;
@ -513,7 +514,7 @@ mod test {
#[test]
fn turns_us_to_duration() {
let span = Span::test_data();
let span = Span::new(0, 2);
let word = Value::test_string("4us");
let expected = Value::Duration {
val: 4 * 1000,
@ -527,7 +528,7 @@ mod test {
#[test]
fn turns_ms_to_duration() {
let span = Span::test_data();
let span = Span::new(0, 2);
let word = Value::test_string("5ms");
let expected = Value::Duration {
val: 5 * 1000 * 1000,
@ -541,7 +542,7 @@ mod test {
#[test]
fn turns_sec_to_duration() {
let span = Span::test_data();
let span = Span::new(0, 3);
let word = Value::test_string("1sec");
let expected = Value::Duration {
val: 1000 * 1000 * 1000,
@ -555,7 +556,7 @@ mod test {
#[test]
fn turns_min_to_duration() {
let span = Span::test_data();
let span = Span::new(0, 3);
let word = Value::test_string("7min");
let expected = Value::Duration {
val: 7 * 60 * 1000 * 1000 * 1000,
@ -569,7 +570,7 @@ mod test {
#[test]
fn turns_hr_to_duration() {
let span = Span::test_data();
let span = Span::new(0, 3);
let word = Value::test_string("42hr");
let expected = Value::Duration {
val: 42 * 60 * 60 * 1000 * 1000 * 1000,
@ -583,7 +584,7 @@ mod test {
#[test]
fn turns_day_to_duration() {
let span = Span::test_data();
let span = Span::new(0, 5);
let word = Value::test_string("123day");
let expected = Value::Duration {
val: 123 * 24 * 60 * 60 * 1000 * 1000 * 1000,
@ -597,7 +598,7 @@ mod test {
#[test]
fn turns_wk_to_duration() {
let span = Span::test_data();
let span = Span::new(0, 2);
let word = Value::test_string("3wk");
let expected = Value::Duration {
val: 3 * 7 * 24 * 60 * 60 * 1000 * 1000 * 1000,

View File

@ -92,7 +92,7 @@ impl Command for SubCommand {
vec![
Example {
description: "Convert string to integer in table",
example: "echo [[num]; ['-5'] [4] [1.5]] | into int num",
example: "[[num]; ['-5'] [4] [1.5]] | into int num",
result: None,
},
Example {
@ -113,10 +113,7 @@ impl Command for SubCommand {
Example {
description: "Convert file size to integer",
example: "4KB | into int",
result: Some(Value::Int {
val: 4000,
span: Span::test_data(),
}),
result: Some(Value::int(4000, Span::test_data())),
},
Example {
description: "Convert bool to integer",
@ -233,20 +230,14 @@ fn action(input: &Value, args: &Arguments, span: Span) -> Value {
}
val.resize(8, 0);
Value::Int {
val: LittleEndian::read_i64(&val),
span: *span,
}
Value::int(LittleEndian::read_i64(&val), *span)
} else {
while val.len() < 8 {
val.insert(0, 0);
}
val.resize(8, 0);
Value::Int {
val: BigEndian::read_i64(&val),
span: *span,
}
Value::int(BigEndian::read_i64(&val), *span)
}
}
_ => Value::Error {
@ -269,13 +260,13 @@ fn convert_int(input: &Value, head: Span, radix: u32) -> Value {
// octal
{
match int_from_string(val, head) {
Ok(x) => return Value::Int { val: x, span: head },
Ok(x) => return Value::int(x, head),
Err(e) => return Value::Error { error: e },
}
} else if val.starts_with("00") {
// It's a padded string
match i64::from_str_radix(val, radix) {
Ok(n) => return Value::Int { val: n, span: head },
Ok(n) => return Value::int(n, head),
Err(e) => {
return Value::Error {
error: ShellError::CantConvert(
@ -300,7 +291,7 @@ fn convert_int(input: &Value, head: Span, radix: u32) -> Value {
}
};
match i64::from_str_radix(i.trim(), radix) {
Ok(n) => Value::Int { val: n, span: head },
Ok(n) => Value::int(n, head),
Err(_reason) => Value::Error {
error: ShellError::CantConvert("string".to_string(), "int".to_string(), head, None),
},

View File

@ -49,7 +49,7 @@ impl Command for SubCommand {
vec![
Example {
description: "Convert from one row table to record",
example: "echo [[value]; [false]] | into record",
example: "[[value]; [false]] | into record",
result: Some(Value::Record {
cols: vec!["value".to_string()],
vals: vec![Value::boolean(false, span)],
@ -183,12 +183,12 @@ fn into_record(
Value::Record { cols, vals, span }
}
Value::Record { cols, vals, span } => Value::Record { cols, vals, span },
other => Value::Error {
error: ShellError::UnsupportedInput(
other => {
return Err(ShellError::UnsupportedInput(
"'into record' does not support this input".into(),
other.span().unwrap_or(call.head),
),
},
))
}
};
Ok(res.into_pipeline_data())
}

View File

@ -79,34 +79,22 @@ impl Command for SubCommand {
Example {
description: "convert integer to string and append three decimal places",
example: "5 | into string -d 3",
result: Some(Value::String {
val: "5.000".to_string(),
span: Span::test_data(),
}),
result: Some(Value::string("5.000", Span::test_data())),
},
Example {
description: "convert decimal to string and round to nearest integer",
example: "1.7 | into string -d 0",
result: Some(Value::String {
val: "2".to_string(),
span: Span::test_data(),
}),
result: Some(Value::string("2", Span::test_data())),
},
Example {
description: "convert decimal to string",
example: "1.7 | into string -d 1",
result: Some(Value::String {
val: "1.7".to_string(),
span: Span::test_data(),
}),
result: Some(Value::string("1.7", Span::test_data())),
},
Example {
description: "convert decimal to string and limit to 2 decimals",
example: "1.734 | into string -d 2",
result: Some(Value::String {
val: "1.73".to_string(),
span: Span::test_data(),
}),
result: Some(Value::string("1.73", Span::test_data())),
},
Example {
description: "try to convert decimal to string and provide negative decimal points",
@ -123,26 +111,17 @@ impl Command for SubCommand {
Example {
description: "convert decimal to string",
example: "4.3 | into string",
result: Some(Value::String {
val: "4.3".to_string(),
span: Span::test_data(),
}),
result: Some(Value::string("4.3", Span::test_data())),
},
Example {
description: "convert string to string",
example: "'1234' | into string",
result: Some(Value::String {
val: "1234".to_string(),
span: Span::test_data(),
}),
result: Some(Value::string("1234", Span::test_data())),
},
Example {
description: "convert boolean to string",
example: "true | into string",
result: Some(Value::String {
val: "true".to_string(),
span: Span::test_data(),
}),
result: Some(Value::string("true", Span::test_data())),
},
// TODO: This should work but does not; see https://github.com/nushell/nushell/issues/7032
// Example {

View File

@ -43,10 +43,10 @@ impl Command for Alias {
&self,
_engine_state: &EngineState,
_stack: &mut Stack,
call: &Call,
_call: &Call,
_input: PipelineData,
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
Ok(PipelineData::new(call.head))
Ok(PipelineData::empty())
}
fn examples(&self) -> Vec<Example> {

View File

@ -37,14 +37,13 @@ impl Command for Ast {
call: &Call,
_input: PipelineData,
) -> Result<PipelineData, ShellError> {
let head = call.head;
let pipeline: Spanned<String> = call.req(engine_state, stack, 0)?;
let mut working_set = StateWorkingSet::new(engine_state);
let (output, err) = parse(&mut working_set, None, pipeline.item.as_bytes(), false, &[]);
eprintln!("output: {:#?}\nerror: {:#?}", output, err);
Ok(PipelineData::new(head))
Ok(PipelineData::empty())
}
fn examples(&self) -> Vec<Example> {

View File

@ -74,7 +74,7 @@ impl Command for Debug {
},
Example {
description: "Debug print a table",
example: "echo [[version patch]; [0.1.0 false] [0.1.1 true] [0.2.0 false]] | debug",
example: "[[version patch]; [0.1.0 false] [0.1.1 true] [0.2.0 false]] | debug",
result: Some(Value::List {
vals: vec![
Value::test_string("{version: 0.1.0, patch: false}"),

View File

@ -36,10 +36,10 @@ impl Command for Def {
&self,
_engine_state: &EngineState,
_stack: &mut Stack,
call: &Call,
_call: &Call,
_input: PipelineData,
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
Ok(PipelineData::new(call.head))
Ok(PipelineData::empty())
}
fn examples(&self) -> Vec<Example> {

View File

@ -62,20 +62,17 @@ def-env cd_with_fallback [arg = ""] {
&self,
_engine_state: &EngineState,
_stack: &mut Stack,
call: &Call,
_call: &Call,
_input: PipelineData,
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
Ok(PipelineData::new(call.head))
Ok(PipelineData::empty())
}
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Set environment variable by call a custom command",
example: r#"def-env foo [] { let-env BAR = "BAZ" }; foo; $env.BAR"#,
result: Some(Value::String {
val: "BAZ".to_string(),
span: Span::test_data(),
}),
result: Some(Value::string("BAZ", Span::test_data())),
}]
}
}

View File

@ -14,7 +14,7 @@ impl Command for Do {
}
fn usage(&self) -> &str {
"Run a block"
"Run a closure, providing it with the pipeline input"
}
fn signature(&self) -> Signature {
@ -23,25 +23,25 @@ impl Command for Do {
.input_output_types(vec![(Type::Any, Type::Any)])
.switch(
"ignore-errors",
"ignore errors as the block runs",
"ignore errors as the closure runs",
Some('i'),
)
.switch(
"ignore-shell-errors",
"ignore shell errors as the block runs",
"ignore shell errors as the closure runs",
Some('s'),
)
.switch(
"ignore-program-errors",
"ignore program errors as the block runs",
"ignore external program errors as the closure runs",
Some('p'),
)
.switch(
"capture-errors",
"capture errors as the block runs and return it",
"catch errors as the closure runs, and return them",
Some('c'),
)
.rest("rest", SyntaxShape::Any, "the parameter(s) for the block")
.rest("rest", SyntaxShape::Any, "the parameter(s) for the closure")
.category(Category::Core)
}
@ -169,9 +169,9 @@ impl Command for Do {
trim_end_newline,
}),
Ok(PipelineData::Value(Value::Error { .. }, ..)) if ignore_shell_errors => {
Ok(PipelineData::new(call.head))
Ok(PipelineData::empty())
}
Err(_) if ignore_shell_errors => Ok(PipelineData::new(call.head)),
Err(_) if ignore_shell_errors => Ok(PipelineData::empty()),
r => r,
}
}
@ -179,22 +179,27 @@ impl Command for Do {
fn examples(&self) -> Vec<Example> {
vec![
Example {
description: "Run the block",
description: "Run the closure",
example: r#"do { echo hello }"#,
result: Some(Value::test_string("hello")),
},
Example {
description: "Run the block and ignore both shell and program errors",
description: "Run a stored first-class closure",
example: r#"let text = "I am enclosed"; let hello = {|| echo $text}; do $hello"#,
result: Some(Value::test_string("I am enclosed")),
},
Example {
description: "Run the closure and ignore both shell and external program errors",
example: r#"do -i { thisisnotarealcommand }"#,
result: None,
},
Example {
description: "Run the block and ignore shell errors",
description: "Run the closure and ignore shell errors",
example: r#"do -s { thisisnotarealcommand }"#,
result: None,
},
Example {
description: "Run the block and ignore program errors",
description: "Run the closure and ignore external program errors",
example: r#"do -p { nu -c 'exit 1' }; echo "I'll still run""#,
result: None,
},
@ -204,12 +209,12 @@ impl Command for Do {
result: None,
},
Example {
description: "Run the block, with a positional parameter",
description: "Run the closure, with a positional parameter",
example: r#"do {|x| 100 + $x } 77"#,
result: Some(Value::test_int(177)),
},
Example {
description: "Run the block, with input",
description: "Run the closure, with input",
example: r#"77 | do {|x| 100 + $in }"#,
result: None, // TODO: returns 177
},

View File

@ -51,13 +51,7 @@ little reason to use this over just writing the values as-is."#
std::cmp::Ordering::Equal => PipelineData::Value(to_be_echoed[0].clone(), None),
// When there are no elements, we echo the empty string
std::cmp::Ordering::Less => PipelineData::Value(
Value::String {
val: "".to_string(),
span: call.head,
},
None,
),
std::cmp::Ordering::Less => PipelineData::Value(Value::string("", call.head), None),
}
})
}

View File

@ -108,10 +108,7 @@ fn make_error(value: &Value, throw_span: Option<Span>) -> Option<ShellError> {
) => Some(ShellError::GenericError(
message,
label_text,
Some(Span {
start: start as usize,
end: end as usize,
}),
Some(Span::new(start as usize, end as usize)),
None,
Vec::new(),
)),

View File

@ -56,10 +56,7 @@ impl Command for ExportCommand {
vec![Example {
description: "Export a definition from a module",
example: r#"module utils { export def my-command [] { "hello" } }; use utils my-command; my-command"#,
result: Some(Value::String {
val: "hello".to_string(),
span: Span::test_data(),
}),
result: Some(Value::string("hello", Span::test_data())),
}]
}

View File

@ -39,10 +39,10 @@ impl Command for ExportAlias {
&self,
_engine_state: &EngineState,
_stack: &mut Stack,
call: &Call,
_call: &Call,
_input: PipelineData,
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
Ok(PipelineData::new(call.head))
Ok(PipelineData::empty())
}
fn examples(&self) -> Vec<Example> {

View File

@ -36,20 +36,17 @@ impl Command for ExportDef {
&self,
_engine_state: &EngineState,
_stack: &mut Stack,
call: &Call,
_call: &Call,
_input: PipelineData,
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
Ok(PipelineData::new(call.head))
Ok(PipelineData::empty())
}
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Define a custom command in a module and call it",
example: r#"module spam { export def foo [] { "foo" } }; use spam foo; foo"#,
result: Some(Value::String {
val: "foo".to_string(),
span: Span::test_data(),
}),
result: Some(Value::string("foo", Span::test_data())),
}]
}

View File

@ -62,20 +62,17 @@ export def-env cd_with_fallback [arg = ""] {
&self,
_engine_state: &EngineState,
_stack: &mut Stack,
call: &Call,
_call: &Call,
_input: PipelineData,
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
Ok(PipelineData::new(call.head))
Ok(PipelineData::empty())
}
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Define a custom command that participates in the environment in a module and call it",
example: r#"module foo { export def-env bar [] { let-env FOO_BAR = "BAZ" } }; use foo bar; bar; $env.FOO_BAR"#,
result: Some(Value::String {
val: "BAZ".to_string(),
span: Span::test_data(),
}),
result: Some(Value::string("BAZ", Span::test_data())),
}]
}

View File

@ -35,10 +35,10 @@ impl Command for ExportExtern {
&self,
_engine_state: &EngineState,
_stack: &mut Stack,
call: &Call,
_call: &Call,
_input: PipelineData,
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
Ok(PipelineData::new(call.head))
Ok(PipelineData::empty())
}
fn examples(&self) -> Vec<Example> {

View File

@ -34,10 +34,10 @@ impl Command for ExportUse {
&self,
_engine_state: &EngineState,
_stack: &mut Stack,
call: &Call,
_call: &Call,
_input: PipelineData,
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
Ok(PipelineData::new(call.head))
Ok(PipelineData::empty())
}
fn examples(&self) -> Vec<Example> {
@ -48,10 +48,7 @@ impl Command for ExportUse {
use eggs foo
foo
"#,
result: Some(Value::String {
val: "foo".to_string(),
span: Span::test_data(),
}),
result: Some(Value::string("foo", Span::test_data())),
}]
}

View File

@ -35,10 +35,10 @@ impl Command for Extern {
&self,
_engine_state: &EngineState,
_stack: &mut Stack,
call: &Call,
_call: &Call,
_input: PipelineData,
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
Ok(PipelineData::new(call.head))
Ok(PipelineData::empty())
}
fn examples(&self) -> Vec<Example> {

View File

@ -91,13 +91,7 @@ impl Command for For {
if numbered {
Value::Record {
cols: vec!["index".into(), "item".into()],
vals: vec![
Value::Int {
val: idx as i64,
span: head,
},
x,
],
vals: vec![Value::int(idx as i64, head), x],
span: head,
}
} else {
@ -110,7 +104,7 @@ impl Command for For {
&engine_state,
stack,
&block,
PipelineData::new(head),
PipelineData::empty(),
redirect_stdout,
redirect_stderr,
) {
@ -124,7 +118,10 @@ impl Command for For {
return Err(err);
}
Ok(pipeline) => {
pipeline.into_value(head);
let exit_code = pipeline.print(&engine_state, stack, false, false)?;
if exit_code != 0 {
break;
}
}
}
}
@ -136,13 +133,7 @@ impl Command for For {
if numbered {
Value::Record {
cols: vec!["index".into(), "item".into()],
vals: vec![
Value::Int {
val: idx as i64,
span: head,
},
x,
],
vals: vec![Value::int(idx as i64, head), x],
span: head,
}
} else {
@ -155,7 +146,7 @@ impl Command for For {
&engine_state,
stack,
&block,
PipelineData::new(head),
PipelineData::empty(),
redirect_stdout,
redirect_stderr,
) {
@ -169,7 +160,10 @@ impl Command for For {
return Err(err);
}
Ok(pipeline) => {
pipeline.into_value(head);
let exit_code = pipeline.print(&engine_state, stack, false, false)?;
if exit_code != 0 {
break;
}
}
}
}
@ -181,14 +175,14 @@ impl Command for For {
&engine_state,
stack,
&block,
PipelineData::new(head),
PipelineData::empty(),
redirect_stdout,
redirect_stderr,
)?
.into_value(head);
}
}
Ok(PipelineData::new(head))
Ok(PipelineData::empty())
}
fn examples(&self) -> Vec<Example> {

View File

@ -1,9 +1,9 @@
use fancy_regex::Regex;
use nu_ansi_term::{
Color::{Default, Red, White},
Color::{Red, White},
Style,
};
use nu_color_config::get_color_config;
use nu_color_config::StyleComputer;
use nu_engine::{get_full_help, CallExt};
use nu_protocol::{
ast::Call,
@ -86,13 +86,13 @@ fn help(
let find: Option<Spanned<String>> = call.get_flag(engine_state, stack, "find")?;
let rest: Vec<Spanned<String>> = call.rest(engine_state, stack, 0)?;
let commands = engine_state.get_decl_ids_sorted(false);
let config = engine_state.get_config();
let color_hm = get_color_config(config);
let default_style = Style::new().fg(Default).on(Default);
let string_style = match color_hm.get("string") {
Some(style) => style,
None => &default_style,
};
// 🚩The following two-lines are copied from filters/find.rs:
let style_computer = StyleComputer::from_config(engine_state, stack);
// Currently, search results all use the same style.
// Also note that this sample string is passed into user-written code (the closure that may or may not be
// defined for "string").
let string_style = style_computer.compute("string", &Value::string("search result", head));
if let Some(f) = find {
let org_search_string = f.item.clone();
@ -123,7 +123,7 @@ fn help(
cols.push("name".into());
vals.push(Value::String {
val: if key_match {
highlight_search_string(&key, &org_search_string, string_style)?
highlight_search_string(&key, &org_search_string, &string_style)?
} else {
key
},
@ -131,10 +131,7 @@ fn help(
});
cols.push("category".into());
vals.push(Value::String {
val: sig.category.to_string(),
span: head,
});
vals.push(Value::string(sig.category.to_string(), head));
cols.push("command_type".into());
vals.push(Value::String {
@ -145,7 +142,7 @@ fn help(
cols.push("usage".into());
vals.push(Value::String {
val: if usage_match {
highlight_search_string(&usage, &org_search_string, string_style)?
highlight_search_string(&usage, &org_search_string, &string_style)?
} else {
usage
},
@ -175,7 +172,7 @@ fn help(
match highlight_search_string(
term,
&org_search_string,
string_style,
&string_style,
) {
Ok(s) => s,
Err(_) => {
@ -231,10 +228,7 @@ fn help(
});
cols.push("category".into());
vals.push(Value::String {
val: sig.category.to_string(),
span: head,
});
vals.push(Value::string(sig.category.to_string(), head));
cols.push("command_type".into());
vals.push(Value::String {
@ -334,11 +328,7 @@ Get the processes on your system actively using CPU:
You can also learn more at https://www.nushell.sh/book/"#;
Ok(Value::String {
val: msg.into(),
span: head,
}
.into_pipeline_data())
Ok(Value::string(msg, head).into_pipeline_data())
}
}

View File

@ -81,6 +81,13 @@ fn generate_operator_info() -> Vec<OperatorInfo> {
description: "Adds a value to a variable.".into(),
precedence: 10,
},
OperatorInfo {
op_type: "Assignment".into(),
operator: "++=".into(),
name: "AppendAssign".into(),
description: "Appends a list or a value to a variable.".into(),
precedence: 10,
},
OperatorInfo {
op_type: "Assignment".into(),
operator: "-=".into(),
@ -284,13 +291,6 @@ fn generate_operator_info() -> Vec<OperatorInfo> {
description: "Shifts a value right by another.".into(),
precedence: 85,
},
OperatorInfo {
op_type: "Boolean".into(),
operator: "&&".into(),
name: "And".into(),
description: "Deprecated. Checks if two values are true.".into(),
precedence: 50,
},
OperatorInfo {
op_type: "Boolean".into(),
operator: "and".into(),
@ -298,13 +298,6 @@ fn generate_operator_info() -> Vec<OperatorInfo> {
description: "Checks if two values are true.".into(),
precedence: 50,
},
OperatorInfo {
op_type: "Boolean".into(),
operator: "||".into(),
name: "Or".into(),
description: "Deprecated. Checks if either value is true.".into(),
precedence: 40,
},
OperatorInfo {
op_type: "Boolean".into(),
operator: "or".into(),

View File

@ -62,7 +62,7 @@ This command is a parser keyword. For details, check:
stack.remove_env_var(engine_state, &env_var_name.item);
Ok(PipelineData::new(call.head))
Ok(PipelineData::empty())
}
fn examples(&self) -> Vec<Example> {

View File

@ -63,7 +63,7 @@ impl Command for HideEnv {
}
}
Ok(PipelineData::new(call.head))
Ok(PipelineData::empty())
}
fn examples(&self) -> Vec<Example> {

View File

@ -28,7 +28,13 @@ impl Command for If {
)
.optional(
"else_expression",
SyntaxShape::Keyword(b"else".to_vec(), Box::new(SyntaxShape::Expression)),
SyntaxShape::Keyword(
b"else".to_vec(),
Box::new(SyntaxShape::OneOf(vec![
SyntaxShape::Block,
SyntaxShape::Expression,
])),
),
"expression or block to run if check fails",
)
.category(Category::Core)
@ -102,7 +108,7 @@ impl Command for If {
.map(|res| res.0)
}
} else {
Ok(PipelineData::new(call.head))
Ok(PipelineData::empty())
}
}
x => Err(ShellError::CantConvert(

View File

@ -32,7 +32,7 @@ impl Command for Ignore {
input: PipelineData,
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
input.into_value(call.head);
Ok(PipelineData::new(call.head))
Ok(PipelineData::empty())
}
fn examples(&self) -> Vec<Example> {

View File

@ -73,7 +73,7 @@ impl Command for Let {
//println!("Adding: {:?} to {}", rhs, var_id);
stack.add_var(var_id, rhs.into_value(call.head));
Ok(PipelineData::new(call.head))
Ok(PipelineData::empty())
}
fn examples(&self) -> Vec<Example> {

View File

@ -1,5 +1,3 @@
use std::sync::atomic::Ordering;
use nu_engine::{eval_block, CallExt};
use nu_protocol::ast::Call;
use nu_protocol::engine::{Block, Command, EngineState, Stack};
@ -44,10 +42,8 @@ impl Command for Loop {
let block: Block = call.req(engine_state, stack, 0)?;
loop {
if let Some(ctrlc) = &engine_state.ctrlc {
if ctrlc.load(Ordering::SeqCst) {
break;
}
if nu_utils::ctrl_c::was_pressed(&engine_state.ctrlc) {
break;
}
let block = engine_state.get_block(block.block_id);
@ -55,7 +51,7 @@ impl Command for Loop {
engine_state,
stack,
block,
PipelineData::new(call.head),
PipelineData::empty(),
call.redirect_stdout,
call.redirect_stderr,
) {
@ -69,21 +65,21 @@ impl Command for Loop {
return Err(err);
}
Ok(pipeline) => {
pipeline.into_value(call.head);
let exit_code = pipeline.print(engine_state, stack, false, false)?;
if exit_code != 0 {
break;
}
}
}
}
Ok(PipelineData::new(call.head))
Ok(PipelineData::empty())
}
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Loop while a condition is true",
example: "mut x = 0; loop { if $x > 10 { break }; $x = $x + 1 }; $x",
result: Some(Value::Int {
val: 11,
span: Span::test_data(),
}),
result: Some(Value::int(11, Span::test_data())),
}]
}
}

View File

@ -81,19 +81,13 @@ impl Command for Metadata {
data_source: DataSource::Ls,
} => {
cols.push("source".into());
vals.push(Value::String {
val: "ls".into(),
span: head,
})
vals.push(Value::string("ls", head))
}
PipelineMetadata {
data_source: DataSource::HtmlThemes,
} => {
cols.push("source".into());
vals.push(Value::String {
val: "into html --list".into(),
span: head,
})
vals.push(Value::string("into html --list", head))
}
}
}
@ -152,19 +146,13 @@ fn build_metadata_record(arg: &Value, metadata: &Option<PipelineMetadata>, head:
data_source: DataSource::Ls,
} => {
cols.push("source".into());
vals.push(Value::String {
val: "ls".into(),
span: head,
})
vals.push(Value::string("ls", head))
}
PipelineMetadata {
data_source: DataSource::HtmlThemes,
} => {
cols.push("source".into());
vals.push(Value::String {
val: "into html --list".into(),
span: head,
})
vals.push(Value::string("into html --list", head))
}
}
}

View File

@ -35,10 +35,10 @@ impl Command for Module {
&self,
_engine_state: &EngineState,
_stack: &mut Stack,
call: &Call,
_call: &Call,
_input: PipelineData,
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
Ok(PipelineData::new(call.head))
Ok(PipelineData::empty())
}
fn examples(&self) -> Vec<Example> {
@ -46,26 +46,17 @@ impl Command for Module {
Example {
description: "Define a custom command in a module and call it",
example: r#"module spam { export def foo [] { "foo" } }; use spam foo; foo"#,
result: Some(Value::String {
val: "foo".to_string(),
span: Span::test_data(),
}),
result: Some(Value::string("foo", Span::test_data())),
},
Example {
description: "Define an environment variable in a module",
example: r#"module foo { export-env { let-env FOO = "BAZ" } }; use foo; $env.FOO"#,
result: Some(Value::String {
val: "BAZ".to_string(),
span: Span::test_data(),
}),
result: Some(Value::string("BAZ", Span::test_data())),
},
Example {
description: "Define a custom command that participates in the environment in a module and call it",
example: r#"module foo { export def-env bar [] { let-env FOO_BAR = "BAZ" } }; use foo bar; bar; $env.FOO_BAR"#,
result: Some(Value::String {
val: "BAZ".to_string(),
span: Span::test_data(),
}),
result: Some(Value::string("BAZ", Span::test_data())),
},
]
}

View File

@ -73,7 +73,7 @@ impl Command for Mut {
//println!("Adding: {:?} to {}", rhs, var_id);
stack.add_var(var_id, rhs.into_value(call.head));
Ok(PipelineData::new(call.head))
Ok(PipelineData::empty())
}
fn examples(&self) -> Vec<Example> {
@ -83,6 +83,11 @@ impl Command for Mut {
example: "mut x = 10; $x = 12",
result: None,
},
Example {
description: "Upsert a value inside a mutable data structure",
example: "mut a = {b:{c:1}}; $a.b.c = 2",
result: None,
},
Example {
description: "Set a mutable variable to the result of an expression",
example: "mut x = 10 + 100",

View File

@ -88,7 +88,7 @@ impl Command for OverlayHide {
stack.add_env_var(name, val);
}
Ok(PipelineData::new(call.head))
Ok(PipelineData::empty())
}
fn examples(&self) -> Vec<Example> {

View File

@ -50,10 +50,7 @@ impl Command for OverlayList {
example: r#"module spam { export def foo [] { "foo" } }
overlay use spam
overlay list | last"#,
result: Some(Value::String {
val: "spam".to_string(),
span: Span::test_data(),
}),
result: Some(Value::string("spam", Span::test_data())),
}]
}
}

View File

@ -49,7 +49,7 @@ This command is a parser keyword. For details, check:
stack.add_overlay(name_arg.item);
Ok(PipelineData::new(call.head))
Ok(PipelineData::empty())
}
fn examples(&self) -> Vec<Example> {

View File

@ -130,22 +130,19 @@ impl Command for OverlayUse {
if let Some(block_id) = module.env_block {
let maybe_path = find_in_dirs_env(&name_arg.item, engine_state, caller_stack)?;
let block = engine_state.get_block(block_id);
let mut callee_stack = caller_stack.gather_captures(&block.captures);
if let Some(path) = &maybe_path {
// Set the currently evaluated directory, if the argument is a valid path
let mut parent = path.clone();
parent.pop();
let file_pwd = Value::String {
val: parent.to_string_lossy().to_string(),
span: call.head,
};
let file_pwd = Value::string(parent.to_string_lossy(), call.head);
caller_stack.add_env_var("FILE_PWD".to_string(), file_pwd);
callee_stack.add_env_var("FILE_PWD".to_string(), file_pwd);
}
let block = engine_state.get_block(block_id);
let mut callee_stack = caller_stack.gather_captures(&block.captures);
let _ = eval_block(
engine_state,
&mut callee_stack,
@ -160,11 +157,6 @@ impl Command for OverlayUse {
// Merge the block's environment to the current stack
redirect_env(engine_state, caller_stack, &callee_stack);
if maybe_path.is_some() {
// Remove the file-relative PWD, if the argument is a valid path
caller_stack.remove_env_var(engine_state, "FILE_PWD");
}
} else {
caller_stack.add_overlay(overlay_name);
}
@ -172,7 +164,7 @@ impl Command for OverlayUse {
caller_stack.add_overlay(overlay_name);
}
Ok(PipelineData::new(call.head))
Ok(PipelineData::empty())
}
fn examples(&self) -> Vec<Example> {

View File

@ -49,10 +49,10 @@ impl Command for Register {
&self,
_engine_state: &EngineState,
_stack: &mut Stack,
call: &Call,
_call: &Call,
_input: PipelineData,
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
Ok(PipelineData::new(call.head))
Ok(PipelineData::empty())
}
fn examples(&self) -> Vec<Example> {

View File

@ -69,15 +69,43 @@ impl Command for Try {
engine_state,
stack,
catch_block,
PipelineData::new(call.head),
PipelineData::empty(),
false,
false,
)
} else {
Ok(PipelineData::new(call.head))
Ok(PipelineData::empty())
}
}
// external command may fail to run
Ok(pipeline) => {
let (pipeline, external_failed) = pipeline.is_external_failed();
if external_failed {
if let Some(catch_block) = catch_block {
let catch_block = engine_state.get_block(catch_block.block_id);
if let Some(var) = catch_block.signature.get_positional(0) {
if let Some(var_id) = &var.var_id {
let err_value = Value::nothing(call.head);
stack.add_var(*var_id, err_value);
}
}
eval_block(
engine_state,
stack,
catch_block,
PipelineData::empty(),
false,
false,
)
} else {
Ok(PipelineData::empty())
}
} else {
Ok(pipeline)
}
}
Ok(output) => Ok(output),
}
}

View File

@ -79,10 +79,7 @@ impl Command for Use {
// If so, set the currently evaluated directory (file-relative PWD)
if let Some(parent) = maybe_parent {
let file_pwd = Value::String {
val: parent.to_string_lossy().to_string(),
span: call.head,
};
let file_pwd = Value::string(parent.to_string_lossy(), call.head);
callee_stack.add_env_var("FILE_PWD".to_string(), file_pwd);
}
@ -112,7 +109,7 @@ impl Command for Use {
));
}
Ok(PipelineData::new(call.head))
Ok(PipelineData::empty())
}
fn examples(&self) -> Vec<Example> {
@ -120,18 +117,12 @@ impl Command for Use {
Example {
description: "Define a custom command in a module and call it",
example: r#"module spam { export def foo [] { "foo" } }; use spam foo; foo"#,
result: Some(Value::String {
val: "foo".to_string(),
span: Span::test_data(),
}),
result: Some(Value::string("foo", Span::test_data())),
},
Example {
description: "Define a custom command that participates in the environment in a module and call it",
example: r#"module foo { export def-env bar [] { let-env FOO_BAR = "BAZ" } }; use foo bar; bar; $env.FOO_BAR"#,
result: Some(Value::String {
val: "BAZ".to_string(),
span: Span::test_data(),
}),
result: Some(Value::string("BAZ", Span::test_data())),
},
]
}

View File

@ -54,97 +54,64 @@ pub fn version(
let mut vals = vec![];
cols.push("version".to_string());
vals.push(Value::String {
val: env!("CARGO_PKG_VERSION").to_string(),
span: tag,
});
vals.push(Value::string(env!("CARGO_PKG_VERSION"), tag));
cols.push("branch".to_string());
vals.push(Value::String {
val: shadow::BRANCH.to_string(),
span: call.head,
});
vals.push(Value::string(shadow::BRANCH, call.head));
let commit_hash: Option<&str> = option_env!("NU_COMMIT_HASH");
if let Some(commit_hash) = commit_hash {
cols.push("commit_hash".to_string());
vals.push(Value::String {
val: commit_hash.to_string(),
span: call.head,
});
vals.push(Value::string(commit_hash, call.head));
}
let build_os: Option<&str> = Some(shadow::BUILD_OS).filter(|x| !x.is_empty());
if let Some(build_os) = build_os {
cols.push("build_os".to_string());
vals.push(Value::String {
val: build_os.to_string(),
span: call.head,
});
vals.push(Value::string(build_os, call.head));
}
let build_target: Option<&str> = Some(shadow::BUILD_TARGET).filter(|x| !x.is_empty());
if let Some(build_target) = build_target {
cols.push("build_target".to_string());
vals.push(Value::String {
val: build_target.to_string(),
span: call.head,
});
vals.push(Value::string(build_target, call.head));
}
let rust_version: Option<&str> = Some(shadow::RUST_VERSION).filter(|x| !x.is_empty());
if let Some(rust_version) = rust_version {
cols.push("rust_version".to_string());
vals.push(Value::String {
val: rust_version.to_string(),
span: call.head,
});
vals.push(Value::string(rust_version, call.head));
}
let rust_channel: Option<&str> = Some(shadow::RUST_CHANNEL).filter(|x| !x.is_empty());
if let Some(rust_channel) = rust_channel {
cols.push("rust_channel".to_string());
vals.push(Value::String {
val: rust_channel.to_string(),
span: call.head,
});
vals.push(Value::string(rust_channel, call.head));
}
let cargo_version: Option<&str> = Some(shadow::CARGO_VERSION).filter(|x| !x.is_empty());
if let Some(cargo_version) = cargo_version {
cols.push("cargo_version".to_string());
vals.push(Value::String {
val: cargo_version.to_string(),
span: call.head,
});
vals.push(Value::string(cargo_version, call.head));
}
let pkg_version: Option<&str> = Some(shadow::PKG_VERSION).filter(|x| !x.is_empty());
if let Some(pkg_version) = pkg_version {
cols.push("pkg_version".to_string());
vals.push(Value::String {
val: pkg_version.to_string(),
span: call.head,
});
vals.push(Value::string(pkg_version, call.head));
}
let build_time: Option<&str> = Some(shadow::BUILD_TIME).filter(|x| !x.is_empty());
if let Some(build_time) = build_time {
cols.push("build_time".to_string());
vals.push(Value::String {
val: build_time.to_string(),
span: call.head,
});
vals.push(Value::string(build_time, call.head));
}
let build_rust_channel: Option<&str> =
Some(shadow::BUILD_RUST_CHANNEL).filter(|x| !x.is_empty());
if let Some(build_rust_channel) = build_rust_channel {
cols.push("build_rust_channel".to_string());
vals.push(Value::String {
val: build_rust_channel.to_string(),
span: call.head,
});
vals.push(Value::string(build_rust_channel, call.head));
}
cols.push("features".to_string());

View File

@ -1,5 +1,3 @@
use std::sync::atomic::Ordering;
use nu_engine::{eval_block, eval_expression, CallExt};
use nu_protocol::ast::Call;
use nu_protocol::engine::{Block, Command, EngineState, Stack};
@ -48,10 +46,8 @@ impl Command for While {
let block: Block = call.req(engine_state, stack, 1)?;
loop {
if let Some(ctrlc) = &engine_state.ctrlc {
if ctrlc.load(Ordering::SeqCst) {
break;
}
if nu_utils::ctrl_c::was_pressed(&engine_state.ctrlc) {
break;
}
let result = eval_expression(engine_state, stack, cond)?;
@ -63,7 +59,7 @@ impl Command for While {
engine_state,
stack,
block,
PipelineData::new(call.head),
PipelineData::empty(),
call.redirect_stdout,
call.redirect_stderr,
) {
@ -77,7 +73,11 @@ impl Command for While {
return Err(err);
}
Ok(pipeline) => {
pipeline.into_value(call.head);
let exit_code =
pipeline.print(engine_state, stack, false, false)?;
if exit_code != 0 {
break;
}
}
}
} else {
@ -94,7 +94,7 @@ impl Command for While {
}
}
}
Ok(PipelineData::new(call.head))
Ok(PipelineData::empty())
}
fn examples(&self) -> Vec<Example> {

View File

@ -1,5 +1,5 @@
use super::super::SQLiteDatabase;
use crate::database::values::definitions::{db::Db, db_row::DbRow, db_table::DbTable};
use crate::database::values::definitions::{db_row::DbRow, db_table::DbTable};
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
@ -22,7 +22,7 @@ impl Command for SchemaDb {
}
fn usage(&self) -> &str {
"Show SQLite database information, including its schema."
"Show the schema of a SQLite database."
}
fn examples(&self) -> Vec<Example> {
@ -50,76 +50,63 @@ impl Command for SchemaDb {
let sqlite_db = SQLiteDatabase::try_from_pipeline(input, span)?;
let conn = open_sqlite_db_connection(&sqlite_db, span)?;
let dbs = get_databases_and_tables(&sqlite_db, &conn, span)?;
let tables = sqlite_db.get_tables(&conn).map_err(|e| {
ShellError::GenericError(
"Error reading tables".into(),
e.to_string(),
Some(span),
None,
Vec::new(),
)
})?;
cols.push("db_filename".into());
vals.push(Value::String {
val: sqlite_db.path.to_string_lossy().into(),
let mut table_names = vec![];
let mut table_values = vec![];
for table in tables {
let column_info = get_table_columns(&sqlite_db, &conn, &table, span)?;
let constraint_info = get_table_constraints(&sqlite_db, &conn, &table, span)?;
let foreign_key_info = get_table_foreign_keys(&sqlite_db, &conn, &table, span)?;
let index_info = get_table_indexes(&sqlite_db, &conn, &table, span)?;
let mut cols = vec![];
let mut vals = vec![];
cols.push("columns".into());
vals.push(Value::List {
vals: column_info,
span,
});
cols.push("constraints".into());
vals.push(Value::List {
vals: constraint_info,
span,
});
cols.push("foreign_keys".into());
vals.push(Value::List {
vals: foreign_key_info,
span,
});
cols.push("indexes".into());
vals.push(Value::List {
vals: index_info,
span,
});
table_names.push(table.name);
table_values.push(Value::Record { cols, vals, span });
}
cols.push("tables".into());
vals.push(Value::Record {
cols: table_names,
vals: table_values,
span,
});
for db in dbs {
let tables = get_database_tables(&db);
let mut table_list: Vec<Value> = vec![];
let mut table_names = vec![];
let mut table_values = vec![];
for table in tables {
let column_info = get_table_columns(&sqlite_db, &conn, &table, span)?;
let constraint_info = get_table_constraints(&sqlite_db, &conn, &table, span)?;
let foreign_key_info = get_table_foreign_keys(&sqlite_db, &conn, &table, span)?;
let index_info = get_table_indexes(&sqlite_db, &conn, &table, span)?;
table_names.push(table.name);
table_values.push(Value::Record {
cols: vec![
"columns".into(),
"constraints".into(),
"foreign_keys".into(),
"indexes".into(),
],
vals: vec![
Value::List {
vals: column_info,
span,
},
Value::List {
vals: constraint_info,
span,
},
Value::List {
vals: foreign_key_info,
span,
},
Value::List {
vals: index_info,
span,
},
],
span,
});
}
table_list.push(Value::Record {
cols: table_names,
vals: table_values,
span,
});
cols.push("databases".into());
let mut rcols = vec![];
let mut rvals = vec![];
rcols.push("name".into());
rvals.push(Value::string(db.name().to_string(), span));
rcols.push("tables".into());
rvals.append(&mut table_list);
vals.push(Value::Record {
cols: rcols,
vals: rvals,
span,
});
}
// TODO: add views and triggers
Ok(PipelineData::Value(
Value::Record { cols, vals, span },
@ -140,26 +127,6 @@ fn open_sqlite_db_connection(db: &SQLiteDatabase, span: Span) -> Result<Connecti
})
}
fn get_databases_and_tables(
db: &SQLiteDatabase,
conn: &Connection,
span: Span,
) -> Result<Vec<Db>, ShellError> {
db.get_databases_and_tables(conn).map_err(|e| {
ShellError::GenericError(
"Error getting databases and tables".into(),
e.to_string(),
Some(span),
None,
Vec::new(),
)
})
}
fn get_database_tables(db: &Db) -> Vec<DbTable> {
db.tables()
}
fn get_table_columns(
db: &SQLiteDatabase,
conn: &Connection,

View File

@ -1,27 +0,0 @@
use super::db_table::DbTable;
// Thank you gobang
// https://github.com/TaKO8Ki/gobang/blob/main/database-tree/src/lib.rs
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Db {
pub name: String,
pub tables: Vec<DbTable>,
}
impl Db {
pub fn new(database: String, tables: Vec<DbTable>) -> Self {
Self {
name: database,
tables,
}
}
pub fn name(&self) -> &str {
self.name.as_str()
}
pub fn tables(&self) -> Vec<DbTable> {
self.tables.clone()
}
}

View File

@ -1,4 +1,3 @@
pub mod db;
pub mod db_column;
pub mod db_constraint;
pub mod db_foreignkey;

View File

@ -1,5 +1,5 @@
use super::definitions::{
db::Db, db_column::DbColumn, db_constraint::DbConstraint, db_foreignkey::DbForeignKey,
db_column::DbColumn, db_constraint::DbConstraint, db_foreignkey::DbForeignKey,
db_index::DbIndex, db_table::DbTable,
};
@ -10,6 +10,7 @@ use std::{
fs::File,
io::Read,
path::{Path, PathBuf},
sync::{atomic::AtomicBool, Arc},
};
const SQLITE_MAGIC_BYTES: &[u8] = "SQLite format 3\0".as_bytes();
@ -20,16 +21,25 @@ pub struct SQLiteDatabase {
// 1) YAGNI, 2) it's not obvious how cloning a connection could work, 3) state
// management gets tricky quick. Revisit this approach if we find a compelling use case.
pub path: PathBuf,
#[serde(skip)]
// this understandably can't be serialized. think that's OK, I'm not aware of a
// reason why a CustomValue would be serialized outside of a plugin
ctrlc: Option<Arc<AtomicBool>>,
}
impl SQLiteDatabase {
pub fn new(path: &Path) -> Self {
pub fn new(path: &Path, ctrlc: Option<Arc<AtomicBool>>) -> Self {
Self {
path: PathBuf::from(path),
ctrlc,
}
}
pub fn try_from_path(path: &Path, span: Span) -> Result<Self, ShellError> {
pub fn try_from_path(
path: &Path,
span: Span,
ctrlc: Option<Arc<AtomicBool>>,
) -> Result<Self, ShellError> {
let mut file =
File::open(path).map_err(|e| ShellError::ReadingFile(e.to_string(), span))?;
@ -38,7 +48,7 @@ impl SQLiteDatabase {
.map_err(|e| ShellError::ReadingFile(e.to_string(), span))
.and_then(|_| {
if buf == SQLITE_MAGIC_BYTES {
Ok(SQLiteDatabase::new(path))
Ok(SQLiteDatabase::new(path, ctrlc))
} else {
Err(ShellError::ReadingFile("Not a SQLite file".into(), span))
}
@ -50,6 +60,7 @@ impl SQLiteDatabase {
Value::CustomValue { val, span } => match val.as_any().downcast_ref::<Self>() {
Some(db) => Ok(Self {
path: db.path.clone(),
ctrlc: db.ctrlc.clone(),
}),
None => Err(ShellError::CantConvert(
"database".into(),
@ -81,7 +92,8 @@ impl SQLiteDatabase {
pub fn query(&self, sql: &Spanned<String>, call_span: Span) -> Result<Value, ShellError> {
let db = open_sqlite_db(&self.path, call_span)?;
run_sql_query(db, sql).map_err(|e| {
let stream = run_sql_query(db, sql, self.ctrlc.clone()).map_err(|e| {
ShellError::GenericError(
"Failed to query SQLite database".into(),
e.to_string(),
@ -89,7 +101,9 @@ impl SQLiteDatabase {
None,
Vec::new(),
)
})
})?;
Ok(stream)
}
pub fn open_connection(&self) -> Result<Connection, rusqlite::Error> {
@ -101,35 +115,6 @@ impl SQLiteDatabase {
Ok(conn)
}
pub fn get_databases_and_tables(&self, conn: &Connection) -> Result<Vec<Db>, rusqlite::Error> {
let mut db_query = conn.prepare("SELECT name FROM pragma_database_list")?;
let databases = db_query.query_map([], |row| {
let name: String = row.get(0)?;
Ok(Db::new(name, self.get_tables(conn)?))
})?;
let mut db_list = vec![];
for db in databases {
db_list.push(db?);
}
Ok(db_list)
}
pub fn get_databases(&self, conn: &Connection) -> Result<Vec<String>, rusqlite::Error> {
let mut db_query = conn.prepare("SELECT name FROM pragma_database_list")?;
let mut db_list = vec![];
let _ = db_query.query_map([], |row| {
let name: String = row.get(0)?;
db_list.push(name);
Ok(())
})?;
Ok(db_list)
}
pub fn get_tables(&self, conn: &Connection) -> Result<Vec<DbTable>, rusqlite::Error> {
let mut table_names =
conn.prepare("SELECT name FROM sqlite_master WHERE type = 'table'")?;
@ -297,6 +282,7 @@ impl CustomValue for SQLiteDatabase {
fn clone_value(&self, span: Span) -> Value {
let cloned = SQLiteDatabase {
path: self.path.clone(),
ctrlc: self.ctrlc.clone(),
};
Value::CustomValue {
@ -311,7 +297,7 @@ impl CustomValue for SQLiteDatabase {
fn to_base_value(&self, span: Span) -> Result<Value, ShellError> {
let db = open_sqlite_db(&self.path, span)?;
read_entire_sqlite_db(db, span).map_err(|e| {
read_entire_sqlite_db(db, span, self.ctrlc.clone()).map_err(|e| {
ShellError::GenericError(
"Failed to read from SQLite database".into(),
e.to_string(),
@ -334,7 +320,7 @@ impl CustomValue for SQLiteDatabase {
fn follow_path_string(&self, _column_name: String, span: Span) -> Result<Value, ShellError> {
let db = open_sqlite_db(&self.path, span)?;
read_single_table(db, _column_name, span).map_err(|e| {
read_single_table(db, _column_name, span, self.ctrlc.clone()).map_err(|e| {
ShellError::GenericError(
"Failed to read from SQLite database".into(),
e.to_string(),
@ -368,47 +354,72 @@ pub fn open_sqlite_db(path: &Path, call_span: Span) -> Result<Connection, nu_pro
})
}
fn run_sql_query(conn: Connection, sql: &Spanned<String>) -> Result<Value, rusqlite::Error> {
fn run_sql_query(
conn: Connection,
sql: &Spanned<String>,
ctrlc: Option<Arc<AtomicBool>>,
) -> Result<Value, rusqlite::Error> {
let stmt = conn.prepare(&sql.item)?;
prepared_statement_to_nu_list(stmt, sql.span)
prepared_statement_to_nu_list(stmt, sql.span, ctrlc)
}
fn read_single_table(
conn: Connection,
table_name: String,
call_span: Span,
ctrlc: Option<Arc<AtomicBool>>,
) -> Result<Value, rusqlite::Error> {
let stmt = conn.prepare(&format!("SELECT * FROM {}", table_name))?;
prepared_statement_to_nu_list(stmt, call_span)
prepared_statement_to_nu_list(stmt, call_span, ctrlc)
}
fn prepared_statement_to_nu_list(
mut stmt: rusqlite::Statement,
call_span: Span,
ctrlc: Option<Arc<AtomicBool>>,
) -> Result<Value, rusqlite::Error> {
let column_names = stmt
.column_names()
.iter()
.map(|c| c.to_string())
.collect::<Vec<String>>();
let results = stmt.query([])?;
let nu_records = results
.mapped(|row| {
Result::Ok(convert_sqlite_row_to_nu_value(
row,
call_span,
column_names.clone(),
))
})
.into_iter()
.collect::<Result<Vec<Value>, rusqlite::Error>>()?;
let row_results = stmt.query_map([], |row| {
Ok(convert_sqlite_row_to_nu_value(
row,
call_span,
column_names.clone(),
))
})?;
// we collect all rows before returning them. Not ideal but it's hard/impossible to return a stream from a CustomValue
let mut row_values = vec![];
for row_result in row_results {
if nu_utils::ctrl_c::was_pressed(&ctrlc) {
// return whatever we have so far, let the caller decide whether to use it
return Ok(Value::List {
vals: row_values,
span: call_span,
});
}
if let Ok(row_value) = row_result {
row_values.push(row_value);
}
}
Ok(Value::List {
vals: nu_records,
vals: row_values,
span: call_span,
})
}
fn read_entire_sqlite_db(conn: Connection, call_span: Span) -> Result<Value, rusqlite::Error> {
fn read_entire_sqlite_db(
conn: Connection,
call_span: Span,
ctrlc: Option<Arc<AtomicBool>>,
) -> Result<Value, rusqlite::Error> {
let mut table_names: Vec<String> = Vec::new();
let mut tables: Vec<Value> = Vec::new();
@ -421,7 +432,7 @@ fn read_entire_sqlite_db(conn: Connection, call_span: Span) -> Result<Value, rus
table_names.push(table_name.clone());
let table_stmt = conn.prepare(&format!("select * from [{}]", table_name))?;
let rows = prepared_statement_to_nu_list(table_stmt, call_span)?;
let rows = prepared_statement_to_nu_list(table_stmt, call_span, ctrlc.clone())?;
tables.push(rows);
}
@ -480,7 +491,7 @@ mod test {
#[test]
fn can_read_empty_db() {
let db = open_connection_in_memory().unwrap();
let converted_db = read_entire_sqlite_db(db, Span::test_data()).unwrap();
let converted_db = read_entire_sqlite_db(db, Span::test_data(), None).unwrap();
let expected = Value::Record {
cols: vec![],
@ -504,7 +515,7 @@ mod test {
[],
)
.unwrap();
let converted_db = read_entire_sqlite_db(db, Span::test_data()).unwrap();
let converted_db = read_entire_sqlite_db(db, Span::test_data(), None).unwrap();
let expected = Value::Record {
cols: vec!["person".to_string()],
@ -538,7 +549,7 @@ mod test {
db.execute("INSERT INTO item (id, name) VALUES (456, 'foo bar')", [])
.unwrap();
let converted_db = read_entire_sqlite_db(db, span).unwrap();
let converted_db = read_entire_sqlite_db(db, span, None).unwrap();
let expected = Value::Record {
cols: vec!["item".to_string()],

View File

@ -30,14 +30,8 @@ impl Command for ColumnsDF {
example: "[[a b]; [1 2] [3 4]] | into df | columns",
result: Some(Value::List {
vals: vec![
Value::String {
val: "a".into(),
span: Span::test_data(),
},
Value::String {
val: "b".into(),
span: Span::test_data(),
},
Value::string("a", Span::test_data()),
Value::string("b", Span::test_data()),
],
span: Span::test_data(),
}),
@ -67,10 +61,7 @@ fn command(
.as_ref()
.get_column_names()
.iter()
.map(|v| Value::String {
val: v.to_string(),
span: call.head,
})
.map(|v| Value::string(*v, call.head))
.collect();
let names = Value::List {

View File

@ -82,10 +82,7 @@ fn command(
span: call.head,
});
Value::String {
val: v.to_string(),
span: call.head,
}
Value::string(*v, call.head)
})
.collect();

View File

@ -61,15 +61,9 @@ impl Command for ListDF {
span: call.head,
};
let columns = Value::Int {
val: df.as_ref().width() as i64,
span: call.head,
};
let columns = Value::int(df.as_ref().width() as i64, call.head);
let rows = Value::Int {
val: df.as_ref().height() as i64,
span: call.head,
};
let rows = Value::int(df.as_ref().height() as i64, call.head);
let cols = vec![
"name".to_string(),

View File

@ -61,15 +61,9 @@ fn command(
) -> Result<PipelineData, ShellError> {
let df = NuDataFrame::try_from_pipeline(input, call.head)?;
let rows = Value::Int {
val: df.as_ref().height() as i64,
span: call.head,
};
let rows = Value::int(df.as_ref().height() as i64, call.head);
let cols = Value::Int {
val: df.as_ref().width() as i64,
span: call.head,
};
let cols = Value::int(df.as_ref().width() as i64, call.head);
let rows_col = Column::new("rows".to_string(), vec![rows]);
let cols_col = Column::new("columns".to_string(), vec![cols]);

View File

@ -32,14 +32,8 @@ impl Command for ExprAsNu {
result: Some(Value::Record {
cols: vec!["expr".into(), "value".into()],
vals: vec![
Value::String {
val: "column".into(),
span: Span::test_data(),
},
Value::String {
val: "a".into(),
span: Span::test_data(),
},
Value::string("column", Span::test_data()),
Value::string("a", Span::test_data()),
],
span: Span::test_data(),
}),

View File

@ -38,14 +38,8 @@ impl Command for ExprCol {
result: Some(Value::Record {
cols: vec!["expr".into(), "value".into()],
vals: vec![
Value::String {
val: "column".into(),
span: Span::test_data(),
},
Value::String {
val: "a".into(),
span: Span::test_data(),
},
Value::string("column", Span::test_data()),
Value::string("a", Span::test_data()),
],
span: Span::test_data(),
}),

View File

@ -37,14 +37,8 @@ impl Command for ExprLit {
result: Some(Value::Record {
cols: vec!["expr".into(), "value".into()],
vals: vec![
Value::String {
val: "literal".into(),
span: Span::test_data(),
},
Value::String {
val: "2i64".into(),
span: Span::test_data(),
},
Value::string("literal", Span::test_data()),
Value::string("2i64", Span::test_data()),
],
span: Span::test_data(),
}),

View File

@ -86,10 +86,7 @@ fn command(
)
})?;
let value = Value::Bool {
val: !bool.any(),
span: call.head,
};
let value = Value::boolean(!bool.any(), call.head);
NuDataFrame::try_from_columns(vec![Column::new("all_false".to_string(), vec![value])])
.map(|df| PipelineData::Value(NuDataFrame::into_value(df, call.head), None))

View File

@ -86,10 +86,7 @@ fn command(
)
})?;
let value = Value::Bool {
val: bool.all(),
span: call.head,
};
let value = Value::boolean(bool.all(), call.head);
NuDataFrame::try_from_columns(vec![Column::new("all_true".to_string(), vec![value])])
.map(|df| PipelineData::Value(NuDataFrame::into_value(df, call.head), None))

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