Compare commits

...

138 Commits

Author SHA1 Message Date
5d8763ed1d Bump version for 0.86.0 release (#10726)
## Release checklist:

- [x] `uu_cp` on crates.io #10725
- [x] new `reedline` released and used nushell/reedline#645
- [x] check of workspace dependency DAG
- [x] release notes ready:
https://github.com/nushell/nushell.github.io/pull/1071
2023-10-18 06:08:20 +13:00
58124e66a4 Pin reedline to 0.25.0 release (#10741)
See release notes:
https://github.com/nushell/reedline/releases/tag/v0.25.0
2023-10-17 07:34:45 +13:00
25af32d3a8 Bump crate-ci/typos from 1.16.17 to 1.16.19 (#10731) 2023-10-16 18:28:49 +00:00
5a746c0ed6 add coreutils to cp search terms (#10738)
# Description

This PR is just a quick change to add `coreutils` to the `cp` command. I
thought that it would be a good search term as we start to integrate
more `coreutils` commands.

# 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` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->

# 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.
-->
2023-10-16 07:21:30 -05:00
89ccdc2b06 docs: fix typos in CONTRIBUTING.md (#10727)
Fixed two small typos/spelling mistakes I came accross upon reading
CONTRIBUTING.md.

Signed-off-by: 0scvr <71343264+0scvr@users.noreply.github.com>
2023-10-15 21:42:34 +02:00
76ee00e013 Pin uu_cp to the 0.0.22 release. (#10725) 2023-10-15 21:19:34 +02:00
4e5a1ced13 nu-table: Use config color scheme in kv tables and table -e (#10720)
fix #10712
cc: @fdncred
2023-10-14 19:25:00 -05:00
1f62024a15 add a debug info command to show memory info (#10711)
# Description

This PR adds a new command called `debug info`. I'm not sure if the name
is right but we can rename it if needed. The purpose of this command is
to show a user how much memory nushell is using. This is what the output
looks like.

I feel like the further we go with nushell, the more we'll need to
easily monitor the memory usage. With this command, we should easily be
able to do that with scripts or just running the command.

```nushell
❯ debug info | table -e
╭─────────┬──────────────────────────────────────────────────────────────────────╮
│pid      │31036                                                                 │
│ppid     │29388                                                                 │
│         │╭─────────────────┬────────────────────────────────────────────────╮  │
│process  ││memory           │63.5 MB                                         │  │
│         ││virtual_memory   │5.6 GB                                          │  │
│         ││status           │Runnable                                        │  │
│         ││root             │C:\cartar\debug                                 │  │
│         ││cwd              │C:\Users\us991808\source\repos\forks\nushell\   │  │
│         ││exe_path         │C:\cartar\debug\nu.exe                          │  │
│         ││command          │c:\cartar\debug\nu.exe -l                       │  │
│         ││name             │nu.exe                                          │  │
│         ││environment      │{record 110 fields}                             │  │
│         │╰─────────────────┴────────────────────────────────────────────────╯  │
│         │╭────────────────┬───────╮                                            │
│system   ││total_memory    │17.1 GB│                                            │
│         ││free_memory     │5.9 GB │                                            │
│         ││used_memory     │11.3 GB│                                            │
│         ││available_memory│5.9 GB │                                            │
│         │╰────────────────┴───────╯                                            │
╰─────────┴──────────────────────────────────────────────────────────────────────╯
```
> [!NOTE]
The `process.environment` is not the nushell `$env` but the environment
that the process was created with at launch time.
# 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` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->

# 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.
-->
2023-10-14 12:28:48 -05:00
6181ea5fc1 fix: only escape path containing numbers if they can be valid floating points (#10719)
<!--
if this PR closes one or more issues, you can automatically link the PR
with
them by using one of the [*linking
keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword),
e.g.
- this PR should close #xxxx
- fixes #xxxx

you can also mention related issues, PRs or discussions!
-->

Refer to
https://github.com/nushell/nushell/pull/10600#issuecomment-1762863791

# 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.
-->

A path is escaped when it can be entirely parsed as a floating point
number. This includes `nan`, `inf` and their negative counterparts since
nu also supports them.

# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->
Paths with numbers that cannot be ambiguous are no longer surrounded by
backticks.

# 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` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->

# 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.
-->
2023-10-14 12:22:15 -05:00
1751ac12f4 allow multiple extensions (#10593)
<!--
if this PR closes one or more issues, you can automatically link the PR
with
them by using one of the [*linking
keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword),
e.g.
- this PR should close #xxxx
- fixes #xxxx

you can also mention related issues, PRs or discussions!
-->

# 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.
-->

This PR allows `open` to handle files with multiple extensions; i.e it
will try to call `from tar.gz`, `from gz` when calling
```nu
open file.tar.gz
```

# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->
No breaking changes.
2023-10-13 13:45:36 -05:00
6cff54ed0d refactor: inline fn partial_from in completer (#10705)
# Description
After the addition of the prefix tab completion support, the older
`partial_from` function is left with a single invocation. This PR moves
the code inside the function to the point of invocation.

# User-Facing Changes

No user facing changes.

# Tests + Formatting
Tests are passing.
2023-10-13 17:57:19 +02:00
ec3e4ce120 dirs goto: update current ring slot before leaving it. (#10706)
Fixes #10696

# Description

As reported, you could mess up the ring of remembered directories in
`std dirs` (a.k.a the `shells` commands) with a sequence like this:
```
~/test> mkdir b c

~/test> pushd b
~/test/b> cd ../c
~/test/c> goto 0
~/test> goto 1
## expect to end up in ~/test/c
## observe you're in ~/test/b
~/test/b>
```
Problem was `dirs goto` was not updating the remembered directories
before leaving the current slot for some other. This matters if the user
did a manual `cd` (which cannot update the remembered directories ring)

# User-Facing Changes
None! it just works ™️

# Tests + Formatting

- 🟢 `toolkit fmt`
- 🟢 `toolkit clippy`
- 🟢 `toolkit test`
- 🟢 `toolkit test stdlib`

# 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.
-->
2023-10-13 06:46:51 -05:00
f97443aff6 Use heck for string casing (again) (#10680)
Re-fixes #3674, if that is seen as desirable to do.

# Description
This PR changes the implementation of the `--features=extra` string
casing commands from Inflector to `heck`, as in PR #4081. This PR landed
a long time ago, but somewhere along the way (i can't find it) the
implementation ended up being switched back to Inflector.

# User-Facing Changes
Inflector and `heck` implement casing differently, so all of the
commands have different behavior around edge cases (consecutive
capitals, interspersed numbers and letters, etc)

### Before
```nu
G:/Dev/nu-itself/nushell> [UserID ABCdefGHI foo123bar] | str camel-case
╭───┬───────────╮
│ 0 │ userID    │
│ 1 │ abcdefGHI │
│ 2 │ foo123Bar │
╰───┴───────────╯
G:/Dev/nu-itself/nushell> [UserID ABCdefGHI foo123bar] | str snake-case
╭───┬─────────────╮
│ 0 │ user_id     │
│ 1 │ ab_cdef_ghi │
│ 2 │ foo_12_3bar │
╰───┴─────────────╯
```

### After
```nu
G:/Dev/nu-itself/nushell> [UserID ABCdefGHI foo123bar] | str camel-case
╭───┬───────────╮
│ 0 │ userId    │
│ 1 │ abCdefGhi │
│ 2 │ foo123bar │
╰───┴───────────╯
G:/Dev/nu-itself/nushell> [UserID ABCdefGHI foo123bar] | str snake-case
╭───┬─────────────╮
│ 0 │ user_id     │
│ 1 │ ab_cdef_ghi │
│ 2 │ foo123bar   │
╰───┴─────────────╯
```

# Tests + Formatting

The existing string casing tests pass... because none of them relied on
any of these edge cases
2023-10-13 12:52:35 +02:00
c925537c48 Update polars to 0.33 (#10672)
# Description
Open question:

Undocumented behavior for the new argument `ambiguous` to the
`as_datetime`
methods. I cheated by passing a default (assuming empty string).
This appears like an API primarily serving the python impl:


https://pola-rs.github.io/polars/py-polars/html/reference/expressions/api/polars.Expr.str.to_datetime.html#polars-expr-str-to-datetime


# User-Facing Changes
Only dependent on breaking changes to the behavior of polars.

# Tests + Formatting
No observed changes to tests

Manually checked `dfr as-datetime`, doesn't seem to panic.
2023-10-11 21:28:18 +02:00
c5545c59c6 Fix output types of math commands to be narrower (#9740)
# Description
Those commands either only return `Type::Float` or `Type::Int`

Narrow the type to the correct output

# User-Facing Changes
More correct type in documentation
2023-10-11 21:26:35 +02:00
55044aa7d6 change Type::Float => SyntaxShape::Number to SyntaxShape::Float (#10689)
# Description

This PR changes `Type::Float` to point at `SyntaxShape::Float` instead
of `SyntaxShape::Number`.

# 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` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->

# 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.
-->
2023-10-11 12:27:09 -05:00
4be7004289 add Ellie to the standard library (#10686)
the other day i heard the story of our friend Ellie the elephant and i
couldn't resist adding it as a command to the standard library 😊
2023-10-11 11:36:16 -05:00
814a5caf9a change canonicalize test use a more deeply rooted folder (#10685)
# Description

This PR changes the `canonicalize_ndots` tests (renames to
canonicalize_ndots2) so that when it's checking for
`canonicalize_with("...", cwd)` it guarantees it begins in a more deeply
nested folder. I was having problems because my new DevDrive is on
D:\nushell and it can't do `cd ...` from that folder.

# 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` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->

# 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.
-->
2023-10-11 11:27:25 -05:00
81ece18d5e Add a stub dfr command (#10683)
# Description
This will only display the list of subcommands.

Prompted by a question on Discord why completions may be missing.
With standard completion settings getting the subcommands doesn't seem
to be a problem but we could add this command for good measure.

# User-Facing Changes
New command `dfr` that does nothing apart from displaying the
subcommands and hogging a space in the completions

# Tests + Formatting
(-)
2023-10-11 17:51:20 +02:00
0ba81f1d51 rename nushell's cp command to cp-old making coreutils the default cp (#10678)
# Description

This PR renames nushell's `cp` command to `cp-old` to make room for
`ucp` to be renamed to `cp`, making the coreutils version of `cp` the
default for nushell. After some period of time, we should remove
`cp-old` entirely.

# 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` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->

# 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.
-->
2023-10-10 18:13:28 -05:00
c81fa397b6 Bump trash from 3.0.6 to 3.1.0 (#10654) 2023-10-10 20:52:45 +00:00
8c36e9df44 remove into decimal (#10341)
followup to
- https://github.com/nushell/nushell/pull/9979

## ⚠️ wait for just before 0.86 ⚠️

# Description
after deprecation comes removal 😏 

# User-Facing Changes
`into decimal` is removed in favor of `into float`

# Tests + Formatting

# After Submitting
2023-10-10 20:05:44 +02:00
1402508416 give better error if required field of url join is invalid (#10589)
# Description
Fix #10506 by adding `ExpectedNonNull` `ShellError` if required field is
entered as `$nothing`, `null`, " ", etc.

This adds a new `ShellError`, `ExpectedNonNull`, taking the expected
type and span.

# User-Facing Changes
Will get a more helpful error in the case described by #10506. Examples:
```nushell
➜ {scheme: "", host: "github.com"} | url join
Error: nu:🐚:expected_non_null

  × Expected string found null.
   ╭─[entry #16:1:1]
 1 │ {scheme: "", host: "github.com"} | url join
   ·          ─┬
   ·           ╰── expected string, found null
   ╰────
```

```nushell
❯ {scheme: "https", host: null} | url join
Error: nu:🐚:expected_non_null

  × Expected string found null.
   ╭─[entry #19:1:1]
 1 │ {scheme: "https", host: null} | url join
   ·                         ──┬─
   ·                           ╰── expected string, found null
   ╰────
```

# Tests + Formatting
All pass.
2023-10-10 19:24:23 +02:00
dc3c34275d add Direnv to the integrations (#10675)
related to
- https://github.com/direnv/direnv/pull/1175

# Description
this PR adds to the list of integrations of Nushell the new Direnv
section introduced in https://github.com/direnv/direnv/pull/1175
🥳

# User-Facing Changes

# Tests + Formatting

# After Submitting
2023-10-10 18:59:20 +02:00
f77fe04425 remove random decimal (#10342)
followup to
- https://github.com/nushell/nushell/pull/9979

## ⚠️ wait for just before 0.86 ⚠️

# Description
after deprecation comes removal 😏 

# User-Facing Changes
`into decimal` is removed in favor of `into float`

# Tests + Formatting

# After Submitting
2023-10-10 18:57:53 +02:00
20ac30b6e2 Bump byteorder from 1.4.3 to 1.5.0 (#10657) 2023-10-10 12:57:36 +00:00
4007256cfd Bump crate-ci/typos from 1.16.15 to 1.16.17 (#10653) 2023-10-10 12:53:51 +00:00
b634f1b010 Add themes to help command when available #10318 (#10623)
# Description
The issue #10318 is resolved by introducing helper methods within the
existing `get_documentation` function in the nu-engine crate. Initially,
I considered using nu-color-config crate to convert HEX config color to
ANSI color and employing the following method
[https://github.com/nushell/nushell/blob/main/crates/nu-color-config/src/color_config.rs#L9C1-L20C2](https://github.com/nushell/nushell/blob/main/crates/nu-color-config/src/color_config.rs#L9C1-L20C2).
However, this approach was deemed impractical due to circular
dependencies. Consequently, in a manner akin to how we invoke the
`table` command from the nu-command crate in `get_documentation`
function to create a themed-colored table, we invoke the `ansi` command
from nu-command to obtain the ANSI theme color code.

# User-Facing Changes
Visual Changes Only: the help command now uses configured theme, else it
falls back on default hard coded values.


# 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` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->

# 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.
-->
2023-10-10 07:40:05 -05:00
8a77d1ed92 Let run_in_login_mode succeed even with broken local config (#10622)
I wondered why this test failed for me.
Turns out my config file is not compatible with current main, but the
error message was useless. I've added `--no-config-file`
2023-10-10 14:12:19 +02:00
69a17fb247 Bump shadow-rs from 0.23.0 to 0.24.1 (#10655) 2023-10-10 10:48:51 +00:00
9f144798d3 Deprecate to xml --pretty {int} in favor of --indent {int} (#10660)
Fixes #10644

## the deprecation errors
- using `--pretty` alone` will run the command and give a warning
```nushell
> {tag: note content : [{tag: remember content : [Event]}]} | to xml --pretty 4
Error:   × Deprecated option
   ╭─[entry #7:1:1]
 1 │ {tag: note content : [{tag: remember content : [Event]}]} | to xml --pretty 4
   ·                                                             ───┬──
   ·                                                                ╰── `to xml --pretty {int}` is deprecated and will be removed in 0.87.
   ╰────
  help: Please use `--indent {int}` instead.


<note>
    <remember>Event</remember>
</note>
```
- using `--pretty` and `--indent` will give the deprecation warning and
throw an error
```nushell
> {tag: note content : [{tag: remember content : [Event]}]} | to xml --pretty 4 --indent 4
Error:   × Deprecated option
   ╭─[entry #9:1:1]
 1 │ {tag: note content : [{tag: remember content : [Event]}]} | to xml --pretty 4 --indent 4
   ·                                                             ───┬──
   ·                                                                ╰── `to xml --pretty {int}` is deprecated and will be removed in 0.87.
   ╰────
  help: Please use `--indent {int}` instead.


Error: nu:🐚:incompatible_parameters

  × Incompatible parameters.
   ╭─[entry #9:1:1]
 1 │ {tag: note content : [{tag: remember content : [Event]}]} | to xml --pretty 4 --indent 4
   ·                                                                             ┬          ┬
   ·                                                                             │          ╰── and --indent
   ·                                                                             ╰── Cannot pass --pretty
   ╰────
```
2023-10-09 19:05:33 +02:00
0b651b6372 add examples with .. and / to path join (#10620)
related to
-
https://discord.com/channels/601130461678272522/615329862395101194/1159484770468773990

# Description
because the following might not be trivial
```nushell
> "/foo/bar" | path join "/" "baz"
/baz
```
i thought adding a few examples to the `path join` command might help
😇

# User-Facing Changes
two new examples in `help path join` one with `..` and the other with
`/` 👍

# Tests + Formatting
the examples have `result`s so that they are checked.

# After Submitting

---------

Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2023-10-09 18:58:32 +02:00
ce09186e2e Preserve relative paths for local files (#10658)
- fixes #10649

# 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
Tab completions for paths starting with `./` shall have the prefix
preserved.
<!-- 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` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->

# 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.
-->
2023-10-10 03:37:45 +13:00
0c67d742f0 fix clippy (#10659)
This pr fix clippy warnings in latest clippy version(1.72.0):

Unfortunally it's not easy to handle for [try
fold](https://rust-lang.github.io/rust-clippy/master/index.html#/manual_try_fold)
warning in `start command`

Refer to known issue:
> This lint doesn’t take into account whether a function does something
on the failure case, i.e., whether short-circuiting will affect
behavior. Refactoring to try_fold is not desirable in those cases.

That's the case for our code, which does something on the failure case.

So this pr is making a little refactor on `try_commands`.
2023-10-10 03:31:15 +13:00
2ef34a3b4b Bump wax from 0.5.0 to 0.6.0 (#10574) 2023-10-09 12:31:50 +00:00
2d72f892fe Fix clippy in registry_query.rs (#10652)
The toolkit check passes locally; I'm not sure what the difference is
there.

cc @fdncred who merged the previous PR
2023-10-09 16:19:20 +08:00
ee4e0a933b Fix registry query flag validation (#10648) 2023-10-08 16:52:37 -05:00
765b303689 Add long options for formats (#10645) 2023-10-08 19:07:09 +02:00
e427c68731 Relax type-check of key-less table/record (#10629)
# Description
Relax typechecking of key-less `table`/`record`

Assume that they are acceptable for more narrowly specified
`table<...>`/`record<...>` where `...` specifies keys and potentially
types for those keys/columns.

This ensures that you can use commands that specify general return
values statically with more specific input-/args-type requirements.

Reduces the power of the type-check a bit but unlocks you to actually
use the specific annotations in more places.
Incompatibilities will only be raised if an output type declares
specific columns/keys.

Closes #9702

Supersedes #10594 as a simpler solution requiring no extra distinction.

h/t @1kinoti, @NotLebedev
# User-Facing Changes
Now legal at type-check time

```nu
def foo []: nothing -> table { [] }
def foo []: nothing -> table<> { ls }
def bar []: table<a:int,b:string> -> nothing {}

foo | bar 
```

# Tests + Formatting
- 1 explicit test with specified relaxed return type passed to concrete
expected input type
- 1 test leveraging the general output type of a built-in command
- 1 test wrapping a general built-in command and verifying the type
inference in the function body
2023-10-08 13:26:36 +02:00
ff6c0fcb81 Add long options for filters (#10641) 2023-10-08 13:12:46 +02:00
bcf3537395 fix labelled error from shell error (#10639)
# Description

Fixes a minor error in the impl From<ShellError> for LabeledError.

# User-Facing Changes

# Tests + Formatting

# After Submitting
2023-10-08 13:09:42 +02:00
4efccb2b1c Fix parsing of signature inp/out types in predecls (#10642)
# Description
Fixes https://github.com/nushell/nushell/issues/10605 (again).

The loop looking for `[` to determine signature position didn't stop
early enough, so it thought the second `[` denoting the inp/out types
marks the beginning of the signature.

# User-Facing Changes

# Tests + Formatting
adds a new `predecl_signature_multiple_inp_out_types` test

# After Submitting
2023-10-08 12:58:26 +02:00
67b5e1bde9 Fix wrong parsing of signatures in predecl scan (#10637) 2023-10-07 16:42:09 +03:00
eb4fd144eb nu-explore: Try to fix a truncation issue in expand view (#10580)
I haven't tested cause can't reproduce, but the issue very likely was
related to a emojies. (I mean I probably could but ....)

Could you try it @fdncred?
 
fix #10560
2023-10-07 06:58:26 -05:00
d51e82f33b bump rust-toolchain to 1.71.1 (#10634)
# Description

This PR bumps the rust toolchain to 1.71.1

# 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` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->

# 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.
-->
2023-10-06 16:29:58 -05:00
7827b1fb87 ucp: Change error when directory is specified but not recursive (#10609)
# Description
Closes #10537. Basically error message was unhelpful, and this temporary
measure adds back the nice previous nushell error message. Ideally, we
would like to add a more permanent solution mentioned in the issue
[comments](https://github.com/nushell/nushell/issues/10537#issuecomment-1743686122),
but since we want to have `ucp` as `cp` on new release, this is hackier
but way simpler so this fix should do it.

Only downside is that now behavior differs from `uutils` in the sense
that:
```
uutils:
> cp a foo/ bar
ls bar
# foo/a

nushell:
>ucp a foo/ bar
# directory error (not copied) ....
```
So, since its non fatal error, uutils copies a, but nushell errors out
with nothing copied. If we go to option 3 mentioned above, then we can
decide what we want to do, and perhaps continue on a non fatal error.


# 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`
to check that you're using the standard code style
- [X] `cargo test --workspace` to check that all tests pass (on Windows
make sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- [X] `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```

# After Submitting

---------

Co-authored-by: amtoine <stevan.antoine@gmail.com>
2023-10-06 18:59:46 +02:00
7dbda76fad Add long options for core and dataframes (#10619) 2023-10-06 18:55:29 +02:00
0dbd014d8b Use long options for debug (#10621)
Also add short options for `profile`
2023-10-06 18:54:15 +02:00
d064d187ab fix: complete paths surrounded by quotes or backticks (#10600)
<!--
if this PR closes one or more issues, you can automatically link the PR
with
them by using one of the [*linking
keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword),
e.g.
- this PR should close #xxxx
- fixes #xxxx

you can also mention related issues, PRs or discussions!
-->
Fixes #10586

# 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.
-->
Any partial path that begins with or is surrounded by a quote or
backtick will be tab completed. The completed result would be surrounded
by backticks unconditionally.


![output](https://github.com/nushell/nushell/assets/107522312/13e01104-18a1-4483-b010-79985294748b)

# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking 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` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->

Formatted and added test cases.

# 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.
-->
2023-10-07 05:45:30 +13:00
399319476a Move SyntaxShape specifier parsing into own file (#10448)
Pure move refactor.

Followup to:
- #10511
- #10512
- #10544 
- #10548 
- #10581
2023-10-05 23:31:40 +02:00
4f4e8c984e Parse custom completer annotation only in args (#10581)
# Description
To my knowledge `type@completer` annotations only make sense in
arguments at the moment.
Restrict the parsing.
Also fix a bug in parsing the completer annotation should there be more
than 1 `@`


- Add test that we disallow completer in type
- Guard against `@` inside command name
- Disallow custom completers in type specification


# User-Facing Changes
Error when annotating a variable or input-output type with a completer

# Tests + Formatting
Tests to verify the error message
2023-10-05 22:39:37 +02:00
129ae0bf3e Add long options for conversions (#10602)
As discussed in
https://github.com/nushell/nushell/pull/10597#issuecomment-1745692687

I've also removed one failing example for `into string`. It was simply
printed in the docs without context, and the expected result was
commented out.
2023-10-05 18:46:13 +02:00
471c58448e Add long options for bits and bytes (#10601)
As discussed in
https://github.com/nushell/nushell/pull/10597#issuecomment-1745692687
2023-10-05 18:45:28 +02:00
a03c1c266c Add url decode command (#10611)
Implemented URL decoding as a url subcommand, created corresponding unit
tests. The logic, examples and descriptions were based on the existing
`url encode` command.

Resolves #10563

# Description
Added a new `url decode` command to compliment the existing `url
encode`, as proposed by myself in #10563.
It takes a string, list of strings or cell path and produces the
corresponding decoded strings.

![image](https://github.com/nushell/nushell/assets/4030336/815a34e9-7ceb-4d09-9d74-e700ba513b17)

# User-Facing Changes
New url subcommand `url decode`, as described above.

# Tests + Formatting
I've added unit tests for the new subcommand and ensured all actions
outlined below showed no issues.
- [x] `cargo fmt --all -- --check`
- [x] `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used`
- [x] `cargo test --workspace`
- [x] `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"`
2023-10-05 18:43:58 +02:00
afdb68dc71 remove underline from std NU_LOG_FORMAT (#10604)
# Description

This PR removes the underline from the log format. It's been messing
things up for me since there is no ansi reset in the log format and
therefore everything after it is underlined.

This PR should end things like this.

![image](https://github.com/nushell/nushell/assets/343840/17e6dc87-11ba-4395-aac3-f70872b9182a)


# 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` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->

# 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.
-->
2023-10-04 13:30:49 -05:00
bc1b2fa5bd Allow specifying a custom date format in std log (#10603)
# Description
Allows the user to specify a custom date format for std log to use.

# User-Facing Changes
Added customization.
2023-10-04 18:53:46 +02:00
JT
8c507dc984 Revert "Port command examples to long option" (#10597)
Reverts nushell/nushell#10596

Using the long option in examples is going to be confusing as it makes
the reader think the long option is required. It also isn't idiomatic
Nushell.

The examples should be copy-paste-able as idiomatic Nushell, so as such
we shouldn't expand them to the long flag name.
2023-10-04 09:41:13 +13:00
4a82ee6c11 Port command examples to long option (#10596)
<!--
if this PR closes one or more issues, you can automatically link the PR
with
them by using one of the [*linking
keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword),
e.g.
- this PR should close #xxxx
- fixes #xxxx

you can also mention related issues, PRs or discussions!
-->

# Description

Long options are preferable over short ones for documentation.
This PR ports some command examples to exclusively use long options.
<!--
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` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->

# 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.
-->
2023-10-03 13:41:41 -05:00
e8da57b05e Correct line folding in from ics/from vcf (#10577)
# Description
Potential fix for #10398

datatracker.ietf.org/doc/html/rfc5545#section-3.1
datatracker.ietf.org/doc/html/rfc6350#section-3.2

---------

Co-authored-by: Joerg <joerg@schuetter.org>
2023-10-03 19:11:16 +02:00
f481879ed3 make "can't follow stream paths" error a bit better (#10569)
related to
- https://github.com/nushell/nushell/issues/9373
- https://github.com/nushell/nushell/issues/8639

might be able to close https://github.com/nushell/nushell/issues/8639? 

# Description
"can't follow stream paths" errors have always been a bit scary and
obnoxious because they give no information about what happens...

in this PR i try to slightly improve the error message by telling if the
stream was empty or not and give span information when available.

# User-Facing Changes
```nushell
> update value (get value)
Error: nu:🐚:incompatible_path_access

  × Data cannot be accessed with a cell path
   ╭─[entry #1:1:1]
 1 │ update value (get value)
   ·               ─┬─
   ·                ╰── empty pipeline doesn't support cell paths
   ╰────
```
```nushell
> ^echo "foo" | get 0
Error: nu:🐚:incompatible_path_access

  × Data cannot be accessed with a cell path
   ╭─[entry #2:1:1]
 1 │ ^echo "foo" | get 0
   ·  ──┬─
   ·    ╰── external stream doesn't support cell paths
   ╰────
```

# Tests + Formatting

# After Submitting
2023-10-03 18:57:26 +02:00
7c1487e18d Use int type name consistently (#10579)
# Description
When referring to the type use `int` consistently. Only when referring
to the concept of integer numbers use `integer`.

- Fix `random integer` to `random int` tests
  - Forgot in #10520
- Use int instead of integer in error messages
- Use int type name in bits commands
- Fix messages in `for` examples
- Use int typename in `into` commands
- Use int typename in rest of commands
- Report errors in `nu-protocol` with int typename

Work for #10332 

# User-Facing Changes
User errorrs should now use `int` so you can easily find the necessary
commands or type annotations.

# Tests + Formatting
Only two tests found that needed updating
2023-10-03 18:24:32 +02:00
2cc4191ec9 engine eval.rs remove pub from fn eval_element_with_input (#10587)
code cleanup of *eval.rs*

I was reviewing the engine code and noticed this...

The *eval_element_with_input* method in eval.rs does not need to be
public at the moment
because no one is calling it...

@jntrnr is making this method not public going to block someone in the
future who might need it ?

Right now its not being used so I decided to tighten up the API a bit...
2023-10-02 21:57:21 -07:00
JT
844cb1213b Remove cd w/ abbreviations (#10588)
# Description

This removes the old style "cd with abbreviations" that would attempt to
guess what directory you wanted to `cd` to. This would sometimes have
false positives, so we left it off by default in the config.

In the current main, we have much-improved path completions
(https://github.com/nushell/nushell/pull/10543) so you can now do `cd
a/b<tab>` and get a much better experience (because you can see the
directory you're about to cd to). This removes the need for the previous
abbreviation system.

# User-Facing Changes

This does remove the old abbreviation system. It will likely mean that
old config files that have settings for abbreviations will now get
errors.

update: here's an example of the error you'll see:


![image](https://github.com/nushell/nushell/assets/547158/6847a25d-895a-4b92-8251-278a57e8d29a)

# 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` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->

# 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.
-->
2023-10-03 10:51:46 +13:00
JT
783f2a9342 Allow auto-cd on trailing slash (#10585)
# Description

This allows auto-cd (cd'ing by just typing the directory name with `cd`)
to work if there's a trailing slash in the path.

# User-Facing Changes

This should be an improvement over previous behaviour. I don't think
this clashes with any existing assumptions.

# 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` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->

# 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.
-->
2023-10-03 08:14:02 +13:00
eb6870cab5 Add --env and --wrapped flags to def (#10566) 2023-10-02 21:13:31 +03:00
0d367af24a Add --env flag to do command (#10572) 2023-10-02 20:47:51 +03:00
5c15a4dd6e Fish-like completions for nested directories (#10543)
<!--
if this PR closes one or more issues, you can automatically link the PR
with
them by using one of the [*linking
keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword),
e.g.
- this PR should close #5683

you can also mention related issues, PRs or discussions!
-->

# 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.
-->

This PR allows tab completion for nested directories while only
specifying a part of the directory names. To illustrate this, if I type
`tar/de/inc` and hit tab, it autocompletes to
`./target/debug/incremental`.



# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->
Nested paths can be tab completed by typing lesser characters.

# 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` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->
Tests cases are added.

# 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.
-->
2023-10-03 06:44:51 +13:00
eeade99452 add a few more grid icons (#10583)
# Description

This PR adds a few more grid icons and updates some existing ones.

# 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` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->

# 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.
-->
2023-10-02 10:04:58 -05:00
679879f79b Add warning to url join when input key is not supported (#10506) (#10565)
<!--
if this PR closes one or more issues, you can automatically link the PR
with
them by using one of the [*linking
keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword),
e.g.
- this PR should close #xxxx
- fixes #xxxx

you can also mention related issues, PRs or discussions!
-->

# 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.
-->
Adds warning to `url join` when input key is not supported as suggested
by @amtoine in #10506.

It just adds a `println!` statement but it seems like that is all that
is done for other warnings, e.g.,
20aaaaf90c/crates/nu-glob/src/lib.rs (L434)

# 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` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->
All pass.
2023-10-02 06:47:02 -05:00
c4bbc3edad Bump crate-ci/typos from 1.16.13 to 1.16.15 (#10575) 2023-10-02 09:56:38 +00:00
6c6d215197 Bump ureq from 2.7.1 to 2.8.0 (#10573) 2023-10-02 09:55:58 +00:00
4b9ec03110 add to ndjson and to jsonl to the standard library (#10519)
follow up to
- #10283

# Description
even though it appears defining `to foo` does not allow to do `save
x.foo` for free (see https://github.com/nushell/nushell/issues/10429),
because #10283 did add `from ndjson` and `from jsonl` to the standard
library, i thought adding their `to ...` counterpart would make sense
😋

# User-Facing Changes
users can now convert structured data back to NDJSON and JSONL 👌

# Tests + Formatting
this PR adds the exact same tests as for the `from ...` commands
- structured data is in `result` and the string is now the expected
- the two invalid `from ...` tests cannot be reproduced for `to ...`
afaik

# After Submitting
2023-10-02 11:50:07 +02:00
b9ecfeb890 explore: remove unused colour config code (#10570)
Remove code for 2 no-longer-used configuration options in `explore`:
`explore.config.cursor_color` and `explore.config.border_color`.

Think I made these unnecessary in
https://github.com/nushell/nushell/pull/10533 and
https://github.com/nushell/nushell/pull/10270 but missed this code, my
bad. The `explore` config code is a little hard to follow because it
does so many key lookups in hashmaps.
2023-10-01 09:06:26 -07:00
4dbbacc35d improve assertion error messages in std assert (#10551)
should close #10549 

# Description
this PR is twofold
- uses `to nuon --raw` in the error messages to make sure #10549 is
solved and makes a difference between `"1"` and `1`
- tries to introduce slightly better errors, i.e. by putting left /
right on new lines => this should hopefully help when the values become
a bit big 😋

# User-Facing Changes
the original issue:
```nushell
> assert equal {one:1 two:2} {one:"1" two:"2"}
Error:   × Assertion failed.
   ╭─[entry #3:1:1]
 1 │ assert equal {one:1 two:2} {one:"1" two:"2"}
   ·              ───────────────┬───────────────
   ·                             ╰── These are not equal.
        Left  : '{one: 1, two: 2}'
        Right : '{one: "1", two: "2"}'
   ╰────
```

a sample for all the assertions and their new messages
```nushell
> assert equal {one:1 two:2} {one:"1" two:"2"}
Error:   × Assertion failed.
   ╭─[entry #3:1:1]
 1 │ assert equal {one:1 two:2} {one:"1" two:"2"}
   ·              ───────────────┬───────────────
   ·                             ╰── These are not equal.
        Left  : '{one: 1, two: 2}'
        Right : '{one: "1", two: "2"}'
   ╰────
```
```nushell
> assert equal 1 2
Error:   × Assertion failed.
   ╭─[entry #4:1:1]
 1 │ assert equal 1 2
   ·              ─┬─
   ·               ╰── These are not equal.
        Left  : '1'
        Right : '2'
   ╰────
```
```nushell
> assert less 3 1
Error:   × Assertion failed.
   ╭─[entry #6:1:1]
 1 │ assert less 3 1
   ·             ─┬─
   ·              ╰── The condition *left < right* is not satisfied.
        Left  : '3'
        Right : '1'
   ╰────
```
```nushell
> assert less or equal 3 1
Error:   × Assertion failed.
   ╭─[entry #7:1:1]
 1 │ assert less or equal 3 1
   ·                      ─┬─
   ·                       ╰── The condition *left <= right* is not satisfied.
        Left  : '3'
        Right : '1'
   ╰────
```
```nushell
> assert greater 1 3
Error:   × Assertion failed.
   ╭─[entry #8:1:1]
 1 │ assert greater 1 3
   ·                ─┬─
   ·                 ╰── The condition *left > right* is not satisfied.
        Left  : '1'
        Right : '3'
   ╰────
```
```nushell
> assert greater or equal 1 3
Error:   × Assertion failed.
   ╭─[entry #9:1:1]
 1 │ assert greater or equal 1 3
   ·                         ─┬─
   ·                          ╰── The condition *left < right* is not satisfied.
        Left  : '1'
        Right : '3'
   ╰────
```
```nushell
> assert length [1 2 3] 2
Error:   × Assertion failed.
   ╭─[entry #10:1:1]
 1 │ assert length [1 2 3] 2
   ·               ────┬────
   ·                   ╰── This does not have the correct length:
        value    : [1, 2, 3]
        length   : 3
        expected : 2
   ╰────
```
```nushell
> assert length [1 "2" 3] 2
Error:   × Assertion failed.
   ╭─[entry #11:1:1]
 1 │ assert length [1 "2" 3] 2
   ·               ─────┬─────
   ·                    ╰── This does not have the correct length:
        value    : [1, "2", 3]
        length   : 3
        expected : 2
   ╰────
```
```nushell
> assert str contains "foo" "bar"
Error:   × Assertion failed.
   ╭─[entry #13:1:1]
 1 │ assert str contains "foo" "bar"
   ·                     ─────┬─────
   ·                          ╰── This does not contain '($right)'.
        value: "foo"
   ╰────
```

# Tests + Formatting

# After Submitting
2023-10-01 16:40:24 +02:00
28ef14399c stdlib: Reduce test file parsing overhead (#10545)
# Description
Retrieving tests and their annotation no longer uses nu --ide-ast
spawned in a subprocess which should reduce test runner startup time.

# User-Facing Changes

# Tests + Formatting

# After Submitting
2023-10-01 15:37:51 +02:00
20aaaaf90c Update build flags for riscv64gc and armv7 targets (#10564)
Update build flags for riscv64gc and armv7 targets, as they are not
required any more, let's give it a try in nightly release
2023-10-01 09:32:34 +08:00
7c274ad4d8 explore: remove 4 line config options (#10562)
This PR removes the `line_head_top`, `line_head_bottom`, `line_shift`,
and `line_index` configuration options from `explore`. These were
previously used to control whether the horizontal+vertical lines in this
`ls | explore -i` screenshot would be displayed:


![image](https://github.com/nushell/nushell/assets/26268125/b705e8a0-935c-40ff-be4a-f119dbae3080)

Now, all lines are displayed (same as the previous default config
values) and this is no longer configurable.

## Context

I'm continuing to chip away at `explore` when I have time. I have a
long-term goal to make `explore` simpler for users+developers. For now
I'm mostly making small incremental changes where I find underused
functionality+configuration and remove it; hopefully eventually this
will make it easier to make larger changes.

I found these specific config options a little hard to understand when
reading `explore` code, and when reading `config.nu` as a user their
behaviour+naming is not obvious. I also think that in the long term,
`explore` styling should inherit most styling from `table` instead of
having its own styling system.
2023-09-30 17:26:43 -07:00
30c331e882 explore: remove Bottom and Right orientations (#10559)
The value rendering code in explore is _very_ flexible; values can be
rendered with orientation `Top`, `Left`, `Bottom`, or `Right`. The
default is `Top` for tables (header at the top) and `Left` for records
(header on the left).

This PR removes `Bottom` and `Right`; they are largely untested,
probably used by nobody, and they complicate the rendering code.

## Testing Performed

I've manually confirmed that tables and records still render the same
ass before, and the `t`/transpose command still works.
2023-09-30 15:10:59 -05:00
fa2e6e5d53 feat: Add unfold command (#10489)
<!--
if this PR closes one or more issues, you can automatically link the PR
with
them by using one of the [*linking
keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword),
e.g.
- this PR should close #xxxx
- fixes #xxxx

you can also mention related issues, PRs or discussions!
-->

# 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.
-->
> [!NOTE]
> This PR description originally used examples where the `generator`
closure returned a list. It has since been updated to use records
instead.

The `unfold` command allows users to dynamically generate streams of
data. The stream is generated by repeatedly invoking a `generator`
closure. The `generator` closure accepts a single argument and returns a
record containing two optional keys: 'out' and 'next'. Each invocation,
the 'out' value, if present, is added to the stream. If a 'next' key is
present, it is used as the next argument to the closure, otherwise
generation stops.

The name "unfold" is borrowed from other functional-programming
languages. Whereas `fold` (or `reduce`) takes a stream of values and
outputs a single value, `unfold` takes a single value and outputs a
stream of values.

### Examples

A common example of using `unfold` is to generate a fibbonacci sequence.
See
[here](6ffdac103c/src/sources.rs (L65))
for an example of this in rust's `itertools`.

```nushell
> unfold [0, 1] {|fib| {out: $fib.0, next: [$fib.1, ($fib.0 + $fib.1)]} } | first 10
───┬────
 0 │  0
 1 │  1
 2 │  1
 3 │  2
 4 │  3
 5 │  5
 6 │  8
 7 │ 13
 8 │ 21
 9 │ 34
───┴────
```

This command is particularly useful when consuming paginated APIs, like
Github's. Previously, nushell users might use a loop and buffer
responses into a list, before returning all responses at once. However,
this behavior is not desirable if the result result is very large. Using
`unfold` avoids buffering and allows subsequent pipeline stages to use
the data concurrently, as it's being fetched.

#### Before
```nushell
mut pages = []
for page in 1.. {
  let resp = http get (
    {
      scheme: https,
      host: "api.github.com",
      path: "/repos/nushell/nushell/issues",
      params: {
	page: $page,
	per_page: $PAGE_SIZE
      }
    } | url join)

  $pages = ($pages | append $resp)

  if ($resp | length) < $PAGE_SIZE {
    break
  }
}
$pages
```

#### After
```nu
unfold 1 {|page|
  let resp = http get (
    {
      scheme: https,
      host: "api.github.com",
      path: "/repos/nushell/nushell/issues",
      params: {
	page: $page,
	per_page: $PAGE_SIZE
      }
    } | url join)

  if ($resp | length) < $PAGE_SIZE {
    {out: $resp}
  } else {
    {out: $resp, next: ($page + 1)}
  }
}
```


# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->
- An `unfold` generator is added to the default context.

# 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` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->

# 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.
-->

Given the complexity of the `generator` closure's return value, it would
be good to document the semantics of `unfold` and provide some in-depth
examples showcasing what it can accomplish.
2023-09-30 09:08:06 -05:00
7eaa6d01ab Add 'help escapes' command for quick reference of nushell string escapes (#10522)
<!--
if this PR closes one or more issues, you can automatically link the PR
with
them by using one of the [*linking
keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword),
e.g.
- this PR should close #xxxx
- fixes #xxxx

you can also mention related issues, PRs or discussions!
-->

resolves #4869 

# 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.
-->
Adds a `help escape` command that can be used to display a table of
string escape sequences and their outputs.
```nu
help escapes
```
```nu
help escapes -h
```

The command should also appear in the list displayed when tab
autocompleting on `help`.

# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->
Users can now use a new `help escapes` command to output a table of
string escape sequences and their outputs.

# 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` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->

# 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.
-->
Need to update docs to reflect existence of the new `help escapes`
command.
2023-09-30 09:04:27 -05:00
d34581db4a Rename: change the SyntaxShape of -c flag from list to record (#10526)
# Description
Fixes: #7085 
Also closes: #7526 

# User-Facing Changes
After this change, we need to use `-c` flag like this:
```nushell
[[a, b, c]; [1, 2, 3]] | rename -c { a: ham }
```
But we can rename many columns easily, here is another example:
```nushell
[[a, b, c]; [1, 2, 3]] | rename -c { a: ham, b: ham2 }
```
2023-09-30 08:59:47 -05:00
85d6529f0d chore: Small refactor of eval.rs (#10554)
# Description
- Extract long expression in `eval.rs` into variable
- Improve loop in eval.rs

# User-Facing Changes

None
2023-09-29 21:57:15 +02:00
JT
50039164f1 fix windows default prompt slash direction (#10555)
<!--
if this PR closes one or more issues, you can automatically link the PR
with
them by using one of the [*linking
keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword),
e.g.
- this PR should close #xxxx
- fixes #xxxx

you can also mention related issues, PRs or discussions!
-->

# Description

This fixes the default prompt on Windows to use the correct path
direction

# 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` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->

# 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.
-->
2023-09-30 08:18:14 +13:00
c64017de7b toolkit check pr does same clippy checks as github CI (#10528)
Align the clippy checks done by `toolkit check pr` with the ones done by
github CI when you post a PR.
Motivated in no small part by my frustration at having the third PR in
one day fail due to a lint that `toolkit check pr` didn't find!

# Description
Change definition of `toolkit clippy` 
* always run checks on all crates in the workspace
* always run checks on tests as well as non-test code
* don't check for `unwrap_used`. There are many (legit) uses of
`.unwrap()` in tests,
* 
# User-Facing Changes
Changes to `toolkit clippy`:
* remove `--workspace` switch
* `--features` is no longer mutually exclusive with `--workspace`

# Tests + Formatting
n/a

# 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: amtoine <stevan.antoine@gmail.com>
2023-09-29 19:51:19 +02:00
9e445fd4c5 Rename SyntaxShape::Custom to CompleterWrapper (#10548)
# Description
The description `Custom` doesn't really reflect meaning in the set of
`SyntaxShape`. Makes it a bit more verbose but explicit


# User-Facing Changes
Only hypothetically breaking as plugins can not effectively use a
requirement on `SyntaxShape::Custom`.

# Tests + Formatting
(-)
2023-09-29 19:22:58 +02:00
cc4f8bbd82 break the definition of LS_COLORS onto multiple lines (#10538)
related to 
- https://github.com/nushell/nushell/pull/10532

# Description
i was reviewing https://github.com/nushell/nushell/pull/10532 and
thought
> wait a minute, this line is huge and it's basically impossible to
review properly...

i had to grab the diff and throw some Nushell magic at it to see that it
was valid 😱

in this PR, i just split the loooooong string on the `:`, put that in a
list, join with `.join(":")` and borrow that to get a `str` 👌

# User-Facing Changes

# Tests + Formatting

# After Submitting
2023-09-29 19:12:46 +02:00
16453b6986 Making open case-insensitive to file extensions (#10451)
# Description

Closes #10441 

Uses `String::to_lowercase()` when the file's extension `ext` is parsed
to allow `from_decl(format!("from {ext}"))` to return the desired output
regardless of extension case.

It doesn't work with sqlite files since those are handled earlier in the
parsing but I think is good- since there's no standard file extension
used by sqlite so a user will likely want case sensitivity in that case.

This also has the (possibly undesired) effect of making `open`
completely case insensitive, e.g. `open foo.JSON` will work on a file
named `foo.json` and vice versa. This is good on Windows as it treats
`foo.json` and `foo.JSON` as the same file, but may not be the desired
behaviour on Unix.

If this behaviour is undesired I assume it would be fixed with a
`#[cfg(not(unix))]` attribute on the `to_lowercase()` operation but that
produces slightly "uglier" code that I didn't wish to submit unless
necessary. 

old behaviour:

![image](https://github.com/nushell/nushell/assets/79598494/261df577-e377-44ac-bef3-f6384bceaeb5)

new behaviour: 

![image](https://github.com/nushell/nushell/assets/79598494/04271740-a46f-4613-a3a6-1e220ef7f829)


# User-Facing Changes

`open` will now present a table when `open`-ing files with captitalized
extensions rather than the file's raw data

# Tests + Formatting

new test: `parses_file_with_uppercase_extension` which tests the desired
behaviour

---------

Co-authored-by: Stefan Holderbach <sholderbach@users.noreply.github.com>
2023-09-29 17:20:59 +02:00
d6b9153ac5 Fix Default Prompt Tilde Insertion Logic (#10539)
This pr closes #10521.

# Description

The default prompt by nushell will replace `$nu.home-path` with `~`.
E.g. for a user named `user`, `/home/user` would become `~`. This also
works with sub paths, e.g. `/home/user/docs` would become `~/docs`.

The issue is that this replacement was a tad overzealous. A path like
`/home/user-with-suffix` would become `~-with-suffix`. This PR fixes the
issue by updating the home path detection logic.

# User-Facing Changes

The bugged behavior no longer occurs.

# Tests + Formatting

* `cargo` checks were not performed as this does not touch rust.
* The updated logic was tested against
[elvish](https://github.com/elves/elvish)'s path replacement logic, for
~10,000 randomly selected folders on a linux server. All paths were
processed the same.
2023-09-29 16:40:51 +02:00
80a183dde2 Fix editor config for reedline and config nu/env (#10535)
# Description
This merges @horasal 's changes from #10246 and #10269

Closes #10205
Closes #8714

Fixes the bug that editor paths with spaces are unusable

Closes #10210 
Closes #10269


# User-Facing Changes
You can now either pass a string with the name of the executable or a
list with the executable and any flags to
`$env.config.buffer_editor`/`$env.EDITOR`/`$env.VISUAL`

Both the external buffer editor of reedline (by default bound to
`Ctrl-o`) and the commands `config nu` and `config env` will respect
those variables in the following order:
1. `$env.config.buffer_editor`
2. `$env.EDITOR`
3. `$env.VISUAL`

Example:
```
$env.EDITOR = "nvim"                      # The system-wide EDITOR is neovim
$env.config.buffer_editor = ["vim" "-p2"] # Force vim to open two tabs (not particularly useful)
$env.config.buffer_editor = null          # Unset `buffer_editor` -> Uses `$env.EDITOR` ergo nvim
```
# Tests + Formatting
None

---------

Co-authored-by: Horasal <1991933+horasal@users.noreply.github.com>
2023-09-29 16:36:03 +02:00
f2af12af2c Docstring some intricacies around SyntaxShape (#10544)
Inspired by @fdncred and @amtoine's questions
https://github.com/nushell/nushell/pull/10512#issuecomment-1739996967
2023-09-29 16:35:22 +02:00
7ad4c679b3 Add kitty protocol config to nushell (#10540)
# Description

Support keyboard enhancement protocol as implemented by Kitty console,
hence Kitty protocol.

This PR enables Nushell to use keybinding that is not available before,
such as Ctrl+i (that alias to Tab) or Ctrl+e (that alias to Esc, likely
I mistaken). After this PR merged and you set `use_kitty_protocol`
enabled, if your console app support Kitty protocol (WezTerm, Kitty,
etc.) you will be able to set more fine-grained keybinding.

For Colemak users, this feature is a blessing, because some Ctrl+[hjkl]
that previously unmap-able to Ctlr+[hnei] now it is.

# User-Facing Changes

This adds `use_kitty_protocol` config which defaults to false. When set
to `true`, it enables kitty protocol on the line editor when supported,
or else it warns.


---------

Co-authored-by: Stefan Holderbach <sholderbach@users.noreply.github.com>
2023-09-29 15:52:34 +02:00
9a0c6f2e02 glob with ../ prefix now works; (#10504)
Fixes #10503 
Also improves link to metacharacter help;

# Description
`glob` code was using pattern as provided by user. If that had leading
`..\`, `wax::Glob` is documented to treat them as literal chars to be
matched.
Fix is to use `wax::Glob.partition()` to split such invariant prefixes
off the pattern and tack them onto the working directory computed
separately.

Before
```
> ls ..
╭───┬───────┬──────┬──────┬───────────────╮
│ # │ name  │ type │ size │   modified    │
├───┼───────┼──────┼──────┼───────────────┤
│ 0 │ ../r1 │ dir  │  7 B │ 3 hours ago   │
│ 1 │ ../r2 │ dir  │  3 B │ a day ago     │
│ 2 │ ../r3 │ dir  │ 13 B │ 4 minutes ago │
╰───┴───────┴──────┴──────┴───────────────╯
> glob ../r*
╭────────────╮
│ empty list │
╰────────────╯
```
After 
```
> glob ../r*
╭───┬──────────────────────────────╮
│ 0 │ /home/bobhy/src/rust/work/r2 │
│ 1 │ /home/bobhy/src/rust/work/r1 │
│ 2 │ /home/bobhy/src/rust/work/r3 │
╰───┴──────────────────────────────╯
```

# User-Facing Changes
None

# Tests + Formatting
- 🟢 `toolkit fmt`
- 🟢 `toolkit clippy`
- 🟢 `toolkit test`
- 🟢 `toolkit test stdlib`

# 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: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2023-09-29 06:48:55 -05:00
78d0e1d0b8 explore: highlight selected cell using background colour instead of cursor (#10533)
More incremental `explore` improvements!

This PR removes the `show_cursor` config from the `explore` command, in
favour of always using the background colour to highlight the selected
cell. I believe this is a better default and I'd like to remove the
`show_cursor` functionality entirely as part of the effort to simplify
`explore`.

The style for selected cells is still configurable. I went with light
blue for the default background colour, it looks OK to me.

## Before:

![Screenshot from 2023-09-27
08-51-03](https://github.com/nushell/nushell/assets/26268125/798636be-a4ea-467f-b852-c0e929e4aa9d)


## After:

![Screenshot from 2023-09-27
08-50-59](https://github.com/nushell/nushell/assets/26268125/c88662e7-05b5-42a7-bf30-b03c70fba79d)
2023-09-28 20:17:56 -05:00
dc739f703a Remove parsing literals of unrepresentable SyntaxShapes (#10512)
# Description
Those `SyntaxShape`s can not coerce to `Value`s or `Type`s that can be
used by the user in an argument or input-output-type position.
Supporting them doesn't make sense.

# User-Facing Changes
Removal of useless "types" in argument type or input/output type
positions

# Tests + Formatting
No adjustment necessary
2023-09-28 22:36:47 +02:00
ac7263d957 Change LS_COLORS to highlight .fb2 files as text documents (#10532)
close #10396
# Description
Change LS_COLORS variable to bring the highlighting for .fb2 files in
line with other types of text documents
### Before
![ls with current LS_COLORS](https://i.imgur.com/KL0nG2y.png)
### After
![ls with changed LS_COLORS](https://i.imgur.com/ZFcLVL3.png)
2023-09-28 19:33:14 +02:00
9c52b93975 allow early return outside of main (#10514)
# Description
Fixes: #9792

When evaluating file, we need to allow early return if we evaluate
script file first.
2023-09-28 18:49:42 +02:00
80220b722b Completions: add support for doas as for sudo (#10256)
# Description

Fixes #2047 but for the `doas` command the same way as in #8094

# User-Facing Changes
No breaking changes. If people not using `doas`, no difference at all.

# Tests
I have not added any tests since its using same logic as for "sudo". I
guess if something would go wrong in this part, sudo tests will cover
it?

# Additional context
As a nushell user I could not find a way to implement custom completion
for a "sudo like command". Since I can see `sudo` being hardcoded in
sources, this is what I propose.

~~Also I have almost zero knowledge of rust and this is definitely not
the clean way yet~~

---------

Co-authored-by: Stefan Holderbach <sholderbach@users.noreply.github.com>
2023-09-28 15:29:57 +02:00
d1dc610769 Remove unused SyntaxShape::Variable (#10511)
# Description
We don't use this shape during parsing and never reference it in command
signatures. Thus it should be removed.

# User-Facing Changes
None functional.
Plugin authors that used it would never be provided with data that
specifically matched `SyntaxShape::Variable`
Builds using it will now fail.

# Tests + Formatting
NA
2023-09-28 11:53:03 +02:00
cc767463e6 Rename random integer to random int (#10520)
# Description
Consistently use `int` for types and commands

h/t @1kinoti

Work for #10332

# User-Facing Changes
Deprecate `random integer` in the next release

New command `random int`

# Tests + Formatting
(-)
2023-09-28 11:47:05 +02:00
8f4ea69c22 Add support for HTTP proxy in network commands (#10401)
Closes https://github.com/nushell/nushell/issues/8847

# Description

If the `HTTP_PROXY` variable is found, use its value to setup ureq
proxy. I haven't implemented `NO_PROXY` at the moment.

# User-Facing Changes

No breaking change for the user, the network commands simply use an
environment variable.

# Tests + Formatting

The existing tests seem to run fine, although I can't think of a new
test to add.
2023-09-27 15:43:34 +08:00
6c026242d4 remove the $nothing variable (#10478)
related to 
- https://github.com/nushell/nushell/pull/9973
- https://github.com/nushell/nushell/pull/9918

thanks to @jntrnr and their super useful tips on this PR, i learned
about the parser + evaluation, so 🙏

# Description
because we already have `null` as the value of the type `nothing` and as
a followup to the two other attempts of mine, i propose to remove the
redundant `$nothing` built-in variable 😋

this PR is the first step, deprecating `$nothing`.
a followup PR will remove it altogether and wait for 0.87 👍 

⚙️ **details**: a new `NOTHING_VARIABLE_ID = 3` has been added,
parsing `$nothing` will create it, finally a `Value::Nothing` will be
produced and a warning will be reported.

this PR already fixes the `toolkit.nu` module so that it does not throw
a bunch of warnings each time 👌

# User-Facing Changes
`$nothing` is now deprecated and will be removed in 0.87
```nushell
> $nothing
Error:   × Deprecated variable
   ╭─[entry #1:1:1]
 1 │ $nothing
   · ────┬───
   ·     ╰── `$nothing` is deprecated and will be removed in 0.87.
   ╰────
  help: Use `null` instead
```

# Tests + Formatting
tests have been updated, especially
- `nothing_fails_string`
- `nothing_fails_int`
which use a variable called `nil` now to make sure `nothing` does not
support cell paths 👍

# After Submitting
classic deprecation mention 👍
2023-09-26 18:49:28 +02:00
4a26719b0c Bump dialoguer to 0.11.0 (#10510)
Includes fixes for breaking changes
Supersedes #10494
2023-09-26 18:00:16 +02:00
d2f513da36 make better error message for not operator (#10507)
Fixes: #10476

After the change, the error message will be something like this:
```nushell
❯ not null
Error: nu:🐚:type_mismatch

  × Type mismatch.
   ╭─[entry #11:1:1]
 1 │ not null
   ·     ──┬─
   ·       ╰── expected bool, found nothing
   ╰────
```
2023-09-26 14:53:59 +02:00
feef612388 show the full directory / file path in "directory not found" error (#10430)
should close https://github.com/nushell/nushell/issues/10406

# Description
when writing a script, with variables you try to `ls` or `open`, you
will get a "directory not found" error but the variable won't be
expanded and you won't be able to see which one of the variable was the
issue...

this PR adds this information to the error.

# User-Facing Changes
let's define a variable
```nushell
let does_not_exist = "i_do_not_exist_in_the_current_directory"
```
### before
```nushell
> open $does_not_exist
Error: nu:🐚:directory_not_found

  × Directory not found
   ╭─[entry #7:1:1]
 1 │ open $does_not_exist
   ·      ───────┬───────
   ·             ╰── directory not found
   ╰────
```
```nushell
> ls $does_not_exist
Error: nu:🐚:directory_not_found

  × Directory not found
   ╭─[entry #8:1:1]
 1 │ ls $does_not_exist
   ·    ───────┬───────
   ·           ╰── directory not found
   ╰────
```

### after
```nushell
> open $does_not_exist
Error: nu:🐚:directory_not_found

  × Directory not found
   ╭─[entry #3:1:1]
 1 │ open $does_not_exist
   ·      ───────┬───────
   ·             ╰── directory not found
   ╰────
  help: /home/amtoine/documents/repos/github.com/amtoine/nushell/i_do_not_exist_in_the_current_directory does not exist
```
```nushell
> ls $does_not_exist
Error: nu:🐚:directory_not_found

  × Directory not found
   ╭─[entry #4:1:1]
 1 │ ls $does_not_exist
   ·    ───────┬───────
   ·           ╰── directory not found
   ╰────
  help: /home/amtoine/documents/repos/github.com/amtoine/nushell/i_do_not_exist_in_the_current_directory does not exist
```

# Tests + Formatting
shouldn't harm anything 🤞 

# After Submitting
2023-09-26 17:38:58 +08:00
65074ec449 nu-table: Fix failing test (relied on termwidth assumptions) (#10492)
close #10468

You can check on different term sizes.
2023-09-25 18:17:42 +02:00
a19cac2673 Command: Add config env/nu --default to print defaults (#10480)
<!--
if this PR closes one or more issues, you can automatically link the PR
with
them by using one of the [*linking
keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword),
e.g.
- this PR should close #xxxx
- fixes #xxxx

you can also mention related issues, PRs or discussions!
-->

# 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.
-->

Closes #5436

When I opened this issue more than a year ago, I mainly wanted the
following capacity: easily access the full env and have the hability to
update it when a new version of `nushell` comes out.

With this PR I can now do the following:

```nu
source-env ~/.config/nushell/defaults/env.nu
source     ~/.config/nushell/defaults/config.nu

# Update nushell default config & env file (run this after a version update)
def update-defaults [] {
    config env --default | save -f ~/.config/nushell/defaults/env.nu
    config nu  --default | save -f ~/.config/nushell/defaults/config.nu
}
```

Which is more than enough for me. Along with `nushell` respecting the
XDG spec on macOS (`dirs-next` should be banned for CLI tools on macOS),
this should be one of the last hurdle before fully switching for me!

# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->

Two new switches to existing commands:

```nu
config env --default # Print the default env embedded at compile time in the binary
config nu  --default # Print the default config embedded at compile time in the binary
```

# 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` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->

- Added a test for the output of `config env --default`
- Added a test for the output of `config nu --default`

# 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.
-->

Are the docs for commands generated automatically or do I need to make a
PR there too ? It's no problem if so, just point me at instructions if
there are any :)
2023-09-25 08:00:59 -05:00
5326e51e4f Improve release script for github release workflow (#10502)
# Description

Improve release script for Github release workflow: Just some small
improvements
2023-09-25 19:55:51 +08:00
b39cca91e5 Bump crate-ci/typos from 1.16.11 to 1.16.13 (#10493) 2023-09-25 11:02:27 +00:00
57825a5c45 Bump rayon from 1.7.0 to 1.8.0 (#10497) 2023-09-25 11:00:05 +00:00
19cee5fda1 fix magenta_reverse and friends (#10491)
# Description

Magenta wasn't being interpreted correctly. note that `bg:
magenta_reverse attr: b` showed up as white. This was because it was
missing from the lookup and it was defaulting to white.

fixes #10490 

### Before

![image](https://github.com/nushell/nushell/assets/343840/0cf69ab8-813e-42e4-aea5-5db231f29f74)

### After

![image](https://github.com/nushell/nushell/assets/343840/d36f18f3-514d-443a-8bc8-cda2fed09615)


# 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` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->

# 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.
-->
2023-09-24 14:43:17 -05:00
95a4649cc9 Update winget submission workflow include only default msi files (#10487)
### Update winget submission workflow include only default msi files:
---
The new release workflow after
https://github.com/nushell/nushell/pull/10457 will add full featured
packages like: `nu-*-x86_64-windows-msvc-full.msi` and
`nu-*-aarch64-windows-msvc-full.msi` (A release preview could be found
here: https://github.com/nushell/nightly/releases/tag/nightly-6a2fd91 )
and this change will make sure only the default packages will be
included just the same as before to make sure that nothing will be
broken.

BTW: Due to lots of changes made recently about the release workflow, I
will stand-by for the next release.
2023-09-24 07:52:10 -05:00
e96039fb1b Fix default argument value type checking (#10460)
# Description
Fix type checking in arguments default values not adhering to subtyping
rules
Currently following examples produce a parse error:
```nu
def test [ --qwe: record<a: int> = {a: 1 b: 1} ] { }
def test [ --qwe: list<any> = [ 1 2 3 ] ] { }
```
despite types matching. Type equality check is replaced with subtyping
check and everything parses fine:
# User-Facing Changes
Default values of flag arguments type checking behavior is in line with
`let` statements
2023-09-24 11:30:58 +02:00
65e2733571 Allow complex types in input/output and let (#10405)
# Description
This PR fixes #9702 on the side of parse. I.e. input/output types in
signature and type annotations in `let` now should correctly parse with
type annotations that contain commas and spaces:

![image](https://github.com/nushell/nushell/assets/17511668/babc0a69-5cb3-46c2-98ef-6da69ee3d3be)

# User-Facing Changes
Return values and let type annotations now can contain stuff like
`table<a: int b: record<c: string d: datetime>>` e.t.c
2023-09-24 11:01:21 +02:00
bc437da5c7 std dt datetime-diff: fix uninitialized field ref when borrowing (#10466)
fixes #10455 

@KAAtheWiseGit, I'm sorry, I didn't mean to block your first PR #10461,
didn't see you had submitted it till I got around to submitting this. If
you want to incoporate useful ideas from this PR into yours, I do not
mind deferring to you.


# Description
Changes made in `datetime-diff`:
* Initialize millisecond and microsecond fields in `$current`, to fix
the error when borrow needs to refer to them.
* Fix `borrow_nanoseconds` to borrow from seconds, not from (unused)
microseconds.
* Added error check to insist that first argument is >= second argument.
`datetime-diff` doesn't represent negative durations correctly (it tries
to borrow out of the year, resulting in negative year and positive all
other fields). We don't currently have a use case requiring negative
durations.
* Add comments so help is a bit clearer (I was surprised that the first
argument, named `$from` was actually supposed to be the *later*
datetime. The order of arguments is reasonable (reminiscent of <later>
<minus> <earlier>), so I just changed the param name to match its
purpose.

Changes made in `pretty-print-duration`:
* changed type of argument from `duration` to `record`. (it's not clear
why Nu was not complaining about this!)
* changed test for skipping a clause from `> 0` to `!= 0`. Even though
`datetime-diff` won't present a negative field in the record, user might
call `pretty-print-duration` with one, might as well handle it. (but I
think `hour:-2` will be rendered as `-2hr`, not `-2hrs`...).
* added help and an example.

# User-Facing Changes
none requiring code changes.

# Tests + Formatting
- 🟢 `toolkit fmt`
- 🟢 `toolkit clippy`
- 🟢 `toolkit test`
- 🟢 `toolkit test stdlib`
- 
- # 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.
-->
2023-09-24 10:53:56 +02:00
65c4083ae6 feat: Update nightly build workflow add full release support (#10485) 2023-09-24 10:15:38 +08:00
6a2fd91a01 show the whole path in "missing mod.nu" errors (#10416) 2023-09-23 16:30:03 +03:00
b6d31e0e45 fix public boolean switches in the standard library (#10477)
related to
- https://github.com/nushell/nushell/pull/10456

# Description
this PR will fix the public API of the standard library by removing the
type annotations from public boolean switches.

1. the signature before
```nushell
clip [--silent: bool, --no-notify: bool, --no-strip: bool, --expand (-e): bool, --codepage (-c): int]
```
2. the signature after
```nushell
clip [--silent, --no-notify, --no-strip, --expand (-e), --codepage (-c): int]
```

# User-Facing Changes
### before
```nushell
> "foo" | clip
Error: nu:🐚:cant_convert

  × Can't convert to bool.
     ╭─[NU_STDLIB_VIRTUAL_DIR/std/mod.nu:148:1]
 148 │         $in
 149 │         | if $expand { table --expand } else { table }
     ·              ───┬───
     ·                 ╰── can't convert nothing to bool
 150 │         | into string
     ╰────
```

### after
```nushell
> "foo" | clip
foo
saved to clipboard
```

# Tests + Formatting

# After Submitting
2023-09-23 06:40:28 -05:00
d2c87ad4b4 differentiating between --x and --x: bool (#10456)
# Description
Fixes: #10450 

This pr differentiating between `--x: bool` and `--x`

Here are examples which demostrate difference between them:
```nushell
def a [--x: bool] { $x };
a --x    # not allowed, you need to parse a value to the flag.
a        # it's allowed, and the value of `$x` is false, which behaves the same to `def a [--x] { $x }; a`
```

For boolean flag with default value, it works a little bit different to
#10450 mentioned:
```nushell
def foo [--option: bool = false] { $option }
foo                  # output false
foo --option         # not allowed, you need to parse a value to the flag.
foo --option true    # output true
```

# User-Facing Changes
After the pr, the following code is not allowed:
```nushell
def a [--x: bool] { $x }; a --x
```

Instead, you have to pass a value to flag `--x` like `a --x false`. But
bare flag works in the same way as before.

## Update: one more breaking change to help on #7260 
```
def foo [--option: bool] { $option == null }
foo
```
After the pr, if we don't use a boolean flag, the value will be `null`
instead of `true`. Because here `--option: bool` is treated as a flag
rather than a switch

---------

Co-authored-by: amtoine <stevan.antoine@gmail.com>
2023-09-23 10:20:48 +02:00
a26a01c8d0 Add full releases of Nu binaries along with the standard releases (#10457)
# Description

Add full releases of Nu binaries along with the standard releases,
close: https://github.com/nushell/nushell/issues/10322

A full release means:

1. Build with `--features=dataframe,extra` flag
2. Contains `-full` in the package name

### **A test release could be found in the nushell/nightly Repo:
https://github.com/nushell/nightly/releases/tag/v0.85.1**
The action running log:
https://github.com/nushell/nightly/actions/runs/6260611553

# User-Facing Changes

Will attach the following release packages along with the official ones
as before:

1. nu-*-aarch64-darwin-full.tar.gz
2. nu-*-aarch64-linux-gnu-full.tar.gz
3. nu-*-aarch64-windows-msvc-full.msi
4. nu-*-aarch64-windows-msvc-full.zip
5. nu-*-x86_64-darwin-full.tar.gz
6. nu-*-x86_64-linux-gnu-full.tar.gz
7. nu-*-x86_64-linux-musl-full.tar.gz
8. nu-*-x86_64-windows-msvc-full.msi
9. nu-*-x86_64-windows-msvc-full.zip
2023-09-23 09:41:08 +08:00
414216edfa Transient prompt (#10391)
## Description

This PR uses environment variables to enable and set a transient prompt,
which lets you draw a different prompt once you've entered a command and
you've moved on to the next line. This is useful if you have a fancy
two-line prompt with a bunch of info about time and git status that you
don't really need in your scrollback buffer.

Here's a screenshot. You can see how my usual prompt has two lines and
would take up a lot more space if every past command also used the full
prompt, but reducing past prompts to `🚀` or `>` makes it take up less
space.

![image](https://github.com/nushell/nushell/assets/45539777/dde8d0f5-f95f-4529-9a14-b7919bd51126)

I added the following lines to my `env.nu` to get that rocket as the
prompt initially:
```nu
$env.TRANSIENT_PROMPT_COMMAND = {|| "" }
$env.TRANSIENT_PROMPT_INDICATOR = {|| open --raw "~/.prompt-indicator" }
$env.TRANSIENT_PROMPT_INDICATOR_VI_INSERT = $env.TRANSIENT_PROMPT_INDICATOR
```

## User-Facing Changes

If you want to change a segment of the prompt, set the corresponding
`TRANSIENT_PROMPT_*` variable.

<!-- 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.
-->

## Problems/Things to Consider:
- The transient prompt clones the `Stack` at the very beginning of the
session and keeps that around. I'm not sure if that could cause
problems, but if so, it could probably take an `Arc<State>` instead.
- This isn't truly a problem, but now there's even more environment
variables, which is kinda annoying.
- There might be some performance issues with creating a new
`NushellPrompt` object and cloning the `Stack` for every segment of the
transient prompt. What's more, the transient prompt is added to the
`Reedline` object whether or not the user has enabled transient prompt,
so if there are indeed performance issues, simply disabling the
transient prompt won't help.
- Perhaps instead of a separate `TRANSIENT_PROMPT_INDICATOR_VI_INSERT`
and `TRANSIENT_PROMPT_INDICATOR_VI_NORMAL`, `TRANSIENT_PROMPT_INDICATOR`
could be used for both (if it exists). Insert and normal mode don't
really matter for previously entered commands.
2023-09-22 14:35:09 -05:00
6df001f72d Prevent cubic time on nested parentheses (#10467)
<!--
if this PR closes one or more issues, you can automatically link the PR
with
them by using one of the [*linking
keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword),
e.g.
- this PR should close #xxxx
- fixes #xxxx

you can also mention related issues, PRs or discussions!
-->

# 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.
-->

When parse_range get an item like ((((1..2)))) it would try to parse
"((((1" with a long chain of recursive parsers, namely:
- parse_value
- parse_paren_expr
- parse_full_cell_path
- parse_block
- parse_pipeline
- parse_builtin_commands
- parse_expression
- parse_math_expression
- parse_value
- ...

where `parse_paren_expr` calls `parse_range` in turn. Because at any
time in the chain `parse_paren_expr` can call `parse_range`, which will
then continue the chain, we get quadratic number of function calls, each
linear on the size of the input

By checking with the lexer that the parens are matched, we prevent the
long chain from being called on unmatched braces. Now, this is still
more quadratic than it needs to be, to fix that, we should process
parens only once, instead of on each recursive call

# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->
Speed improvements in some edge cases

# Tests + Formatting
Not sure how to test this, maybe I could add a benchmark
<!--
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` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->

# 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.
-->

# Other notes
Found using the fuzzer, by setting a timeout on max run-time. It also
found a stack-overflow on too many parentheses, which this doesn't fix.
2023-09-23 04:24:35 +12:00
4880721b73 evaluate $nu during --ide-check (#10470)
# Description

This PR fixes a bug found by @kubouch where `$nu` is not evaluated as a
constant when the `--ide-check` parameter is passed to nushell for the
LSP-like functionality. Not quite sure my changes are proper but it
seems to work!

### Before

![image](https://github.com/nushell/nushell/assets/343840/72ba28fe-74a1-450a-8a75-8d152c3a15b1)


### After

![image](https://github.com/nushell/nushell/assets/343840/1f70985b-4350-4e3f-8708-0aead3f5a505)


# 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` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->

# 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: Jakub Žádník <kubouch@gmail.com>
2023-09-22 10:53:25 -05:00
1bb953877e Improve select row perf for large N (#10355)
# Description
While reviewing #10350 I noticed that a `HashSet<usize>` was used to
deduplicate the incoming rows, which are then sorted after cloning to a
separate `Vec`. This sounds like a candidate for a `BTreeSet` which
guarantees the ordering.

In the process I removed some dead code.

- Use `BTreeSet` instead of `HashSet`
- Remove dead `skip` logic
- Use `BTreeSet` directly in `NthIterator`
- Consume `BTreeSet` through `Peekable<IntoIter>`
2023-09-21 23:51:13 +02:00
ef7ade59f3 Split up nu-protocol/src/engine/engine_state.rs (#10368)
Factor the big parts into separate files:
- `state_delta.rs`
- `state_working_set.rs`
- smaller `usage.rs`

This required adjusting the visibility of several parts.
Makes `StateDelta` transparent for the module.
Trying to reduce visibility in some other places
2023-09-21 22:53:36 +02:00
1c677c9577 Map DirectoryNotFound to FileNotFound for open command (#10089)
# Description


This PR should close #10085
Maps `DirectoryNotFound` errors to `FileNotFound`. All other errors are
left unchanged.

# User-Facing Changes

This means a user will see `FileNotFound` instead of `DirectoryNotFound`
which is more meaning full to the user.
2023-09-21 20:17:44 +02:00
1072bd06c3 Improve assertions in src/tests.rs (#10449)
# Description
Mention the expected substring in:
- `fn run_test_contains()`
- `fn test_ide_contains()`
- `fn fail_test()`


# Developer-Facing Changes
You can read the test failure to figure out what is going on, don't
necessarily have to look up the test

New look of failure
```
failures:

---- tests::test_math::broken_math stdout ----
stdout:
stderr: Error: nu::parser::incomplete_math_expression

  × Incomplete math expression.
   ╭─[/tmp/.tmpz0V8nC:1:1]
 1 │ 3 +
   ·   ┬
   ·   ╰── incomplete math expression
   ╰────


Expected error to contain: Incomplete universe
thread 'tests::test_math::broken_math' panicked at 'assertion failed: !stderr.is_empty() && stderr.contains(expected)', src/tests.rs:181:5
```
2023-09-21 20:12:36 +02:00
4aa9102523 Simplify nu! test macros. (#10403)
# Description
Unify the logic between `nu!` and `nu_with_std!`.
The inner code actually does not contain any variadic components. So it
can safely be abstracted into a function.
Similarly simplify the variadic to an array in `nu_with_plugin!`

This also seems to simplify the codegen for tests.

Comparing the size of the `/target/debug` folder after running:

```sh
cargo clean --profile dev
cargo build --workspace --tests
```

With this branch a reduction from `8.9GB` to `8.7GB`

# User-Facing Changes
None

# Tests + Formatting
No changes necessary
2023-09-21 20:11:56 +02:00
0c7a8e3634 Remove dead BSON related tests (#10458)
Those tests where behind a feature flag `bson` that is never defined in
`Cargo.toml`

Remove them.
2023-09-21 20:01:49 +02:00
addf8ca942 update the doc in toolchain.toml describing the update plan (#10453)
The *toolchain.toml* doc incorrectly stated how many releases behind
stable we will be...

It said we would be 1 release behind when actually we want to be 2
releases behind stable.
2023-09-20 20:34:25 -07:00
7cfd4d2cfa nu-table: Add table option --abbreviated (#10399)
- Added `--abbreviated`/`-a` option
- Adedd `abbreviate_if_longer_than` config opt for it.

```nu
ls | table -a 3
```

```
╭───┬────────────────────┬──────┬───────────┬──────────────╮
│ # │        name        │ type │   size    │   modified   │
├───┼────────────────────┼──────┼───────────┼──────────────┤
│ 0 │ CODE_OF_CONDUCT.md │ file │   3.4 KiB │ 4 days ago   │
│ 1 │ CONTRIBUTING.md    │ file │  18.3 KiB │ 2 weeks ago  │
│ 2 │ Cargo.lock         │ file │ 144.3 KiB │ 15 hours ago │
│ 3 │ ...                │ ...  │ ...       │ ...          │
│ 4 │ tests              │ dir  │   4.0 KiB │ 4 months ago │
│ 5 │ toolkit.nu         │ file │  14.6 KiB │ 5 days ago   │
│ 6 │ wix                │ dir  │   4.0 KiB │ 2 months ago │
╰───┴────────────────────┴──────┴───────────┴──────────────╯
```

```nu
$env | table -a 3
```

```
╭──────────────────┬──────────────────────────────────────────────────────────────────────────╮
│ BROWSER          │ firefox                                                                  │
│ CARGO            │ /home/maxim/.rustup/toolchains/1.70.0-x86_64-unknown-linux-gnu/bin/cargo │
│ CARGO_HOME       │ /home/maxim/.cargo                                                       │
│ ...              │ ...                                                                      │
│ XDG_SESSION_TYPE │ x11                                                                      │
│ XDG_VTNR         │ 7                                                                        │
│ _                │ /home/maxim/.cargo/bin/cargo                                             │
╰──────────────────┴──────────────────────────────────────────────────────────────────────────╯
```

close #10393

PS: Maybe as a separate issue (good candidate for `GOOD FIRST ISSUE`)
add a config option to change a default `...` truncation sign to a
custom? (which would be applicable not only for `--abbreviated` but all
kind of tables)

---------

Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2023-09-20 12:59:08 -05:00
4ae53d93fb new command: into value (#10427)
# Description

This new command `into value` is a command that tries to infer the type
of data you have in a table. It converts each cell to a string and then
runs a set of regular expressions on that string. This was mostly
cobbled together after looking at how polars does similar things. The
regular expressions were taken straight form polars and tweaked.

### Before
```nushell
❯ [[col1 col2 col3 col4 col5 col6]; ["1" "two" "3.4" "true" "2023-08-10 14:07:17.922050800 -05:00" "2023-09-19"]] |
  update col1 {|r| $r.col1 | into int } |
  update col3 {|r| $r.col3 | into float } |
  update col4 {|r| $r.col4 | into bool } |
  update col5 {|r| $r.col5 | into datetime } |
  update col6 {|r| $r.col6 | into datetime }
╭#┬col1┬col2┬col3┬col4┬───col5────┬───col6────╮
│0│   1│two │3.40│true│a month ago│8 hours ago│
╰─┴────┴────┴────┴────┴───────────┴───────────╯
```
or
```nushell
❯ [[col1 col2 col3 col4 col5 col6]; ["1" "two" "3.4" "true" "2023-08-10 14:07:17.922050800 -05:00" "2023-09-19"]] |
  into int col1 |
  into float col3 |
  into bool col4 |
  into datetime col5 col6
╭#┬col1┬col2┬col3┬col4┬───col5────┬───col6────╮
│0│   1│two │3.40│true│a month ago│8 hours ago│
╰─┴────┴────┴────┴────┴───────────┴───────────╯
```

### After
```nushell
❯ [[col1 col2 col3 col4 col5 col6]; ["1" "two" "3.4" "true" "2023-08-10 14:07:17.922050800 -05:00" "2023-09-19"]] | into value
╭#┬col1┬col2┬col3┬col4┬───col5────┬───col6────╮
│0│   1│two │3.40│true│a month ago│8 hours ago│
╰─┴────┴────┴────┴────┴───────────┴───────────╯
```

It's definitely not perfect. There are ways it will fail because on
regular expressions not working on all formats. My hope is that people
will pick this up and add more regular expressions and if there are
problems with the existing ones, change them. This is meant as a
"starter command" with easy entry for newcomers that are looking to chip
in and help out.

Also, some tests probably need to be added to ensure what we have now
doesn't break with updates.

# 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` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->

# 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.
-->
2023-09-20 12:57:58 -05:00
29e809ad77 allow values command to support LazyRecords (#10418)
# Description

This PR allows the `values` command to support lazy records.

closes https://github.com/nushell/nushell/issues/10417

### Before
```nushell
sys | values
Error: nu:🐚:only_supports_this_input_type

  × Input type not supported.
   ╭─[entry #1:1:1]
 1 │ sys | values
   · ─┬─   ───┬──
   ·  │       ╰── only record or table input data is supported
   ·  ╰── input type: record<host: record<name: string, os_version: string, long_os_version: string, kernel_version: string, hostname: string, uptime: duration, boot_time: string, sessions: list<any>>, cpu: table<name: string, brand: string, freq: int, cpu_usage: float, load_average: string, vendor_id: string>, disks: table<device: string, type: string, mount: string, total: filesize, free: filesize, removable: bool, kind: string>, mem: record<total: filesize, free: filesize, used: filesize, available: filesize, swap total: filesize, swap free: filesize, swap used: filesize>, temp: list<any>, net: table<name: string, sent: filesize, recv: filesize>>
   ╰────
```

### After
```nushell
❯ sys | values
╭─┬─────────────────╮
│0│{record 8 fields}│
│1│[table 16 rows]  │
│2│[table 1 row]    │
│3│{record 7 fields}│
│4│[list 0 items]   │
│5│[table 5 rows]   │
╰─┴─────────────────╯
```

# 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` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->

# 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.
-->
2023-09-20 12:57:29 -05:00
e1c6be0682 Fix tilde-expansion for multi-byte unicode chars (#10434)
<!--
if this PR closes one or more issues, you can automatically link the PR
with
them by using one of the [*linking
keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword),
e.g.
- this PR should close #xxxx
- fixes #xxxx

you can also mention related issues, PRs or discussions!
-->

# 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.
-->

Fixes #10365

Use bytes() instead of chars() to get an actual index that can be used
with file.split_at(). utf8 is safe to process bytewise, since an ascii
character can never be mistaken for a non-ascii character


# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->

# Tests + Formatting

- [x] 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`
to check that you're using the standard code style
- [x] `cargo test --workspace` to check that all tests pass (on Windows
make sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- [x] `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library
<!--
> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->

# 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.
-->
2023-09-21 04:04:28 +12:00
bf40f035f6 don't overrite arg's type if it's annotated explicitly (#10424)
# Description
Fixes: #10410 

So the following script is possible:
```nushell
def a [b: any = null] { let b = ($b | default "default_b"); }
a "given_b"
```

## About the change
When parsing signature, and nushell meets something like `a: any`, it
force the parser to treat `a` as `any` type. This is what
`arg_explicit_type` means, it's only set when we goes into
`ParseMode::TypeMode`, and it will be reset to `false` if the token goes
to next argument.

so, when we have something like this: `def a [b: any = null] { $b }`,
the type of `$b` won't be overwritten.

But if we have something like this: `def a [b = null] { $b }`, the type
of `$b` is not annotated, so we make it to be `nothing`(which is the
type of null)
2023-09-21 03:58:29 +12:00
989a14709c optimize aarch64 when able (#10433)
# Description

This PR optimizes for the aarch64 m1 processor when able.

# 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` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->

# 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.
-->
2023-09-21 03:57:07 +12:00
8d8b44342b Fix exponential parser time on sequence of [[[[ (#10439)
<!--
if this PR closes one or more issues, you can automatically link the PR
with
them by using one of the [*linking
keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword),
e.g.
- this PR should close #xxxx
- fixes #xxxx

you can also mention related issues, PRs or discussions!
-->

# 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.
-->

Before this change, parsing `[[[[[[[[[[[[[[[[[[[[[[` would cause nushell
to consume several gigabytes of memory, now it should be linear in time.

The old code first tried parsing the head of the table as a list and
then after that it checked if it got more arguments. If it didn't, it
throws away the previous result and tries to parse the whole thing as a
list, which means we call `parse_list_expression` twice for each call to
`parse_table_expression`, resulting in the exponential growth

The fix is to simply check that we have all the arguments we need before
parsing the head of the table, so we know that we will either call
parse_list_expression only on sub-expressions or on the whole thing,
never both.

Fixes #10438


# User-Facing Changes
Should give a noticable speedup when typing a sequence of `[[[[[[` open
brackets
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->

# Tests + Formatting

I would like to add tests, but I'm not sure how to do that without
crashing CI with OOM on regression

- [x] Don't forget to add tests that cover your changes.
- [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`
to check that you're using the standard code style
- [x] `cargo test --workspace` to check that all tests pass (on Windows
make sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- [x] `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library
<!--
> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->

# 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.
2023-09-21 03:53:48 +12:00
7980ad9f7f update lock file (#10437) 2023-09-20 17:20:40 +08:00
af15f794b4 Bump to 0.85.1 development version (#10431) 2023-09-20 18:38:42 +12:00
312 changed files with 8319 additions and 5600 deletions

View File

@ -26,3 +26,8 @@ rustflags = ["-C", "link-args=-stack:10000000", "-C", "target-feature=+crt-stati
# [target.aarch64-apple-darwin]
# linker = "clang"
# rustflags = ["-C", "link-arg=-fuse-ld=mold"]
[target.aarch64-apple-darwin]
# We can guarantee that this target will always run on a CPU with _at least_
# these capabilities, so let's optimize for them
rustflags = ["-Ctarget-cpu=apple-m1"]

1
.github/.typos.toml vendored
View File

@ -11,3 +11,4 @@ Plasticos = "Plasticos"
IIF = "IIF"
numer = "numer"
ratatui = "ratatui"
doas = "doas"

View File

@ -39,7 +39,7 @@ jobs:
uses: hustcer/setup-nu@v3.6
if: github.repository == 'nushell/nightly'
with:
version: 0.84.0
version: 0.85.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@ -66,8 +66,8 @@ jobs:
git push origin --tags
}
release:
name: Release
standard:
name: Std
needs: prepare
strategy:
fail-fast: false
@ -117,10 +117,10 @@ jobs:
target_rustflags: ''
- target: armv7-unknown-linux-gnueabihf
os: ubuntu-20.04
target_rustflags: '--exclude=nu-cmd-dataframe'
target_rustflags: ''
- target: riscv64gc-unknown-linux-gnu
os: ubuntu-20.04
target_rustflags: '--exclude=nu-cmd-dataframe'
target_rustflags: ''
runs-on: ${{matrix.os}}
@ -128,6 +128,7 @@ jobs:
- uses: actions/checkout@v4
with:
ref: main
fetch-depth: 0
- name: Update Rust Toolchain Target
run: |
@ -135,13 +136,11 @@ jobs:
- name: Setup Rust toolchain and cache
uses: actions-rust-lang/setup-rust-toolchain@v1.5.0
with:
rustflags: ''
- name: Setup Nushell
uses: hustcer/setup-nu@v3.6
with:
version: 0.84.0
version: 0.85.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@ -149,6 +148,118 @@ jobs:
id: nu
run: nu .github/workflows/release-pkg.nu
env:
RELEASE_TYPE: standard
OS: ${{ matrix.os }}
REF: ${{ github.ref }}
TARGET: ${{ matrix.target }}
_EXTRA_: ${{ matrix.extra }}
TARGET_RUSTFLAGS: ${{ matrix.target_rustflags }}
- name: Create an Issue for Release Failure
if: ${{ failure() }}
uses: JasonEtco/create-an-issue@v2.9.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
update_existing: true
search_existing: open
filename: .github/AUTO_ISSUE_TEMPLATE/nightly-build-fail.md
- name: Set Outputs of Short SHA
id: vars
run: |
echo "date=$(date -u +'%Y-%m-%d')" >> $GITHUB_OUTPUT
sha_short=$(git rev-parse --short HEAD)
echo "sha_short=${sha_short:0:7}" >> $GITHUB_OUTPUT
# REF: https://github.com/marketplace/actions/gh-release
# Create a release only in nushell/nightly repo
- name: Publish Archive
uses: softprops/action-gh-release@v0.1.15
if: ${{ startsWith(github.repository, 'nushell/nightly') }}
with:
prerelease: true
files: ${{ steps.nu.outputs.archive }}
tag_name: nightly-${{ steps.vars.outputs.sha_short }}
name: Nu-nightly-${{ steps.vars.outputs.date }}-${{ steps.vars.outputs.sha_short }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
full:
name: Full
needs: prepare
strategy:
fail-fast: false
matrix:
target:
- aarch64-apple-darwin
- x86_64-apple-darwin
- x86_64-pc-windows-msvc
- aarch64-pc-windows-msvc
- x86_64-unknown-linux-gnu
- x86_64-unknown-linux-musl
- aarch64-unknown-linux-gnu
extra: ['bin']
include:
- target: aarch64-apple-darwin
os: macos-latest
target_rustflags: '--features=dataframe,extra'
- target: x86_64-apple-darwin
os: macos-latest
target_rustflags: '--features=dataframe,extra'
- target: x86_64-pc-windows-msvc
extra: 'bin'
os: windows-latest
target_rustflags: '--features=dataframe,extra'
- target: x86_64-pc-windows-msvc
extra: msi
os: windows-latest
target_rustflags: '--features=dataframe,extra'
- target: aarch64-pc-windows-msvc
extra: 'bin'
os: windows-latest
target_rustflags: '--features=dataframe,extra'
- target: aarch64-pc-windows-msvc
extra: msi
os: windows-latest
target_rustflags: '--features=dataframe,extra'
- target: x86_64-unknown-linux-gnu
os: ubuntu-20.04
target_rustflags: '--features=dataframe,extra'
- target: x86_64-unknown-linux-musl
os: ubuntu-20.04
target_rustflags: '--features=dataframe,extra'
- target: aarch64-unknown-linux-gnu
os: ubuntu-20.04
target_rustflags: '--features=dataframe,extra'
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v4
with:
ref: main
fetch-depth: 0
- 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.5.0
- name: Setup Nushell
uses: hustcer/setup-nu@v3.6
with:
version: 0.85.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Release Nu Binary
id: nu
run: nu .github/workflows/release-pkg.nu
env:
RELEASE_TYPE: full
OS: ${{ matrix.os }}
REF: ${{ github.ref }}
TARGET: ${{ matrix.target }}
@ -206,7 +317,7 @@ jobs:
- name: Setup Nushell
uses: hustcer/setup-nu@v3.6
with:
version: 0.84.0
version: 0.85.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -51,11 +51,26 @@ let dist = $'($env.GITHUB_WORKSPACE)/output'
let version = (open Cargo.toml | get package.version)
print $'Debugging info:'
print { version: $version, bin: $bin, os: $os, target: $target, src: $src, flags: $flags, dist: $dist }; hr-line -b
print { version: $version, bin: $bin, os: $os, releaseType: $env.RELEASE_TYPE, target: $target, src: $src, flags: $flags, dist: $dist }; hr-line -b
# Rename the full release name so that we won't break the existing scripts for standard release downloading, such as:
# curl -s https://api.github.com/repos/chmln/sd/releases/latest | grep browser_download_url | cut -d '"' -f 4 | grep x86_64-unknown-linux-musl
const FULL_RLS_NAMING = {
x86_64-apple-darwin: 'x86_64-darwin-full',
aarch64-apple-darwin: 'aarch64-darwin-full',
x86_64-unknown-linux-gnu: 'x86_64-linux-gnu-full',
x86_64-pc-windows-msvc: 'x86_64-windows-msvc-full',
x86_64-unknown-linux-musl: 'x86_64-linux-musl-full',
aarch64-unknown-linux-gnu: 'aarch64-linux-gnu-full',
aarch64-pc-windows-msvc: 'aarch64-windows-msvc-full',
riscv64gc-unknown-linux-gnu: 'riscv64-linux-gnu-full',
armv7-unknown-linux-gnueabihf: 'armv7-linux-gnueabihf-full',
}
# $env
let USE_UBUNTU = 'ubuntu-20.04'
let FULL_NAME = $FULL_RLS_NAMING | get -i $target | default 'unknown-target-full'
print $'(char nl)Packaging ($bin) v($version) for ($target) in ($src)...'; hr-line -b
if not ('Cargo.lock' | path exists) { cargo generate-lockfile }
@ -141,7 +156,7 @@ cd $dist; print $'(char nl)Creating release archive...'; hr-line
if $os in [$USE_UBUNTU, 'macos-latest'] {
let files = (ls | get name)
let dest = $'($bin)-($version)-($target)'
let dest = if $env.RELEASE_TYPE == 'full' { $'($bin)-($version)-($FULL_NAME)' } else { $'($bin)-($version)-($target)' }
let archive = $'($dist)/($dest).tar.gz'
mkdir $dest
@ -156,7 +171,7 @@ if $os in [$USE_UBUNTU, 'macos-latest'] {
} else if $os == 'windows-latest' {
let releaseStem = $'($bin)-($version)-($target)'
let releaseStem = if $env.RELEASE_TYPE == 'full' { $'($bin)-($version)-($FULL_NAME)' } else { $'($bin)-($version)-($target)' }
print $'(char nl)Download less related stuffs...'; hr-line
aria2c https://github.com/jftuga/less-Windows/releases/download/less-v608/less.exe -o less.exe
@ -173,7 +188,7 @@ if $os in [$USE_UBUNTU, 'macos-latest'] {
cargo install cargo-wix --version 0.3.4
cargo wix --no-build --nocapture --package nu --output $wixRelease
# Workaround for https://github.com/softprops/action-gh-release/issues/280
let archive = ($wixRelease | str replace -a '\' '/')
let archive = ($wixRelease | str replace --all '\' '/')
print $'archive: ---> ($archive)';
echo $"archive=($archive)" | save --append $env.GITHUB_OUTPUT
@ -185,7 +200,7 @@ if $os in [$USE_UBUNTU, 'macos-latest'] {
let pkg = (ls -f $archive | get name)
if not ($pkg | is-empty) {
# Workaround for https://github.com/softprops/action-gh-release/issues/280
let archive = ($pkg | get 0 | str replace -a '\' '/')
let archive = ($pkg | get 0 | str replace --all '\' '/')
print $'archive: ---> ($archive)'
echo $"archive=($archive)" | save --append $env.GITHUB_OUTPUT
}

View File

@ -14,8 +14,8 @@ defaults:
shell: bash
jobs:
all:
name: All
standard:
name: Std
strategy:
matrix:
@ -64,10 +64,10 @@ jobs:
target_rustflags: ''
- target: armv7-unknown-linux-gnueabihf
os: ubuntu-20.04
target_rustflags: '--exclude=nu-cmd-dataframe'
target_rustflags: ''
- target: riscv64gc-unknown-linux-gnu
os: ubuntu-20.04
target_rustflags: '--exclude=nu-cmd-dataframe'
target_rustflags: ''
runs-on: ${{matrix.os}}
@ -80,13 +80,11 @@ jobs:
- name: Setup Rust toolchain and cache
uses: actions-rust-lang/setup-rust-toolchain@v1.5.0
with:
rustflags: ''
- name: Setup Nushell
uses: hustcer/setup-nu@v3.6
with:
version: 0.84.0
version: 0.85.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@ -94,6 +92,95 @@ jobs:
id: nu
run: nu .github/workflows/release-pkg.nu
env:
RELEASE_TYPE: standard
OS: ${{ matrix.os }}
REF: ${{ github.ref }}
TARGET: ${{ matrix.target }}
_EXTRA_: ${{ matrix.extra }}
TARGET_RUSTFLAGS: ${{ matrix.target_rustflags }}
# REF: https://github.com/marketplace/actions/gh-release
- name: Publish Archive
uses: softprops/action-gh-release@v0.1.15
if: ${{ startsWith(github.ref, 'refs/tags/') }}
with:
draft: true
files: ${{ steps.nu.outputs.archive }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
full:
name: Full
strategy:
fail-fast: false
matrix:
target:
- aarch64-apple-darwin
- x86_64-apple-darwin
- x86_64-pc-windows-msvc
- aarch64-pc-windows-msvc
- x86_64-unknown-linux-gnu
- x86_64-unknown-linux-musl
- aarch64-unknown-linux-gnu
extra: ['bin']
include:
- target: aarch64-apple-darwin
os: macos-latest
target_rustflags: '--features=dataframe,extra'
- target: x86_64-apple-darwin
os: macos-latest
target_rustflags: '--features=dataframe,extra'
- target: x86_64-pc-windows-msvc
extra: 'bin'
os: windows-latest
target_rustflags: '--features=dataframe,extra'
- target: x86_64-pc-windows-msvc
extra: msi
os: windows-latest
target_rustflags: '--features=dataframe,extra'
- target: aarch64-pc-windows-msvc
extra: 'bin'
os: windows-latest
target_rustflags: '--features=dataframe,extra'
- target: aarch64-pc-windows-msvc
extra: msi
os: windows-latest
target_rustflags: '--features=dataframe,extra'
- target: x86_64-unknown-linux-gnu
os: ubuntu-20.04
target_rustflags: '--features=dataframe,extra'
- target: x86_64-unknown-linux-musl
os: ubuntu-20.04
target_rustflags: '--features=dataframe,extra'
- target: aarch64-unknown-linux-gnu
os: ubuntu-20.04
target_rustflags: '--features=dataframe,extra'
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v4
- 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.5.0
- name: Setup Nushell
uses: hustcer/setup-nu@v3.6
with:
version: 0.85.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Release Nu Binary
id: nu
run: nu .github/workflows/release-pkg.nu
env:
RELEASE_TYPE: full
OS: ${{ matrix.os }}
REF: ${{ github.ref }}
TARGET: ${{ matrix.target }}

View File

@ -10,6 +10,6 @@ jobs:
uses: actions/checkout@v4
- name: Check spelling
uses: crate-ci/typos@v1.16.11
uses: crate-ci/typos@v1.16.19
with:
config: ./.github/.typos.toml

View File

@ -7,7 +7,7 @@ on:
inputs:
tag_name:
description: 'Specific tag name'
required: true
required: true
type: string
jobs:
@ -20,6 +20,9 @@ jobs:
uses: vedantmgoyal2009/winget-releaser@v2
with:
identifier: Nushell.Nushell
# Exclude all `*-msvc-full.msi` full release files,
# and only the default `*msvc.msi` files will be included
installers-regex: 'msvc\.msi$'
version: ${{ inputs.tag_name || github.event.release.tag_name }}
release-tag: ${{ inputs.tag_name || github.event.release.tag_name }}
token: ${{ secrets.NUSHELL_PAT }}

View File

@ -46,7 +46,7 @@ cargo build
### Tests
It is a good practice to cover your changes with a test. Also, try to think about corner cases and various ways how your changes could break. Cover those in the tests as well.
It is good practice to cover your changes with a test. Also, try to think about corner cases and various ways how your changes could break. Cover those in the tests as well.
Tests can be found in different places:
* `/tests`
@ -58,7 +58,7 @@ Most of the tests are built upon the `nu-test-support` crate. For testing specif
### Useful Commands
As Nushell is build using a cargo workspace consisting of multiple crates keep in mind that you may need to pass additional flags compared to how you may be used to it from a single crate project.
As Nushell is built using a cargo workspace consisting of multiple crates keep in mind that you may need to pass additional flags compared to how you may be used to it from a single crate project.
Read cargo's documentation for more details: https://doc.rust-lang.org/cargo/reference/workspaces.html
- Build and run Nushell:

1101
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -11,7 +11,7 @@ license = "MIT"
name = "nu"
repository = "https://github.com/nushell/nushell"
rust-version = "1.60"
version = "0.85.0"
version = "0.86.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -46,28 +46,28 @@ members = [
]
[dependencies]
nu-cli = { path = "./crates/nu-cli", version = "0.85.0" }
nu-color-config = { path = "./crates/nu-color-config", version = "0.85.0" }
nu-cmd-base = { path = "./crates/nu-cmd-base", version = "0.85.0" }
nu-cmd-lang = { path = "./crates/nu-cmd-lang", version = "0.85.0" }
nu-cmd-dataframe = { path = "./crates/nu-cmd-dataframe", version = "0.85.0", features = ["dataframe"], optional = true }
nu-cmd-extra = { path = "./crates/nu-cmd-extra", version = "0.85.0", optional = true }
nu-command = { path = "./crates/nu-command", version = "0.85.0" }
nu-engine = { path = "./crates/nu-engine", version = "0.85.0" }
nu-explore = { path = "./crates/nu-explore", version = "0.85.0" }
nu-json = { path = "./crates/nu-json", version = "0.85.0" }
nu-parser = { path = "./crates/nu-parser", version = "0.85.0" }
nu-path = { path = "./crates/nu-path", version = "0.85.0" }
nu-plugin = { path = "./crates/nu-plugin", optional = true, version = "0.85.0" }
nu-pretty-hex = { path = "./crates/nu-pretty-hex", version = "0.85.0" }
nu-protocol = { path = "./crates/nu-protocol", version = "0.85.0" }
nu-system = { path = "./crates/nu-system", version = "0.85.0" }
nu-table = { path = "./crates/nu-table", version = "0.85.0" }
nu-term-grid = { path = "./crates/nu-term-grid", version = "0.85.0" }
nu-std = { path = "./crates/nu-std", version = "0.85.0" }
nu-utils = { path = "./crates/nu-utils", version = "0.85.0" }
nu-cli = { path = "./crates/nu-cli", version = "0.86.0" }
nu-color-config = { path = "./crates/nu-color-config", version = "0.86.0" }
nu-cmd-base = { path = "./crates/nu-cmd-base", version = "0.86.0" }
nu-cmd-lang = { path = "./crates/nu-cmd-lang", version = "0.86.0" }
nu-cmd-dataframe = { path = "./crates/nu-cmd-dataframe", version = "0.86.0", features = ["dataframe"], optional = true }
nu-cmd-extra = { path = "./crates/nu-cmd-extra", version = "0.86.0", optional = true }
nu-command = { path = "./crates/nu-command", version = "0.86.0" }
nu-engine = { path = "./crates/nu-engine", version = "0.86.0" }
nu-explore = { path = "./crates/nu-explore", version = "0.86.0" }
nu-json = { path = "./crates/nu-json", version = "0.86.0" }
nu-parser = { path = "./crates/nu-parser", version = "0.86.0" }
nu-path = { path = "./crates/nu-path", version = "0.86.0" }
nu-plugin = { path = "./crates/nu-plugin", optional = true, version = "0.86.0" }
nu-pretty-hex = { path = "./crates/nu-pretty-hex", version = "0.86.0" }
nu-protocol = { path = "./crates/nu-protocol", version = "0.86.0" }
nu-system = { path = "./crates/nu-system", version = "0.86.0" }
nu-table = { path = "./crates/nu-table", version = "0.86.0" }
nu-term-grid = { path = "./crates/nu-term-grid", version = "0.86.0" }
nu-std = { path = "./crates/nu-std", version = "0.86.0" }
nu-utils = { path = "./crates/nu-utils", version = "0.86.0" }
nu-ansi-term = "0.49.0"
reedline = { version = "0.24.0", features = ["bashisms", "sqlite"] }
reedline = { version = "0.25.0", features = ["bashisms", "sqlite"] }
crossterm = "0.27"
ctrlc = "3.4"
@ -95,7 +95,7 @@ nix = { version = "0.27", default-features = false, features = [
] }
[dev-dependencies]
nu-test-support = { path = "./crates/nu-test-support", version = "0.85.0" }
nu-test-support = { path = "./crates/nu-test-support", version = "0.86.0" }
assert_cmd = "2.0"
criterion = "0.5"
pretty_assertions = "1.4"
@ -117,7 +117,7 @@ stable = ["default"]
wasi = ["nu-cmd-lang/wasi"]
# NOTE: individual features are also passed to `nu-cmd-lang` that uses them to generate the feature matrix in the `version` command
# Enable to statically link OpenSSL (perl is required, to build OpenSSL https://docs.rs/openssl/latest/openssl/);
# Enable to statically link OpenSSL (perl is required, to build OpenSSL https://docs.rs/openssl/latest/openssl/);
# otherwise the system version will be used. Not enabled by default because it takes a while to build
static-link-openssl = ["dep:openssl", "nu-cmd-lang/static-link-openssl"]
@ -164,8 +164,9 @@ bench = false
# To use a development version of a dependency please use a global override here
# changing versions in each sub-crate of the workspace is tedious
[patch.crates-io]
# reedline = { git = "https://github.com/nushell/reedline.git", branch = "main"}
# reedline = { git = "https://github.com/nushell/reedline.git", branch = "main" }
# nu-ansi-term = {git = "https://github.com/nushell/nu-ansi-term.git", branch = "main"}
# uu_cp = { git = "https://github.com/uutils/coreutils.git", branch = "main" }
# Criterion benchmarking setup
# Run all benchmarks with `cargo bench`

View File

@ -220,6 +220,7 @@ Please submit an issue or PR to be added to this list.
- [atuin](https://github.com/ellie/atuin)
- [clap](https://github.com/clap-rs/clap/tree/master/clap_complete_nushell)
- [Dorothy](http://github.com/bevry/dorothy)
- [Direnv](https://github.com/direnv/direnv/blob/master/docs/hook.md#nushell)
## Contributing

View File

@ -5,27 +5,27 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cli"
edition = "2021"
license = "MIT"
name = "nu-cli"
version = "0.85.0"
version = "0.86.0"
[lib]
bench = false
[dev-dependencies]
nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.85.0" }
nu-command = { path = "../nu-command", version = "0.85.0" }
nu-test-support = { path = "../nu-test-support", version = "0.85.0" }
nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.86.0" }
nu-command = { path = "../nu-command", version = "0.86.0" }
nu-test-support = { path = "../nu-test-support", version = "0.86.0" }
rstest = { version = "0.18.1", default-features = false }
[dependencies]
nu-cmd-base = { path = "../nu-cmd-base", version = "0.85.0" }
nu-engine = { path = "../nu-engine", version = "0.85.0" }
nu-path = { path = "../nu-path", version = "0.85.0" }
nu-parser = { path = "../nu-parser", version = "0.85.0" }
nu-protocol = { path = "../nu-protocol", version = "0.85.0" }
nu-utils = { path = "../nu-utils", version = "0.85.0" }
nu-color-config = { path = "../nu-color-config", version = "0.85.0" }
nu-cmd-base = { path = "../nu-cmd-base", version = "0.86.0" }
nu-engine = { path = "../nu-engine", version = "0.86.0" }
nu-path = { path = "../nu-path", version = "0.86.0" }
nu-parser = { path = "../nu-parser", version = "0.86.0" }
nu-protocol = { path = "../nu-protocol", version = "0.86.0" }
nu-utils = { path = "../nu-utils", version = "0.86.0" }
nu-color-config = { path = "../nu-color-config", version = "0.86.0" }
nu-ansi-term = "0.49.0"
reedline = { version = "0.24.0", features = ["bashisms", "sqlite"] }
reedline = { version = "0.25.0", features = ["bashisms", "sqlite"] }
chrono = { default-features = false, features = ["std"], version = "0.4" }
crossterm = "0.27"
@ -36,8 +36,10 @@ log = "0.4"
miette = { version = "5.10", features = ["fancy-no-backtrace"] }
once_cell = "1.18"
percent-encoding = "2"
pathdiff = "0.2"
sysinfo = "0.29"
unicode-segmentation = "1.10"
uuid = { version = "1.4.1", features = ["v4"] }
[features]
plugin = []

View File

@ -91,7 +91,7 @@ impl Command for Commandline {
from_type: "string".to_string(),
span: cmd.span(),
help: Some(format!(
r#"string "{cmd_str}" does not represent a valid integer"#
r#"string "{cmd_str}" does not represent a valid int"#
)),
})
}

View File

@ -1,3 +1,4 @@
use crossterm::execute;
use crossterm::QueueableCommand;
use crossterm::{event::Event, event::KeyCode, event::KeyEvent, terminal};
use nu_protocol::ast::Call;
@ -69,6 +70,32 @@ pub fn print_events(engine_state: &EngineState) -> Result<Value, ShellError> {
stdout().flush()?;
terminal::enable_raw_mode()?;
if config.use_kitty_protocol {
if let Ok(false) = crossterm::terminal::supports_keyboard_enhancement() {
println!("WARN: The terminal doesn't support use_kitty_protocol config.\r");
}
// enable kitty protocol
//
// Note that, currently, only the following support this protocol:
// * [kitty terminal](https://sw.kovidgoyal.net/kitty/)
// * [foot terminal](https://codeberg.org/dnkl/foot/issues/319)
// * [WezTerm terminal](https://wezfurlong.org/wezterm/config/lua/config/enable_kitty_keyboard.html)
// * [notcurses library](https://github.com/dankamongmen/notcurses/issues/2131)
// * [neovim text editor](https://github.com/neovim/neovim/pull/18181)
// * [kakoune text editor](https://github.com/mawww/kakoune/issues/4103)
// * [dte text editor](https://gitlab.com/craigbarnes/dte/-/issues/138)
//
// Refer to https://sw.kovidgoyal.net/kitty/keyboard-protocol/ if you're curious.
let _ = execute!(
stdout(),
crossterm::event::PushKeyboardEnhancementFlags(
crossterm::event::KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES
)
);
}
let mut stdout = std::io::BufWriter::new(std::io::stderr());
loop {
@ -95,6 +122,14 @@ pub fn print_events(engine_state: &EngineState) -> Result<Value, ShellError> {
stdout.queue(crossterm::style::Print("\r\n"))?;
stdout.flush()?;
}
if config.use_kitty_protocol {
let _ = execute!(
std::io::stdout(),
crossterm::event::PopKeyboardEnhancementFlags
);
}
terminal::disable_raw_mode()?;
Ok(Value::nothing(Span::unknown()))

View File

@ -234,7 +234,7 @@ pub fn is_passthrough_command(working_set_file_contents: &[(Vec<u8>, usize, usiz
let cur_pos = find_non_whitespace_index(contents, last_pipe_pos);
let result = match contents.get(cur_pos..) {
Some(contents) => contents.starts_with(b"sudo "),
Some(contents) => contents.starts_with(b"sudo ") || contents.starts_with(b"doas "),
None => false,
};
if result {

View File

@ -136,7 +136,9 @@ impl NuCompleter {
for (flat_idx, flat) in flattened.iter().enumerate() {
let is_passthrough_command = spans
.first()
.filter(|content| content.as_str() == "sudo")
.filter(|content| {
content.as_str() == "sudo" || content.as_str() == "doas"
})
.is_some();
// Read the current spam to string
let current_span = working_set.get_span_contents(flat.0).to_vec();

View File

@ -0,0 +1,160 @@
use crate::completions::{matches, CompletionOptions};
use nu_path::home_dir;
use std::path::{is_separator, Component, Path, PathBuf, MAIN_SEPARATOR as SEP};
fn complete_rec(
partial: &[String],
cwd: &Path,
options: &CompletionOptions,
dir: bool,
isdir: bool,
) -> Vec<PathBuf> {
let mut completions = vec![];
if let Ok(result) = cwd.read_dir() {
for entry in result.filter_map(|e| e.ok()) {
let entry_name = entry.file_name().to_string_lossy().into_owned();
let path = entry.path();
if !dir || path.is_dir() {
match partial.first() {
Some(base) if matches(base, &entry_name, options) => {
let partial = &partial[1..];
if !partial.is_empty() || isdir {
completions.extend(complete_rec(partial, &path, options, dir, isdir))
} else {
completions.push(path)
}
}
None => completions.push(path),
_ => {}
}
}
}
}
completions
}
enum OriginalCwd {
None,
Home(PathBuf),
Some(PathBuf),
// referencing a single local file
Local(PathBuf),
}
impl OriginalCwd {
fn apply(&self, p: &Path) -> String {
let mut ret = match self {
Self::None => p.to_string_lossy().into_owned(),
Self::Some(base) => pathdiff::diff_paths(p, base)
.unwrap_or(p.to_path_buf())
.to_string_lossy()
.into_owned(),
Self::Home(home) => match p.strip_prefix(home) {
Ok(suffix) => format!("~{}{}", SEP, suffix.to_string_lossy()),
_ => p.to_string_lossy().into_owned(),
},
Self::Local(base) => Path::new(".")
.join(pathdiff::diff_paths(p, base).unwrap_or(p.to_path_buf()))
.to_string_lossy()
.into_owned(),
};
if p.is_dir() {
ret.push(SEP);
}
ret
}
}
fn surround_remove(partial: &str) -> String {
for c in ['`', '"', '\''] {
if partial.starts_with(c) {
let ret = partial.strip_prefix(c).unwrap_or(partial);
return match ret.split(c).collect::<Vec<_>>()[..] {
[inside] => inside.to_string(),
[inside, outside] if inside.ends_with(is_separator) => format!("{inside}{outside}"),
_ => ret.to_string(),
};
}
}
partial.to_string()
}
pub fn complete_item(
want_directory: bool,
span: nu_protocol::Span,
partial: &str,
cwd: &str,
options: &CompletionOptions,
) -> Vec<(nu_protocol::Span, String)> {
let partial = surround_remove(partial);
let isdir = partial.ends_with(is_separator);
let cwd_pathbuf = Path::new(cwd).to_path_buf();
let mut original_cwd = OriginalCwd::None;
let mut components = Path::new(&partial).components().peekable();
let mut cwd = match components.peek().cloned() {
Some(c @ Component::Prefix(..)) => {
// windows only by definition
components.next();
if let Some(Component::RootDir) = components.peek().cloned() {
components.next();
};
[c, Component::RootDir].iter().collect()
}
Some(c @ Component::RootDir) => {
components.next();
PathBuf::from(c.as_os_str())
}
Some(Component::Normal(home)) if home.to_string_lossy() == "~" => {
components.next();
original_cwd = OriginalCwd::Home(home_dir().unwrap_or(cwd_pathbuf.clone()));
home_dir().unwrap_or(cwd_pathbuf)
}
Some(Component::CurDir) => {
components.next();
original_cwd = match components.peek().cloned() {
Some(Component::Normal(_)) | None => OriginalCwd::Local(cwd_pathbuf.clone()),
_ => OriginalCwd::Some(cwd_pathbuf.clone()),
};
cwd_pathbuf
}
_ => {
original_cwd = OriginalCwd::Some(cwd_pathbuf.clone());
cwd_pathbuf
}
};
let mut partial = vec![];
for component in components {
match component {
Component::Prefix(..) => unreachable!(),
Component::RootDir => unreachable!(),
Component::CurDir => {}
Component::ParentDir => {
if partial.pop().is_none() {
cwd.pop();
}
}
Component::Normal(c) => partial.push(c.to_string_lossy().into_owned()),
}
}
complete_rec(partial.as_slice(), &cwd, options, want_directory, isdir)
.into_iter()
.map(|p| (span, escape_path(original_cwd.apply(&p), want_directory)))
.collect()
}
// Fix files or folders with quotes or hashes
pub fn escape_path(path: String, dir: bool) -> String {
let filename_contaminated = !dir && path.contains(['\'', '"', ' ', '#', '(', ')']);
let dirname_contaminated = dir && path.contains(['\'', '"', ' ', '#']);
if filename_contaminated || dirname_contaminated || path.parse::<f64>().is_ok() {
format!("`{path}`")
} else {
path
}
}

View File

@ -1,17 +1,12 @@
use crate::completions::{matches, Completer, CompletionOptions};
use crate::completions::{completion_common::complete_item, Completer, CompletionOptions, SortBy};
use nu_protocol::{
engine::{EngineState, StateWorkingSet},
levenshtein_distance, Span,
};
use reedline::Suggestion;
use std::fs;
use std::path::Path;
use std::path::{Path, MAIN_SEPARATOR as SEP};
use std::sync::Arc;
use super::{partial_from, prepend_base_dir, SortBy};
const SEP: char = std::path::MAIN_SEPARATOR;
#[derive(Clone)]
pub struct DirectoryCompletion {
engine_state: Arc<EngineState>,
@ -33,23 +28,27 @@ impl Completer for DirectoryCompletion {
_: usize,
options: &CompletionOptions,
) -> Vec<Suggestion> {
let cwd = self.engine_state.current_work_dir();
let partial = String::from_utf8_lossy(&prefix).to_string();
// Filter only the folders
let output: Vec<_> = directory_completion(span, &partial, &cwd, options)
.into_iter()
.map(move |x| Suggestion {
value: x.1,
description: None,
extra: None,
span: reedline::Span {
start: x.0.start - offset,
end: x.0.end - offset,
},
append_whitespace: false,
})
.collect();
let output: Vec<_> = directory_completion(
span,
&partial,
&self.engine_state.current_work_dir(),
options,
)
.into_iter()
.map(move |x| Suggestion {
value: x.1,
description: None,
extra: None,
span: reedline::Span {
start: x.0.start - offset,
end: x.0.end - offset,
},
append_whitespace: false,
})
.collect();
output
}
@ -111,60 +110,5 @@ pub fn directory_completion(
cwd: &str,
options: &CompletionOptions,
) -> Vec<(nu_protocol::Span, String)> {
let original_input = partial;
let (base_dir_name, partial) = partial_from(partial);
let base_dir = nu_path::expand_path_with(&base_dir_name, cwd);
// This check is here as base_dir.read_dir() with base_dir == "" will open the current dir
// which we don't want in this case (if we did, base_dir would already be ".")
if base_dir == Path::new("") {
return Vec::new();
}
if let Ok(result) = base_dir.read_dir() {
return result
.filter_map(|entry| {
entry.ok().and_then(|entry| {
if let Ok(metadata) = fs::metadata(entry.path()) {
if metadata.is_dir() {
let mut file_name = entry.file_name().to_string_lossy().into_owned();
if matches(&partial, &file_name, options) {
let mut path = if prepend_base_dir(original_input, &base_dir_name) {
format!("{base_dir_name}{file_name}")
} else {
file_name.to_string()
};
if entry.path().is_dir() {
path.push(SEP);
file_name.push(SEP);
}
// Fix files or folders with quotes or hash
if path.contains('\'')
|| path.contains('"')
|| path.contains(' ')
|| path.contains('#')
{
path = format!("`{path}`");
}
Some((span, path))
} else {
None
}
} else {
None
}
} else {
None
}
})
})
.collect();
}
Vec::new()
complete_item(true, span, partial, cwd, options)
}

View File

@ -1,13 +1,13 @@
use crate::completions::{
file_path_completion, partial_from, Completer, CompletionOptions, SortBy,
};
use crate::completions::{file_path_completion, Completer, CompletionOptions, SortBy};
use nu_protocol::{
engine::{EngineState, StateWorkingSet},
Span,
};
use reedline::Suggestion;
use std::sync::Arc;
const SEP: char = std::path::MAIN_SEPARATOR;
use std::{
path::{is_separator, MAIN_SEPARATOR as SEP, MAIN_SEPARATOR_STR},
sync::Arc,
};
#[derive(Clone)]
pub struct DotNuCompletion {
@ -30,9 +30,16 @@ impl Completer for DotNuCompletion {
_: usize,
options: &CompletionOptions,
) -> Vec<Suggestion> {
let prefix_str = String::from_utf8_lossy(&prefix).to_string();
let prefix_str = String::from_utf8_lossy(&prefix).replace('`', "");
let mut search_dirs: Vec<String> = vec![];
let (base_dir, mut partial) = partial_from(&prefix_str);
// If prefix_str is only a word we want to search in the current dir
let (base, partial) = prefix_str
.rsplit_once(is_separator)
.unwrap_or((".", &prefix_str));
let base_dir = base.replace(is_separator, MAIN_SEPARATOR_STR);
let mut partial = partial.to_string();
// On windows, this standardizes paths to use \
let mut is_current_folder = false;
// Fetch the lib dirs
@ -58,7 +65,8 @@ impl Completer for DotNuCompletion {
};
// Check if the base_dir is a folder
if base_dir != format!(".{SEP}") {
// rsplit_once removes the separator
if base_dir != "." {
// Add the base dir into the directories to be searched
search_dirs.push(base_dir.clone());

View File

@ -1,16 +1,12 @@
use crate::completions::{Completer, CompletionOptions};
use crate::completions::{completion_common::complete_item, Completer, CompletionOptions, SortBy};
use nu_protocol::{
engine::{EngineState, StateWorkingSet},
levenshtein_distance, Span,
};
use reedline::Suggestion;
use std::path::{is_separator, Path};
use std::path::{Path, MAIN_SEPARATOR as SEP};
use std::sync::Arc;
use super::SortBy;
const SEP: char = std::path::MAIN_SEPARATOR;
#[derive(Clone)]
pub struct FileCompletion {
engine_state: Arc<EngineState>,
@ -32,21 +28,25 @@ impl Completer for FileCompletion {
_: usize,
options: &CompletionOptions,
) -> Vec<Suggestion> {
let cwd = self.engine_state.current_work_dir();
let prefix = String::from_utf8_lossy(&prefix).to_string();
let output: Vec<_> = file_path_completion(span, &prefix, &cwd, options)
.into_iter()
.map(move |x| Suggestion {
value: x.1,
description: None,
extra: None,
span: reedline::Span {
start: x.0.start - offset,
end: x.0.end - offset,
},
append_whitespace: false,
})
.collect();
let output: Vec<_> = file_path_completion(
span,
&prefix,
&self.engine_state.current_work_dir(),
options,
)
.into_iter()
.map(move |x| Suggestion {
value: x.1,
description: None,
extra: None,
span: reedline::Span {
start: x.0.start - offset,
end: x.0.end - offset,
},
append_whitespace: false,
})
.collect();
output
}
@ -102,84 +102,13 @@ impl Completer for FileCompletion {
}
}
pub fn partial_from(input: &str) -> (String, String) {
let partial = input.replace('`', "");
// If partial is only a word we want to search in the current dir
let (base, rest) = partial.rsplit_once(is_separator).unwrap_or((".", &partial));
// On windows, this standardizes paths to use \
let mut base = base.replace(is_separator, &SEP.to_string());
// rsplit_once removes the separator
base.push(SEP);
(base.to_string(), rest.to_string())
}
pub fn file_path_completion(
span: nu_protocol::Span,
partial: &str,
cwd: &str,
options: &CompletionOptions,
) -> Vec<(nu_protocol::Span, String)> {
let original_input = partial;
let (base_dir_name, partial) = partial_from(partial);
let base_dir = nu_path::expand_path_with(&base_dir_name, cwd);
// This check is here as base_dir.read_dir() with base_dir == "" will open the current dir
// which we don't want in this case (if we did, base_dir would already be ".")
if base_dir == Path::new("") {
return Vec::new();
}
if let Ok(result) = base_dir.read_dir() {
return result
.filter_map(|entry| {
entry.ok().and_then(|entry| {
let mut file_name = entry.file_name().to_string_lossy().into_owned();
if matches(&partial, &file_name, options) {
let mut path = if prepend_base_dir(original_input, &base_dir_name) {
format!("{base_dir_name}{file_name}")
} else {
file_name.to_string()
};
if entry.path().is_dir() {
path.push(SEP);
file_name.push(SEP);
}
// Fix files or folders with quotes or hashes
if path.contains('\'')
|| path.contains('"')
|| path.contains(' ')
|| path.contains('#')
|| path.contains('(')
|| path.contains(')')
|| path.starts_with('0')
|| path.starts_with('1')
|| path.starts_with('2')
|| path.starts_with('3')
|| path.starts_with('4')
|| path.starts_with('5')
|| path.starts_with('6')
|| path.starts_with('7')
|| path.starts_with('8')
|| path.starts_with('9')
{
path = format!("`{path}`");
}
Some((span, path))
} else {
None
}
})
})
.collect();
}
Vec::new()
complete_item(false, span, partial, cwd, options)
}
pub fn matches(partial: &str, from: &str, options: &CompletionOptions) -> bool {
@ -192,23 +121,3 @@ pub fn matches(partial: &str, from: &str, options: &CompletionOptions) -> bool {
options.match_algorithm.matches_str(from, partial)
}
/// Returns whether the base_dir should be prepended to the file path
pub fn prepend_base_dir(input: &str, base_dir: &str) -> bool {
if base_dir == format!(".{SEP}") {
// if the current base_dir path is the local folder we only add a "./" prefix if the user
// input already includes a local folder prefix.
let manually_entered = {
let mut chars = input.chars();
let first_char = chars.next();
let second_char = chars.next();
first_char == Some('.') && second_char.map(is_separator).unwrap_or(false)
};
manually_entered
} else {
// always prepend the base dir if it is a subfolder
true
}
}

View File

@ -1,6 +1,7 @@
mod base;
mod command_completions;
mod completer;
mod completion_common;
mod completion_options;
mod custom_completions;
mod directory_completions;
@ -16,8 +17,6 @@ pub use completion_options::{CompletionOptions, MatchAlgorithm, SortBy};
pub use custom_completions::CustomCompletion;
pub use directory_completions::DirectoryCompletion;
pub use dotnu_completions::DotNuCompletion;
pub use file_completions::{
file_path_completion, matches, partial_from, prepend_base_dir, FileCompletion,
};
pub use file_completions::{file_path_completion, matches, FileCompletion};
pub use flag_completions::FlagCompletion;
pub use variable_completions::VariableCompletion;

View File

@ -2,7 +2,7 @@ use crate::util::eval_source;
use log::info;
use log::trace;
use miette::{IntoDiagnostic, Result};
use nu_engine::eval_block_with_early_return;
use nu_engine::eval_block;
use nu_engine::{convert_env_values, current_dir};
use nu_parser::parse;
use nu_path::canonicalize_with;
@ -126,14 +126,22 @@ pub fn evaluate_file(
if engine_state.find_decl(b"main", &[]).is_some() {
let args = format!("main {}", args.join(" "));
let pipeline_data = eval_block_with_early_return(
let pipeline_data = eval_block(
engine_state,
stack,
&block,
PipelineData::empty(),
false,
false,
)
);
let pipeline_data = match pipeline_data {
Err(ShellError::Return(_, _)) => {
// allows early exists before `main` is run.
return Ok(());
}
x => x,
}
.unwrap_or_else(|e| {
let working_set = StateWorkingSet::new(engine_state);
report_error(&working_set, &e);

View File

@ -57,7 +57,7 @@ impl NuHelpCompleter {
let _ = write!(long_desc, "Usage:\r\n > {}\r\n", sig.call_signature());
if !sig.named.is_empty() {
long_desc.push_str(&get_flags_section(sig, |v| {
long_desc.push_str(&get_flags_section(Some(&*self.0.clone()), sig, |v| {
v.into_string_parsable(", ", &self.0.config)
}))
}

View File

@ -7,6 +7,8 @@ use nu_protocol::{
Config, PipelineData, Value,
};
use reedline::Prompt;
use std::borrow::Cow;
use std::sync::Arc;
// Name of environment variable where the prompt could be stored
pub(crate) const PROMPT_COMMAND: &str = "PROMPT_COMMAND";
@ -15,6 +17,15 @@ pub(crate) const PROMPT_INDICATOR: &str = "PROMPT_INDICATOR";
pub(crate) const PROMPT_INDICATOR_VI_INSERT: &str = "PROMPT_INDICATOR_VI_INSERT";
pub(crate) const PROMPT_INDICATOR_VI_NORMAL: &str = "PROMPT_INDICATOR_VI_NORMAL";
pub(crate) const PROMPT_MULTILINE_INDICATOR: &str = "PROMPT_MULTILINE_INDICATOR";
pub(crate) const TRANSIENT_PROMPT_COMMAND: &str = "TRANSIENT_PROMPT_COMMAND";
pub(crate) const TRANSIENT_PROMPT_COMMAND_RIGHT: &str = "TRANSIENT_PROMPT_COMMAND_RIGHT";
pub(crate) const TRANSIENT_PROMPT_INDICATOR: &str = "TRANSIENT_PROMPT_INDICATOR";
pub(crate) const TRANSIENT_PROMPT_INDICATOR_VI_INSERT: &str =
"TRANSIENT_PROMPT_INDICATOR_VI_INSERT";
pub(crate) const TRANSIENT_PROMPT_INDICATOR_VI_NORMAL: &str =
"TRANSIENT_PROMPT_INDICATOR_VI_NORMAL";
pub(crate) const TRANSIENT_PROMPT_MULTILINE_INDICATOR: &str =
"TRANSIENT_PROMPT_MULTILINE_INDICATOR";
// According to Daniel Imms @Tyriar, we need to do these this way:
// <133 A><prompt><133 B><command><133 C><command output>
const PRE_PROMPT_MARKER: &str = "\x1b]133;A\x1b\\";
@ -145,3 +156,119 @@ pub(crate) fn update_prompt<'prompt>(
ret_val
}
struct TransientPrompt {
engine_state: Arc<EngineState>,
stack: Stack,
}
/// Try getting `$env.TRANSIENT_PROMPT_<X>`, and get `$env.PROMPT_<X>` if that fails
fn get_transient_prompt_string(
transient_prompt: &str,
prompt: &str,
config: &Config,
engine_state: &EngineState,
stack: &mut Stack,
) -> Option<String> {
get_prompt_string(transient_prompt, config, engine_state, stack)
.or_else(|| get_prompt_string(prompt, config, engine_state, stack))
}
impl Prompt for TransientPrompt {
fn render_prompt_left(&self) -> Cow<str> {
let mut nu_prompt = NushellPrompt::new();
let config = &self.engine_state.get_config().clone();
let mut stack = self.stack.clone();
nu_prompt.update_prompt_left(get_transient_prompt_string(
TRANSIENT_PROMPT_COMMAND,
PROMPT_COMMAND,
config,
&self.engine_state,
&mut stack,
));
nu_prompt.render_prompt_left().to_string().into()
}
fn render_prompt_right(&self) -> Cow<str> {
let mut nu_prompt = NushellPrompt::new();
let config = &self.engine_state.get_config().clone();
let mut stack = self.stack.clone();
nu_prompt.update_prompt_right(
get_transient_prompt_string(
TRANSIENT_PROMPT_COMMAND_RIGHT,
PROMPT_COMMAND_RIGHT,
config,
&self.engine_state,
&mut stack,
),
config.render_right_prompt_on_last_line,
);
nu_prompt.render_prompt_right().to_string().into()
}
fn render_prompt_indicator(&self, prompt_mode: reedline::PromptEditMode) -> Cow<str> {
let mut nu_prompt = NushellPrompt::new();
let config = &self.engine_state.get_config().clone();
let mut stack = self.stack.clone();
nu_prompt.update_prompt_indicator(get_transient_prompt_string(
TRANSIENT_PROMPT_INDICATOR,
PROMPT_INDICATOR,
config,
&self.engine_state,
&mut stack,
));
nu_prompt.update_prompt_vi_insert(get_transient_prompt_string(
TRANSIENT_PROMPT_INDICATOR_VI_INSERT,
PROMPT_INDICATOR_VI_INSERT,
config,
&self.engine_state,
&mut stack,
));
nu_prompt.update_prompt_vi_normal(get_transient_prompt_string(
TRANSIENT_PROMPT_INDICATOR_VI_NORMAL,
PROMPT_INDICATOR_VI_NORMAL,
config,
&self.engine_state,
&mut stack,
));
nu_prompt
.render_prompt_indicator(prompt_mode)
.to_string()
.into()
}
fn render_prompt_multiline_indicator(&self) -> Cow<str> {
let mut nu_prompt = NushellPrompt::new();
let config = &self.engine_state.get_config().clone();
let mut stack = self.stack.clone();
nu_prompt.update_prompt_multiline(get_transient_prompt_string(
TRANSIENT_PROMPT_MULTILINE_INDICATOR,
PROMPT_MULTILINE_INDICATOR,
config,
&self.engine_state,
&mut stack,
));
nu_prompt
.render_prompt_multiline_indicator()
.to_string()
.into()
}
fn render_prompt_history_search_indicator(
&self,
history_search: reedline::PromptHistorySearch,
) -> Cow<str> {
NushellPrompt::new()
.render_prompt_history_search_indicator(history_search)
.to_string()
.into()
}
}
/// Construct the transient prompt
pub(crate) fn transient_prompt(engine_state: Arc<EngineState>, stack: &Stack) -> Box<dyn Prompt> {
Box::new(TransientPrompt {
engine_state,
stack: stack.clone(),
})
}

View File

@ -8,8 +8,8 @@ use crate::{
use crossterm::cursor::SetCursorStyle;
use log::{trace, warn};
use miette::{ErrReport, IntoDiagnostic, Result};
use nu_cmd_base::hook::eval_hook;
use nu_cmd_base::util::get_guaranteed_cwd;
use nu_cmd_base::{hook::eval_hook, util::get_editor};
use nu_color_config::StyleComputer;
use nu_engine::convert_env_values;
use nu_parser::{lex, parse, trim_quotes_str};
@ -26,6 +26,7 @@ use reedline::{
SqliteBackedHistory, Vi,
};
use std::{
env::temp_dir,
io::{self, IsTerminal, Write},
path::Path,
sync::atomic::Ordering,
@ -94,6 +95,7 @@ pub fn evaluate_repl(
let mut start_time = std::time::Instant::now();
let mut line_editor = Reedline::create();
let temp_file = temp_dir().join(format!("{}.nu", uuid::Uuid::new_v4()));
// Now that reedline is created, get the history session id and store it in engine_state
store_history_id_in_engine(engine_state, &line_editor);
@ -180,6 +182,14 @@ pub fn evaluate_repl(
);
}
if engine_state.get_config().use_kitty_protocol {
if line_editor.can_use_kitty_protocol() {
line_editor.enable_kitty_protocol();
} else {
warn!("Terminal doesn't support use_kitty_protocol config");
}
}
loop {
let loop_start_time = std::time::Instant::now();
@ -271,7 +281,11 @@ pub fn evaluate_repl(
.with_quick_completions(config.quick_completions)
.with_partial_completions(config.partial_completions)
.with_ansi_colors(config.use_ansi_coloring)
.with_cursor_config(cursor_config);
.with_cursor_config(cursor_config)
.with_transient_prompt(prompt_update::transient_prompt(
engine_reference.clone(),
stack,
));
perf(
"reedline builder",
start_time,
@ -318,23 +332,17 @@ pub fn evaluate_repl(
);
start_time = std::time::Instant::now();
let buffer_editor = if !config.buffer_editor.is_empty() {
Some(config.buffer_editor.clone())
} else {
stack
.get_env_var(engine_state, "EDITOR")
.map(|v| v.as_string().unwrap_or_default())
.filter(|v| !v.is_empty())
.or_else(|| {
stack
.get_env_var(engine_state, "VISUAL")
.map(|v| v.as_string().unwrap_or_default())
.filter(|v| !v.is_empty())
})
};
let buffer_editor = get_editor(engine_state, stack, Span::unknown());
line_editor = if let Some(buffer_editor) = buffer_editor {
line_editor.with_buffer_editor(buffer_editor, "nu".into())
line_editor = if let Ok((cmd, args)) = buffer_editor {
let mut command = std::process::Command::new(&cmd);
command.args(args).envs(
engine_state
.render_env_vars()
.into_iter()
.filter_map(|(k, v)| v.as_string().ok().map(|v| (k, v))),
);
line_editor.with_buffer_editor(command, temp_file.clone())
} else {
line_editor
};
@ -508,7 +516,10 @@ pub fn evaluate_repl(
report_error(
&working_set,
&ShellError::DirectoryNotFound(tokens.0[0].span, None),
&ShellError::DirectoryNotFound(
tokens.0[0].span,
path.to_string_lossy().to_string(),
),
);
}
let path = nu_path::canonicalize_with(path, &cwd)
@ -809,16 +820,29 @@ fn looks_like_path(orig: &str) -> bool {
|| orig.starts_with('~')
|| orig.starts_with('/')
|| orig.starts_with('\\')
|| orig.ends_with(std::path::MAIN_SEPARATOR)
}
#[cfg(windows)]
#[test]
fn looks_like_path_windows_drive_path_works() {
let on_windows = cfg!(windows);
assert_eq!(looks_like_path("C:"), on_windows);
assert_eq!(looks_like_path("D:\\"), on_windows);
assert_eq!(looks_like_path("E:/"), on_windows);
assert_eq!(looks_like_path("F:\\some_dir"), on_windows);
assert_eq!(looks_like_path("G:/some_dir"), on_windows);
assert!(looks_like_path("C:"));
assert!(looks_like_path("D:\\"));
assert!(looks_like_path("E:/"));
assert!(looks_like_path("F:\\some_dir"));
assert!(looks_like_path("G:/some_dir"));
}
#[cfg(windows)]
#[test]
fn trailing_slash_looks_like_path() {
assert!(looks_like_path("foo\\"))
}
#[cfg(not(windows))]
#[test]
fn trailing_slash_looks_like_path() {
assert!(looks_like_path("foo/"))
}
#[test]

View File

@ -1,11 +1,16 @@
pub mod support;
use std::path::PathBuf;
use nu_cli::NuCompleter;
use nu_parser::parse;
use nu_protocol::engine::StateWorkingSet;
use reedline::{Completer, Suggestion};
use rstest::{fixture, rstest};
use support::{completions_helpers::new_quote_engine, file, folder, match_suggestions, new_engine};
use support::{
completions_helpers::{new_partial_engine, new_quote_engine},
file, folder, match_suggestions, new_engine,
};
#[fixture]
fn completer() -> NuCompleter {
@ -201,6 +206,87 @@ fn file_completions() {
match_suggestions(expected_paths, suggestions);
}
#[test]
fn partial_completions() {
// Create a new engine
let (dir, _, engine, stack) = new_partial_engine();
// Instantiate a new completer
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack);
// Test completions for a folder's name
let target_dir = format!("cd {}", file(dir.join("pa")));
let suggestions = completer.complete(&target_dir, target_dir.len());
// Create the expected values
let expected_paths: Vec<String> = vec![
folder(dir.join("partial_a")),
folder(dir.join("partial_b")),
folder(dir.join("partial_c")),
];
// Match the results
match_suggestions(expected_paths, suggestions);
// Test completions for the files whose name begin with "h"
// and are present under directories whose names begin with "pa"
let dir_str = file(dir.join("pa").join("h"));
let target_dir = format!("cp {dir_str}");
let suggestions = completer.complete(&target_dir, target_dir.len());
// Create the expected values
let expected_paths: Vec<String> = vec![
file(dir.join("partial_a").join("hello")),
file(dir.join("partial_a").join("hola")),
file(dir.join("partial_b").join("hello_b")),
file(dir.join("partial_b").join("hi_b")),
file(dir.join("partial_c").join("hello_c")),
];
// Match the results
match_suggestions(expected_paths, suggestions);
// Test completion for all files under directories whose names begin with "pa"
let dir_str = folder(dir.join("pa"));
let target_dir = format!("ls {dir_str}");
let suggestions = completer.complete(&target_dir, target_dir.len());
// Create the expected values
let expected_paths: Vec<String> = vec![
file(dir.join("partial_a").join("anotherfile")),
file(dir.join("partial_a").join("hello")),
file(dir.join("partial_a").join("hola")),
file(dir.join("partial_b").join("hello_b")),
file(dir.join("partial_b").join("hi_b")),
file(dir.join("partial_c").join("hello_c")),
];
// Match the results
match_suggestions(expected_paths, suggestions);
// Test completion for a single file
let dir_str = file(dir.join("fi").join("so"));
let target_dir = format!("rm {dir_str}");
let suggestions = completer.complete(&target_dir, target_dir.len());
// Create the expected values
let expected_paths: Vec<String> = vec![file(dir.join("final_partial").join("somefile"))];
// Match the results
match_suggestions(expected_paths, suggestions);
// Test completion where there is a sneaky `..` in the path
let dir_str = file(dir.join("par").join("..").join("fi").join("so"));
let target_dir = format!("rm {dir_str}");
let suggestions = completer.complete(&target_dir, target_dir.len());
// Create the expected values
let expected_paths: Vec<String> = vec![file(dir.join("final_partial").join("somefile"))];
// Match the results
match_suggestions(expected_paths, suggestions);
}
#[test]
fn command_ls_with_filecompletion() {
let (_, _, engine, stack) = new_engine();
@ -445,6 +531,18 @@ fn file_completion_quoted() {
"`te#st.txt`".to_string(),
"`te'st.txt`".to_string(),
"`te(st).txt`".to_string(),
format!("`{}`", folder("test dir".into())),
];
match_suggestions(expected_paths, suggestions);
let dir: PathBuf = "test dir".into();
let target_dir = format!("open '{}'", folder(dir.clone()));
let suggestions = completer.complete(&target_dir, target_dir.len());
let expected_paths: Vec<String> = vec![
format!("`{}`", file(dir.join("double quote"))),
format!("`{}`", file(dir.join("single quote"))),
];
match_suggestions(expected_paths, suggestions)

View File

@ -109,6 +109,42 @@ pub fn new_quote_engine() -> (PathBuf, String, EngineState, Stack) {
(dir, dir_str, engine_state, stack)
}
pub fn new_partial_engine() -> (PathBuf, String, EngineState, Stack) {
// Target folder inside assets
let dir = fs::fixtures().join("partial_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(dir_str.clone(), nu_protocol::Span::new(0, dir_str.len())),
);
stack.add_env_var(
"TEST".to_string(),
Value::string(
"NUSHELL".to_string(),
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)
}
// match a list of suggestions with the expected values
pub fn match_suggestions(expected: Vec<String>, suggestions: Vec<Suggestion>) {
let expected_len = expected.len();

View File

@ -5,14 +5,14 @@ edition = "2021"
license = "MIT"
name = "nu-cmd-base"
repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cmd-base"
version = "0.85.0"
version = "0.86.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
nu-engine = { path = "../nu-engine", version = "0.85.0" }
nu-parser = { path = "../nu-parser", version = "0.85.0" }
nu-path = { path = "../nu-path", version = "0.85.0" }
nu-protocol = { version = "0.85.0", path = "../nu-protocol" }
nu-engine = { path = "../nu-engine", version = "0.86.0" }
nu-parser = { path = "../nu-parser", version = "0.86.0" }
nu-path = { path = "../nu-path", version = "0.86.0" }
nu-protocol = { version = "0.86.0", path = "../nu-protocol" }
indexmap = { version = "2.0" }
miette = { version = "5.10", features = ["fancy-no-backtrace"] }

View File

@ -55,3 +55,72 @@ pub fn process_range(range: &Range) -> Result<(isize, isize), MakeRangeError> {
Ok((start, end))
}
const HELP_MSG: &str = "Nushell's config file can be found with the command: $nu.config-path. \
For more help: (https://nushell.sh/book/configuration.html#configurations-with-built-in-commands)";
fn get_editor_commandline(
value: &Value,
var_name: &str,
) -> Result<(String, Vec<String>), ShellError> {
match value {
Value::String { val, .. } if !val.is_empty() => Ok((val.to_string(), Vec::new())),
Value::List { vals, .. } if !vals.is_empty() => {
let mut editor_cmd = vals.iter().map(|l| l.as_string());
match editor_cmd.next().transpose()? {
Some(editor) if !editor.is_empty() => {
let params = editor_cmd.collect::<Result<_, ShellError>>()?;
Ok((editor, params))
}
_ => Err(ShellError::GenericError(
"Editor executable is missing".into(),
"Set the first element to an executable".into(),
Some(value.span()),
Some(HELP_MSG.into()),
vec![],
)),
}
}
Value::String { .. } | Value::List { .. } => Err(ShellError::GenericError(
format!("{var_name} should be a non-empty string or list<String>"),
"Specify an executable here".into(),
Some(value.span()),
Some(HELP_MSG.into()),
vec![],
)),
x => Err(ShellError::CantConvert {
to_type: "string or list<string>".into(),
from_type: x.get_type().to_string(),
span: value.span(),
help: None,
}),
}
}
pub fn get_editor(
engine_state: &EngineState,
stack: &mut Stack,
span: Span,
) -> Result<(String, Vec<String>), ShellError> {
let config = engine_state.get_config();
let env_vars = stack.get_env_vars(engine_state);
if let Ok(buff_editor) =
get_editor_commandline(&config.buffer_editor, "$env.config.buffer_editor")
{
Ok(buff_editor)
} else if let Some(value) = env_vars.get("EDITOR") {
get_editor_commandline(value, "$env.EDITOR")
} else if let Some(value) = env_vars.get("VISUAL") {
get_editor_commandline(value, "$env.VISUAL")
} else {
Err(ShellError::GenericError(
"No editor configured".into(),
"Please specify one via `$env.config.buffer_editor` or `$env.EDITOR`/`$env.VISUAL`"
.into(),
Some(span),
Some(HELP_MSG.into()),
vec![],
))
}
}

View File

@ -5,7 +5,7 @@ edition = "2021"
license = "MIT"
name = "nu-cmd-dataframe"
repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cmd-dataframe"
version = "0.85.0"
version = "0.86.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -13,9 +13,9 @@ version = "0.85.0"
bench = false
[dependencies]
nu-engine = { path = "../nu-engine", version = "0.85.0" }
nu-parser = { path = "../nu-parser", version = "0.85.0" }
nu-protocol = { path = "../nu-protocol", version = "0.85.0" }
nu-engine = { path = "../nu-engine", version = "0.86.0" }
nu-parser = { path = "../nu-parser", version = "0.86.0" }
nu-protocol = { path = "../nu-protocol", version = "0.86.0" }
# Potential dependencies for extras
chrono = { version = "0.4", features = ["std", "unstable-locales"], default-features = false }
@ -24,7 +24,7 @@ indexmap = { version = "2.0" }
num = { version = "0.4", optional = true }
serde = { version = "1.0", features = ["derive"] }
sqlparser = { version = "0.36.1", optional = true }
polars-io = { version = "0.32", features = ["avro"], optional = true }
polars-io = { version = "0.33", features = ["avro"], optional = true }
[dependencies.polars]
features = [
@ -38,7 +38,7 @@ features = [
"dtype-categorical",
"dtype-datetime",
"dtype-struct",
"dynamic_groupby",
"dynamic_group_by",
"ipc",
"is_in",
"json",
@ -54,12 +54,12 @@ features = [
"to_dummies",
]
optional = true
version = "0.32"
version = "0.33"
[features]
dataframe = ["num", "polars", "polars-io", "sqlparser"]
default = []
[dev-dependencies]
nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.85.0" }
nu-test-support = { path = "../nu-test-support", version = "0.85.0" }
nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.86.0" }
nu-test-support = { path = "../nu-test-support", version = "0.86.0" }

View File

@ -52,12 +52,13 @@ impl Command for SampleDF {
vec![
Example {
description: "Sample rows from dataframe",
example: "[[a b]; [1 2] [3 4]] | dfr into-df | dfr sample -n 1",
example: "[[a b]; [1 2] [3 4]] | dfr into-df | dfr sample --n-rows 1",
result: None, // No expected value because sampling is random
},
Example {
description: "Shows sample row using fraction and replace",
example: "[[a b]; [1 2] [3 4] [5 6]] | dfr into-df | dfr sample -f 0.5 -e",
example:
"[[a b]; [1 2] [3 4] [5 6]] | dfr into-df | dfr sample --fraction 0.5 --replace",
result: None, // No expected value because sampling is random
},
]

View File

@ -147,7 +147,7 @@ impl SQLContext {
.enumerate()
.map(|(agg_pj, (proj_p, expr))| (expr.clone(), (proj_p, agg_pj + group_by.len())))
.unzip();
let agg_df = df.groupby(group_by).agg(agg_projection);
let agg_df = df.group_by(group_by).agg(agg_projection);
let mut final_proj_pos = groupby_pos
.into_iter()
.chain(agg_proj_pos)

View File

@ -45,7 +45,7 @@ impl Command for ToCSV {
},
Example {
description: "Saves dataframe to CSV file using other delimiter",
example: "[[a b]; [1 2] [3 4]] | dfr into-df | dfr to-csv test.csv -d '|'",
example: "[[a b]; [1 2] [3 4]] | dfr into-df | dfr to-csv test.csv --delimiter '|'",
result: None,
},
]

View File

@ -61,7 +61,7 @@ impl Command for ToNu {
},
Example {
description: "Shows tail rows from dataframe",
example: "[[a b]; [1 2] [5 6] [3 4]] | dfr into-df | dfr into-nu -t -n 1",
example: "[[a b]; [1 2] [5 6] [3 4]] | dfr into-df | dfr into-nu --tail --rows 1",
result: Some(Value::list(vec![rec_3], Span::test_data())),
},
Example {

View File

@ -131,7 +131,7 @@ impl Command for ToLazyGroupBy {
let group_by = NuLazyGroupBy {
schema: lazy.schema.clone(),
from_eager: lazy.from_eager,
group_by: Some(lazy.into_polars().groupby(&expressions)),
group_by: Some(lazy.into_polars().group_by(&expressions)),
};
Ok(PipelineData::Value(group_by.into_value(call.head), None))

View File

@ -2,6 +2,7 @@ mod eager;
mod expressions;
mod lazy;
mod series;
mod stub;
mod utils;
mod values;
@ -15,6 +16,7 @@ use nu_protocol::engine::{EngineState, StateWorkingSet};
pub fn add_dataframe_context(mut engine_state: EngineState) -> EngineState {
let delta = {
let mut working_set = StateWorkingSet::new(&engine_state);
working_set.add_decl(Box::new(stub::Dfr));
add_series_decls(&mut working_set);
add_eager_decls(&mut working_set);
add_expressions(&mut working_set);

View File

@ -148,7 +148,7 @@ fn command(
TimeUnit::Nanoseconds,
false,
None,
None,
&Default::default(),
)
} else {
casted.as_datetime(
@ -157,7 +157,7 @@ fn command(
false,
false,
None,
None,
&Default::default(),
)
};

View File

@ -31,7 +31,7 @@ impl Command for GetDay {
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Returns day from a date",
example: r#"let dt = ('2020-08-04T16:39:18+00:00' | into datetime -z 'UTC');
example: r#"let dt = ('2020-08-04T16:39:18+00:00' | into datetime --timezone 'UTC');
let df = ([$dt $dt] | dfr into-df);
$df | dfr get-day"#,
result: Some(

View File

@ -31,7 +31,7 @@ impl Command for GetHour {
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Returns hour from a date",
example: r#"let dt = ('2020-08-04T16:39:18+00:00' | into datetime -z 'UTC');
example: r#"let dt = ('2020-08-04T16:39:18+00:00' | into datetime --timezone 'UTC');
let df = ([$dt $dt] | dfr into-df);
$df | dfr get-hour"#,
result: Some(

View File

@ -31,7 +31,7 @@ impl Command for GetMinute {
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Returns minute from a date",
example: r#"let dt = ('2020-08-04T16:39:18+00:00' | into datetime -z 'UTC');
example: r#"let dt = ('2020-08-04T16:39:18+00:00' | into datetime --timezone 'UTC');
let df = ([$dt $dt] | dfr into-df);
$df | dfr get-minute"#,
result: Some(

View File

@ -31,7 +31,7 @@ impl Command for GetMonth {
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Returns month from a date",
example: r#"let dt = ('2020-08-04T16:39:18+00:00' | into datetime -z 'UTC');
example: r#"let dt = ('2020-08-04T16:39:18+00:00' | into datetime --timezone 'UTC');
let df = ([$dt $dt] | dfr into-df);
$df | dfr get-month"#,
result: Some(

View File

@ -31,7 +31,7 @@ impl Command for GetNanosecond {
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Returns nanosecond from a date",
example: r#"let dt = ('2020-08-04T16:39:18+00:00' | into datetime -z 'UTC');
example: r#"let dt = ('2020-08-04T16:39:18+00:00' | into datetime --timezone 'UTC');
let df = ([$dt $dt] | dfr into-df);
$df | dfr get-nanosecond"#,
result: Some(

View File

@ -31,7 +31,7 @@ impl Command for GetOrdinal {
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Returns ordinal from a date",
example: r#"let dt = ('2020-08-04T16:39:18+00:00' | into datetime -z 'UTC');
example: r#"let dt = ('2020-08-04T16:39:18+00:00' | into datetime --timezone 'UTC');
let df = ([$dt $dt] | dfr into-df);
$df | dfr get-ordinal"#,
result: Some(

View File

@ -31,7 +31,7 @@ impl Command for GetSecond {
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Returns second from a date",
example: r#"let dt = ('2020-08-04T16:39:18+00:00' | into datetime -z 'UTC');
example: r#"let dt = ('2020-08-04T16:39:18+00:00' | into datetime --timezone 'UTC');
let df = ([$dt $dt] | dfr into-df);
$df | dfr get-second"#,
result: Some(

View File

@ -31,7 +31,7 @@ impl Command for GetWeek {
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Returns week from a date",
example: r#"let dt = ('2020-08-04T16:39:18+00:00' | into datetime -z 'UTC');
example: r#"let dt = ('2020-08-04T16:39:18+00:00' | into datetime --timezone 'UTC');
let df = ([$dt $dt] | dfr into-df);
$df | dfr get-week"#,
result: Some(

View File

@ -31,7 +31,7 @@ impl Command for GetWeekDay {
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Returns weekday from a date",
example: r#"let dt = ('2020-08-04T16:39:18+00:00' | into datetime -z 'UTC');
example: r#"let dt = ('2020-08-04T16:39:18+00:00' | into datetime --timezone 'UTC');
let df = ([$dt $dt] | dfr into-df);
$df | dfr get-weekday"#,
result: Some(

View File

@ -31,7 +31,7 @@ impl Command for GetYear {
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Returns year from a date",
example: r#"let dt = ('2020-08-04T16:39:18+00:00' | into datetime -z 'UTC');
example: r#"let dt = ('2020-08-04T16:39:18+00:00' | into datetime --timezone 'UTC');
let df = ([$dt $dt] | dfr into-df);
$df | dfr get-year"#,
result: Some(

View File

@ -61,7 +61,7 @@ impl Command for ArgSort {
},
Example {
description: "Returns indexes for a sorted series",
example: "[1 2 2 3 3] | dfr into-df | dfr arg-sort -r",
example: "[1 2 2 3 3] | dfr into-df | dfr arg-sort --reverse",
result: Some(
NuDataFrame::try_from_columns(vec![Column::new(
"arg_sort".to_string(),

View File

@ -41,7 +41,7 @@ impl Command for SetWithIndex {
description: "Set value in selected rows from series",
example: r#"let series = ([4 1 5 2 4 3] | dfr into-df);
let indices = ([0 2] | dfr into-df);
$series | dfr set-with-idx 6 -i $indices"#,
$series | dfr set-with-idx 6 --indices $indices"#,
result: Some(
NuDataFrame::try_from_columns(vec![Column::new(
"0".to_string(),

View File

@ -6,7 +6,7 @@ use nu_protocol::{
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
};
use polars::prelude::IntoSeries;
use polars::prelude::{is_in, IntoSeries};
#[derive(Clone)]
pub struct IsIn;
@ -71,16 +71,14 @@ fn command(
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let df = NuDataFrame::try_from_pipeline(input, call.head)?;
let df = NuDataFrame::try_from_pipeline(input, call.head)?.as_series(call.head)?;
let other_value: Value = call.req(engine_state, stack, 0)?;
let other_span = other_value.span();
let other_df = NuDataFrame::try_from_value(other_value)?;
let other = other_df.as_series(other_span)?;
let mut res = df
.as_series(call.head)?
.is_in(&other)
let mut res = is_in(&df, &other)
.map_err(|e| {
ShellError::GenericError(
"Error finding in other".into(),

View File

@ -44,7 +44,7 @@ impl Command for Replace {
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Replaces string",
example: "[abc abc abc] | dfr into-df | dfr replace -p ab -r AB",
example: "[abc abc abc] | dfr into-df | dfr replace --pattern ab --replace AB",
result: Some(
NuDataFrame::try_from_columns(vec![Column::new(
"0".to_string(),

View File

@ -44,7 +44,7 @@ impl Command for ReplaceAll {
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Replaces string",
example: "[abac abac abac] | dfr into-df | dfr replace-all -p a -r A",
example: "[abac abac abac] | dfr into-df | dfr replace-all --pattern a --replace A",
result: Some(
NuDataFrame::try_from_columns(vec![Column::new(
"0".to_string(),

View File

@ -34,7 +34,7 @@ impl Command for StrSlice {
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Creates slices from the strings",
example: "[abcded abc321 abc123] | dfr into-df | dfr str-slice 1 -l 2",
example: "[abcded abc321 abc123] | dfr into-df | dfr str-slice 1 --length 2",
result: Some(
NuDataFrame::try_from_columns(vec![Column::new(
"0".to_string(),

View File

@ -33,7 +33,7 @@ impl Command for StrFTime {
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Formats date",
example: r#"let dt = ('2020-08-04T16:39:18+00:00' | into datetime -z 'UTC');
example: r#"let dt = ('2020-08-04T16:39:18+00:00' | into datetime --timezone 'UTC');
let df = ([$dt $dt] | dfr into-df);
$df | dfr strftime "%Y/%m/%d""#,
result: Some(

View File

@ -0,0 +1,47 @@
use nu_engine::get_full_help;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{Category, IntoPipelineData, PipelineData, ShellError, Signature, Type, Value};
#[derive(Clone)]
pub struct Dfr;
impl Command for Dfr {
fn name(&self) -> &str {
"dfr"
}
fn usage(&self) -> &str {
"Operate with data in a dataframe format."
}
fn signature(&self) -> nu_protocol::Signature {
Signature::build("dfr")
.category(Category::Custom("dataframe".into()))
.input_output_types(vec![(Type::Nothing, Type::String)])
}
fn extra_usage(&self) -> &str {
"You must use one of the following subcommands. Using this command as-is will only produce this help message."
}
fn run(
&self,
engine_state: &EngineState,
stack: &mut Stack,
call: &Call,
_input: PipelineData,
) -> Result<PipelineData, ShellError> {
Ok(Value::string(
get_full_help(
&Dfr.signature(),
&Dfr.examples(),
engine_state,
stack,
self.is_parser_keyword(),
),
call.head,
)
.into_pipeline_data())
}
}

View File

@ -5,7 +5,7 @@ edition = "2021"
license = "MIT"
name = "nu-cmd-extra"
repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cmd-extra"
version = "0.85.0"
version = "0.86.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -13,22 +13,22 @@ version = "0.85.0"
bench = false
[dependencies]
nu-engine = { path = "../nu-engine", version = "0.85.0" }
nu-parser = { path = "../nu-parser", version = "0.85.0" }
nu-protocol = { path = "../nu-protocol", version = "0.85.0" }
nu-cmd-base = { path = "../nu-cmd-base", version = "0.85.0" }
nu-utils = { path = "../nu-utils", version = "0.85.0" }
nu-engine = { path = "../nu-engine", version = "0.86.0" }
nu-parser = { path = "../nu-parser", version = "0.86.0" }
nu-protocol = { path = "../nu-protocol", version = "0.86.0" }
nu-cmd-base = { path = "../nu-cmd-base", version = "0.86.0" }
nu-utils = { path = "../nu-utils", version = "0.86.0" }
# Potential dependencies for extras
Inflector = "0.11"
heck = "0.4.1"
num-traits = "0.2"
ahash = "0.8.3"
nu-ansi-term = "0.49.0"
fancy-regex = "0.11.0"
rust-embed = "8.0.0"
serde = "1.0.164"
nu-pretty-hex = { version = "0.85.0", path = "../nu-pretty-hex" }
nu-json = { version = "0.85.0", path = "../nu-json" }
nu-pretty-hex = { version = "0.86.0", path = "../nu-pretty-hex" }
nu-json = { version = "0.86.0", path = "../nu-json" }
serde_urlencoded = "0.7.1"
htmlescape = "0.3.1"
@ -37,6 +37,6 @@ extra = ["default"]
default = []
[dev-dependencies]
nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.85.0" }
nu-command = { path = "../nu-command", version = "0.85.0" }
nu-test-support = { path = "../nu-test-support", version = "0.85.0" }
nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.86.0" }
nu-command = { path = "../nu-command", version = "0.86.0" }
nu-test-support = { path = "../nu-test-support", version = "0.86.0" }

View File

@ -22,16 +22,12 @@ impl Command for BitsAnd {
Type::List(Box::new(Type::Int)),
),
])
.required(
"target",
SyntaxShape::Int,
"target integer to perform bit and",
)
.required("target", SyntaxShape::Int, "target int to perform bit and")
.category(Category::Bits)
}
fn usage(&self) -> &str {
"Performs bitwise and for integers."
"Performs bitwise and for ints."
}
fn search_terms(&self) -> Vec<&str> {
@ -85,7 +81,7 @@ fn operate(value: Value, target: i64, head: Span) -> Value {
Value::Error { .. } => value,
other => Value::error(
ShellError::OnlySupportsThisInputType {
exp_input_type: "integer".into(),
exp_input_type: "int".into(),
wrong_type: other.get_type().to_string(),
dst_span: head,
src_span: other.span(),

View File

@ -219,7 +219,7 @@ pub fn action(input: &Value, _args: &Arguments, span: Span) -> Value {
Value::Error { .. } => input.clone(),
other => Value::error(
ShellError::OnlySupportsThisInputType {
exp_input_type: "integer, filesize, string, date, duration, binary or bool".into(),
exp_input_type: "int, filesize, string, date, duration, binary, or bool".into(),
wrong_type: other.get_type().to_string(),
dst_span: span,
src_span: other.span(),

View File

@ -96,7 +96,7 @@ impl Command for BitsNot {
Example {
description:
"Apply logical negation to a list of numbers, treat input as 2 bytes number",
example: "[4 3 2] | bits not -n '2'",
example: "[4 3 2] | bits not --number-bytes '2'",
result: Some(Value::list(
vec![
Value::test_int(65531),
@ -109,7 +109,7 @@ impl Command for BitsNot {
Example {
description:
"Apply logical negation to a list of numbers, treat input as signed number",
example: "[4 3 2] | bits not -s",
example: "[4 3 2] | bits not --signed",
result: Some(Value::list(
vec![
Value::test_int(-5),
@ -158,7 +158,7 @@ fn operate(value: Value, head: Span, signed: bool, number_size: NumberBytes) ->
Value::Error { .. } => other,
_ => Value::error(
ShellError::OnlySupportsThisInputType {
exp_input_type: "integer".into(),
exp_input_type: "int".into(),
wrong_type: other.get_type().to_string(),
dst_span: head,
src_span: other.span(),

View File

@ -22,16 +22,12 @@ impl Command for BitsOr {
Type::List(Box::new(Type::Int)),
),
])
.required(
"target",
SyntaxShape::Int,
"target integer to perform bit or",
)
.required("target", SyntaxShape::Int, "target int to perform bit or")
.category(Category::Bits)
}
fn usage(&self) -> &str {
"Performs bitwise or for integers."
"Performs bitwise or for ints."
}
fn search_terms(&self) -> Vec<&str> {
@ -85,7 +81,7 @@ fn operate(value: Value, target: i64, head: Span) -> Value {
Value::Error { .. } => value,
other => Value::error(
ShellError::OnlySupportsThisInputType {
exp_input_type: "integer".into(),
exp_input_type: "int".into(),
wrong_type: other.get_type().to_string(),
dst_span: head,
src_span: other.span(),

View File

@ -41,7 +41,7 @@ impl Command for BitsRol {
}
fn usage(&self) -> &str {
"Bitwise rotate left for integers."
"Bitwise rotate left for ints."
}
fn search_terms(&self) -> Vec<&str> {
@ -145,7 +145,7 @@ fn operate(value: Value, bits: usize, head: Span, signed: bool, number_size: Num
Value::Error { .. } => value,
other => Value::error(
ShellError::OnlySupportsThisInputType {
exp_input_type: "integer".into(),
exp_input_type: "int".into(),
wrong_type: other.get_type().to_string(),
dst_span: head,
src_span: other.span(),

View File

@ -41,7 +41,7 @@ impl Command for BitsRor {
}
fn usage(&self) -> &str {
"Bitwise rotate right for integers."
"Bitwise rotate right for ints."
}
fn search_terms(&self) -> Vec<&str> {
@ -90,7 +90,7 @@ impl Command for BitsRor {
},
Example {
description: "Rotate right a list of numbers of one byte",
example: "[15 33 92] | bits ror 2 -n '1'",
example: "[15 33 92] | bits ror 2 --number-bytes '1'",
result: Some(Value::list(
vec![
Value::test_int(195),
@ -149,7 +149,7 @@ fn operate(value: Value, bits: usize, head: Span, signed: bool, number_size: Num
Value::Error { .. } => value,
other => Value::error(
ShellError::OnlySupportsThisInputType {
exp_input_type: "integer".into(),
exp_input_type: "int".into(),
wrong_type: other.get_type().to_string(),
dst_span: head,
src_span: other.span(),

View File

@ -41,7 +41,7 @@ impl Command for BitsShl {
}
fn usage(&self) -> &str {
"Bitwise shift left for integers."
"Bitwise shift left for ints."
}
fn search_terms(&self) -> Vec<&str> {
@ -90,12 +90,12 @@ impl Command for BitsShl {
},
Example {
description: "Shift left a number with 1 byte by 7 bits",
example: "2 | bits shl 7 -n '1'",
example: "2 | bits shl 7 --number-bytes '1'",
result: Some(Value::test_int(0)),
},
Example {
description: "Shift left a signed number by 1 bit",
example: "0x7F | bits shl 1 -s",
example: "0x7F | bits shl 1 --signed",
result: Some(Value::test_int(254)),
},
Example {
@ -169,7 +169,7 @@ fn operate(value: Value, bits: usize, head: Span, signed: bool, number_size: Num
Value::Error { .. } => value,
other => Value::error(
ShellError::OnlySupportsThisInputType {
exp_input_type: "integer".into(),
exp_input_type: "int".into(),
wrong_type: other.get_type().to_string(),
dst_span: head,
src_span: other.span(),

View File

@ -41,7 +41,7 @@ impl Command for BitsShr {
}
fn usage(&self) -> &str {
"Bitwise shift right for integers."
"Bitwise shift right for ints."
}
fn search_terms(&self) -> Vec<&str> {
@ -159,7 +159,7 @@ fn operate(value: Value, bits: usize, head: Span, signed: bool, number_size: Num
Value::Error { .. } => value,
other => Value::error(
ShellError::OnlySupportsThisInputType {
exp_input_type: "integer".into(),
exp_input_type: "int".into(),
wrong_type: other.get_type().to_string(),
dst_span: head,
src_span: other.span(),

View File

@ -22,16 +22,12 @@ impl Command for BitsXor {
Type::List(Box::new(Type::Int)),
),
])
.required(
"target",
SyntaxShape::Int,
"target integer to perform bit xor",
)
.required("target", SyntaxShape::Int, "target int to perform bit xor")
.category(Category::Bits)
}
fn usage(&self) -> &str {
"Performs bitwise xor for integers."
"Performs bitwise xor for ints."
}
fn search_terms(&self) -> Vec<&str> {
@ -84,7 +80,7 @@ fn operate(value: Value, target: i64, head: Span) -> Value {
Value::Error { .. } => value,
other => Value::error(
ShellError::OnlySupportsThisInputType {
exp_input_type: "integer".into(),
exp_input_type: "int".into(),
wrong_type: other.get_type().to_string(),
dst_span: head,
src_span: other.span(),

View File

@ -88,7 +88,7 @@ fn action(input: &Value, _args: &CellPathOnlyArgs, span: Span) -> Value {
Value::Error { .. } => input.clone(),
other => Value::error(
ShellError::OnlySupportsThisInputType {
exp_input_type: "float , integer or filesize".into(),
exp_input_type: "float, int, or filesize".into(),
wrong_type: other.get_type().to_string(),
dst_span: span,
src_span: other.span(),

View File

@ -1,4 +1,4 @@
use inflector::cases::camelcase::to_camel_case;
use heck::ToLowerCamelCase;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{
@ -50,7 +50,13 @@ impl Command for SubCommand {
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
operate(engine_state, stack, call, input, &to_camel_case)
operate(
engine_state,
stack,
call,
input,
&ToLowerCamelCase::to_lower_camel_case,
)
}
fn examples(&self) -> Vec<Example> {

View File

@ -1,4 +1,4 @@
use inflector::cases::kebabcase::to_kebab_case;
use heck::ToKebabCase;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{
@ -50,7 +50,13 @@ impl Command for SubCommand {
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
operate(engine_state, stack, call, input, &to_kebab_case)
operate(
engine_state,
stack,
call,
input,
&ToKebabCase::to_kebab_case,
)
}
fn examples(&self) -> Vec<Example> {

View File

@ -1,4 +1,4 @@
use inflector::cases::pascalcase::to_pascal_case;
use heck::ToUpperCamelCase;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{
@ -50,7 +50,13 @@ impl Command for SubCommand {
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
operate(engine_state, stack, call, input, &to_pascal_case)
operate(
engine_state,
stack,
call,
input,
&ToUpperCamelCase::to_upper_camel_case,
)
}
fn examples(&self) -> Vec<Example> {

View File

@ -1,4 +1,4 @@
use inflector::cases::screamingsnakecase::to_screaming_snake_case;
use heck::ToShoutySnakeCase;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{
@ -50,7 +50,13 @@ impl Command for SubCommand {
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
operate(engine_state, stack, call, input, &to_screaming_snake_case)
operate(
engine_state,
stack,
call,
input,
&ToShoutySnakeCase::to_shouty_snake_case,
)
}
fn examples(&self) -> Vec<Example> {

View File

@ -1,4 +1,4 @@
use inflector::cases::snakecase::to_snake_case;
use heck::ToSnakeCase;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{
@ -49,7 +49,13 @@ impl Command for SubCommand {
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
operate(engine_state, stack, call, input, &to_snake_case)
operate(
engine_state,
stack,
call,
input,
&ToSnakeCase::to_snake_case,
)
}
fn examples(&self) -> Vec<Example> {

View File

@ -1,4 +1,4 @@
use inflector::cases::titlecase::to_title_case;
use heck::ToTitleCase;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{
@ -50,7 +50,13 @@ impl Command for SubCommand {
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
operate(engine_state, stack, call, input, &to_title_case)
operate(
engine_state,
stack,
call,
input,
&ToTitleCase::to_title_case,
)
}
fn examples(&self) -> Vec<Example> {

View File

@ -6,24 +6,24 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cmd-lang"
edition = "2021"
license = "MIT"
name = "nu-cmd-lang"
version = "0.85.0"
version = "0.86.0"
[lib]
bench = false
[dependencies]
nu-engine = { path = "../nu-engine", version = "0.85.0" }
nu-parser = { path = "../nu-parser", version = "0.85.0" }
nu-protocol = { path = "../nu-protocol", version = "0.85.0" }
nu-utils = { path = "../nu-utils", version = "0.85.0" }
nu-engine = { path = "../nu-engine", version = "0.86.0" }
nu-parser = { path = "../nu-parser", version = "0.86.0" }
nu-protocol = { path = "../nu-protocol", version = "0.86.0" }
nu-utils = { path = "../nu-utils", version = "0.86.0" }
nu-ansi-term = "0.49.0"
fancy-regex = "0.11"
itertools = "0.11"
shadow-rs = { version = "0.23", default-features = false }
shadow-rs = { version = "0.24", default-features = false }
[build-dependencies]
shadow-rs = { version = "0.23", default-features = false }
shadow-rs = { version = "0.24", default-features = false }
[features]
mimalloc = []

View File

@ -19,9 +19,11 @@ impl Command for Def {
fn signature(&self) -> nu_protocol::Signature {
Signature::build("def")
.input_output_types(vec![(Type::Nothing, Type::Nothing)])
.required("def_name", SyntaxShape::String, "definition name")
.required("def_name", SyntaxShape::String, "command name")
.required("params", SyntaxShape::Signature, "parameters")
.required("body", SyntaxShape::Closure(None), "body of the definition")
.required("block", SyntaxShape::Closure(None), "body of the definition")
.switch("env", "keep the environment defined inside the command", None)
.switch("wrapped", "treat unknown flags and arguments as strings (requires ...rest-like parameter in signature)", None)
.category(Category::Core)
}
@ -56,6 +58,16 @@ impl Command for Def {
example: r#"def say-sth [sth: string] { echo $sth }; say-sth hi"#,
result: Some(Value::test_string("hi")),
},
Example {
description: "Set environment variable by call a custom command",
example: r#"def --env foo [] { $env.BAR = "BAZ" }; foo; $env.BAR"#,
result: Some(Value::test_string("BAZ")),
},
Example {
description: "Define a custom wrapper for an external command",
example: r#"def --wrapped my-echo [...rest] { echo $rest }; my-echo spam"#,
result: Some(Value::test_list(vec![Value::test_string("spam")])),
},
]
}
}

View File

@ -1,6 +1,6 @@
use std::thread;
use nu_engine::{eval_block_with_early_return, CallExt};
use nu_engine::{eval_block_with_early_return, redirect_env, CallExt};
use nu_protocol::ast::Call;
use nu_protocol::engine::{Closure, Command, EngineState, Stack};
use nu_protocol::{
@ -48,6 +48,11 @@ impl Command for Do {
"catch errors as the closure runs, and return them",
Some('c'),
)
.switch(
"env",
"keep the environment defined inside the command",
None,
)
.rest("rest", SyntaxShape::Any, "the parameter(s) for the closure")
.category(Category::Core)
}
@ -55,18 +60,19 @@ impl Command for Do {
fn run(
&self,
engine_state: &EngineState,
stack: &mut Stack,
caller_stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let block: Closure = call.req(engine_state, stack, 0)?;
let rest: Vec<Value> = call.rest(engine_state, stack, 1)?;
let block: Closure = call.req(engine_state, caller_stack, 0)?;
let rest: Vec<Value> = call.rest(engine_state, caller_stack, 1)?;
let ignore_all_errors = call.has_flag("ignore-errors");
let ignore_shell_errors = ignore_all_errors || call.has_flag("ignore-shell-errors");
let ignore_program_errors = ignore_all_errors || call.has_flag("ignore-program-errors");
let capture_errors = call.has_flag("capture-errors");
let has_env = call.has_flag("env");
let mut stack = stack.captures_to_stack(&block.captures);
let mut callee_stack = caller_stack.captures_to_stack(&block.captures);
let block = engine_state.get_block(block.block_id);
let params: Vec<_> = block
@ -78,7 +84,7 @@ impl Command for Do {
for param in params.iter().zip(&rest) {
if let Some(var_id) = param.0.var_id {
stack.add_var(var_id, param.1.clone())
callee_stack.add_var(var_id, param.1.clone())
}
}
@ -96,7 +102,7 @@ impl Command for Do {
call.head
};
stack.add_var(
callee_stack.add_var(
param
.var_id
.expect("Internal error: rest positional parameter lacks var_id"),
@ -106,13 +112,18 @@ impl Command for Do {
}
let result = eval_block_with_early_return(
engine_state,
&mut stack,
&mut callee_stack,
block,
input,
call.redirect_stdout,
call.redirect_stdout,
);
if has_env {
// Merge the block's environment to the current stack
redirect_env(engine_state, caller_stack, &callee_stack);
}
match result {
Ok(PipelineData::ExternalStream {
stdout,
@ -264,22 +275,22 @@ impl Command for Do {
},
Example {
description: "Run the closure and ignore both shell and external program errors",
example: r#"do -i { thisisnotarealcommand }"#,
example: r#"do --ignore-errors { thisisnotarealcommand }"#,
result: None,
},
Example {
description: "Run the closure and ignore shell errors",
example: r#"do -s { thisisnotarealcommand }"#,
example: r#"do --ignore-shell-errors { thisisnotarealcommand }"#,
result: None,
},
Example {
description: "Run the closure and ignore external program errors",
example: r#"do -p { nu -c 'exit 1' }; echo "I'll still run""#,
example: r#"do --ignore-program-errors { nu --commands 'exit 1' }; echo "I'll still run""#,
result: None,
},
Example {
description: "Abort the pipeline if a program returns a non-zero exit code",
example: r#"do -c { nu -c 'exit 1' } | myscarycommand"#,
example: r#"do --capture-errors { nu --commands 'exit 1' } | myscarycommand"#,
result: None,
},
Example {
@ -292,6 +303,11 @@ impl Command for Do {
example: r#"77 | do {|x| 100 + $in }"#,
result: None, // TODO: returns 177
},
Example {
description: "Run the closure and keep changes to the environment",
example: r#"do --env { $env.foo = 'bar' }; $env.foo"#,
result: Some(Value::test_string("bar")),
},
]
}
}

View File

@ -19,9 +19,11 @@ impl Command for ExportDef {
fn signature(&self) -> nu_protocol::Signature {
Signature::build("export def")
.input_output_types(vec![(Type::Nothing, Type::Nothing)])
.required("name", SyntaxShape::String, "definition name")
.required("def_name", SyntaxShape::String, "command name")
.required("params", SyntaxShape::Signature, "parameters")
.required("block", SyntaxShape::Block, "body of the definition")
.switch("env", "keep the environment defined inside the command", None)
.switch("wrapped", "treat unknown flags and arguments as strings (requires ...rest-like parameter in signature)", None)
.category(Category::Core)
}

View File

@ -199,7 +199,7 @@ impl Command for For {
fn examples(&self) -> Vec<Example> {
vec![
Example {
description: "Echo the square of each integer",
description: "Print the square of each integer",
example: "for x in [1 2 3] { print ($x * $x) }",
result: None,
},
@ -209,7 +209,7 @@ impl Command for For {
result: None,
},
Example {
description: "Number each item and echo a message",
description: "Number each item and print a message",
example:
"for $it in ['bob' 'fred'] --numbered { print $\"($it.index) is ($it.item)\" }",
result: None,

View File

@ -88,7 +88,7 @@ impl Command for LazyMake {
},
Example {
description: "Test the laziness of lazy records",
example: r#"lazy make -c ["hello"] -g { |key| print $"getting ($key)!"; $key | str upcase }"#,
example: r#"lazy make --columns ["hello"] --get-value { |key| print $"getting ($key)!"; $key | str upcase }"#,
result: None,
},
]

View File

@ -62,7 +62,7 @@ impl Command for Module {
},
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 [] { $env.FOO_BAR = "BAZ" } }; use foo bar; bar; $env.FOO_BAR"#,
example: r#"module foo { export def --env bar [] { $env.FOO_BAR = "BAZ" } }; use foo bar; bar; $env.FOO_BAR"#,
result: Some(Value::test_string("BAZ")),
},
]

View File

@ -155,7 +155,7 @@ This command is a parser keyword. For details, check:
},
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 [] { $env.FOO_BAR = "BAZ" } }; use foo bar; bar; $env.FOO_BAR"#,
example: r#"module foo { export def --env bar [] { $env.FOO_BAR = "BAZ" } }; use foo bar; bar; $env.FOO_BAR"#,
result: Some(Value::test_string("BAZ")),
},
Example {

View File

@ -5,19 +5,19 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-color-confi
edition = "2021"
license = "MIT"
name = "nu-color-config"
version = "0.85.0"
version = "0.86.0"
[lib]
bench = false
[dependencies]
nu-protocol = { path = "../nu-protocol", version = "0.85.0" }
nu-protocol = { path = "../nu-protocol", version = "0.86.0" }
nu-ansi-term = "0.49.0"
nu-utils = { path = "../nu-utils", version = "0.85.0" }
nu-engine = { path = "../nu-engine", version = "0.85.0" }
nu-json = { path = "../nu-json", version = "0.85.0" }
nu-utils = { path = "../nu-utils", version = "0.86.0" }
nu-engine = { path = "../nu-engine", version = "0.86.0" }
nu-json = { path = "../nu-json", version = "0.86.0" }
serde = { version = "1.0", features = ["derive"] }
[dev-dependencies]
nu-test-support = { path = "../nu-test-support", version = "0.85.0" }
nu-test-support = { path = "../nu-test-support", version = "0.86.0" }

View File

@ -247,6 +247,24 @@ pub fn lookup_style(s: &str) -> Style {
"lpbl" | "light_purple_blink" => Color::LightPurple.blink(),
"lpst" | "light_purple_strike" => Color::LightPurple.strikethrough(),
"m" | "magenta" => Color::Magenta.normal(),
"mb" | "magenta_bold" => Color::Magenta.bold(),
"mu" | "magenta_underline" => Color::Magenta.underline(),
"mi" | "magenta_italic" => Color::Magenta.italic(),
"md" | "magenta_dimmed" => Color::Magenta.dimmed(),
"mr" | "magenta_reverse" => Color::Magenta.reverse(),
"mbl" | "magenta_blink" => Color::Magenta.blink(),
"mst" | "magenta_strike" => Color::Magenta.strikethrough(),
"lm" | "light_magenta" => Color::LightMagenta.normal(),
"lmb" | "light_magenta_bold" => Color::LightMagenta.bold(),
"lmu" | "light_magenta_underline" => Color::LightMagenta.underline(),
"lmi" | "light_magenta_italic" => Color::LightMagenta.italic(),
"lmd" | "light_magenta_dimmed" => Color::LightMagenta.dimmed(),
"lmr" | "light_magenta_reverse" => Color::LightMagenta.reverse(),
"lmbl" | "light_magenta_blink" => Color::LightMagenta.blink(),
"lmst" | "light_magenta_strike" => Color::LightMagenta.strikethrough(),
"c" | "cyan" => Color::Cyan.normal(),
"cb" | "cyan_bold" => Color::Cyan.bold(),
"cu" | "cyan_underline" => Color::Cyan.underline(),

View File

@ -5,7 +5,7 @@ edition = "2021"
license = "MIT"
name = "nu-command"
repository = "https://github.com/nushell/nushell/tree/main/crates/nu-command"
version = "0.85.0"
version = "0.86.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -14,23 +14,23 @@ bench = false
[dependencies]
nu-ansi-term = "0.49.0"
nu-cmd-base = { path = "../nu-cmd-base", version = "0.85.0" }
nu-color-config = { path = "../nu-color-config", version = "0.85.0" }
nu-engine = { path = "../nu-engine", version = "0.85.0" }
nu-glob = { path = "../nu-glob", version = "0.85.0" }
nu-json = { path = "../nu-json", version = "0.85.0" }
nu-parser = { path = "../nu-parser", version = "0.85.0" }
nu-path = { path = "../nu-path", version = "0.85.0" }
nu-pretty-hex = { path = "../nu-pretty-hex", version = "0.85.0" }
nu-protocol = { path = "../nu-protocol", version = "0.85.0" }
nu-system = { path = "../nu-system", version = "0.85.0" }
nu-table = { path = "../nu-table", version = "0.85.0" }
nu-term-grid = { path = "../nu-term-grid", version = "0.85.0" }
nu-utils = { path = "../nu-utils", version = "0.85.0" }
nu-cmd-base = { path = "../nu-cmd-base", version = "0.86.0" }
nu-color-config = { path = "../nu-color-config", version = "0.86.0" }
nu-engine = { path = "../nu-engine", version = "0.86.0" }
nu-glob = { path = "../nu-glob", version = "0.86.0" }
nu-json = { path = "../nu-json", version = "0.86.0" }
nu-parser = { path = "../nu-parser", version = "0.86.0" }
nu-path = { path = "../nu-path", version = "0.86.0" }
nu-pretty-hex = { path = "../nu-pretty-hex", version = "0.86.0" }
nu-protocol = { path = "../nu-protocol", version = "0.86.0" }
nu-system = { path = "../nu-system", version = "0.86.0" }
nu-table = { path = "../nu-table", version = "0.86.0" }
nu-term-grid = { path = "../nu-term-grid", version = "0.86.0" }
nu-utils = { path = "../nu-utils", version = "0.86.0" }
alphanumeric-sort = "1.5"
base64 = "0.21"
byteorder = "1.4"
byteorder = "1.5"
bytesize = "1.3"
calamine = "0.22"
chrono = { version = "0.4", features = ["std", "unstable-locales"], default-features = false }
@ -38,7 +38,7 @@ chrono-humanize = "0.2.3"
chrono-tz = "0.8"
crossterm = "0.27"
csv = "1.2"
dialoguer = { default-features = false, features = ["fuzzy-select"], version = "0.10" }
dialoguer = { default-features = false, features = ["fuzzy-select"], version = "0.11" }
digest = { default-features = false, version = "0.10" }
dtparse = "2.0"
encoding_rs = "0.8"
@ -66,12 +66,11 @@ open = "5.0"
os_pipe = "1.1"
pathdiff = "0.2"
percent-encoding = "2.3"
powierza-coefficient = "1.0"
print-positions = "0.6"
quick-xml = "0.30"
rand = "0.8"
rayon = "1.7"
regex = "1.7"
rayon = "1.8"
regex = "1.9.5"
roxmltree = "0.18"
rusqlite = { version = "0.29", features = ["bundled"], optional = true }
same-file = "1.0"
@ -86,11 +85,11 @@ terminal_size = "0.3"
titlecase = "2.0"
toml = "0.8"
unicode-segmentation = "1.10"
ureq = { version = "2.7", default-features = false, features = ["charset", "gzip", "json", "native-tls"] }
ureq = { version = "2.8", default-features = false, features = ["charset", "gzip", "json", "native-tls"] }
url = "2.2"
uu_cp = "0.0.21"
uu_cp = "0.0.22"
uuid = { version = "1.3", features = ["v4"] }
wax = { version = "0.5" }
wax = { version = "0.6" }
which = { version = "4.4", optional = true }
bracoxide = "0.1.2"
chardetng = "0.1.17"
@ -105,7 +104,7 @@ nix = { version = "0.27", default-features = false, features = ["user"] }
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies.trash]
optional = true
version = "3.0"
version = "3.1"
[target.'cfg(windows)'.dependencies.windows]
features = [
@ -124,8 +123,8 @@ trash-support = ["trash"]
which-support = ["which"]
[dev-dependencies]
nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.85.0" }
nu-test-support = { path = "../nu-test-support", version = "0.85.0" }
nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.86.0" }
nu-test-support = { path = "../nu-test-support", version = "0.86.0" }
dirs-next = "2.0"
mockito = { version = "1.2", default-features = false }

View File

@ -97,21 +97,21 @@ impl Command for BytesAdd {
},
Example {
description: "Add bytes `0x[AA BB]` to `0x[1F FF AA AA]` at index 1",
example: "0x[1F FF AA AA] | bytes add 0x[AA BB] -i 1",
example: "0x[1F FF AA AA] | bytes add 0x[AA BB] --index 1",
result: Some(Value::binary(vec![0x1F, 0xAA, 0xBB, 0xFF, 0xAA, 0xAA],
Span::test_data(),
)),
},
Example {
description: "Add bytes `0x[11]` to `0x[FF AA AA]` at the end",
example: "0x[FF AA AA] | bytes add 0x[11] -e",
example: "0x[FF AA AA] | bytes add 0x[11] --end",
result: Some(Value::binary(vec![0xFF, 0xAA, 0xAA, 0x11],
Span::test_data(),
)),
},
Example {
description: "Add bytes `0x[11 22 33]` to `0x[FF AA AA]` at the end, at index 1(the index is start from end)",
example: "0x[FF AA BB] | bytes add 0x[11 22 33] -e -i 1",
example: "0x[FF AA BB] | bytes add 0x[11 22 33] --end --index 1",
result: Some(Value::binary(vec![0xFF, 0xAA, 0x11, 0x22, 0x33, 0xBB],
Span::test_data(),
)),

View File

@ -89,12 +89,12 @@ impl Command for BytesIndexOf {
},
Example {
description: "Returns index of pattern, search from end",
example: " 0x[33 44 55 10 01 13 44 55] | bytes index-of -e 0x[44 55]",
example: " 0x[33 44 55 10 01 13 44 55] | bytes index-of --end 0x[44 55]",
result: Some(Value::test_int(6)),
},
Example {
description: "Returns all matched index",
example: " 0x[33 44 55 10 01 33 44 33 44] | bytes index-of -a 0x[33 44]",
example: " 0x[33 44 55 10 01 33 44 33 44] | bytes index-of --all 0x[33 44]",
result: Some(Value::list(
vec![Value::test_int(0), Value::test_int(5), Value::test_int(7)],
Span::test_data(),
@ -102,7 +102,7 @@ impl Command for BytesIndexOf {
},
Example {
description: "Returns all matched index, searching from end",
example: " 0x[33 44 55 10 01 33 44 33 44] | bytes index-of -a -e 0x[33 44]",
example: " 0x[33 44 55 10 01 33 44 33 44] | bytes index-of --all --end 0x[33 44]",
result: Some(Value::list(
vec![Value::test_int(7), Value::test_int(5), Value::test_int(0)],
Span::test_data(),

View File

@ -94,7 +94,7 @@ impl Command for BytesRemove {
},
Example {
description: "Remove all occurrences of find binary in record field",
example: "{ data: 0x[10 AA 10 BB 10] } | bytes remove -a 0x[10] data",
example: "{ data: 0x[10 AA 10 BB 10] } | bytes remove --all 0x[10] data",
result: Some(Value::test_record(Record {
cols: vec!["data".to_string()],
vals: vec![Value::test_binary(vec![0xAA, 0xBB])]
@ -102,7 +102,7 @@ impl Command for BytesRemove {
},
Example {
description: "Remove occurrences of find binary from end",
example: "0x[10 AA 10 BB CC AA 10] | bytes remove -e 0x[10]",
example: "0x[10 AA 10 BB CC AA 10] | bytes remove --end 0x[10]",
result: Some(Value::binary (
vec![0x10, 0xAA, 0x10, 0xBB, 0xCC, 0xAA],
Span::test_data(),

View File

@ -94,7 +94,7 @@ impl Command for BytesReplace {
},
Example {
description: "Find and replace all occurrences of find binary",
example: "0x[10 AA 10 BB 10] | bytes replace -a 0x[10] 0x[A0]",
example: "0x[10 AA 10 BB 10] | bytes replace --all 0x[10] 0x[A0]",
result: Some(Value::binary (
vec![0xA0, 0xAA, 0xA0, 0xBB, 0xA0],
Span::test_data(),
@ -102,7 +102,7 @@ impl Command for BytesReplace {
},
Example {
description: "Find and replace all occurrences of find binary in table",
example: "[[ColA ColB ColC]; [0x[11 12 13] 0x[14 15 16] 0x[17 18 19]]] | bytes replace -a 0x[11] 0x[13] ColA ColC",
example: "[[ColA ColB ColC]; [0x[11 12 13] 0x[14 15 16] 0x[17 18 19]]] | bytes replace --all 0x[11] 0x[13] ColA ColC",
result: Some(Value::list (
vec![Value::test_record(Record {
cols: vec!["ColA".to_string(), "ColB".to_string(), "ColC".to_string()],

View File

@ -85,18 +85,18 @@ impl Command for Fill {
Example {
description:
"Fill a string on the left side to a width of 15 with the character '─'",
example: "'nushell' | fill -a l -c '─' -w 15",
example: "'nushell' | fill --alignment l --character '─' --width 15",
result: Some(Value::string("nushell────────", Span::test_data())),
},
Example {
description:
"Fill a string on the right side to a width of 15 with the character '─'",
example: "'nushell' | fill -a r -c '─' -w 15",
example: "'nushell' | fill --alignment r --character '─' --width 15",
result: Some(Value::string("────────nushell", Span::test_data())),
},
Example {
description: "Fill a string on both sides to a width of 15 with the character '─'",
example: "'nushell' | fill -a m -c '─' -w 15",
example: "'nushell' | fill --alignment m --character '─' --width 15",
result: Some(Value::string("────nushell────", Span::test_data())),
},
Example {

View File

@ -115,8 +115,7 @@ impl Command for SubCommand {
)),
},
Example {
description:
"convert an integer to a nushell binary primitive with compact enabled",
description: "convert an int to a nushell binary primitive with compact enabled",
example: "10 | into binary --compact",
result: Some(Value::binary(vec![10], Span::test_data())),
},
@ -172,7 +171,7 @@ pub fn action(input: &Value, _args: &Arguments, span: Span) -> Value {
Value::Error { .. } => input.clone(),
other => Value::error(
ShellError::OnlySupportsThisInputType {
exp_input_type: "integer, float, filesize, string, date, duration, binary or bool"
exp_input_type: "int, float, filesize, string, date, duration, binary, or bool"
.into(),
wrong_type: other.get_type().to_string(),
dst_span: span,

View File

@ -90,7 +90,7 @@ impl Command for SubCommand {
result: Some(Value::bool(true, span)),
},
Example {
description: "convert integer to boolean",
description: "convert int to boolean",
example: "1 | into bool",
result: Some(Value::bool(true, span)),
},
@ -159,7 +159,7 @@ fn action(input: &Value, _args: &CellPathOnlyArgs, span: Span) -> Value {
Value::Error { .. } => input.clone(),
other => Value::error(
ShellError::OnlySupportsThisInputType {
exp_input_type: "bool, integer, float or string".into(),
exp_input_type: "bool, int, float or string".into(),
wrong_type: other.get_type().to_string(),
dst_span: span,
src_span: other.span(),

View File

@ -175,7 +175,7 @@ impl Command for SubCommand {
Example {
description:
"Convert non-standard timestamp string to datetime using a custom format",
example: "'20210227_135540+0000' | into datetime -f '%Y%m%d_%H%M%S%z'",
example: "'20210227_135540+0000' | into datetime --format '%Y%m%d_%H%M%S%z'",
#[allow(clippy::inconsistent_digit_grouping)]
result: example_result_1(1614434140_000000000),
},
@ -256,7 +256,7 @@ fn action(input: &Value, args: &Arguments, head: Span) -> Value {
other => {
return Value::error(
ShellError::OnlySupportsThisInputType {
exp_input_type: "string and integer".into(),
exp_input_type: "string and int".into(),
wrong_type: other.get_type().to_string(),
dst_span: head,
src_span: other.span(),

View File

@ -1,198 +0,0 @@
use nu_cmd_base::input_handler::{operate, CellPathOnlyArgs};
use nu_engine::CallExt;
use nu_protocol::{
ast::{Call, CellPath},
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, Record, ShellError, Signature, Span, SyntaxShape, Type, Value,
};
#[derive(Clone)]
pub struct SubCommand;
impl Command for SubCommand {
fn name(&self) -> &str {
"into decimal"
}
fn signature(&self) -> Signature {
Signature::build("into decimal")
.input_output_types(vec![
(Type::Int, Type::Float),
(Type::String, Type::Float),
(Type::Bool, Type::Float),
(Type::Float, Type::Float),
(Type::Table(vec![]), Type::Table(vec![])),
(Type::Record(vec![]), Type::Record(vec![])),
(
Type::List(Box::new(Type::Any)),
Type::List(Box::new(Type::Float)),
),
])
.rest(
"rest",
SyntaxShape::CellPath,
"for a data structure input, convert data at the given cell paths",
)
.allow_variants_without_examples(true)
.category(Category::Conversions)
}
fn usage(&self) -> &str {
"deprecated: convert data into a floating point number."
}
fn extra_usage(&self) -> &str {
"Use `into float` instead"
}
fn search_terms(&self) -> Vec<&str> {
vec!["convert", "number", "floating"]
}
fn run(
&self,
engine_state: &EngineState,
stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
nu_protocol::report_error_new(
engine_state,
&ShellError::GenericError(
"Deprecated command".into(),
"`into decimal` is deprecated and will be removed in 0.86.".into(),
Some(call.head),
Some("Use `into float` instead".into()),
vec![],
),
);
let cell_paths: Vec<CellPath> = call.rest(engine_state, stack, 0)?;
let args = CellPathOnlyArgs::from(cell_paths);
operate(action, args, input, call.head, engine_state.ctrlc.clone())
}
fn examples(&self) -> Vec<Example> {
vec![
Example {
description: "Convert string to float in table",
example: "[[num]; ['5.01']] | into decimal num",
result: Some(Value::list(
vec![Value::test_record(Record {
cols: vec!["num".to_string()],
vals: vec![Value::test_float(5.01)],
})],
Span::test_data(),
)),
},
Example {
description: "Convert string to float",
example: "'1.345' | into decimal",
result: Some(Value::test_float(1.345)),
},
Example {
description: "Coerce list of ints and floats to float",
example: "[4 -5.9] | into decimal",
result: Some(Value::test_list(vec![
Value::test_float(4.0),
Value::test_float(-5.9),
])),
},
Example {
description: "Convert boolean to float",
example: "true | into decimal",
result: Some(Value::test_float(1.0)),
},
]
}
}
fn action(input: &Value, _args: &CellPathOnlyArgs, head: Span) -> Value {
let span = input.span();
match input {
Value::Float { .. } => input.clone(),
Value::String { val: s, .. } => {
let other = s.trim();
match other.parse::<f64>() {
Ok(x) => Value::float(x, head),
Err(reason) => Value::error(
ShellError::CantConvert {
to_type: "float".to_string(),
from_type: reason.to_string(),
span,
help: None,
},
span,
),
}
}
Value::Int { val: v, .. } => Value::float(*v as f64, span),
Value::Bool { val: b, .. } => Value::float(
match b {
true => 1.0,
false => 0.0,
},
span,
),
// Propagate errors by explicitly matching them before the final case.
Value::Error { .. } => input.clone(),
other => Value::error(
ShellError::OnlySupportsThisInputType {
exp_input_type: "string, integer or bool".into(),
wrong_type: other.get_type().to_string(),
dst_span: head,
src_span: other.span(),
},
head,
),
}
}
#[cfg(test)]
mod tests {
use super::*;
use nu_protocol::Type::Error;
#[test]
fn test_examples() {
use crate::test_examples;
test_examples(SubCommand {})
}
#[test]
#[allow(clippy::approx_constant)]
fn string_to_decimal() {
let word = Value::test_string("3.1415");
let expected = Value::test_float(3.1415);
let actual = action(&word, &CellPathOnlyArgs::from(vec![]), Span::test_data());
assert_eq!(actual, expected);
}
#[test]
fn communicates_parsing_error_given_an_invalid_decimallike_string() {
let decimal_str = Value::test_string("11.6anra");
let actual = action(
&decimal_str,
&CellPathOnlyArgs::from(vec![]),
Span::test_data(),
);
assert_eq!(actual.get_type(), Error);
}
#[test]
fn int_to_decimal() {
let decimal_str = Value::test_int(10);
let expected = Value::test_float(10.0);
let actual = action(
&decimal_str,
&CellPathOnlyArgs::from(vec![]),
Span::test_data(),
);
assert_eq!(actual, expected);
}
}

View File

@ -136,7 +136,7 @@ pub fn action(input: &Value, _args: &CellPathOnlyArgs, span: Span) -> Value {
Value::Nothing { .. } => Value::filesize(0, value_span),
other => Value::error(
ShellError::OnlySupportsThisInputType {
exp_input_type: "string and integer".into(),
exp_input_type: "string and int".into(),
wrong_type: other.get_type().to_string(),
dst_span: span,
src_span: value_span,

View File

@ -121,7 +121,7 @@ fn action(input: &Value, _args: &CellPathOnlyArgs, head: Span) -> Value {
Value::Error { .. } => input.clone(),
other => Value::error(
ShellError::OnlySupportsThisInputType {
exp_input_type: "string, integer or bool".into(),
exp_input_type: "string, int or bool".into(),
wrong_type: other.get_type().to_string(),
dst_span: head,
src_span: other.span(),

View File

@ -158,32 +158,32 @@ impl Command for SubCommand {
fn examples(&self) -> Vec<Example> {
vec![
Example {
description: "Convert string to integer in table",
description: "Convert string to int in table",
example: "[[num]; ['-5'] [4] [1.5]] | into int num",
result: None,
},
Example {
description: "Convert string to integer",
description: "Convert string to int",
example: "'2' | into int",
result: Some(Value::test_int(2)),
},
Example {
description: "Convert float to integer",
description: "Convert float to int",
example: "5.9 | into int",
result: Some(Value::test_int(5)),
},
Example {
description: "Convert decimal string to integer",
description: "Convert decimal string to int",
example: "'5.9' | into int",
result: Some(Value::test_int(5)),
},
Example {
description: "Convert file size to integer",
description: "Convert file size to int",
example: "4KB | into int",
result: Some(Value::test_int(4000)),
},
Example {
description: "Convert bool to integer",
description: "Convert bool to int",
example: "[false, true] | into int",
result: Some(Value::list(
vec![Value::test_int(0), Value::test_int(1)],
@ -191,33 +191,33 @@ impl Command for SubCommand {
)),
},
Example {
description: "Convert date to integer (Unix nanosecond timestamp)",
description: "Convert date to int (Unix nanosecond timestamp)",
example: "1983-04-13T12:09:14.123456789-05:00 | into int",
result: Some(Value::test_int(419101754123456789)),
},
Example {
description: "Convert to integer from binary",
example: "'1101' | into int -r 2",
description: "Convert to int from binary data (radix: 2)",
example: "'1101' | into int --radix 2",
result: Some(Value::test_int(13)),
},
Example {
description: "Convert to integer from hex",
example: "'FF' | into int -r 16",
description: "Convert to int from hex",
example: "'FF' | into int --radix 16",
result: Some(Value::test_int(255)),
},
Example {
description: "Convert octal string to integer",
description: "Convert octal string to int",
example: "'0o10132' | into int",
result: Some(Value::test_int(4186)),
},
Example {
description: "Convert 0 padded string to integer",
description: "Convert 0 padded string to int",
example: "'0010132' | into int",
result: Some(Value::test_int(10132)),
},
Example {
description: "Convert 0 padded string to integer with radix",
example: "'0010132' | into int -r 8",
description: "Convert 0 padded string to int with radix 8",
example: "'0010132' | into int --radix 8",
result: Some(Value::test_int(4186)),
},
]
@ -248,7 +248,7 @@ fn action(input: &Value, args: &Arguments, span: Span) -> Value {
return Value::error(
ShellError::CantConvert {
to_type: "float".to_string(),
from_type: "integer".to_string(),
from_type: "int".to_string(),
span,
help: None,
},
@ -327,7 +327,7 @@ fn action(input: &Value, args: &Arguments, span: Span) -> Value {
Value::Error { .. } => input.clone(),
other => Value::error(
ShellError::OnlySupportsThisInputType {
exp_input_type: "integer, float, filesize, date, string, binary, duration or bool"
exp_input_type: "int, float, filesize, date, string, binary, duration, or bool"
.into(),
wrong_type: other.get_type().to_string(),
dst_span: span,
@ -376,7 +376,7 @@ fn convert_int(input: &Value, head: Span, radix: u32) -> Value {
other => {
return Value::error(
ShellError::OnlySupportsThisInputType {
exp_input_type: "string and integer".into(),
exp_input_type: "string and int".into(),
wrong_type: other.get_type().to_string(),
dst_span: head,
src_span: other.span(),

View File

@ -2,22 +2,22 @@ mod binary;
mod bool;
mod command;
mod datetime;
mod decimal;
mod duration;
mod filesize;
mod float;
mod int;
mod record;
mod string;
mod value;
pub use self::bool::SubCommand as IntoBool;
pub use self::filesize::SubCommand as IntoFilesize;
pub use binary::SubCommand as IntoBinary;
pub use command::Into;
pub use datetime::SubCommand as IntoDatetime;
pub use decimal::SubCommand as IntoDecimal;
pub use duration::SubCommand as IntoDuration;
pub use float::SubCommand as IntoFloat;
pub use int::SubCommand as IntoInt;
pub use record::SubCommand as IntoRecord;
pub use string::SubCommand as IntoString;
pub use value::IntoValue;

View File

@ -84,37 +84,25 @@ impl Command for SubCommand {
fn examples(&self) -> Vec<Example> {
vec![
Example {
description: "convert integer to string and append three decimal places",
example: "5 | into string -d 3",
description: "convert int to string and append three decimal places",
example: "5 | into string --decimals 3",
result: Some(Value::test_string("5.000")),
},
Example {
description: "convert float to string and round to nearest integer",
example: "1.7 | into string -d 0",
example: "1.7 | into string --decimals 0",
result: Some(Value::test_string("2")),
},
Example {
description: "convert float to string",
example: "1.7 | into string -d 1",
example: "1.7 | into string --decimals 1",
result: Some(Value::test_string("1.7")),
},
Example {
description: "convert float to string and limit to 2 decimals",
example: "1.734 | into string -d 2",
example: "1.734 | into string --decimals 2",
result: Some(Value::test_string("1.73")),
},
Example {
description: "try to convert float to string and provide negative decimal points",
example: "1.734 | into string -d -2",
result: None,
// FIXME
// result: Some(Value::Error {
// error: ShellError::UnsupportedInput(
// String::from("Cannot accept negative integers for decimals arguments"),
// Span::test_data(),
// ),
// }),
},
Example {
description: "convert float to string",
example: "4.3 | into string",

View File

@ -0,0 +1,474 @@
use crate::parse_date_from_string;
use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, IntoInterruptiblePipelineData, PipelineData, PipelineIterator, ShellError,
Signature, Span, SyntaxShape, Type, Value,
};
use once_cell::sync::Lazy;
use regex::{Regex, RegexBuilder};
use std::{collections::HashSet, iter::FromIterator};
#[derive(Clone)]
pub struct IntoValue;
impl Command for IntoValue {
fn name(&self) -> &str {
"into value"
}
fn signature(&self) -> Signature {
Signature::build("into value")
.input_output_types(vec![(Type::Table(vec![]), Type::Table(vec![]))])
.named(
"columns",
SyntaxShape::Table(vec![]),
"list of columns to update",
Some('c'),
)
.allow_variants_without_examples(true)
.category(Category::Filters)
}
fn usage(&self) -> &str {
"Infer nushell datatype for each cell."
}
fn examples(&self) -> Vec<Example> {
vec![
Example {
description: "Infer Nushell values for each cell.",
example: "$table | into value",
result: None,
},
Example {
description: "Infer Nushell values for each cell in the given columns.",
example: "$table | into value -c [column1, column5]",
result: None,
},
]
}
fn run(
&self,
engine_state: &EngineState,
stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let engine_state = engine_state.clone();
let metadata = input.metadata();
let ctrlc = engine_state.ctrlc.clone();
let span = call.head;
// the columns to update
let columns: Option<Value> = call.get_flag(&engine_state, stack, "columns")?;
let columns: Option<HashSet<String>> = match columns {
Some(val) => {
let cols = val
.as_list()?
.iter()
.map(|val| val.as_string())
.collect::<Result<Vec<String>, ShellError>>()?;
Some(HashSet::from_iter(cols))
}
None => None,
};
Ok(UpdateCellIterator {
input: input.into_iter(),
columns,
span,
}
.into_pipeline_data(ctrlc)
.set_metadata(metadata))
}
}
struct UpdateCellIterator {
input: PipelineIterator,
columns: Option<HashSet<String>>,
span: Span,
}
impl Iterator for UpdateCellIterator {
type Item = Value;
fn next(&mut self) -> Option<Self::Item> {
match self.input.next() {
Some(val) => {
if let Some(ref cols) = self.columns {
if !val.columns().iter().any(|c| cols.contains(c)) {
return Some(val);
}
}
let span = val.span();
match val {
Value::Record { val, .. } => Some(Value::record(
val.into_iter()
.map(|(col, val)| match &self.columns {
Some(cols) if !cols.contains(&col) => (col, val),
_ => (
col,
match process_cell(val, span) {
Ok(val) => val,
Err(err) => Value::error(err, span),
},
),
})
.collect(),
span,
)),
val => match process_cell(val, self.span) {
Ok(val) => Some(val),
Err(err) => Some(Value::error(err, self.span)),
},
}
}
None => None,
}
}
}
// This function will check each cell to see if it matches a regular expression
// for a particular datatype. If it does, it will convert the cell to that datatype.
fn process_cell(val: Value, span: Span) -> Result<Value, ShellError> {
// step 1: convert value to string
let val_str = val.as_string().unwrap_or_default();
// step 2: bounce string up against regexes
if BOOLEAN_RE.is_match(&val_str) {
let bval = val_str
.parse::<bool>()
.map_err(|_| ShellError::CantConvert {
to_type: "string".to_string(),
from_type: "bool".to_string(),
span,
help: Some(format!(
r#""{val_str}" does not represent a valid boolean value"#
)),
})?;
Ok(Value::bool(bval, span))
} else if FLOAT_RE.is_match(&val_str) {
let fval = val_str
.parse::<f64>()
.map_err(|_| ShellError::CantConvert {
to_type: "string".to_string(),
from_type: "float".to_string(),
span,
help: Some(format!(
r#""{val_str}" does not represent a valid floating point value"#
)),
})?;
Ok(Value::float(fval, span))
} else if INTEGER_RE.is_match(&val_str) {
let ival = val_str
.parse::<i64>()
.map_err(|_| ShellError::CantConvert {
to_type: "string".to_string(),
from_type: "int".to_string(),
span,
help: Some(format!(
r#""{val_str}" does not represent a valid integer value"#
)),
})?;
Ok(Value::int(ival, span))
} else if INTEGER_WITH_DELIMS_RE.is_match(&val_str) {
let mut val_str = val_str;
val_str.retain(|x| !['_', ','].contains(&x));
let ival = val_str
.parse::<i64>()
.map_err(|_| ShellError::CantConvert {
to_type: "string".to_string(),
from_type: "int".to_string(),
span,
help: Some(format!(
r#""{val_str}" does not represent a valid integer value"#
)),
})?;
Ok(Value::int(ival, span))
} else if DATETIME_DMY_RE.is_match(&val_str) {
let dt = parse_date_from_string(&val_str, span).map_err(|_| ShellError::CantConvert {
to_type: "date".to_string(),
from_type: "string".to_string(),
span,
help: Some(format!(
r#""{val_str}" does not represent a valid DATETIME_MDY_RE value"#
)),
})?;
Ok(Value::date(dt, span))
} else if DATETIME_YMD_RE.is_match(&val_str) {
let dt = parse_date_from_string(&val_str, span).map_err(|_| ShellError::CantConvert {
to_type: "date".to_string(),
from_type: "string".to_string(),
span,
help: Some(format!(
r#""{val_str}" does not represent a valid DATETIME_YMD_RE value"#
)),
})?;
Ok(Value::date(dt, span))
} else if DATETIME_YMDZ_RE.is_match(&val_str) {
let dt = parse_date_from_string(&val_str, span).map_err(|_| ShellError::CantConvert {
to_type: "date".to_string(),
from_type: "string".to_string(),
span,
help: Some(format!(
r#""{val_str}" does not represent a valid DATETIME_YMDZ_RE value"#
)),
})?;
Ok(Value::date(dt, span))
} else {
// If we don't know what it is, just return whatever it was passed in as
Ok(val)
}
}
// region: datatype regexes
const DATETIME_DMY_PATTERN: &str = r#"(?x)
^
['"]? # optional quotes
(?:\d{1,2}) # day
[-/] # separator
(?P<month>[01]?\d{1}) # month
[-/] # separator
(?:\d{4,}) # year
(?:
[T\ ] # separator
(?:\d{2}) # hour
:? # separator
(?:\d{2}) # minute
(?:
:? # separator
(?:\d{2}) # second
(?:
\.(?:\d{1,9}) # subsecond
)?
)?
)?
['"]? # optional quotes
$
"#;
static DATETIME_DMY_RE: Lazy<Regex> =
Lazy::new(|| Regex::new(DATETIME_DMY_PATTERN).expect("datetime_dmy_pattern should be valid"));
const DATETIME_YMD_PATTERN: &str = r#"(?x)
^
['"]? # optional quotes
(?:\d{4,}) # year
[-/] # separator
(?P<month>[01]?\d{1}) # month
[-/] # separator
(?:\d{1,2}) # day
(?:
[T\ ] # separator
(?:\d{2}) # hour
:? # separator
(?:\d{2}) # minute
(?:
:? # separator
(?:\d{2}) # seconds
(?:
\.(?:\d{1,9}) # subsecond
)?
)?
)?
['"]? # optional quotes
$
"#;
static DATETIME_YMD_RE: Lazy<Regex> =
Lazy::new(|| Regex::new(DATETIME_YMD_PATTERN).expect("datetime_ymd_pattern should be valid"));
//2023-03-24 16:44:17.865147299 -05:00
const DATETIME_YMDZ_PATTERN: &str = r#"(?x)
^
['"]? # optional quotes
(?:\d{4,}) # year
[-/] # separator
(?P<month>[01]?\d{1}) # month
[-/] # separator
(?:\d{1,2}) # day
[T\ ] # separator
(?:\d{2}) # hour
:? # separator
(?:\d{2}) # minute
(?:
:? # separator
(?:\d{2}) # second
(?:
\.(?:\d{1,9}) # subsecond
)?
)?
\s? # optional space
(?:
# offset (e.g. +01:00)
[+-](?:\d{2})
:?
(?:\d{2})
# or Zulu suffix
|Z
)
['"]? # optional quotes
$
"#;
static DATETIME_YMDZ_RE: Lazy<Regex> =
Lazy::new(|| Regex::new(DATETIME_YMDZ_PATTERN).expect("datetime_ymdz_pattern should be valid"));
static FLOAT_RE: Lazy<Regex> = Lazy::new(|| {
Regex::new(r"^\s*[-+]?((\d*\.\d+)([eE][-+]?\d+)?|inf|NaN|(\d+)[eE][-+]?\d+|\d+\.)$")
.expect("float pattern should be valid")
});
static INTEGER_RE: Lazy<Regex> =
Lazy::new(|| Regex::new(r"^\s*-?(\d+)$").expect("integer pattern should be valid"));
static INTEGER_WITH_DELIMS_RE: Lazy<Regex> = Lazy::new(|| {
Regex::new(r"^\s*-?(\d{1,3}([,_]\d{3})+)$")
.expect("integer with delimiters pattern should be valid")
});
static BOOLEAN_RE: Lazy<Regex> = Lazy::new(|| {
RegexBuilder::new(r"^\s*(true)$|^(false)$")
.case_insensitive(true)
.build()
.expect("boolean pattern should be valid")
});
// endregion:
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_examples() {
use crate::test_examples;
test_examples(IntoValue {})
}
#[test]
fn test_float_parse() {
// The regex should work on all these but nushell's float parser is more strict
assert!(FLOAT_RE.is_match("0.1"));
assert!(FLOAT_RE.is_match("3.0"));
assert!(FLOAT_RE.is_match("3.00001"));
assert!(FLOAT_RE.is_match("-9.9990e-003"));
assert!(FLOAT_RE.is_match("9.9990e+003"));
assert!(FLOAT_RE.is_match("9.9990E+003"));
assert!(FLOAT_RE.is_match("9.9990E+003"));
assert!(FLOAT_RE.is_match(".5"));
assert!(FLOAT_RE.is_match("2.5E-10"));
assert!(FLOAT_RE.is_match("2.5e10"));
assert!(FLOAT_RE.is_match("NaN"));
assert!(FLOAT_RE.is_match("-NaN"));
assert!(FLOAT_RE.is_match("-inf"));
assert!(FLOAT_RE.is_match("inf"));
assert!(FLOAT_RE.is_match("-7e-05"));
assert!(FLOAT_RE.is_match("7e-05"));
assert!(FLOAT_RE.is_match("+7e+05"));
}
#[test]
fn test_int_parse() {
assert!(INTEGER_RE.is_match("0"));
assert!(INTEGER_RE.is_match("1"));
assert!(INTEGER_RE.is_match("10"));
assert!(INTEGER_RE.is_match("100"));
assert!(INTEGER_RE.is_match("1000"));
assert!(INTEGER_RE.is_match("10000"));
assert!(INTEGER_RE.is_match("100000"));
assert!(INTEGER_RE.is_match("1000000"));
assert!(INTEGER_RE.is_match("10000000"));
assert!(INTEGER_RE.is_match("100000000"));
assert!(INTEGER_RE.is_match("1000000000"));
assert!(INTEGER_RE.is_match("10000000000"));
assert!(INTEGER_RE.is_match("100000000000"));
assert!(INTEGER_WITH_DELIMS_RE.is_match("1_000"));
assert!(INTEGER_WITH_DELIMS_RE.is_match("10_000"));
assert!(INTEGER_WITH_DELIMS_RE.is_match("100_000"));
assert!(INTEGER_WITH_DELIMS_RE.is_match("1_000_000"));
assert!(INTEGER_WITH_DELIMS_RE.is_match("10_000_000"));
assert!(INTEGER_WITH_DELIMS_RE.is_match("100_000_000"));
assert!(INTEGER_WITH_DELIMS_RE.is_match("1_000_000_000"));
assert!(INTEGER_WITH_DELIMS_RE.is_match("10_000_000_000"));
assert!(INTEGER_WITH_DELIMS_RE.is_match("100_000_000_000"));
assert!(INTEGER_WITH_DELIMS_RE.is_match("1,000"));
assert!(INTEGER_WITH_DELIMS_RE.is_match("10,000"));
assert!(INTEGER_WITH_DELIMS_RE.is_match("100,000"));
assert!(INTEGER_WITH_DELIMS_RE.is_match("1,000,000"));
assert!(INTEGER_WITH_DELIMS_RE.is_match("10,000,000"));
assert!(INTEGER_WITH_DELIMS_RE.is_match("100,000,000"));
assert!(INTEGER_WITH_DELIMS_RE.is_match("1,000,000,000"));
assert!(INTEGER_WITH_DELIMS_RE.is_match("10,000,000,000"));
}
#[test]
fn test_bool_parse() {
assert!(BOOLEAN_RE.is_match("true"));
assert!(BOOLEAN_RE.is_match("false"));
assert!(!BOOLEAN_RE.is_match("1"));
assert!(!BOOLEAN_RE.is_match("0"));
}
#[test]
fn test_datetime_ymdz_pattern() {
assert!(DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00Z"));
assert!(DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00.123456789Z"));
assert!(DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00+01:00"));
assert!(DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00.123456789+01:00"));
assert!(DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00-01:00"));
assert!(DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00.123456789-01:00"));
assert!(DATETIME_YMDZ_RE.is_match("'2022-01-01T00:00:00Z'"));
assert!(!DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00"));
assert!(!DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00."));
assert!(!DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00.123456789"));
assert!(!DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00+01"));
assert!(!DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00+01:0"));
assert!(!DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00+1:00"));
assert!(!DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00.123456789+01"));
assert!(!DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00.123456789+01:0"));
assert!(!DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00.123456789+1:00"));
assert!(!DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00-01"));
assert!(!DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00-01:0"));
assert!(!DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00-1:00"));
assert!(!DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00.123456789-01"));
assert!(!DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00.123456789-01:0"));
assert!(!DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00.123456789-1:00"));
}
#[test]
fn test_datetime_ymd_pattern() {
assert!(DATETIME_YMD_RE.is_match("2022-01-01"));
assert!(DATETIME_YMD_RE.is_match("2022/01/01"));
assert!(DATETIME_YMD_RE.is_match("2022-01-01T00:00:00"));
assert!(DATETIME_YMD_RE.is_match("2022-01-01T00:00:00.000000000"));
assert!(DATETIME_YMD_RE.is_match("'2022-01-01'"));
// The regex isn't this specific, but it would be nice if it were
// assert!(!DATETIME_YMD_RE.is_match("2022-13-01"));
// assert!(!DATETIME_YMD_RE.is_match("2022-01-32"));
// assert!(!DATETIME_YMD_RE.is_match("2022-01-01T24:00:00"));
// assert!(!DATETIME_YMD_RE.is_match("2022-01-01T00:60:00"));
// assert!(!DATETIME_YMD_RE.is_match("2022-01-01T00:00:60"));
assert!(!DATETIME_YMD_RE.is_match("2022-01-01T00:00:00.0000000000"));
}
#[test]
fn test_datetime_dmy_pattern() {
assert!(DATETIME_DMY_RE.is_match("31-12-2021"));
assert!(DATETIME_DMY_RE.is_match("01/01/2022"));
assert!(DATETIME_DMY_RE.is_match("15-06-2023 12:30"));
assert!(!DATETIME_DMY_RE.is_match("2022-13-01"));
assert!(!DATETIME_DMY_RE.is_match("2022-01-32"));
assert!(!DATETIME_DMY_RE.is_match("2022-01-01 24:00"));
}
}

View File

@ -98,7 +98,7 @@ fn timezone_offset_internal(
};
match s.len() {
len if len >= 2 => &s[2..],
len if len == 0 => s,
0 => s,
_ => return Err(ParseErrorKind::TooShort),
};

View File

@ -149,7 +149,7 @@ impl Command for Ast {
},
Example {
description: "Print the ast of a pipeline with an error, as json, minified",
example: "ast 'for x in 1..10 { echo $x ' -j -m",
example: "ast 'for x in 1..10 { echo $x ' --json --minify",
result: None,
},
]

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