Compare commits

...

278 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
a6f62e05ae Bump version for the 0.85 release (#10425) 2023-09-19 21:42:47 +03:00
f8939de14f Remove str replace --string after deprecation (#10064)
related to
- https://github.com/nushell/nushell/pull/10038

# Description
`str replace --string` has been deprecated in
https://github.com/nushell/nushell/pull/10038 and should be removed
before 0.85.

this PR removes the `--string` option from `str replace` completely.

# User-Facing Changes
`str replace --string` will no longer work and will give an error
instead of a warning.
2023-09-19 15:54:20 +02:00
01ade02ac1 Pin reedline to 0.24 for release (#10426)
See release notes:
https://github.com/nushell/reedline/releases/tag/v0.24.0
2023-09-19 15:21:09 +02:00
39d93b536a Bump toml from 0.7.6 to 0.8.0 (#10408)
Bumps [toml](https://github.com/toml-rs/toml) from 0.7.6 to 0.8.0.
<details>
<summary>Commits</summary>
<ul>
<li><a
href="310f6ee9c5"><code>310f6ee</code></a>
chore: Release</li>
<li><a
href="90da8bc425"><code>90da8bc</code></a>
docs: Update changelog</li>
<li><a
href="f3e120f1a0"><code>f3e120f</code></a>
Merge pull request <a
href="https://redirect.github.com/toml-rs/toml/issues/608">#608</a> from
epage/enum</li>
<li><a
href="58a7101f68"><code>58a7101</code></a>
fix(serde): Support struct variants as table of a table</li>
<li><a
href="88a4dba312"><code>88a4dba</code></a>
fix(serde): Support tuple variants as table of an array</li>
<li><a
href="cf06b83424"><code>cf06b83</code></a>
test(serde): Verify both Table and Value serializers</li>
<li><a
href="4ffa44ec16"><code>4ffa44e</code></a>
test(serde): Make parameter order more consistent</li>
<li><a
href="2b7c34c900"><code>2b7c34c</code></a>
test(serde): Focus on string serialization first</li>
<li><a
href="e2a6a1cece"><code>e2a6a1c</code></a>
test(serde): Verify existing variant behavior</li>
<li><a
href="3f3e8329bb"><code>3f3e832</code></a>
chore: Release</li>
<li>Additional commits viewable in <a
href="https://github.com/toml-rs/toml/compare/toml-v0.7.6...toml-v0.8.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=toml&package-manager=cargo&previous-version=0.7.6&new-version=0.8.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-18 13:50:30 +08:00
32f67557af Bump terminal_size from 0.2.6 to 0.3.0 (#10409)
Bumps [terminal_size](https://github.com/eminence/terminal-size) from
0.2.6 to 0.3.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/eminence/terminal-size/releases">terminal_size's
releases</a>.</em></p>
<blockquote>
<h2>v0.3.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Check all streams (out/err/in) to find one that has a tty and size
by <a href="https://github.com/eminence"><code>@​eminence</code></a> in
<a
href="https://redirect.github.com/eminence/terminal-size/pull/58">eminence/terminal-size#58</a>
<ul>
<li>Note that this is a subtle change in behavior, since the
<code>terminal_size()</code> function will now return success in cases
more cases than before</li>
</ul>
</li>
<li>Update to rustix 0.38 by <a
href="https://github.com/chenx97"><code>@​chenx97</code></a> in <a
href="https://redirect.github.com/eminence/terminal-size/pull/57">eminence/terminal-size#57</a>
<ul>
<li>This change bumps the MSRV from 1.48.0 to 1.63.0</li>
</ul>
</li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/eminence/terminal-size/compare/v0.2.6...v0.3.0">https://github.com/eminence/terminal-size/compare/v0.2.6...v0.3.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="2983b7bf18"><code>2983b7b</code></a>
Release v0.3.0</li>
<li><a
href="27a4459b22"><code>27a4459</code></a>
Merge pull request <a
href="https://redirect.github.com/eminence/terminal-size/issues/57">#57</a>
from chenx97/rustix-0.38</li>
<li><a
href="c24c1c34e5"><code>c24c1c3</code></a>
Bump MSRV to 1.63.0</li>
<li><a
href="78e13c77d7"><code>78e13c7</code></a>
Update to rustix 0.38</li>
<li><a
href="18c58b1ed5"><code>18c58b1</code></a>
Merge pull request <a
href="https://redirect.github.com/eminence/terminal-size/issues/58">#58</a>
from eminence/check_all_streams</li>
<li><a
href="08f0e73926"><code>08f0e73</code></a>
Check all streams (out/err/in) to find one that has a tty and size</li>
<li>See full diff in <a
href="https://github.com/eminence/terminal-size/compare/v0.2.6...v0.3.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=terminal_size&package-manager=cargo&previous-version=0.2.6&new-version=0.3.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-18 13:50:17 +08:00
f05eed8e8d Bump mockito from 1.1.0 to 1.2.0 (#10407)
Bumps [mockito](https://github.com/lipanski/mockito) from 1.1.0 to
1.2.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/lipanski/mockito/releases">mockito's
releases</a>.</em></p>
<blockquote>
<h2>1.2.0</h2>
<ul>
<li><strong>[Breaking]</strong> The minimum supported Rust version was
bumped to 1.68.0</li>
<li>The server pool was limited to 20 servers for <code>mac_os</code>
targets to prevent hitting the file descriptor limit</li>
</ul>
<p>Thanks to <a
href="https://github.com/kornelski"><code>@​kornelski</code></a></p>
<h2>1.1.1</h2>
<ul>
<li><a
href="https://redirect.github.com/lipanski/mockito/pull/176">Ensure</a>
<code>with_chunked_body</code> supports streaming responses (as opposed
to writing the entire buffer in one go)</li>
</ul>
<p>Thanks to <a
href="https://github.com/kornelski"><code>@​kornelski</code></a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="7514e38524"><code>7514e38</code></a>
Bump to 1.2.0</li>
<li><a
href="be00de417e"><code>be00de4</code></a>
Merge pull request <a
href="https://redirect.github.com/lipanski/mockito/issues/177">#177</a>
from kornelski/pool</li>
<li><a
href="6b4073e911"><code>6b4073e</code></a>
MSRV</li>
<li><a
href="9faa825110"><code>9faa825</code></a>
Test exhausting server pool</li>
<li><a
href="3099e94471"><code>3099e94</code></a>
Simplify server pool</li>
<li><a
href="99735e7c41"><code>99735e7</code></a>
Bump to 1.1.1</li>
<li><a
href="3b63970619"><code>3b63970</code></a>
Merge pull request <a
href="https://redirect.github.com/lipanski/mockito/issues/176">#176</a>
from kornelski/stream</li>
<li><a
href="339bffc983"><code>339bffc</code></a>
Support streaming body</li>
<li><a
href="8b7575cd38"><code>8b7575c</code></a>
Simplify server pool test</li>
<li>See full diff in <a
href="https://github.com/lipanski/mockito/compare/1.1.0...1.2.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=mockito&package-manager=cargo&previous-version=1.1.0&new-version=1.2.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-18 13:50:08 +08:00
f0a265dbee Adapt for improved history isolation in reedline (#10402)
Depends on https://github.com/nushell/reedline/pull/634

---------

Co-authored-by: WindSoilder <WindSoilder@outlook.com>
2023-09-18 13:49:26 +08:00
bc7736bc99 Add 2 fuzzers for nu-path, nu-parser (#10376)
# Description

This PR adds a fuzzer for the nu-path and the nu-parser crate.
Now you can go to `crates/nu-path/fuzz`/`crates/nu-parser/fuzz` and run `cargo fuzz` to
find crashes.
https://github.com/nushell/nushell/issues/10365 and #9417 was found by
this


---------

Co-authored-by: sholderbach <sholderbach@users.noreply.github.com>
2023-09-16 22:32:53 +02:00
19d732f313 Clippy in tests (#10394)
Running `cargo clippy --workspace --tests`

We should move that to CI as well
2023-09-16 21:49:10 +02:00
a9a82de5c4 fix some new chrono warnings (#10384)
# Description

This PR cleans up some warnings on the latest chrono dependency.

# 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-15 15:46:25 -05:00
9074015d1c Adds mimalloc as default feature. (#10378)
<!--
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 makes `mimalloc` the default allocator, it has been the default
on the nightly builds of nushell now for a couple of months and the
performance improvements are quite nice, measuring upwards of 30% faster
startup time on Windows, and a bit smaller on Linux,
https://github.com/nushell/nushell/pull/9415

# 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-15 14:17:33 -05:00
2b77544e58 nu-table: Fix expand table unnessary color in trail head config when wrap is used (#10367)
So it must address it,
But please check.

PS: I don't like the patch... but it is what it is

fix: #10359
cc: @amtoine
2023-09-15 11:44:53 -05:00
5ee74b6ab5 fix input --until-bytes: now stops at any of given bytes (#10235)
- this PR should close #10197

# Description
`input --bytes-until` takes a string but used to only terminate on the
first byte of that string. Now it checks for each byte in the string.

# User-Facing Changes
all of the above. No change in documentation needed. New behavior
arguably fits better.

# Tests + Formatting
don't know how to test input
2023-09-15 06:55:37 -05:00
3a04bd9154 fix the pretty printing of failing tests in std (#10373)
related to
-
https://github.com/nushell/nushell/pull/10293/files#diff-371ea1a6b13ef0f2f10ddd0b23b86c54eb8221892e45c2e4c1913a233c585ae7R137

# Description
looks to me like https://github.com/nushell/nushell/pull/10293
introduced the use of `map` command in `std testing`, but it's not a
valid Nushell command, right?

this PR uses `each` as a replacement, that's what the error even says
2023-09-14 20:11:08 +02:00
2c176a7f14 Ps: add cwd column on linux and macos (#10347)
# Description
Close:  #7484

Just found that I want `cwd` column on linux/macos as well..
2023-09-14 08:10:15 -05:00
JT
026e18399e fix 'let' to properly redirect (#10360)
# Description

Fixes a bug in `let` where the pipeline wasn't being properly
redirected.

fixes #9767

# User-Facing Changes

Shouldn't have any breaking changes, as this should be better for
expected use cases.

# 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-14 10:18:29 +12:00
bbf0b45c59 Update internal use of decimal to float (#10333)
# Description
We made the decision that our floating point type should be referred to
as `float` over `decimal`.
Commands were updated by #9979 and #10320

Now make the internal codebase consistent in referring to this data type
as `float`.

Work for #10332

# User-Facing Changes

`decimal` has been removed as a type name/symbol. 

Instead of 
```nushell
def foo [bar: decimal] decimal -> decimal {}
```
use 
```nushell
def foo [bar: float] float -> float {}
```

Potential effect of `SyntaxShape`'s `Display` implementation now also
referring to `float` instead of `decimal`

# Details
- Rename `SyntaxShape::Decimal` to `Float`
- Update `Display for SyntaxShape` to `float`
- Update error message + fn name in dataframe code
- Fix docs in command examples
- Rename tests that are float specific
- Update doccomment on `SyntaxShape`
- Update comment in script

# Tests + Formatting
Updates the names of some tests
2023-09-13 23:53:55 +02:00
5bd7300cd5 add helper switch to move cursor to end of buffer (#10354)
# Description

This PR adds a helper flag named `--cursor-end`/`-e` that allows you to
set the cursor to the end of the buffer. Before this, you'd have to do
something like `--cursor 100` where you're guessing that 100 would be
longer than the buffer and just put it at the end.

# 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-13 12:44:09 -05:00
ffb5051f6c nu-table: Strip custom color in the header when used on border (#10357)
ref: #10351
cc: @fdncred
2023-09-13 12:11:00 -05:00
ce4ea16c08 fix #10319: allow json request of value type list (#10356)
# Description

this commit adds the handling of Value::List when BodyType is Json
it also adds the corresponding test (trying to send a list)

Fixes #10319

# User-Facing Changes

Added the ability to send a json list in the POST message

# Tests + Formatting
- [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

Also ran `nc -l -p 8080` in other terminal and `http post -fe -t
application/json http://localhost:8080 [{ field: true }]` I see the
following appear in the output of nc:
```
POST / HTTP/1.1
Host: localhost:8080
User-Agent: nushell
Accept: */*
Content-Type: application/json
accept-encoding: gzip
Content-Length: 16

[{"field":true}]%
```
2023-09-13 16:54:03 +02:00
48c94c75fc Optimize use of range in std repeat (#10353)
# Description
By using a `from: 1` the additional subexpression for `to` becomes
unnecessary.

Saves additional evaluation steps if `std repeat` is frequently used
with low `n`

# User-Facing Changes
None

# Tests + Formatting
(-)
2023-09-13 07:50:09 -05:00
73d3708006 Patch restore lead trail space bg color (#10351)
```nu
 $env.config.color_config.leading_trailing_space_bg = { bg: 'white' }; [[a b, 'c   ']; ['  1  ' '    2' '3    '] ['  4  ' "hello   \n  world  " ['  1  ' 2 [1 '  2  ' 3]]]] | table --expand
```


![image](https://github.com/nushell/nushell/assets/20165848/01a35042-0e36-4c51-99a9-3011fabb551b)

ref: #2794
close: #10317

note: test are not actually make scenes cause `nu!` strips colors.
(Ideally it would need a flag to not do so)
note: It does does does ... slower down quite a bit rendering... (

PS: Maybe it's better being a flag to `table` rather then a
configuration option?
PS: I am not sure why the logic was removed in a first place
2023-09-13 07:47:53 -05:00
bbea7da669 Remove select error if same row/column is provided (#10350)
This PR is in reference to #10215.

This PR changes `select` to work even if multiple equal items were
provided.
This would previously error, but now works
```nushell
let arg = [ 1 a ]
[[a b c]; [1 2 3] [4 5 6] [7 8 9]] 
| select $arg

```
# User-Facing Changes

Nothing too radical, just experience improvements. Users won't need to
pass the values through `unique` beforehand.
2023-09-13 13:49:55 +02:00
7f39609d9a Remove python-like string multiplication (#10293)
# Description
Currently we support "multiplication" of strings, resulting in a terse
way to repeat a particular string.
This can have unintended side effects when dealing with mixed data (e.g.
after parsing data that is not all numbers).
Furthermore as we frequently fall-back to strings while parsing source
code, this introduced a runaway edge case in const evaluation (#10212)

Work for #10233

## Details
- Remove python-like string multiplication.
- Workaround for indentation
  - This should probably be addressed with a purpose built command
- Remove special const-eval error test

# User-Facing Changes
**Major breaking change!**
`"string" * 42` will stop working. (This was used for example in the
stdlib)

We should bless a good alternative before landing this

---------

Co-authored-by: JT <547158+jntrnr@users.noreply.github.com>
2023-09-13 19:52:04 +12:00
a14e9e0a2e Invert &Options to Option<&T> (#10315)
Elide the reference for `Copy` type (`usize`)
Use the canonical deref where possible.
* `&Box` -> `&`
* `&String` -> `&str`
* `&PathBuf` -> `&Path`

Skips the ctrl-C handler for now.
2023-09-13 07:00:58 +08:00
3e14dc3eb8 Remove pythonic int * list behavior (#10292)
# Description
The pythonism that multiplying a scalar integer with a list results in a
repeated concatenation of the list, is ambiguous with other possible
interpretations and thus actively harmful to clear semantics in nushell.

Another possible reading of this scalar/vector product would be trying
to perform elementwise multiplication with the scalar.

Before we bless this alternative as a more reasonable design the best
course of action is to remove this pythonism.

Work related to #10233


# User-Facing Changes
Breaking change as this turns `int * list` or `list * int` into hard
errors.

# Tests + Formatting
Remove the associated test
2023-09-13 10:43:49 +12:00
ba6d8ad261 add std repeat command to replace "foo" * 3 (#10339)
related to
- https://github.com/nushell/nushell/issues/10233
- https://github.com/nushell/nushell/pull/10293
- https://github.com/nushell/nushell/pull/10292

inspired by @kubouch 

# Description
this PR adds a `repeat` command to the standard library

# User-Facing Changes
a new `repeat` command in `std`
```nushell
repeat anything a bunch of times, yielding a list of *n* times the input

# Examples
    repeat a string
    > "foo" | std repeat 3 | str join
    "foofoofoo"

Usage:
  > repeat <n>

Flags:
  -h, --help - Display the help message for this command

Parameters:
  n <int>: the number of repetitions, must be positive

Input/output types:
  ╭───┬───────┬───────────╮
  │ # │ input │  output   │
  ├───┼───────┼───────────┤
  │ 0 │ any   │ list<any> │
  ╰───┴───────┴───────────╯
```

# Tests + Formatting
a new test called `repeat_things` in `test_std.nu`

# After Submitting
2023-09-12 21:59:31 +02:00
2a08865851 add a few more columns to linux ps -l output (#10344)
# Description

This PR tried to add a few more columns to the Linux `ps -l` command.
Those columns are:
* start_time
* user_id
* priority
* process_threads

There are a few that I left commented out that could be added but the
screen was beginning to look crowded. So, I left out:
* group_id
* session_id
* tgp_id (which could be helpful for eventual job control)

And there's like 100 more things that could be added that didn't seem
especially useful right now.


![image](https://github.com/nushell/nushell/assets/343840/065c0538-8f7d-4c9f-871f-a1bc98aff9d1)


# 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-12 14:50:05 -05:00
0a3bfe7f73 Allow parse-time evaluation of if (#10326) 2023-09-12 21:35:47 +03:00
JT
451a9c64d3 Change echo to print when not redirected (#10338)
# Description

This changes `echo` to work more closely to what users of other shells
would expect:

* when redirected, `echo` works as before and sends values through the
pipeline
* when not redirected, `echo` will print values to the screen/terminal

# User-Facing Changes

A standalone `echo` now will print to the terminal, if not redirected.

The `echo` command is no longer const eval-able, as it will now print to
the terminal in some cases.

# 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-13 06:35:01 +12:00
88d79c84cd Update Nu to v0.84 for release and nightly-build (#10334)
<!--
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
Update Nu to v0.84 for release and nightly-build
2023-09-12 22:00:58 +08:00
abcb0877e2 Upgrade softprops/action-gh-release to v0.1.15 for release and nightly build workflow (#10331) 2023-09-12 21:05:55 +08:00
9e1e2a4320 provide env to commands and try to start provided path (#10302)
fixes #8551

# Description
Use `open::commands` function to get list of command available for
starting given path. run commands directly, providing environment, until
one of them is successful.

example of output if start was not successful:
```
~\code\nushell> start ..\nustart\a.myext                                                                    09/12/2023 01:37:55 PM
Error: nu:🐚:external_command

  × External command failed
   ╭─[entry #1:1:1]
 1 │ start ..\nustart\a.myext
   ·       ─────────┬────────
   ·                ╰── No command found to start with this path
   ╰────
  help: Try different path or install appropriate command

        Command `cmd /c start "" "..\nustart\a.myext"` failed with exit code: 1
```

# User-Facing Changes
`start` command now provides environment to the external command. This
is how it worked in `nu 0.72`, see linked issue.

# Tests + Formatting
`start` command didn't have any tests and this PR does not add any.
Integration-level tests will require setup specific to OS and
potentially change global environment on testing machine. For unit-level
test it is possible to test `try_commands` function. But is still runs
external commands, and robust test will require apriori knowledge which
commands are necessary successful to run and which are not.
2023-09-12 14:03:41 +02:00
d53b0a99d0 Rename random decimal to random float (#10320)
# Description
Similar to #9979

# User-Facing Changes
`random decimal` will now raise a warning and can be removed in an
upcoming release.

New command is named `random float`

# Tests + Formatting
Tests updated and improved.
2023-09-12 13:03:05 +02:00
1fb4f9e455 Rename into decimal to into float (#9979)
# Description
We keep "into decimal" for a release and warn through a message that it
will be removed in 0.86.

All tests are updated to use `into float`

# User-Facing Changes
`into decimal` raises a deprecation warning, will be removed soon.
Use `into float` as the new functionally identical command instead.

```
~/nushell> 2 | into decimal
Error:   × Deprecated command
   ╭─[entry #1:1:1]
 1 │ 2 | into decimal
   ·     ──────┬─────
   ·           ╰── `into decimal` is deprecated and will be removed in 0.86.
   ╰────
  help: Use `into float` instead


2
```

# Tests + Formatting
Updated

---------

Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2023-09-12 13:02:47 +02:00
6e9b6f22c9 Deref &String arguments to &str where appropriate (#10321)
# Description
This generally makes for nicer APIs, as you are not forced to use an
existing allocation covering the full `String`.

Some exceptions remain where the underlying type requirements favor it.

# User-Facing Changes
None
2023-09-12 14:06:56 +08:00
e90b099622 Use slices directly instead of &Vec (#10328)
Simplifies the signature, makes it more flexible.
Detected a few unnecessary allocations in the process.
2023-09-12 11:38:20 +08:00
JT
84c10de864 remove profiling from nushell's hot loop (#10325)
# Description

This removes pipeline element profiling. This could be a useful feature,
but pipeline elements are going to be the most sensitive to in terms of
performance, as `eval_block` and how pipelines are built is one of the
hot loops inside of the eval engine.

# User-Facing Changes

Removes pipeline element profiling.

# 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-12 06:50:03 +12:00
d618b60d9e Remove leftover const eval file (#10324) 2023-09-11 21:30:38 +03:00
c761f7f844 add 'from ndjson' into standard library (#10283)
close #8574
related #10276 
# Description

added below into standard library
```
def "from ndjson" []: string -> any {
    from json --objects
}
```

# User-Facing Changes


Users can use functions like "from ndjson" in standard library, and can
open ndjson files with `open` command.
```
use std formats *
# `from ndjson` is available now
open sample.ndjson
```

# Tests + Formatting

`toolkit check pr`

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


# After Submitting

---------

Co-authored-by: Stefan Holderbach <sholderbach@users.noreply.github.com>
2023-09-11 14:59:07 +02:00
7b89fab327 Keep order for par-each (#10249)
# Description
This PR adds new flag `--keep-order/-k` for the `par_each` filter. This
flag keeps sequence of output same as the order of input.

Output without the flag:
```nu
> 1..6 | par-each {|n| $n * 2 }
╭────╮
│  4 │
│ 10 │
│  2 │
│  8 │
│ 12 │
│  6 │
╰────╯
```

Output with the `--keep-order` flag:
```nu
> 1..6 | par-each --keep-order {|n| $n * 2 }
╭────╮
│  2 │
│  4 │
│  6 │
│  8 │
│ 10 │
│ 12 │
╰────╯
```

I think the presence of this flag is justified, since:
- Much easier to use than `.. | enumerate | par-each {|p| update item
..} | sort-by index | get item`
- Faster, as it uses internally parallel sorting in the same thread pool

A note about naming: it may conflict with `--keep-empty/-k` flag of the
`each` filter if the same feature will be used in `par-each`, so maybe
it needs some other name.
2023-09-11 06:42:09 -05:00
eddff46155 Bump calamine and fix clippy (#10314)
Upgrade calamine to 0.22
Reduces one potential dependency duplication

Supersedes #10305

Includes fixes for clippy lints as API changed to return owned data.
2023-09-11 12:39:52 +02:00
baa50ec9b2 Update crates-ci/typos and fix new typos (#10313)
Supersedes #10309
2023-09-11 12:37:06 +02:00
513186c390 Bump bytesize from 1.2.0 to 1.3.0 (#10306) 2023-09-11 09:55:21 +00:00
0c37463bfa Bump tempfile from 3.7.0 to 3.8.0 (#10307) 2023-09-11 09:54:49 +00:00
94fc33bbee Bump actions/checkout from 3 to 4 (#10308) 2023-09-11 09:54:22 +00:00
ce378a68a6 Fix variables not allowed in ucp (#10304)
<!--
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
Fixes #10300 , where using variables didnt work with `ucp` as it was
only expecting a `Expr::FilePath`.

Before: (from the issue)
```
❯ ucp -r $var $folder
Error:   × Missing file operand
   ╭─[entry #40:1:1]
 1 │ ucp -r $var $folder
   · ─┬─
   ·  ╰── Missing file operand
   ╰────
  help: Please provide source and destination paths
```
Now:
```
`ucp -r $var $folder`
# success
```

Also added the test to ensure its working:) . Oh, and I tweaked again
slightly the messages on two tests because now the whole `path` is
printed rather than `a`. Say:
```
#before
`cp a a` --> 'a' and 'a' are the same file 
# now
`cp a a` --> /home/current/location/a and /home/current/location/a are the same file
```
<!--
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:

- [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-10 17:54:33 -05:00
fa40740e77 add case-insensitive example to where (#10299)
related to
-
https://discord.com/channels/601130461678272522/614593951969574961/1150395064292495400

# Description
two cool things about the `where` command
- it's versatile enough to allow creating a case-insensitive version of
itself
- it does not require the explicit use of a closure

this PR adds an example showing how to filter with `where` but
case-insensitively and without an explicite closure.

# User-Facing Changes
new example to `where`:
```nushell
  Find case-insensitively files called "readme", without an explicit closure
  > ls | where ($it.name | str downcase) =~ readme
```

# Tests + Formatting
the new example test above.

# After Submitting
2023-09-10 15:24:38 -05:00
762fdb98ac silence some ucp warnings (#10294)
# Description

This PR fixes some ucp warnings.

# 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-09 19:41:53 -05:00
5f795b1aec Mention that perl is required for feature static-link-openssl… (#10291)
this PR should close https://github.com/nushell/nushell/issues/10290

it is a simple comment in Cargo.toml, which explains that perl is
required for feature static-link-openssl to work.
2023-09-09 22:34:07 +02:00
6811700b90 update reject to be able to recive arg list (#10216)
This PR is in relation to #10215 

# Description

This PR introduces `reject` to receive list of columns or rows as
argument.
This change is similar to change of `select` and the code used is
similar.

# User-Facing Changes
The user will be able to pass a list as rejection arguments.
```nushell
let arg = [ type size ]
[[name type size]; [ cargo.toml file 20mb ] [ Cargo.lock file 20mb] [src dir 100mb]] | reject $arg
```
2023-09-09 15:01:25 -05:00
248aca7a44 reject multiple row args support (#10163)
# Description
This PR fixes `reject` failing when providing row items in ascending
order.


# User-Facing Changes
users can now `reject` multiple rows independently of each other.
```nushell
let foo = [[a b]; [ 1 2] [3 4] [ 5 6]]
# this will work independant of the order
print ($foo | reject 2 1)
print ($foo | reject 1 2)
```

---------

Co-authored-by: Antoine Stevan <44101798+amtoine@users.noreply.github.com>
2023-09-09 13:59:31 -05:00
17abbdf6e0 allow into duration to take an integer amount of ns (#10286)
related to
-
https://discord.com/channels/601130461678272522/615329862395101194/1149717458786197524

# Description
because `1_234 | into datetime` takes an integer number of `ns` and
`1_234 | into filesize` takes an integer amount of bytes, i think `1_234
| into duration` should also be valid and see `1_234` as an integer
amount of `ns` 😋

# User-Facing Changes
## before
either
```nushell
1234 | into string | $in ++ "ns" | into duration
```
```nushell
1234 | $"($in)ns" | into duration
```
or
```nushell
1234 * 1ns
```
and
```nushell
> 1_234 | into duration
Error: nu::parser::input_type_mismatch

  × Command does not support int input.
   ╭─[entry #2:1:1]
 1 │ 1_234 | into duration
   ·         ──────┬──────
   ·               ╰── command doesn't support int input
   ╰────
```

## after
```nushell
> 1_234 | into duration
1µs 234ns
```

# Tests + Formatting
new example test
```rust
Example {
    description: "Convert a number of ns to duration",
    example: "1_234_567 | into duration",
    result: Some(Value::duration(1_234_567, span)),
}
```

# After Submitting
2023-09-09 13:49:08 -05:00
40eca52ed5 allow update to use metadata (#10264)
# Description

This PR is an attempt to fix the `update` command so that it passes
along metadata. I'm not really sure I did this right, so please feel
free to point out where it's wrong.

The point is to be able to do something like this and have it respect
your LS_COLORS.
```
ls | update modified { format date }
```
### Before

![image](https://github.com/nushell/nushell/assets/343840/fc3eb207-4f6f-42b1-b5a4-87a1fe194399)

### After

![image](https://github.com/nushell/nushell/assets/343840/19d58443-7c88-4dd6-9532-1f45f615ac7b)


# 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-09 13:47:42 -05:00
7907dda8f7 Make cursor_shape optional (#10289)
# Description
There are several cursor shape related issues #7151 #9243 #7271 #8452
#10169, you can't disable the cursor shape feature even if you comment
out the entire `cursor_shape` block in the config.nu, and even worse,
when nushell exits with an error, the cursor shape can't be restored,
that is annoying.

This PR provides an opportunity to disable setting the cursor shape.

# User-Facing Changes
If you use the default config.nu, nothing changes, but if you comment
out `cursor_shape` block or set them to `inherit`, related cursor shape
will not be set.

# 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-09 13:42:36 -05:00
8501024546 signpost 'input list --types [key]' from 'keybindings list' (#10287)
Supercedes https://github.com/nushell/nushell/pull/10196

# Description

After reading
https://github.com/nushell/nushell/pull/10196#issuecomment-1703986359 I
added a signpost from `keybindings listen` to `input listen`

When I initially tried `input listen` it always immediately returned
with:
```
╭───────┬────────╮
│ type  │ focus  │
│ event │ gained │
╰───────┴────────╯
```

I added an example to `input listen --help` to suggest only listening to
key events

Initially I also included a `result` but it prints as:

```
  ╭───────────┬───────────────╮
  │ type      │ key           │
  │ key_type  │ char          │
  │ code      │ c             │
  │ modifiers │ [list 1 item] │
  ╰───────────┴───────────────╯
```

rather than:

```
╭───────────┬───────────────────────────────╮
│ type      │ key                           │
│ key_type  │ char                          │
│ code      │ c                             │
│           │ ╭───┬───────────────────────╮ │
│ modifiers │ │ 0 │ keymodifiers(control) │ │
│           │ ╰───┴───────────────────────╯ │
╰───────────┴───────────────────────────────╯
```
so I removed it.

# User-Facing Changes

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

* Example describing how to use `input list --types [key]` to listen for
keybindings.
* Signpost pointing at `use std input; input list --types [key]` from
`keybindings list`.

## After merging

It is probably worth:

a) signposting to the keybindings section of the book from both of these
subcommands (like I did in
https://github.com/nushell/nushell/pull/10193),
b) giving an example in the book of how to take the output from `input
listen --types [key]` and format it for including in `config nu`
c) there are not currently any examples in
crates/nu-utils/src/sample_config/default_config.nu for keybindings with
multiple modifiers. Should I add alt+backspace-in-macos-vscode as an
example (gets translated to `{ modifier: control_alt keycode: char_h }`
for historical reasons)?

---------

Co-authored-by: Antoine Stevan <44101798+amtoine@users.noreply.github.com>
2023-09-09 09:42:37 -05:00
21d30d1e4d Fix rm on macOS (#10282)
# Description

Removes the signal ignore for `SIGCHLD` added by #10021, since it
interferes with `rm` on macOS.
2023-09-08 19:03:30 -05:00
eeaa65c8af Bump itertools from 0.10.5 to 0.11.0 (#9524) 2023-09-08 23:12:45 +00:00
6754b8534e Remove Cargo.lock in subcrates (#10280)
This should not be there in a workspace crate.

[See cargo
docs](https://doc.rust-lang.org/cargo/reference/workspaces.html)

Causes a spurious dependabot alert and is not easily updated.
2023-09-09 00:45:43 +02:00
2ffff959fc add 6 more table themes (#10279)
# Description

After looking at a users terminal that didn't support UTF-8, I wanted to
add some themes that may help them. Here's what they look like.

## psql

![image](https://github.com/nushell/nushell/assets/343840/67ac003a-72f1-4e2b-8bb0-244b70385d59)

## markdown

![image](https://github.com/nushell/nushell/assets/343840/a8f4a439-013b-48ee-b9e0-284ec47d1eef)

## dots
please excuse the different theme

![image](https://github.com/nushell/nushell/assets/343840/fb931650-cc64-4f0a-bf3d-ec736e0374ad)

## restructured

![image](https://github.com/nushell/nushell/assets/343840/80595a8e-f2b3-49dc-ad02-81e94bde5253)

## ascii_rounded

![image](https://github.com/nushell/nushell/assets/343840/42f0b8b2-1fd2-4ae5-b28c-477e83ded354)

## basic_compact

![image](https://github.com/nushell/nushell/assets/343840/5888b6b2-b9b8-48bc-963e-5a76ef246adc)


# 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-08 16:34:36 -05:00
fed4233db4 use uutils/coreutils cp command in place of nushell's cp command (#10097)
<!--
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
Hi. Basically, this is a continuation of the work that @fdncred started.
Given some nice discussions on #9463 , and [merged uutils
PR](https://github.com/uutils/coreutils/pull/5152) from @tertsdiepraam
we have decided to give the `cp` command the `crawl` stage as it was
named.

> [!NOTE] 
Given that the `uutils` crate has not made the release for the merged
PR, just make sure you checkout latest and put it in the required place
to make this PR work.

The aim of this PR is for is to see how to move forward using `uutils`
crate. In order to getting this started, I have made the current
`nushell cp tests` pass along with some extra ones I copied over from
the `uutils` repo.

With all of that being said, things that would be nice to decide, and
keep working on:

Crawl:
- Handling of certain `named` flags, with their long and short
forms(e.g. --update, --reflink, --preserve, etc), and using default
values. Maybe `-u` can already have a `default_missing_value`.
- Should we maybe just support one single option `switch` flags (see
`--backup` in code) as a contrast to the other named args.
- Complete test coverage from `uutils`. They had > 100 tests, and I
could only port like 12 as they are a bit time consuming given they
cannot be straight up copy pasted. Maybe we do not need all >100, but
maybe the more relevant to what we want.
- Refactor this code

Walk:
- Non fatal errors on `copy` from `utils`. Currently it just sends it to
stdout but errors have no span
- Better integration 

An added possibility is the addition of `SyntaxShape::OneOf()` for
`Named` arguments which was briefly mentioned in the discord server, but
that is still to be decided. This could greatly improve some of the
integration. This would enable something like `cp --preserve [all
timestamp]` or `cp --preserve all` to both work.

I did not want to keep holding on this, and wait till I was happy with
the code because I think its nice if everyone can start up and suggest
refactors, but the main important part now was getting it out the door,
as if I take my sweet time this will take way longer 😛

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

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

---------

Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2023-09-08 13:57:38 -05:00
2f47263380 respect a users locale with the right prompt (#10273)
# Description

This PR tries to respect a person's locale setting with date/time in the
default right prompt. This also restores the right prompt so that it
does not load from the US default from reedline.

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


Here's the fromat reference if anyone thinks there's a better time
format. I could be talked into `%c` maybe.
https://docs.rs/chrono/latest/chrono/format/strftime/index.html

# 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-08 12:24:42 -05:00
4d5386635e add more ps columns in Windows (#10275)
# Description

This PR adds a few more columns to `ps -l` on Windows. It would be good
to add these changes cross-platform in separate PRs. This PR also fixes
a bug where start time was calculated wrong.

I've added:
start_time
user
user_sid
priority


![image](https://github.com/nushell/nushell/assets/343840/cba16a17-ee70-46b5-9e6d-ef06641b264e)

# 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-08 12:24:29 -05:00
872eb2c3df Restore initial foreground process group on exit (#10021)
# Description
When launching nushell interactively from another shell, the parent
shell usually gives us own our process group and handles restoring
control to itself. However, other programs that do not support job
control expect us to give control of the terminal back to them. This PR
makes it so that we record the initial foreground process group and
restore it when nushell exits. An "exit" can be from the `exit` command,
a panic, or a `SIGTERM` signal.

The changes in `terminal.rs` mostly follow [fish's
example](0874dd6a96/fish-rust/src/common.rs (L1634)).

# User-Facing Changes
Fixes interactions between nushell and other interactive CLI commands
(e.g., VIFM #10015).
2023-09-08 18:19:01 +02:00
e62a77a885 Start removing colour config from explore (#10270)
This PR removes the `explore.try.border_color` config item, and instead
always uses the `separator` colour (the one used for regular table
borders) from the current theme.

The PR also removes some unused `explore.config` bits from the default
config (I missed this in https://github.com/nushell/nushell/pull/10259).

### Future Work

This PR is intentionally small, I want to confirm that I'm on the right
track before I rip out more colour config from `explore`. If all goes
well, expect more PRs like this soon.

### Testing

I confirmed that this works by changing my `separator` colour in
`config.nu`, and also confirmed that nothing breaks if a user still has
`explore.try.border_color` in their config.
2023-09-08 07:34:47 -07:00
9bca63ebef update format date when using %x %X %r (#10272)
# Description

Apparently some strftime formats are already localized and when you
"double localize" them, they don't work. This PR fixes that so that %x
%X %r %c don't go through the localization step.

Example: %x %X
### Before
```nushell
❯ date now | format date "%x %X %p"
09/08/2023 08 AM
```
### After
```nushell
❯ date now | format date "%x %X %p"
09/08/23 08:09:14 AM
```

I started to make one format_datetime to rule them all but one returns a
string and one returns a value. If we convert to the string, we lose the
nice error messages. If we change to value, more code has to be changed
elsewhere. So, I decided to just leave two functions.

# 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-08 08:59:05 -05:00
ae54dc862c Move spellcheck config into .github folder (#10267)
Keep the `.typos.toml` out of the repo root for better readability

Also specify a version for the workflow to protect against breakage
2023-09-07 22:46:00 +02:00
5e951b2be9 Remove codecov.io setup (#10266)
As we currently don't run the coverage in CI and don't upload to
codecov.io remove the config to clean up the repo root.
2023-09-07 22:12:23 +02:00
f78d57a703 feat: Search terms for use, while, and range (#5093) (#10265)
# Description

Add search terms to the commands: `use` ("environment", "import"),
`while` ("loop"), and `range` ("filter", "head", "tail").

# Tests + Formatting
All completed successfully.

---------

Co-authored-by: Stefan Holderbach <sholderbach@users.noreply.github.com>
2023-09-07 22:11:42 +02:00
f021be623e Exit explore on ctrl+c/d/q (#10257)
Currently, `ctrl+z` is the command to exit `explore` no matter where you
are in the UI. IMO this is a bit unintuitive since that's usually used
to suspend a process.

After this change, `ctrl+c`, `ctrl+d`, and `ctrl+q` all work to exit
`explore`.

I think these are all shortcuts that users might try when attempting to
exit `explore`, and I think we might as well handle them all.
2023-09-07 19:47:17 +02:00
b6189879e3 explore: remove :config, :show-config, :tweak commands (#10259)
More trimming of underused `explore` functionality.

The `explore` command has subcommands that can be run like `:config` or
`:try` or whatnot. This PR removes the `:config`, `:show-config`, and
`:tweak` commands which are all for viewing+modifying config.

These are interesting commands and they were cool experiments, but
ultimately I don't think they fit with our plans for a simplified
`explore`. They'd need a lot more polish if we want to keep them and I
don't think we do. Happy to discuss if I've missed a good reason to keep
these.

cc @fdncred
2023-09-07 10:34:08 -05:00
c7c6445b03 Remove exit_esc and show_banner config from explore (#10258)
Removing 2 underused config options from `explore`.

`show_banner` controls whether `For help type :help"` is shown in the
message area when `explore is first launched. I don't think there's any
good reason not to show it, it's not a modal dialog or anything.

`exit_esc` controls whether to exit `explore` when `esc` is pressed and
we can't "go up" any further (or at least that's what it's supposed to
do, looking at the code I'm not so sure). IMO we don't need to make this
kind of basic interaction configurable unless there's a really good
reason.

## Context

`explore` is complicated and we want to overhaul its design. It will be
easier to make meaningful changes if `explore` is a little slimmer
first, so I'm trying to pare back unused/underused code and config as a
starting point.

I'm gonna be making more PRs like this, I'll try to keep them
small+self-contained.
2023-09-07 14:39:04 +02:00
535aec0648 readme: add dorothy to supported by (#10262)
Add Dorothy — https://github.com/bevry/dorothy — to the supported by
section. Dorothy is a dotfile ecosystem that enables a cross-shell and
cross-operating system dotfile experience. Allowing you to easily switch
to Nu, while keeping your existing env configuration, and allowing you
to write Nu commands that are accessible to other shells.

Dorothy  now has CI testing for its Nu integration.
2023-09-07 13:58:31 +02:00
664dd291eb Restore NU_LIB_DIRS and NU_PLUGIN_DIRS defaults (#10252)
# Description

This PR reverts some changes to NU_LIB_DIRS and NU_PLUGIN_DIRS in the
default_env.config file. Our practice is to have default configs that
match if you were to run `nu -n`. I agree with this goal, but until
someone adds NU_LIB_DIRS and NU_PLUGIN_DIRS, we should revert this
change and not penalize users, breaking their scripts that run with `nu
-c blah` when `blah` is located in the default_env's NU_LIB_DIRS.


# 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-06 22:00:55 +02:00
a9216deaa4 allow --login to be used with nu's --commands parameter (#10253)
# Description

This PR allows the `--login`/`-l` parameter to be used with nushell's
`--commands`/`-c` parameter. When you do this, since you're invoking it
with the `-l` flag, nushell will load your env.nu, config.nu, and
login.nu, in that order. Then it will proceed to run your commands. I
think this provides a better quality of life when you want to run
scripts with your personal config files as a login shell.


### Before (these entries are from the default_env.nu)

![image](https://github.com/nushell/nushell/assets/343840/ce7adcd0-419e-485c-b7d1-f11f162e8e9e)


### After (these entries are from my personal env.nu)

![image](https://github.com/nushell/nushell/assets/343840/33bbc06b-983c-4461-8274-290e4c712506)


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

# 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-06 13:27:16 -05:00
99caad7d60 nu-explore: Refactorings (#10247)
1. Added mode to the status bar right most corner
2. Added a command name with a status when run

ref #8582 
cc: @fdncred
2023-09-06 13:24:24 -05:00
7486850357 rename the types with spaces in them to use - (#9929)
# Description
before this PR,
```nushell
> $.a.b | describe
cell path
```
which feels inconsistent with the `cell-path` type annotation, like in
```nushell
> def foo [x: cell-path] { $x | describe }; foo $.a.b
cell path
```

this PR changes the name of the "cell path" type from `cell path` to
`cell-path`

# User-Facing Changes
`cell path` is now `cell-path` in the output of `describe`.
this might be a breaking change in some scripts.

same goes with
- `list stream` -> `list-stream`
- `match pattern` -> `match-pattern`

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

this PR adds a new `cell_path_type` test to make sure it stays equal to
`cell-path` in the future.

# After Submitting

---------

Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2023-09-06 13:22:12 -05:00
bb06661d24 Document that open looks up from subcommands (#10255)
# Description
Related to https://github.com/nushell/nushell.github.io/pull/1048

Include this information in the command help.


# User-Facing Changes
As soon as this information is documented people are much more likely to
depend on it so we need to be careful in the future if this design
sparks joy or not.
2023-09-06 19:26:53 +02:00
6a374182a7 change LOG_FORMAT to NU_LOG_FORMAT in nu-std library (#10254)
this closes #10248 

@fdncred pointed out the problem and he was correct 😄 

I went ahead and made the simple change and the
https://github.com/influxdata/influxdb_iox binary
works like a charm...

@amtoine hopefully there are no issues with this change

I believe its a good one as other rust binaries might take advantage of
this common
environment variable as well...
2023-09-06 10:17:14 -07:00
f433b3102f fix default after an empty where (#10240)
should close https://github.com/nushell/nushell/issues/10237

# Description
this is @fdncred's findings 😋 
i just made the PR 😌 

# User-Facing Changes
```nushell
[a b] | where $it == 'c' | last | default 'd'
```
now works and gives `d`


# Tests + Formatting
adds a new `default_after_empty_filter` test.

# After Submitting
2023-09-06 16:39:35 +08:00
456e2a8ee3 move math constants to standard library (#9678)
# Description
we talked about this before in some meetings so i thought, why not?

the hope is that these constants do not require Rust code to be
implemented and that this move will make the Rust source base a bit
smaller 🤞

# User-Facing Changes
mathematical constants (e, pi, tau, phi and gamma) are now in `std math`
rather than `math`

## what can be done
```nushell
> use std; $std.math
> use std math; $math
> use std *; $math
```
will all give
```
╭───────┬────────────────────╮
│ GAMMA │ 0.5772156649015329 │
│ E     │ 2.718281828459045  │
│ PI    │ 3.141592653589793  │
│ TAU   │ 6.283185307179586  │
│ PHI   │ 1.618033988749895  │
╰───────┴────────────────────╯
```
and the following will work too
```nushell
> use std math E; $E
2.718281828459045
```
```nushell
> use std math *; $GAMMA
0.5772156649015329
```

## what can NOT be done
looks like every export works fine now 😌 

# Tests + Formatting
# After Submitting
2023-09-05 19:32:31 +02:00
1ee3bf784c Tweak contributor image to include more users (#10238)
We previously had a limit of 500 users but we are well past that
2023-09-05 16:52:21 +02:00
54394fe9af Allow operator in constants (#10212)
This pr fixes https://github.com/nushell/nushell/issues/10200

# Description

Allow unary and binary operators in constants, e.g.

```bash
const a = 1 + 2
const b = [0, 1, 2, 3] ++ [4]
```

# User-Facing Changes

Now constants can contain operators.

# Tests + Formatting

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

# After Submitting

None

---------

Co-authored-by: Horasal <horsal@horsal.dev>
2023-09-05 16:35:58 +02:00
7a728340de return error when user break sleep by ctrl-c (#10234)
# Description

Closes: #10218
I think this is `sleep`'s specific issue, it's because it always return
a `Value::nothing` where it's interrupted by `ctrl-c`.

To fix the issue, I'd propose to make it returns Err(ShellError)

This is how it behaves:
```nushell
❯ sleep 5sec; echo "hello!"
^CError: nu:🐚:sleep_breaked

  × Sleep is breaked.

❯ sleep 5sec; ^echo "hello!"
^CError: nu:🐚:sleep_breaked

  × Sleep is breaked.
```
# User-Facing Changes
None

# Tests + Formatting


# After Submitting
2023-09-05 09:21:30 -05:00
5f1e8a6af8 Clean up trash support on Android (#10225)
# Description

Currently on Android, there are warnings about unused variables. This PR
fixes that with more conditional guards for the unused variables.

Additionally, in #10013, @kubouch gave feedback in [the last
PR](https://github.com/nushell/nushell/pull/10013#pullrequestreview-1596828128)
that it was unwieldy to repeat

```rust
#[cfg(all(
    feature = "trash-support",
    not(target_os = "android"),
    not(target_os = "ios")
))]
```
2023-09-05 14:38:23 +02:00
e566a073dc Exit early when encountering parsing errors (#10213)
# Description
This PR tries to fix #10184 and #10182.
2023-09-05 14:36:37 +02:00
9a4dad6ca1 Fix unit tests on Android (#10224)
# Description

* The path to the binaries for tests is slightly incorrect. It is
missing the build target when it is set with the `CARGO_BUILD_TARGET`
environment variable. For example, when `CARGO_BUILD_TARGET` is set to
`aarch64-linux-android`, the path to the `nu` binary is:

  `./target/aarch64-linux-android/debug/nu`

  rather than

  `./target/debug/nu`

This is common on Termux since the default target that rustc detects can
cause problems on some projects, such as [python's `cryptography`
package](https://github.com/pyca/cryptography/issues/7248).
  
This technically isn't a problem specific to Android, but is more likely
to happen on Android due to the latter.
* Additionally, the existing variable named `NUSHELL_CARGO_TARGET` is in
fact the profile, not the build target, so this was renamed to
`NUSHELL_CARGO_PROFILE`. This change is included because without the
rename, the build system would be using `CARGO_BUILD_TARGET` for the
build target and `NUSHELL_CARGO_TARGET` for the build profile, which is
confusing.
* `std path add` tests were missing `android` test

# User-Facing Changes

For those who would like to build nushell on Termux, the unit tests will
pass now.
2023-09-05 20:17:34 +12:00
eca9f461da Make append/prepend consistent for ranges (#10231)
# Description
This PR makes `append`/`prepend` more consistent, in particular, it allows you to
work with ranges. Previously, you couldn't append a list by range:
```nu
> 0..1 | append 2..4
╭──────╮
│    0 │
│    1 │
│ 2..4 │
╰──────╯
```

Now it works:
```nu
> 0..1 | append 2..4
╭───╮
│ 0 │
│ 1 │
│ 2 │
│ 3 │
│ 4 │
╰───╯
```

# User-Facing Changes
If someone needs the old behavior, then it can be obtained like this:
```nu
> 0..1 | append [2..4]
╭──────╮
│    0 │
│    1 │
│ 2..4 │
╰──────╯
```
2023-09-05 01:47:51 +02:00
08aaa9494c Bump rust-embed from 6.8.1 to 8.0.0 (#10208) 2023-09-04 21:16:44 +00:00
352f913c39 Bump git2 from 0.17.2 to 0.18.0 (#10207) 2023-09-04 21:10:25 +00:00
aeeb5dd405 Bump winreg from 0.50.0 to 0.51.0 (#10209) 2023-09-04 21:05:00 +00:00
278bf7ffa9 upgrade nix to 0.27 (#10223)
This fixes a segfault on Android when fetching the user group.

See: https://github.com/nix-rust/nix/issues/2084
2023-09-04 22:41:28 +02:00
b15c824932 Fix example history command pipeline (#10220)
the example for `history` was out of date, this PR updates it.

## the failing command
```
❯ history | wrap cmd | where cmd =~ cargo
Error: nu:🐚:type_mismatch

  × Type mismatch during operation.
   ╭─[entry #23:1:1]
 1 │ history | wrap cmd | where cmd =~ cargo
   · ───┬───                        ─┬ ──┬──
   ·    │                            │   ╰── string
   ·    │                            ╰── type mismatch for operator
   ·    ╰── record<start_timestamp: string, command: string, cwd: string, duration: duration, exit_status: int>
   ╰────
```
2023-09-04 19:17:56 +02:00
5ad3bfa31b Auto format let-else block (#10214)
<!--
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.
-->
rustfmt 1.6.0 has added support for formatting [let-else
statements](https://doc.rust-lang.org/rust-by-example/flow_control/let_else.html)

See https://github.com/rust-lang/rustfmt/blob/master/CHANGELOG.md#added

# 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-04 19:42:31 +12:00
e5145358eb treat path contains '?' as pattern (#10142)
Fix https://github.com/nushell/nushell/issues/10136

# Description
Current nushell only handle path containing '*' as match pattern and
treat '?' as just normal path.
This pr makes path containing '?' is also processed as pattern.

🔴 **Concerns: Need to design/comfirm a consistent rule to handle
dirs/files with '?' in their names.**

Currently:

- if no dir has exactly same name with pattern, it will print the list
of matched directories
- if pattern exactly matches an empty dir's name, it will just print the
empty dir's content ( i.e. `[]`)
- if pattern exactly matches an dir's name, it will perform pattern
match and print all the dir contains

e.g.
```bash
mkdir src
ls s?c 
```

| name | type | size   | modified                                      |
| ---- | ---- | ------ | --------------------------------------------- |
| src  | dir  | 1.1 KB | Tue, 29 Aug 2023 07:39:41 +0900 (9 hours ago) |

-----------

```bash
mkdir src
mkdir scc
mkdir scs
ls s?c
```

| name | type | size | modified |
| ---- | ---- | ------ |
------------------------------------------------ |
| scc | dir | 64 B | Tue, 29 Aug 2023 16:55:31 +0900 (14 seconds ago) |
| src | dir | 1.1 KB | Tue, 29 Aug 2023 07:39:41 +0900 (9 hours ago) |

-----------

```bash
mkdir  s?c
ls s?c
```

print empty (i.e. ls of dir `s?c`)

-----------

```bash
mkdir -p  s?c/test
ls s?c
```
|name|type|size|modified|
|-|-|-|-|
|s?c/test|dir|64 B|Tue, 29 Aug 2023 16:47:53 +0900 (2 minutes ago)|
|src/bytes|dir|480 B|Fri, 25 Aug 2023 17:43:52 +0900 (3 days ago)|
|src/charting|dir|160 B|Fri, 25 Aug 2023 17:43:52 +0900 (3 days ago)|
|src/conversions|dir|160 B|Fri, 25 Aug 2023 17:43:52 +0900 (3 days ago)|

-----------

# User-Facing Changes

User will be able to use '?' to match directory/file.

# Tests + Formatting

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

# After Submitting

None

---------

Co-authored-by: Horasal <horsal@horsal.dev>
2023-09-03 19:25:00 -05:00
3a20fbfe94 Update crossterm/ratatui/dev-reedline (#10137)
# Description
This updates most crates to 0.27 `crossterm`.
To do so we need the most recent `ratatui`

`reedline` can now update as well.
See https://github.com/nushell/reedline/pull/625

Sadly this introduces some crate duplication again as there are some
other dependency updates.
Furthermore we have another crate depending on 0.26.1 crossterm
(`comfy-table` that some how gets pulled in by polars)

# User-Facing Changes
2 additional mouse events detected by `input listen`

# Tests + Formatting
None
2023-09-03 19:22:25 -05:00
dac32557cd prevent crash when use redirection with let/mut (#10139)
Fix #9992 

I mistakenly messed up https://github.com/nushell/nushell/pull/10118 and
this is a cleaned version.

# Description

* This pr changes the panic to errors while parsing `let`, now user will
get the following errors:
<img width="395" alt="scr"
src="https://github.com/nushell/nushell/assets/1991933/4b39ac14-cd1f-47b3-9490-81009ca42717">
<img width="394" alt="scr"
src="https://github.com/nushell/nushell/assets/1991933/71ce33ad-f4d0-4132-828f-9674b9603556">
<img width="440" alt="scr"
src="https://github.com/nushell/nushell/assets/1991933/257eab4d-1a72-42db-b09e-f42bef33d2ec">

* `out+err>` is cached by `parse_expression` but not this, which may be
a potential problem.
* `Commond(None, ..)` remains panic for future bug report because I
don't actually know when/how does it happen

# User-Facing Changes

Nushell won't crash when user typing `let a = 1 err> ...`

# Tests + Formatting

- `cargo fmt --all -- --check` : OK
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used` : OK
- `cargo test --workspace` : OK
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` : OK

# After Submitting

None

Co-authored-by: Horasal <horsal@horsal.dev>
2023-09-03 19:21:45 -05:00
fedd879b2e support tab completion cycling (#10199)
should close https://github.com/nushell/nushell/issues/7202

# Description
i have been annoyed enough by this missing feature, so let's add that to
Nushell without requiring any user configuration 😏

# User-Facing Changes
this PR should allow tab completion cycling everytime, without requiring
the user to use the default config files or add the following
keybindings to their config
```nushell
    {
        name: completion_menu
        modifier: none
        keycode: tab
        mode: [emacs vi_normal vi_insert]
        event: {
            until: [
                { send: menu name: completion_menu }
                { send: menunext }
                { edit: complete }
            ]
        }
    }
```

### 🧪 try it out
from the root of the repo, one can try `<tab>` in each of the following
cases:
- `cargo run -- -n` to load Nushell without any config
- `cargo run -- --config
crates/nu-utils/src/sample_config/default_config.nu --env-config
crates/nu-utils/src/sample_config/default_env.nu` to load the default
configuration
- `cargo run` to load the user configuration

## before
- `<tab>`, `ls <tab>` and `str <tab>` only work with the second `cargo
run`, i.e. when loading the default config files

## after
- `<tab>` should cycle through the available commands
- `ls <tab>` should cycle through the available files and directories
- `str <tab>` should cycle the subcommands of `str`

in all three cases

# Tests + Formatting

# After submitting
2023-09-03 19:19:39 -05:00
a46c21cffb add plugin path when there are no signatures (#10201)
# Description

This PR adds the ability to have a `$nu.plugin-path` even when you
plugins are registered and it also should work with `nu -n --no-stdlib`.

### Before
It would give an error
```
│ plugin-path        │ IOError("Could not get plugin signature location")             │
```

### After
It returns the proper path, like this for me
```
│ plugin-path        │ /Users/fdncred/Library/Application Support/nushell/plugin.nu   │
```

Closed #10198 
# 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-03 19:19:04 -05:00
JT
6cdfee3573 Move Value to helpers, separate span call (#10121)
# Description

As part of the refactor to split spans off of Value, this moves to using
helper functions to create values, and using `.span()` instead of
matching span out of Value directly.

Hoping to get a few more helping hands to finish this, as there are a
lot of commands to update :)

# 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: Darren Schroeder <343840+fdncred@users.noreply.github.com>
Co-authored-by: WindSoilder <windsoilder@outlook.com>
2023-09-03 07:27:29 -07:00
af79eb2943 Point from keybindings help to the book's reedline chapter (#10193)
Documentation of keybindings command now points to the appropriate
section of the book.
2023-09-02 21:12:14 +02:00
e9d4730099 refactor input command (#10150)
close #8074 

I attempted to refactor the "input" command. The reason for this is that
the current implementation of the "input" command lacks consistency for
different options. For instance, some parts use `std::io::stdin` while
others use `crossterm::event::read`.

In this pull request, I have made changes to use crossterm consistently:
- Detection of the -u option is now done using `crossterm`'s
`KeyCode::Char`.
- The current input is displayed when using `crossterm` for input (it
won't be displayed when -s is present).
- Ctrl-C triggers SIGINT. 


# User-Facing Changes

Users can interrupt "input" with ctrl-c.
2023-09-02 21:09:26 +02:00
844f541719 changed default env file to use $nu.home_path to find home (#10192)
# Description
Changed the default env file so that home is found using `$nu.home-path`
instead to using an if-else statement to find the os then find the
specific environment variable
2023-09-02 09:00:10 -05:00
d28f728787 Add NU_VERSION environment variable on startup (#10177) 2023-09-01 09:48:13 +03:00
f35808cb89 Make $nu constant (#10160) 2023-09-01 09:18:55 +03:00
7d6b23ee2f Simplify rawstrings in tests (#10180)
Inspired by
https://rust-lang.github.io/rust-clippy/master/index.html#/needless_raw_string_hashes

Ran `cargo +stable clippy --workspace --all-targets`

Fixed manually as I ran into a false positive along the lines of:
https://github.com/rust-lang/rust-clippy/issues/11068

Also collapse one set of single line tests.

Work for #8670
2023-09-01 00:08:27 +02:00
e68ae4c8d1 Bump notify-debouncer-full from 0.2.0 to 0.3.1 (#10129) 2023-08-31 22:07:41 +00:00
faad6ca355 Remove dead tests depending on inc (#10179)
They relied on the `nu_plugin_inc` but where behind a feature flag that
isn't actually defined anywhere. These tests of `update` or `upsert`
shouldn't really depend on `inc` so I decided to remove them outright as
they haven't been used to exercise the commands under test.
2023-08-31 23:11:04 +02:00
c77c1bd297 Tests: clean up unnecessary use of pipeline() (#10170)
As described in Issue #8670, removed `pipeline()` wherever its argument
contained no line breaks.

---------

Co-authored-by: sholderbach <sholderbach@users.noreply.github.com>
2023-08-31 23:10:29 +02:00
5b4b4446b7 Keep arrow2 out of basic --workspace build (#10178)
Same logic as in #9971

Prevents building the heavy polars and arrow dependencies when just
running `cargo test --workspace` or `rust-analyzer`

`polars-io` dependency was introduced in #10019
2023-08-31 23:10:11 +02:00
93f20b406e feat: allow from csv to accept 4 byte unicode separator chars (#10138)
- this PR should close #10132

# Description
* added a flag to `from csv --ascii` that replaces the given `separator
with the unicode separator x1f https://www.codetable.net/hex/1f (aka
Information Separator One)

# User-Facing Changes
New flags are available for `from csv` ( `--ascii` or short `-a`)

# Tests + Formatting
There are no tests at the moment. Code has been formatted.
- `cargo test --workspace` (breaks with a non related test on my
machine)
2023-08-31 18:55:39 +02:00
02318cf3a7 update query web example because wikipedia changed their page (#10173)
# Description

This PR updates one of the query web examples because the wikipedia page
changed. This works again.

![image](https://github.com/nushell/nushell/assets/343840/72658c98-a339-4e76-96da-56d725e7a0e1)


# 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-08-31 11:00:30 -05:00
35fc387505 Fix #10154 (#10162)
close #10154
2023-08-31 08:43:27 -05:00
fd4ba0443d fixed usages of deprecated chrono DateTime::from_utc (#10161)
This addresses the warnings generated from using DateTime::from_utc.
DateTime::from_utc was deprecated as of chrono 0.4.27

Co-authored-by: Jack Wright <jack.wright@disqo.com>
2023-08-30 17:04:19 -05:00
b943cbedff skip comments and eols while parsing pipeline (#10149)
This pr 
- fixes https://github.com/nushell/nushell/issues/10143
- fixes https://github.com/nushell/nushell/issues/5559

# Description

Current `lite_parse` does not handle multiple line comments and eols in
pipeline.
When parsing the following tokens:


| `"abcdefg"` | ` \|` | `# foobar` | ` \n` | `split chars` |
| ------------- | ------------- |------------- |-------------
|------------- |
| [Command] | [Pipe] | [Comment] | [Eol] | [Command] |
| | | Last Token |Current Token | |

`TokenContent::Eol` handler only checks if `last_token` is `Pipe` but it
will be broken if there exist any other thing, e.g. extra `[Comment]` in
this example.

This pr make the following change:

- While parsing `[Eol]`, try to find the last non-comment token as
`last_token`
- Comment is supposed as `[Comment]+` or `([Comment] [Eol])+`
- `[Eol]+` is still parsed just like current nu (i.e. generates
`nothing`).

Notice that this pr is just a quick patch if more comment/eol related
issue occures, `lite_parser` may need a rewrite.

# User-Facing Changes

Now the following pipeline works: 

```bash
1 | # comment
each { |it| $it + 2 } | # comment
math sum
```

Comment will not end the pipeline in interactive mode:

```bash
❯ 1 | # comment   (now enter multiple line mode instead of end)
▶▶ # foo
▶▶ 2
```

# Tests + Formatting

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

# After Submitting

None

---------

Co-authored-by: Horasal <horsal@horsal.dev>
2023-08-30 13:24:13 -05:00
3fd1a26ec0 Updating polars and sqlparser versions (#10114)
Polars and SQLParser upgrade.

I have exposed features that have been added to polars as command args
where appropriate.

---------

Co-authored-by: Jack Wright <jack.wright@disqo.com>
Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
Co-authored-by: sholderbach <sholderbach@users.noreply.github.com>
2023-08-30 00:13:34 +02:00
3f2c76df28 Move eval_hook to nu-cmd-base (#10146)
I moved hook to *nu_cmd_base* instead of *nu_cli* because it will enable
other developers to continue to use hook even if they decide to write
their on cli or NOT depend on nu-cli

Then they will still have the hook functionality because they can
include nu-cmd-base
2023-08-29 23:46:50 +02:00
7d3312e96e remove warnings in nu_command tests (#10145)
several warnings were appearing in nu_command tests when running just
the tests
in nu_command so I went ahead and removed the warnings...
2023-08-29 13:18:52 -07:00
c59d9dc306 update rust-toolchain doc to 4 weeks from 3 (#10140)
When we updated our release schedule from 3 weeks to 4 weeks the doc on
the toolchain
file was never updated so I went ahead and did that...
2023-08-28 20:57:03 -07:00
1f06f8405c handle empty pipeline while parsing let (fix Issue10083) (#10116)
- fixes #10083 

# Description

nushell crashes in the following 2 condition:

- `let a = {}` , then delete `{`
- `let a = | {}`, then delete `{`

When delete `{` the pipeline becomes empty but current `nu-parser`
assume they are non-empty. This pr adds extra empty check to avoid
crash.


Co-authored-by: Horasal <horsal@horsal.dev>
2023-08-28 13:38:11 +02:00
38f454d5ab Support Termux (#10013) 2023-08-28 09:53:25 +03:00
487f1a97ea Update removed "MDI" icons to current MD icons (#10126)
# Description
This PR updates now-removed (since NF 3.0.0) file icons shown in e.g.
`grid` to their updated codepoints.

# User-Facing Changes
File icons changed were for:
`cs`, `csproj`, `csx`, `license`, `node`, `rtf`, `vue`, `xml`, and `xul`

# Tests + Formatting

# After Submitting
2023-08-27 15:48:37 +02:00
0f05475e2e name hooks internally (#10127)
# Description

This PR names the hooks as they're executing so that you can see them
with debug statements. So, at the beginning of `eval_hook()` you could
put a dbg! or eprintln! to see what hook was executing. It also shows up
in View files.

### Before - notice item 14 and 25

![image](https://github.com/nushell/nushell/assets/343840/22c19bbe-6bac-4132-9579-863922d91f22)

### After - The hooks are now named (14 & 25)

![image](https://github.com/nushell/nushell/assets/343840/a08abd11-4f03-4f09-bbac-e4b5180df078)


Curiosity, on my mac, the display_output hook fires 3 times before
anything else. Also, curious is that the value if the display_output, is
not what I have in my config but what is in the default_config. So,
there may be a bug or some shenanigans going on somewhere with hooks.

# 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-08-27 06:55:20 -05:00
cc805f3f01 Screen reader-friendly errors (#10122)
- Hopefully closes #10120  

# Description

This PR adds a new config item, `error_style`. It will render errors in
a screen reader friendly mode when set to `"simple"`. This is done using
`miette`'s own `NarratableReportHandler`, which seamlessly replaces the
default one when needed.

Before:
```
Error: nu:🐚:external_command

  × External command failed
   ╭─[entry #2:1:1]
 1 │ doesnt exist
   · ───┬──
   ·    ╰── executable was not found
   ╰────
  help: No such file or directory (os error 2)
```

After:
```
Error: External command failed
    Diagnostic severity: error
Begin snippet for entry #4 starting at line 1, column 1

snippet line 1: doesnt exist
    label at line 1, columns 1 to 6: executable was not found
diagnostic help: No such file or directory (os error 2)
diagnostic code: nu:🐚:external_command

```

## Things to be determined

- ~Review naming. `errors.style` is not _that_ consistent with the rest
of the code. Menus use a `style` record, but table rendering mode is set
via `mode`.~ As it's a single config, we're using `error_style` for now.
- Should this kind of setting be toggable with one single parameter?
`accessibility.no_decorations` or similar, which would adjust the style
of both errors and tables accordingly.

# User-Facing Changes

No changes by default, errors will be rendered differently if
`error_style` is set to `simple`.

# 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

There's a PR updating the docs over here
https://github.com/nushell/nushell.github.io/pull/1026
2023-08-27 06:54:15 -05:00
5ac5b90aed Allow parse-time evaluation of calls, pipelines and subexpressions (#9499)
Co-authored-by: Antoine Stevan <44101798+amtoine@users.noreply.github.com>
2023-08-26 16:41:29 +03:00
3d73287ea4 add support for Vim motions in explore (#9966)
related to
- https://github.com/nushell/nushell/issues/7819

# Description
this PR does not quite address
https://github.com/nushell/nushell/issues/7819 because it does not
implement configurable keybindings for `explore` but rather only adds
support for Vim-like motions *out of the box*.

# User-Facing Changes
in *view* and *cursor* modes,
- `h`, `j`, `k` and `l` give standard Qwerty-based Vim motions
- `g` and `G` go to the top and the end respectively
- `u` and `d` scroll up and down

> **Note**
> the bindings do not support the use of modifiers for now, so it's not
`c-u` and `c-d` which scroll pages but rather `u` and `d`

# Tests + Formatting

# After Submitting
2023-08-26 07:48:37 -05:00
7ebdced256 toolkit: Renames pretty-print-command (#10110)
It doesn't print, but returns a string.
So it should be called format.
2023-08-25 19:23:30 +02:00
ad12018199 Use built-in is_terminal instead of is_terminal::is_terminal (#9550)
# Description
This PR tries to remove ~atty~ is-terminal from the entire code base,
since ~[atty is
unmaintained](https://rustsec.org/advisories/RUSTSEC-2021-0145) and~
[`is_terminal` has been
stabilized](https://blog.rust-lang.org/2023/06/01/Rust-1.70.0.html#isterminal)
in rust 1.70.0.

cc @fdncred 

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

# Tests + Formatting
<!--
Don't forget to add tests that cover your changes.

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

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect -A clippy::result_large_err` to check that
you're using the standard code style
- `cargo test --workspace` to check that all tests pass
- `cargo run -- crates/nu-std/tests/run.nu` 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-08-25 10:54:44 +02:00
27dcc3ecc3 Don't use oldtime feature of chrono (#9577)
<!--
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
`chrono` crate enables `oldtime` feature by default, which has a
vulnerability (https://rustsec.org/advisories/RUSTSEC-2020-0071). This
PR tries to remove `time` v0.1.45 completely from nu and add an audit CI
to check for security vulnerabilities.

 Wait for the following PRs:
- [x] https://github.com/nushell/reedline/pull/599
- [x] https://github.com/bspeice/dtparse/pull/44
- [x] https://github.com/Byron/trash-rs/pull/75
- [x] https://gitlab.com/imp/chrono-humanize-rs/-/merge_requests/15

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

# Tests + Formatting
<!--
Don't forget to add tests that cover your changes.

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

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect -A clippy::result_large_err` to check that
you're using the standard code style
- `cargo test --workspace` to check that all tests pass
- `cargo run -- crates/nu-std/tests/run.nu` 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: sholderbach <sholderbach@users.noreply.github.com>
2023-08-25 10:54:01 +02:00
e25a795cf6 Add encoding auto-detection for decode (#10030)
# Description
Allow `decode` command to guess the encoding of input if no encoding
name is given.

# User-Facing Changes

* `decode` now has an optional parameter instead of required one. User
can just run `decode` to let the command automatically detect encoding
and convert it to utf-8.
<img width="575" alt="Example"
src="https://github.com/nushell/nushell/assets/1991933/03a0ba11-910e-4db9-89aa-79cfec06893f">



* Based on the detect result, user may have to give a encoding name
<img width="572" alt="Error Sample1"
src="https://github.com/nushell/nushell/assets/1991933/f21fda85-1f04-4cb3-9feb-cb9fb7dcee07">
     or get informed that the input is not supported by `decode`
<img width="568" alt="Error Sample2"
src="https://github.com/nushell/nushell/assets/1991933/dd3cc4c0-f119-493e-8609-d07594fc055a">

# Tests + Formatting

* `cargo fmt --all -- --check` : OK
* `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect -A clippy::result_large_err`: OK
* `cargo test --workspace` : OK
* `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"`: OK


# After Submitting

[Command document](https://www.nushell.sh/commands/docs/decode.html) is
auto-generated and requires no action.

---------

Co-authored-by: Horasal <horsal@horsal.dev>
2023-08-24 19:21:17 -05:00
16c15e83a3 bump rust-toolchain to 1.70.0 (#10113)
# Description

This PR bumps the rust-toolchain to 1.70.0 since 1.72.0 was released
today.

# 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-08-24 19:13:57 -05:00
cea67cb30b Allow for .parq file ending as alternative to .parquet (#10112)
# Description

Many systems like Hadoops HDFS store parquet files with the short
variant `.parq`. It is quite annoying to rename these file before
opening them with nushell. This PR lets nushell accept .parq alongside
.parquet file endings.


# User-Facing Changes
Not sure if this is applicable here.

# Tests + Formatting

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 -  (fails on
none related test)
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library -
✔️
2023-08-24 15:57:33 -05:00
JT
1e3e034021 Spanned Value step 1: span all value cases (#10042)
# Description

This doesn't really do much that the user could see, but it helps get us
ready to do the steps of the refactor to split the span off of Value, so
that values can be spanless. This allows us to have top-level values
that can hold both a Value and a Span, without requiring that all values
have them.

We expect to see significant memory reduction by removing so many
unnecessary spans from values. For example, a table of 100,000 rows and
5 columns would have a savings of ~8megs in just spans that are almost
always duplicated.

# User-Facing Changes

Nothing yet

# Tests + Formatting
<!--
Don't forget to add tests that cover your changes.

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

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect -A clippy::result_large_err` to check that
you're using the standard code style
- `cargo test --workspace` to check that all tests pass
- `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-08-25 08:48:05 +12:00
8da27a1a09 Create Record type (#10103)
# Description
This PR creates a new `Record` type to reduce duplicate code and
possibly bugs as well. (This is an edited version of #9648.)
- `Record` implements `FromIterator` and `IntoIterator` and so can be
iterated over or collected into. For example, this helps with
conversions to and from (hash)maps. (Also, no more
`cols.iter().zip(vals)`!)
- `Record` has a `push(col, val)` function to help insure that the
number of columns is equal to the number of values. I caught a few
potential bugs thanks to this (e.g. in the `ls` command).
- Finally, this PR also adds a `record!` macro that helps simplify
record creation. It is used like so:
   ```rust
   record! {
       "key1" => some_value,
       "key2" => Value::string("text", span),
       "key3" => Value::int(optional_int.unwrap_or(0), span),
       "key4" => Value::bool(config.setting, span),
   }
   ```
Since macros hinder formatting, etc., the right hand side values should
be relatively short and sweet like the examples above.

Where possible, prefer `record!` or `.collect()` on an iterator instead
of multiple `Record::push`s, since the first two automatically set the
record capacity and do less work overall.

# User-Facing Changes
Besides the changes in `nu-protocol` the only other breaking changes are
to `nu-table::{ExpandedTable::build_map, JustTable::kv_table}`.
2023-08-25 07:50:29 +12:00
030e749fe7 Add notice to enable develop mode on Windows (#10111)
Developer mode needs to be enabled to create symlinks on Windows. Since
creating symlinks is part of the testbench, this needs to be enabled.

(I always wondered why two tests fail on my Windows machine, but not on
the CI)
2023-08-24 11:02:54 -07:00
a785e64bc9 Fix 9156 endian consistency (#9873)
- fixed #9156

# Description
I'm trying to fix the problems mentioned in the issue. It's my first
attempt in Rust. Please let me know if there are any problems.

# User-Facing Changes
- The `--little-endian` option dropped, replaced with `--endian`.
- Add the `--compact` option to the `into binary` command.
- `into int` accepts binary input
2023-08-24 07:08:58 -05:00
d4eeef4bd1 Fix tab completion order of directories to consistent with order of files (#10102)
# Description

fixed #10020

Tab completion order of directories is inconsistent with order of files.
This problem is caused by sorting folder names containing a trailing
slash.
This PR fixes the problem.

# User-Facing Changes

Users get the same order of suggestions in the tab completion for both
file and directory.


![image](https://github.com/nushell/nushell/assets/37319612/208e5a01-01a2-489c-b41a-36ece999f971)


# Tests + Formatting

```
$ toolkit check pr

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

# After Submitting

nothing
2023-08-24 06:19:13 -05:00
c8a07d477f Fix watch not detecting modifications on Windows (#10109)
Closes #9910 FOR REAL this time.

I had fixed the issue on Linux but not Windows. Context:
https://github.com/nushell/nushell/issues/9910#issuecomment-1689308886

I've tested this PR successfully on Windows, Linux, and macOS by running
`watch . {|a,b| print $a; print $b}` and confirming that it prints once
when I change a file in the current directory.
2023-08-23 19:07:39 -07:00
af82eeca72 remove --column from length command and remove record processing (#10091)
# Description

This PR removes `record` processing from the `length` command. It just
doesn't make sense to try and get the length of a record. This PR also
removes the `--column` parameter. If you want to list or count columns,
you could use `$table | columns` or `$table | columns | length`.

close #10074 

### Before

![image](https://github.com/nushell/nushell/assets/343840/83488316-3ec4-4c32-9583-00341a71f46f)

### After
Catches records two different ways now.
with the `input_output_types` checker

![image](https://github.com/nushell/nushell/assets/343840/ca67f8b6-359e-4933-ab4d-1b702f8d79cf)

and with additional logic in the command for cases like `echo`

![image](https://github.com/nushell/nushell/assets/343840/99064351-b208-4bd3-bab9-535f97cd7ad4)


# 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
- `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-08-23 16:03:26 -05:00
3d698b74d8 bump nushell to dev version 0.84.1 (#10101)
# Description

This PR bumps nushell from release version 0.84.0 to dev version 0.84.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
- `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-08-23 15:23:27 -05:00
792 changed files with 24715 additions and 23038 deletions

View File

@ -26,3 +26,8 @@ rustflags = ["-C", "link-args=-stack:10000000", "-C", "target-feature=+crt-stati
# [target.aarch64-apple-darwin] # [target.aarch64-apple-darwin]
# linker = "clang" # linker = "clang"
# rustflags = ["-C", "link-arg=-fuse-ld=mold"] # 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"]

View File

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

View File

@ -25,7 +25,7 @@ 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 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 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 - `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 - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library
> **Note** > **Note**

25
.github/workflows/audit.yml vendored Normal file
View File

@ -0,0 +1,25 @@
name: Security audit
on:
pull_request:
paths:
- '**/Cargo.toml'
- '**/Cargo.lock'
push:
branches:
- main
env:
RUST_BACKTRACE: 1
CARGO_TERM_COLOR: always
CLICOLOR: 1
jobs:
security_audit:
runs-on: ubuntu-latest
# Prevent sudden announcement of a new advisory from failing ci:
continue-on-error: true
steps:
- uses: actions/checkout@v4
- uses: rustsec/audit-check@v1.4.1
with:
token: ${{ secrets.GITHUB_TOKEN }}

View File

@ -7,7 +7,7 @@ on:
name: continuous-integration name: continuous-integration
env: env:
NUSHELL_CARGO_TARGET: ci NUSHELL_CARGO_PROFILE: ci
NU_LOG_LEVEL: DEBUG NU_LOG_LEVEL: DEBUG
CLIPPY_OPTIONS: "-D warnings -D clippy::unwrap_used" CLIPPY_OPTIONS: "-D warnings -D clippy::unwrap_used"
@ -37,7 +37,7 @@ jobs:
runs-on: ${{ matrix.platform }} runs-on: ${{ matrix.platform }}
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Setup Rust toolchain and cache - name: Setup Rust toolchain and cache
uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 uses: actions-rust-lang/setup-rust-toolchain@v1.5.0
@ -49,6 +49,10 @@ jobs:
- name: Clippy - name: Clippy
run: cargo clippy --workspace ${{ matrix.flags }} --exclude nu_plugin_* -- $CLIPPY_OPTIONS run: cargo clippy --workspace ${{ matrix.flags }} --exclude nu_plugin_* -- $CLIPPY_OPTIONS
# In tests we don't have to deny unwrap
- name: Clippy of tests
run: cargo clippy --tests --workspace ${{ matrix.flags }} --exclude nu_plugin_* -- -D warnings
tests: tests:
strategy: strategy:
@ -76,7 +80,7 @@ jobs:
runs-on: ${{ matrix.platform }} runs-on: ${{ matrix.platform }}
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Setup Rust toolchain and cache - name: Setup Rust toolchain and cache
uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 uses: actions-rust-lang/setup-rust-toolchain@v1.5.0
@ -97,7 +101,7 @@ jobs:
runs-on: ${{ matrix.platform }} runs-on: ${{ matrix.platform }}
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Setup Rust toolchain and cache - name: Setup Rust toolchain and cache
uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 uses: actions-rust-lang/setup-rust-toolchain@v1.5.0
@ -132,7 +136,7 @@ jobs:
runs-on: ${{ matrix.platform }} runs-on: ${{ matrix.platform }}
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Setup Rust toolchain and cache - name: Setup Rust toolchain and cache
uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 uses: actions-rust-lang/setup-rust-toolchain@v1.5.0

View File

@ -13,7 +13,7 @@ on:
- nightly # Just for test purpose only with the nightly repo - nightly # Just for test purpose only with the nightly repo
# This schedule will run only from the default branch # This schedule will run only from the default branch
schedule: schedule:
- cron: '15 1 * * *' # run at 01:15 AM UTC - cron: '15 0 * * *' # run at 00:15 AM UTC
defaults: defaults:
run: run:
@ -27,7 +27,7 @@ jobs:
# if: github.repository == 'nushell/nightly' # if: github.repository == 'nushell/nightly'
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v4
if: github.repository == 'nushell/nightly' if: github.repository == 'nushell/nightly'
with: with:
ref: main ref: main
@ -36,10 +36,10 @@ jobs:
token: ${{ secrets.WORKFLOW_TOKEN }} token: ${{ secrets.WORKFLOW_TOKEN }}
- name: Setup Nushell - name: Setup Nushell
uses: hustcer/setup-nu@v3 uses: hustcer/setup-nu@v3.6
if: github.repository == 'nushell/nightly' if: github.repository == 'nushell/nightly'
with: with:
version: 0.81.0 version: 0.85.0
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@ -53,22 +53,21 @@ jobs:
# We can't push if no user name and email are configured # We can't push if no user name and email are configured
git config user.name 'hustcer' git config user.name 'hustcer'
git config user.email 'hustcer@outlook.com' git config user.email 'hustcer@outlook.com'
git fetch origin main git pull origin main
git remote add src https://github.com/nushell/nushell.git git remote add src https://github.com/nushell/nushell.git
git fetch src main git fetch src main
# git pull --rebase src main
# All the changes will be overwritten by the upstream main branch # All the changes will be overwritten by the upstream main branch
git reset --hard src/main git reset --hard src/main
git push origin main -f git push origin main -f
let sha_short = (git rev-parse --short src/main | str trim | str substring 0..7) let sha_short = (git rev-parse --short origin/main | str trim | str substring 0..7)
let tag_name = $'nightly-($sha_short)' let tag_name = $'nightly-($sha_short)'
if (git ls-remote --tags origin $tag_name | is-empty) { if (git ls-remote --tags origin $tag_name | is-empty) {
git tag -a $tag_name -m $'Nightly build from ($sha_short)' git tag -a $tag_name -m $'Nightly build from ($sha_short)'
git push origin --tags git push origin --tags
} }
release: standard:
name: Release name: Std
needs: prepare needs: prepare
strategy: strategy:
fail-fast: false fail-fast: false
@ -118,17 +117,18 @@ jobs:
target_rustflags: '' target_rustflags: ''
- target: armv7-unknown-linux-gnueabihf - target: armv7-unknown-linux-gnueabihf
os: ubuntu-20.04 os: ubuntu-20.04
target_rustflags: '--exclude=nu-cmd-dataframe' target_rustflags: ''
- target: riscv64gc-unknown-linux-gnu - target: riscv64gc-unknown-linux-gnu
os: ubuntu-20.04 os: ubuntu-20.04
target_rustflags: '--exclude=nu-cmd-dataframe' target_rustflags: ''
runs-on: ${{matrix.os}} runs-on: ${{matrix.os}}
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
with: with:
ref: main ref: main
fetch-depth: 0
- name: Update Rust Toolchain Target - name: Update Rust Toolchain Target
run: | run: |
@ -136,13 +136,11 @@ jobs:
- name: Setup Rust toolchain and cache - name: Setup Rust toolchain and cache
uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 uses: actions-rust-lang/setup-rust-toolchain@v1.5.0
with:
rustflags: ''
- name: Setup Nushell - name: Setup Nushell
uses: hustcer/setup-nu@v3 uses: hustcer/setup-nu@v3.6
with: with:
version: 0.81.0 version: 0.85.0
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@ -150,6 +148,7 @@ jobs:
id: nu id: nu
run: nu .github/workflows/release-pkg.nu run: nu .github/workflows/release-pkg.nu
env: env:
RELEASE_TYPE: standard
OS: ${{ matrix.os }} OS: ${{ matrix.os }}
REF: ${{ github.ref }} REF: ${{ github.ref }}
TARGET: ${{ matrix.target }} TARGET: ${{ matrix.target }}
@ -176,7 +175,118 @@ jobs:
# REF: https://github.com/marketplace/actions/gh-release # REF: https://github.com/marketplace/actions/gh-release
# Create a release only in nushell/nightly repo # Create a release only in nushell/nightly repo
- name: Publish Archive - name: Publish Archive
uses: softprops/action-gh-release@v0.1.13 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 }}
_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') }} if: ${{ startsWith(github.repository, 'nushell/nightly') }}
with: with:
draft: false draft: false
@ -200,14 +310,14 @@ jobs:
- name: Waiting for Release - name: Waiting for Release
run: sleep 1800 run: sleep 1800
- uses: actions/checkout@v3 - uses: actions/checkout@v4
with: with:
ref: main ref: main
- name: Setup Nushell - name: Setup Nushell
uses: hustcer/setup-nu@v3 uses: hustcer/setup-nu@v3.6
with: with:
version: 0.81.0 version: 0.85.0
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 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) let version = (open Cargo.toml | get package.version)
print $'Debugging info:' 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 # $env
let USE_UBUNTU = 'ubuntu-20.04' 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 print $'(char nl)Packaging ($bin) v($version) for ($target) in ($src)...'; hr-line -b
if not ('Cargo.lock' | path exists) { cargo generate-lockfile } 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'] { if $os in [$USE_UBUNTU, 'macos-latest'] {
let files = (ls | get name) 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' let archive = $'($dist)/($dest).tar.gz'
mkdir $dest mkdir $dest
@ -156,7 +171,7 @@ if $os in [$USE_UBUNTU, 'macos-latest'] {
} else if $os == 'windows-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 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 aria2c https://github.com/jftuga/less-Windows/releases/download/less-v608/less.exe -o less.exe
@ -172,18 +187,22 @@ if $os in [$USE_UBUNTU, 'macos-latest'] {
cp -r $'($dist)/*' target/release/ cp -r $'($dist)/*' target/release/
cargo install cargo-wix --version 0.3.4 cargo install cargo-wix --version 0.3.4
cargo wix --no-build --nocapture --package nu --output $wixRelease cargo wix --no-build --nocapture --package nu --output $wixRelease
print $'archive: ---> ($wixRelease)'; # Workaround for https://github.com/softprops/action-gh-release/issues/280
echo $"archive=($wixRelease)" | save --append $env.GITHUB_OUTPUT let archive = ($wixRelease | str replace --all '\' '/')
print $'archive: ---> ($archive)';
echo $"archive=($archive)" | save --append $env.GITHUB_OUTPUT
} else { } else {
print $'(char nl)(ansi g)Archive contents:(ansi reset)'; hr-line; ls print $'(char nl)(ansi g)Archive contents:(ansi reset)'; hr-line; ls
let archive = $'($dist)/($releaseStem).zip' let archive = $'($dist)/($releaseStem).zip'
7z a $archive * 7z a $archive *
print $'archive: ---> ($archive)';
let pkg = (ls -f $archive | get name) let pkg = (ls -f $archive | get name)
if not ($pkg | is-empty) { if not ($pkg | is-empty) {
echo $"archive=($pkg | get 0)" | save --append $env.GITHUB_OUTPUT # Workaround for https://github.com/softprops/action-gh-release/issues/280
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 shell: bash
jobs: jobs:
all: standard:
name: All name: Std
strategy: strategy:
matrix: matrix:
@ -64,15 +64,15 @@ jobs:
target_rustflags: '' target_rustflags: ''
- target: armv7-unknown-linux-gnueabihf - target: armv7-unknown-linux-gnueabihf
os: ubuntu-20.04 os: ubuntu-20.04
target_rustflags: '--exclude=nu-cmd-dataframe' target_rustflags: ''
- target: riscv64gc-unknown-linux-gnu - target: riscv64gc-unknown-linux-gnu
os: ubuntu-20.04 os: ubuntu-20.04
target_rustflags: '--exclude=nu-cmd-dataframe' target_rustflags: ''
runs-on: ${{matrix.os}} runs-on: ${{matrix.os}}
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Update Rust Toolchain Target - name: Update Rust Toolchain Target
run: | run: |
@ -80,13 +80,11 @@ jobs:
- name: Setup Rust toolchain and cache - name: Setup Rust toolchain and cache
uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 uses: actions-rust-lang/setup-rust-toolchain@v1.5.0
with:
rustflags: ''
- name: Setup Nushell - name: Setup Nushell
uses: hustcer/setup-nu@v3 uses: hustcer/setup-nu@v3.6
with: with:
version: 0.81.0 version: 0.85.0
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@ -94,6 +92,7 @@ jobs:
id: nu id: nu
run: nu .github/workflows/release-pkg.nu run: nu .github/workflows/release-pkg.nu
env: env:
RELEASE_TYPE: standard
OS: ${{ matrix.os }} OS: ${{ matrix.os }}
REF: ${{ github.ref }} REF: ${{ github.ref }}
TARGET: ${{ matrix.target }} TARGET: ${{ matrix.target }}
@ -102,7 +101,95 @@ jobs:
# REF: https://github.com/marketplace/actions/gh-release # REF: https://github.com/marketplace/actions/gh-release
- name: Publish Archive - name: Publish Archive
uses: softprops/action-gh-release@v0.1.13 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 }}
_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/') }} if: ${{ startsWith(github.ref, 'refs/tags/') }}
with: with:
draft: true draft: true

View File

@ -7,7 +7,9 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout Actions Repository - name: Checkout Actions Repository
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Check spelling - name: Check spelling
uses: crate-ci/typos@master uses: crate-ci/typos@v1.16.19
with:
config: ./.github/.typos.toml

View File

@ -7,7 +7,7 @@ on:
inputs: inputs:
tag_name: tag_name:
description: 'Specific tag name' description: 'Specific tag name'
required: true required: true
type: string type: string
jobs: jobs:
@ -20,6 +20,9 @@ jobs:
uses: vedantmgoyal2009/winget-releaser@v2 uses: vedantmgoyal2009/winget-releaser@v2
with: with:
identifier: Nushell.Nushell 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 }} version: ${{ inputs.tag_name || github.event.release.tag_name }}
release-tag: ${{ inputs.tag_name || github.event.release.tag_name }} release-tag: ${{ inputs.tag_name || github.event.release.tag_name }}
token: ${{ secrets.NUSHELL_PAT }} token: ${{ secrets.NUSHELL_PAT }}

View File

@ -46,7 +46,7 @@ cargo build
### Tests ### 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 can be found in different places:
* `/tests` * `/tests`
@ -58,7 +58,7 @@ Most of the tests are built upon the `nu-test-support` crate. For testing specif
### Useful Commands ### 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 Read cargo's documentation for more details: https://doc.rust-lang.org/cargo/reference/workspaces.html
- Build and run Nushell: - Build and run Nushell:

1556
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -11,7 +11,7 @@ license = "MIT"
name = "nu" name = "nu"
repository = "https://github.com/nushell/nushell" repository = "https://github.com/nushell/nushell"
rust-version = "1.60" rust-version = "1.60"
version = "0.84.0" version = "0.86.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -46,34 +46,34 @@ members = [
] ]
[dependencies] [dependencies]
nu-cli = { path = "./crates/nu-cli", version = "0.84.0" } nu-cli = { path = "./crates/nu-cli", version = "0.86.0" }
nu-color-config = { path = "./crates/nu-color-config", version = "0.84.0" } nu-color-config = { path = "./crates/nu-color-config", version = "0.86.0" }
nu-cmd-base = { path = "./crates/nu-cmd-base", version = "0.84.0" } nu-cmd-base = { path = "./crates/nu-cmd-base", version = "0.86.0" }
nu-cmd-lang = { path = "./crates/nu-cmd-lang", version = "0.84.0" } nu-cmd-lang = { path = "./crates/nu-cmd-lang", version = "0.86.0" }
nu-cmd-dataframe = { path = "./crates/nu-cmd-dataframe", version = "0.84.0", features = ["dataframe"], optional = true } 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.84.0", optional = true } nu-cmd-extra = { path = "./crates/nu-cmd-extra", version = "0.86.0", optional = true }
nu-command = { path = "./crates/nu-command", version = "0.84.0" } nu-command = { path = "./crates/nu-command", version = "0.86.0" }
nu-engine = { path = "./crates/nu-engine", version = "0.84.0" } nu-engine = { path = "./crates/nu-engine", version = "0.86.0" }
nu-explore = { path = "./crates/nu-explore", version = "0.84.0" } nu-explore = { path = "./crates/nu-explore", version = "0.86.0" }
nu-json = { path = "./crates/nu-json", version = "0.84.0" } nu-json = { path = "./crates/nu-json", version = "0.86.0" }
nu-parser = { path = "./crates/nu-parser", version = "0.84.0" } nu-parser = { path = "./crates/nu-parser", version = "0.86.0" }
nu-path = { path = "./crates/nu-path", version = "0.84.0" } nu-path = { path = "./crates/nu-path", version = "0.86.0" }
nu-plugin = { path = "./crates/nu-plugin", optional = true, version = "0.84.0" } nu-plugin = { path = "./crates/nu-plugin", optional = true, version = "0.86.0" }
nu-pretty-hex = { path = "./crates/nu-pretty-hex", version = "0.84.0" } nu-pretty-hex = { path = "./crates/nu-pretty-hex", version = "0.86.0" }
nu-protocol = { path = "./crates/nu-protocol", version = "0.84.0" } nu-protocol = { path = "./crates/nu-protocol", version = "0.86.0" }
nu-system = { path = "./crates/nu-system", version = "0.84.0" } nu-system = { path = "./crates/nu-system", version = "0.86.0" }
nu-table = { path = "./crates/nu-table", version = "0.84.0" } nu-table = { path = "./crates/nu-table", version = "0.86.0" }
nu-term-grid = { path = "./crates/nu-term-grid", version = "0.84.0" } nu-term-grid = { path = "./crates/nu-term-grid", version = "0.86.0" }
nu-std = { path = "./crates/nu-std", version = "0.84.0" } nu-std = { path = "./crates/nu-std", version = "0.86.0" }
nu-utils = { path = "./crates/nu-utils", version = "0.84.0" } nu-utils = { path = "./crates/nu-utils", version = "0.86.0" }
nu-ansi-term = "0.49.0" nu-ansi-term = "0.49.0"
reedline = { version = "0.23.0", features = ["bashisms", "sqlite"]} reedline = { version = "0.25.0", features = ["bashisms", "sqlite"] }
crossterm = "0.26" crossterm = "0.27"
ctrlc = "3.4" ctrlc = "3.4"
log = "0.4" log = "0.4"
miette = { version = "5.10", features = ["fancy-no-backtrace"] } miette = { version = "5.10", features = ["fancy-no-backtrace"] }
mimalloc = { version = "0.1.37", default-features = false, optional = true} mimalloc = { version = "0.1.37", default-features = false, optional = true }
serde_json = "1.0" serde_json = "1.0"
simplelog = "0.12" simplelog = "0.12"
time = "0.3" time = "0.3"
@ -87,22 +87,21 @@ signal-hook = { version = "0.3", default-features = false }
winresource = "0.1" winresource = "0.1"
[target.'cfg(target_family = "unix")'.dependencies] [target.'cfg(target_family = "unix")'.dependencies]
nix = { version = "0.26", default-features = false, features = [ nix = { version = "0.27", default-features = false, features = [
"signal", "signal",
"process", "process",
"fs", "fs",
"term", "term",
] } ] }
is-terminal = "0.4.8"
[dev-dependencies] [dev-dependencies]
nu-test-support = { path = "./crates/nu-test-support", version = "0.84.0" } nu-test-support = { path = "./crates/nu-test-support", version = "0.86.0" }
assert_cmd = "2.0" assert_cmd = "2.0"
criterion = "0.5" criterion = "0.5"
pretty_assertions = "1.4" pretty_assertions = "1.4"
rstest = { version = "0.18", default-features = false } rstest = { version = "0.18", default-features = false }
serial_test = "2.0" serial_test = "2.0"
tempfile = "3.7" tempfile = "3.8"
[features] [features]
plugin = [ plugin = [
@ -113,12 +112,13 @@ plugin = [
"nu-protocol/plugin", "nu-protocol/plugin",
"nu-engine/plugin", "nu-engine/plugin",
] ]
default = ["plugin", "which-support", "trash-support", "sqlite"] default = ["plugin", "which-support", "trash-support", "sqlite", "mimalloc"]
stable = ["default"] stable = ["default"]
wasi = ["nu-cmd-lang/wasi"] 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 # 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; otherwise the system version will be used. Not enabled by default because it takes a while to build # 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"] static-link-openssl = ["dep:openssl", "nu-cmd-lang/static-link-openssl"]
mimalloc = ["nu-cmd-lang/mimalloc", "dep:mimalloc"] mimalloc = ["nu-cmd-lang/mimalloc", "dep:mimalloc"]
@ -164,8 +164,9 @@ bench = false
# To use a development version of a dependency please use a global override here # 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 # changing versions in each sub-crate of the workspace is tedious
[patch.crates-io] [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"} # 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 # Criterion benchmarking setup
# Run all benchmarks with `cargo bench` # Run all benchmarks with `cargo bench`

View File

@ -7,7 +7,6 @@
[![@nu_shell](https://img.shields.io/badge/twitter-@nu_shell-1DA1F3?style=flat-square)](https://twitter.com/nu_shell) [![@nu_shell](https://img.shields.io/badge/twitter-@nu_shell-1DA1F3?style=flat-square)](https://twitter.com/nu_shell)
[![GitHub commit activity](https://img.shields.io/github/commit-activity/m/nushell/nushell)](https://github.com/nushell/nushell/graphs/commit-activity) [![GitHub commit activity](https://img.shields.io/github/commit-activity/m/nushell/nushell)](https://github.com/nushell/nushell/graphs/commit-activity)
[![GitHub contributors](https://img.shields.io/github/contributors/nushell/nushell)](https://github.com/nushell/nushell/graphs/contributors) [![GitHub contributors](https://img.shields.io/github/contributors/nushell/nushell)](https://github.com/nushell/nushell/graphs/contributors)
[![codecov](https://codecov.io/gh/nushell/nushell/branch/main/graph/badge.svg?token=JheS8qu2II)](https://codecov.io/gh/nushell/nushell)
A new type of shell. A new type of shell.
@ -220,13 +219,15 @@ Please submit an issue or PR to be added to this list.
- [virtualenv](https://github.com/pypa/virtualenv) - [virtualenv](https://github.com/pypa/virtualenv)
- [atuin](https://github.com/ellie/atuin) - [atuin](https://github.com/ellie/atuin)
- [clap](https://github.com/clap-rs/clap/tree/master/clap_complete_nushell) - [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 ## Contributing
See [Contributing](CONTRIBUTING.md) for details. Thanks to all the people who already contributed! See [Contributing](CONTRIBUTING.md) for details. Thanks to all the people who already contributed!
<a href="https://github.com/nushell/nushell/graphs/contributors"> <a href="https://github.com/nushell/nushell/graphs/contributors">
<img src="https://contributors-img.web.app/image?repo=nushell/nushell&max=500" /> <img src="https://contributors-img.web.app/image?repo=nushell/nushell&max=600" />
</a> </a>
## License ## License

View File

@ -114,15 +114,13 @@ fn eval_benchmarks(c: &mut Criterion) {
// generate a new table data with `row_cnt` rows, `col_cnt` columns. // generate a new table data with `row_cnt` rows, `col_cnt` columns.
fn encoding_test_data(row_cnt: usize, col_cnt: usize) -> Value { fn encoding_test_data(row_cnt: usize, col_cnt: usize) -> Value {
let columns: Vec<String> = (0..col_cnt).map(|x| format!("col_{x}")).collect(); let record = Value::test_record(
let vals: Vec<Value> = (0..col_cnt as i64).map(Value::test_int).collect(); (0..col_cnt)
.map(|x| (format!("col_{x}"), Value::test_int(x as i64)))
Value::List {
vals: (0..row_cnt)
.map(|_| Value::test_record(columns.clone(), vals.clone()))
.collect(), .collect(),
span: Span::test_data(), );
}
Value::list(vec![record; row_cnt], Span::test_data())
} }
fn encoding_benchmarks(c: &mut Criterion) { fn encoding_benchmarks(c: &mut Criterion) {

View File

@ -1,17 +0,0 @@
coverage:
status:
project:
default:
target: 55%
threshold: 2%
patch:
default:
informational: true
comment:
layout: reach, diff, files
behavior: default
require_base: yes
require_head: yes
after_n_builds: 1 # Disabled windows else: 2

View File

@ -5,40 +5,41 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cli"
edition = "2021" edition = "2021"
license = "MIT" license = "MIT"
name = "nu-cli" name = "nu-cli"
version = "0.84.0" version = "0.86.0"
[lib] [lib]
bench = false bench = false
[dev-dependencies] [dev-dependencies]
nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.84.0" } nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.86.0" }
nu-test-support = { path = "../nu-test-support", version = "0.84.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 } rstest = { version = "0.18.1", default-features = false }
[dependencies] [dependencies]
nu-cmd-base = { path = "../nu-cmd-base", version = "0.84.0" } nu-cmd-base = { path = "../nu-cmd-base", version = "0.86.0" }
nu-command = { path = "../nu-command", version = "0.84.0" } nu-engine = { path = "../nu-engine", version = "0.86.0" }
nu-engine = { path = "../nu-engine", version = "0.84.0" } nu-path = { path = "../nu-path", version = "0.86.0" }
nu-path = { path = "../nu-path", version = "0.84.0" } nu-parser = { path = "../nu-parser", version = "0.86.0" }
nu-parser = { path = "../nu-parser", version = "0.84.0" } nu-protocol = { path = "../nu-protocol", version = "0.86.0" }
nu-protocol = { path = "../nu-protocol", version = "0.84.0" } nu-utils = { path = "../nu-utils", version = "0.86.0" }
nu-utils = { path = "../nu-utils", version = "0.84.0" } nu-color-config = { path = "../nu-color-config", version = "0.86.0" }
nu-color-config = { path = "../nu-color-config", version = "0.84.0" }
nu-ansi-term = "0.49.0" nu-ansi-term = "0.49.0"
reedline = { version = "0.23.0", features = ["bashisms", "sqlite"]} reedline = { version = "0.25.0", features = ["bashisms", "sqlite"] }
chrono = { default-features = false, features = ["std"], version = "0.4" } chrono = { default-features = false, features = ["std"], version = "0.4" }
crossterm = "0.26" crossterm = "0.27"
fancy-regex = "0.11" fancy-regex = "0.11"
fuzzy-matcher = "0.3" fuzzy-matcher = "0.3"
is_executable = "1.0" is_executable = "1.0"
is-terminal = "0.4.8"
log = "0.4" log = "0.4"
miette = { version = "5.10", features = ["fancy-no-backtrace"] } miette = { version = "5.10", features = ["fancy-no-backtrace"] }
once_cell = "1.18" once_cell = "1.18"
percent-encoding = "2" percent-encoding = "2"
pathdiff = "0.2"
sysinfo = "0.29" sysinfo = "0.29"
unicode-segmentation = "1.10" unicode-segmentation = "1.10"
uuid = { version = "1.4.1", features = ["v4"] }
[features] [features]
plugin = [] plugin = []

View File

@ -1,9 +1,9 @@
use nu_engine::CallExt; use nu_engine::CallExt;
use nu_protocol::ast::Call; use nu_protocol::{
use nu_protocol::engine::{Command, EngineState, Stack}; ast::Call,
use nu_protocol::Category; engine::{Command, EngineState, Stack},
use nu_protocol::IntoPipelineData; Category, IntoPipelineData, PipelineData, ShellError, Signature, SyntaxShape, Type, Value,
use nu_protocol::{PipelineData, ShellError, Signature, SyntaxShape, Type, Value}; };
use unicode_segmentation::UnicodeSegmentation; use unicode_segmentation::UnicodeSegmentation;
#[derive(Clone)] #[derive(Clone)]
@ -25,6 +25,11 @@ impl Command for Commandline {
"Set or get the current cursor position", "Set or get the current cursor position",
Some('c'), Some('c'),
) )
.switch(
"cursor-end",
"Set the current cursor position to the end of the buffer",
Some('e'),
)
.switch( .switch(
"append", "append",
"appends the string to the end of the buffer", "appends the string to the end of the buffer",
@ -84,9 +89,9 @@ impl Command for Commandline {
return Err(ShellError::CantConvert { return Err(ShellError::CantConvert {
to_type: "int".to_string(), to_type: "int".to_string(),
from_type: "string".to_string(), from_type: "string".to_string(),
span: cmd.span()?, span: cmd.span(),
help: Some(format!( help: Some(format!(
r#"string "{cmd_str}" does not represent a valid integer"# r#"string "{cmd_str}" does not represent a valid int"#
)), )),
}) })
} }
@ -102,27 +107,22 @@ impl Command for Commandline {
repl.buffer = cmd.as_string()?; repl.buffer = cmd.as_string()?;
repl.cursor_pos = repl.buffer.len(); repl.cursor_pos = repl.buffer.len();
} }
Ok(Value::Nothing { span: call.head }.into_pipeline_data()) Ok(Value::nothing(call.head).into_pipeline_data())
} else { } else {
let repl = engine_state.repl_state.lock().expect("repl state mutex"); let mut repl = engine_state.repl_state.lock().expect("repl state mutex");
if call.has_flag("cursor") { if call.has_flag("cursor-end") {
repl.cursor_pos = repl.buffer.graphemes(true).count();
Ok(Value::nothing(call.head).into_pipeline_data())
} else if call.has_flag("cursor") {
let char_pos = repl let char_pos = repl
.buffer .buffer
.grapheme_indices(true) .grapheme_indices(true)
.chain(std::iter::once((repl.buffer.len(), ""))) .chain(std::iter::once((repl.buffer.len(), "")))
.position(|(i, _c)| i == repl.cursor_pos) .position(|(i, _c)| i == repl.cursor_pos)
.expect("Cursor position isn't on a grapheme boundary"); .expect("Cursor position isn't on a grapheme boundary");
Ok(Value::String { Ok(Value::string(char_pos.to_string(), call.head).into_pipeline_data())
val: char_pos.to_string(),
span: call.head,
}
.into_pipeline_data())
} else { } else {
Ok(Value::String { Ok(Value::string(repl.buffer.to_string(), call.head).into_pipeline_data())
val: repl.buffer.to_string(),
span: call.head,
}
.into_pipeline_data())
} }
} }
} }

View File

@ -1,8 +1,8 @@
use nu_protocol::ast::Call; use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack}; use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{ use nu_protocol::{
Category, Example, HistoryFileFormat, IntoInterruptiblePipelineData, PipelineData, ShellError, record, Category, Example, HistoryFileFormat, IntoInterruptiblePipelineData, PipelineData,
Signature, Span, Type, Value, ShellError, Signature, Span, Type, Value,
}; };
use reedline::{ use reedline::{
FileBackedHistory, History as ReedlineHistory, HistoryItem, SearchDirection, SearchQuery, FileBackedHistory, History as ReedlineHistory, HistoryItem, SearchDirection, SearchQuery,
@ -70,12 +70,14 @@ impl Command for History {
} else { } else {
let history_reader: Option<Box<dyn ReedlineHistory>> = let history_reader: Option<Box<dyn ReedlineHistory>> =
match engine_state.config.history_file_format { match engine_state.config.history_file_format {
HistoryFileFormat::Sqlite => SqliteBackedHistory::with_file(history_path) HistoryFileFormat::Sqlite => {
.map(|inner| { SqliteBackedHistory::with_file(history_path, None, None)
let boxed: Box<dyn ReedlineHistory> = Box::new(inner); .map(|inner| {
boxed let boxed: Box<dyn ReedlineHistory> = Box::new(inner);
}) boxed
.ok(), })
.ok()
}
HistoryFileFormat::PlainText => FileBackedHistory::with_file( HistoryFileFormat::PlainText => FileBackedHistory::with_file(
engine_state.config.max_history_size as usize, engine_state.config.max_history_size as usize,
@ -95,20 +97,15 @@ impl Command for History {
.ok() .ok()
}) })
.map(move |entries| { .map(move |entries| {
entries entries.into_iter().enumerate().map(move |(idx, entry)| {
.into_iter() Value::record(
.enumerate() record! {
.map(move |(idx, entry)| Value::Record { "command" => Value::string(entry.command_line, head),
cols: vec!["command".to_string(), "index".to_string()], "index" => Value::int(idx as i64, head),
vals: vec![ },
Value::String { head,
val: entry.command_line, )
span: head, })
},
Value::int(idx as i64, head),
],
span: head,
})
}) })
.ok_or(ShellError::FileNotFound(head))? .ok_or(ShellError::FileNotFound(head))?
.into_pipeline_data(ctrlc)), .into_pipeline_data(ctrlc)),
@ -144,7 +141,7 @@ impl Command for History {
result: None, result: None,
}, },
Example { Example {
example: "history | wrap cmd | where cmd =~ cargo", example: "history | where command =~ cargo | get command",
description: "Search all the commands from history that contains 'cargo'", description: "Search all the commands from history that contains 'cargo'",
result: None, result: None,
}, },
@ -156,8 +153,8 @@ fn create_history_record(idx: usize, entry: HistoryItem, long: bool, head: Span)
//1. Format all the values //1. Format all the values
//2. Create a record of either short or long columns and values //2. Create a record of either short or long columns and values
let item_id_value = Value::Int { let item_id_value = Value::int(
val: match entry.id { match entry.id {
Some(id) => { Some(id) => {
let ids = id.to_string(); let ids = id.to_string();
match ids.parse::<i64>() { match ids.parse::<i64>() {
@ -167,21 +164,18 @@ fn create_history_record(idx: usize, entry: HistoryItem, long: bool, head: Span)
} }
None => 0i64, None => 0i64,
}, },
span: head, head,
}; );
let start_timestamp_value = Value::String { let start_timestamp_value = Value::string(
val: match entry.start_timestamp { match entry.start_timestamp {
Some(time) => time.to_string(), Some(time) => time.to_string(),
None => "".into(), None => "".into(),
}, },
span: head, head,
}; );
let command_value = Value::String { let command_value = Value::string(entry.command_line, head);
val: entry.command_line, let session_id_value = Value::int(
span: head, match entry.session_id {
};
let session_id_value = Value::Int {
val: match entry.session_id {
Some(sid) => { Some(sid) => {
let sids = sid.to_string(); let sids = sid.to_string();
match sids.parse::<i64>() { match sids.parse::<i64>() {
@ -191,74 +185,56 @@ fn create_history_record(idx: usize, entry: HistoryItem, long: bool, head: Span)
} }
None => 0i64, None => 0i64,
}, },
span: head, head,
}; );
let hostname_value = Value::String { let hostname_value = Value::string(
val: match entry.hostname { match entry.hostname {
Some(host) => host, Some(host) => host,
None => "".into(), None => "".into(),
}, },
span: head, head,
}; );
let cwd_value = Value::String { let cwd_value = Value::string(
val: match entry.cwd { match entry.cwd {
Some(cwd) => cwd, Some(cwd) => cwd,
None => "".into(), None => "".into(),
}, },
span: head, head,
}; );
let duration_value = Value::Duration { let duration_value = Value::duration(
val: match entry.duration { match entry.duration {
Some(d) => d.as_nanos().try_into().unwrap_or(0), Some(d) => d.as_nanos().try_into().unwrap_or(0),
None => 0, None => 0,
}, },
span: head, head,
}; );
let exit_status_value = Value::int(entry.exit_status.unwrap_or(0), head); let exit_status_value = Value::int(entry.exit_status.unwrap_or(0), head);
let index_value = Value::int(idx as i64, head); let index_value = Value::int(idx as i64, head);
if long { if long {
Value::Record { Value::record(
cols: vec![ record! {
"item_id".into(), "item_id" => item_id_value,
"start_timestamp".into(), "start_timestamp" => start_timestamp_value,
"command".to_string(), "command" => command_value,
"session_id".into(), "session_id" => session_id_value,
"hostname".into(), "hostname" => hostname_value,
"cwd".into(), "cwd" => cwd_value,
"duration".into(), "duration" => duration_value,
"exit_status".into(), "exit_status" => exit_status_value,
"idx".to_string(), "idx" => index_value,
], },
vals: vec![ head,
item_id_value, )
start_timestamp_value,
command_value,
session_id_value,
hostname_value,
cwd_value,
duration_value,
exit_status_value,
index_value,
],
span: head,
}
} else { } else {
Value::Record { Value::record(
cols: vec![ record! {
"start_timestamp".into(), "start_timestamp" => start_timestamp_value,
"command".to_string(), "command" => command_value,
"cwd".into(), "cwd" => cwd_value,
"duration".into(), "duration" => duration_value,
"exit_status".into(), "exit_status" => exit_status_value,
], },
vals: vec![ head,
start_timestamp_value, )
command_value,
cwd_value,
duration_value,
exit_status_value,
],
span: head,
}
} }
} }

View File

@ -24,7 +24,10 @@ impl Command for Keybindings {
} }
fn extra_usage(&self) -> &str { fn extra_usage(&self) -> &str {
"You must use one of the following subcommands. Using this command as-is will only produce this help message." r#"You must use one of the following subcommands. Using this command as-is will only produce this help message.
For more information on input and keybindings, check:
https://www.nushell.sh/book/line_editor.html"#
} }
fn search_terms(&self) -> Vec<&str> { fn search_terms(&self) -> Vec<&str> {
@ -38,16 +41,16 @@ impl Command for Keybindings {
call: &Call, call: &Call,
_input: PipelineData, _input: PipelineData,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
Ok(Value::String { Ok(Value::string(
val: get_full_help( get_full_help(
&Keybindings.signature(), &Keybindings.signature(),
&Keybindings.examples(), &Keybindings.examples(),
engine_state, engine_state,
stack, stack,
self.is_parser_keyword(), self.is_parser_keyword(),
), ),
span: call.head, call.head,
} )
.into_pipeline_data()) .into_pipeline_data())
} }
} }

View File

@ -1,7 +1,7 @@
use nu_protocol::{ use nu_protocol::{
ast::Call, ast::Call,
engine::{Command, EngineState, Stack}, engine::{Command, EngineState, Stack},
Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, Type, Value, record, Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, Type, Value,
}; };
use reedline::get_reedline_default_keybindings; use reedline::get_reedline_default_keybindings;
@ -41,43 +41,18 @@ impl Command for KeybindingsDefault {
let records = get_reedline_default_keybindings() let records = get_reedline_default_keybindings()
.into_iter() .into_iter()
.map(|(mode, modifier, code, event)| { .map(|(mode, modifier, code, event)| {
let mode = Value::String { Value::record(
val: mode, record! {
span: call.head, "mode" => Value::string(mode, call.head),
}; "modifier" => Value::string(modifier, call.head),
"code" => Value::string(code, call.head),
let modifier = Value::String { "event" => Value::string(event, call.head),
val: modifier, },
span: call.head, call.head,
}; )
let code = Value::String {
val: code,
span: call.head,
};
let event = Value::String {
val: event,
span: call.head,
};
Value::Record {
cols: vec![
"mode".to_string(),
"modifier".to_string(),
"code".to_string(),
"event".to_string(),
],
vals: vec![mode, modifier, code, event],
span: call.head,
}
}) })
.collect(); .collect();
Ok(Value::List { Ok(Value::list(records, call.head).into_pipeline_data())
vals: records,
span: call.head,
}
.into_pipeline_data())
} }
} }

View File

@ -1,7 +1,8 @@
use nu_protocol::{ use nu_protocol::{
ast::Call, ast::Call,
engine::{Command, EngineState, Stack}, engine::{Command, EngineState, Stack},
Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, Type, Value, record, Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, Type,
Value,
}; };
use reedline::{ use reedline::{
get_reedline_edit_commands, get_reedline_keybinding_modifiers, get_reedline_keycodes, get_reedline_edit_commands, get_reedline_keybinding_modifiers, get_reedline_keycodes,
@ -70,11 +71,7 @@ impl Command for KeybindingsList {
.collect() .collect()
}; };
Ok(Value::List { Ok(Value::list(records, call.head).into_pipeline_data())
vals: records,
span: call.head,
}
.into_pipeline_data())
} }
} }
@ -96,15 +93,13 @@ fn get_records(entry_type: &str, span: Span) -> Vec<Value> {
} }
fn convert_to_record(edit: &str, entry_type: &str, span: Span) -> Value { fn convert_to_record(edit: &str, entry_type: &str, span: Span) -> Value {
let entry_type = Value::string(entry_type, span); Value::record(
record! {
let name = Value::string(edit, span); "type" => Value::string(entry_type, span),
"name" => Value::string(edit, span),
Value::Record { },
cols: vec!["type".to_string(), "name".to_string()],
vals: vec![entry_type, name],
span, span,
} )
} }
// Helper to sort a vec and return a vec // Helper to sort a vec and return a vec

View File

@ -1,9 +1,11 @@
use crossterm::execute;
use crossterm::QueueableCommand; use crossterm::QueueableCommand;
use crossterm::{event::Event, event::KeyCode, event::KeyEvent, terminal}; use crossterm::{event::Event, event::KeyCode, event::KeyEvent, terminal};
use nu_protocol::ast::Call; use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack}; use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{ use nu_protocol::{
Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, Type, Value, record, Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, Type,
Value,
}; };
use std::io::{stdout, Write}; use std::io::{stdout, Write};
@ -19,6 +21,10 @@ impl Command for KeybindingsListen {
"Get input from the user." "Get input from the user."
} }
fn extra_usage(&self) -> &str {
"This is an internal debugging tool. For better output, try `input listen --types [key]`"
}
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build(self.name()) Signature::build(self.name())
.category(Category::Platform) .category(Category::Platform)
@ -64,6 +70,32 @@ pub fn print_events(engine_state: &EngineState) -> Result<Value, ShellError> {
stdout().flush()?; stdout().flush()?;
terminal::enable_raw_mode()?; 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()); let mut stdout = std::io::BufWriter::new(std::io::stderr());
loop { loop {
@ -78,9 +110,8 @@ pub fn print_events(engine_state: &EngineState) -> Result<Value, ShellError> {
let v = print_events_helper(event)?; let v = print_events_helper(event)?;
// Print out the record // Print out the record
let o = match v { let o = match v {
Value::Record { cols, vals, .. } => cols Value::Record { val, .. } => val
.iter() .iter()
.zip(vals.iter())
.map(|(x, y)| format!("{}: {}", x, y.into_string("", config))) .map(|(x, y)| format!("{}: {}", x, y.into_string("", config)))
.collect::<Vec<String>>() .collect::<Vec<String>>()
.join(", "), .join(", "),
@ -91,6 +122,14 @@ pub fn print_events(engine_state: &EngineState) -> Result<Value, ShellError> {
stdout.queue(crossterm::style::Print("\r\n"))?; stdout.queue(crossterm::style::Print("\r\n"))?;
stdout.flush()?; stdout.flush()?;
} }
if config.use_kitty_protocol {
let _ = execute!(
std::io::stdout(),
crossterm::event::PopKeyboardEnhancementFlags
);
}
terminal::disable_raw_mode()?; terminal::disable_raw_mode()?;
Ok(Value::nothing(Span::unknown())) Ok(Value::nothing(Span::unknown()))
@ -111,54 +150,29 @@ fn print_events_helper(event: Event) -> Result<Value, ShellError> {
{ {
match code { match code {
KeyCode::Char(c) => { KeyCode::Char(c) => {
let record = Value::Record { let record = record! {
cols: vec![ "char" => Value::string(format!("{c}"), Span::unknown()),
"char".into(), "code" => Value::string(format!("{:#08x}", u32::from(c)), Span::unknown()),
"code".into(), "modifier" => Value::string(format!("{modifiers:?}"), Span::unknown()),
"modifier".into(), "flags" => Value::string(format!("{modifiers:#08b}"), Span::unknown()),
"flags".into(), "kind" => Value::string(format!("{kind:?}"), Span::unknown()),
"kind".into(), "state" => Value::string(format!("{state:?}"), Span::unknown()),
"state".into(),
],
vals: vec![
Value::string(format!("{c}"), Span::unknown()),
Value::string(format!("{:#08x}", u32::from(c)), Span::unknown()),
Value::string(format!("{modifiers:?}"), Span::unknown()),
Value::string(format!("{modifiers:#08b}"), Span::unknown()),
Value::string(format!("{kind:?}"), Span::unknown()),
Value::string(format!("{state:?}"), Span::unknown()),
],
span: Span::unknown(),
}; };
Ok(record) Ok(Value::record(record, Span::unknown()))
} }
_ => { _ => {
let record = Value::Record { let record = record! {
cols: vec![ "code" => Value::string(format!("{code:?}"), Span::unknown()),
"code".into(), "modifier" => Value::string(format!("{modifiers:?}"), Span::unknown()),
"modifier".into(), "flags" => Value::string(format!("{modifiers:#08b}"), Span::unknown()),
"flags".into(), "kind" => Value::string(format!("{kind:?}"), Span::unknown()),
"kind".into(), "state" => Value::string(format!("{state:?}"), Span::unknown()),
"state".into(),
],
vals: vec![
Value::string(format!("{code:?}"), Span::unknown()),
Value::string(format!("{modifiers:?}"), Span::unknown()),
Value::string(format!("{modifiers:#08b}"), Span::unknown()),
Value::string(format!("{kind:?}"), Span::unknown()),
Value::string(format!("{state:?}"), Span::unknown()),
],
span: Span::unknown(),
}; };
Ok(record) Ok(Value::record(record, Span::unknown()))
} }
} }
} else { } else {
let record = Value::Record { let record = record! { "event" => Value::string(format!("{event:?}"), Span::unknown()) };
cols: vec!["event".into()], Ok(Value::record(record, Span::unknown()))
vals: vec![Value::string(format!("{event:?}"), Span::unknown())],
span: Span::unknown(),
};
Ok(record)
} }
} }

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 cur_pos = find_non_whitespace_index(contents, last_pipe_pos);
let result = match contents.get(cur_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, None => false,
}; };
if result { if result {
@ -263,7 +263,7 @@ mod command_completions_tests {
(" hello sud", 1), (" hello sud", 1),
]; ];
for (idx, ele) in commands.iter().enumerate() { for (idx, ele) in commands.iter().enumerate() {
let index = find_non_whitespace_index(&Vec::from(ele.0.as_bytes()), 0); let index = find_non_whitespace_index(ele.0.as_bytes(), 0);
assert_eq!(index, ele.1, "Failed on index {}", idx); assert_eq!(index, ele.1, "Failed on index {}", idx);
} }
} }

View File

@ -74,13 +74,13 @@ impl NuCompleter {
if let Some(var_id) = pos_arg.var_id { if let Some(var_id) = pos_arg.var_id {
callee_stack.add_var( callee_stack.add_var(
var_id, var_id,
Value::List { Value::list(
vals: spans spans
.iter() .iter()
.map(|it| Value::string(it, Span::unknown())) .map(|it| Value::string(it, Span::unknown()))
.collect(), .collect(),
span: Span::unknown(), Span::unknown(),
}, ),
); );
} }
} }
@ -97,7 +97,7 @@ impl NuCompleter {
match result { match result {
Ok(pd) => { Ok(pd) => {
let value = pd.into_value(span); let value = pd.into_value(span);
if let Value::List { vals, span: _ } = value { if let Value::List { vals, .. } = value {
let result = let result =
map_value_completions(vals.iter(), Span::new(span.start, span.end), offset); map_value_completions(vals.iter(), Span::new(span.start, span.end), offset);
@ -136,7 +136,9 @@ impl NuCompleter {
for (flat_idx, flat) in flattened.iter().enumerate() { for (flat_idx, flat) in flattened.iter().enumerate() {
let is_passthrough_command = spans let is_passthrough_command = spans
.first() .first()
.filter(|content| *content == &String::from("sudo")) .filter(|content| {
content.as_str() == "sudo" || content.as_str() == "doas"
})
.is_some(); .is_some();
// Read the current spam to string // Read the current spam to string
let current_span = working_set.get_span_contents(flat.0).to_vec(); let current_span = working_set.get_span_contents(flat.0).to_vec();
@ -454,7 +456,7 @@ pub fn map_value_completions<'a>(
} }
// Match for record values // Match for record values
if let Ok((cols, vals)) = x.as_record() { if let Ok(record) = x.as_record() {
let mut suggestion = Suggestion { let mut suggestion = Suggestion {
value: String::from(""), // Initialize with empty string value: String::from(""), // Initialize with empty string
description: None, description: None,
@ -467,7 +469,7 @@ pub fn map_value_completions<'a>(
}; };
// Iterate the cols looking for `value` and `description` // Iterate the cols looking for `value` and `description`
cols.iter().zip(vals).for_each(|it| { record.iter().for_each(|it| {
// Match `value` column // Match `value` column
if it.0 == "value" { if it.0 == "value" {
// Convert the value to string // Convert the value to string

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::{ use nu_protocol::{
engine::{EngineState, StateWorkingSet}, engine::{EngineState, StateWorkingSet},
levenshtein_distance, Span, levenshtein_distance, Span,
}; };
use reedline::Suggestion; use reedline::Suggestion;
use std::fs; use std::path::{Path, MAIN_SEPARATOR as SEP};
use std::path::Path;
use std::sync::Arc; use std::sync::Arc;
use super::{partial_from, prepend_base_dir, SortBy};
const SEP: char = std::path::MAIN_SEPARATOR;
#[derive(Clone)] #[derive(Clone)]
pub struct DirectoryCompletion { pub struct DirectoryCompletion {
engine_state: Arc<EngineState>, engine_state: Arc<EngineState>,
@ -33,23 +28,27 @@ impl Completer for DirectoryCompletion {
_: usize, _: usize,
options: &CompletionOptions, options: &CompletionOptions,
) -> Vec<Suggestion> { ) -> Vec<Suggestion> {
let cwd = self.engine_state.current_work_dir();
let partial = String::from_utf8_lossy(&prefix).to_string(); let partial = String::from_utf8_lossy(&prefix).to_string();
// Filter only the folders // Filter only the folders
let output: Vec<_> = directory_completion(span, &partial, &cwd, options) let output: Vec<_> = directory_completion(
.into_iter() span,
.map(move |x| Suggestion { &partial,
value: x.1, &self.engine_state.current_work_dir(),
description: None, options,
extra: None, )
span: reedline::Span { .into_iter()
start: x.0.start - offset, .map(move |x| Suggestion {
end: x.0.end - offset, value: x.1,
}, description: None,
append_whitespace: false, extra: None,
}) span: reedline::Span {
.collect(); start: x.0.start - offset,
end: x.0.end - offset,
},
append_whitespace: false,
})
.collect();
output output
} }
@ -63,7 +62,12 @@ impl Completer for DirectoryCompletion {
match self.get_sort_by() { match self.get_sort_by() {
SortBy::Ascending => { SortBy::Ascending => {
sorted_items.sort_by(|a, b| a.value.cmp(&b.value)); sorted_items.sort_by(|a, b| {
// Ignore trailing slashes in folder names when sorting
a.value
.trim_end_matches(SEP)
.cmp(b.value.trim_end_matches(SEP))
});
} }
SortBy::LevenshteinDistance => { SortBy::LevenshteinDistance => {
sorted_items.sort_by(|a, b| { sorted_items.sort_by(|a, b| {
@ -106,60 +110,5 @@ pub fn directory_completion(
cwd: &str, cwd: &str,
options: &CompletionOptions, options: &CompletionOptions,
) -> Vec<(nu_protocol::Span, String)> { ) -> Vec<(nu_protocol::Span, String)> {
let original_input = partial; complete_item(true, span, partial, cwd, options)
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()
} }

View File

@ -1,13 +1,13 @@
use crate::completions::{ use crate::completions::{file_path_completion, Completer, CompletionOptions, SortBy};
file_path_completion, partial_from, Completer, CompletionOptions, SortBy,
};
use nu_protocol::{ use nu_protocol::{
engine::{EngineState, StateWorkingSet}, engine::{EngineState, StateWorkingSet},
Span, Span,
}; };
use reedline::Suggestion; use reedline::Suggestion;
use std::sync::Arc; use std::{
const SEP: char = std::path::MAIN_SEPARATOR; path::{is_separator, MAIN_SEPARATOR as SEP, MAIN_SEPARATOR_STR},
sync::Arc,
};
#[derive(Clone)] #[derive(Clone)]
pub struct DotNuCompletion { pub struct DotNuCompletion {
@ -30,9 +30,16 @@ impl Completer for DotNuCompletion {
_: usize, _: usize,
options: &CompletionOptions, options: &CompletionOptions,
) -> Vec<Suggestion> { ) -> 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 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; let mut is_current_folder = false;
// Fetch the lib dirs // Fetch the lib dirs
@ -58,7 +65,8 @@ impl Completer for DotNuCompletion {
}; };
// Check if the base_dir is a folder // 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 // Add the base dir into the directories to be searched
search_dirs.push(base_dir.clone()); 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::{ use nu_protocol::{
engine::{EngineState, StateWorkingSet}, engine::{EngineState, StateWorkingSet},
levenshtein_distance, Span, levenshtein_distance, Span,
}; };
use reedline::Suggestion; use reedline::Suggestion;
use std::path::{is_separator, Path}; use std::path::{Path, MAIN_SEPARATOR as SEP};
use std::sync::Arc; use std::sync::Arc;
use super::SortBy;
const SEP: char = std::path::MAIN_SEPARATOR;
#[derive(Clone)] #[derive(Clone)]
pub struct FileCompletion { pub struct FileCompletion {
engine_state: Arc<EngineState>, engine_state: Arc<EngineState>,
@ -32,21 +28,25 @@ impl Completer for FileCompletion {
_: usize, _: usize,
options: &CompletionOptions, options: &CompletionOptions,
) -> Vec<Suggestion> { ) -> Vec<Suggestion> {
let cwd = self.engine_state.current_work_dir();
let prefix = String::from_utf8_lossy(&prefix).to_string(); let prefix = String::from_utf8_lossy(&prefix).to_string();
let output: Vec<_> = file_path_completion(span, &prefix, &cwd, options) let output: Vec<_> = file_path_completion(
.into_iter() span,
.map(move |x| Suggestion { &prefix,
value: x.1, &self.engine_state.current_work_dir(),
description: None, options,
extra: None, )
span: reedline::Span { .into_iter()
start: x.0.start - offset, .map(move |x| Suggestion {
end: x.0.end - offset, value: x.1,
}, description: None,
append_whitespace: false, extra: None,
}) span: reedline::Span {
.collect(); start: x.0.start - offset,
end: x.0.end - offset,
},
append_whitespace: false,
})
.collect();
output output
} }
@ -60,7 +60,12 @@ impl Completer for FileCompletion {
match self.get_sort_by() { match self.get_sort_by() {
SortBy::Ascending => { SortBy::Ascending => {
sorted_items.sort_by(|a, b| a.value.cmp(&b.value)); sorted_items.sort_by(|a, b| {
// Ignore trailing slashes in folder names when sorting
a.value
.trim_end_matches(SEP)
.cmp(b.value.trim_end_matches(SEP))
});
} }
SortBy::LevenshteinDistance => { SortBy::LevenshteinDistance => {
sorted_items.sort_by(|a, b| { sorted_items.sort_by(|a, b| {
@ -97,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( pub fn file_path_completion(
span: nu_protocol::Span, span: nu_protocol::Span,
partial: &str, partial: &str,
cwd: &str, cwd: &str,
options: &CompletionOptions, options: &CompletionOptions,
) -> Vec<(nu_protocol::Span, String)> { ) -> Vec<(nu_protocol::Span, String)> {
let original_input = partial; complete_item(false, span, partial, cwd, options)
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()
} }
pub fn matches(partial: &str, from: &str, options: &CompletionOptions) -> bool { pub fn matches(partial: &str, from: &str, options: &CompletionOptions) -> bool {
@ -187,23 +121,3 @@ pub fn matches(partial: &str, from: &str, options: &CompletionOptions) -> bool {
options.match_algorithm.matches_str(from, partial) 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 base;
mod command_completions; mod command_completions;
mod completer; mod completer;
mod completion_common;
mod completion_options; mod completion_options;
mod custom_completions; mod custom_completions;
mod directory_completions; mod directory_completions;
@ -16,8 +17,6 @@ pub use completion_options::{CompletionOptions, MatchAlgorithm, SortBy};
pub use custom_completions::CustomCompletion; pub use custom_completions::CustomCompletion;
pub use directory_completions::DirectoryCompletion; pub use directory_completions::DirectoryCompletion;
pub use dotnu_completions::DotNuCompletion; pub use dotnu_completions::DotNuCompletion;
pub use file_completions::{ pub use file_completions::{file_path_completion, matches, FileCompletion};
file_path_completion, matches, partial_from, prepend_base_dir, FileCompletion,
};
pub use flag_completions::FlagCompletion; pub use flag_completions::FlagCompletion;
pub use variable_completions::VariableCompletion; pub use variable_completions::VariableCompletion;

View File

@ -235,13 +235,9 @@ fn nested_suggestions(
let value = recursive_value(val, sublevels); let value = recursive_value(val, sublevels);
match value { match value {
Value::Record { Value::Record { val, .. } => {
cols,
vals: _,
span: _,
} => {
// Add all the columns as completion // Add all the columns as completion
for item in cols { for item in val.cols {
output.push(Suggestion { output.push(Suggestion {
value: item, value: item,
description: None, description: None,
@ -267,7 +263,7 @@ fn nested_suggestions(
output output
} }
Value::List { vals, span: _ } => { Value::List { vals, .. } => {
for column_name in get_columns(vals.as_slice()) { for column_name in get_columns(vals.as_slice()) {
output.push(Suggestion { output.push(Suggestion {
value: column_name, value: column_name,
@ -288,13 +284,10 @@ fn nested_suggestions(
fn recursive_value(val: Value, sublevels: Vec<Vec<u8>>) -> Value { fn recursive_value(val: Value, sublevels: Vec<Vec<u8>>) -> Value {
// Go to next sublevel // Go to next sublevel
if let Some(next_sublevel) = sublevels.clone().into_iter().next() { if let Some(next_sublevel) = sublevels.clone().into_iter().next() {
let span = val.span();
match val { match val {
Value::Record { Value::Record { val, .. } => {
cols, for item in val {
vals,
span: _,
} => {
for item in cols.into_iter().zip(vals) {
// Check if index matches with sublevel // Check if index matches with sublevel
if item.0.as_bytes().to_vec() == next_sublevel { if item.0.as_bytes().to_vec() == next_sublevel {
// If matches try to fetch recursively the next // If matches try to fetch recursively the next
@ -303,11 +296,9 @@ fn recursive_value(val: Value, sublevels: Vec<Vec<u8>>) -> Value {
} }
// Current sublevel value not found // Current sublevel value not found
return Value::Nothing { return Value::nothing(span);
span: Span::unknown(),
};
} }
Value::LazyRecord { val, span: _ } => { Value::LazyRecord { val, .. } => {
for col in val.column_names() { for col in val.column_names() {
if col.as_bytes().to_vec() == next_sublevel { if col.as_bytes().to_vec() == next_sublevel {
return recursive_value( return recursive_value(
@ -318,15 +309,13 @@ fn recursive_value(val: Value, sublevels: Vec<Vec<u8>>) -> Value {
} }
// Current sublevel value not found // Current sublevel value not found
return Value::Nothing { return Value::nothing(span);
span: Span::unknown(),
};
} }
Value::List { vals, span } => { Value::List { vals, .. } => {
for col in get_columns(vals.as_slice()) { for col in get_columns(vals.as_slice()) {
if col.as_bytes().to_vec() == next_sublevel { if col.as_bytes().to_vec() == next_sublevel {
return recursive_value( return recursive_value(
Value::List { vals, span } Value::list(vals, span)
.get_data_by_key(&col) .get_data_by_key(&col)
.unwrap_or_default(), .unwrap_or_default(),
sublevels.into_iter().skip(1).collect(), sublevels.into_iter().skip(1).collect(),
@ -335,9 +324,7 @@ fn recursive_value(val: Value, sublevels: Vec<Vec<u8>>) -> Value {
} }
// Current sublevel value not found // Current sublevel value not found
return Value::Nothing { return Value::nothing(span);
span: Span::unknown(),
};
} }
_ => return val, _ => return val,
} }

View File

@ -2,7 +2,7 @@ use crate::util::eval_source;
use log::info; use log::info;
use log::trace; use log::trace;
use miette::{IntoDiagnostic, Result}; 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_engine::{convert_env_values, current_dir};
use nu_parser::parse; use nu_parser::parse;
use nu_path::canonicalize_with; use nu_path::canonicalize_with;
@ -107,13 +107,17 @@ pub fn evaluate_file(
trace!("parsing file: {}", file_path_str); trace!("parsing file: {}", file_path_str);
let block = parse(&mut working_set, Some(file_path_str), &file, false); let block = parse(&mut working_set, Some(file_path_str), &file, false);
if let Some(err) = working_set.parse_errors.first() {
report_error(&working_set, err);
std::process::exit(1);
}
for block in &mut working_set.delta.blocks { for block in &mut working_set.delta.blocks {
if block.signature.name == "main" { if block.signature.name == "main" {
block.signature.name = source_filename.to_string_lossy().to_string(); block.signature.name = source_filename.to_string_lossy().to_string();
} else if block.signature.name.starts_with("main ") { } else if block.signature.name.starts_with("main ") {
block.signature.name = source_filename.to_string_lossy().to_string() block.signature.name =
+ " " source_filename.to_string_lossy().to_string() + " " + &block.signature.name[5..];
+ &String::from_utf8_lossy(&block.signature.name.as_bytes()[5..]);
} }
} }
@ -122,14 +126,22 @@ pub fn evaluate_file(
if engine_state.find_decl(b"main", &[]).is_some() { if engine_state.find_decl(b"main", &[]).is_some() {
let args = format!("main {}", args.join(" ")); let args = format!("main {}", args.join(" "));
let pipeline_data = eval_block_with_early_return( let pipeline_data = eval_block(
engine_state, engine_state,
stack, stack,
&block, &block,
PipelineData::empty(), PipelineData::empty(),
false, false,
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| { .unwrap_or_else(|e| {
let working_set = StateWorkingSet::new(engine_state); let working_set = StateWorkingSet::new(engine_state);
report_error(&working_set, &e); report_error(&working_set, &e);
@ -185,7 +197,7 @@ pub(crate) fn print_table_or_error(
// Change the engine_state config to use the passed in configuration // Change the engine_state config to use the passed in configuration
engine_state.set_config(config); engine_state.set_config(config);
if let PipelineData::Value(Value::Error { error }, ..) = &pipeline_data { if let PipelineData::Value(Value::Error { error, .. }, ..) = &pipeline_data {
let working_set = StateWorkingSet::new(engine_state); let working_set = StateWorkingSet::new(engine_state);
report_error(&working_set, &**error); report_error(&working_set, &**error);
std::process::exit(1); std::process::exit(1);
@ -232,7 +244,7 @@ pub(crate) fn print_table_or_error(
fn print_or_exit(pipeline_data: PipelineData, engine_state: &mut EngineState, config: &Config) { fn print_or_exit(pipeline_data: PipelineData, engine_state: &mut EngineState, config: &Config) {
for item in pipeline_data { for item in pipeline_data {
if let Value::Error { error } = item { if let Value::Error { error, .. } = item {
let working_set = StateWorkingSet::new(engine_state); let working_set = StateWorkingSet::new(engine_state);
report_error(&working_set, &*error); report_error(&working_set, &*error);

View File

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

View File

@ -48,14 +48,9 @@ impl Command for NuHighlight {
Ok(line) => { Ok(line) => {
let highlights = highlighter.highlight(&line, line.len()); let highlights = highlighter.highlight(&line, line.len());
Value::String { Value::string(highlights.render_simple(), head)
val: highlights.render_simple(),
span: head,
}
} }
Err(err) => Value::Error { Err(err) => Value::error(err, head),
error: Box::new(err),
},
}, },
ctrlc, ctrlc,
) )

View File

@ -7,6 +7,8 @@ use nu_protocol::{
Config, PipelineData, Value, Config, PipelineData, Value,
}; };
use reedline::Prompt; use reedline::Prompt;
use std::borrow::Cow;
use std::sync::Arc;
// Name of environment variable where the prompt could be stored // Name of environment variable where the prompt could be stored
pub(crate) const PROMPT_COMMAND: &str = "PROMPT_COMMAND"; 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_INSERT: &str = "PROMPT_INDICATOR_VI_INSERT";
pub(crate) const PROMPT_INDICATOR_VI_NORMAL: &str = "PROMPT_INDICATOR_VI_NORMAL"; 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 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: // According to Daniel Imms @Tyriar, we need to do these this way:
// <133 A><prompt><133 B><command><133 C><command output> // <133 A><prompt><133 B><command><133 C><command output>
const PRE_PROMPT_MARKER: &str = "\x1b]133;A\x1b\\"; const PRE_PROMPT_MARKER: &str = "\x1b]133;A\x1b\\";
@ -145,3 +156,119 @@ pub(crate) fn update_prompt<'prompt>(
ret_val 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

@ -7,7 +7,8 @@ use nu_parser::parse;
use nu_protocol::{ use nu_protocol::{
create_menus, create_menus,
engine::{EngineState, Stack, StateWorkingSet}, engine::{EngineState, Stack, StateWorkingSet},
extract_value, Config, ParsedKeybinding, ParsedMenu, PipelineData, ShellError, Span, Value, extract_value, Config, ParsedKeybinding, ParsedMenu, PipelineData, Record, ShellError, Span,
Value,
}; };
use reedline::{ use reedline::{
default_emacs_keybindings, default_vi_insert_keybindings, default_vi_normal_keybindings, default_emacs_keybindings, default_vi_insert_keybindings, default_vi_normal_keybindings,
@ -130,8 +131,9 @@ fn add_menu(
stack: &Stack, stack: &Stack,
config: &Config, config: &Config,
) -> Result<Reedline, ShellError> { ) -> Result<Reedline, ShellError> {
if let Value::Record { cols, vals, span } = &menu.menu_type { let span = menu.menu_type.span();
let layout = extract_value("layout", cols, vals, *span)?.into_string("", config); if let Value::Record { val, .. } = &menu.menu_type {
let layout = extract_value("layout", val, span)?.into_string("", config);
match layout.as_str() { match layout.as_str() {
"columnar" => add_columnar_menu(line_editor, menu, engine_state, stack, config), "columnar" => add_columnar_menu(line_editor, menu, engine_state, stack, config),
@ -140,22 +142,22 @@ fn add_menu(
_ => Err(ShellError::UnsupportedConfigValue( _ => Err(ShellError::UnsupportedConfigValue(
"columnar, list or description".to_string(), "columnar, list or description".to_string(),
menu.menu_type.into_abbreviated_string(config), menu.menu_type.into_abbreviated_string(config),
menu.menu_type.span()?, menu.menu_type.span(),
)), )),
} }
} else { } else {
Err(ShellError::UnsupportedConfigValue( Err(ShellError::UnsupportedConfigValue(
"only record type".to_string(), "only record type".to_string(),
menu.menu_type.into_abbreviated_string(config), menu.menu_type.into_abbreviated_string(config),
menu.menu_type.span()?, menu.menu_type.span(),
)) ))
} }
} }
macro_rules! add_style { macro_rules! add_style {
// first arm match add!(1,2), add!(2,3) etc // first arm match add!(1,2), add!(2,3) etc
($name:expr, $cols: expr, $vals:expr, $span:expr, $config: expr, $menu:expr, $f:expr) => { ($name:expr, $record: expr, $span:expr, $config: expr, $menu:expr, $f:expr) => {
$menu = match extract_value($name, $cols, $vals, *$span) { $menu = match extract_value($name, $record, $span) {
Ok(text) => { Ok(text) => {
let style = match text { let style = match text {
Value::String { val, .. } => lookup_ansi_color_style(&val), Value::String { val, .. } => lookup_ansi_color_style(&val),
@ -177,11 +179,12 @@ pub(crate) fn add_columnar_menu(
stack: &Stack, stack: &Stack,
config: &Config, config: &Config,
) -> Result<Reedline, ShellError> { ) -> Result<Reedline, ShellError> {
let span = menu.menu_type.span();
let name = menu.name.into_string("", config); let name = menu.name.into_string("", config);
let mut columnar_menu = ColumnarMenu::default().with_name(&name); let mut columnar_menu = ColumnarMenu::default().with_name(&name);
if let Value::Record { cols, vals, span } = &menu.menu_type { if let Value::Record { val, .. } = &menu.menu_type {
columnar_menu = match extract_value("columns", cols, vals, *span) { columnar_menu = match extract_value("columns", val, span) {
Ok(columns) => { Ok(columns) => {
let columns = columns.as_int()?; let columns = columns.as_int()?;
columnar_menu.with_columns(columns as u16) columnar_menu.with_columns(columns as u16)
@ -189,7 +192,7 @@ pub(crate) fn add_columnar_menu(
Err(_) => columnar_menu, Err(_) => columnar_menu,
}; };
columnar_menu = match extract_value("col_width", cols, vals, *span) { columnar_menu = match extract_value("col_width", val, span) {
Ok(col_width) => { Ok(col_width) => {
let col_width = col_width.as_int()?; let col_width = col_width.as_int()?;
columnar_menu.with_column_width(Some(col_width as usize)) columnar_menu.with_column_width(Some(col_width as usize))
@ -197,7 +200,7 @@ pub(crate) fn add_columnar_menu(
Err(_) => columnar_menu.with_column_width(None), Err(_) => columnar_menu.with_column_width(None),
}; };
columnar_menu = match extract_value("col_padding", cols, vals, *span) { columnar_menu = match extract_value("col_padding", val, span) {
Ok(col_padding) => { Ok(col_padding) => {
let col_padding = col_padding.as_int()?; let col_padding = col_padding.as_int()?;
columnar_menu.with_column_padding(col_padding as usize) columnar_menu.with_column_padding(col_padding as usize)
@ -206,11 +209,11 @@ pub(crate) fn add_columnar_menu(
}; };
} }
if let Value::Record { cols, vals, span } = &menu.style { let span = menu.style.span();
if let Value::Record { val, .. } = &menu.style {
add_style!( add_style!(
"text", "text",
cols, val,
vals,
span, span,
config, config,
columnar_menu, columnar_menu,
@ -218,8 +221,7 @@ pub(crate) fn add_columnar_menu(
); );
add_style!( add_style!(
"selected_text", "selected_text",
cols, val,
vals,
span, span,
config, config,
columnar_menu, columnar_menu,
@ -227,8 +229,7 @@ pub(crate) fn add_columnar_menu(
); );
add_style!( add_style!(
"description_text", "description_text",
cols, val,
vals,
span, span,
config, config,
columnar_menu, columnar_menu,
@ -242,18 +243,15 @@ pub(crate) fn add_columnar_menu(
let only_buffer_difference = menu.only_buffer_difference.as_bool()?; let only_buffer_difference = menu.only_buffer_difference.as_bool()?;
columnar_menu = columnar_menu.with_only_buffer_difference(only_buffer_difference); columnar_menu = columnar_menu.with_only_buffer_difference(only_buffer_difference);
let span = menu.source.span();
match &menu.source { match &menu.source {
Value::Nothing { .. } => { Value::Nothing { .. } => {
Ok(line_editor.with_menu(ReedlineMenu::EngineCompleter(Box::new(columnar_menu)))) Ok(line_editor.with_menu(ReedlineMenu::EngineCompleter(Box::new(columnar_menu))))
} }
Value::Closure { Value::Closure { val, captures, .. } => {
val,
captures,
span,
} => {
let menu_completer = NuMenuCompleter::new( let menu_completer = NuMenuCompleter::new(
*val, *val,
*span, span,
stack.captures_to_stack(captures), stack.captures_to_stack(captures),
engine_state, engine_state,
only_buffer_difference, only_buffer_difference,
@ -266,7 +264,7 @@ pub(crate) fn add_columnar_menu(
_ => Err(ShellError::UnsupportedConfigValue( _ => Err(ShellError::UnsupportedConfigValue(
"block or omitted value".to_string(), "block or omitted value".to_string(),
menu.source.into_abbreviated_string(config), menu.source.into_abbreviated_string(config),
menu.source.span()?, span,
)), )),
} }
} }
@ -282,8 +280,9 @@ pub(crate) fn add_list_menu(
let name = menu.name.into_string("", config); let name = menu.name.into_string("", config);
let mut list_menu = ListMenu::default().with_name(&name); let mut list_menu = ListMenu::default().with_name(&name);
if let Value::Record { cols, vals, span } = &menu.menu_type { let span = menu.menu_type.span();
list_menu = match extract_value("page_size", cols, vals, *span) { if let Value::Record { val, .. } = &menu.menu_type {
list_menu = match extract_value("page_size", val, span) {
Ok(page_size) => { Ok(page_size) => {
let page_size = page_size.as_int()?; let page_size = page_size.as_int()?;
list_menu.with_page_size(page_size as usize) list_menu.with_page_size(page_size as usize)
@ -292,11 +291,11 @@ pub(crate) fn add_list_menu(
}; };
} }
if let Value::Record { cols, vals, span } = &menu.style { let span = menu.style.span();
if let Value::Record { val, .. } = &menu.style {
add_style!( add_style!(
"text", "text",
cols, val,
vals,
span, span,
config, config,
list_menu, list_menu,
@ -304,8 +303,7 @@ pub(crate) fn add_list_menu(
); );
add_style!( add_style!(
"selected_text", "selected_text",
cols, val,
vals,
span, span,
config, config,
list_menu, list_menu,
@ -313,8 +311,7 @@ pub(crate) fn add_list_menu(
); );
add_style!( add_style!(
"description_text", "description_text",
cols, val,
vals,
span, span,
config, config,
list_menu, list_menu,
@ -328,18 +325,15 @@ pub(crate) fn add_list_menu(
let only_buffer_difference = menu.only_buffer_difference.as_bool()?; let only_buffer_difference = menu.only_buffer_difference.as_bool()?;
list_menu = list_menu.with_only_buffer_difference(only_buffer_difference); list_menu = list_menu.with_only_buffer_difference(only_buffer_difference);
let span = menu.source.span();
match &menu.source { match &menu.source {
Value::Nothing { .. } => { Value::Nothing { .. } => {
Ok(line_editor.with_menu(ReedlineMenu::HistoryMenu(Box::new(list_menu)))) Ok(line_editor.with_menu(ReedlineMenu::HistoryMenu(Box::new(list_menu))))
} }
Value::Closure { Value::Closure { val, captures, .. } => {
val,
captures,
span,
} => {
let menu_completer = NuMenuCompleter::new( let menu_completer = NuMenuCompleter::new(
*val, *val,
*span, span,
stack.captures_to_stack(captures), stack.captures_to_stack(captures),
engine_state, engine_state,
only_buffer_difference, only_buffer_difference,
@ -352,7 +346,7 @@ pub(crate) fn add_list_menu(
_ => Err(ShellError::UnsupportedConfigValue( _ => Err(ShellError::UnsupportedConfigValue(
"block or omitted value".to_string(), "block or omitted value".to_string(),
menu.source.into_abbreviated_string(config), menu.source.into_abbreviated_string(config),
menu.source.span()?, menu.source.span(),
)), )),
} }
} }
@ -368,8 +362,9 @@ pub(crate) fn add_description_menu(
let name = menu.name.into_string("", config); let name = menu.name.into_string("", config);
let mut description_menu = DescriptionMenu::default().with_name(&name); let mut description_menu = DescriptionMenu::default().with_name(&name);
if let Value::Record { cols, vals, span } = &menu.menu_type { let span = menu.menu_type.span();
description_menu = match extract_value("columns", cols, vals, *span) { if let Value::Record { val, .. } = &menu.menu_type {
description_menu = match extract_value("columns", val, span) {
Ok(columns) => { Ok(columns) => {
let columns = columns.as_int()?; let columns = columns.as_int()?;
description_menu.with_columns(columns as u16) description_menu.with_columns(columns as u16)
@ -377,7 +372,7 @@ pub(crate) fn add_description_menu(
Err(_) => description_menu, Err(_) => description_menu,
}; };
description_menu = match extract_value("col_width", cols, vals, *span) { description_menu = match extract_value("col_width", val, span) {
Ok(col_width) => { Ok(col_width) => {
let col_width = col_width.as_int()?; let col_width = col_width.as_int()?;
description_menu.with_column_width(Some(col_width as usize)) description_menu.with_column_width(Some(col_width as usize))
@ -385,7 +380,7 @@ pub(crate) fn add_description_menu(
Err(_) => description_menu.with_column_width(None), Err(_) => description_menu.with_column_width(None),
}; };
description_menu = match extract_value("col_padding", cols, vals, *span) { description_menu = match extract_value("col_padding", val, span) {
Ok(col_padding) => { Ok(col_padding) => {
let col_padding = col_padding.as_int()?; let col_padding = col_padding.as_int()?;
description_menu.with_column_padding(col_padding as usize) description_menu.with_column_padding(col_padding as usize)
@ -393,7 +388,7 @@ pub(crate) fn add_description_menu(
Err(_) => description_menu, Err(_) => description_menu,
}; };
description_menu = match extract_value("selection_rows", cols, vals, *span) { description_menu = match extract_value("selection_rows", val, span) {
Ok(selection_rows) => { Ok(selection_rows) => {
let selection_rows = selection_rows.as_int()?; let selection_rows = selection_rows.as_int()?;
description_menu.with_selection_rows(selection_rows as u16) description_menu.with_selection_rows(selection_rows as u16)
@ -401,7 +396,7 @@ pub(crate) fn add_description_menu(
Err(_) => description_menu, Err(_) => description_menu,
}; };
description_menu = match extract_value("description_rows", cols, vals, *span) { description_menu = match extract_value("description_rows", val, span) {
Ok(description_rows) => { Ok(description_rows) => {
let description_rows = description_rows.as_int()?; let description_rows = description_rows.as_int()?;
description_menu.with_description_rows(description_rows as usize) description_menu.with_description_rows(description_rows as usize)
@ -410,11 +405,11 @@ pub(crate) fn add_description_menu(
}; };
} }
if let Value::Record { cols, vals, span } = &menu.style { let span = menu.style.span();
if let Value::Record { val, .. } = &menu.style {
add_style!( add_style!(
"text", "text",
cols, val,
vals,
span, span,
config, config,
description_menu, description_menu,
@ -422,8 +417,7 @@ pub(crate) fn add_description_menu(
); );
add_style!( add_style!(
"selected_text", "selected_text",
cols, val,
vals,
span, span,
config, config,
description_menu, description_menu,
@ -431,8 +425,7 @@ pub(crate) fn add_description_menu(
); );
add_style!( add_style!(
"description_text", "description_text",
cols, val,
vals,
span, span,
config, config,
description_menu, description_menu,
@ -446,6 +439,7 @@ pub(crate) fn add_description_menu(
let only_buffer_difference = menu.only_buffer_difference.as_bool()?; let only_buffer_difference = menu.only_buffer_difference.as_bool()?;
description_menu = description_menu.with_only_buffer_difference(only_buffer_difference); description_menu = description_menu.with_only_buffer_difference(only_buffer_difference);
let span = menu.source.span();
match &menu.source { match &menu.source {
Value::Nothing { .. } => { Value::Nothing { .. } => {
let completer = Box::new(NuHelpCompleter::new(engine_state)); let completer = Box::new(NuHelpCompleter::new(engine_state));
@ -454,14 +448,10 @@ pub(crate) fn add_description_menu(
completer, completer,
})) }))
} }
Value::Closure { Value::Closure { val, captures, .. } => {
val,
captures,
span,
} => {
let menu_completer = NuMenuCompleter::new( let menu_completer = NuMenuCompleter::new(
*val, *val,
*span, span,
stack.captures_to_stack(captures), stack.captures_to_stack(captures),
engine_state, engine_state,
only_buffer_difference, only_buffer_difference,
@ -474,7 +464,7 @@ pub(crate) fn add_description_menu(
_ => Err(ShellError::UnsupportedConfigValue( _ => Err(ShellError::UnsupportedConfigValue(
"closure or omitted value".to_string(), "closure or omitted value".to_string(),
menu.source.into_abbreviated_string(config), menu.source.into_abbreviated_string(config),
menu.source.span()?, menu.source.span(),
)), )),
} }
} }
@ -486,6 +476,7 @@ fn add_menu_keybindings(keybindings: &mut Keybindings) {
KeyCode::Tab, KeyCode::Tab,
ReedlineEvent::UntilFound(vec![ ReedlineEvent::UntilFound(vec![
ReedlineEvent::Menu("completion_menu".to_string()), ReedlineEvent::Menu("completion_menu".to_string()),
ReedlineEvent::MenuNext,
ReedlineEvent::Edit(vec![EditCommand::Complete]), ReedlineEvent::Edit(vec![EditCommand::Complete]),
]), ]),
); );
@ -583,15 +574,16 @@ fn add_keybinding(
insert_keybindings: &mut Keybindings, insert_keybindings: &mut Keybindings,
normal_keybindings: &mut Keybindings, normal_keybindings: &mut Keybindings,
) -> Result<(), ShellError> { ) -> Result<(), ShellError> {
let span = mode.span();
match &mode { match &mode {
Value::String { val, span } => match val.as_str() { Value::String { val, .. } => match val.as_str() {
"emacs" => add_parsed_keybinding(emacs_keybindings, keybinding, config), "emacs" => add_parsed_keybinding(emacs_keybindings, keybinding, config),
"vi_insert" => add_parsed_keybinding(insert_keybindings, keybinding, config), "vi_insert" => add_parsed_keybinding(insert_keybindings, keybinding, config),
"vi_normal" => add_parsed_keybinding(normal_keybindings, keybinding, config), "vi_normal" => add_parsed_keybinding(normal_keybindings, keybinding, config),
m => Err(ShellError::UnsupportedConfigValue( m => Err(ShellError::UnsupportedConfigValue(
"emacs, vi_insert or vi_normal".to_string(), "emacs, vi_insert or vi_normal".to_string(),
m.to_string(), m.to_string(),
*span, span,
)), )),
}, },
Value::List { vals, .. } => { Value::List { vals, .. } => {
@ -611,7 +603,7 @@ fn add_keybinding(
v => Err(ShellError::UnsupportedConfigValue( v => Err(ShellError::UnsupportedConfigValue(
"string or list of strings".to_string(), "string or list of strings".to_string(),
v.into_abbreviated_string(config), v.into_abbreviated_string(config),
v.span()?, v.span(),
)), )),
} }
} }
@ -641,7 +633,7 @@ fn add_parsed_keybinding(
return Err(ShellError::UnsupportedConfigValue( return Err(ShellError::UnsupportedConfigValue(
"CONTROL, SHIFT, ALT or NONE".to_string(), "CONTROL, SHIFT, ALT or NONE".to_string(),
keybinding.modifier.into_abbreviated_string(config), keybinding.modifier.into_abbreviated_string(config),
keybinding.modifier.span()?, keybinding.modifier.span(),
)) ))
} }
}; };
@ -665,7 +657,7 @@ fn add_parsed_keybinding(
return Err(ShellError::UnsupportedConfigValue( return Err(ShellError::UnsupportedConfigValue(
"char_<CHAR: unicode codepoint>".to_string(), "char_<CHAR: unicode codepoint>".to_string(),
c.to_string(), c.to_string(),
keybinding.keycode.span()?, keybinding.keycode.span(),
)); ));
}; };
@ -692,7 +684,7 @@ fn add_parsed_keybinding(
.ok_or(ShellError::UnsupportedConfigValue( .ok_or(ShellError::UnsupportedConfigValue(
"(f1|f2|...|f20)".to_string(), "(f1|f2|...|f20)".to_string(),
format!("unknown function key: {c}"), format!("unknown function key: {c}"),
keybinding.keycode.span()?, keybinding.keycode.span(),
))?; ))?;
KeyCode::F(fn_num) KeyCode::F(fn_num)
} }
@ -702,7 +694,7 @@ fn add_parsed_keybinding(
return Err(ShellError::UnsupportedConfigValue( return Err(ShellError::UnsupportedConfigValue(
"crossterm KeyCode".to_string(), "crossterm KeyCode".to_string(),
keybinding.keycode.into_abbreviated_string(config), keybinding.keycode.into_abbreviated_string(config),
keybinding.keycode.span()?, keybinding.keycode.span(),
)) ))
} }
}; };
@ -722,68 +714,61 @@ enum EventType<'config> {
} }
impl<'config> EventType<'config> { impl<'config> EventType<'config> {
fn try_from_columns( fn try_from_record(record: &'config Record, span: Span) -> Result<Self, ShellError> {
cols: &'config [String], extract_value("send", record, span)
vals: &'config [Value],
span: Span,
) -> Result<Self, ShellError> {
extract_value("send", cols, vals, span)
.map(Self::Send) .map(Self::Send)
.or_else(|_| extract_value("edit", cols, vals, span).map(Self::Edit)) .or_else(|_| extract_value("edit", record, span).map(Self::Edit))
.or_else(|_| extract_value("until", cols, vals, span).map(Self::Until)) .or_else(|_| extract_value("until", record, span).map(Self::Until))
.map_err(|_| ShellError::MissingConfigValue("send, edit or until".to_string(), span)) .map_err(|_| ShellError::MissingConfigValue("send, edit or until".to_string(), span))
} }
} }
fn parse_event(value: &Value, config: &Config) -> Result<Option<ReedlineEvent>, ShellError> { fn parse_event(value: &Value, config: &Config) -> Result<Option<ReedlineEvent>, ShellError> {
let span = value.span();
match value { match value {
Value::Record { cols, vals, span } => { Value::Record { val: record, .. } => match EventType::try_from_record(record, span)? {
match EventType::try_from_columns(cols, vals, *span)? { EventType::Send(value) => event_from_record(
EventType::Send(value) => event_from_record( value.into_string("", config).to_lowercase().as_str(),
record,
config,
span,
)
.map(Some),
EventType::Edit(value) => {
let edit = edit_from_record(
value.into_string("", config).to_lowercase().as_str(), value.into_string("", config).to_lowercase().as_str(),
cols, record,
vals,
config, config,
*span, span,
) )?;
.map(Some), Ok(Some(ReedlineEvent::Edit(vec![edit])))
EventType::Edit(value) => {
let edit = edit_from_record(
value.into_string("", config).to_lowercase().as_str(),
cols,
vals,
config,
*span,
)?;
Ok(Some(ReedlineEvent::Edit(vec![edit])))
}
EventType::Until(value) => match value {
Value::List { vals, .. } => {
let events = vals
.iter()
.map(|value| match parse_event(value, config) {
Ok(inner) => match inner {
None => Err(ShellError::UnsupportedConfigValue(
"List containing valid events".to_string(),
"Nothing value (null)".to_string(),
value.span()?,
)),
Some(event) => Ok(event),
},
Err(e) => Err(e),
})
.collect::<Result<Vec<ReedlineEvent>, ShellError>>()?;
Ok(Some(ReedlineEvent::UntilFound(events)))
}
v => Err(ShellError::UnsupportedConfigValue(
"list of events".to_string(),
v.into_abbreviated_string(config),
v.span()?,
)),
},
} }
} EventType::Until(value) => match value {
Value::List { vals, .. } => {
let events = vals
.iter()
.map(|value| match parse_event(value, config) {
Ok(inner) => match inner {
None => Err(ShellError::UnsupportedConfigValue(
"List containing valid events".to_string(),
"Nothing value (null)".to_string(),
value.span(),
)),
Some(event) => Ok(event),
},
Err(e) => Err(e),
})
.collect::<Result<Vec<ReedlineEvent>, ShellError>>()?;
Ok(Some(ReedlineEvent::UntilFound(events)))
}
v => Err(ShellError::UnsupportedConfigValue(
"list of events".to_string(),
v.into_abbreviated_string(config),
v.span(),
)),
},
},
Value::List { vals, .. } => { Value::List { vals, .. } => {
let events = vals let events = vals
.iter() .iter()
@ -792,7 +777,7 @@ fn parse_event(value: &Value, config: &Config) -> Result<Option<ReedlineEvent>,
None => Err(ShellError::UnsupportedConfigValue( None => Err(ShellError::UnsupportedConfigValue(
"List containing valid events".to_string(), "List containing valid events".to_string(),
"Nothing value (null)".to_string(), "Nothing value (null)".to_string(),
value.span()?, value.span(),
)), )),
Some(event) => Ok(event), Some(event) => Ok(event),
}, },
@ -806,15 +791,14 @@ fn parse_event(value: &Value, config: &Config) -> Result<Option<ReedlineEvent>,
v => Err(ShellError::UnsupportedConfigValue( v => Err(ShellError::UnsupportedConfigValue(
"record or list of records, null to unbind key".to_string(), "record or list of records, null to unbind key".to_string(),
v.into_abbreviated_string(config), v.into_abbreviated_string(config),
v.span()?, v.span(),
)), )),
} }
} }
fn event_from_record( fn event_from_record(
name: &str, name: &str,
cols: &[String], record: &Record,
vals: &[Value],
config: &Config, config: &Config,
span: Span, span: Span,
) -> Result<ReedlineEvent, ShellError> { ) -> Result<ReedlineEvent, ShellError> {
@ -848,11 +832,11 @@ fn event_from_record(
"menupageprevious" => ReedlineEvent::MenuPagePrevious, "menupageprevious" => ReedlineEvent::MenuPagePrevious,
"openeditor" => ReedlineEvent::OpenEditor, "openeditor" => ReedlineEvent::OpenEditor,
"menu" => { "menu" => {
let menu = extract_value("name", cols, vals, span)?; let menu = extract_value("name", record, span)?;
ReedlineEvent::Menu(menu.into_string("", config)) ReedlineEvent::Menu(menu.into_string("", config))
} }
"executehostcommand" => { "executehostcommand" => {
let cmd = extract_value("cmd", cols, vals, span)?; let cmd = extract_value("cmd", record, span)?;
ReedlineEvent::ExecuteHostCommand(cmd.into_string("", config)) ReedlineEvent::ExecuteHostCommand(cmd.into_string("", config))
} }
v => { v => {
@ -869,8 +853,7 @@ fn event_from_record(
fn edit_from_record( fn edit_from_record(
name: &str, name: &str,
cols: &[String], record: &Record,
vals: &[Value],
config: &Config, config: &Config,
span: Span, span: Span,
) -> Result<EditCommand, ShellError> { ) -> Result<EditCommand, ShellError> {
@ -889,16 +872,16 @@ fn edit_from_record(
"movewordrightstart" => EditCommand::MoveWordRightStart, "movewordrightstart" => EditCommand::MoveWordRightStart,
"movebigwordrightstart" => EditCommand::MoveBigWordRightStart, "movebigwordrightstart" => EditCommand::MoveBigWordRightStart,
"movetoposition" => { "movetoposition" => {
let value = extract_value("value", cols, vals, span)?; let value = extract_value("value", record, span)?;
EditCommand::MoveToPosition(value.as_int()? as usize) EditCommand::MoveToPosition(value.as_int()? as usize)
} }
"insertchar" => { "insertchar" => {
let value = extract_value("value", cols, vals, span)?; let value = extract_value("value", record, span)?;
let char = extract_char(value, config)?; let char = extract_char(value, config)?;
EditCommand::InsertChar(char) EditCommand::InsertChar(char)
} }
"insertstring" => { "insertstring" => {
let value = extract_value("value", cols, vals, span)?; let value = extract_value("value", record, span)?;
EditCommand::InsertString(value.into_string("", config)) EditCommand::InsertString(value.into_string("", config))
} }
"insertnewline" => EditCommand::InsertNewline, "insertnewline" => EditCommand::InsertNewline,
@ -930,42 +913,42 @@ fn edit_from_record(
"undo" => EditCommand::Undo, "undo" => EditCommand::Undo,
"redo" => EditCommand::Redo, "redo" => EditCommand::Redo,
"cutrightuntil" => { "cutrightuntil" => {
let value = extract_value("value", cols, vals, span)?; let value = extract_value("value", record, span)?;
let char = extract_char(value, config)?; let char = extract_char(value, config)?;
EditCommand::CutRightUntil(char) EditCommand::CutRightUntil(char)
} }
"cutrightbefore" => { "cutrightbefore" => {
let value = extract_value("value", cols, vals, span)?; let value = extract_value("value", record, span)?;
let char = extract_char(value, config)?; let char = extract_char(value, config)?;
EditCommand::CutRightBefore(char) EditCommand::CutRightBefore(char)
} }
"moverightuntil" => { "moverightuntil" => {
let value = extract_value("value", cols, vals, span)?; let value = extract_value("value", record, span)?;
let char = extract_char(value, config)?; let char = extract_char(value, config)?;
EditCommand::MoveRightUntil(char) EditCommand::MoveRightUntil(char)
} }
"moverightbefore" => { "moverightbefore" => {
let value = extract_value("value", cols, vals, span)?; let value = extract_value("value", record, span)?;
let char = extract_char(value, config)?; let char = extract_char(value, config)?;
EditCommand::MoveRightBefore(char) EditCommand::MoveRightBefore(char)
} }
"cutleftuntil" => { "cutleftuntil" => {
let value = extract_value("value", cols, vals, span)?; let value = extract_value("value", record, span)?;
let char = extract_char(value, config)?; let char = extract_char(value, config)?;
EditCommand::CutLeftUntil(char) EditCommand::CutLeftUntil(char)
} }
"cutleftbefore" => { "cutleftbefore" => {
let value = extract_value("value", cols, vals, span)?; let value = extract_value("value", record, span)?;
let char = extract_char(value, config)?; let char = extract_char(value, config)?;
EditCommand::CutLeftBefore(char) EditCommand::CutLeftBefore(char)
} }
"moveleftuntil" => { "moveleftuntil" => {
let value = extract_value("value", cols, vals, span)?; let value = extract_value("value", record, span)?;
let char = extract_char(value, config)?; let char = extract_char(value, config)?;
EditCommand::MoveLeftUntil(char) EditCommand::MoveLeftUntil(char)
} }
"moveleftbefore" => { "moveleftbefore" => {
let value = extract_value("value", cols, vals, span)?; let value = extract_value("value", record, span)?;
let char = extract_char(value, config)?; let char = extract_char(value, config)?;
EditCommand::MoveLeftBefore(char) EditCommand::MoveLeftBefore(char)
} }
@ -983,7 +966,7 @@ fn edit_from_record(
} }
fn extract_char(value: &Value, config: &Config) -> Result<char, ShellError> { fn extract_char(value: &Value, config: &Config) -> Result<char, ShellError> {
let span = value.span()?; let span = value.span();
value value
.into_string("", config) .into_string("", config)
.chars() .chars()
@ -999,16 +982,13 @@ mod test {
fn test_send_event() { fn test_send_event() {
let cols = vec!["send".to_string()]; let cols = vec!["send".to_string()];
let vals = vec![Value::test_string("Enter")]; let vals = vec![Value::test_string("Enter")];
let event = Record { vals, cols };
let span = Span::test_data(); let span = Span::test_data();
let b = EventType::try_from_columns(&cols, &vals, span).unwrap(); let b = EventType::try_from_record(&event, span).unwrap();
assert!(matches!(b, EventType::Send(_))); assert!(matches!(b, EventType::Send(_)));
let event = Value::Record { let event = Value::test_record(event);
vals,
cols,
span: Span::test_data(),
};
let config = Config::default(); let config = Config::default();
let parsed_event = parse_event(&event, &config).unwrap(); let parsed_event = parse_event(&event, &config).unwrap();
@ -1019,16 +999,13 @@ mod test {
fn test_edit_event() { fn test_edit_event() {
let cols = vec!["edit".to_string()]; let cols = vec!["edit".to_string()];
let vals = vec![Value::test_string("Clear")]; let vals = vec![Value::test_string("Clear")];
let event = Record { vals, cols };
let span = Span::test_data(); let span = Span::test_data();
let b = EventType::try_from_columns(&cols, &vals, span).unwrap(); let b = EventType::try_from_record(&event, span).unwrap();
assert!(matches!(b, EventType::Edit(_))); assert!(matches!(b, EventType::Edit(_)));
let event = Value::Record { let event = Value::test_record(event);
vals,
cols,
span: Span::test_data(),
};
let config = Config::default(); let config = Config::default();
let parsed_event = parse_event(&event, &config).unwrap(); let parsed_event = parse_event(&event, &config).unwrap();
@ -1045,16 +1022,13 @@ mod test {
Value::test_string("Menu"), Value::test_string("Menu"),
Value::test_string("history_menu"), Value::test_string("history_menu"),
]; ];
let event = Record { vals, cols };
let span = Span::test_data(); let span = Span::test_data();
let b = EventType::try_from_columns(&cols, &vals, span).unwrap(); let b = EventType::try_from_record(&event, span).unwrap();
assert!(matches!(b, EventType::Send(_))); assert!(matches!(b, EventType::Send(_)));
let event = Value::Record { let event = Value::test_record(event);
vals,
cols,
span: Span::test_data(),
};
let config = Config::default(); let config = Config::default();
let parsed_event = parse_event(&event, &config).unwrap(); let parsed_event = parse_event(&event, &config).unwrap();
@ -1073,38 +1047,27 @@ mod test {
Value::test_string("history_menu"), Value::test_string("history_menu"),
]; ];
let menu_event = Value::Record { let menu_event = Value::test_record(Record { cols, vals });
cols,
vals,
span: Span::test_data(),
};
// Enter event // Enter event
let cols = vec!["send".to_string()]; let cols = vec!["send".to_string()];
let vals = vec![Value::test_string("Enter")]; let vals = vec![Value::test_string("Enter")];
let enter_event = Value::Record { let enter_event = Value::test_record(Record { cols, vals });
cols,
vals,
span: Span::test_data(),
};
// Until event // Until event
let cols = vec!["until".to_string()]; let cols = vec!["until".to_string()];
let vals = vec![Value::List { let vals = vec![Value::list(
vals: vec![menu_event, enter_event], vec![menu_event, enter_event],
span: Span::test_data(), Span::test_data(),
}]; )];
let event = Record { cols, vals };
let span = Span::test_data(); let span = Span::test_data();
let b = EventType::try_from_columns(&cols, &vals, span).unwrap(); let b = EventType::try_from_record(&event, span).unwrap();
assert!(matches!(b, EventType::Until(_))); assert!(matches!(b, EventType::Until(_)));
let event = Value::Record { let event = Value::test_record(event);
cols,
vals,
span: Span::test_data(),
};
let config = Config::default(); let config = Config::default();
let parsed_event = parse_event(&event, &config).unwrap(); let parsed_event = parse_event(&event, &config).unwrap();
@ -1126,27 +1089,16 @@ mod test {
Value::test_string("history_menu"), Value::test_string("history_menu"),
]; ];
let menu_event = Value::Record { let menu_event = Value::test_record(Record { cols, vals });
cols,
vals,
span: Span::test_data(),
};
// Enter event // Enter event
let cols = vec!["send".to_string()]; let cols = vec!["send".to_string()];
let vals = vec![Value::test_string("Enter")]; let vals = vec![Value::test_string("Enter")];
let enter_event = Value::Record { let enter_event = Value::test_record(Record { cols, vals });
cols,
vals,
span: Span::test_data(),
};
// Multiple event // Multiple event
let event = Value::List { let event = Value::list(vec![menu_event, enter_event], Span::test_data());
vals: vec![menu_event, enter_event],
span: Span::test_data(),
};
let config = Config::default(); let config = Config::default();
let parsed_event = parse_event(&event, &config).unwrap(); let parsed_event = parse_event(&event, &config).unwrap();
@ -1163,9 +1115,10 @@ mod test {
fn test_error() { fn test_error() {
let cols = vec!["not_exist".to_string()]; let cols = vec!["not_exist".to_string()];
let vals = vec![Value::test_string("Enter")]; let vals = vec![Value::test_string("Enter")];
let event = Record { cols, vals };
let span = Span::test_data(); let span = Span::test_data();
let b = EventType::try_from_columns(&cols, &vals, span); let b = EventType::try_from_record(&event, span);
assert!(matches!(b, Err(ShellError::MissingConfigValue(_, _)))); assert!(matches!(b, Err(ShellError::MissingConfigValue(_, _))));
} }
} }

View File

@ -6,19 +6,19 @@ use crate::{
NuHighlighter, NuValidator, NushellPrompt, NuHighlighter, NuValidator, NushellPrompt,
}; };
use crossterm::cursor::SetCursorStyle; use crossterm::cursor::SetCursorStyle;
use is_terminal::IsTerminal;
use log::{trace, warn}; use log::{trace, warn};
use miette::{ErrReport, IntoDiagnostic, Result}; use miette::{ErrReport, IntoDiagnostic, Result};
use nu_cmd_base::util::get_guaranteed_cwd; 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_color_config::StyleComputer;
use nu_command::hook::eval_hook;
use nu_engine::convert_env_values; use nu_engine::convert_env_values;
use nu_parser::{lex, parse, trim_quotes_str}; use nu_parser::{lex, parse, trim_quotes_str};
use nu_protocol::{ use nu_protocol::{
config::NuCursorShape, config::NuCursorShape,
engine::{EngineState, Stack, StateWorkingSet}, engine::{EngineState, Stack, StateWorkingSet},
eval_const::create_nu_constant,
report_error, report_error_new, HistoryFileFormat, PipelineData, ShellError, Span, Spanned, report_error, report_error_new, HistoryFileFormat, PipelineData, ShellError, Span, Spanned,
Value, Value, NU_VARIABLE_ID,
}; };
use nu_utils::utils::perf; use nu_utils::utils::perf;
use reedline::{ use reedline::{
@ -26,7 +26,8 @@ use reedline::{
SqliteBackedHistory, Vi, SqliteBackedHistory, Vi,
}; };
use std::{ use std::{
io::{self, Write}, env::temp_dir,
io::{self, IsTerminal, Write},
path::Path, path::Path,
sync::atomic::Ordering, sync::atomic::Ordering,
time::Instant, time::Instant,
@ -51,7 +52,7 @@ pub fn evaluate_repl(
load_std_lib: Option<Spanned<String>>, load_std_lib: Option<Spanned<String>>,
entire_start_time: Instant, entire_start_time: Instant,
) -> Result<()> { ) -> Result<()> {
use nu_command::hook; use nu_cmd_base::hook;
use reedline::Signal; use reedline::Signal;
let use_color = engine_state.get_config().use_ansi_coloring; let use_color = engine_state.get_config().use_ansi_coloring;
@ -94,6 +95,7 @@ pub fn evaluate_repl(
let mut start_time = std::time::Instant::now(); let mut start_time = std::time::Instant::now();
let mut line_editor = Reedline::create(); 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 // 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); store_history_id_in_engine(engine_state, &line_editor);
@ -165,6 +167,10 @@ pub fn evaluate_repl(
engine_state.set_startup_time(entire_start_time.elapsed().as_nanos() as i64); engine_state.set_startup_time(entire_start_time.elapsed().as_nanos() as i64);
// Regenerate the $nu constant to contain the startup time and any other potential updates
let nu_const = create_nu_constant(engine_state, Span::unknown())?;
engine_state.set_variable_const_val(NU_VARIABLE_ID, nu_const);
if load_std_lib.is_none() && engine_state.get_config().show_banner { if load_std_lib.is_none() && engine_state.get_config().show_banner {
eval_source( eval_source(
engine_state, engine_state,
@ -176,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 { loop {
let loop_start_time = std::time::Instant::now(); let loop_start_time = std::time::Instant::now();
@ -231,13 +245,15 @@ pub fn evaluate_repl(
// Find the configured cursor shapes for each mode // Find the configured cursor shapes for each mode
let cursor_config = CursorConfig { let cursor_config = CursorConfig {
vi_insert: Some(map_nucursorshape_to_cursorshape( vi_insert: config
config.cursor_shape_vi_insert, .cursor_shape_vi_insert
)), .map(map_nucursorshape_to_cursorshape),
vi_normal: Some(map_nucursorshape_to_cursorshape( vi_normal: config
config.cursor_shape_vi_normal, .cursor_shape_vi_normal
)), .map(map_nucursorshape_to_cursorshape),
emacs: Some(map_nucursorshape_to_cursorshape(config.cursor_shape_emacs)), emacs: config
.cursor_shape_emacs
.map(map_nucursorshape_to_cursorshape),
}; };
perf( perf(
"get config/cursor config", "get config/cursor config",
@ -265,7 +281,11 @@ pub fn evaluate_repl(
.with_quick_completions(config.quick_completions) .with_quick_completions(config.quick_completions)
.with_partial_completions(config.partial_completions) .with_partial_completions(config.partial_completions)
.with_ansi_colors(config.use_ansi_coloring) .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( perf(
"reedline builder", "reedline builder",
start_time, start_time,
@ -312,23 +332,17 @@ pub fn evaluate_repl(
); );
start_time = std::time::Instant::now(); start_time = std::time::Instant::now();
let buffer_editor = if !config.buffer_editor.is_empty() { let buffer_editor = get_editor(engine_state, stack, Span::unknown());
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())
})
};
line_editor = if let Some(buffer_editor) = buffer_editor { line_editor = if let Ok((cmd, args)) = buffer_editor {
line_editor.with_buffer_editor(buffer_editor, "nu".into()) 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 { } else {
line_editor line_editor
}; };
@ -391,7 +405,7 @@ pub fn evaluate_repl(
// Right before we start our prompt and take input from the user, // Right before we start our prompt and take input from the user,
// fire the "pre_prompt" hook // fire the "pre_prompt" hook
if let Some(hook) = config.hooks.pre_prompt.clone() { if let Some(hook) = config.hooks.pre_prompt.clone() {
if let Err(err) = eval_hook(engine_state, stack, None, vec![], &hook) { if let Err(err) = eval_hook(engine_state, stack, None, vec![], &hook, "pre_prompt") {
report_error_new(engine_state, &err); report_error_new(engine_state, &err);
} }
} }
@ -466,7 +480,9 @@ pub fn evaluate_repl(
repl.buffer = s.to_string(); repl.buffer = s.to_string();
drop(repl); drop(repl);
if let Err(err) = eval_hook(engine_state, stack, None, vec![], &hook) { if let Err(err) =
eval_hook(engine_state, stack, None, vec![], &hook, "pre_execution")
{
report_error_new(engine_state, &err); report_error_new(engine_state, &err);
} }
} }
@ -500,7 +516,10 @@ pub fn evaluate_repl(
report_error( report_error(
&working_set, &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) let path = nu_path::canonicalize_with(path, &cwd)
@ -508,24 +527,12 @@ pub fn evaluate_repl(
(path.to_string_lossy().to_string(), tokens.0[0].span) (path.to_string_lossy().to_string(), tokens.0[0].span)
}; };
stack.add_env_var( stack.add_env_var("OLDPWD".into(), Value::string(cwd.clone(), Span::unknown()));
"OLDPWD".into(),
Value::String {
val: cwd.clone(),
span: Span::unknown(),
},
);
//FIXME: this only changes the current scope, but instead this environment variable //FIXME: this only changes the current scope, but instead this environment variable
//should probably be a block that loads the information from the state in the overlay //should probably be a block that loads the information from the state in the overlay
stack.add_env_var( stack.add_env_var("PWD".into(), Value::string(path.clone(), Span::unknown()));
"PWD".into(), let cwd = Value::string(cwd, span);
Value::String {
val: path.clone(),
span: Span::unknown(),
},
);
let cwd = Value::String { val: cwd, span };
let shells = stack.get_env_var(engine_state, "NUSHELL_SHELLS"); let shells = stack.get_env_var(engine_state, "NUSHELL_SHELLS");
let mut shells = if let Some(v) = shells { let mut shells = if let Some(v) = shells {
@ -550,15 +557,12 @@ pub fn evaluate_repl(
0 0
}; };
shells[current_shell] = Value::String { val: path, span }; shells[current_shell] = Value::string(path, span);
stack.add_env_var("NUSHELL_SHELLS".into(), Value::List { vals: shells, span }); stack.add_env_var("NUSHELL_SHELLS".into(), Value::list(shells, span));
stack.add_env_var( stack.add_env_var(
"NUSHELL_LAST_SHELL".into(), "NUSHELL_LAST_SHELL".into(),
Value::Int { Value::int(last_shell as i64, span),
val: last_shell as i64,
span,
},
); );
} else if !s.trim().is_empty() { } else if !s.trim().is_empty() {
trace!("eval source: {}", s); trace!("eval source: {}", s);
@ -601,10 +605,7 @@ pub fn evaluate_repl(
stack.add_env_var( stack.add_env_var(
"CMD_DURATION_MS".into(), "CMD_DURATION_MS".into(),
Value::String { Value::string(format!("{}", cmd_duration.as_millis()), Span::unknown()),
val: format!("{}", cmd_duration.as_millis()),
span: Span::unknown(),
},
); );
if history_supports_meta && !s.is_empty() && line_editor.has_last_command_context() if history_supports_meta && !s.is_empty() && line_editor.has_last_command_context()
@ -740,9 +741,14 @@ fn update_line_editor_history(
) )
.into_diagnostic()?, .into_diagnostic()?,
), ),
HistoryFileFormat::Sqlite => { HistoryFileFormat::Sqlite => Box::new(
Box::new(SqliteBackedHistory::with_file(history_path.to_path_buf()).into_diagnostic()?) SqliteBackedHistory::with_file(
} history_path.to_path_buf(),
history_session_id,
Some(chrono::Utc::now()),
)
.into_diagnostic()?,
),
}; };
let line_editor = line_editor let line_editor = line_editor
.with_history_session_id(history_session_id) .with_history_session_id(history_session_id)
@ -814,16 +820,29 @@ fn looks_like_path(orig: &str) -> bool {
|| orig.starts_with('~') || orig.starts_with('~')
|| orig.starts_with('/') || orig.starts_with('/')
|| orig.starts_with('\\') || orig.starts_with('\\')
|| orig.ends_with(std::path::MAIN_SEPARATOR)
} }
#[cfg(windows)]
#[test] #[test]
fn looks_like_path_windows_drive_path_works() { fn looks_like_path_windows_drive_path_works() {
let on_windows = cfg!(windows); assert!(looks_like_path("C:"));
assert_eq!(looks_like_path("C:"), on_windows); assert!(looks_like_path("D:\\"));
assert_eq!(looks_like_path("D:\\"), on_windows); assert!(looks_like_path("E:/"));
assert_eq!(looks_like_path("E:/"), on_windows); assert!(looks_like_path("F:\\some_dir"));
assert_eq!(looks_like_path("F:\\some_dir"), on_windows); assert!(looks_like_path("G:/some_dir"));
assert_eq!(looks_like_path("G:/some_dir"), on_windows); }
#[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] #[test]

View File

@ -144,7 +144,7 @@ impl Highlighter for NuHighlighter {
fn split_span_by_highlight_positions( fn split_span_by_highlight_positions(
line: &str, line: &str,
span: Span, span: Span,
highlight_positions: &Vec<usize>, highlight_positions: &[usize],
global_span_offset: usize, global_span_offset: usize,
) -> Vec<(Span, bool)> { ) -> Vec<(Span, bool)> {
let mut start = span.start; let mut start = span.start;

View File

@ -1,4 +1,4 @@
use nu_command::hook::eval_hook; use nu_cmd_base::hook::eval_hook;
use nu_engine::{eval_block, eval_block_with_early_return}; use nu_engine::{eval_block, eval_block_with_early_return};
use nu_parser::{escape_quote_string, lex, parse, unescape_unquote_string, Token, TokenContents}; use nu_parser::{escape_quote_string, lex, parse, unescape_unquote_string, Token, TokenContents};
use nu_protocol::engine::StateWorkingSet; use nu_protocol::engine::StateWorkingSet;
@ -185,10 +185,7 @@ fn gather_env_vars(
continue; continue;
} }
Value::String { Value::string(bytes, *span)
val: bytes,
span: *span,
}
} else { } else {
report_capture_error( report_capture_error(
engine_state, engine_state,
@ -257,7 +254,14 @@ pub fn eval_source(
{ {
result = print_if_stream(stream, stderr_stream, false, exit_code); result = print_if_stream(stream, stderr_stream, false, exit_code);
} else if let Some(hook) = config.hooks.display_output.clone() { } else if let Some(hook) = config.hooks.display_output.clone() {
match eval_hook(engine_state, stack, Some(pipeline_data), vec![], &hook) { match eval_hook(
engine_state,
stack,
Some(pipeline_data),
vec![],
&hook,
"display_output",
) {
Err(err) => { Err(err) => {
result = Err(err); result = Err(err);
} }

View File

@ -1,11 +1,16 @@
pub mod support; pub mod support;
use std::path::PathBuf;
use nu_cli::NuCompleter; use nu_cli::NuCompleter;
use nu_parser::parse; use nu_parser::parse;
use nu_protocol::engine::StateWorkingSet; use nu_protocol::engine::StateWorkingSet;
use reedline::{Completer, Suggestion}; use reedline::{Completer, Suggestion};
use rstest::{fixture, rstest}; 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] #[fixture]
fn completer() -> NuCompleter { fn completer() -> NuCompleter {
@ -201,6 +206,87 @@ fn file_completions() {
match_suggestions(expected_paths, suggestions); 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] #[test]
fn command_ls_with_filecompletion() { fn command_ls_with_filecompletion() {
let (_, _, engine, stack) = new_engine(); 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(), "`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) match_suggestions(expected_paths, suggestions)

View File

@ -4,7 +4,8 @@ use nu_engine::eval_block;
use nu_parser::parse; use nu_parser::parse;
use nu_protocol::{ use nu_protocol::{
engine::{EngineState, Stack, StateWorkingSet}, engine::{EngineState, Stack, StateWorkingSet},
PipelineData, ShellError, Span, Value, eval_const::create_nu_constant,
PipelineData, ShellError, Span, Value, NU_VARIABLE_ID,
}; };
use nu_test_support::fs; use nu_test_support::fs;
use reedline::Suggestion; use reedline::Suggestion;
@ -28,39 +29,41 @@ pub fn new_engine() -> (PathBuf, String, EngineState, Stack) {
// Create a new engine with default context // Create a new engine with default context
let mut engine_state = create_default_context(); let mut engine_state = create_default_context();
// Add $nu
let nu_const =
create_nu_constant(&engine_state, Span::test_data()).expect("Failed creating $nu");
engine_state.set_variable_const_val(NU_VARIABLE_ID, nu_const);
// New stack // New stack
let mut stack = Stack::new(); let mut stack = Stack::new();
// Add pwd as env var // Add pwd as env var
stack.add_env_var( stack.add_env_var(
"PWD".to_string(), "PWD".to_string(),
Value::String { Value::string(dir_str.clone(), nu_protocol::Span::new(0, dir_str.len())),
val: dir_str.clone(),
span: nu_protocol::Span::new(0, dir_str.len()),
},
); );
stack.add_env_var( stack.add_env_var(
"TEST".to_string(), "TEST".to_string(),
Value::String { Value::string(
val: "NUSHELL".to_string(), "NUSHELL".to_string(),
span: nu_protocol::Span::new(0, dir_str.len()), nu_protocol::Span::new(0, dir_str.len()),
}, ),
); );
#[cfg(windows)] #[cfg(windows)]
stack.add_env_var( stack.add_env_var(
"Path".to_string(), "Path".to_string(),
Value::String { Value::string(
val: "c:\\some\\path;c:\\some\\other\\path".to_string(), "c:\\some\\path;c:\\some\\other\\path".to_string(),
span: nu_protocol::Span::new(0, dir_str.len()), nu_protocol::Span::new(0, dir_str.len()),
}, ),
); );
#[cfg(not(windows))] #[cfg(not(windows))]
stack.add_env_var( stack.add_env_var(
"PATH".to_string(), "PATH".to_string(),
Value::String { Value::string(
val: "/some/path:/some/other/path".to_string(), "/some/path:/some/other/path".to_string(),
span: nu_protocol::Span::new(0, dir_str.len()), nu_protocol::Span::new(0, dir_str.len()),
}, ),
); );
// Merge environment into the permanent state // Merge environment into the permanent state
@ -89,17 +92,50 @@ pub fn new_quote_engine() -> (PathBuf, String, EngineState, Stack) {
// Add pwd as env var // Add pwd as env var
stack.add_env_var( stack.add_env_var(
"PWD".to_string(), "PWD".to_string(),
Value::String { Value::string(dir_str.clone(), nu_protocol::Span::new(0, dir_str.len())),
val: dir_str.clone(),
span: nu_protocol::Span::new(0, dir_str.len()),
},
); );
stack.add_env_var( stack.add_env_var(
"TEST".to_string(), "TEST".to_string(),
Value::String { Value::string(
val: "NUSHELL".to_string(), "NUSHELL".to_string(),
span: nu_protocol::Span::new(0, dir_str.len()), nu_protocol::Span::new(0, dir_str.len()),
}, ),
);
// Merge environment into the permanent state
let merge_result = engine_state.merge_env(&mut stack, &dir);
assert!(merge_result.is_ok());
(dir, dir_str, engine_state, stack)
}
pub fn new_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 // Merge environment into the permanent state
@ -162,12 +198,7 @@ pub fn merge_input(
engine_state, engine_state,
stack, stack,
&block, &block,
PipelineData::Value( PipelineData::Value(Value::nothing(Span::unknown(),), None),
Value::Nothing {
span: Span::unknown(),
},
None
),
false, false,
false false
) )

View File

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

View File

@ -6,7 +6,7 @@ pub fn merge_descriptors(values: &[Value]) -> Vec<String> {
let mut seen: IndexSet<String> = indexset! {}; let mut seen: IndexSet<String> = indexset! {};
for value in values { for value in values {
let data_descriptors = match value { let data_descriptors = match value {
Value::Record { cols, .. } => cols.to_owned(), Value::Record { val, .. } => val.cols.clone(),
_ => vec!["".to_string()], _ => vec!["".to_string()],
}; };
for desc in data_descriptors { for desc in data_descriptors {

View File

@ -1,5 +1,5 @@
use crate::util::get_guaranteed_cwd;
use miette::Result; use miette::Result;
use nu_cmd_base::util::get_guaranteed_cwd;
use nu_engine::{eval_block, eval_block_with_early_return}; use nu_engine::{eval_block, eval_block_with_early_return};
use nu_parser::parse; use nu_parser::parse;
use nu_protocol::ast::PathMember; use nu_protocol::ast::PathMember;
@ -14,12 +14,8 @@ pub fn eval_env_change_hook(
) -> Result<(), ShellError> { ) -> Result<(), ShellError> {
if let Some(hook) = env_change_hook { if let Some(hook) = env_change_hook {
match hook { match hook {
Value::Record { Value::Record { val, .. } => {
cols: env_names, for (env_name, hook_value) in &val {
vals: hook_values,
..
} => {
for (env_name, hook_value) in env_names.iter().zip(hook_values.iter()) {
let before = engine_state let before = engine_state
.previous_env_vars .previous_env_vars
.get(env_name) .get(env_name)
@ -37,6 +33,7 @@ pub fn eval_env_change_hook(
None, None,
vec![("$before".into(), before), ("$after".into(), after.clone())], vec![("$before".into(), before), ("$after".into(), after.clone())],
hook_value, hook_value,
"env_change",
)?; )?;
engine_state engine_state
@ -48,7 +45,7 @@ pub fn eval_env_change_hook(
x => { x => {
return Err(ShellError::TypeMismatch { return Err(ShellError::TypeMismatch {
err_message: "record for the 'env_change' hook".to_string(), err_message: "record for the 'env_change' hook".to_string(),
span: x.span()?, span: x.span(),
}); });
} }
} }
@ -63,8 +60,9 @@ pub fn eval_hook(
input: Option<PipelineData>, input: Option<PipelineData>,
arguments: Vec<(String, Value)>, arguments: Vec<(String, Value)>,
value: &Value, value: &Value,
hook_name: &str,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
let value_span = value.span()?; let value_span = value.span();
// Hooks can optionally be a record in this form: // Hooks can optionally be a record in this form:
// { // {
@ -86,8 +84,9 @@ pub fn eval_hook(
optional: false, optional: false,
}; };
let span = value.span();
match value { match value {
Value::String { val, span } => { Value::String { val, .. } => {
let (block, delta, vars) = { let (block, delta, vars) = {
let mut working_set = StateWorkingSet::new(engine_state); let mut working_set = StateWorkingSet::new(engine_state);
@ -96,22 +95,26 @@ pub fn eval_hook(
for (name, val) in arguments { for (name, val) in arguments {
let var_id = working_set.add_variable( let var_id = working_set.add_variable(
name.as_bytes().to_vec(), name.as_bytes().to_vec(),
val.span()?, val.span(),
Type::Any, Type::Any,
false, false,
); );
vars.push((var_id, val)); vars.push((var_id, val));
} }
let output = parse(&mut working_set, Some("hook"), val.as_bytes(), false); let output = parse(
&mut working_set,
Some(&format!("{hook_name} hook")),
val.as_bytes(),
false,
);
if let Some(err) = working_set.parse_errors.first() { if let Some(err) = working_set.parse_errors.first() {
report_error(&working_set, err); report_error(&working_set, err);
return Err(ShellError::UnsupportedConfigValue( return Err(ShellError::UnsupportedConfigValue(
"valid source code".into(), "valid source code".into(),
"source code with syntax errors".into(), "source code with syntax errors".into(),
*span, span,
)); ));
} }
@ -148,68 +151,67 @@ pub fn eval_hook(
} }
Value::List { vals, .. } => { Value::List { vals, .. } => {
for val in vals { for val in vals {
eval_hook(engine_state, stack, None, arguments.clone(), val)?; eval_hook(
engine_state,
stack,
None,
arguments.clone(),
val,
&format!("{hook_name} list, recursive"),
)?;
} }
} }
Value::Record { .. } => { Value::Record { .. } => {
let do_run_hook = let do_run_hook = if let Ok(condition) =
if let Ok(condition) = value.clone().follow_cell_path(&[condition_path], false) { value.clone().follow_cell_path(&[condition_path], false)
match condition { {
Value::Block { let other_span = condition.span();
val: block_id, match condition {
span: block_span, Value::Block { val: block_id, .. } | Value::Closure { val: block_id, .. } => {
.. match run_hook_block(
} engine_state,
| Value::Closure { stack,
val: block_id, block_id,
span: block_span, None,
.. arguments.clone(),
} => { other_span,
match run_hook_block( ) {
engine_state, Ok(pipeline_data) => {
stack, if let PipelineData::Value(Value::Bool { val, .. }, ..) =
block_id, pipeline_data
None, {
arguments.clone(), val
block_span, } else {
) { return Err(ShellError::UnsupportedConfigValue(
Ok(pipeline_data) => { "boolean output".to_string(),
if let PipelineData::Value(Value::Bool { val, .. }, ..) = "other PipelineData variant".to_string(),
pipeline_data other_span,
{ ));
val
} else {
return Err(ShellError::UnsupportedConfigValue(
"boolean output".to_string(),
"other PipelineData variant".to_string(),
block_span,
));
}
}
Err(err) => {
return Err(err);
} }
} }
} Err(err) => {
other => { return Err(err);
return Err(ShellError::UnsupportedConfigValue( }
"block".to_string(),
format!("{}", other.get_type()),
other.span()?,
));
} }
} }
} else { other => {
// always run the hook return Err(ShellError::UnsupportedConfigValue(
true "block".to_string(),
}; format!("{}", other.get_type()),
other_span,
));
}
}
} else {
// always run the hook
true
};
if do_run_hook { if do_run_hook {
match value.clone().follow_cell_path(&[code_path], false)? { let follow = value.clone().follow_cell_path(&[code_path], false)?;
Value::String { let source_span = follow.span();
val, match follow {
span: source_span, Value::String { val, .. } => {
} => {
let (block, delta, vars) = { let (block, delta, vars) = {
let mut working_set = StateWorkingSet::new(engine_state); let mut working_set = StateWorkingSet::new(engine_state);
@ -218,16 +220,19 @@ pub fn eval_hook(
for (name, val) in arguments { for (name, val) in arguments {
let var_id = working_set.add_variable( let var_id = working_set.add_variable(
name.as_bytes().to_vec(), name.as_bytes().to_vec(),
val.span()?, val.span(),
Type::Any, Type::Any,
false, false,
); );
vars.push((var_id, val)); vars.push((var_id, val));
} }
let output = let output = parse(
parse(&mut working_set, Some("hook"), val.as_bytes(), false); &mut working_set,
Some(&format!("{hook_name} hook")),
val.as_bytes(),
false,
);
if let Some(err) = working_set.parse_errors.first() { if let Some(err) = working_set.parse_errors.first() {
report_error(&working_set, err); report_error(&working_set, err);
@ -265,77 +270,47 @@ pub fn eval_hook(
stack.remove_var(*var_id); stack.remove_var(*var_id);
} }
} }
Value::Block { Value::Block { val: block_id, .. } => {
val: block_id,
span: block_span,
..
} => {
run_hook_block( run_hook_block(
engine_state, engine_state,
stack, stack,
block_id, block_id,
input, input,
arguments, arguments,
block_span, source_span,
)?; )?;
} }
Value::Closure { Value::Closure { val: block_id, .. } => {
val: block_id,
span: block_span,
..
} => {
run_hook_block( run_hook_block(
engine_state, engine_state,
stack, stack,
block_id, block_id,
input, input,
arguments, arguments,
block_span, source_span,
)?; )?;
} }
other => { other => {
return Err(ShellError::UnsupportedConfigValue( return Err(ShellError::UnsupportedConfigValue(
"block or string".to_string(), "block or string".to_string(),
format!("{}", other.get_type()), format!("{}", other.get_type()),
other.span()?, source_span,
)); ));
} }
} }
} }
} }
Value::Block { Value::Block { val: block_id, .. } => {
val: block_id, output = run_hook_block(engine_state, stack, *block_id, input, arguments, span)?;
span: block_span,
..
} => {
output = run_hook_block(
engine_state,
stack,
*block_id,
input,
arguments,
*block_span,
)?;
} }
Value::Closure { Value::Closure { val: block_id, .. } => {
val: block_id, output = run_hook_block(engine_state, stack, *block_id, input, arguments, span)?;
span: block_span,
..
} => {
output = run_hook_block(
engine_state,
stack,
*block_id,
input,
arguments,
*block_span,
)?;
} }
other => { other => {
return Err(ShellError::UnsupportedConfigValue( return Err(ShellError::UnsupportedConfigValue(
"string, block, record, or list of commands".into(), "string, block, record, or list of commands".into(),
format!("{}", other.get_type()), format!("{}", other.get_type()),
other.span()?, other.span(),
)); ));
} }
} }
@ -378,7 +353,7 @@ fn run_hook_block(
let pipeline_data = let pipeline_data =
eval_block_with_early_return(engine_state, &mut callee_stack, block, input, false, false)?; eval_block_with_early_return(engine_state, &mut callee_stack, block, input, false, false)?;
if let PipelineData::Value(Value::Error { error }, _) = pipeline_data { if let PipelineData::Value(Value::Error { error, .. }, _) = pipeline_data {
return Err(*error); return Err(*error);
} }

View File

@ -76,9 +76,7 @@ where
}), }),
); );
if let Err(error) = r { if let Err(error) = r {
return Value::Error { return Value::error(error, span);
error: Box::new(error),
};
} }
} }
v v

View File

@ -1,3 +1,4 @@
pub mod formats; pub mod formats;
pub mod hook;
pub mod input_handler; pub mod input_handler;
pub mod util; pub mod util;

View File

@ -55,3 +55,72 @@ pub fn process_range(range: &Range) -> Result<(isize, isize), MakeRangeError> {
Ok((start, end)) 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" license = "MIT"
name = "nu-cmd-dataframe" name = "nu-cmd-dataframe"
repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cmd-dataframe" repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cmd-dataframe"
version = "0.84.0" version = "0.86.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -13,9 +13,9 @@ version = "0.84.0"
bench = false bench = false
[dependencies] [dependencies]
nu-engine = { path = "../nu-engine", version = "0.84.0" } nu-engine = { path = "../nu-engine", version = "0.86.0" }
nu-parser = { path = "../nu-parser", version = "0.84.0" } nu-parser = { path = "../nu-parser", version = "0.86.0" }
nu-protocol = { path = "../nu-protocol", version = "0.84.0" } nu-protocol = { path = "../nu-protocol", version = "0.86.0" }
# Potential dependencies for extras # Potential dependencies for extras
chrono = { version = "0.4", features = ["std", "unstable-locales"], default-features = false } chrono = { version = "0.4", features = ["std", "unstable-locales"], default-features = false }
@ -23,8 +23,8 @@ fancy-regex = "0.11"
indexmap = { version = "2.0" } indexmap = { version = "2.0" }
num = { version = "0.4", optional = true } num = { version = "0.4", optional = true }
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
sqlparser = { version = "0.34", features = ["serde"], optional = true } sqlparser = { version = "0.36.1", optional = true }
polars-io = { version = "0.30.0", features = ["avro"] } polars-io = { version = "0.33", features = ["avro"], optional = true }
[dependencies.polars] [dependencies.polars]
features = [ features = [
@ -38,7 +38,7 @@ features = [
"dtype-categorical", "dtype-categorical",
"dtype-datetime", "dtype-datetime",
"dtype-struct", "dtype-struct",
"dynamic_groupby", "dynamic_group_by",
"ipc", "ipc",
"is_in", "is_in",
"json", "json",
@ -51,15 +51,15 @@ features = [
"serde", "serde",
"serde-lazy", "serde-lazy",
"strings", "strings",
"to_dummies" "to_dummies",
] ]
optional = true optional = true
version = "0.30.0" version = "0.33"
[features] [features]
dataframe = ["num", "polars", "sqlparser"] dataframe = ["num", "polars", "polars-io", "sqlparser"]
default = [] default = []
[dev-dependencies] [dev-dependencies]
nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.84.0" } nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.86.0" }
nu-test-support = { path = "../nu-test-support", version = "0.84.0" } nu-test-support = { path = "../nu-test-support", version = "0.86.0" }

View File

@ -27,10 +27,10 @@ impl Command for ColumnsDF {
vec![Example { vec![Example {
description: "Dataframe columns", description: "Dataframe columns",
example: "[[a b]; [1 2] [3 4]] | dfr into-df | dfr columns", example: "[[a b]; [1 2] [3 4]] | dfr into-df | dfr columns",
result: Some(Value::List { result: Some(Value::list(
vals: vec![Value::test_string("a"), Value::test_string("b")], vec![Value::test_string("a"), Value::test_string("b")],
span: Span::test_data(), Span::test_data(),
}), )),
}] }]
} }
@ -60,10 +60,7 @@ fn command(
.map(|v| Value::string(*v, call.head)) .map(|v| Value::string(*v, call.head))
.collect(); .collect();
let names = Value::List { let names = Value::list(names, call.head);
vals: names,
span: call.head,
};
Ok(PipelineData::Value(names, None)) Ok(PipelineData::Value(names, None))
} }

View File

@ -79,10 +79,7 @@ fn command(
.dtype(); .dtype();
let dtype_str = dtype.to_string(); let dtype_str = dtype.to_string();
dtypes.push(Value::String { dtypes.push(Value::string(dtype_str, call.head));
val: dtype_str,
span: call.head,
});
Value::string(*v, call.head) Value::string(*v, call.head)
}) })

View File

@ -20,6 +20,7 @@ impl Command for Dummies {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build(self.name()) Signature::build(self.name())
.switch("drop-first", "Drop first row", Some('d'))
.input_output_type( .input_output_type(
Type::Custom("dataframe".into()), Type::Custom("dataframe".into()),
Type::Custom("dataframe".into()), Type::Custom("dataframe".into()),
@ -115,10 +116,11 @@ fn command(
call: &Call, call: &Call,
input: PipelineData, input: PipelineData,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
let drop_first: bool = call.has_flag("drop-first");
let df = NuDataFrame::try_from_pipeline(input, call.head)?; let df = NuDataFrame::try_from_pipeline(input, call.head)?;
df.as_ref() df.as_ref()
.to_dummies(None) .to_dummies(None, drop_first)
.map_err(|e| { .map_err(|e| {
ShellError::GenericError( ShellError::GenericError(
"Error calculating dummies".into(), "Error calculating dummies".into(),

View File

@ -92,7 +92,7 @@ fn command_eager(
df: NuDataFrame, df: NuDataFrame,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
let mask_value: Value = call.req(engine_state, stack, 0)?; let mask_value: Value = call.req(engine_state, stack, 0)?;
let mask_span = mask_value.span()?; let mask_span = mask_value.span();
if NuExpression::can_downcast(&mask_value) { if NuExpression::can_downcast(&mask_value) {
let expression = NuExpression::try_from_value(mask_value)?; let expression = NuExpression::try_from_value(mask_value)?;

View File

@ -1,7 +1,7 @@
use nu_protocol::{ use nu_protocol::{
ast::Call, ast::Call,
engine::{Command, EngineState, Stack}, engine::{Command, EngineState, Stack},
Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, Value, record, Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, Value,
}; };
use crate::dataframe::values::NuDataFrame; use crate::dataframe::values::NuDataFrame;
@ -55,34 +55,18 @@ impl Command for ListDF {
NuDataFrame::try_from_value(value).ok().map(|df| (name, df)) NuDataFrame::try_from_value(value).ok().map(|df| (name, df))
}) })
.map(|(name, df)| { .map(|(name, df)| {
let name = Value::String { Value::record(
val: name, record! {
span: call.head, "name" => Value::string(name, call.head),
}; "columns" => Value::int(df.as_ref().width() as i64, call.head),
"rows" => Value::int(df.as_ref().height() as i64, call.head),
let columns = Value::int(df.as_ref().width() as i64, call.head); },
call.head,
let rows = Value::int(df.as_ref().height() as i64, call.head); )
let cols = vec![
"name".to_string(),
"columns".to_string(),
"rows".to_string(),
];
let vals = vec![name, columns, rows];
Value::Record {
cols,
vals,
span: call.head,
}
}) })
.collect::<Vec<Value>>(); .collect::<Vec<Value>>();
let list = Value::List { let list = Value::list(vals, call.head);
vals,
span: call.head,
};
Ok(list.into_pipeline_data()) Ok(list.into_pipeline_data())
} }

View File

@ -116,7 +116,7 @@ fn command(
match type_id { match type_id {
Some((e, msg, blamed)) => match e.as_str() { Some((e, msg, blamed)) => match e.as_str() {
"csv" | "tsv" => from_csv(engine_state, stack, call), "csv" | "tsv" => from_csv(engine_state, stack, call),
"parquet" => from_parquet(engine_state, stack, call), "parquet" | "parq" => from_parquet(engine_state, stack, call),
"ipc" | "arrow" => from_ipc(engine_state, stack, call), "ipc" | "arrow" => from_ipc(engine_state, stack, call),
"json" => from_json(engine_state, stack, call), "json" => from_json(engine_state, stack, call),
"jsonl" => from_jsonl(engine_state, stack, call), "jsonl" => from_jsonl(engine_state, stack, call),

View File

@ -88,10 +88,7 @@ fn command(
let lazy = NuLazyFrame::new(false, df_sql); let lazy = NuLazyFrame::new(false, df_sql);
let eager = lazy.collect(call.head)?; let eager = lazy.collect(call.head)?;
let value = Value::CustomValue { let value = Value::custom_value(Box::new(eager), call.head);
val: Box::new(eager),
span: call.head,
};
Ok(PipelineData::Value(value, None)) Ok(PipelineData::Value(value, None))
} }

View File

@ -160,7 +160,7 @@ fn command_lazy(
let value: Value = call.req(engine_state, stack, 1)?; let value: Value = call.req(engine_state, stack, 1)?;
return Err(ShellError::IncompatibleParametersSingle { return Err(ShellError::IncompatibleParametersSingle {
msg: "New name list has different size to column list".into(), msg: "New name list has different size to column list".into(),
span: value.span()?, span: value.span(),
}); });
} }

View File

@ -52,12 +52,13 @@ impl Command for SampleDF {
vec![ vec![
Example { Example {
description: "Sample rows from dataframe", 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 result: None, // No expected value because sampling is random
}, },
Example { Example {
description: "Shows sample row using fraction and replace", 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 result: None, // No expected value because sampling is random
}, },
] ]

View File

@ -147,7 +147,7 @@ impl SQLContext {
.enumerate() .enumerate()
.map(|(agg_pj, (proj_p, expr))| (expr.clone(), (proj_p, agg_pj + group_by.len()))) .map(|(agg_pj, (proj_p, expr))| (expr.clone(), (proj_p, agg_pj + group_by.len())))
.unzip(); .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 let mut final_proj_pos = groupby_pos
.into_iter() .into_iter()
.chain(agg_proj_pos) .chain(agg_proj_pos)

View File

@ -125,7 +125,7 @@ pub fn parse_sql_expr(expr: &SqlExpr) -> Result<Expr> {
}) })
} }
fn apply_window_spec(expr: Expr, window_type: &Option<WindowType>) -> Result<Expr> { fn apply_window_spec(expr: Expr, window_type: Option<&WindowType>) -> Result<Expr> {
Ok(match &window_type { Ok(match &window_type {
Some(wtype) => match wtype { Some(wtype) => match wtype {
WindowType::WindowSpec(window_spec) => { WindowType::WindowSpec(window_spec) => {
@ -168,13 +168,13 @@ fn parse_sql_function(sql_function: &SQLFunction) -> Result<Expr> {
sql_function.distinct, sql_function.distinct,
) { ) {
("sum", [FunctionArgExpr::Expr(expr)], false) => { ("sum", [FunctionArgExpr::Expr(expr)], false) => {
apply_window_spec(parse_sql_expr(expr)?, &sql_function.over)?.sum() apply_window_spec(parse_sql_expr(expr)?, sql_function.over.as_ref())?.sum()
} }
("count", [FunctionArgExpr::Expr(expr)], false) => { ("count", [FunctionArgExpr::Expr(expr)], false) => {
apply_window_spec(parse_sql_expr(expr)?, &sql_function.over)?.count() apply_window_spec(parse_sql_expr(expr)?, sql_function.over.as_ref())?.count()
} }
("count", [FunctionArgExpr::Expr(expr)], true) => { ("count", [FunctionArgExpr::Expr(expr)], true) => {
apply_window_spec(parse_sql_expr(expr)?, &sql_function.over)?.n_unique() apply_window_spec(parse_sql_expr(expr)?, sql_function.over.as_ref())?.n_unique()
} }
// Special case for wildcard args to count function. // Special case for wildcard args to count function.
("count", [FunctionArgExpr::Wildcard], false) => lit(1i32).count(), ("count", [FunctionArgExpr::Wildcard], false) => lit(1i32).count(),

View File

@ -120,30 +120,31 @@ fn command(
let quantiles = quantiles.map(|values| { let quantiles = quantiles.map(|values| {
values values
.iter() .iter()
.map(|value| match value { .map(|value| {
Value::Float { val, span } => { let span = value.span();
if (&0.0..=&1.0).contains(&val) { match value {
Ok(*val) Value::Float { val, .. } => {
} else { if (&0.0..=&1.0).contains(&val) {
Err(ShellError::GenericError( Ok(*val)
"Incorrect value for quantile".to_string(), } else {
"value should be between 0 and 1".to_string(), Err(ShellError::GenericError(
Some(*span), "Incorrect value for quantile".to_string(),
None, "value should be between 0 and 1".to_string(),
Vec::new(), Some(span),
)) None,
Vec::new(),
))
}
} }
} Value::Error { error, .. } => Err(*error.clone()),
_ => match value.span() { _ => Err(ShellError::GenericError(
Ok(span) => Err(ShellError::GenericError(
"Incorrect value for quantile".to_string(), "Incorrect value for quantile".to_string(),
"value should be a float".to_string(), "value should be a float".to_string(),
Some(span), Some(span),
None, None,
Vec::new(), Vec::new(),
)), )),
Err(e) => Err(e), }
},
}) })
.collect::<Result<Vec<f64>, ShellError>>() .collect::<Result<Vec<f64>, ShellError>>()
}); });

View File

@ -93,7 +93,7 @@ fn command(
input: PipelineData, input: PipelineData,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
let index_value: Value = call.req(engine_state, stack, 0)?; let index_value: Value = call.req(engine_state, stack, 0)?;
let index_span = index_value.span()?; let index_span = index_value.span();
let index = NuDataFrame::try_from_value(index_value)?.as_series(index_span)?; let index = NuDataFrame::try_from_value(index_value)?.as_series(index_span)?;
let casted = match index.dtype() { let casted = match index.dtype() {

View File

@ -78,16 +78,10 @@ fn command(
) )
})?; })?;
let file_value = Value::String { let file_value = Value::string(format!("saved {:?}", &file_name.item), file_name.span);
val: format!("saved {:?}", &file_name.item),
span: file_name.span,
};
Ok(PipelineData::Value( Ok(PipelineData::Value(
Value::List { Value::list(vec![file_value], call.head),
vals: vec![file_value],
span: call.head,
},
None, None,
)) ))
} }

View File

@ -108,16 +108,10 @@ fn command(
) )
})?; })?;
let file_value = Value::String { let file_value = Value::string(format!("saved {:?}", &file_name.item), file_name.span);
val: format!("saved {:?}", &file_name.item),
span: file_name.span,
};
Ok(PipelineData::Value( Ok(PipelineData::Value(
Value::List { Value::list(vec![file_value], call.head),
vals: vec![file_value],
span: call.head,
},
None, None,
)) ))
} }

View File

@ -45,7 +45,7 @@ impl Command for ToCSV {
}, },
Example { Example {
description: "Saves dataframe to CSV file using other delimiter", 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, result: None,
}, },
] ]
@ -124,16 +124,10 @@ fn command(
) )
})?; })?;
let file_value = Value::String { let file_value = Value::string(format!("saved {:?}", &file_name.item), file_name.span);
val: format!("saved {:?}", &file_name.item),
span: file_name.span,
};
Ok(PipelineData::Value( Ok(PipelineData::Value(
Value::List { Value::list(vec![file_value], call.head),
vals: vec![file_value],
span: call.head,
},
None, None,
)) ))
} }

View File

@ -81,16 +81,10 @@ fn command(
) )
})?; })?;
let file_value = Value::String { let file_value = Value::string(format!("saved {:?}", &file_name.item), file_name.span);
val: format!("saved {:?}", &file_name.item),
span: file_name.span,
};
Ok(PipelineData::Value( Ok(PipelineData::Value(
Value::List { Value::list(vec![file_value], call.head),
vals: vec![file_value],
span: call.head,
},
None, None,
)) ))
} }

View File

@ -2,7 +2,7 @@ use nu_engine::CallExt;
use nu_protocol::{ use nu_protocol::{
ast::Call, ast::Call,
engine::{Command, EngineState, Stack}, engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value, Category, Example, PipelineData, Record, ShellError, Signature, Span, SyntaxShape, Type, Value,
}; };
use crate::dataframe::values::NuExpression; use crate::dataframe::values::NuExpression;
@ -40,47 +40,37 @@ impl Command for ToNu {
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
let cols = vec!["index".into(), "a".into(), "b".into()]; let cols = vec!["index".into(), "a".into(), "b".into()];
let rec_1 = Value::Record { let rec_1 = Value::test_record(Record {
cols: cols.clone(), cols: cols.clone(),
vals: vec![Value::test_int(0), Value::test_int(1), Value::test_int(2)], vals: vec![Value::test_int(0), Value::test_int(1), Value::test_int(2)],
span: Span::test_data(), });
}; let rec_2 = Value::test_record(Record {
let rec_2 = Value::Record {
cols: cols.clone(), cols: cols.clone(),
vals: vec![Value::test_int(1), Value::test_int(3), Value::test_int(4)], vals: vec![Value::test_int(1), Value::test_int(3), Value::test_int(4)],
span: Span::test_data(), });
}; let rec_3 = Value::test_record(Record {
let rec_3 = Value::Record {
cols, cols,
vals: vec![Value::test_int(2), Value::test_int(3), Value::test_int(4)], vals: vec![Value::test_int(2), Value::test_int(3), Value::test_int(4)],
span: Span::test_data(), });
};
vec![ vec![
Example { Example {
description: "Shows head rows from dataframe", description: "Shows head rows from dataframe",
example: "[[a b]; [1 2] [3 4]] | dfr into-df | dfr into-nu", example: "[[a b]; [1 2] [3 4]] | dfr into-df | dfr into-nu",
result: Some(Value::List { result: Some(Value::list(vec![rec_1, rec_2], Span::test_data())),
vals: vec![rec_1, rec_2],
span: Span::test_data(),
}),
}, },
Example { Example {
description: "Shows tail rows from dataframe", 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 { result: Some(Value::list(vec![rec_3], Span::test_data())),
vals: vec![rec_3],
span: Span::test_data(),
}),
}, },
Example { Example {
description: "Convert a col expression into a nushell value", description: "Convert a col expression into a nushell value",
example: "dfr col a | dfr into-nu", example: "dfr col a | dfr into-nu",
result: Some(Value::Record { result: Some(Value::test_record(Record {
cols: vec!["expr".into(), "value".into()], cols: vec!["expr".into(), "value".into()],
vals: vec![Value::test_string("column"), Value::test_string("a")], vals: vec![Value::test_string("column"), Value::test_string("a")],
span: Span::test_data(), })),
}),
}, },
] ]
} }
@ -123,16 +113,13 @@ fn dataframe_command(
} }
}; };
let value = Value::List { let value = Value::list(values, call.head);
vals: values,
span: call.head,
};
Ok(PipelineData::Value(value, None)) Ok(PipelineData::Value(value, None))
} }
fn expression_command(call: &Call, input: Value) -> Result<PipelineData, ShellError> { fn expression_command(call: &Call, input: Value) -> Result<PipelineData, ShellError> {
let expr = NuExpression::try_from_value(input)?; let expr = NuExpression::try_from_value(input)?;
let value = expr.to_value(call.head); let value = expr.to_value(call.head)?;
Ok(PipelineData::Value(value, None)) Ok(PipelineData::Value(value, None))
} }

View File

@ -78,16 +78,10 @@ fn command(
) )
})?; })?;
let file_value = Value::String { let file_value = Value::string(format!("saved {:?}", &file_name.item), file_name.span);
val: format!("saved {:?}", &file_name.item),
span: file_name.span,
};
Ok(PipelineData::Value( Ok(PipelineData::Value(
Value::List { Value::list(vec![file_value], call.head),
vals: vec![file_value],
span: call.head,
},
None, None,
)) ))
} }

View File

@ -114,7 +114,7 @@ impl Command for WithColumn {
Err(ShellError::CantConvert { Err(ShellError::CantConvert {
to_type: "lazy or eager dataframe".into(), to_type: "lazy or eager dataframe".into(),
from_type: value.get_type().to_string(), from_type: value.get_type().to_string(),
span: value.span()?, span: value.span(),
help: None, help: None,
}) })
} }
@ -128,14 +128,11 @@ fn command_eager(
mut df: NuDataFrame, mut df: NuDataFrame,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
let new_column: Value = call.req(engine_state, stack, 0)?; let new_column: Value = call.req(engine_state, stack, 0)?;
let column_span = new_column.span()?; let column_span = new_column.span();
if NuExpression::can_downcast(&new_column) { if NuExpression::can_downcast(&new_column) {
let vals: Vec<Value> = call.rest(engine_state, stack, 0)?; let vals: Vec<Value> = call.rest(engine_state, stack, 0)?;
let value = Value::List { let value = Value::list(vals, call.head);
vals,
span: call.head,
};
let expressions = NuExpression::extract_exprs(value)?; let expressions = NuExpression::extract_exprs(value)?;
let lazy = NuLazyFrame::new(true, df.lazy().with_columns(&expressions)); let lazy = NuLazyFrame::new(true, df.lazy().with_columns(&expressions));
@ -179,10 +176,7 @@ fn command_lazy(
lazy: NuLazyFrame, lazy: NuLazyFrame,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
let vals: Vec<Value> = call.rest(engine_state, stack, 0)?; let vals: Vec<Value> = call.rest(engine_state, stack, 0)?;
let value = Value::List { let value = Value::list(vals, call.head);
vals,
span: call.head,
};
let expressions = NuExpression::extract_exprs(value)?; let expressions = NuExpression::extract_exprs(value)?;
let lazy: NuLazyFrame = lazy.into_polars().with_columns(&expressions).into(); let lazy: NuLazyFrame = lazy.into_polars().with_columns(&expressions).into();

View File

@ -4,7 +4,7 @@ use nu_engine::CallExt;
use nu_protocol::{ use nu_protocol::{
ast::Call, ast::Call,
engine::{Command, EngineState, Stack}, engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value, Category, Example, PipelineData, Record, ShellError, Signature, SyntaxShape, Type, Value,
}; };
#[derive(Clone)] #[derive(Clone)]
@ -41,20 +41,18 @@ impl Command for ExprAlias {
let cols = vec!["expr".into(), "value".into()]; let cols = vec!["expr".into(), "value".into()];
let expr = Value::test_string("column"); let expr = Value::test_string("column");
let value = Value::test_string("a"); let value = Value::test_string("a");
let expr = Value::Record { let expr = Value::test_record(Record {
cols, cols,
vals: vec![expr, value], vals: vec![expr, value],
span: Span::test_data(), });
};
let cols = vec!["expr".into(), "alias".into()]; let cols = vec!["expr".into(), "alias".into()];
let value = Value::test_string("new_a"); let value = Value::test_string("new_a");
let record = Value::Record { let record = Value::test_record(Record {
cols, cols,
vals: vec![expr, value], vals: vec![expr, value],
span: Span::test_data(), });
};
Some(record) Some(record)
}, },

View File

@ -3,7 +3,7 @@ use nu_engine::CallExt;
use nu_protocol::{ use nu_protocol::{
ast::Call, ast::Call,
engine::{Command, EngineState, Stack}, engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value, Category, Example, PipelineData, Record, ShellError, Signature, SyntaxShape, Type, Value,
}; };
use polars::prelude::col; use polars::prelude::col;
@ -34,11 +34,10 @@ impl Command for ExprCol {
vec![Example { vec![Example {
description: "Creates a named column expression and converts it to a nu object", description: "Creates a named column expression and converts it to a nu object",
example: "dfr col a | dfr into-nu", example: "dfr col a | dfr into-nu",
result: Some(Value::Record { result: Some(Value::test_record(Record {
cols: vec!["expr".into(), "value".into()], cols: vec!["expr".into(), "value".into()],
vals: vec![Value::test_string("column"), Value::test_string("a")], vals: vec![Value::test_string("column"), Value::test_string("a")],
span: Span::test_data(), })),
}),
}] }]
} }

View File

@ -3,7 +3,7 @@ use nu_engine::CallExt;
use nu_protocol::{ use nu_protocol::{
ast::Call, ast::Call,
engine::{Command, EngineState, Stack}, engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value, Category, Example, PipelineData, Record, ShellError, Signature, SyntaxShape, Type, Value,
}; };
#[derive(Clone)] #[derive(Clone)]
@ -33,11 +33,10 @@ impl Command for ExprLit {
vec![Example { vec![Example {
description: "Created a literal expression and converts it to a nu object", description: "Created a literal expression and converts it to a nu object",
example: "dfr lit 2 | dfr into-nu", example: "dfr lit 2 | dfr into-nu",
result: Some(Value::Record { result: Some(Value::test_record(Record {
cols: vec!["expr".into(), "value".into()], cols: vec!["expr".into(), "value".into()],
vals: vec![Value::test_string("literal"), Value::test_string("2")], vals: vec![Value::test_string("literal"), Value::test_string("2")],
span: Span::test_data(), })),
}),
}] }]
} }

View File

@ -95,10 +95,8 @@ impl Command for ExprOtherwise {
let value = input.into_value(call.head); let value = input.into_value(call.head);
let complete: NuExpression = match NuWhen::try_from_value(value)? { let complete: NuExpression = match NuWhen::try_from_value(value)? {
NuWhen::WhenThen(when_then) => when_then NuWhen::Then(then) => then.otherwise(otherwise_predicate.into_polars()).into(),
.otherwise(otherwise_predicate.into_polars()) NuWhen::ChainedThen(chained_when) => chained_when
.into(),
NuWhen::WhenThenThen(when_then_then) => when_then_then
.otherwise(otherwise_predicate.into_polars()) .otherwise(otherwise_predicate.into_polars())
.into(), .into(),
}; };

View File

@ -110,11 +110,11 @@ impl Command for ExprWhen {
.then(then_predicate.into_polars()) .then(then_predicate.into_polars())
.into(), .into(),
v => match NuWhen::try_from_value(v)? { v => match NuWhen::try_from_value(v)? {
NuWhen::WhenThen(when_then) => when_then NuWhen::Then(when_then) => when_then
.when(when_predicate.into_polars()) .when(when_predicate.into_polars())
.then(then_predicate.into_polars()) .then(then_predicate.into_polars())
.into(), .into(),
NuWhen::WhenThenThen(when_then_then) => when_then_then NuWhen::ChainedThen(when_then_then) => when_then_then
.when(when_predicate.into_polars()) .when(when_predicate.into_polars())
.then(then_predicate.into_polars()) .then(then_predicate.into_polars())
.into(), .into(),

View File

@ -114,10 +114,7 @@ impl Command for LazyAggregate {
input: PipelineData, input: PipelineData,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
let vals: Vec<Value> = call.rest(engine_state, stack, 0)?; let vals: Vec<Value> = call.rest(engine_state, stack, 0)?;
let value = Value::List { let value = Value::list(vals, call.head);
vals,
span: call.head,
};
let expressions = NuExpression::extract_exprs(value)?; let expressions = NuExpression::extract_exprs(value)?;
let group_by = NuLazyGroupBy::try_from_pipeline(input, call.head)?; let group_by = NuLazyGroupBy::try_from_pipeline(input, call.head)?;
@ -172,7 +169,6 @@ fn get_col_name(expr: &Expr) -> Option<String> {
}, },
Expr::Filter { input: expr, .. } Expr::Filter { input: expr, .. }
| Expr::Slice { input: expr, .. } | Expr::Slice { input: expr, .. }
| Expr::Cache { input: expr, .. }
| Expr::Cast { expr, .. } | Expr::Cast { expr, .. }
| Expr::Sort { expr, .. } | Expr::Sort { expr, .. }
| Expr::Take { expr, .. } | Expr::Take { expr, .. }
@ -192,7 +188,8 @@ fn get_col_name(expr: &Expr) -> Option<String> {
| Expr::Wildcard | Expr::Wildcard
| Expr::RenameAlias { .. } | Expr::RenameAlias { .. }
| Expr::Count | Expr::Count
| Expr::Nth(_) => None, | Expr::Nth(_)
| Expr::Selector(_) => None,
} }
} }

View File

@ -58,10 +58,7 @@ impl Command for LazyCollect {
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
let lazy = NuLazyFrame::try_from_pipeline(input, call.head)?; let lazy = NuLazyFrame::try_from_pipeline(input, call.head)?;
let eager = lazy.collect(call.head)?; let eager = lazy.collect(call.head)?;
let value = Value::CustomValue { let value = Value::custom_value(Box::new(eager), call.head);
val: Box::new(eager),
span: call.head,
};
Ok(PipelineData::Value(value, None)) Ok(PipelineData::Value(value, None))
} }

View File

@ -93,7 +93,7 @@ impl Command for LazyFillNA {
None, None,
)) ))
} else { } else {
let val_span = value.span()?; let val_span = value.span();
let frame = NuDataFrame::try_from_value(value)?; let frame = NuDataFrame::try_from_value(value)?;
let columns = frame.columns(val_span)?; let columns = frame.columns(val_span)?;
let dataframe = columns let dataframe = columns
@ -102,18 +102,21 @@ impl Command for LazyFillNA {
let column_name = column.name().to_string(); let column_name = column.name().to_string();
let values = column let values = column
.into_iter() .into_iter()
.map(|value| match value { .map(|value| {
Value::Float { val, .. } => { let span = value.span();
if val.is_nan() { match value {
fill.clone() Value::Float { val, .. } => {
} else { if val.is_nan() {
value fill.clone()
} else {
value
}
} }
Value::List { vals, .. } => {
NuDataFrame::fill_list_nan(vals, span, fill.clone())
}
_ => value,
} }
Value::List { vals, span } => {
NuDataFrame::fill_list_nan(vals, span, fill.clone())
}
_ => value,
}) })
.collect::<Vec<Value>>(); .collect::<Vec<Value>>();
Column::new(column_name, values) Column::new(column_name, values)

View File

@ -113,10 +113,7 @@ impl Command for ToLazyGroupBy {
input: PipelineData, input: PipelineData,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
let vals: Vec<Value> = call.rest(engine_state, stack, 0)?; let vals: Vec<Value> = call.rest(engine_state, stack, 0)?;
let value = Value::List { let value = Value::list(vals, call.head);
vals,
span: call.head,
};
let expressions = NuExpression::extract_exprs(value)?; let expressions = NuExpression::extract_exprs(value)?;
if expressions if expressions
@ -126,7 +123,7 @@ impl Command for ToLazyGroupBy {
let value: Value = call.req(engine_state, stack, 0)?; let value: Value = call.req(engine_state, stack, 0)?;
return Err(ShellError::IncompatibleParametersSingle { return Err(ShellError::IncompatibleParametersSingle {
msg: "Expected only Col expressions".into(), msg: "Expected only Col expressions".into(),
span: value.span()?, span: value.span(),
}); });
} }
@ -134,7 +131,7 @@ impl Command for ToLazyGroupBy {
let group_by = NuLazyGroupBy { let group_by = NuLazyGroupBy {
schema: lazy.schema.clone(), schema: lazy.schema.clone(),
from_eager: lazy.from_eager, 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)) Ok(PipelineData::Value(group_by.into_value(call.head), None))

View File

@ -199,7 +199,7 @@ impl Command for LazyJoin {
let right_on: Value = call.req(engine_state, stack, 2)?; let right_on: Value = call.req(engine_state, stack, 2)?;
return Err(ShellError::IncompatibleParametersSingle { return Err(ShellError::IncompatibleParametersSingle {
msg: "The right column list has a different size to the left column list".into(), msg: "The right column list has a different size to the left column list".into(),
span: right_on.span()?, span: right_on.span(),
}); });
} }
@ -209,7 +209,7 @@ impl Command for LazyJoin {
let value: Value = call.req(engine_state, stack, *index)?; let value: Value = call.req(engine_state, stack, *index)?;
return Err(ShellError::IncompatibleParametersSingle { return Err(ShellError::IncompatibleParametersSingle {
msg: "Expected only a string, col expressions or list of strings".into(), msg: "Expected only a string, col expressions or list of strings".into(),
span: value.span()?, span: value.span(),
}); });
} }
} }

View File

@ -55,10 +55,7 @@ impl Command for LazySelect {
input: PipelineData, input: PipelineData,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
let vals: Vec<Value> = call.rest(engine_state, stack, 0)?; let vals: Vec<Value> = call.rest(engine_state, stack, 0)?;
let value = Value::List { let value = Value::list(vals, call.head);
vals,
span: call.head,
};
let expressions = NuExpression::extract_exprs(value)?; let expressions = NuExpression::extract_exprs(value)?;
let lazy = NuLazyFrame::try_from_pipeline(input, call.head)?; let lazy = NuLazyFrame::try_from_pipeline(input, call.head)?;

View File

@ -37,6 +37,7 @@ impl Command for LazySortBy {
"nulls are shown last in the dataframe", "nulls are shown last in the dataframe",
Some('n'), Some('n'),
) )
.switch("maintain-order", "Maintains order during sort", Some('m'))
.input_output_type( .input_output_type(
Type::Custom("dataframe".into()), Type::Custom("dataframe".into()),
Type::Custom("dataframe".into()), Type::Custom("dataframe".into()),
@ -104,12 +105,10 @@ impl Command for LazySortBy {
input: PipelineData, input: PipelineData,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
let vals: Vec<Value> = call.rest(engine_state, stack, 0)?; let vals: Vec<Value> = call.rest(engine_state, stack, 0)?;
let value = Value::List { let value = Value::list(vals, call.head);
vals,
span: call.head,
};
let expressions = NuExpression::extract_exprs(value)?; let expressions = NuExpression::extract_exprs(value)?;
let nulls_last = call.has_flag("nulls-last"); let nulls_last = call.has_flag("nulls-last");
let maintain_order = call.has_flag("maintain-order");
let reverse: Option<Vec<bool>> = call.get_flag(engine_state, stack, "reverse")?; let reverse: Option<Vec<bool>> = call.get_flag(engine_state, stack, "reverse")?;
let reverse = match reverse { let reverse = match reverse {
@ -118,7 +117,7 @@ impl Command for LazySortBy {
let span = call let span = call
.get_flag::<Value>(engine_state, stack, "reverse")? .get_flag::<Value>(engine_state, stack, "reverse")?
.expect("already checked and it exists") .expect("already checked and it exists")
.span()?; .span();
return Err(ShellError::GenericError( return Err(ShellError::GenericError(
"Incorrect list size".into(), "Incorrect list size".into(),
"Size doesn't match expression list".into(), "Size doesn't match expression list".into(),
@ -137,7 +136,7 @@ impl Command for LazySortBy {
let lazy = NuLazyFrame::new( let lazy = NuLazyFrame::new(
lazy.from_eager, lazy.from_eager,
lazy.into_polars() lazy.into_polars()
.sort_by_exprs(&expressions, reverse, nulls_last), .sort_by_exprs(&expressions, reverse, nulls_last, maintain_order),
); );
Ok(PipelineData::Value( Ok(PipelineData::Value(

View File

@ -41,10 +41,7 @@ impl Command for ToLazyFrame {
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
let df = NuDataFrame::try_from_iter(input.into_iter())?; let df = NuDataFrame::try_from_iter(input.into_iter())?;
let lazy = NuLazyFrame::from_dataframe(df); let lazy = NuLazyFrame::from_dataframe(df);
let value = Value::CustomValue { let value = Value::custom_value(Box::new(lazy), call.head);
val: Box::new(lazy),
span: call.head,
};
Ok(PipelineData::Value(value, None)) Ok(PipelineData::Value(value, None))
} }

View File

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

View File

@ -56,22 +56,22 @@ impl Command for AsDateTime {
NuDataFrame::try_from_columns(vec![Column::new( NuDataFrame::try_from_columns(vec![Column::new(
"datetime".to_string(), "datetime".to_string(),
vec![ vec![
Value::Date { Value::date(
val: DateTime::parse_from_str( DateTime::parse_from_str(
"2021-12-30 00:00:00 +0000", "2021-12-30 00:00:00 +0000",
"%Y-%m-%d %H:%M:%S %z", "%Y-%m-%d %H:%M:%S %z",
) )
.expect("date calculation should not fail in test"), .expect("date calculation should not fail in test"),
span: Span::test_data(), Span::test_data(),
}, ),
Value::Date { Value::date(
val: DateTime::parse_from_str( DateTime::parse_from_str(
"2021-12-31 00:00:00 +0000", "2021-12-31 00:00:00 +0000",
"%Y-%m-%d %H:%M:%S %z", "%Y-%m-%d %H:%M:%S %z",
) )
.expect("date calculation should not fail in test"), .expect("date calculation should not fail in test"),
span: Span::test_data(), Span::test_data(),
}, ),
], ],
)]) )])
.expect("simple df for test should not fail") .expect("simple df for test should not fail")
@ -85,22 +85,22 @@ impl Command for AsDateTime {
NuDataFrame::try_from_columns(vec![Column::new( NuDataFrame::try_from_columns(vec![Column::new(
"datetime".to_string(), "datetime".to_string(),
vec![ vec![
Value::Date { Value::date(
val: DateTime::parse_from_str( DateTime::parse_from_str(
"2021-12-30 00:00:00.123456789 +0000", "2021-12-30 00:00:00.123456789 +0000",
"%Y-%m-%d %H:%M:%S.%9f %z", "%Y-%m-%d %H:%M:%S.%9f %z",
) )
.expect("date calculation should not fail in test"), .expect("date calculation should not fail in test"),
span: Span::test_data(), Span::test_data(),
}, ),
Value::Date { Value::date(
val: DateTime::parse_from_str( DateTime::parse_from_str(
"2021-12-31 00:00:00.123456789 +0000", "2021-12-31 00:00:00.123456789 +0000",
"%Y-%m-%d %H:%M:%S.%9f %z", "%Y-%m-%d %H:%M:%S.%9f %z",
) )
.expect("date calculation should not fail in test"), .expect("date calculation should not fail in test"),
span: Span::test_data(), Span::test_data(),
}, ),
], ],
)]) )])
.expect("simple df for test should not fail") .expect("simple df for test should not fail")
@ -143,7 +143,13 @@ fn command(
})?; })?;
let res = if not_exact { let res = if not_exact {
casted.as_datetime_not_exact(Some(format.as_str()), TimeUnit::Nanoseconds, None) casted.as_datetime_not_exact(
Some(format.as_str()),
TimeUnit::Nanoseconds,
false,
None,
&Default::default(),
)
} else { } else {
casted.as_datetime( casted.as_datetime(
Some(format.as_str()), Some(format.as_str()),
@ -151,6 +157,7 @@ fn command(
false, false,
false, false,
None, None,
&Default::default(),
) )
}; };

View File

@ -31,7 +31,7 @@ impl Command for GetDay {
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
vec![Example { vec![Example {
description: "Returns day from a date", 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); let df = ([$dt $dt] | dfr into-df);
$df | dfr get-day"#, $df | dfr get-day"#,
result: Some( result: Some(

View File

@ -31,7 +31,7 @@ impl Command for GetHour {
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
vec![Example { vec![Example {
description: "Returns hour from a date", 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); let df = ([$dt $dt] | dfr into-df);
$df | dfr get-hour"#, $df | dfr get-hour"#,
result: Some( result: Some(

View File

@ -31,7 +31,7 @@ impl Command for GetMinute {
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
vec![Example { vec![Example {
description: "Returns minute from a date", 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); let df = ([$dt $dt] | dfr into-df);
$df | dfr get-minute"#, $df | dfr get-minute"#,
result: Some( result: Some(

View File

@ -31,7 +31,7 @@ impl Command for GetMonth {
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
vec![Example { vec![Example {
description: "Returns month from a date", 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); let df = ([$dt $dt] | dfr into-df);
$df | dfr get-month"#, $df | dfr get-month"#,
result: Some( result: Some(

View File

@ -31,7 +31,7 @@ impl Command for GetNanosecond {
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
vec![Example { vec![Example {
description: "Returns nanosecond from a date", 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); let df = ([$dt $dt] | dfr into-df);
$df | dfr get-nanosecond"#, $df | dfr get-nanosecond"#,
result: Some( result: Some(

View File

@ -31,7 +31,7 @@ impl Command for GetOrdinal {
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
vec![Example { vec![Example {
description: "Returns ordinal from a date", 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); let df = ([$dt $dt] | dfr into-df);
$df | dfr get-ordinal"#, $df | dfr get-ordinal"#,
result: Some( result: Some(

View File

@ -31,7 +31,7 @@ impl Command for GetSecond {
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
vec![Example { vec![Example {
description: "Returns second from a date", 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); let df = ([$dt $dt] | dfr into-df);
$df | dfr get-second"#, $df | dfr get-second"#,
result: Some( result: Some(

View File

@ -31,7 +31,7 @@ impl Command for GetWeek {
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
vec![Example { vec![Example {
description: "Returns week from a date", 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); let df = ([$dt $dt] | dfr into-df);
$df | dfr get-week"#, $df | dfr get-week"#,
result: Some( result: Some(

View File

@ -31,7 +31,7 @@ impl Command for GetWeekDay {
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
vec![Example { vec![Example {
description: "Returns weekday from a date", 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); let df = ([$dt $dt] | dfr into-df);
$df | dfr get-weekday"#, $df | dfr get-weekday"#,
result: Some( result: Some(

View File

@ -31,7 +31,7 @@ impl Command for GetYear {
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
vec![Example { vec![Example {
description: "Returns year from a date", 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); let df = ([$dt $dt] | dfr into-df);
$df | dfr get-year"#, $df | dfr get-year"#,
result: Some( result: Some(

View File

@ -27,6 +27,11 @@ impl Command for ArgSort {
Signature::build(self.name()) Signature::build(self.name())
.switch("reverse", "reverse order", Some('r')) .switch("reverse", "reverse order", Some('r'))
.switch("nulls-last", "nulls ordered last", Some('n')) .switch("nulls-last", "nulls ordered last", Some('n'))
.switch(
"maintain-order",
"maintain order on sorted items",
Some('m'),
)
.input_output_type( .input_output_type(
Type::Custom("dataframe".into()), Type::Custom("dataframe".into()),
Type::Custom("dataframe".into()), Type::Custom("dataframe".into()),
@ -56,7 +61,7 @@ impl Command for ArgSort {
}, },
Example { Example {
description: "Returns indexes for a sorted series", 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( result: Some(
NuDataFrame::try_from_columns(vec![Column::new( NuDataFrame::try_from_columns(vec![Column::new(
"arg_sort".to_string(), "arg_sort".to_string(),
@ -98,6 +103,7 @@ fn command(
descending: call.has_flag("reverse"), descending: call.has_flag("reverse"),
nulls_last: call.has_flag("nulls-last"), nulls_last: call.has_flag("nulls-last"),
multithreaded: true, multithreaded: true,
maintain_order: call.has_flag("maintain-order"),
}; };
let mut res = df let mut res = df

View File

@ -98,7 +98,12 @@ fn command(
let value = NuDataFrame::dataframe_into_value(res, call.head); let value = NuDataFrame::dataframe_into_value(res, call.head);
Ok(PipelineData::Value(value, None)) Ok(PipelineData::Value(value, None))
} }
_ => todo!(), _ => Err(ShellError::UnsupportedInput(
"Expected the dataframe to have a column".to_string(),
"".to_string(),
call.head,
call.head,
)),
} }
} }

View File

@ -41,7 +41,7 @@ impl Command for SetWithIndex {
description: "Set value in selected rows from series", description: "Set value in selected rows from series",
example: r#"let series = ([4 1 5 2 4 3] | dfr into-df); example: r#"let series = ([4 1 5 2 4 3] | dfr into-df);
let indices = ([0 2] | 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( result: Some(
NuDataFrame::try_from_columns(vec![Column::new( NuDataFrame::try_from_columns(vec![Column::new(
"0".to_string(), "0".to_string(),
@ -82,7 +82,7 @@ fn command(
let indices_value: Value = call let indices_value: Value = call
.get_flag(engine_state, stack, "indices")? .get_flag(engine_state, stack, "indices")?
.expect("required named value"); .expect("required named value");
let indices_span = indices_value.span()?; let indices_span = indices_value.span();
let indices = NuDataFrame::try_from_value(indices_value)?.as_series(indices_span)?; let indices = NuDataFrame::try_from_value(indices_value)?.as_series(indices_span)?;
let casted = match indices.dtype() { let casted = match indices.dtype() {
@ -123,8 +123,9 @@ fn command(
let df = NuDataFrame::try_from_pipeline(input, call.head)?; let df = NuDataFrame::try_from_pipeline(input, call.head)?;
let series = df.as_series(call.head)?; let series = df.as_series(call.head)?;
let span = value.span();
let res = match value { let res = match value {
Value::Int { val, span } => { Value::Int { val, .. } => {
let chunked = series.i64().map_err(|e| { let chunked = series.i64().map_err(|e| {
ShellError::GenericError( ShellError::GenericError(
"Error casting to i64".into(), "Error casting to i64".into(),
@ -147,7 +148,7 @@ fn command(
NuDataFrame::try_from_series(vec![res.into_series()], call.head) NuDataFrame::try_from_series(vec![res.into_series()], call.head)
} }
Value::Float { val, span } => { Value::Float { val, .. } => {
let chunked = series.f64().map_err(|e| { let chunked = series.f64().map_err(|e| {
ShellError::GenericError( ShellError::GenericError(
"Error casting to f64".into(), "Error casting to f64".into(),
@ -170,7 +171,7 @@ fn command(
NuDataFrame::try_from_series(vec![res.into_series()], call.head) NuDataFrame::try_from_series(vec![res.into_series()], call.head)
} }
Value::String { val, span } => { Value::String { val, .. } => {
let chunked = series.utf8().map_err(|e| { let chunked = series.utf8().map_err(|e| {
ShellError::GenericError( ShellError::GenericError(
"Error casting to string".into(), "Error casting to string".into(),
@ -204,7 +205,7 @@ fn command(
"this value cannot be set in a series of type '{}'", "this value cannot be set in a series of type '{}'",
series.dtype() series.dtype()
), ),
Some(value.span()?), Some(span),
None, None,
Vec::new(), Vec::new(),
)), )),

View File

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

View File

@ -81,7 +81,7 @@ fn command(
let mask_value: Value = call let mask_value: Value = call
.get_flag(engine_state, stack, "mask")? .get_flag(engine_state, stack, "mask")?
.expect("required named value"); .expect("required named value");
let mask_span = mask_value.span()?; let mask_span = mask_value.span();
let mask = NuDataFrame::try_from_value(mask_value)?.as_series(mask_span)?; let mask = NuDataFrame::try_from_value(mask_value)?.as_series(mask_span)?;
let bool_mask = match mask.dtype() { let bool_mask = match mask.dtype() {
@ -105,9 +105,9 @@ fn command(
let df = NuDataFrame::try_from_pipeline(input, call.head)?; let df = NuDataFrame::try_from_pipeline(input, call.head)?;
let series = df.as_series(call.head)?; let series = df.as_series(call.head)?;
let span = value.span();
let res = match value { let res = match value {
Value::Int { val, span } => { Value::Int { val, .. } => {
let chunked = series.i64().map_err(|e| { let chunked = series.i64().map_err(|e| {
ShellError::GenericError( ShellError::GenericError(
"Error casting to i64".into(), "Error casting to i64".into(),
@ -130,7 +130,7 @@ fn command(
NuDataFrame::try_from_series(vec![res.into_series()], call.head) NuDataFrame::try_from_series(vec![res.into_series()], call.head)
} }
Value::Float { val, span } => { Value::Float { val, .. } => {
let chunked = series.f64().map_err(|e| { let chunked = series.f64().map_err(|e| {
ShellError::GenericError( ShellError::GenericError(
"Error casting to f64".into(), "Error casting to f64".into(),
@ -153,7 +153,7 @@ fn command(
NuDataFrame::try_from_series(vec![res.into_series()], call.head) NuDataFrame::try_from_series(vec![res.into_series()], call.head)
} }
Value::String { val, span } => { Value::String { val, .. } => {
let chunked = series.utf8().map_err(|e| { let chunked = series.utf8().map_err(|e| {
ShellError::GenericError( ShellError::GenericError(
"Error casting to string".into(), "Error casting to string".into(),
@ -185,7 +185,7 @@ fn command(
"this value cannot be set in a series of type '{}'", "this value cannot be set in a series of type '{}'",
series.dtype() series.dtype()
), ),
Some(value.span()?), Some(span),
None, None,
Vec::new(), Vec::new(),
)), )),

View File

@ -149,6 +149,7 @@ fn command(
closed_window: None, closed_window: None,
tu: None, tu: None,
tz: None, tz: None,
fn_params: None,
}; };
let res = match roll_type { let res = match roll_type {
RollType::Max => series.rolling_max(rolling_opts), RollType::Max => series.rolling_max(rolling_opts),

View File

@ -74,7 +74,7 @@ fn command(
let df = NuDataFrame::try_from_pipeline(input, call.head)?; let df = NuDataFrame::try_from_pipeline(input, call.head)?;
let other: Value = call.req(engine_state, stack, 0)?; let other: Value = call.req(engine_state, stack, 0)?;
let other_span = other.span()?; let other_span = other.span();
let other_df = NuDataFrame::try_from_value(other)?; let other_df = NuDataFrame::try_from_value(other)?;
let other_series = other_df.as_series(other_span)?; let other_series = other_df.as_series(other_span)?;

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