Compare commits

...

333 Commits
0.86.0 ... main

Author SHA1 Message Date
c74cff213e remove std clip (#11131)
follow up to
- https://github.com/nushell/nushell/pull/11097

related to
- https://github.com/nushell/nu_scripts/pull/674

> **Important**
> wait for in between Nushell 0.88.0 and 0.89.0

# Description
this PR removes the `std clip` command after it's been deprecated in
https://github.com/nushell/nushell/pull/11097 😋

# User-Facing Changes
`std clip` will no longer be available.

# Tests + Formatting

# After Submitting
2024-01-08 21:46:10 +02:00
2ea5819b02 Bump crate-ci/typos from 1.16.26 to 1.17.0
Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.16.26 to 1.17.0.
- [Release notes](https://github.com/crate-ci/typos/releases)
- [Changelog](https://github.com/crate-ci/typos/blob/master/CHANGELOG.md)
- [Commits](https://github.com/crate-ci/typos/compare/v1.16.26...v1.17.0)

---
updated-dependencies:
- dependency-name: crate-ci/typos
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-08 01:17:04 +00:00
1115190a49 Bump shadow-rs from 0.25.0 to 0.26.0
Bumps [shadow-rs](https://github.com/baoyachi/shadow-rs) from 0.25.0 to 0.26.0.
- [Release notes](https://github.com/baoyachi/shadow-rs/releases)
- [Changelog](https://github.com/baoyachi/shadow-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/baoyachi/shadow-rs/compare/v0.25.0...v0.26.0)

---
updated-dependencies:
- dependency-name: shadow-rs
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-08 01:06:59 +00:00
7132c5ad02 add wheres 2024-01-07 19:04:04 -06:00
1920ece759 fix: closure captures can also be constants (#11493)
<!--
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 evaluating a closure (in
`EvalRuntime::eval_row_condition_or_closure()`), we try to resolve the
closure's block's captures, but we only check if they're variables on
the stack. We need to also check if they are constants (see the logic in
`Stack::gather_captures()`).

fixes #10701
# 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.
-->
2024-01-07 12:51:39 +02:00
6f59abaf43 update reedline version to latest main (#11490)
# Description
Update reedline version to fix
https://github.com/nushell/nushell/issues/11399
2024-01-05 17:19:43 -06:00
5f7425a7b4 Xml errors fix (#11487)
# Description
Fixes #11264
This PR adds checks in `to xml` to output error for malformed xml
entries:
* With columns that are not one of `tag`, `attributes` or `content`
* With no `tag` when entry is not a string
* With `tag` that is not a string
This PR also replaces `attrs` with `attributes` in example and
extra_usage of `to xml` (column was originally named attrs and renamed
to attributes, but this was missed in docs)

# User-Facing Changes
`to xml` will produce error for conditions described above instead of
silently returning nothing

# Tests + Formatting
Added tests for `to xml` to check handling of malformed xml entries
2024-01-05 15:56:13 -06:00
1ab9ec3ebc Bump terminal_size to 0.3 (#11486)
# Description
Simplify the dependencies. There are two different versions of
`terminal_size` that nushell directly depends on.

Related: #8060
2024-01-05 10:19:46 -06:00
f2095ed0cc Fix cross building for target x86_64-pc-windows-gnu on linux (#11485)
# Description

Cross build for target `x86_64-pc-windows-gnu` fails on linux.

```console
nushell on  main [?] is 📦 v0.88.2 via 🦀 v1.77.0-nightly
❯ cargo build --target x86_64-pc-windows-gnu -p nu-system
   Compiling nu-system v0.88.2 (/data/source/nushell/crates/nu-system)
error[E0432]: unresolved import `chrono::Local`
   --> crates/nu-system/src/windows.rs:5:14
    |
5   | use chrono::{Local, NaiveDate};
    |              ^^^^^ no `Local` in the root
    |
note: found an item that was configured out
   --> /path/to/home/.cargo/registry/src/rsproxy.cn-0dccff568467c15b/chrono-0.4.31/src/lib.rs:537:17
    |
537 | pub use offset::Local;
    |                 ^^^^^
    = note: the item is gated behind the `clock` feature

error[E0412]: cannot find type `Local` in crate `chrono`
   --> crates/nu-system/src/windows.rs:68:46
    |
68  |     pub start_time: chrono::DateTime<chrono::Local>,
    |                                              ^^^^^ not found in `chrono`
    |
note: found an item that was configured out
   --> /path/to/home/.cargo/registry/src/rsproxy.cn-0dccff568467c15b/chrono-0.4.31/src/lib.rs:537:17
    |
537 | pub use offset::Local;
    |                 ^^^^^
    = note: the item is gated behind the `clock` feature

Some errors have detailed explanations: E0412, E0432.
For more information about an error, try `rustc --explain E0412`.
error: could not compile `nu-system` (lib) due to 2 previous errors
```
2024-01-05 07:31:38 -06:00
7e26b4fcc2 Bump sysinfo from 0.29 to 0.30 (#11484)
# Description
Bumps `sysinfo` to 0.30.

* Changelog
 https://github.com/GuillaumeGomez/sysinfo/blob/master/CHANGELOG.md#0304

# User-Facing Changes
N/A
2024-01-05 05:31:29 -06:00
ad95e4cc27 Refactor tests (using cococo instead of ^echo) (#11479)
- related PR: #11478 

# Description

Now we can use `nu --testbin cococo` instead of `^echo` to echo messages
to stdout in tests.

But `nu` treats parameters as its own flags when parameter starts with
`-`. So `^echo --foo='bar'` still use `^echo`.

# User-Facing Changes

(none)

# 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


# After Submitting

(none)
2024-01-05 11:40:56 +08:00
ee5a18167c Replace winapi with windows (#11481)
# Description
`winapi` is not actively maintained, use the Microsoft blessed `windows`
crate instead.

# User-Facing Changes
N/A
2024-01-04 11:17:19 -06:00
75c9e3e5df Try to fix riscv64 building by using unbuntu-latest (#11476)
Try to fix `riscv64gc-unknown-linux-gnu` building by using
`unbuntu-latest`
This PR should close https://github.com/nushell/nushell/issues/11452
The action should run without errors:
https://github.com/nushell/nightly/actions/runs/7394915358
2024-01-04 07:55:10 +08:00
77f10eb270 Fix the test which fails on windows (#11478)
- related PR: #11463

# Description

Currently, `commands::complete::basic` fails on Windows without git
bash.
This pr fixes it.

# User-Facing Changes

(none)

# Tests + Formatting

- [x] (on Windows) `cargo fmt --all -- --check` to check standard code
formatting (`cargo fmt --all` applies these changes)
- [x] (on Windows) `cargo clippy --workspace -- -D warnings -D
clippy::unwrap_used` to check that you're using the standard code style
- [x] (on Windows without git bash, Windows with git bash and Ubuntu)
`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))
- on my Windows with Japanese lang pack: 1 test still fails. (see
#11463)
- [x] (on Windows and Ubuntu) `cargo run -- -c "use std testing; testing
run-tests --path crates/nu-std"` to run the tests for the standard
library

# After Submitting

(none)
2024-01-03 07:22:43 -06:00
42bb42a2e1 Fix rm for symlinks pointing to directory on windows (issue #11461) (#11463)
<!--
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!
-->

- this PR closes #11461

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

Using `std::fs::remove_dir` instead of `std::fs::remove_file` when try
remove symlinks pointing to a directory on Windows.

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

none

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

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

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used` 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
> ```
-->

- [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))
- I got 2 test fails on my Windows devenv; these fails in main branch
too
- `commands::complete::basic` : passed on Ubuntu, failed on Windows (a
bug?)
- `commands::cp::copy_file_with_read_permission`: failed on Windows with
Japanese environment (This test refers error message, so that fails on
environments using a language except for english.)
- [x] `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library

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

This fix has no changes to user-facing interface.
2024-01-02 21:27:03 +08:00
f597380112 Bump lsp-types from 0.94.1 to 0.95.0 (#11457)
Bumps [lsp-types](https://github.com/gluon-lang/lsp-types) from 0.94.1
to 0.95.0.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/gluon-lang/lsp-types/blob/master/CHANGELOG.md">lsp-types's
changelog</a>.</em></p>
<blockquote>
<h2>v0.95.0 (2023-12-12)</h2>
<p><!-- raw HTML omitted --><!-- raw HTML omitted --></p>
<h3>v0.94.2 (2023-12-12)</h3>
<p><!-- raw HTML omitted --><!-- raw HTML omitted --></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="ccf64e2fb6"><code>ccf64e2</code></a>
chore: Release lsp-types version 0.95.0</li>
<li><a
href="bccf50c1c6"><code>bccf50c</code></a>
Update changelog</li>
<li><a
href="75cea03884"><code>75cea03</code></a>
chore: Release lsp-types version 0.94.2</li>
<li><a
href="4084a00cd1"><code>4084a00</code></a>
Update changelog</li>
<li><a
href="b588e166be"><code>b588e16</code></a>
Merge pull request <a
href="https://redirect.github.com/gluon-lang/lsp-types/issues/274">#274</a>
from lapce/inline-completion</li>
<li><a
href="3031a76c44"><code>3031a76</code></a>
Add support for textDocument/inlineCompletion</li>
<li><a
href="038577b0b5"><code>038577b</code></a>
doc: Update readme to request links to the spec for PRs</li>
<li><a
href="f106ccb584"><code>f106ccb</code></a>
Merge pull request <a
href="https://redirect.github.com/gluon-lang/lsp-types/issues/257">#257</a>
from ahlinc/init-work-done-token</li>
<li><a
href="730924021a"><code>7309240</code></a>
Merge pull request <a
href="https://redirect.github.com/gluon-lang/lsp-types/issues/259">#259</a>
from ebkalderon/fix-telemetry-event-params</li>
<li><a
href="a15daede51"><code>a15daed</code></a>
Merge pull request <a
href="https://redirect.github.com/gluon-lang/lsp-types/issues/264">#264</a>
from tage64/master</li>
<li>Additional commits viewable in <a
href="https://github.com/gluon-lang/lsp-types/compare/v0.94.1...v0.95.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=lsp-types&package-manager=cargo&previous-version=0.94.1&new-version=0.95.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>
2024-01-02 07:22:38 +08:00
b92b4120dc Bump crate-ci/typos from 1.16.25 to 1.16.26 (#11458)
Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.16.25
to 1.16.26.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/crate-ci/typos/releases">crate-ci/typos's
releases</a>.</em></p>
<blockquote>
<h2>v1.16.26</h2>
<h2>[1.16.26] - 2023-12-27</h2>
<h3>Fixes</h3>
<ul>
<li>Apply <code>extend-ignore-re</code> to file names in addition to
file content</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/crate-ci/typos/blob/master/CHANGELOG.md">crate-ci/typos's
changelog</a>.</em></p>
<blockquote>
<h2>[1.16.26] - 2023-12-27</h2>
<h3>Fixes</h3>
<ul>
<li>Apply <code>extend-ignore-re</code> to file names in addition to
file content</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="45a880d9f8"><code>45a880d</code></a>
chore: Release</li>
<li><a
href="1e55ede61c"><code>1e55ede</code></a>
docs: Update changelog</li>
<li><a
href="e32ec882ea"><code>e32ec88</code></a>
Merge pull request <a
href="https://redirect.github.com/crate-ci/typos/issues/886">#886</a>
from epage/olt</li>
<li><a
href="bf66cbd0b6"><code>bf66cbd</code></a>
fix(config): Apply extend-ignore-re to file names</li>
<li><a
href="a9afeef275"><code>a9afeef</code></a>
test(cli): Show extend-ignore on file names</li>
<li>See full diff in <a
href="https://github.com/crate-ci/typos/compare/v1.16.25...v1.16.26">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=crate-ci/typos&package-manager=github_actions&previous-version=1.16.25&new-version=1.16.26)](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>
2024-01-02 07:22:19 +08:00
de5ad5de19 Revert "Return external file completions if not empty (#10898)" (#11446)
<!--
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 reverts #10898 which breaks external completion.
Not having file completion fallback on empty result is **intentional**
as this indicates that there is nothing to complete at this position.
To have nushell fallback to file completion the external completer can
simply return *nothing*.


`NO RECORDS FOUND`:
```nushell
let external_completer = {|spans|
    []
}
```

Fallback to file completion:
```nushell
let external_completer = {|spans|
}
```

# 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-12-31 08:45:05 -06:00
64695cd67c bump rust toolchain to 1.73.0 (#11445)
This PR bumps the nushell rust toolchain from 1.72.1 to 1.73.0 since
1.75.0 was released recently.

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

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

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

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

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

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used` 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-12-30 10:41:27 -06:00
21b3eeed99 Allow spreading arguments to commands (#11289)
<!--
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!
-->

Finishes implementing https://github.com/nushell/nushell/issues/10598,
which asks for a spread operator in lists, in records, and when calling
commands.

# 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 will allow spreading arguments to commands (both internal and
external). It will also deprecate spreading arguments automatically when
passing to external commands.

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

- Users will be able to use `...` to spread arguments to custom/builtin
commands that have rest parameters or allow unknown arguments, or to any
external command
- If a custom command doesn't have a rest parameter and it doesn't allow
unknown arguments either, the spread operator will not be allowed
- Passing lists to external commands without `...` will work for now but
will cause a deprecation warning saying that it'll stop working in 0.91
(is 2 versions enough time?)

Here's a function to help with demonstrating some behavior:
```nushell
> def foo [ a, b, c?, d?, ...rest ] { [$a $b $c $d $rest] | to nuon }
```

You can pass a list of arguments to fill in the `rest` parameter using
`...`:
```nushell
> foo 1 2 3 4 ...[5 6]
[1, 2, 3, 4, [5, 6]]
```

If you don't use `...`, the list `[5 6]` will be treated as a single
argument:

```nushell
> foo 1 2 3 4 [5 6] # Note the double [[]]
[1, 2, 3, 4, [[5, 6]]]
```

You can omit optional parameters before the spread arguments:
```nushell
> foo 1 2 3 ...[4 5] # d is omitted here
[1, 2, 3, null, [4, 5]]
```

If you have multiple lists, you can spread them all:
```nushell
> foo 1 2 3 ...[4 5] 6 7 ...[8] ...[]
[1, 2, 3, null, [4, 5, 6, 7, 8]]
```

Here's the kind of error you get when you try to spread arguments to a
command with no rest parameter:

![image](https://github.com/nushell/nushell/assets/45539777/93faceae-00eb-4e59-ac3f-17f98436e6e4)

And this is the warning you get when you pass a list to an external now
(without `...`):


![image](https://github.com/nushell/nushell/assets/45539777/d368f590-201e-49fb-8b20-68476ced415e)


# 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 tests to cover the following cases:
- Spreading arguments to a command that doesn't have a rest parameter
(unexpected spread argument error)
- Spreading arguments to a command that doesn't have a rest parameter
*but* there's also a missing positional argument (missing positional
error)
- Spreading arguments to a command that doesn't have a rest parameter
but does allow unknown arguments, such as `exec` (allowed)
- Spreading a list literal containing arguments of the wrong type (parse
error)
- Spreading a non-list value, both to internal and external commands
- Having named arguments in the middle of rest arguments
- `explain`ing a command call that spreads its arguments

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

# Examples

Suppose you have multiple tables:
```nushell
let people = [[id name age]; [0 alice 100] [1 bob 200] [2 eve 300]]
let evil_twins = [[id name age]; [0 ecila 100] [-1 bob 200] [-2 eve 300]]
```

Maybe you often find yourself needing to merge multiple tables and want
a utility to do that. You could write a function like this:
```nushell
def merge_all [ ...tables ] { $tables | reduce { |it, acc| $acc | merge $it } }
```

Then you can use it like this:
```nushell
> merge_all ...([$people $evil_twins] | each { |$it| $it | select name age })
╭───┬───────┬─────╮
│ # │ name  │ age │
├───┼───────┼─────┤
│ 0 │ ecila │ 100 │
│ 1 │ bob   │ 200 │
│ 2 │ eve   │ 300 │
╰───┴───────┴─────╯
```

Except they had duplicate columns, so now you first want to suffix every
column with a number to tell you which table the column came from. You
can make a command for that:
```nushell
def select_and_merge [ --cols: list<string>, ...tables ] {
  let renamed_tables = $tables
    | enumerate
    | each { |it|
      $it.item | select $cols | rename ...($cols | each { |col| $col + ($it.index | into string) })
    };
  merge_all ...$renamed_tables
}
```
And call it like this:
```nushell
> select_and_merge --cols [name age] $people $evil_twins
╭───┬───────┬──────┬───────┬──────╮
│ # │ name0 │ age0 │ name1 │ age1 │
├───┼───────┼──────┼───────┼──────┤
│ 0 │ alice │  100 │ ecila │  100 │
│ 1 │ bob   │  200 │ bob   │  200 │
│ 2 │ eve   │  300 │ eve   │  300 │
╰───┴───────┴──────┴───────┴──────╯
```

---

Suppose someone's made a command to search for APT packages:

```nushell
# The main command
def search-pkgs [
    --install                   # Whether to install any packages it finds
    log_level: int              # Pretend it's a good idea to make this a required positional parameter
    exclude?: list<string>      # Packages to exclude
    repositories?: list<string> # Which repositories to look in (searches in all if not given)
    ...pkgs                     # Package names to search for
] {
  { install: $install, log_level: $log_level, exclude: ($exclude | to nuon), repositories: ($repositories | to nuon), pkgs: ($pkgs | to nuon) }
}
```

It has a lot of parameters to configure it, so you might make your own
helper commands to wrap around it for specific cases. Here's one
example:
```nushell
# Only look for packages locally
def search-pkgs-local [
    --install              # Whether to install any packages it finds
    log_level: int
    exclude?: list<string> # Packages to exclude
    ...pkgs                # Package names to search for
] {
  # All required and optional positional parameters are given
  search-pkgs --install=$install $log_level [] ["<local URI or something>"] ...$pkgs
}
```
And you can run it like this:
```nushell
> search-pkgs-local --install=false 5 ...["python2.7" "vim"]
╭──────────────┬──────────────────────────────╮
│ install      │ false                        │
│ log_level    │ 5                            │
│ exclude      │ []                           │
│ repositories │ ["<local URI or something>"] │
│ pkgs         │ ["python2.7", vim]           │
╰──────────────┴──────────────────────────────╯
```

One thing I realized when writing this was that if we decide to not
allow passing optional arguments using the spread operator, then you can
(mis?)use the spread operator to skip optional parameters. Here, I
didn't want to give `exclude` explicitly, so I used a spread operator to
pass the packages to install. Without it, I would've needed to do
`search-pkgs-local --install=false 5 [] "python2.7" "vim"` (explicitly
pass `[]` (or `null`, in the general case) to `exclude`). There are
probably more idiomatic ways to do this, but I just thought it was
something interesting.

If you're a virologist of the [xkcd](https://xkcd.com/350/) kind,
another helper command you might make is this:
```nushell
# Install any packages it finds
def live-dangerously [ ...pkgs ] {
  # One optional argument was given (exclude), while another was not (repositories)
  search-pkgs 0 [] ...$pkgs --install # Flags can go after spread arguments
}
```

Running it:
```nushell
> live-dangerously "git" "*vi*" # *vi* because I don't feel like typing out vim and neovim
╭──────────────┬─────────────╮
│ install      │ true        │
│ log_level    │ 0           │
│ exclude      │ []          │
│ repositories │ null        │
│ pkgs         │ [git, *vi*] │
╰──────────────┴─────────────╯
```

Here's an example that uses the spread operator more than once within
the same command call:
```nushell
let extras = [ chrome firefox python java git ]

def search-pkgs-curated [ ...pkgs ] {
  (search-pkgs
      1
      [emacs]
      ["example.com", "foo.com"]
      vim # A must for everyone!
      ...($pkgs | filter { |p| not ($p | str contains "*") }) # Remove packages with globs
      python # Good tool to have
      ...$extras
      --install=false
      python3) # I forget, did I already put Python in extras?
}
```

Running it:
```nushell
> search-pkgs-curated "git" "*vi*"
╭──────────────┬───────────────────────────────────────────────────────────────────╮
│ install      │ false                                                             │
│ log_level    │ 1                                                                 │
│ exclude      │ [emacs]                                                           │
│ repositories │ [example.com, foo.com]                                            │
│ pkgs         │ [vim, git, python, chrome, firefox, python, java, git, "python3"] │
╰──────────────┴───────────────────────────────────────────────────────────────────╯
```
2023-12-28 15:43:20 +08:00
a86a7e6c29 Allow http commands' automatic redirect-following to be disabled (#11329)
Intends to close #8920 

This PR suggests a new flag for the `http` commands, `--redirect-mode`,
which enables users to choose between different redirect handling modes.
The current behaviour of letting ureq silently follow redirects remains
the default, but two new options are introduced here, following the lead
of [JavaScript's `fetch`
API](https://developer.mozilla.org/en-US/docs/Web/API/fetch#redirect):
"manual", where any 3xx response to a request is simply returned as the
command's result, and "error", where any 3xx response causes a network
error like those caused by 4xx and 5xx responses.

This PR is a draft. Tests have not been added or run, the flag is
currently only implemented for the `http get` command, and design tweaks
are likely to be appropriate.

Most notably, it's not obvious to me whether a single flag which can
take one of three values is the nicest solution here.
We might instead consider two binary flags (like
`--no-following-redirects` and `--disallow-redirects`, although I'm bad
at naming things so I need help with that anyway), or completely drop
the "error" option if it's not deemed useful enough. (I personally think
it has some merit, especially since 4xx and 5xx responses are already
treated as errors by default; So this would allow users to treat only
immediate 2xx responses as success)

# User-facing changes
New options for the `http [method]` commands. Behaviour remains
unchanged when the command line flag introduced here is not used.


![image](https://github.com/nushell/nushell/assets/12228688/1eb89f14-7d48-4f41-8a3e-cc0f1bd0a4f8)
2023-12-28 15:26:34 +08:00
15421dc45e Fix the bug for "bytes remove --end" . (#11428)
This PR should close #11426 .

# Description
> ### Describe the bug
> When using the `--end` option of bytes remove, nushell panics if the
provided bytes don't exist. This doesn't seem to affect `bytes remove`
w/o flag or `bytes remove --all`.

# User-Facing Changes
Nushell doesn`t panic anymore.

# Tests + Formatting
Behavior before fixing the bug:
![nu-before
changes](https://github.com/UPB-CS-OpenSourceUpstream/nushell/assets/119429832/f9c26d88-8962-4f38-a373-ba436a26ca7c)
Behavior after fixing the bug:
![nu- after
changes](https://github.com/UPB-CS-OpenSourceUpstream/nushell/assets/119429832/0dd2b487-1696-45a6-9ea2-928cbd3a33a8)
2023-12-28 07:01:55 +08:00
9522052063 More specific errors for missing values in records (#11423)
# Description
Currently, when writing a record, if you don't give the value for a
field, the syntax error highlights the entire record instead of
pinpointing the issue. Here's some examples:

```nushell
> { a: 2, 3 } # Missing colon (and value)
Error: nu::parser::parse_mismatch

  × Parse mismatch during operation.
   ╭─[entry #2:1:1]
 1 │  { a: 2, 3 }
   ·  ─────┬─────
   ·       ╰── expected record
   ╰────

> { a: 2, 3: } # Missing value
Error: nu::parser::parse_mismatch

  × Parse mismatch during operation.
   ╭─[entry #3:1:1]
 1 │  { a: 2, 3: }
   ·  ──────┬─────
   ·        ╰── expected record
   ╰────

> { a: 2, 3 4 } # Missing colon
Error: nu::parser::parse_mismatch

  × Parse mismatch during operation.
   ╭─[entry #4:1:1]
 1 │  { a: 2, 3 4 }
   ·  ──────┬──────
   ·        ╰── expected record
   ╰────
```

In all of them, the entire record is highlighted red because an
`Expr::Garbage` is returned covering that whole span:


![image](https://github.com/nushell/nushell/assets/45539777/36660b50-23be-4353-b180-3f84eff3c220)

This PR is for highlighting only the part inside the record that could
not be parsed. If the record literal is big, an error message pointing
to the start of where the parser thinks things went wrong should help
people fix their code.

# User-Facing Changes
Below are screenshots of the new errors:

If there's a stray record key right before the record ends, it
highlights only that key and tells the user it expected a colon after
it:


![image](https://github.com/nushell/nushell/assets/45539777/94503256-8ea2-47dd-b69a-4b520c66f7b6)

If the record ends before the value for the last field was given, it
highlights the key and colon of that field and tells the user it
expected a value after the colon:


![image](https://github.com/nushell/nushell/assets/45539777/2f3837ec-3b35-4b81-8c57-706f8056ac04)

If there are two consecutive expressions without a colon between them,
it highlights everything from the second expression to the end of the
record and tells the user it expected a colon. I was tempted to add a
help message suggesting adding a colon in between, but that may not
always be the right thing to do.


![image](https://github.com/nushell/nushell/assets/45539777/1abaaaa8-1896-4909-bbb7-9a38cece5250)

# Tests + Formatting

# After Submitting
2023-12-27 10:15:12 +01:00
ba880277bf Remove unnecessary replace_in_variable (#11424)
# Description
`Expression::replace_in_variable` is only called in one place, and it is
called with `new_var_id` = `IN_VARIABLE_ID`. So, it ends up doing
nothing. E.g., adding `debug_assert_eq!(new_var_id, IN_VARIABLE_ID)` in
`replace_in_variable` does not trigger any panic.

# User-Facing Changes
Breaking change for `nu_protocol`.
2023-12-26 18:46:49 +01:00
40241e9be6 Revert "Bump reedline development version" (#11425)
Reverts nushell/nushell#11406

This PR https://github.com/nushell/reedline/pull/688 is causing clear
screens to happen at strange times. Documented here
https://github.com/nushell/nushell/pull/11406#issuecomment-1869591405
2023-12-26 09:08:32 -06:00
34f3da7150 Don't panic when http_client fails (#11422)
# Description

This PR makes `http_client` return `Result<ureq::Agent, ShellError>`, so
errors can be propagated to the caller.
2023-12-25 23:09:37 +08:00
534287ed65 Don't create a thread if stderr_stream is None (#11421)
# Description

There is no need to create a thread if `stderr_stream` is `None`.
2023-12-25 08:10:15 -06:00
913c2b8d1c Bump ical from 0.8.0 to 0.9.0 (#11419)
Bumps [ical](https://github.com/Peltoche/ical-rs) from 0.8.0 to 0.9.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/Peltoche/ical-rs/releases">ical's
releases</a>.</em></p>
<blockquote>
<h2>v0.9.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Add the github actions by <a
href="https://github.com/Peltoche"><code>@​Peltoche</code></a> in <a
href="https://redirect.github.com/Peltoche/ical-rs/pull/35">Peltoche/ical-rs#35</a></li>
<li>Use thiserror instead of failure by <a
href="https://github.com/Peltoche"><code>@​Peltoche</code></a> in <a
href="https://redirect.github.com/Peltoche/ical-rs/pull/36">Peltoche/ical-rs#36</a></li>
<li>Accept lowercase vCards by <a
href="https://github.com/link2xt"><code>@​link2xt</code></a> in <a
href="https://redirect.github.com/Peltoche/ical-rs/pull/37">Peltoche/ical-rs#37</a></li>
<li>Parse multiline attributes with tabs correctly by <a
href="https://github.com/FliegendeWurst"><code>@​FliegendeWurst</code></a>
in <a
href="https://redirect.github.com/Peltoche/ical-rs/pull/41">Peltoche/ical-rs#41</a></li>
<li>Ical serde by <a
href="https://github.com/daladim"><code>@​daladim</code></a> in <a
href="https://redirect.github.com/Peltoche/ical-rs/pull/44">Peltoche/ical-rs#44</a></li>
<li>Set the license to Apache 2 by <a
href="https://github.com/Peltoche"><code>@​Peltoche</code></a> in <a
href="https://redirect.github.com/Peltoche/ical-rs/pull/47">Peltoche/ical-rs#47</a></li>
<li>Update README.md by <a
href="https://github.com/Zearin"><code>@​Zearin</code></a> in <a
href="https://redirect.github.com/Peltoche/ical-rs/pull/51">Peltoche/ical-rs#51</a></li>
<li>Adding ical-output support by <a
href="https://github.com/migmedia"><code>@​migmedia</code></a> in <a
href="https://redirect.github.com/Peltoche/ical-rs/pull/49">Peltoche/ical-rs#49</a></li>
<li>Improve documentation of builders. by <a
href="https://github.com/migmedia"><code>@​migmedia</code></a> in <a
href="https://redirect.github.com/Peltoche/ical-rs/pull/52">Peltoche/ical-rs#52</a></li>
<li>Add access functions for properties by <a
href="https://github.com/reedts"><code>@​reedts</code></a> in <a
href="https://redirect.github.com/Peltoche/ical-rs/pull/53">Peltoche/ical-rs#53</a></li>
<li>Fix README by <a
href="https://github.com/westy92"><code>@​westy92</code></a> in <a
href="https://redirect.github.com/Peltoche/ical-rs/pull/55">Peltoche/ical-rs#55</a></li>
<li>Handle the case were a line contains non-utf8 characters by <a
href="https://github.com/Peltoche"><code>@​Peltoche</code></a> in <a
href="https://redirect.github.com/Peltoche/ical-rs/pull/57">Peltoche/ical-rs#57</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/link2xt"><code>@​link2xt</code></a> made
their first contribution in <a
href="https://redirect.github.com/Peltoche/ical-rs/pull/37">Peltoche/ical-rs#37</a></li>
<li><a
href="https://github.com/FliegendeWurst"><code>@​FliegendeWurst</code></a>
made their first contribution in <a
href="https://redirect.github.com/Peltoche/ical-rs/pull/41">Peltoche/ical-rs#41</a></li>
<li><a href="https://github.com/daladim"><code>@​daladim</code></a> made
their first contribution in <a
href="https://redirect.github.com/Peltoche/ical-rs/pull/44">Peltoche/ical-rs#44</a></li>
<li><a href="https://github.com/Zearin"><code>@​Zearin</code></a> made
their first contribution in <a
href="https://redirect.github.com/Peltoche/ical-rs/pull/51">Peltoche/ical-rs#51</a></li>
<li><a href="https://github.com/migmedia"><code>@​migmedia</code></a>
made their first contribution in <a
href="https://redirect.github.com/Peltoche/ical-rs/pull/49">Peltoche/ical-rs#49</a></li>
<li><a href="https://github.com/reedts"><code>@​reedts</code></a> made
their first contribution in <a
href="https://redirect.github.com/Peltoche/ical-rs/pull/53">Peltoche/ical-rs#53</a></li>
<li><a href="https://github.com/westy92"><code>@​westy92</code></a> made
their first contribution in <a
href="https://redirect.github.com/Peltoche/ical-rs/pull/55">Peltoche/ical-rs#55</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/Peltoche/ical-rs/compare/0.6.0...v0.9.0">https://github.com/Peltoche/ical-rs/compare/0.6.0...v0.9.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/Peltoche/ical-rs/commits/v0.9.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=ical&package-manager=cargo&previous-version=0.8.0&new-version=0.9.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-12-25 09:23:27 +08:00
aeffa188f0 Fix an infinite loop if the input stream and output stream are the same (#11384)
# Description

Fixes #11382 

# User-Facing Changes
* before

```console
nushell/test (109f629) [✘?]
❯ open hello.md
hello
nushell/test (109f629) [✘?]
❯ ls hello.md | get size
╭───┬─────╮
│ 0 │ 6 B │
╰───┴─────╯
nushell/test (109f629) [✘?]
❯ open --raw hello.md | prepend "world" | save --raw --force hello.md
^C
nushell/test (109f629) [✘?]
❯ ls hello.md | get size
╭───┬─────────╮
│ 0 │ 2.8 GiB │
╰───┴─────────╯
```

* after

```console
nushell/test on  fix_save [✘!?⇡]
❯ open hello.md | prepend "hello" | save --force hello.md
nushell/test on  fix_save [✘!?⇡]
❯ open --raw hello.md | prepend "hello" | save --raw --force ../test/hello.md
Error:   × pipeline input and output are same file
   ╭─[entry #4:1:1]
 1 │ open --raw hello.md | prepend "hello" | save --raw --force ../test/hello.md
   ·                                                           ────────┬───────
   ·                                                                   ╰── can't save output to '/data/source/nushell/test/hello.md' while it's being reading
   ╰────
  help: you should change output path


nushell/test on  fix_save [✘!?⇡]
❯ open hello | prepend "hello" | save --force hello
Error:   × pipeline input and output are same file
   ╭─[entry #5:1:1]
 1 │ open hello | prepend "hello" | save --force hello
   ·                                            ──┬──
   ·                                              ╰── can't save output to '/data/source/nushell/test/hello' while it's being reading
   ╰────
  help: you should change output path
```

# Tests + Formatting
Make sure you've run and fixed any issues with these commands:
- [x] add `commands::save::save_same_file_with_extension`
- [x] add `commands::save::save_same_file_without_extension`
- [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

# After Submitting
2023-12-24 23:29:23 +08:00
543a25599c Simplify the feature gates for stor commands (#11416)
All of them depend on feature `sqlite` so just conditionally `use` the
parent module.
2023-12-24 13:31:46 +01:00
7ad0e5541e Make polars deps optional for cargo test --all (#11415)
As `--workspace/--all` pulls in all crates in the workspace for `cargo
test --workspace` let's make sure that the `polars` family of
dependencies are also feature gated so they only build for `--features
dataframe`. The test modules themselves also depend on the feature.

Should speed up a bare `cargo test --workspace`
2023-12-24 13:12:31 +01:00
c1cc1c82cc Lock out new direct construction of Record (#11414)
# Description
With #11386 we don't have any nushell-internal code directly accessing
the `vals` field of `Record`, so let's make it private so everyone in
the future uses the checked ways guaranteeing matching cols/vals.

The `cols` feel has to remain pub for now as `rename` still directly
mutates this field. See #11020 for challenges for this refactor.

# Plugin-Author-Facing Changes
This is a breaking change for outside plugins that relied on the `pub`
fields.
2023-12-24 13:12:16 +01:00
b0b4c3dffd Check for clean repo after tests (#11409)
Goal: detect problems like adressed by #11407 or missing `Cargo.lock`
update early

Try to fail when there is a non clear `git status` message
2023-12-23 20:28:07 +01:00
f3de373c59 Bump reedline development version (#11406)
Fix for #11399
Provided by nushell/reedline#688
2023-12-23 20:08:37 +01:00
df1fecd2cb Fix sandboxing of redirection tests (#11407)
When running `cargo test --workspace` a file `crates/nu-command/a.txt`
remained which we also saw as an accidential additions in some commits.

Searching for `a.txt` narrowed it down that
`redirection_keep_exit_codes` was not sandboxed in a temporary directory
and created this file.

Went through redirection tests and placed them in a `Playground` to get
sandboxing `dirs` for `nu!(cwd:`.
For those tests where redirection fails and no file should be created
now I added a check that no file is created on accident.


- Sandbox `redirection_keep_exit_codes` test
- Sandbox `no_duplicate_redirection` test
- Check that no redirect file is created on error
- Sandbox `redirection_should_have_a_target` test
2023-12-23 20:01:20 +01:00
9620e27e4f fix: prevent greedy matching of directory names (#11403)
Fixes #11396

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

If a directory name is an exact match, the completer stops greedily
matching directories with the same prefix.

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

Completions should work as described in #11396.

# 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-12-23 00:06:00 -06:00
072ecec8ca Bump unsafe-libyaml from 0.2.9 to 0.2.10 (#11391) 2023-12-21 18:49:12 +00:00
748d82cec1 Bump windows from 0.48.0 to 0.52.0 (#11325)
# Description
Bump `windows` to 0.52.0 and fix `is_admin`

https://github.com/microsoft/windows-rs/pull/2476

# User-Facing Changes
N/A

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-21 18:49:15 +01:00
5e5d1ea81b Bump fancy-regex to single 0.12.0 version (#11389)
Supersedes #11039 that was broken due to dependabot not correctly taking
the workspace into account (this bug has been worked around in #11387)
2023-12-21 17:10:33 +01:00
bb570e42be Bump lscolors from 0.15.0 to 0.16.0 (#11359) 2023-12-21 16:08:19 +00:00
3a050864df Simplify SIGQUIT handling (#11381)
# Description
Simplifies `SIGQUIT` protection to a single `signal` ignore system call.

# User-Facing Changes
`SIGQUIT` is no longer blocked if nushell is in non-interactive mode
(signals should not be blocked in non-interactive mode).
Also a breaking API change for `nu_protocol`.

# Tests + Formatting
Should come after #11178 for testing.
2023-12-21 17:00:38 +01:00
8cfa96b4c0 Construct Records only through checked helpers (#11386)
# Description

Constructing the internals of `Record` without checking the lengths is
bad. (also incompatible with changes to how we store records)

- Use `Record::from_raw_cols_vals` in dataframe code
- Use `record!` macro in dataframe test
- Use `record!` in `nu-color-config` tests
- Stop direct record construction in `nu-command`
- Refactor table construction in `from nuon`

# User-Facing Changes
None

# Tests + Formatting
No new tests, updated tests in equal fashion
2023-12-21 16:48:15 +01:00
6f384da57e Make Call::get_flag_expr return Expression by ref (#11388)
# Description
A small refactor that eliminates some `Expression` cloning.

# User-Facing Changes
Breaking change for `nu_protocol`.
2023-12-21 16:42:07 +01:00
f8e63328d8 Expand the workspace members in Cargo.toml (#11387)
While the `cargo` tools will include crates we depend on in the
directory into the workspace, I observed dependabot not taking all of
our crates into account in its version bump attempts leading to
duplication of outside dependencies.

e.g.
- https://github.com/nushell/nushell/pull/11039
2023-12-21 16:41:31 +01:00
5d98a727ca Deprecate --flag: bool in custom command (#11365)
# Description
While #11057 is merged, it's hard to tell the difference between
`--flag: bool` and `--flag`, and it makes user hard to read custom
commands' signature, and hard to use them correctly.

After discussion, I think we can deprecate `--flag: bool` usage, and
encourage using `--flag` instead.

# User-Facing Changes
The following code will raise warning message, but don't stop from
running.
```nushell
❯ def florb [--dry-run: bool, --another-flag] { "aaa" };  florb
Error:   × Deprecated: --flag: bool
   ╭─[entry #7:1:1]
 1 │ def florb [--dry-run: bool, --another-flag] { "aaa" };  florb
   ·                       ──┬─
   ·                         ╰── `--flag: bool` is deprecated. Please use `--flag` instead, more info: https://www.nushell.sh/book/custom_commands.html
   ╰────

aaa
```

cc @kubouch 

# Tests + Formatting
Done

# After Submitting
- [ ] Add more information under
https://www.nushell.sh/book/custom_commands.html to indicate `--dry-run:
bool` is not allowed,
- [ ] remove `: bool` from custom commands between 0.89 and 0.90

---------

Co-authored-by: Antoine Stevan <44101798+amtoine@users.noreply.github.com>
2023-12-21 10:07:08 +01:00
109f629cb6 📝 Update str trim CLI help doc (#11383)
# Description
Hi! I updated the samples of `str trim` because there were repeated and
clarified the explanations

# User-Facing Changes
Yes! I send the details here:


![image](https://github.com/nushell/nushell/assets/30557287/e30a5612-4214-4365-8b83-7aefbc0ee825)

(`old` is version `88.1` not the latest main)

# Tests + Formatting
~~I ran `toolkit check pr` successfully~~

There was a tiny problem, a test I never touched now it's failing

```nu
(^echo a | complete) == {stdout: "a\n", exit_code: 0}
```
should output `true` but outputs `false`, both in my running `nu`
version and in my PR version
This make the test `nu-command::main commands::complete::basic` fail
located in `crates\nu-command\tests\commands\complete.rs`

# After Submitting
I'm not sure if I need to update nushell.github.io, some of the help is
auto-generated, but maybe not all?
I can file a PR if needed
2023-12-20 14:23:41 -06:00
ff6a67d293 Remove Expr::MatchPattern (#11367)
# Description
Following from #11356, it looks like `Expr::MatchPattern` is no longer
used in any way. This PR removes `Expr::MatchPattern` alongside
`Type::MatchPattern` and `SyntaxShape::MatchPattern`.

# User-Facing Changes
Breaking API change for `nu_protocol`.
2023-12-20 18:52:28 +01:00
03ae01f11e Bump itertools from 0.11.0 to 0.12.0 (#11360)
Bumps [itertools](https://github.com/rust-itertools/itertools) from
0.11.0 to 0.12.0.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/rust-itertools/itertools/blob/master/CHANGELOG.md">itertools's
changelog</a>.</em></p>
<blockquote>
<h2>0.12.0</h2>
<h3>Breaking</h3>
<ul>
<li>Made <code>take_while_inclusive</code> consume iterator by value (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/709">#709</a>)</li>
<li>Added <code>Clone</code> bound to <code>Unique</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/777">#777</a>)</li>
</ul>
<h3>Added</h3>
<ul>
<li>Added <code>Itertools::try_len</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/723">#723</a>)</li>
<li>Added free function <code>sort_unstable</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/796">#796</a>)</li>
<li>Added <code>GroupMap::fold_with</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/778">#778</a>,
<a
href="https://redirect.github.com/rust-itertools/itertools/issues/785">#785</a>)</li>
<li>Added <code>PeekNth::{peek_mut, peek_nth_mut}</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/716">#716</a>)</li>
<li>Added <code>PeekNth::{next_if, next_if_eq}</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/734">#734</a>)</li>
<li>Added conversion into <code>(Option&lt;A&gt;,Option&lt;B&gt;)</code>
to <code>EitherOrBoth</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/713">#713</a>)</li>
<li>Added conversion from <code>Either&lt;A, B&gt;</code> to
<code>EitherOrBoth&lt;A, B&gt;</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/715">#715</a>)</li>
<li>Implemented <code>ExactSizeIterator</code> for <code>Tuples</code>
(<a
href="https://redirect.github.com/rust-itertools/itertools/issues/761">#761</a>)</li>
<li>Implemented <code>ExactSizeIterator</code> for
<code>(Circular)TupleWindows</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/752">#752</a>)</li>
<li>Made <code>EitherOrBoth&lt;T&gt;</code> a shorthand for
<code>EitherOrBoth&lt;T, T&gt;</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/719">#719</a>)</li>
</ul>
<h3>Changed</h3>
<ul>
<li>Added missing <code>#[must_use]</code> annotations on iterator
adaptors (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/794">#794</a>)</li>
<li>Made <code>Combinations</code> lazy (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/795">#795</a>)</li>
<li>Made <code>Intersperse(With)</code> lazy (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/797">#797</a>)</li>
<li>Made <code>Permutations</code> lazy (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/793">#793</a>)</li>
<li>Made <code>Product</code> lazy (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/800">#800</a>)</li>
<li>Made <code>TupleWindows</code> lazy (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/602">#602</a>)</li>
<li>Specialized <code>Combinations::{count, size_hint}</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/729">#729</a>)</li>
<li>Specialized <code>CombinationsWithReplacement::{count,
size_hint}</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/737">#737</a>)</li>
<li>Specialized <code>Powerset::fold</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/765">#765</a>)</li>
<li>Specialized <code>Powerset::count</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/735">#735</a>)</li>
<li>Specialized <code>TupleCombinations::{count, size_hint}</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/763">#763</a>)</li>
<li>Specialized <code>TupleCombinations::fold</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/775">#775</a>)</li>
<li>Specialized <code>WhileSome::fold</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/780">#780</a>)</li>
<li>Specialized <code>WithPosition::fold</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/772">#772</a>)</li>
<li>Specialized <code>ZipLongest::fold</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/774">#774</a>)</li>
<li>Changed <code>{min, max}_set*</code> operations require
<code>alloc</code> feature, instead of <code>std</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/760">#760</a>)</li>
<li>Improved documentation of <code>tree_fold1</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/787">#787</a>)</li>
<li>Improved documentation of <code>permutations</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/724">#724</a>)</li>
<li>Fixed typo in documentation of <code>multiunzip</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/770">#770</a>)</li>
</ul>
<h3>Notable Internal Changes</h3>
<ul>
<li>Improved specialization tests (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/799">#799</a>,
<a
href="https://redirect.github.com/rust-itertools/itertools/issues/786">#786</a>,
<a
href="https://redirect.github.com/rust-itertools/itertools/issues/782">#782</a>)</li>
<li>Simplified implementation of <code>Permutations</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/739">#739</a>,
<a
href="https://redirect.github.com/rust-itertools/itertools/issues/748">#748</a>,
<a
href="https://redirect.github.com/rust-itertools/itertools/issues/790">#790</a>)</li>
<li>Combined
<code>Merge</code>/<code>MergeBy</code>/<code>MergeJoinBy</code>
implementations (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/736">#736</a>)</li>
<li>Simplified <code>Permutations::size_hint</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/739">#739</a>)</li>
<li>Fix wrapping arithmetic in benchmarks (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/770">#770</a>)</li>
<li>Enforced <code>rustfmt</code> in CI (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/751">#751</a>)</li>
<li>Disallowed compile warnings in CI (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/720">#720</a>)</li>
<li>Used <code>cargo hack</code> to check MSRV (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/754">#754</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="98ecabb47d"><code>98ecabb</code></a>
chore: Release itertools version 0.12.0</li>
<li><a
href="22fc427ac5"><code>22fc427</code></a>
prepare v0.12.0 release</li>
<li><a
href="6d291786a9"><code>6d29178</code></a>
Document the field <code>a_cur</code> of <code>Product</code></li>
<li><a
href="bf2b0129d1"><code>bf2b012</code></a>
Better <code>Product::size_hint</code></li>
<li><a
href="8d07f6b856"><code>8d07f6b</code></a>
Make <code>Product</code> lazy</li>
<li><a
href="d7e6bab9fd"><code>d7e6bab</code></a>
Document the field <code>peek</code> of
<code>IntersperseWith</code></li>
<li><a
href="9b01a11891"><code>9b01a11</code></a>
Make <code>IntersperseWith</code> lazy</li>
<li><a
href="4f22173b93"><code>4f22173</code></a>
Refactor <code>IntersperseWith::next</code></li>
<li><a
href="b76172b412"><code>b76172b</code></a>
chore: adjust docs to reflect discussion in the PR</li>
<li><a
href="955927f6c4"><code>955927f</code></a>
chore: fixup docs of tree_fold1</li>
<li>Additional commits viewable in <a
href="https://github.com/rust-itertools/itertools/compare/v0.11.0...v0.12.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=itertools&package-manager=cargo&previous-version=0.11.0&new-version=0.12.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-12-20 22:58:07 +08:00
697f3c03f1 enable flag value type checking (#11311)
# Description
Fixes: #11310

# User-Facing Changes
After the change, the following code will go to error:
```nushell
> def a [--x: int = 3] { "aa" }
> let y = "aa"
> a --x=$y
Error: nu::parser::type_mismatch

  × Type mismatch.
   ╭─[entry #32:2:1]
 2 │ let y = "aa"
 3 │ a --x=$y
   ·       ─┬
   ·        ╰── expected int, found string
   ╰────
```
2023-12-20 11:07:19 +01:00
1cecb37628 Bump shadow-rs from 0.24.1 to 0.25.0 (#11282)
Bumps [shadow-rs](https://github.com/baoyachi/shadow-rs) from 0.24.1 to
0.25.0.
<details>
<summary>Commits</summary>
<ul>
<li><a
href="f08828be45"><code>f08828b</code></a>
Update Cargo.toml</li>
<li><a
href="a3cc1a118f"><code>a3cc1a1</code></a>
Update README.md</li>
<li><a
href="96fdafc738"><code>96fdafc</code></a>
Merge pull request <a
href="https://redirect.github.com/baoyachi/shadow-rs/issues/144">#144</a>
from baoyachi/wasm_example</li>
<li><a
href="24d3bd82c0"><code>24d3bd8</code></a>
fix</li>
<li><a
href="aab9bf2d4d"><code>aab9bf2</code></a>
Update check.yml</li>
<li><a
href="1d4e455730"><code>1d4e455</code></a>
add wasm example</li>
<li>See full diff in <a
href="https://github.com/baoyachi/shadow-rs/compare/v0.24.1...v0.25.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=shadow-rs&package-manager=cargo&previous-version=0.24.1&new-version=0.25.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-12-20 17:49:03 +08:00
89436e978b add special emoji handling for debug --raw (#11368)
# Description

This PR add special handling in `debug -r` for emoji's so that it prints
the code points.

### Before
```nushell
❯ emoji --list | where name =~ farmer | reject utf8_bytes | get 0.emoji | debug -r
String {
    val: "🧑\u{200d}🌾",
    internal_span: Span {
        start: 0,
        end: 0,
    },
}
```

### After
```nushell
❯ emoji --list | where name =~ farmer | reject utf8_bytes | get 0.emoji | debug -r
String {
    val: "\\u{1f9d1}\\u{200d}\\u{1f33e}",
    internal_span: Span {
        start: 0,
        end: 0,
    },
}
```

# 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-12-19 13:09:31 -06:00
cd0a52cf00 Fix build for BSDs (#11372)
# Description
This PR fixes build for BSD variants (including FreeBSD and NetBSD). 

Currently, `procfs` only support linux, android and l4re, and
0cba269d80 only adds support for NetBSD,
this PR should work on all BSD variants.


b153b782a5/procfs/build.rs (L4-L8)

Fixes #11373 

# User-Facing Changes
* before

```console
nibon7@fbsd /d/s/nushell ((70f7db14))> cargo build
   Compiling tempfile v3.8.1
   Compiling procfs v0.16.0
   Compiling toml_edit v0.21.0
   Compiling native-tls v0.2.11
error: failed to run custom build command for `procfs v0.16.0`

Caused by:
  process didn't exit successfully: `/data/source/nushell/target/debug/build/procfs-d59599f40f32f0d5/build-script-build` (exit status: 1)
  --- stderr
  Building procfs on an for a unsupported platform. Currently only linux and android are supported
  (Your current target_os is freebsd)
warning: build failed, waiting for other jobs to finish...
```

* after

```console
nushell on  bsd [✘!?] is 📦 v0.88.2 via 🦀 v1.74.1
❯ version
╭────────────────────┬───────────────────────────────────────────╮
│ version            │ 0.88.2                                    │
│ branch             │ bsd                                       │
│ commit_hash        │ 151edef186  │
│ build_os           │ freebsd-x86_64                            │
│ build_target       │ x86_64-unknown-freebsd                    │
│ rust_version       │ rustc 1.74.1 (a28077b28 2023-12-04)       │
│ rust_channel       │ stable-x86_64-unknown-freebsd             │
│ cargo_version      │ cargo 1.74.1 (ecb9851af 2023-10-18)       │
│ build_time         │ 2023-12-19 10:12:15 +00:00                │
│ build_rust_channel │ debug                                     │
│ allocator          │ mimalloc                                  │
│ features           │ default, extra, sqlite, trash, which, zip │
│ installed_plugins  │                                           │
╰────────────────────┴───────────────────────────────────────────╯
nushell on  bsd [✘!?] is 📦 v0.88.2 via 🦀 v1.74.1
❯ cargo test --workspace commands::ulimit e>> /dev/null | rg ulimit
test commands::ulimit::limit_set_filesize2 ... ok
test commands::ulimit::limit_set_filesize1 ... ok
test commands::ulimit::limit_set_hard1 ... ok
test commands::ulimit::limit_set_hard2 ... ok
test commands::ulimit::limit_set_invalid1 ... ok
test commands::ulimit::limit_set_invalid3 ... ok
test commands::ulimit::limit_set_invalid4 ... ok
test commands::ulimit::limit_set_invalid5 ... ok
test commands::ulimit::limit_set_soft2 ... ok
test commands::ulimit::limit_set_soft1 ... ok
nushell on  bsd [✘!?] is 📦 v0.88.2 via 🦀 v1.74.1
```


# 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-12-19 08:58:45 -06:00
c6043eb500 improve completions of use and overlay use (#11330)
# Description
this PR is two-fold
- make `use` and `overlay use` use the same completion algorithm in
48f29b633
- list directory modules in completions of both with 402acde5c

# User-Facing Changes
i currently have the following in my `NU_LIB_DIRS`
<details>
<summary>click to see the script</summary>

```nushell
for dir in $env.NU_LIB_DIRS {
    print $dir
    print (ls $dir --short-names | select name type)
}
```
</details>

```
/home/amtoine/.local/share/nupm/modules
#┬────────name────────┬type
0│nu-git-manager      │dir
1│nu-git-manager-sugar│dir
2│nu-hooks            │dir
3│nu-scripts          │dir
4│nu-themes           │dir
5│nupm                │dir
─┴────────────────────┴────

/home/amtoine/.config/nushell/overlays
#┬──name──┬type
0│ocaml.nu│file
─┴────────┴────
```

> **Note**
> all the samples below are run from the Nushell repo, i.e. a directory
with a `toolkit.nu` module

## before the changes
- `use` would give me `["ocaml.nu", "toolkit.nu"]` 
- `overlay use` would give me `[]` 

## after the changes
both commands give me
```nushell
[
    "nupm/",
    "ocaml.nu",
    "toolkit.nu",
    "nu-scripts/",
    "nu-git-manager/",
    "nu-git-manager-sugar/",
]
```

# Tests + Formatting
- adds a new `directory_completion/mod.nu` to the completion fixtures
- make sure `source-env`, `use` and `overlay-use` are all tested in the
_dotnu_ test
- fix all the other tests that use completions in the fixtures directory
for completions

# After Submitting
2023-12-19 17:14:34 +08:00
729373aba0 fix(cd): on android/termux fails to cd into /sdcard (#10329)
fix on android/termux fails to cd into /sdcard or any directory that
user has access via group

fixes #8095

I am not aware how this works on other platform so feel free to modify
this pr or even close it if it is not correct

# Description
on android or on linux to check if the user belongs to given directory
group, use `libc::getgroups` function

# User-Facing Changes
NA
2023-12-19 16:48:20 +08:00
f59a6990dc Refactor group-by with closure grouper (#11370)
# Description
Refactors `group_closure` in `group_by.rs` as suggested by the TODO
comment.
2023-12-19 15:48:37 +08:00
0f9094ead2 Bump crate-ci/typos from 1.16.24 to 1.16.25 (#11358)
Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.16.24
to 1.16.25.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/crate-ci/typos/releases">crate-ci/typos's
releases</a>.</em></p>
<blockquote>
<h2>v1.16.25</h2>
<h2>[1.16.25] - 2023-12-13</h2>
<h3>Fixes</h3>
<ul>
<li>Have correction in <code>extend-words</code> match the original
word's case</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/crate-ci/typos/blob/master/CHANGELOG.md">crate-ci/typos's
changelog</a>.</em></p>
<blockquote>
<h2>[1.16.25] - 2023-12-13</h2>
<h3>Fixes</h3>
<ul>
<li>Have correction in <code>extend-words</code> match the original
word's case</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="5bd389de71"><code>5bd389d</code></a>
chore: Release</li>
<li><a
href="8dbecf3e45"><code>8dbecf3</code></a>
docs: Update changelog</li>
<li><a
href="f8f8c6edf1"><code>f8f8c6e</code></a>
Merge pull request <a
href="https://redirect.github.com/crate-ci/typos/issues/884">#884</a>
from epage/custom</li>
<li><a
href="55d802d0ef"><code>55d802d</code></a>
fix(dict): Mirror original case for custom dict</li>
<li><a
href="86c4c9fb4a"><code>86c4c9f</code></a>
test(cli): Add reproduction case</li>
<li>See full diff in <a
href="https://github.com/crate-ci/typos/compare/v1.16.24...v1.16.25">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=crate-ci/typos&package-manager=github_actions&previous-version=1.16.24&new-version=1.16.25)](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-12-19 15:17:10 +08:00
70f7db14d4 Only run $env.PROMPT_COMMAND once per prompt (copy of #10986) (#11366)
<!--
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 is basically a copy of #10986 by @CAD97, which made
`$env.PROMPT_COMMAND` only run once per prompt, but @fdncred found an
issue where hitting Enter would make the transient prompt appear and be
immediately overwritten by the regular prompt, so it was
[reverted](https://github.com/nushell/nushell/pull/11340).
https://github.com/nushell/nushell/pull/10788 was also made to do the
same thing as #10986 but that ended up having the same issue. For some
reason, this branch doesn't have that problem, although I haven't
figured out why yet.

@CAD97, if you have any inputs or want to make your own PR, let me know.

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

When hitting enter, the prompt shouldn't blink in place anymore.

# 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-12-18 09:33:04 -06:00
pin
0cba269d80 Fix build on NetBSD (#11364)
- this PR should close #11354

# Description
Allow building on NetBSD.

# User-Facing Changes
NA
2023-12-18 06:41:27 -06:00
ec2593efb8 nu-cli repl get_command_finished_marker() does not need to be pub (#11362)
```rust
fn get_command_finished_marker
```
does not need to be public so just doing a little code cleanup
2023-12-17 20:20:31 -08:00
c2283596ac Rename extra's format to format pattern (#11355)
This removes the naming conflict, introduced by `fd77114` (#11334), when
the `extra` feature is enabled.
2023-12-17 17:32:34 -06:00
c9399f5142 Downgrade openssl-src to fix riscv64 build target, close #11345 (#11353) 2023-12-18 05:57:20 +08:00
c9c93f5b4d Remove Value::MatchPattern (#11356)
# Description
`Value::MatchPattern` implies that `MatchPattern`s are first-class
values. This PR removes this case, and commands must now instead use
`Expr::MatchPattern` to extract `MatchPattern`s just like how the
`match` command does using `Expr::MatchBlock`.

# User-Facing Changes
Breaking API change for `nu_protocol` crate.
2023-12-18 07:25:34 +13:00
2264682443 fix shell integration markers (#11352)
<!--
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 #11260 

# 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: my issue description was a bit wrong. Issue one can't be
reproduced without a config (`shell_integration` isn't on by default,
so..), however the issue itself is still valid

For issue 1, the default prompt needs to know about the
`shell_integration` config, and the markers are added around the default
prompt when that's on.

For issue 2, this is actually related to transient prompts. When
rendering, the markers weren't added like for normal prompts.

After the fix the output do now contain the proper markers:

Reproducing the minimum config here for convenience:

```nu
$env.config = {
    show_banner: false
    shell_integration: true
}
# $env.PROMPT_COMMAND = {|| "> " }
```

For issue 1, the output looks like: 
```
[2.3490236,"o","\u001b[?25l\u001b[21;1H\u001b[21;1H\u001b[J\u001b[38;5;10m\u001b]133;A\u001b\\/home/steven\u001b]133;B\u001b\\\u001b[38;5;14m\u001b[38;5;5m\u001b7\u001b[21;84H12/16/2023 03:31:58 PM\u001b8\u001b[0m\u001b[0m\u001b[1;36mecho\u001b[0m\u001b7\u001b8\u001b[?25h"]
[2.5676293,"o","\u001b[6n"]
[2.571353,"o","\u001b[?25l\u001b[21;1H\u001b[21;1H\u001b[J\u001b[38;5;10m\u001b]133;A\u001b\\\u001b]133;A\u001b\\/home/steven\u001b]133;B\u001b\\\u001b]133;B\u001b\\\u001b[38;5;14m\u001b[38;5;5m\u001b7\u001b[21;84H12/16/2023 03:31:59 PM\u001b8\u001b[0m\u001b[0m\u001b[1;36mecho\u001b[0m\u001b7\u001b8\u001b[?25h\u001b[21;1H\r\n\u001b[21;1H"]
[2.571436,"o","\u001b[?2004l"]
[2.5714657,"o","\u001b]133;C\u001b\\"]
```
in line 3, where enter is pressed, `133 A` and `B` are present.

Same for issue 2 (uncomment the `PROMPT_COMMAND` line in the config):
```
[1.9585224,"o","\u001b[?25l\u001b[21;1H\u001b[21;1H\u001b[J\u001b[38;5;10m\u001b]133;A\u001b\\> \u001b]133;B\u001b\\\u001b[38;5;14m\u001b[38;5;5m\u001b7\u001b[21;84H12/16/2023 03:32:15 PM\u001b8\u001b[0m\u001b[0m\u001b[1;36mecho\u001b[0m\u001b7\u001b8\u001b[?25h"]
[2.453972,"o","\u001b[6n"]
[2.4585786,"o","\u001b[?25l\u001b[21;1H\u001b[21;1H\u001b[J\u001b[38;5;10m\u001b]133;A\u001b\\\u001b]133;A\u001b\\> \u001b]133;B\u001b\\\u001b]133;B\u001b\\\u001b[38;5;14m\u001b[38;5;5m\u001b7\u001b[21;84H12/16/2023 03:32:15 PM\u001b8\u001b[0m\u001b[0m\u001b[1;36mecho\u001b[0m\u001b7\u001b8\u001b[?25h\u001b[21;1H\r\n\u001b[21;1H\u001b[?2004l\u001b]133;C\u001b\\\r\n\u001b]133;D;0\u001b\\\u001b]7;file://Aostro-5468/home/steven\u001b\\\u001b]2;~\u0007\u001b[?1l"]
[2.4669976,"o","\u001b[?2004h\u001b[6n"]
[2.4703515,"o","\u001b[6n"]
[2.4736586,"o","\u001b[?25l\u001b[21;1H\u001b[21;1H\u001b[J\u001b[38;5;10m\u001b]133;A\u001b\\> \u001b]133;B\u001b\\\u001b[38;5;14m\u001b[38;5;5m\u001b7\u001b[21;84H12/16/2023 03:32:15 PM\u001b8\u001b[0m\u001b[0m\u001b7\u001b8\u001b[?25h"]
```

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

None user facing changes other than that prompt markers are working

# 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-12-16 20:12:34 -06:00
247c33b6d6 Satisfy clippy lint in benchmark (#11350)
Fixes the two `clippy::let_and_return` lints in `benchmark.rs`.
2023-12-16 21:06:42 +01:00
a6da8ce769 Allow filesize type as a valid limit value (#11349)
# Description
This pr allow us to use `filesize` type as a valid limit value, which is
benefit for some file size based limits.

# User-Facing Changes
```console
/data/source/nushell> ulimit -f                                                                                                   
╭───┬─────────────────────────────────────────────────────┬───────────┬───────────╮
│ # │                     description                     │   soft    │   hard    │
├───┼─────────────────────────────────────────────────────┼───────────┼───────────┤
│ 0 │ Maximum size of files created by the shell (kB, -f) │ unlimited │ unlimited │
╰───┴─────────────────────────────────────────────────────┴───────────┴───────────╯
/data/source/nushell> ulimit -f 10Mib                                                                                           
/data/source/nushell> ulimit -f                                                                                                    
╭───┬─────────────────────────────────────────────────────┬───────┬───────╮
│ # │                     description                     │ soft  │ hard  │
├───┼─────────────────────────────────────────────────────┼───────┼───────┤
│ 0 │ Maximum size of files created by the shell (kB, -f) │ 10240 │ 10240 │
╰───┴─────────────────────────────────────────────────────┴───────┴───────╯
/data/source/nushell> ulimit -n                                                                                                 
╭───┬──────────────────────────────────────────────┬──────┬────────╮
│ # │                 description                  │ soft │  hard  │
├───┼──────────────────────────────────────────────┼──────┼────────┤
│ 0 │ Maximum number of open file descriptors (-n) │ 1024 │ 524288 │
╰───┴──────────────────────────────────────────────┴──────┴────────╯
/data/source/nushell> ulimit -n 10Mib                                                                                            
Error: nu:🐚:type_mismatch

  × Type mismatch.
   ╭─[entry #5:1:1]
 1 │ ulimit -n 10Mib
   ·             ─┬─
   ·              ╰── filesize is not compatible with resource RLIMIT_NOFILE
   ╰────
```

# Tests + Formatting
Make sure you've run and fixed any issues with these commands:

- [x] add `commands::ulimit::limit_set_filesize1`
- [x] add `commands::ulimit::limit_set_filesize2`
- [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
2023-12-16 09:56:03 -06:00
020e121391 Bubble up errors passed to complete (#11313)
Errors passed in `PipelineData::Value` get thrown in `complete` now.

Also added two simple tests for the command.

Fix #11187
Fix #10204
2023-12-16 09:07:08 -06:00
7d5bd0d6be Allow int type as a valid limit value (#11346)
# Description
This PR allows `int` type as a valid limit value for `ulimit`, so there
is no need to use `into string` to convert limit values in the tests.

# User-Facing Changes
N/A

# Tests + Formatting
Make sure you've run and fixed any issues with these commands:
- [x] add `commands::ulimit::limit_set_invalid3`
- [x] add `commands::ulimit::limit_set_invalid4`
- [x] add `commands::ulimit::limit_set_invalid5`
- [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
2023-12-16 08:55:44 -06:00
87717b9ddd Don't redraw prompt when transient prompt disabled (#10788)
# 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.
-->

moonlander pointed out in Discord that the transient prompt feature
added in release 0.86 (implemented in #10391) is causing the normal
prompt to be redrawn when the transient prompt variables are unset or
set to null. This PR is for fixing that, although it's more of a bandaid
fix. Maybe the transient prompt feature should be taken out entirely for
now so more thought can be given to its implementation.

Previously, I'd thought that when reedline redraws the prompt after a
command is entered, it's a whole new prompt, but apparently it's
actually the same prompt as the current line (?). So now, `nu_prompt` in
`repl.rs` is an `Arc<RwLock<NushellPrompt>>` (rather than just a
`NushellPrompt`), and this `Arc` is shared with the `TransientPrompt`
object so that if it can't find one of the `TRANSIENT_PROMPT_*`
variables, it uses a segment from `NushellPrompt` rather than
re-evaluate `PROMPT_COMMAND`, `PROMPT_COMMAND_RIGHT`, etc. Using an
`RwLock` means that there's a bunch of `.expect()`s all over the place,
which is not nice. It could perhaps be avoided with some changes on the
reedline side.

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

`$env.PROMPT_COMMAND` (and other such variables) should no longer be
executed twice if the corresponding `$env.TRANSIENT_PROMPT_*` variable
is not set.

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

# Steps to reproduce

Described by moonlander in Discord
[here](https://discord.com/channels/601130461678272522/614593951969574961/1164928022126792844).

Adding this to `env.nu` will result in `11` being added to
`/tmp/run_count` every time any command is run. The expected behavior is
a single `1` being added to `/tmp/run_count` instead of two. The prompt
command should not be executed again when the prompt is redrawn after a
command is executed.

```nu
$env.PROMPT_COMMAND = {||
  touch /tmp/run_count
  '1' | save /tmp/run_count --append
  '>'
}

# $env.TRANSIENT_PROMPT_COMMAND not set
```

If the following is added to `env.nu`, then `12` will be added to
`/tmp/run_count` every time any command is run, which is expected
behavior because the normal prompt command must be displayed the first
time the prompt is shown, then the transient prompt command is run when
the prompt is redrawn.
```nu
$env.TRANSIENT_PROMPT_COMMAND = {||
  touch /tmp/run_count
  '2' | save /tmp/run_count --append
  '>'
}
```

Here's a screenshot of what adding that first snippet looks like (`cargo
run` in the `main` branch):

![image](https://github.com/nushell/nushell/assets/45539777/b27a5c07-55b4-43c7-8a2c-0deba2d9d53a)


Here's a screenshot of what it looks like with this PR (only one `1` is
added to `/tmp/run_count` each time):

![image](https://github.com/nushell/nushell/assets/45539777/2b5c0a3a-8566-4428-9fda-1ffcc1dd6ae3)
2023-12-15 13:41:44 -06:00
3c6fac059e Properly update to the reedline repo patch (#11342)
Follow up to #11339
2023-12-15 20:16:36 +01:00
9092fc1b12 Revert "Only run $env.PROMPT_COMMAND once per prompt" (#11340)
Reverts nushell/nushell#10986

@CAD97 This isn't working right. I have a 2 line prompt with a transient
prompt. on enter, you see the transient prompt drawn and then the normal
prompt overwrites it.
2023-12-15 11:58:32 -06:00
5b557a888e update reedline to latest + include PR 675 for testing (#11339)
# Description

This PR updates to the latest reedline main branch which includes
reedline 27.1 and reedline PR
https://github.com/nushell/reedline/pull/675 for better resize behavior.

# 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-12-15 11:48:54 -06:00
398b756aee Make hover equal to help command (#11320)
# Description
Hi! A few days ago I changed the hover from `--ide-lsp` to match `help`
#11284, now this PR is doing the same but for the new `--lsp` server

I also did some tiny fixes to syntax, with some clippy `pedantic` lints

# User-Facing Changes

![image](https://github.com/nushell/nushell/assets/30557287/0e167dc8-777a-4961-8746-aa29f18eccfa)


# Tests + Formatting
 ran `toolkit check pr`
2023-12-15 11:39:19 -06:00
533c1a89af Only run $env.PROMPT_COMMAND once per prompt (#10986)
# Description

If `$env.TRANSIENT_PROMPT_COMMAND` is not set, use the prompt created by
`$env.PROMPT_COMMAND` instead of running the command a second time. As a
side effect, `$env.TRANSIENT_PROMPT_COMMAND` now runs after the hooks
`pre_prompt` and `env_change`, instead of before.

# User-Facing Changes

- `$env.PROMPT_COMMAND` gets run only once per prompt instead of twice
- `$env.TRANSIENT_PROMPT_COMMAND` now sees any environment set in a
`pre_prompt` or `env_change` hook, like `$env.PROMPT_COMMAND` does
2023-12-15 07:56:29 -06:00
84742275a1 Add ulimit command (#11324)
# Description
Add `ulimit` command to Nushell.

Closes #9563
Closes #3976

Related pr #11246

Reference:
https://github.com/fish-shell/fish-shell/blob/master/fish-rust/src/builtins/ulimit.rs
https://github.com/mirror/busybox/blob/master/shell/shell_common.c#L529

# User-Facing Changes
```
nushell on  ulimit is 📦 v0.88.2 via 🦀 v1.72.1                                                                                                [3/246]
❯ ulimit -a
╭────┬──────────────────────────────────────────────────────────────────────────┬───────────┬───────────╮
│  # │                               description                                │   soft    │   hard    │
├────┼──────────────────────────────────────────────────────────────────────────┼───────────┼───────────┤
│  0 │ Maximum size of core files created                              (kB, -c) │ unlimited │ unlimited │
│  1 │ Maximum size of a process's data segment                        (kB, -d) │ unlimited │ unlimited │
│  2 │ Controls of maximum nice priority                                   (-e) │         0 │         0 │
│  3 │ Maximum size of files created by the shell                      (kB, -f) │ unlimited │ unlimited │
│  4 │ Maximum number of pending signals                                   (-i) │     55273 │     55273 │
│  5 │ Maximum size that may be locked into memory                     (kB, -l) │      8192 │      8192 │
│  6 │ Maximum resident set size                                       (kB, -m) │ unlimited │ unlimited │
│  7 │ Maximum number of open file descriptors                             (-n) │      1024 │    524288 │
│  8 │ Maximum bytes in POSIX message queues                           (kB, -q) │       800 │       800 │
│  9 │ Maximum realtime scheduling priority                                (-r) │         0 │         0 │
│ 10 │ Maximum stack size                                              (kB, -s) │      8192 │ unlimited │
│ 11 │ Maximum amount of CPU time in seconds                      (seconds, -t) │ unlimited │ unlimited │
│ 12 │ Maximum number of processes available to the current user           (-u) │     55273 │     55273 │
│ 13 │ Maximum amount of virtual memory available to each process      (kB, -v) │ unlimited │ unlimited │
│ 14 │ Maximum number of file locks                                        (-x) │ unlimited │ unlimited │
│ 15 │ Maximum contiguous realtime CPU time                                (-y) │ unlimited │ unlimited │
╰────┴──────────────────────────────────────────────────────────────────────────┴───────────┴───────────╯
nushell on  ulimit is 📦 v0.88.2 via 🦀 v1.72.1
❯ ulimit -s
╭───┬─────────────────────────────┬──────┬───────────╮
│ # │         description         │ soft │   hard    │
├───┼─────────────────────────────┼──────┼───────────┤
│ 0 │ Maximum stack size (kB, -s) │ 8192 │ unlimited │
╰───┴─────────────────────────────┴──────┴───────────╯
nushell on  ulimit is 📦 v0.88.2 via 🦀 v1.72.1
❯ ulimit -s 100
nushell on  ulimit is 📦 v0.88.2 via 🦀 v1.72.1
❯ ulimit -s
╭───┬─────────────────────────────┬──────┬──────╮
│ # │         description         │ soft │ hard │
├───┼─────────────────────────────┼──────┼──────┤
│ 0 │ Maximum stack size (kB, -s) │  100 │  100 │
╰───┴─────────────────────────────┴──────┴──────╯
nushell on  ulimit is 📦 v0.88.2 via 🦀 v1.72.1
```

# Tests + Formatting
- [x] add commands::ulimit::limit_set_soft1
- [x] add commands::ulimit::limit_set_soft2
- [x] add commands::ulimit::limit_set_hard1
- [x] add commands::ulimit::limit_set_hard2
- [x] add commands::ulimit::limit_set_invalid1
- [x] add commands::ulimit::limit_set_invalid2
- [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
2023-12-15 07:11:17 -06:00
92d968b8c8 ♻️ Match --ide-hover with help command (#11284)
# Description
Hi! @fdncred pointed that the `help` command doesn't give the same
result as hovering a command in the VS Code extension. I digged out that
this trace back from `src/ide.rs`, so I decided to change this: (look at
the window of VS Code when hovering help)

![image](https://github.com/nushell/nushell/assets/30557287/32e24090-9238-423e-88ba-7dd6eb53d885)

into this:

![image](https://github.com/nushell/nushell/assets/30557287/51457cf7-4baf-4220-b901-66a78f7ee817)


# User-Facing Changes
The `--ide-hover` change a lot, by matching the `help` command of the
terminal nushell

The only missing part is the `subcommands` part

# Tests + Formatting
All good!

# After Submitting
2023-12-15 07:00:08 -06:00
50102bf69b Move history into their own module (#11308)
# Description

Since there are plans to add more history commands, it seems sensible to
put them into their own module and category

https://github.com/nushell/nushell/pull/10440#issuecomment-1731408785

# User-Facing Changes

The history commands are in the category "History" rather than "Misc"
2023-12-15 13:17:12 +01:00
156232fe08 disable directory submodule auto export (#11157)
should
- close https://github.com/nushell/nushell/issues/11133

# Description
to allow more freedom when writing complex modules, we are disabling the
auto-export of director modules.

the change was as simple as removing the crawling of files and modules
next to any `mod.nu` and update the standard library.

# User-Facing Changes
users will have to explicitely use `export module <mod>` to define
submodules and `export use <mod> <cmd>` to re-export definitions, e.g.
```nushell
# my-module/mod.nu
export module foo.nu     # export a submodule
export use bar.nu bar-1  # re-export an internal command

export def top [] {
    print "`top` from `mod.nu`"
}
```
```nushell
# my-module/foo.nu
export def "foo-1" [] {
    print "`foo-1` from `lib/foo.nu`"
}

export def "foo-2" [] {
    print "`foo-2` from `lib/foo.nu`"
}
```
```nushell
# my-module/bar.nu
export def "bar-1" [] {
    print "`bar-1` from `lib/bar.nu`"
}
```

# Tests + Formatting
i had to add `export module` calls in the `tests/modules/samples/spam`
directory module and allow the `not_allowed` module to not give an
error, it is just empty, which is fine.

# After Submitting
- mention in the release note
- update the following repos
```
#┬─────name─────┬version┬─type─┬─────────repo─────────
0│nu-git-manager│0.4.0  │module│amtoine/nu-git-manager
1│nu-scripts    │0.1.0  │module│amtoine/scripts       
2│nu-zellij     │0.1.0  │module│amtoine/zellij-layouts
3│nu-scripts    │0.1.0  │module│nushell/nu_scripts    
4│nupm          │0.1.0  │module│nushell/nupm          
─┴──────────────┴───────┴──────┴──────────────────────
```
2023-12-15 12:37:55 +01:00
0a3761a594 Bump zerocopy from 0.7.29 to 0.7.31 (#11336) 2023-12-15 10:40:56 +00:00
44dc890124 Polars Struct support without unsafe blocks (#11229)
Second attempt at polars Struct support. This version avoid using unsafe
checks by cloning the StructArray and utilizing the into_static to
convert to a StructOwned.

---------

Co-authored-by: Jack Wright <jack.wright@disqo.com>
2023-12-15 11:21:30 +01:00
6ead98effb Bump actions/setup-python from 4 to 5 (#11279)
Bumps [actions/setup-python](https://github.com/actions/setup-python)
from 4 to 5.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/actions/setup-python/releases">actions/setup-python's
releases</a>.</em></p>
<blockquote>
<h2>v5.0.0</h2>
<h2>What's Changed</h2>
<p>In scope of this release, we update node version runtime from node16
to node20 (<a
href="https://redirect.github.com/actions/setup-python/pull/772">actions/setup-python#772</a>).
Besides, we update dependencies to the latest versions.</p>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/setup-python/compare/v4.8.0...v5.0.0">https://github.com/actions/setup-python/compare/v4.8.0...v5.0.0</a></p>
<h2>v4.8.0</h2>
<h2>What's Changed</h2>
<p>In scope of this release we added support for GraalPy (<a
href="https://redirect.github.com/actions/setup-python/pull/694">actions/setup-python#694</a>).
You can use this snippet to set up GraalPy:</p>
<pre lang="yaml"><code>steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4 
  with:
    python-version: 'graalpy-22.3' 
- run: python my_script.py
</code></pre>
<p>Besides, the release contains such changes as:</p>
<ul>
<li>Trim python version when reading from file by <a
href="https://github.com/FerranPares"><code>@​FerranPares</code></a> in
<a
href="https://redirect.github.com/actions/setup-python/pull/628">actions/setup-python#628</a></li>
<li>Use non-deprecated versions in examples by <a
href="https://github.com/jeffwidman"><code>@​jeffwidman</code></a> in <a
href="https://redirect.github.com/actions/setup-python/pull/724">actions/setup-python#724</a></li>
<li>Change deprecation comment to past tense by <a
href="https://github.com/jeffwidman"><code>@​jeffwidman</code></a> in <a
href="https://redirect.github.com/actions/setup-python/pull/723">actions/setup-python#723</a></li>
<li>Bump <code>@​babel/traverse</code> from 7.9.0 to 7.23.2 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/actions/setup-python/pull/743">actions/setup-python#743</a></li>
<li>advanced-usage.md: Encourage the use actions/checkout@v4 by <a
href="https://github.com/cclauss"><code>@​cclauss</code></a> in <a
href="https://redirect.github.com/actions/setup-python/pull/729">actions/setup-python#729</a></li>
<li>Examples now use checkout@v4 by <a
href="https://github.com/simonw"><code>@​simonw</code></a> in <a
href="https://redirect.github.com/actions/setup-python/pull/738">actions/setup-python#738</a></li>
<li>Update actions/checkout to v4 by <a
href="https://github.com/dmitry-shibanov"><code>@​dmitry-shibanov</code></a>
in <a
href="https://redirect.github.com/actions/setup-python/pull/761">actions/setup-python#761</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/FerranPares"><code>@​FerranPares</code></a>
made their first contribution in <a
href="https://redirect.github.com/actions/setup-python/pull/628">actions/setup-python#628</a></li>
<li><a href="https://github.com/timfel"><code>@​timfel</code></a> made
their first contribution in <a
href="https://redirect.github.com/actions/setup-python/pull/694">actions/setup-python#694</a></li>
<li><a
href="https://github.com/jeffwidman"><code>@​jeffwidman</code></a> made
their first contribution in <a
href="https://redirect.github.com/actions/setup-python/pull/724">actions/setup-python#724</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/setup-python/compare/v4...v4.8.0">https://github.com/actions/setup-python/compare/v4...v4.8.0</a></p>
<h2>v4.7.1</h2>
<h2>What's Changed</h2>
<ul>
<li>Bump word-wrap from 1.2.3 to 1.2.4 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/actions/setup-python/pull/702">actions/setup-python#702</a></li>
<li>Add range validation for toml files by <a
href="https://github.com/dmitry-shibanov"><code>@​dmitry-shibanov</code></a>
in <a
href="https://redirect.github.com/actions/setup-python/pull/726">actions/setup-python#726</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/setup-python/compare/v4...v4.7.1">https://github.com/actions/setup-python/compare/v4...v4.7.1</a></p>
<h2>v4.7.0</h2>
<p>In scope of this release, the support for reading python version from
pyproject.toml was added (<a
href="https://redirect.github.com/actions/setup-python/pull/669">actions/setup-python#669</a>).</p>
<pre lang="yaml"><code>      - name: Setup Python
        uses: actions/setup-python@v4
&lt;/tr&gt;&lt;/table&gt; 
</code></pre>
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="0a5c615913"><code>0a5c615</code></a>
Update action to node20 (<a
href="https://redirect.github.com/actions/setup-python/issues/772">#772</a>)</li>
<li><a
href="0ae58361cd"><code>0ae5836</code></a>
Add example of GraalPy to docs (<a
href="https://redirect.github.com/actions/setup-python/issues/773">#773</a>)</li>
<li><a
href="b64ffcaf5b"><code>b64ffca</code></a>
update actions/checkout to v4 (<a
href="https://redirect.github.com/actions/setup-python/issues/761">#761</a>)</li>
<li><a
href="8d2896179a"><code>8d28961</code></a>
Examples now use checkout@v4 (<a
href="https://redirect.github.com/actions/setup-python/issues/738">#738</a>)</li>
<li><a
href="7bc6abb01e"><code>7bc6abb</code></a>
advanced-usage.md: Encourage the use actions/checkout@v4 (<a
href="https://redirect.github.com/actions/setup-python/issues/729">#729</a>)</li>
<li><a
href="e8111cec9d"><code>e8111ce</code></a>
Bump <code>@​babel/traverse</code> from 7.9.0 to 7.23.2 (<a
href="https://redirect.github.com/actions/setup-python/issues/743">#743</a>)</li>
<li><a
href="a00ea43da6"><code>a00ea43</code></a>
add fix for graalpy ci (<a
href="https://redirect.github.com/actions/setup-python/issues/741">#741</a>)</li>
<li><a
href="8635b1ccc5"><code>8635b1c</code></a>
Change deprecation comment to past tense (<a
href="https://redirect.github.com/actions/setup-python/issues/723">#723</a>)</li>
<li><a
href="f6cc428f53"><code>f6cc428</code></a>
Use non-deprecated versions in examples (<a
href="https://redirect.github.com/actions/setup-python/issues/724">#724</a>)</li>
<li><a
href="5f2af211d6"><code>5f2af21</code></a>
Add GraalPy support (<a
href="https://redirect.github.com/actions/setup-python/issues/694">#694</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/actions/setup-python/compare/v4...v5">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/setup-python&package-manager=github_actions&previous-version=4&new-version=5)](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-12-15 15:31:18 +08:00
d5f76c02f0 Bump crate-ci/typos from 1.16.23 to 1.16.24 (#11280)
Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.16.23
to 1.16.24.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/crate-ci/typos/releases">crate-ci/typos's
releases</a>.</em></p>
<blockquote>
<h2>v1.16.24</h2>
<h2>[1.16.24] - 2023-12-08</h2>
<h3>Fixes</h3>
<ul>
<li>Don't silently ignore config when there is an error in a field</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/crate-ci/typos/blob/master/CHANGELOG.md">crate-ci/typos's
changelog</a>.</em></p>
<blockquote>
<h2>[1.16.24] - 2023-12-08</h2>
<h3>Fixes</h3>
<ul>
<li>Don't silently ignore config when there is an error in a field</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="548ac37a5d"><code>548ac37</code></a>
chore: Release</li>
<li><a
href="a838b1820f"><code>a838b18</code></a>
chore: Release</li>
<li><a
href="44e4455f33"><code>44e4455</code></a>
docs: Update changelog</li>
<li><a
href="4362a6e5e4"><code>4362a6e</code></a>
Merge pull request <a
href="https://redirect.github.com/crate-ci/typos/issues/882">#882</a>
from epage/regex</li>
<li><a
href="1b92c0182c"><code>1b92c01</code></a>
fix(config): Propagate validation errors</li>
<li><a
href="632b256901"><code>632b256</code></a>
test: Demonstrate bad config bug</li>
<li><a
href="8dec26e3c6"><code>8dec26e</code></a>
Merge pull request <a
href="https://redirect.github.com/crate-ci/typos/issues/879">#879</a>
from epage/update</li>
<li><a
href="69f4b1eaff"><code>69f4b1e</code></a>
chore: Move off deprecated</li>
<li><a
href="cb9b485bd3"><code>cb9b485</code></a>
chore: Update from '_rust/main'</li>
<li><a
href="8c836eaa9d"><code>8c836ea</code></a>
Merge pull request <a
href="https://redirect.github.com/crate-ci/typos/issues/10">#10</a> from
epage/renovate/migrate-config</li>
<li>Additional commits viewable in <a
href="https://github.com/crate-ci/typos/compare/v1.16.23...v1.16.24">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=crate-ci/typos&package-manager=github_actions&previous-version=1.16.23&new-version=1.16.24)](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-12-15 15:31:04 +08:00
fd77114d82 Add format meta command (#11334) 2023-12-15 14:57:18 +08:00
78f52e8b66 Replace bash with POSIX sh in tests (#11293)
Just my small pet peeve. This allows to run tests without bash
installed.

There were only two minor tests which required a change.
2023-12-15 14:53:19 +08:00
5b01685fc3 Enforce required, optional, and rest positional arguments start with an uppercase and end with a period. (#11285)
# Description

This updates all the positional arguments (except with
`--features=dataframe` or `--features=extra`) to start with an uppercase
letter and end with a period.

Part of #5066, specifically [this
comment](/nushell/nushell/issues/5066#issuecomment-1421528910)

Some arguments had example data removed from them because it also
appears in the examples.

There are other inconsistencies in positional arguments I noticed while
making the tests pass which I will bring up in #5066.

# User-Facing Changes

Positional arguments are now consistent

# Tests + Formatting

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

# After Submitting

Automatic documentation updates
2023-12-15 14:32:37 +08:00
c2b684464f Bump version to 0.88.2 (#11333) 2023-12-14 13:55:48 -06:00
fd56768fdc Bump version to 0.88.1 (#11303) 2023-12-14 18:14:47 +01:00
070afa4528 Revert lock file changes due to openssl build fail (#11328)
A theoretically semver compatible version bump of dependencies in the
`Cargo.lock` was part of #11302. The particular upstream openSSL version
pulled in by that fails to build on our RISC-V build config (3.2.0)

- https://github.com/nushell/nushell/pull/11302#issuecomment-1856011363
-
https://github.com/nushell/nightly/actions/runs/7210339119/job/19643253780

So far no updated openssl release is available or it is unclear how the
runner needs to be configured to avoid the issue described in:

- https://github.com/openssl/openssl/issues/22871

Out of abundance of caution let's try to revert this version bump and
try to figure out a solution later, so we can ship our `0.88.1` patch
release.
2023-12-14 18:09:28 +01:00
23fec8eb0d Fix piping output logic (#11317)
# Description
Fixes: #11295

Sorry for introducing such issue.
The issue is caused by we wrongly set `redirect_stdout` and
`redirect_stderr` during eval, take the following as example:
```nushell
ls | bat --paging always
```
When running `bat --paging always`, `redirect_stdout` should be `false`.
But before this pr, it's set to true due to `ls` command, and then the
`true` value will go to all remaining commands.

# User-Facing Changes
NaN

# Tests + Formatting
Sorry I don't think we have a way to test it. Because it needs to be
tested on interactive command like `nvim`.

# After Submitting
NaN
2023-12-13 13:16:23 -06:00
c9841f67e9 fix-open-is-ambiguous (#11302)
# Description
Running `cargo install nu` on rustc 1.71.1 (eb26296b5 2023-08-03)
produced the following error message when reaching `nu-command v0.88.0`:
```sh
error[E0659]: `open` is ambiguous
  --> /home/antoine/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nu-command-0.88.0/src/stor/mod.rs:30:9
   |
30 | pub use open::StorOpen;
   |         ^^^^ ambiguous name
   |
   = note: ambiguous because of multiple potential import sources
   = note: `open` could refer to a crate passed with `--extern`
   = help: use `::open` to refer to this crate unambiguously
note: `open` could also refer to the module defined here
  --> /home/antoine/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nu-command-0.88.0/src/stor/mod.rs:12:1
   |
12 | mod open;
   | ^^^^^^^^^
   = help: use `self::open` to refer to this module unambiguously

   Compiling nu-cli v0.88.0
   Compiling nu-lsp v0.88.0
For more information about this error, try `rustc --explain E0659`.
error: could not compile `nu-command` (lib) due to previous error
warning: build failed, waiting for other jobs to finish...
error: failed to compile `nu v0.88.0`, intermediate artifacts can be found at `/tmp/cargo-installEUsfIr`
```

# User-Facing Changes
No user-facing changes.
2023-12-13 13:08:00 -06:00
76482cc1b2 Move stor commands to category Database (#11315)
Fixes #11309
2023-12-13 16:24:16 +01:00
d43f4253e8 Bump version for 0.88.0 release (#11298)
- [x] reedline
  - [x] released
  - [x] pinned
- [x] git dependency check
- [x] release notes
2023-12-13 06:31:14 +13:00
0fba08808c bump reedline dep to 0.27 (#11299)
<!--
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.
-->

# 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-12-13 06:30:58 +13:00
b3a52a247f 📝 Fix logical error in help glob (#11286) 2023-12-11 06:42:55 -06:00
4763801cb2 add nothing -> table to format date (#11290)
this will allow to run
```nushell
format date --list | get 0
```
and get
```
─────────────┬───────────────────────────────────────────────────────────
Specification│%Y
Example      │2023
Description  │The full proleptic Gregorian year, zero-padded to 4 digits.
─────────────┴───────────────────────────────────────────────────────────
```
instead of currently
```
Error: nu::parser::input_type_mismatch

  × Command does not support string input.
   ╭─[entry #2:1:1]
 1 │ format date --list | get 0
   ·                      ─┬─
   ·                       ╰── command doesn't support string input
   ╰────
```
2023-12-11 13:21:17 +01:00
ecb3b3a364 Ensure that command usage starts uppercase and ends period (#11278)
# Description

This repeats #8268 to make all command usage strings start with an
uppercase letter and end with a period per #5056

Adds a test to ensure that commands won't regress

Part of #5066

# User-Facing Changes

Command usage is now consistent

# Tests + Formatting

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

# After Submitting

Automatic documentation updates
2023-12-10 08:28:54 -06:00
3e5f81ae14 Convert remainder of ShellError variants to named fields (#11276)
# Description

Removed variants that are no longer in use:
* `NoFile*`
* `UnexpectedAbbrComponent`

Converted:
* `OutsideSpannedLabeledError`
* `EvalBlockWithInput`
* `Break`
* `Continue`
* `Return`
* `NotAConstant`
* `NotAConstCommand`
* `NotAConstHelp`
* `InvalidGlobPattern`
* `ErrorExpandingGlob`

Fixes #10700 

# User-Facing Changes

None

# Tests + Formatting

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

# After Submitting

N/A
2023-12-09 18:46:21 -06:00
ca05553fc6 Simplify clear implementation (#11273)
# Description
This PR uses the `crossterm` api to reimplement `clear` command, since
`crossterm` is cross-platform.
This seems to work on linux and windows.

# User-Facing Changes
N/A

# 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

# After Submitting
N/A
2023-12-09 15:24:19 -06:00
fa5d7babb9 Fix replacement closures for update, insert, and upsert (#11258)
# Description
This PR addresses #11204 which points out that using a closure for the
replacement value with `update`, `insert`, or `upsert` does not work for
lists.

# User-Facing Changes
- Replacement closures should now work for lists in `upsert`, `insert`,
and `update`. E.g., `[0] | update 0 {|i| $i + 1 }` now gives `[1]`
instead of an unhelpful error.
- `[1 2] | insert 4 20` no longer works. Before, this would give `[1, 2,
null, null, 20]`, but now it gives an error. This was done to match the
intended behavior in `Value::insert_data_at_cell_path`, whereas the
behavior before was probably unintentional. Following
`Value::insert_data_at_cell_path`, inserting at the end of a list is
also fine, so the valid indices for `upsert` and `insert` are
`0..=length` just like `Vec::insert` or list inserts in other languages.

# Tests + Formatting
Added tests for `upsert`, `insert`, and `update`:
- Replacement closures for lists, list streams, records, and tables
- Other list stream tests
2023-12-09 15:22:45 -06:00
94b27267fd 🐛 Fixes markdown formatting on LSP hover (#11253)
<!--
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! I was playing around and I fixed the formatting in the LSP hover. 
I _only tested in VS Code using Windows_, if anyone is capable, can you
test it on nvim or linux if it works properly? I think markdown
shouldn't have any problem

The link of the LSP meta issue just for reference #10941 
<!--
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
Now the LSP hovers markdown properly

![image](https://github.com/nushell/nushell/assets/30557287/7e824331-d9b1-40dd-957f-da77a21e97a2)

<!-- 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-12-08 12:30:13 -06:00
d1390ac95b Fix overlay_use_main_not_exported hanging when an external spam command exists (#11261)
# Description
The `spam` command is provided by
[opensp](https://openjade.sourceforge.net/) which causes
`overlay_use_main_not_exported` to hang. `opensp` is pulled by
`gnome-control-center` on my system.

[opensp package
list](https://archlinux.org/packages/extra/x86_64/opensp/files/)

```
opensp 1.5.2-10 File List

Package has 224 files and 14 directories.

[Back to Package](https://archlinux.org/packages/extra/x86_64/opensp/)

    usr/
    usr/bin/
    usr/bin/nsgmls
    usr/bin/onsgmls
    usr/bin/osgmlnorm
    usr/bin/ospam
    usr/bin/ospcat
    usr/bin/ospent
    usr/bin/osx
    usr/bin/sgml2xml
    usr/bin/sgmlnorm
    usr/bin/spam
    ...snip...
```

`cargo test` output
```
...snip...
test shell::pipeline::commands::internal::unlet_variable_in_parent_scope ... ok
test shell::pipeline::commands::internal::unlet_env_variable ... ok
test shell::pipeline::doesnt_break_on_utf8 ... ok
test shell::run_export_extern ... ok
test shell::run_script_that_looks_like_module ... ok
test shell::pipeline::commands::internal::can_process_one_row_from_internal_and_pipes_it_to_stdin_of_external ... ok
test shell::pipeline::commands::internal::variable_scoping::access_variables_in_scopes ... ok
test shell::run_in_login_mode ... ok
test shell::run_in_interactive_mode ... ok
test shell::run_in_noninteractive_mode ... ok
test shell::run_in_not_login_mode ... ok
test shell::pipeline::commands::internal::subexpression_properly_redirects ... ok
test shell::pipeline::commands::internal::subexpression_handles_dot ... ok
test shell::pipeline::commands::internal::takes_rows_of_nu_value_strings_and_pipes_it_to_stdin_of_external ... ok
test overlays::overlay_use_main_not_exported has been running for over 60 seconds
```
# User-Facing Changes
N/A

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



# After Submitting
N/A
2023-12-08 06:08:38 -06:00
d717e8faeb Add nu lib dirs default (#11248)
# Description

This PR is kind of two PRs in one because they were dependent on each
other.

PR1 -
3de58d4dc2
with update
7fcdb242d9
- This follows our mantra of having everything with defaults written in
nushell rust code. So, that if you run without a config, you get the
same behavior as with the default config/env files. This sets
NU_LIB_DIRS to $nu.config-path/scripts and sets NU_PLUGIN_DIRS to
$nu.config-path/plugins.

PR2 -
0e8ac876fd
- The benchmarks have been broke for some time and we didn't notice it.
This PR fixes that. It's dependent on PR1 because it was throwing errors
because PWD needed to be set to a valid folder and `$nu` did not exist
based on how the benchmark was setup.

I've tested the benchmarks and they run without error now and I've also
launched nushell as `nu -n --no-std-lib` and the env vars exist.

closes #11236

# 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-12-07 08:13:50 -06:00
a95a4505ef Convert Shellerror::GenericError to named fields (#11230)
# Description

Replace `.to_string()` used in `GenericError` with `.into()` as
`.into()` seems more popular

Replace `Vec::new()` used in `GenericError` with `vec![]` as `vec![]`
seems more popular

(There are so, so many)
2023-12-07 00:40:03 +01:00
b03f1efac4 Upgrade lsp-server Dependency (#11252)
The lsp-server crate has been released and thus it is now possible to
depend on this version rather on the git dependency of the crate.
2023-12-06 17:19:03 -06:00
5d5088b5d5 Match ++= capabilities with ++ (#11130)
Allow `++=` to work in all situations `++` does, namely for appending
single elements: `$list ++= 1`.

Resolve #11087

# Description

Bring `++=` to parity with `++`.

# User-Facing Changes

It is now possible to do `$list ++= 1` (appending a single element).
Similarly, this can be done:

```Nushell
~> mut a = [1]
~> $a ++= 2
~> a
╭───┬───╮
│ 0 │ 1 │
│ 1 │ 2 │
╰───┴───╯
```

# Tests + Formatting

Added two tests:

- `commands::assignment::append_assign::append_assign_single_element`
- `commands::assignment::append_assign::append_assign_to_single_element`
2023-12-07 05:46:37 +08:00
c1c73811d5 fix nu-std README (#11244)
related to
-
https://github.com/nushell/nushell/issues/10676#issuecomment-1842472941
from @suimong

# Description
the command in the `README.md` of `nu-std` should use `scope commands`
instead of `help commands`, which return an empty list.

# User-Facing Changes

# Tests + Formatting

# After Submitting
2023-12-06 16:26:02 +01:00
51bf8d9f6a Remove unnecessary boxing of Stack::recursion_count (#11238) 2023-12-06 10:48:56 +02:00
858c93d2e5 Fix highlighting of spread subexpressions in records (#11202)
<!--
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.
-->

It turns out that I left a bug in
[#11144](https://github.com/nushell/nushell/pull/11144/), which
introduced a spread operator in record literals. When highlighting
subexpressions that are spread inside records, the spread operator and
the token before it are insert twice. Currently, when you type `{ ...()
}`, this is what you'll see:


![image](https://github.com/nushell/nushell/assets/45539777/9a76647a-6bbe-426e-95bc-50becf2fa537)

With the PR, the behavior is as expected:


![image](https://github.com/nushell/nushell/assets/45539777/36bdab23-3252-4500-8317-51278da0e869)

I'm still not sure how `FlatShape` works, I just copied the existing
logic for flattening key-value pairs in records, so it's possible
there's still issues, but I haven't found any yet (tried spreading
subexpressions, variables, and records).

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

Highlighting for subexpressions spread inside records should no longer
be screwed up.

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

Is there any way to test flattening/syntax highlighting?

# 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-12-06 08:56:35 +08:00
31146a7591 Upgrading to polars 0.35 (#11241)
Co-authored-by: Jack Wright <jack.wright@disqo.com>
2023-12-05 18:09:34 -06:00
05d7d6d6ad Do not create help for wrapped command (#11235)
Pretty self-explanatory.  The commit is only one `if`.

Fix #11096
2023-12-05 13:04:36 -06:00
fb3350ebc3 Error on use path item1 item2, if item1 is not a module (#11183)
# Description
Fixes: #11143

# User-Facing Changes
Take the following as example:
```nushell
module foo { export def bar [] {}; export def baz [] {} }
```

`use foo bar baz` will be error:
```
❯ use foo c d
Error: nu::parser::wrong_import_pattern

  × Wrong import pattern structure.
   ╭─[entry #2:1:1]
 1 │ use foo c d
   ·           ┬
   ·           ╰── Trying to import something but the parent `c` is not a module, maybe you want to try `use <module> [<name1>, <name2>]`
   ╰────
```

# Tests + Formatting
Done
2023-12-05 11:38:45 +01:00
2ffe30ecf0 Respect non-zero exit code in subexpressions and blocks (#8984)
# Description

This PR changes the way we handled non-zero exit codes to be and early
exit between `foo; bar`. If `foo` in the example has a non-zero exit
code, `bar` wouldn't be run.

This also affects subexpressions.
2023-12-05 14:42:55 +08:00
f8dc3421b0 Bump actions-rust-lang/setup-rust-toolchain from 1.5.0 to 1.6.0 (#11223)
Bumps
[actions-rust-lang/setup-rust-toolchain](https://github.com/actions-rust-lang/setup-rust-toolchain)
from 1.5.0 to 1.6.0.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/actions-rust-lang/setup-rust-toolchain/blob/main/CHANGELOG.md">actions-rust-lang/setup-rust-toolchain's
changelog</a>.</em></p>
<blockquote>
<h2>[1.6.0] - 2023-12-04</h2>
<h3>Added</h3>
<ul>
<li>Allow disabling problem matchers (<a
href="https://redirect.github.com/actions-rust-lang/setup-rust-toolchain/issues/27">#27</a>)
This can be useful when having a matrix of jobs, that produce the same
errors.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="c7e1de2846"><code>c7e1de2</code></a>
Update CHANGELOG.md</li>
<li><a
href="24c9dd087b"><code>24c9dd0</code></a>
Merge pull request <a
href="https://redirect.github.com/actions-rust-lang/setup-rust-toolchain/issues/24">#24</a>
from obi1kenobi/patch-1</li>
<li><a
href="74a4154991"><code>74a4154</code></a>
Merge pull request <a
href="https://redirect.github.com/actions-rust-lang/setup-rust-toolchain/issues/27">#27</a>
from oxideai/feature/config-matcher</li>
<li><a
href="84ba0c9d1b"><code>84ba0c9</code></a>
Update README</li>
<li><a
href="51173b3da4"><code>51173b3</code></a>
feature(matcher): allow disabling problem matcher</li>
<li><a
href="33678a48c0"><code>33678a4</code></a>
Add docs for the <code>cachekey</code> output to the README</li>
<li><a
href="317ed62323"><code>317ed62</code></a>
Update example workflow in readme</li>
<li><a
href="8cb8f77172"><code>8cb8f77</code></a>
Merge pull request <a
href="https://redirect.github.com/actions-rust-lang/setup-rust-toolchain/issues/23">#23</a>
from actions-rust-lang/dependabot/github_actions/actio...</li>
<li><a
href="1f541c5b05"><code>1f541c5</code></a>
Bump actions/checkout from 3 to 4</li>
<li>See full diff in <a
href="https://github.com/actions-rust-lang/setup-rust-toolchain/compare/v1.5.0...v1.6.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions-rust-lang/setup-rust-toolchain&package-manager=github_actions&previous-version=1.5.0&new-version=1.6.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-12-05 10:42:40 +08:00
c1a30ac60f Reduce code duplication in eval.rs and eval_const.rs (#11192) 2023-12-04 21:13:47 +02:00
fc06afd051 feat: Add default docs for aliases, generated from the command they point to (#10825) 2023-12-04 20:56:46 +02:00
c9aa6ba0f3 Add special error for calling metadata on $env and $nu (#11228)
Trying to call `metadata $env` or `metadata $nu` will throw an error:

```Nushell
~> metadata $nu                                                                                                                            
Error:   × Built-in variables `$env` and `$nu` have no metadata
   ╭─[entry #1:1:1]
 1 │ metadata $nu
   ·          ─┬─
   ·           ╰── no metadata available
   ╰────
```
2023-12-04 12:49:36 -06:00
f8c82588b6 Explicitly indicate duplicate flags (#11226)
# Description
This PR adds an explicit indication for duplicate flags, which helps
with debugging.

# User-Facing Changes
N/A

# 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

# After Submitting
N/A
2023-12-04 22:06:27 +08:00
67eec92e76 Convert more ShellError variants to named fields (#11222)
# Description

Convert errors to named fields:
* NeedsPositiveValue
* MissingConfigValue
* UnsupportedConfigValue
* DowncastNotPossible
* NonUtf8Custom
* NonUtf8
* DidYouMeanCustom
* DidYouMean
* ReadingFile
* RemoveNotPossible
* ChangedModifiedTimeNotPossible
* ChangedAccessTimeNotPossible

Part of #10700
2023-12-04 10:19:32 +01:00
b227eea668 Add checks for ports (#11214)
# Description
This PR adds checks for ports. This fixes unexpected output similar to
the one in the comment
https://github.com/nushell/nushell/pull/11210#issuecomment-1837152357.

* before

```console
/data/source/nushell> port 65536 99999                                                                                        
41233
```

* after

```console
/data/source/nushell> port 65536 99999                                                                                             
Error: nu:🐚:cant_convert

  × Can't convert to u16.
   ╭─[entry #1:1:1]
 1 │ port 65536 99999
   ·      ──┬──
   ·        ╰── can't convert usize to u16
   ╰────
  help: out of range integral type conversion attempted (min: 0, max: 65535)
```

# User-Facing Changes
N/A

# Tests + Formatting
* [x] add `port_out_of_range` test

# After Submitting
N/A
2023-12-03 08:07:15 -06:00
58d002d469 expose argv[0] as $env.PROCESS_PATH (#11203)
closes #11059 

# Description
I'm not sure what the consensus was after discussing this in discord, so
I'm creating a PR as suggested

# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->
TBD
# Tests + Formatting
TBD
<!--
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
TBD
<!-- 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-12-02 11:36:02 -06:00
5d283755e3 Fix Option<&str> == Option<&String> w/ rust_decimal/rkyv feat (#11205)
Without this change, projects which depend on both nu-command and
rust_decimal's "rkyv" feature cause nu-command to fail to compile.

```toml
[dependencies]
nu-command = { path = "../nushell/crates/nu-command" }
rust_decimal = { version = "1", features = ["rkyv"] }
```

```console
error[E0277]: can't compare `std::option::Option<&str>` with `std::option::Option<&std::string::String>`
   --> nushell/crates/nu-command/src/filters/join.rs:367:35
    |
367 |         let k_shared = shared_key == Some(k);
    |                                   ^^ no implementation for `std::option::Option<&str> == std::option::Option<&std::string::String>`
    |
    = help: the trait `PartialEq<std::option::Option<&std::string::String>>` is not implemented for `std::option::Option<&str>`
    = help: the following other types implement trait `PartialEq<Rhs>`:
              <std::option::Option<Box<U>> as PartialEq<rkyv::niche::option_box::ArchivedOptionBox<T>>>
              <std::option::Option<T> as PartialEq>
              <std::option::Option<U> as PartialEq<rkyv::option::ArchivedOption<T>>>

For more information about this error, try `rustc --explain E0277`.
warning: `nu-command` (lib) generated 1 warning
error: could not compile `nu-command` (lib) due to previous error; 1 warning emitted
```
2023-12-02 18:19:15 +01:00
35e8db160d Fix get -i ignoring errors for only the first cellpath (#11213)
# Description
Fixes issue #11212 where only the first cellpath supplied to `get -i` is
treated as optional, and the rest of the cell paths are treated as
non-optional.

# Tests
Added one test.
2023-12-02 11:01:08 -06:00
7d8df4ba9e Fix capacity overflow caused by large range of ports (#11210)
<!--
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.
-->

Try to fix capacity overflow caused by large range of ports. 

```
$ port 1024 999999999999999999                                                                                 12/02/23 20:03:14 PM
thread 'main' panicked at 'capacity overflow', library/alloc/src/raw_vec.rs:524:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```

# 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-12-02 09:17:14 -06:00
f36c055c50 Fix span of invalid range (#11207)
<!--
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.
-->

Try to improve the error message of invalid range.

* before 

![Screenshot from 2023-12-02
08-45-23](https://github.com/nushell/nushell/assets/15247421/4d4e3533-b6c6-42c4-9f59-d4d30e4ad5c2)


* after

![Screenshot from 2023-12-02
13-18-34](https://github.com/nushell/nushell/assets/15247421/d380dced-4b60-4b1a-9992-9e0727e22054)


# 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-12-02 07:33:05 -06:00
76bdda1178 deprecate std testing (#11151)
# Description
this PR deprecates the `std testing` module in favor of Nupm.
the plan is to simply hide the module to the user but still use it
internally when running the tests so that
- users don't start to use this module and rather focus on Nupm
- devs don't have to install anything to run the tests locally, they can
just use `toolkit test stdlib` for instance

the deprecation message will be very similar to
https://github.com/nushell/nushell/pull/11097

> **Note**
> to demonstrate that the removal of such a command from the exposed
modules of `std` will be transparent and not require the user to install
anything, i have it [prepared in a branch based on this
PR](https://github.com/amtoine/nushell/compare/deprecate-std-testing...amtoine:nushell:hide-std-testing)
> running `toolkit test stdlib` will run the standard library tests
without an issue and yet `use std testing` won't work 👌

# User-Facing Changes
`std testing run-tests` will be removed in `0.90`

# Tests + Formatting

# After Submitting
2023-12-02 13:15:47 +01:00
5c07e82fc0 Remove list<any> -> list<any> (#11137)
this should
- close https://github.com/nushell/nushell/issues/11134

# Description
this is band-aid...
but it should address the issue in
https://github.com/nushell/nushell/issues/11134 until we have a better
long-term fix for this i/o types bug 😇

# User-Facing Changes
the following will now parse and run fine
```nushell
def get-initial-commit []: nothing -> string {
    ^git rev-list HEAD | lines | last
}
```

# Tests + Formatting

# After Submitting
2023-12-02 15:16:17 +08:00
6ea5bdcf47 Allow more types for input list (#11195)
`input list` now allows all types by using `into_string`.

Custom formatting logic for records was removed.

Allow ranges as an input types.

Also made the prompt check depend on option, so `input list ""` will
have an empty prompt, while `input list` does not.

Resolve #11181
2023-12-01 11:01:15 -06:00
15c7e1b725 Add OutOfBounds error (#11201)
<!--
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 is a continuation of #11190. Try to add `OutOfBounds` error. It
seems that `OutOfBounds` is more accurate than `InvalidRange`.


# 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-12-01 08:56:06 -06:00
e5d9f405db add some tests for stor create (#11194)
# Description

This is a PR to start adding a few tests to the `stor` commands. It
refactors the `stor create` command so it's easier to write tests.

# 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-11-30 15:00:47 -06:00
80881c75f9 When using redirection, if a command generates non-zero exit code, the script should stop running (#11191)
# Description
Fixes: #11153

To make sure scripts stop from running on non-zero exit code, we need to
invoke `might_consume_external_result` on
`PipelineData::ExternalStream`, so it can tell nushell if this command
exists with non-zero exit code.

And this pr also adjusts some test cases.

# User-Facing Changes
```nushell
^false out> /dev/null; print "ok"
```

After this pr, it shouldn't print ok.

# Tests + Formatting
Done
2023-11-30 18:52:02 +01:00
250ee62e16 Add boundary check for str index-of (#11190)
<!--
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 tries to fix #10774

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

![Screenshot from 2023-11-30
20-18-56](https://github.com/nushell/nushell/assets/15247421/4559e114-0757-4a73-91e7-c7536a8ce5f1)

![Screenshot from 2023-11-30
20-19-23](https://github.com/nushell/nushell/assets/15247421/30ab1b5a-3ec3-48a8-ae76-65721b650fcf)

* after

![Screenshot from 2023-11-30
20-21-04](https://github.com/nushell/nushell/assets/15247421/f34fd276-dccf-4328-b9d2-bf368b5b3ae5)

![Screenshot from 2023-11-30
20-20-39](https://github.com/nushell/nushell/assets/15247421/653e47d8-8d68-4ef3-adef-0865179c4f9b)

# 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-11-30 08:13:10 -06:00
54d73748e4 Remove file I/O from tests that don't need it (#11182)
# Description

This PR implements modifications to command tests that write unnecessary
json and csv to disk then load it with open, by using nuon literals
instead.

- Fixes #7189



# User-Facing Changes
None

# Tests + Formatting
This only affects existing tests, which still pass.
2023-11-29 23:21:34 +01:00
d08e254d16 Fix spans passed to external_completer (#11008)
close #10973
2023-11-29 23:17:06 +01:00
7f771babb7 Bump ureq from 2.8.0 to 2.9.1 (#11163) 2023-11-29 17:48:18 +00:00
b9b9eaaca5 Bump openssl from 0.10.59 to 0.10.60 (#11176) 2023-11-29 17:47:15 +00:00
0303d709e6 Spread operator in record literals (#11144)
Goes towards implementing #10598, which asks for a spread operator in
lists, in records, and when calling commands (continuation of #11006,
which only implements it in lists)

# Description
This PR is for adding a spread operator that can be used when building
records. Additional functionality can be added later.

Changes:

- Previously, the `Expr::Record` variant held `(Expression, Expression)`
pairs. It now holds instances of an enum `RecordItem` (the name isn't
amazing) that allows either a key-value mapping or a spread operator.
- `...` will be treated as the spread operator when it appears before
`$`, `{`, or `(` inside records (no whitespace allowed in between) (not
implemented yet)
- The error message for duplicate columns now includes the column name
itself, because if two spread records are involved in such an error, you
can't tell which field was duplicated from the spans alone

`...` will still be treated as a normal string outside records, and even
in records, it is not treated as a spread operator when not followed
immediately by a `$`, `{`, or `(`.

# User-Facing Changes
Users will be able to use `...` when building records.

```
> let rec = { x: 1, ...{ a: 2 } }
> $rec
╭───┬───╮
│ x │ 1 │
│ a │ 2 │
╰───┴───╯
> { foo: bar, ...$rec, baz: blah }
╭─────┬──────╮
│ foo │ bar  │
│ x   │ 1    │
│ a   │ 2    │
│ baz │ blah │
╰─────┴──────╯
```
If you want to update a field of a record, you'll have to use `merge`
instead:
```
> { ...$rec, x: 5 }
Error: nu:🐚:column_defined_twice

  × Record field or table column used twice: x
   ╭─[entry #2:1:1]
 1 │  { ...$rec, x: 5 }
   ·       ──┬─  ┬
   ·         │   ╰── field redefined here
   ·         ╰── field first defined here
   ╰────
> $rec | merge { x: 5 }
╭───┬───╮
│ x │ 5 │
│ a │ 2 │
╰───┴───╯
```

# Tests + Formatting

# After Submitting
2023-11-29 18:31:31 +01:00
0e1322e6d6 Forbid reserved variable names for function arguments (#11169)
Works for all arguments and flags. Because the signature parsing doesn't
give the spans, it is flags the entire signature.

Also added a constant with reserved variable names.

Fix #11158.
2023-11-29 18:29:07 +01:00
e290fa0e68 Add stor family of commands (#11170)
# Description

This PR adds the `stor` family of commands. These commands are meant to
create, open, insert, update, delete, reset data in an in-memory sqlite
database. This is really an experiment to see how creatively we can use
an in-memory database.

```
Usage:
  > stor

Subcommands:
  stor create - Create a table in the in-memory sqlite database
  stor delete - Delete a table or specified rows in the in-memory sqlite database
  stor export - Export the in-memory sqlite database to a sqlite database file
  stor import - Import a sqlite database file into the in-memory sqlite database
  stor insert - Insert information into a specified table in the in-memory sqlite database
  stor open - Opens the in-memory sqlite database
  stor reset - Reset the in-memory database by dropping all tables
  stor update - Update information in a specified table in the in-memory sqlite database

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

Input/output types:
  ╭─#─┬──input──┬─output─╮
  │ 0 │ nothing │ string │
  ╰───┴─────────┴────────╯
```

### Examples

## stor create
```nushell
❯ stor create --table-name nudb --columns {bool1: bool, int1: int, float1: float, str1: str, datetime1: datetime}
╭──────┬────────────────╮
│ nudb │ [list 0 items] │
╰──────┴────────────────╯
```
## stor insert
```nushell
❯ stor insert --table-name nudb --data-record {bool1: true, int1: 2, float1: 1.1, str1: fdncred, datetime1: 2023-04-17} 
╭──────┬───────────────╮
│ nudb │ [table 1 row] │
╰──────┴───────────────╯
```
## stor open
```nushell
❯ stor open | table -e 
╭──────┬────────────────────────────────────────────────────────────────────╮
│      │ ╭─#─┬id─┬bool1┬int1┬float1┬──str1───┬─────────datetime1──────────╮ │
│ nudb │ │ 0 │ 1 │   1 │  2 │ 1.10 │ fdncred │ 2023-04-17 00:00:00 +00:00 │ │
│      │ ╰───┴───┴─────┴────┴──────┴─────────┴────────────────────────────╯ │
╰──────┴────────────────────────────────────────────────────────────────────╯
```
## stor update
```nushell
❯ stor update --table-name nudb --update-record {str1: toby datetime1: 2021-04-17} --where-clause "bool1 = 1"
╭──────┬───────────────╮
│ nudb │ [table 1 row] │
╰──────┴───────────────╯
❯ stor open | table -e
╭──────┬─────────────────────────────────────────────────────────────────╮
│      │ ╭─#─┬id─┬bool1┬int1┬float1┬─str1─┬─────────datetime1──────────╮ │
│ nudb │ │ 0 │ 1 │   1 │  2 │ 1.10 │ toby │ 2021-04-17 00:00:00 +00:00 │ │
│      │ ╰───┴───┴─────┴────┴──────┴──────┴────────────────────────────╯ │
╰──────┴─────────────────────────────────────────────────────────────────╯
```
## insert another row
```nushell
❯ stor insert --table-name nudb --data-record {bool1: true, int1: 5, float1: 1.1, str1: fdncred, datetime1: 2023-04-17} 
╭──────┬────────────────╮
│ nudb │ [table 2 rows] │
╰──────┴────────────────╯
❯ stor open | table -e
╭──────┬────────────────────────────────────────────────────────────────────╮
│      │ ╭─#─┬id─┬bool1┬int1┬float1┬──str1───┬─────────datetime1──────────╮ │
│ nudb │ │ 0 │ 1 │   1 │  2 │ 1.10 │ toby    │ 2021-04-17 00:00:00 +00:00 │ │
│      │ │ 1 │ 2 │   1 │  5 │ 1.10 │ fdncred │ 2023-04-17 00:00:00 +00:00 │ │
│      │ ╰───┴───┴─────┴────┴──────┴─────────┴────────────────────────────╯ │
╰──────┴────────────────────────────────────────────────────────────────────╯
```
## stor delete (specific row(s))
```nushell
❯ stor delete --table-name nudb --where-clause "int1 == 5"
╭──────┬───────────────╮
│ nudb │ [table 1 row] │
╰──────┴───────────────╯
```
## insert multiple tables
```nushell
❯ stor create --table-name nudb1 --columns {bool1: bool, int1: int, float1: float, str1: str, datetime1: datetime}
╭───────┬────────────────╮
│ nudb  │ [table 1 row]  │
│ nudb1 │ [list 0 items] │
╰───────┴────────────────╯
❯ stor insert --table-name nudb1 --data-record {bool1: true, int1: 2, float1: 1.1, str1: fdncred, datetime1: 2023-04-17}
╭───────┬───────────────╮
│ nudb  │ [table 1 row] │
│ nudb1 │ [table 1 row] │
╰───────┴───────────────╯
❯ stor create --table-name nudb2 --columns {bool1: bool, int1: int, float1: float, str1: str, datetime1: datetime}
╭───────┬────────────────╮
│ nudb  │ [table 1 row]  │
│ nudb1 │ [table 1 row]  │
│ nudb2 │ [list 0 items] │
╰───────┴────────────────╯
❯ stor insert --table-name nudb2 --data-record {bool1: true, int1: 2, float1: 1.1, str1: fdncred, datetime1: 2023-04-17}
╭───────┬───────────────╮
│ nudb  │ [table 1 row] │
│ nudb1 │ [table 1 row] │
│ nudb2 │ [table 1 row] │
╰───────┴───────────────╯
```
## stor delete (specific table)
```nushell
❯ stor delete --table-name nudb1
╭───────┬───────────────╮
│ nudb  │ [table 1 row] │
│ nudb2 │ [table 1 row] │
╰───────┴───────────────╯
```
## stor reset (all tables are deleted)
```nushell
❯ stor reset
```
## stor export
```nushell
❯ stor export --file-name nudb.sqlite3
╭──────┬───────────────╮
│ nudb │ [table 1 row] │
╰──────┴───────────────╯
❯ open nudb.sqlite3 | table -e
╭──────┬────────────────────────────────────────────────────────────────────╮
│      │ ╭─#─┬id─┬bool1┬int1┬float1┬──str1───┬─────────datetime1──────────╮ │
│ nudb │ │ 0 │ 1 │   1 │  5 │ 1.10 │ fdncred │ 2023-04-17 00:00:00 +00:00 │ │
│      │ ╰───┴───┴─────┴────┴──────┴─────────┴────────────────────────────╯ │
╰──────┴────────────────────────────────────────────────────────────────────╯
❯ open nudb.sqlite3 | schema | table -e
╭────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│        │ ╭──────┬──────────────────────────────────────────────────────────────────────────────────────────────────╮ │
│ tables │ │      │ ╭───────────────┬──────────────────────────────────────────────────────────────────────────────╮ │ │
│        │ │ nudb │ │               │ ╭─#─┬─cid─┬───name────┬─────type─────┬─notnull─┬───────default────────┬─pk─╮ │ │ │
│        │ │      │ │ columns       │ │ 0 │ 0   │ id        │ INTEGER      │ 1       │                      │ 1  │ │ │ │
│        │ │      │ │               │ │ 1 │ 1   │ bool1     │ BOOLEAN      │ 0       │                      │ 0  │ │ │ │
│        │ │      │ │               │ │ 2 │ 2   │ int1      │ INTEGER      │ 0       │                      │ 0  │ │ │ │
│        │ │      │ │               │ │ 3 │ 3   │ float1    │ REAL         │ 0       │                      │ 0  │ │ │ │
│        │ │      │ │               │ │ 4 │ 4   │ str1      │ VARCHAR(255) │ 0       │                      │ 0  │ │ │ │
│        │ │      │ │               │ │ 5 │ 5   │ datetime1 │ DATETIME     │ 0       │ STRFTIME('%Y-%m-%d   │ 0  │ │ │ │
│        │ │      │ │               │ │   │     │           │              │         │ %H:%M:%f', 'NOW')    │    │ │ │ │
│        │ │      │ │               │ ╰─#─┴─cid─┴───name────┴─────type─────┴─notnull─┴───────default────────┴─pk─╯ │ │ │
│        │ │      │ │ constraints   │ [list 0 items]                                                               │ │ │
│        │ │      │ │ foreign_keys  │ [list 0 items]                                                               │ │ │
│        │ │      │ │ indexes       │ [list 0 items]                                                               │ │ │
│        │ │      │ ╰───────────────┴──────────────────────────────────────────────────────────────────────────────╯ │ │
│        │ ╰──────┴──────────────────────────────────────────────────────────────────────────────────────────────────╯ │
╰────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
```
## Using with `query db`
```nushell
❯ stor open | query db "select * from nudb"
╭─#─┬id─┬bool1┬int1┬float1┬──str1───┬─────────datetime1──────────╮
│ 0 │ 1 │   1 │  5 │ 1.10 │ fdncred │ 2023-04-17 00:00:00 +00:00 │
╰───┴───┴─────┴────┴──────┴─────────┴────────────────────────────╯
```
## stor import
```nushell
❯ stor open
# note, nothing is returned. there is nothing in memory, atm.
❯ stor import --file-name nudb.sqlite3
╭──────┬───────────────╮
│ nudb │ [table 1 row] │
╰──────┴───────────────╯
❯ stor open | table -e 
╭──────┬────────────────────────────────────────────────────────────────────╮
│      │ ╭─#─┬id─┬bool1┬int1┬float1┬──str1───┬─────────datetime1──────────╮ │
│ nudb │ │ 0 │ 1 │   1 │  5 │ 1.10 │ fdncred │ 2023-04-17 00:00:00 +00:00 │ │
│      │ ╰───┴───┴─────┴────┴──────┴─────────┴────────────────────────────╯ │
╰──────┴────────────────────────────────────────────────────────────────────╯
```

TODO:
- [x] `stor export` - Export a fully formed sqlite db file. 
- [x] `stor import` - Imports a specified sqlite db file.
- [x] Perhaps feature-gate it with the sqlite feature
- [x] Update `query db` to work with the in-memory database
- [x] Remove `open --in-memory`

# 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-11-29 08:02:46 -08:00
112306aab5 Revert "Adding support for Polars structs" (#11171)
Reverts nushell/nushell#10943

The current implementation of `arr_to_value` is unsound, as it allows
casts of arbitrary data to arbitrary types without being marked
`unsafe`.
The full safety requirements to perform both the cast and the following
unchecked access are not as clear that a simple change of `fn
arr_to_value` to `unsafe fn arr_to_value` could be blessed without
further investigation.

cc @ayax79
2023-11-29 16:33:27 +01:00
98952082ae Build nu-protocol docs with all features enabled (#11180)
# Description
Currently, `PluginSignature` does not appear on
[`docs.rs`](https://docs.rs/nu-protocol/latest/nu_protocol/index.html),
since it is behind the `plugin` feature which is not enabled by default.
This PR adds [metadata](https://docs.rs/about/metadata) to the
Cargo.toml to get `docs.rs` to build docs with all features enabled.
2023-11-29 16:17:22 +01:00
8386bc0919 Convert more ShellError variants to named fields (#11173)
# Description

Convert these ShellError variants to named fields:
* CreateNotPossible
* MoveNotPossibleSingle
* DirectoryNotFoundCustom
* DirectoryNotFound
* NotADirectory
* OutOfMemoryError
* PermissionDeniedError
* IOErrorSpanned
* IOError
* IOInterrupted

Also place the `span` field of `DirectoryNotFound` last to match other
errors.

Part of #10700 (almost half done!)

# User-Facing Changes

None

# Tests + Formatting

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

# After Submitting

N/A
2023-11-28 06:43:51 -06:00
182b0ab4fb add echo_env_mixed testbin to reduce windows only tests (#11172)
# Description
We have seen some test cases which requires to output message to both
stdout and stderr, especially in redirection scenario.

This pr is going to introduce a new echo_env_mixed testbin, so we can
have less tests which only runs on windows.

# User-Facing Changes
NaN

# Tests + Formatting
NaN

# After Submitting
NaN
2023-11-28 06:42:35 -06:00
fa83458a6d Add metadata to some filters (#11160)
<!--
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 PR preserves metadata when running some filters. As discussed on
discord that helps when running for example `ls | reject modified`
because it keeps colouring and links.
<!--
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-11-27 12:16:34 -06:00
54398f9546 Bump sysinfo to 0.29.11 (#11166)
I discovered [a condition in which `sysinfo` would
segfault](https://github.com/GuillaumeGomez/sysinfo/issues/1154),
thereby causing nushell to segfault when the `sys` command was run
(perhaps the cause of
[this](https://github.com/nushell/nushell/issues/10987)). The segfault
was fixed in `sysinfo`, I'm just bumping the version here.
2023-11-27 09:37:47 -06:00
077d1c8125 Support o>>, e>>, o+e>> to append output to an external file (#10764)
# Description
Close: #10278

This pr introduces `o>>`, `e>>`, `o+e>>` to allow redirection to append
to a file.
Examples:
```nushell
echo abc o>> a.txt
echo abc o>> a.txt
cat asdf e>> a.txt
cat asdf e>> a.txt
cat asdf o+e>> a.txt
```

~~TODO:~~
~~1. currently internal commands with `o+e>` redirect to a variable is
broken: `let x = "a.txt"; echo abc o+e> $x`, not sure when it was
introduced...~~
~~2. redirect stdout and stderr with append mode doesn't supported yet:
`cat asdf o>>a.txt e>>b.ext`~~

~~For these 2 items, I'd like to fix them in different prs.~~
Already done in this pr
2023-11-27 07:52:39 -06:00
1ff8c2d81d Cp target expansion (#11152)
# Description
This PR addresses issue with cp brough up on
[discord](https://discord.com/channels/601130461678272522/614593951969574961/1177669443917189130)
where target of cp is not correctly expanded.
If one has directory `test` with file `file.txt` in it then the
following command (in one line or inside a `do` block):
```nu
cd test; let file = 'copy.txt'; cp file.txt $file
```
will create a `copy.txt` in `.` not in `test` instead. This happens
because target of `cp` is a variable which is not expanded unlike a
string literal

# User-Facing Changes
`cp` will correctly parse realative target paths

# 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-11-25 09:42:20 -06:00
d77f1753c2 add shape ExternalResolved to show found externals via syntax highlighting in the repl (#11135)
# Description

This PR enables a new feature that shows which externals are found in
your path via the syntax highlighter as you type.

![external_resolved](https://github.com/nushell/nushell/assets/343840/e5fa91f0-6fac-485c-8afc-5711fc0ed9bc)

This idea could use some improvement where it caches the items in your
path and on some trigger, expires that cache and creates a new on. Right
now, all it does is call the `which` crate on every character you type.
This could be problematic if you have hundreds of paths in your PATH or
if some of your paths in your Path point to extraordinarily slow file
systems. WSL pointing to Windows comes to mind. Either way, I've thrown
it up here for people to try and provide feedback. I think the novelty
of showing what is valid and what isn't is pretty cool. I believe
fish-shell also does this, IIRC.

# 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-11-25 09:42:05 -06:00
85c6047b71 fix the link to the nu_scripts in std clip deprecation (#11150)
this is just a simple fix for the link to the `nu_scripts` introduced in
https://github.com/nushell/nushell/pull/11097 😌
2023-11-24 19:03:07 +01:00
d37893cca0 Add more descriptive error message when passing list to from_csv (#10962)
<!--
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
Added statement catching early List passed to CSV and printing more
helpful error message. This fixes #10081. Similar message might be
useful for other from_* calls but I'm not sure if there aren't any
converters accepting List as input.

# 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-11-24 07:45:01 -06:00
95ac436d26 Fix release and nightly build workflow (#11146)
Fix release and nightly build workflow:
https://github.com/nushell/nightly/issues/15
I think the `mv` command in v0.87.1 still has some bugs, when downgrade
to v0.86 everything works as expected
2023-11-24 09:10:39 +08:00
c2a46070aa Exit the release job if creating binary package failed (#11145)
Try to exit the job if creating binary package failed, related issue:
https://github.com/nushell/nightly/issues/15
2023-11-24 07:47:59 +08:00
57808ca7cc Redirect: support redirect stderr with piping stdout to next commands. (#10851)
# Description
Fixes: #10271

Given the following script:
```shell
# test.sh
echo aaaaa
echo bbbbb 1>&2
echo cc
```

This pr makes the following command possible:
```nushell
bash test.sh err> /dev/null | lines | each {|line| $line | str length}
```


## General idea behind the change:
When nushell redirect stderr message to external file
1. it take stdout of external stream, and pass this stream to next
command, so it won't block next pipeline command from running.
2. relative stderr stream are handled by `save` command

These two streams are handled separately, so we need to delegate a
thread to `save` command, or else we'll have a chance to hang nushell,
we have meet a similar before: #5625.

### One case to consider
What if we're failed to save to an external stream? (Like we don't have
a permission to save to a file)?
In this case nushell will just print a waning message, and don't stop
the following scripts from running.

# User-Facing Changes
## Before
```nushell
❯ bash test2.sh err> /dev/null | lines | each {|line| $line | str length}
aaaaa
cc
```

## After
```nushell
❯ bash test2.sh err> /dev/null | lines | each {|line| $line | str length}
╭───┬───╮
│ 0 │ 5 │
│ 1 │ 2 │
╰───┴───╯
```

BTY, after this pr, the following commands are impossible either, it's
important to make sure that the implementation doesn't introduce too
much costs:
```nushell
❯ echo a e> a.txt e> a.txt
Error:   × Can't make stderr redirection twice
   ╭─[entry #1:1:1]
 1 │ echo a e> a.txt e> a.txt
   ·                 ─┬
   ·                  ╰── try to remove one
   ╰────

❯ echo a o> a.txt o> a.txt
Error:   × Can't make stdout redirection twice
   ╭─[entry #2:1:1]
 1 │ echo a o> a.txt o> a.txt
   ·                 ─┬
   ·                  ╰── try to remove one
   ╰────
```
2023-11-23 10:11:00 +08:00
6cfe35eb7e enable to pass switch values dynamically (#11057)
# Description
Closes: #7260 

About the change:
When we make an internalcall, and meet a `switch` (Flag.arg is None),
nushell will try to see if the switch is called like `--xyz=false` , if
that is true, `parse_long_flag` will return relative value.

# User-Facing Changes
So after the pr, the following would be possible:
```nushell
def build-imp [--push, --release] {
    echo $"Doing a build with push: ($push) and release: ($release)"
}
def build [--push, --release] {
    build-imp --push=$push --release=$release
}

build --push --release=false
build --push=false --release=true
build --push=false --release=false
build --push --release
build
```

# Tests + Formatting
Done

# After Submitting
Needs to submit a doc update, mentioned about the difference between
`def a [--x] {}` and `def a [--x: bool] {}`
2023-11-23 06:57:37 +08:00
b2734db015 Move more commands to opaque Record type (#11122)
# Description

Further work towards the goal that we can make `Record`'s field private
and experiment with different internal representations

## Details
- Use inplace record iter in `nu-command/math/utils`
  - Guarantee that existing allocation can be reused
- Use proper record iterators in `path join`
- Remove unnecesary hashmap in `path join`
  - Should minimally reduce the overhead
- Unzip records in `nu-command`
- Refactor `query web` plugin to use record APIs
- Use `Record::into_values` for `values` command
- Use `Record::columns()` in `join` instead.
  - Potential minor pessimisation
  - Not the hot value path
- Use sane `Record` iters in example `Debug` impl
- Avoid layout assumption in `nu-cmd-extra/roll/mod`
  - Potential minor pessimisation
- relegated to `extra`, changing the representation may otherwise break
this op.
- Use record api in `rotate`
- Minor risk that this surfaces some existing invalid behavior as panics
as we now validate column/value lengths
  - `extra` so things are unstable
- Remove unnecessary references in `rotate`
  - Bonus cleanup
# User-Facing Changes
None functional, minor potential differences in runtime. You win some,
you lose some.

# Tests + Formatting
Relying on existing tests
2023-11-22 23:48:48 +01:00
823e578c46 Spread operator for list literals (#11006) 2023-11-22 23:10:08 +02:00
95a745e622 deprecate std clip (#11097)
related to 
- https://github.com/nushell/nushell/issues/11041
- https://github.com/nushell/nu_scripts/pull/674

cc/ @FMotalleb 

# Description
reading the [frontpage of the standard
library](https://github.com/nushell/nushell/blob/main/crates/nu-std/README.md#--welcome-to-the-standard-library-of-nushell--)
and according to the last Nushell meeting, i has been agreed that `std
clip` does not belong to the standard library 😮
- it is not written in pure Nushell and requires external dependencies
which might not even work properly as in
https://github.com/nushell/nushell/issues/11041
- it is not a building block to build more complex applications

this PR deprecates the `std clip` command in favor of [`modules/system
clip`](https://github.com/nushell/nu_scripts/pull/674) for now.

the `std clip` command will be removed in Nushell 0.89.

# User-Facing Changes
the deprecation warning:

![std-clip-deprecation](https://github.com/nushell/nushell/assets/44101798/84bbdf3c-178c-4191-b0bf-9b1b25c229a2)
> **Note**
> the link has been changed to the `nu_scripts` in fa6c17da0 according
to the review comments

# Tests + Formatting

# After Submitting
this will have to be mentionned in the next release note, namely the
slight differences between the two commands.
2023-11-22 18:26:12 +01:00
776df7cd93 Convert PluginFailedToDecode to named fields (#11126)
# Description

Part of #10700

# User-Facing Changes

None

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

# After Submitting

N/A
2023-11-22 12:56:04 +01:00
d5677625a7 Add is-terminal to determine if stdin/out/err are a terminal (#10970)
# Description

I'm not sure if "is-terminal" is the best name for this command as there
is also "term size". Uses
[`is_terminal()`](https://doc.rust-lang.org/stable/std/io/trait.IsTerminal.html#tymethod.is_terminal)
which is cross-platform.

Possible alternative names:
* `term is-tty --stdout`
* `term is-tty stdout`
* `term is-terminal stdout`

If multiple streams are provided an error is returned. The error span
covers all arguments as the incompatible one is not known. This may be
new?

Fixes #10517

# User-Facing Changes

* Add `is-terminal` to check if stdin, stdout, or stderr are a terminal
(TTY)

# Tests + Formatting

The nu tests always redirect stdin, stdout, and stderr so a positive
test case is not possible without extra work

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

# After Submitting

The new command will be added automatically

---------

Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2023-11-21 20:48:39 -06:00
64288b4350 Convert PluginFailedToEncode to named fields (#11125)
# Description

Part of #10700

# User-Facing Changes

None

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

# After Submitting

N/A
2023-11-21 17:38:58 -06:00
a42fd3611a Convert PluginFailedToLoad to named fields (#11124)
# Description

Part of #10700

# User-Facing Changes

None

# Tests + Formatting

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

# After Submitting

N/A
2023-11-21 17:30:52 -06:00
e36f69bf3c Convert FileNotFoundCustom to named fields (#11123)
# Description

Part of #10700

# User-Facing Changes

None

# Tests + Formatting

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

# After Submitting

N/A
2023-11-21 17:30:21 -06:00
5ad7b8f029 Fix toolkit to run workspace on 'check pr' (issue #10906) (#11112)
- Fixes #10906 

No rust changes, just tookit.nu. When `check pr` is run, it should now
run with the `--workspace` argument so all tests are run.
2023-11-21 18:19:35 +01:00
ffb80b8873 Curate developer documentation in tree (#11052)
This is still work in progress. But let's start somewhere.

Goal for this being in the repo is to make sure we update it more
frequently than the
https://github.com/nushell/nushell.github.io/tree/main/contributor-book


- Add folder for in-repo developer documentation
- Move PLATFORM_SUPPORT into devdocs
- Move our rust style to devdocs
- Use nushell code formatting in CONTRIBUTING
- Add FAQ file for developers with example questions
- Describe error handling best practices
2023-11-21 18:12:00 +01:00
177e800a07 Use record API in describe --detailed (#11075)
For the new stuff from #10795

Added helper to contract `{"type": ...}` records
Use inplace operations if possible for records/lists

Referencing #11027
2023-11-21 17:49:23 +01:00
a7e8970383 Upgrade Nu and script for release workflow (#11121)
Upgrade Nu and script for release workflow
2023-11-21 06:40:01 -06:00
a324a50bb7 Convert FileNotFound to named fields (#11120)
# Description

Part of #10700

# User-Facing Changes

None

# Tests + Formatting

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

# After Submitting

N/A
2023-11-21 17:08:10 +08:00
0578cf85ac Convert ShellError::AliasNotFound to named fields (#11118)
# Description

Part of #10700

# User-Facing Changes

None

# Tests + Formatting

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

# After Submitting

N/A
2023-11-21 16:24:08 +08:00
1b54dd5418 Remove ShellError::FlagNotFound (#11119)
# Description

`ShellError::FlagNotFound` had a note that said it may be removable so
this PR removes it instead of updating it to named fields per #10700

I can't see this error being used since it was introduced with #4364. I
can't find why or where it was used before that date, though. There was
a large merge with that PR but I can't penetrate the secrets of git to
find out where its earlier history went.

# User-Facing Changes

None

# Tests + Formatting

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

# After Submitting

N/A
2023-11-21 16:23:09 +08:00
8ad5d8bb6a Bump procfs to 0.16.0 (#11115)
Fix the breaking changes.
Get's rid of some outdated transitive dependencies.
Sadly we need to expose more of `procfs` to `nu-command` based on how
the features of `nu-system` are exposed right now.

Conditional compilation/dependencies from hell included

Supersedes #11101
2023-11-20 21:22:35 +01:00
869b01205c Bump uuid from 1.5.0 to 1.6.0 (#11104) 2023-11-20 19:38:41 +00:00
f5b2f5a9ee Bump winreg from 0.51.0 to 0.52.0 (#11102) 2023-11-20 19:35:21 +00:00
adfa4d00c0 Bump version to 0.87.2 (#11114)
Based on the hotfix
https://github.com/nushell/nushell/releases/tag/0.87.1 use this to
disambiguate
2023-11-20 20:31:10 +01:00
12effd9b4e Refactor Value cell path functions to fix bugs (#11066)
# Description
Slightly refactors the cell path functions (`insert_data_at_cell_path`,
etc.) for `Value` to fix a few bugs and ensure consistent behavior.
Namely, case (in)sensitivity now applies to lazy records just like it
does for regular `Records`. Also, the insert behavior of `insert` and
`upsert` now match, alongside fixing a few related bugs described below.
Otherwise, a few places were changed to use the `Record` API.

# Tests
Added tests for two bugs:
- `{a: {}} | insert a.b.c 0`: before this PR, doesn't create the
innermost record `c`.
- `{table: [[col]; [{a: 1}], [{a: 1}]]} | insert table.col.b 2`: before
this PR, doesn't add the field `b: 2` to each row.
2023-11-19 21:46:41 +01:00
c26fca7419 Add Argument::span() and Call::arguments_span() (#10983)
# Description

These make it easy to make a Span that covers an entire argument and the
span of all arguments in a Call.

Call::arguments_span() is useful for errors where a command may accept
arguments or the pipeline, but not both.

Argument::span() is useful for errors where an arguments is incompatible
with one or more other arguments.

In particular, I wish to use this to create an error for an
implementation of #9563 that either allows arguments to set limits:

```nushell
limits set RLIMIT_NOFILE --soft 255 --hard 1024
```

Or pipeline:

```nushell
{name: RLIMIT_NOFILE, soft: 255} | limits set
```

But not both:

```
❯ [{name: RLIMIT_NOFILE, soft: 255, hard: 1024}] | limits set AS --soft 5 --hard 5
Error: nu:🐚:incompatible_parameters

  × Incompatible parameters.
   ╭─[source:1:1]
 1 │ [{name: RLIMIT_NOFILE, soft: 255, hard: 1024}] | limits set AS --soft 5 --hard 5
   · ───────────────────────┬──────────────────────              ──────────┬─────────
   ·                        │                                              ╰── or arguments, not both
   ·                        ╰── Supply either pipeline
   ╰────
```

# User-Facing Changes

Only nushell Command API changes
2023-11-19 21:43:56 +01:00
da59dfe7d2 Convert ShellError::NetworkFailure to named fields (#11093)
# Description

Part of #10700
2023-11-19 21:32:11 +01:00
08715e6308 Convert ShellError::CommandNotFound to named fields (#11094)
# Description

Part of #10700
2023-11-19 21:31:28 +01:00
07d7899a97 remove def-env and export def-env (#10999)
follow-up to
- https://github.com/nushell/nushell/pull/10715

> **Important**
> wait for between 0.87 and 0.88 to land this

# Description
it's time for removal again 😋 
this PR removes `def-env` and `export def-env` in favor of `def --env`

# User-Facing Changes
`def-env` and `export def-env` will not be found anymore.

# Tests + Formatting

# After Submitting
2023-11-19 23:25:09 +08:00
494a5a5286 Add mktemp command (#11005)
closes #10845 

I've opened this a little prematurely to get some questions answered
before I cleanup the code.

As I started trying to better understand GNUs `mktemp` I've realized its
kind of peculiar and we might want to change its behavior to introduce
it to nushell.

#### quiet and dry run

Does it make sense to keep the `quiet` and `dry_run` flags? I don't
think so. The GNU documentation says this about the dry run flag "Using
the output of this command to create a new file is inherently unsafe, as
there is a window of time between generating the name and using it where
another process can create an object by the same name." So yeah why keep
it? As far as quiet goes, does it make sense to silence the errors in
nushell?

#### other confusing flags

According to the [gnu
docs](https://www.gnu.org/software/coreutils/manual/html_node/mktemp-invocation.html),
the `-t` flag is deprecated and the `-p`/ `--tempdir` are the same flag
with the only difference being `--tempdir` takes an optional path, Given
that, I've broken the `-p` away from `--tempdir`. Now there is one
switch `--tmpdir`/`-t` and one named param `--tmpdir-path`/`-p`.

GNU mktemp
```
  -p DIR, --tmpdir[=DIR]  interpret TEMPLATE relative to DIR; if DIR is not
                        specified, use $TMPDIR if set, else /tmp.  With
                        this option, TEMPLATE must not be an absolute name;
                        unlike with -t, TEMPLATE may contain slashes, but
                        mktemp creates only the final component
  -t                  interpret TEMPLATE as a single file name component,
                        relative to a directory: $TMPDIR, if set; else the
                        directory specified via -p; else /tmp [deprecated]

```
to
nushell mktemp
```
  -p, --tmpdir-path <Filepath> # named param, must provide a path
  -t, --tmpdir                 # a switch
```

Is this a terrible idea?

What should I do?

---------

Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2023-11-17 19:30:53 -06:00
f41c93b2d3 Apply nightly clippy fixes (#11083)
<!--
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.
-->
Clippy fixes for rust 1.76.0-nightly

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

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

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

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used` 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-11-17 09:15:55 -06:00
5063e01c12 std: add cross platform null-device name (#11070)
# Description
We have meet a discord discussion about cross platform `null-device`:
https://discord.com/channels/601130461678272522/988303282931912704/1165966467095875624

I want the same feature too...And I think it's good enough to add it
into `nu-std`.

Different to https://github.com/nushell/nu_scripts/pull/649/files, I
think named it to `null-device`(the name comes from
[wiki](https://en.wikipedia.org/wiki/Null_device)) is better than
`null-stream`.
2023-11-17 14:49:07 +01:00
d1137cc700 Send only absolute paths to uu_cp (#11080)
# Description
Fixes https://github.com/nushell/nushell/issues/10832

Replaces: https://github.com/nushell/nushell/pull/10843
2023-11-17 07:30:57 +08:00
3966c0a9fd Fix rm path handling (#11064)
# Description
Fixes issue #11061 where `rm` fails to find a file after a `cd`. It
looks like the new glob functions do not return absolute file paths
which we forgot to account for.

# Tests
Added a test (fails on current main, but passes with this PR).

---------

Co-authored-by: Jakub Žádník <kubouch@gmail.com>
2023-11-17 07:30:15 +08:00
dbdb1f6600 remove the unfold command (#10773)
follow-up to:
- https://github.com/nushell/nushell/pull/10771

> **Important**
> wait for between 0.87 and 0.88 to land this

# Description
after deprecation comes the removal... this PR removes `unfold` in favor
of `generate` 🥳

# User-Facing Changes
users should use `generate` now, `unfold` will stop working.

# Tests + Formatting

# After Submitting
2023-11-17 06:50:20 +08:00
84cdc0d521 remove size command in favor of str stats (#10784)
follow-up to
- https://github.com/nushell/nushell/pull/10798

> **Important**
> wait for between 0.87 and 0.88 to land this

# Description
once again, after deprecation comes removal 😌 

# User-Facing Changes
`size` is now removed and `str size` should be used

# Tests + Formatting

# After Submitting
2023-11-17 06:49:19 +08:00
ab59dab129 remove --not from glob (#10839)
follow-up to
- https://github.com/nushell/nushell/pull/10827

> **Important**  
> wait for between 0.87 and 0.88 to land this

# Description
after deprecation comes removal... this PR removes `glob --not` in favor
of `glob --exclude`.

# User-Facing Changes
`glob --not` will stop working.

# Tests + Formatting

# After Submitting
i didn't find any use of `glob --not` in the `nu_scripts` so no update
required there 👍
2023-11-17 06:46:15 +08:00
e0c8a3d14c remove extern-wrapped and export extern-wrapped (#11000)
follow-up to
- https://github.com/nushell/nushell/pull/10716

> **Important**
> wait for between 0.87 and 0.88 to land this

# Description
it's time for removal again 😋 
this PR removes `extern-wrapped` and `export extern-wrapped` in favor of
`def --wrapped`

# User-Facing Changes
`extern-wrapped` and `export extern-wrapped` will not be found anymore.

# Tests + Formatting

# After Submitting
2023-11-17 06:44:28 +08:00
e93e51d672 bump rust-toolchain to 1.72.1 (#11079)
# Description

This PR follows our process of staying 2 releases behind rust. 1.74.0
was released today so we update to 1.72.1.

Reference https://releases.rs/

# 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-11-16 15:14:45 -06:00
4205edbc70 Fix the output type for 'view files' (#11077)
<!--
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.
-->

# 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: JT <547158+jntrnr@users.noreply.github.com>
2023-11-16 11:53:51 -06:00
80bee40807 optimize/clean up a few of the table changes (#11076)
# Description

@sholderbach pointed out some places that I could help improve the code
in the table command changes. This PR tries to implement those.

# 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-11-16 11:37:46 -06:00
461837773b correct table example syntax (#11074)
# Description

Correct an example that had old syntax.

# 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-11-16 08:20:52 -06:00
52d4259f58 add "default" table theme (#11072)
# Description

This PR fixes a minor bug that prevented this command from running.
```nushell
table --list | each {|r| print ($r); print (ls | first 3 | table --theme $r)}
```
Here's the output now of the first few themes.

![image](https://github.com/nushell/nushell/assets/343840/21bc8942-5106-4b6a-8905-e90d6cb9a153)

It prevented it from running because "default" wasn't a real table
theme. Now "default" is a synonym of rounded.

Also tweaked the error message when a bad theme name is provided.

# 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-11-16 06:14:18 -06:00
274a8366c6 tweak table example/parameter text (#11071)
# Description

This PR just tweaks the `table` example text and some parameter text.

# 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-11-16 05:35:55 -06:00
a1dfc35968 Fix #11047 (#11054)
close #11047
2023-11-16 05:28:54 -06:00
5886a74ccc into binary -c: return 0 as single byte (#11068)
# Description

The `into binary` command has a `-c` flag which strips any leading 0s in
the most significant digits to represent the minimal number of bytes,
rather than the system's complete in-memory representation of the input.

However, currently giving 0 as input results in eight 0 bytes even with
the `-c` flag, which is inconsistent with the purpose of the flag.

```nu
❯ : 345678 | into binary
Length: 8 (0x8) bytes | printable whitespace ascii_other non_ascii
00000000:   4e 46 05 00  00 00 00 00                             NF•00000

❯ : 345678 | into binary -c
Length: 3 (0x3) bytes | printable whitespace ascii_other non_ascii
00000000:   4e 46 05

❯ : 0 | into binary
Length: 8 (0x8) bytes | printable whitespace ascii_other non_ascii
00000000:   00 00 00 00  00 00 00 00                             00000000

❯ : 0 | into binary -c
Length: 8 (0x8) bytes | printable whitespace ascii_other non_ascii
00000000:   00 00 00 00  00 00 00 00                             00000000
```

This change fixes this behavior so that if the entire input results in
all 0 bytes, only a single 0 byte is returned.

```nu
❯ : ~/src/nushell/target/aarch64-linux-android/debug/nu -c '0 | into binar
y -c'
Length: 1 (0x1) bytes | printable whitespace ascii_other non_ascii
00000000:   00
```

# User-Facing Changes

Values which result in all null bytes will be truncated to a single byte
when `-c` is given. This could potentially be considered a breaking
change if this behavior was relied upon in some way.
2023-11-16 04:09:31 -06:00
4367aa9f58 allow parsing of human readable datetimes (#11051)
# Description

This PR adds the ability to parse human readable datetime strings as
part of the `into datetime` command. I added a new `-n`/`--list-human`
parameter that produces this list to give the user an idea of what is
supported.
```nushell
❯ into datetime --list-human 
╭#─┬parseable human datetime examples┬───result───╮
│0 │Today 18:30                      │in 8 hours  │
│1 │2022-11-07 13:25:30              │a year ago  │
│2 │15:20 Friday                     │in 3 days   │
│3 │This Friday 17:00                │in 3 days   │
│4 │13:25, Next Tuesday              │in a week   │
│5 │Last Friday at 19:45             │3 days ago  │
│6 │In 3 days                        │in 2 days   │
│7 │In 2 hours                       │in 2 hours  │
│8 │10 hours and 5 minutes ago       │10 hours ago│
│9 │1 years ago                      │a year ago  │
│10│A year ago                       │a year ago  │
│11│A month ago                      │a month ago │
│12│A week ago                       │a week ago  │
│13│A day ago                        │a day ago   │
│14│An hour ago                      │an hour ago │
│15│A minute ago                     │a minute ago│
│16│A second ago                     │now         │
│17│Now                              │now         │
╰#─┴parseable human datetime examples┴───result───╯
```

Or with `$env.config.datetime_format.table` set.
```nushell
❯ into datetime --list-human 
╭#─┬parseable human datetime examples┬──────result───────╮
│0 │Today 18:30                      │11/14/23 06:30:00PM│
│1 │2022-11-07 13:25:30              │11/07/22 01:25:30PM│
│2 │15:20 Friday                     │11/17/23 03:20:00PM│
│3 │This Friday 17:00                │11/17/23 05:00:00PM│
│4 │13:25, Next Tuesday              │11/21/23 01:25:00PM│
│5 │Last Friday at 19:45             │11/10/23 07:45:00PM│
│6 │In 3 days                        │11/17/23 10:12:54AM│
│7 │In 2 hours                       │11/14/23 12:12:54PM│
│8 │10 hours and 5 minutes ago       │11/14/23 12:07:54AM│
│9 │1 years ago                      │11/13/22 10:12:54AM│
│10│A year ago                       │11/13/22 10:12:54AM│
│11│A month ago                      │10/15/23 11:12:54AM│
│12│A week ago                       │11/07/23 10:12:54AM│
│13│A day ago                        │11/13/23 10:12:54AM│
│14│An hour ago                      │11/14/23 09:12:54AM│
│15│A minute ago                     │11/14/23 10:11:54AM│
│16│A second ago                     │11/14/23 10:12:53AM│
│17│Now                              │11/14/23 10:12:54AM│
╰#─┴parseable human datetime examples┴──────result───────╯
```
# 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-11-15 17:43:37 -06:00
e9c298713e nu-table/ Add -t/theme argument && Replace -n/start-number with -i/index (#11058)
ref #11054

cc: @fdncred 

I've not figured out how to be able to have a flag option as `table -i`
:(

```nu
~/bin/nushell> [[a b, c]; [1 [2 3 3] 3] [4 5 [1 2 [1 2 3]]]] | table -e --width=80 --theme basic -i false

+---+-------+-----------+
| a |   b   |     c     |
+---+-------+-----------+
| 1 | +---+ |         3 |
|   | | 2 | |           |
|   | +---+ |           |
|   | | 3 | |           |
|   | +---+ |           |
|   | | 3 | |           |
|   | +---+ |           |
+---+-------+-----------+
| 4 |     5 | +-------+ |
|   |       | |     1 | |
|   |       | +-------+ |
|   |       | |     2 | |
|   |       | +-------+ |
|   |       | | +---+ | |
|   |       | | | 1 | | |
|   |       | | +---+ | |
|   |       | | | 2 | | |
|   |       | | +---+ | |
|   |       | | | 3 | | |
|   |       | | +---+ | |
|   |       | +-------+ |
+---+-------+-----------+
```

```nu
~/bin/nushell> [[a b, c]; [1 [2 3 3] 3] [4 5 [1 2 [1 2 3]]]] | table -e --width=80 --theme basic -i 100

+-----+---+-------------+-----------------------+
|   # | a |      b      |           c           |
+-----+---+-------------+-----------------------+
| 100 | 1 | +-----+---+ |                     3 |
|     |   | | 100 | 2 | |                       |
|     |   | +-----+---+ |                       |
|     |   | | 101 | 3 | |                       |
|     |   | +-----+---+ |                       |
|     |   | | 102 | 3 | |                       |
|     |   | +-----+---+ |                       |
+-----+---+-------------+-----------------------+
| 101 | 4 |           5 | +-----+-------------+ |
|     |   |             | | 100 |           1 | |
|     |   |             | +-----+-------------+ |
|     |   |             | | 101 |           2 | |
|     |   |             | +-----+-------------+ |
|     |   |             | | 102 | +-----+---+ | |
|     |   |             | |     | | 100 | 1 | | |
|     |   |             | |     | +-----+---+ | |
|     |   |             | |     | | 101 | 2 | | |
|     |   |             | |     | +-----+---+ | |
|     |   |             | |     | | 102 | 3 | | |
|     |   |             | |     | +-----+---+ | |
|     |   |             | +-----+-------------+ |
+-----+---+-------------+-----------------------+
```
2023-11-15 17:41:18 -06:00
c110ddff66 Implement LSP Text Document Synchronization (#10941) 2023-11-15 17:35:48 -06:00
a806717f35 Testing support tweaks: exit status in Outcome (#10692)
This PR makes a couple of tweaks to the testing support crate:

Add the `nu` invocation's exit status to the test output so that one
can assert that nu exited with a successful code.

This PR was split off of #10232.
2023-11-15 23:50:43 +01:00
2b5f1ee5b3 Bump version to 0.87.1 (#11056) 2023-11-15 23:50:11 +01:00
77a1c3c7b2 Bump version for 0.87.0 release (#11031)
# Release checklist

- [x] reedline
  - [x] released
  - [x] pinned
- [x] crate graph check
- [x] release notes
- [x] release script update (new crate `nu-lsp`)
- [ ] permission management `nu-lsp` on crates.io
2023-11-14 21:01:19 +01:00
82b3ae826f Pin reedline to 0.26 release (#11053)
See full release notes:
https://github.com/nushell/reedline/releases/tag/v0.26.0
2023-11-14 20:47:25 +01:00
1b3092ae7c Move to clearer reedline keyboard enhancement API (#11045)
Go from the ill-defined `enable/disable` pairs to `.use_...` builders
This alleviates unclear properties when the underlying enhancements are
enabled. Now they are enabed when entering `Reedline::read_line` and
disabled when exiting that.

Furthermore allow setting `$env.config.use_kitty_protocol` to have an
effect when toggling during runtime. Previously it was only enabled when
receiving a value from `config.nu`. I kept the warning code there to not
pollute the log. We could move it into the REPL-loop if desired

Not sure if we should actively block the enabling of `bracketed_paste`
on Windows. Need to test what happens if it just doesn't do anything we
could remove the `cfg!` switch. At least for WSL2 Windows Terminal
already supports bracketed paste. `target_os = windows` is a bad
predictor for `conhost.exe`.

Depends on https://github.com/nushell/reedline/pull/659
(pointing to personal fork)

Closes https://github.com/nushell/nushell/issues/10982
Supersedes https://github.com/nushell/nushell/pull/10998
2023-11-14 20:27:14 +01:00
942ff7df4d fix custom command's default value (#11043)
# Description
Fixes: #11033

Sorry for the issue, it's a regression which introduce by this pr:
#10456.
And this pr is going to fix it.

About the change: create a new field named `type_annotated` for
`Arg::Flag` and `Arg::Signature` instead of `arg_explicit_type`
variable.
When we meet a type in `TypeMode`, we set `type_annotated` field of the
argument to be true, then we know that if the arg have a annotated type
easily
2023-11-14 13:46:05 +01:00
51abe4c262 Bump rustix patch versions (#11044)
We have three different `rustix` minor versions. For two of them with
their previous patch versions a security advisory has been released:

https://github.com/advisories/GHSA-c827-hfw6-qwvm

Bump the patch versions, to resolve the potential vulnerability.

At the moment we haven't  assessed the potential impact on nushell,
whether we are exposed to the underlying issue.
2023-11-13 15:09:37 +01:00
e8e0526f57 Bump crate-ci/typos from 1.16.22 to 1.16.23 (#11038) 2023-11-13 11:28:28 +00:00
0b25385109 Revert "add color-backtrace crate (#10942)" (#11032)
The `color-backtrace` crate does not seem to either handle the terminal
modes well or operate in a way that the unwinding has not yet succeeded
to reach the backup disablement of the terminal raw mode in
`reedline::Reedline`'s `Drop` implementation.

This reverts commit d838871063.

Fixes #11029
2023-11-11 16:03:33 -06:00
415b1273b4 Fix (http) get HTTP_PROXY from $env (#11026)
# Description

This PR closes this
[issue](https://github.com/nushell/nushell/issues/11025)

# User-Facing Changes

Setting the environment variable HTTP_PROXY using $env.HTTP_PROXY will
work.

# Before

```bash
~> $env.HTTP_PROXY = http://127.0.0.1:7890 | http get https://lumtest.com/myip.json | get country
IR # (direct)
```

# After

```bash
~> $env.HTTP_PROXY = http://127.0.0.1:7890 | http get https://lumtest.com/myip.json | get country
DE # (with proxy)
```
2023-11-11 10:16:17 -06:00
6bee80dcd7 make reject support list input directly (#11024)
# Description
Fixes: #10895 

It's because `reject` and `select` command can't handle list of CellPath
input directly.
After this pr, the following should be ok:
```nushell
❯ [{'a': 1, 'b': 2, 'c': 3}, {'a': 1, 'b': 2, 'c': 3}] | reject ['a', 'b']
╭───┬───╮
│ # │ c │
├───┼───┤
│ 0 │ 3 │
│ 1 │ 3 │
╰───┴───╯
❯ [{'a': 1, 'b': 2, 'c': 3}, {'a': 1, 'b': 2, 'c': 3}] | select ['a', 'b']
╭───┬───┬───╮
│ # │ a │ b │
├───┼───┼───┤
│ 0 │ 1 │ 2 │
│ 1 │ 1 │ 2 │
╰───┴───┴───╯
```
2023-11-11 10:15:11 -06:00
588a078872 Fix tests for cargo.exe check command (#11022)
This pull request fixes the tests for the `cargo.exe check` command. The
tests were failing due `cargo check -h` sometimes reporting `cargo.exe`
as the binary and thus not containing `cargo check` in the output.

The fix involves using the `Command` module from the `std::process`
library to run the command and comparing its output to the expected
output. No changes were made to the codebase itself.
2023-11-10 21:15:11 +01:00
93096a07aa Implement Display for CellPath (#11023)
# Description
Because `CellPath::into_string` takes a borrowed `self`, I renamed it to
`to_string` to follow Rust [API
guidelines](https://rust-lang.github.io/api-guidelines/naming.html#ad-hoc-conversions-follow-as_-to_-into_-conventions-c-conv).
This then triggered the clippy lint
[inherent_to_string](https://rust-lang.github.io/rust-clippy/master/index.html#/inherent_to_string),
which is... correct! The current `CellPath::into_string` is being used
as if it were the `Display` implementation for `CellPath`.

# User-Facing Changes
Breaking API change for `nu-protocol`, since `CellPath::into_string` was
removed.
2023-11-10 21:12:51 +01:00
523d0bca16 Refactor flatten command (#11017)
# Description
Refactors the `flatten` command to remove a bunch of cloning. This was
down by passing ownership of the `Value` to `flat_value`, removing the
lifetime on `TableInside`, and using `Vec<Record>` in `FlattenedRows`
instead of a pair of `Vec` of columns and values.

For the quick benchmark below, it seems to be twice as fast now:
```nushell
let data = ls crates | where type == dir | each { ls $'($in.name)/**/*' }
timeit { for x in 0..1000 { $data | flatten } }
```
This took 550ms on v0.86.0 and only 230ms on this PR.
But considering that
```nushell
timeit { for x in 0..1000 { $data } }
```
takes 200ms on both versions, then the difference for `flatten` itself
is really 250ms vs 30ms -- 8x faster.
2023-11-10 13:18:02 +01:00
fe92051bb3 Adding support for Polars structs (#10943)
Provides support for reading Polars structs. This allows opening of
supported files (jsonl, parquet, etc) that contain rows with structured
data.

The following attached json lines
file([receipts.jsonl.gz](https://github.com/nushell/nushell/files/13311476/receipts.jsonl.gz))
contains a customer column with structured data. This json lines file
can now be loaded via `dfr open` and will render as follows:

<img width="525" alt="Screenshot 2023-11-09 at 10 09 18"
src="https://github.com/nushell/nushell/assets/56345/4b26ccdc-c230-43ae-a8d5-8af88a1b72de">


This also addresses some cleanup of date handling and utilizing
timezones where provided.

This pull request only addresses reading data from polars structs. I
will address converting nushell data to polars structs in a future
request as this change is large enough as it is.

---------

Co-authored-by: Jack Wright <jack.wright@disqo.com>
2023-11-09 19:00:59 -06:00
ee648ecb7d Refactor transpose and improve perf (#11013)
# Description

Generally elide a bunch of unnecessary clones. Both globally stopping to
clone the whole input data in a bunch of places where we need to read it
but also some minor places where we currently cloned.

As part of that, we can make the overwriting with `keep-all` and
`keep-last` inplace so the items don't need to be removed and repushed
to the record. 

# Benchmarking

```nu
timeit { scope commands | transpose -r }
```

Before ~24 ms now just ~5 ms

# User-Facing Changes
This can change the order of apperance in the transposed record with
`--keep-last`/`--keep-all`. Now the
order is determined by the first appearance and not by the last
appearance in the ingoing columns.
This mirrors the behavior when not passed `keep-all` or `keep-last`.

# Tests + Formatting
Sadly the `transpose` command is so far undertested for more complex
operations.
2023-11-09 22:41:38 +01:00
91920373b5 Match toolkit clippy settings to CI clippy settings (#10984)
# Description

I've had a few PRs fail clippy in CI after they pass `toolkit check pr`
because the clippy settings are different. This brings `toolkit.nu` into
alignment with CI and leaves notes to prompt future synchronization.

# User-Facing Changes

N/A

# Tests + Formatting

`cargo` output elided:

```
❯ toolkit check pr
running `toolkit fmt`
running `toolkit clippy`
running `toolkit clippy` on tests
running `toolkit clippy` on plugins
running `toolkit test`
running `toolkit test stdlib`
- 🟢 `toolkit fmt`
- 🟢 `toolkit clippy`
- 🟢 `toolkit test`
- 🟢 `toolkit test stdlib`
```

# After Submitting

N/A
2023-11-09 19:07:15 +01:00
33a7bc405f Refactor drop columns to fix issues (#10903)
# Description
This PR refactors `drop columns` and fixes issues #10902 and #6846.
Tables with "holes" are now handled consistently, although still
somewhat awkwardly. That is, the columns in the first row are used to
determine which columns to drop, meaning that the columns displayed all
the way to the right by `table` may not be the columns actually being
dropped. For example, `[{a: 1}, {b: 2}] | drop column` will drop column
`a` instead of `b`. Before, this would give a list of empty records.

# User-Facing Changes
`drop columns` can now take records as input.
2023-11-09 13:51:46 +01:00
cd75640a90 Add Record::truncate for trimming based on len (#11004)
# Description
Compatible with `Vec::truncate` and `indexmap::IndexMap::truncate`

Found useful in #10903 for `drop column`

# Tests + Formatting
Doctest with the relevant edge-cases
2023-11-09 00:00:20 +01:00
0f600bc3f5 Improve case insensitivity consistency (#10884)
# Description

Add an extension trait `IgnoreCaseExt` to nu_utils which adds some case
insensitivity helpers, and use them throughout nu to improve the
handling of case insensitivity. Proper case folding is done via unicase,
which is already a dependency via mime_guess from nu-command.

In actuality a lot of code still does `to_lowercase`, because unicase
only provides immediate comparison and doesn't expose a `to_folded_case`
yet. And since we do a lot of `contains`/`starts_with`/`ends_with`, it's
not sufficient to just have `eq_ignore_case`. But if we get access in
the future, this makes us ready to use it with a change in one place.

Plus, it's clearer what the purpose is at the call site to call
`to_folded_case` instead of `to_lowercase` if it's exclusively for the
purpose of case insensitive comparison, even if it just does
`to_lowercase` still.

# User-Facing Changes

- Some commands that were supposed to be case insensitive remained only
insensitive to ASCII case (a-z), and now are case insensitive w.r.t.
non-ASCII characters as well.

# Tests + Formatting

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

---------

Co-authored-by: Stefan Holderbach <sholderbach@users.noreply.github.com>
2023-11-08 23:58:54 +01:00
aed4b626b8 Refactor env conversion, yeet Value::follow_cell_path_not... (#10926)
# Description
Replaces the only usage of `Value::follow_cell_path_not_from_user_input`
with some `Record::get`s.

# User-Facing Changes
Breaking change for `nu-protocol`, since
`Value::follow_cell_path_not_from_user_input` was deleted.

Nushell now reports errors for when environment conversions are not
closures.
2023-11-08 23:57:24 +01:00
92503e6571 Use record API in more parts of nu-protocol (#10928)
# Description

This is pretty complementary/orthogonal to @IanManske 's changes to
`Value` cellpath accessors in:
- #10925
- to a lesser extent #10926

## Steps
- Use `R.remove` in `Value.remove_data_at_cell_path`
- Pretty sound after #10875 (tests mentioned in commit message have been
removed by that)
- Update `did_you_mean` helper to use iterator
- Change `Value::columns` to return iterator
  - This is not a place of honor
- Use `Record::get` in `Value::get_data_by_key`
# User-Facing Changes
None intentional, potential edge cases on duplicated columns could
change (considered undefined behavior)

# Tests + Formatting
(-)
2023-11-08 23:03:08 +01:00
44c0db46e1 Add Record::drain to take out elements by range (#11002)
Matches the general behavior of `Vec::drain` or
`indexmap::IndexMap::drain`:
- Drop the remaining elements (implementing the unstable `keep_rest()`
would not be compatible with something like `indexmap`)
- No `AsRef<[T]>` or `Drain::as_slice()` behavior as this would make
layout assumptions.
- `Drain: DoubleEndedIterator`

Found useful in #10903
2023-11-08 22:54:02 +01:00
1fd3bc1ba6 Add exec command for Windows (#11001)
# Description
Based of the work and discussion in #10844, this PR adds the `exec`
command for Windows. This is done by simply spawning a
`std::process::Command` and then immediately exiting via
`std::process::exit` once the child process is finished. The child
process's exit code is passed to `exit`.

# User-Facing Changes
The `exec` command is now available on Windows, and there should be no
change in behaviour for Unix systems.
2023-11-08 14:50:25 -06:00
59ea28cf06 Use Record::get instead of Value functions (#10925)
# Description
Where appropriate, this PR replaces instances of
`Value::get_data_by_key` and `Value::follow_cell_path` with
`Record::get`. This avoids some unnecessary clones and simplifies the
code in some places.
2023-11-08 21:47:37 +01:00
435abadd8a Add special error case for alias (#10975)
Adds a special error, which is triggered by `alias foo=bar` style
commands. It adds a help string which recommends adding spaces.

Resolve #10958

---------

Co-authored-by: Jakub Žádník <kubouch@gmail.com>
2023-11-08 13:35:40 -06:00
86cd387439 Refactor and fix Config<->Value mechanism (#10896)
# Description
Our config exists both as a `Config` struct for internal consumption and
as a `Value`. The latter is exposed through `$env.config` and can be
both set and read.
Thus we have a complex bug-prone mechanism, that reads a `Value` and
then tries to plug anything where the value is unrepresentable in
`Config` with the correct state from `Config`.

The parsing involves therefore mutation of the `Value` in a nested
`Record` structure. Previously this was wholy done manually, with
indices.
To enable deletion for example, things had to be iterated over from the
back. Also things were indexed in a bunch of places. This was hard to
read and an invitation for bugs.

With #10876 we can now use `Record::retain_mut` to traverse the records,
modify anything that needs fixing, and drop invalid fields.

# Parts:

- Error messages now consistently use the correct spans pointing to the
problematic value and the paths displayed in some messages are also
aligned with the keys used for lookup.
- Reconstruction of values has been fixed for:
	- `table.padding`
	- `buffer_editor`
	- `hooks.command_not_found`
	- `datetime_format` (partial solution)
- Fix validation of `table.padding` input so value is not set (and
underflows `usize` causing `table` to run forever with negative values)
- New proper types for settings. Fully validated enums instead of
strings:
  - `config.edit_mode` -> `EditMode` 
  	- Don't fall back to vi-mode on invalid string
  - `config.table.mode` -> `TableMode`
- there is still a fall back to `rounded` if given an invalid
`TableMode` as argument to the `nu` binary
  - `config.completions.algorithm` -> `CompletionAlgorithm`
  - `config.error_style` -> `ErrorStyle`
    - don't implicitly fall back to `fancy` when given an invalid value.
- This should also shrink the size of `Config` as instead of 4x24 bytes
those fields now need only 4x1 bytes in `Config`
- Completely removed macros relying on the scope of `Value::into_config`
so we can break it up into smaller parts in the future.
- Factored everything into smaller files with the types and helpers for
particular topics.
- `NuCursorShape` now explicitly expresses the `Inherit` setting.
conversion to option only happens at the interface to `reedline`
2023-11-08 20:31:30 +01:00
edbf3aaccb Use Record's public API in a bunch of places (#10927)
# Description
Since #10841 the goal is to remove the implementation details of
`Record` outside of core operations.

To this end use Record iterators and map-like accessors in a bunch of
places. In this PR I try to collect the boring cases where I don't
expect any dramatic performance impacts or don't have doubts about the
correctness afterwards

- Use checked record construction in `nu_plugin_example`
- Use `Record::into_iter` in `columns`
- Use `Record` iterators in `headers` cmd
- Use explicit record iterators in `split-by`
- Use `Record::into_iter` in variable completions
- Use `Record::values` iterator in `into sqlite`
- Use `Record::iter_mut` for-loop in `default`
- Change `nu_engine::nonexistent_column` to use iterator
- Use `Record::columns` iter in `nu-cmd-base`
- Use `Record::get_index` in `nu-command/network/http`
- Use `Record.insert()` in `merge`
- Refactor `move` to use encapsulated record API
- Use `Record.insert()` in `explore`
- Use proper `Record` API in `explore`
- Remove defensiveness around record in `explore`
- Use encapsulated record API in more `nu-command`s

# User-Facing Changes
None intentional

# Tests + Formatting
(-)
2023-11-08 14:24:00 +01:00
b03ef56bcb Fix alpine docker file (#10992)
<!--
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

Fix docker file. For more detail see:
https://github.com/nushell/nushell/issues/8307
2023-11-08 06:30:34 -06:00
55316a9f27 Convert ShellError::DatetimeParseError to named fields (#10991)
# Description

Part of #10700

# User-Facing Changes

None

# Tests + Formatting

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

# After Submitting

N/A
2023-11-08 13:04:02 +01:00
d3ec3dc66b allow vscode-specific ansi escape sequence to set path (#10990)
# Description

This change allows the vscode-specific ansi escape sequence of
633;P;Cwd= to be run when nushell detects that it's running inside of
vscode's terminal. Otherwise the standard OSC7 will run. This is helpful
with ctrl+g inside of vscode terminal as well.

closed #10989 

/cc @CAD97 

# 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-11-07 19:38:30 -06:00
7ebae0b5f7 Refactor table cmd and nu-table with Record API (#10930)
# Description
- Simplify `table` record highlight with `.get_mut`
  - pretty straight forward
- Use record iterators in `table` abbreviation logic
- This required some rework if we go from guaranted contiguous arrays to
iterators
- Refactor `nu-table` internals to new record API
# User-Facing Changes
None intened

# Tests + Formatting
(-)
2023-11-08 01:22:47 +01:00
f45aed257f Refactor find in terms of clean Record API (#10929)
# Description
Rewrite `find` internals with the same principles as in #10927.

Here we can remove an unnecessary lookup accross all columns when not
narrowing find to particular columns

- Change `find` internal fns to use iterators
- Remove unnecessary quadratic lookup in `find`
- Refactor `find` record highlight logic
# User-Facing Changes
Should provide a small speedup when not providing `find --columns`

# Tests + Formatting
(-)
2023-11-08 01:06:22 +01:00
60da7abbc7 Use Vec for Closure captures (#10940)
# Description
Changes the `captures` field in `Closure` from a `HashMap` to a `Vec`
and makes `Stack::captures_to_stack` take an owned `Vec` instead of a
borrowed `HashMap`.

This eliminates the conversion to a `Vec` inside `captures_to_stack` and
makes it possible to avoid clones altogether when using an owned
`Closure` (which is the case for most commands). Additionally, using a
`Vec` reduces the size of `Value` by 8 bytes (down to 72).

# User-Facing Changes
Breaking API change for `nu-protocol`.
2023-11-08 00:43:28 +01:00
7a3cbf43e8 Convert ShellError::UnsupportedInput to named fields (#10971)
# Description

This is easy to do with rust-analyzer, but I didn't want to just pump
these all out without feedback.

Part of #10700

# User-Facing Changes

None

# Tests + Formatting

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

# After Submitting

N/A

---------

Co-authored-by: Stefan Holderbach <sholderbach@users.noreply.github.com>
2023-11-07 23:25:32 +01:00
45b02ce2ab Bump indexmap from 2.0.2 to 2.1.0 (#10969) 2023-11-07 15:36:34 +00:00
c039e4b3d0 Update description and error types for split-by (#10865)
# Description

`split-by` only works on a `Record`, the error type was updated to
match, and now uses a more-specific type. (Two type fixes for the price
of one!)

The `usage` was updated to say "record" as well

# User-Facing Changes

* Providing the wrong type to `split-by` now gives an error messages
with the correct required input type

Previously:

```
❯ ls | get name | split-by type
Error:   × unsupported input
   ╭─[entry #267:1:1]
 1 │ ls | get name | split-by type
   ·      ─┬─
   ·       ╰── requires a table with one row for splitting
   ╰────
```

With this PR:

```
❯ ls | get name | split-by type
Error: nu:🐚:type_mismatch

  × Type mismatch.
   ╭─[entry #1:1:1]
 1 │ ls | get name | split-by type
   ·      ─┬─
   ·       ╰── requires a record to split
   ╰────
```

# Tests + Formatting

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

# After Submitting

Only generated commands need to be updated

---------

Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2023-11-07 16:27:10 +01:00
9b202d560d Limit run-external --redirect-combine sh test to not(Windows) (#10905)
# Description

Limit the test `-p nu-command --test main
commands::run_external::redirect_combine` which uses `sh` to running on
`not(Windows)` like is done for other tests assuming unixy CLI items;
`sh` doesn't exist on Windows.

# User-Facing Changes

None; this is a change to tests only.

# Tests + Formatting

- 🟢 `toolkit fmt`
- 🟢 `toolkit clippy`
- 🟢 `toolkit test`
- 🟢 `toolkit test stdlib`
2023-11-07 16:35:24 +08:00
1874082a2c allow items to properly evaluate block settings (#10980)
# Description

@jntrnr discovered that `items` wasn't properly setting the
`eval_block_with_early_return()` block settings. This change fixes that
which allows `echo` to be redirected and therefore pass data through the
pipeline.

Without `echo`
```nushell
❯ { new: york, san: francisco } | items {|key, value| $'($key) ($value)' }
╭─┬─────────────╮
│0│new york     │
│1│san francisco│
╰─┴─────────────╯
```
With `echo`
```nushell
❯ { new: york, san: francisco } | items {|key, value| echo $'($key) ($value)' }
╭─┬─────────────╮
│0│new york     │
│1│san francisco│
╰─┴─────────────╯
```

# 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-11-06 12:15:37 -06:00
1359b26da2 update items example to send data through the pipeline (#10976)
# Description

This PR updates the `items` example so that it doesn't use `echo`.
`echo` now works like print unless it's being redirected, so it doesn't
send values through the pipeline anymore like the example showed.

# 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-11-06 06:59:13 -06:00
b9bc527d27 Bump crate-ci/typos from 1.16.21 to 1.16.22 (#10968) 2023-11-06 00:57:55 +00:00
51cdd9fbb2 Bump hustcer/setup-nu from 3.7 to 3.8 (#10967) 2023-11-06 00:56:59 +00:00
d838871063 add color-backtrace crate for more intuitive backtraces (#10942)
# Description

Just throwing up this PR because color-backtrace seemed to produce more
useful backtraces. Just curious what others think.

Did this:
1. RUST_BACKTRACE=full cargo r
2. ❯ def test01 [] {
     let sorted = [storm]
     $sorted | range 1.. | zip ($sorted | range ..(-2))
  }
3. test01

I like how it shows the code snippet.


![image](https://github.com/nushell/nushell/assets/343840/1302e766-dfac-4749-a465-85bf53060532)

# 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-11-05 17:19:06 -06:00
4d16d92847 remove unnecessary files (#10966)
# Description

I committed things in my nushell folder that I shouldn't have. oops.

# 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-11-05 15:23:21 -06:00
fc01701a41 updates trash dependency to 3.1.2 (#10965)
# Description

This PR updates the trash dependency from 3.1.0 to 3.1.2 for better
support on FreeBSD.

closes #10961

# 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-11-05 15:00:13 -06:00
51d5d0eac8 Restore test_config tests (#10954)
# Description

These tests got orphaned and they would be a good place to test behavior
I want to add for #10867

# User-Facing Changes

None

# Tests + Formatting

Tests were updated to account for removed test infrastructure

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

# After Submitting

N/A
2023-11-04 15:18:57 -05:00
81d00f71a9 Show plugin extra usage and search terms (#10952)
# Description

The `PluginSignature` type supports extra usage but this was not
available in `plugin_name --help`. It also supports search terms but
these did not appear in `help commands`

New behavior show below is the "Extra usage for nu-example-1" line and
the "Search terms:" line

```
❯ nu-example-1 --help
PluginSignature test 1 for plugin. Returns Value::Nothing

Extra usage for nu-example-1

Search terms: example

Usage:
  > nu-example-1 {flags} <a> <b> (opt) ...(rest)

Flags:
  -h, --help - Display the help message for this command
  -f, --flag - a flag for the signature
  -n, --named <String> - named string

Parameters:
  a <int>: required integer value
  b <string>: required string value
  opt <int>: Optional number (optional)
  ...rest <string>: rest value string

Examples:
  running example with an int value and string value
  > nu-example-1 3 bb
```

Search terms are also available in `help commands`:

```
❯ help commands | where name == "nu-example-1" | select name search_terms
╭──────────────┬──────────────╮
│     name     │ search_terms │
├──────────────┼──────────────┤
│ nu-example-1 │ example      │
╰──────────────┴──────────────╯
```

# User-Facing Changes

Users can now see plugin extra usage and search terms 

# Tests + Formatting

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

# After Submitting

N/A
2023-11-04 15:12:58 -05:00
77fbf3e2d2 better help message for MissingPositional error (#10949)
Added "Use `--help` for more information." to the help of
MissingPositional error
- this PR should close
[#10946](https://github.com/nushell/nushell/issues/10946)

**Before:**

![image](https://github.com/nushell/nushell/assets/1835944/629aeaae-e985-41aa-a791-05ef062e988e)

**After:**

![image](https://github.com/nushell/nushell/assets/1835944/0bc1868c-ffed-4440-ad98-2cf29aa8c656)



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

# 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: Denis Zorya <denis.zorya@trafigura.com>
2023-11-04 12:24:21 -05:00
f565661f42 Fix issues with error make refactor (#10950)
- Replaced one error return `None` with a `help` option.
- Fixed example.
- Added comments highlighting correct early returns.

Fix #10947
2023-11-04 17:23:43 +01:00
1a864ea6f4 Refactor error make (#10923)
- Replaced `start`/`end` with span.
- Fixed standard library.
- Add `help` option.
- Add a couple more errors for invalid record types.

Resolve #10914


# Description



# User-Facing Changes

- **BREAKING CHANGE:** `error make` now takes in `span` instead of
`start`/`end`:

  ```Nushell
  error make {
      msg: "Message"
      label: {
          text: "Label text"
          span: (metadata $var).span
      }
  }
  ```
- `error make` now has a `help` argument for custom error help.
2023-11-03 10:09:33 -05:00
c1738620e3 remove unwraps in registry_query command (#10936)
# Description

After talking to @CAD97, I decided to change these unwraps to expects.
See the comments. The bigger question is, how did unwrap pass the CI?

# 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-11-03 08:12:36 -05:00
56e35fc3f9 Reduce element shifting in Record::retain_mut (#10915)
# Description
Replaces the `Vec::remove` in `Record::retain_mut` with some swaps which
should eliminate the `O(n^2)` complexity due to repeated shifting of
elements.
2023-11-02 20:01:46 +01:00
29591c97a7 Add "shape_keyword" to default config (#10922)
Keep it in sync with Rust code.
Mainly so that people know they can style keywords.

I discovered this while trying to change color of "else".
2023-11-02 19:59:17 +01:00
697dee6750 Change input list to return null (#10913)
Now the `input list` command, when nothing is selected, will return a
null instead of empty string or an empty list.

Resolves #10909.


# User-Facing Changes

`input list` now returns a `null` when nothing is selected.
2023-11-02 19:57:06 +01:00
0ca8fcf58c Integrated Language Server (#10723)
# Description

This commit integrates a language server into nushell so that IDEs don't
have to convert CLI option back and forth.

- fixes https://github.com/nushell/vscode-nushell-lang/issues/117
- fixes https://github.com/jokeyrhyme/nuls/issues/8

Tracking tasks


- [x]
[textDocument/hover](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_hover)
-> `nu --ide-hover`
- [x]
[textDocument/completion](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_completion)
-> `nu --ide-complete`
- [x]
[textDocument/definition](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_definition)
-> `nu --ide-goto-def`
- ~~[ ]
[textDocument/didChange](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_didChange),
[textDocument/didClose](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_didClose),
and
[textDocument/didOpen](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_didOpen)~~
(will be done in a follow-up PR)
- ~~[ ]
[textDocument/inlayHint](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_inlayHint)
-> `nu --ide-check`~~ (will be done in a follow-up PR)
- ~~[ ]
[textDocument/publishDiagnostics](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_publishDiagnostics)
-> `nu --ide-check`~~ (will be done in a follow-up PR)
- ~~[ ]
[workspace/configuration](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_configuration)~~
(will be done in a follow-up PR)
- ~~[ ]
[workspace/didChangeConfiguration](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_didChangeConfiguration)~~
(will be done in a follow-up PR)


# User-Facing Changes

The command line options `--lsp` will start a LSP server.

# 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-11-02 10:18:57 -05:00
a46048f362 Use Record APIs in nu-protocol/nu-engine (#10917)
# Description
Consequences of #10841

This does not yet make the assumption that columns are always
duplicated. Follow the existing logic here

- Use saner record API in `nu-engine/src/eval.rs`
- Use checked record construction in `nu-engine/src/scope.rs`
- Use `values` iterator in `nu-engine/src/scope.rs`
- Use `columns` iterator in `nu_engine::get_columns()`
- Start using record API in `value/mod.rs`
- Use `.insert` in `eval_const.rs` Record code
- Record API for `eval_const.rs` table code

# User-Facing Changes
None

# Tests + Formatting
None
2023-11-01 23:19:58 +01:00
0569a9c92e Disallow duplicated columns in table literals (#10875)
# Description
Pretty much all operations/commands in Nushell assume that the column
names/keys in a record and thus also in a table (which consists of a
list of records) are unique.
Access through a string-like cell path should refer to a single column
or key/value pair and our output through `table` will only show the last
mention of a repeated column name.

```nu
[[a a]; [1 2]]
╭─#─┬─a─╮
│ 0 │ 2 │
╰───┴───╯
```

While the record parsing already either errors with the
`ShellError::ColumnDefinedTwice` or silently overwrites the first
occurence with the second occurence, the table literal syntax `[[header
columns]; [val1 val2]]` currently still allowed the creation of tables
(and internally records with more than one entry with the same name.

This is not only confusing, but also breaks some assumptions around how
we can efficiently perform operations or in the past lead to outright
bugs (e.g. #8431 fixed by #8446).

This PR proposes to make this an error.
After this change another hole which allowed the construction of records
with non-unique column names will be plugged.

## Parts
- Fix `SE::ColumnDefinedTwice` error code
- Remove previous tests permitting duplicate columns
- Deny duplicate column in table literal eval
- Deny duplicate column in const eval
- Deny duplicate column in `from nuon`

# User-Facing Changes
`[[a a]; [1 2]]` will now return an error:

```
Error: nu:🐚:column_defined_twice

  × Record field or table column used twice
   ╭─[entry #2:1:1]
 1 │ [[a a]; [1 2]]
   ·   ┬ ┬
   ·   │ ╰── field redefined here
   ·   ╰── field first defined here
   ╰────
```

this may under rare circumstances block code from evaluating.

Furthermore this makes some NUON files invalid if they previously
contained tables with repeated column names.

# Tests + Formatting
Added tests for each of the different evaluation paths that materialize
tables.
2023-11-01 21:25:35 +01:00
c1ca10ffd1 allow compact to also compact empty strings (#10912)
# Description

This change allows `compact` to also compact things with empty strings,
empty lists, and empty records if the `--empty` switch is used. Let's
add a quality-of-life improvement here to just compact all this mess. If
this is a bad idea, please cite examples demonstrating why.

```
❯ [[name position]; [Francis Lead] [Igor TechLead] [Aya null]] | compact position
╭#┬─name──┬position╮
│0│Francis│Lead    │
│1│Igor   │TechLead│
╰─┴───────┴────────╯
❯ [[name position]; [Francis Lead] [Igor TechLead] [Aya ""]] | compact position --empty
╭#┬─name──┬position╮
│0│Francis│Lead    │
│1│Igor   │TechLead│
╰─┴───────┴────────╯
❯ [1, null, 2, "", 3, [], 4, {}, 5] | compact
╭─┬─────────────────╮
│0│                1│
│1│                2│
│2│                 │
│3│                3│
│4│[list 0 items]   │
│5│                4│
│6│{record 0 fields}│
│7│                5│
╰─┴─────────────────╯
❯ [1, null, 2, "", 3, [], 4, {}, 5] | compact --empty
╭─┬─╮
│0│1│
│1│2│
│2│3│
│3│4│
│4│5│
╰─┴─╯
```

# 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-11-01 13:56:25 -05:00
15c22db8f4 Make FromValue take owned Values (#10900)
# Description
Changes `FromValue` to take owned `Value`s instead of borrowed `Value`s.
This eliminates some unnecessary clones (e.g., in `call_ext.rs`).

# User-Facing Changes
Breaking API change for `nu_protocol`.
2023-10-31 19:47:00 +01:00
1c52b112c8 Return external file completions if not empty (#10898)
<!--
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.
-->
If an external completer is used and it returns no completions for a
filepath, we fall back to the builtin path completer.

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

Path completions will remain consistent with the use of an external
completer.

# 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-31 11:32:21 -05:00
275dba82d5 fix: preserve path when completing intermediate directory (#10831)
<!--
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 #10766

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

If the partial supplied to the completion function is shorter than the
span, the cursor is in between the path, we are trying to complete an
intermediate directory. In such a case we:
- only suggest directory names
- don't append the slash since it is already present
- only complete the path till the component the cursor is on

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

Intermediate directories can be completed without erasing the rest of
the path.

# 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-31 07:39:14 -05:00
cf7040a215 Refactor: introduce a gen_save_call function to reduce duplicate code (#10852)
make a little refactor on relative code to make it more
readable.
2023-10-31 10:45:36 +08:00
72cb4b6032 Reuse Closure type in Value::Closure (#10894)
# Description
Reuses the existing `Closure` type in `Value::Closure`. This will help
with the span refactoring for `Value`. Additionally, this allows us to
more easily box or unbox the `Closure` case should we chose to do so in
the future.

# User-Facing Changes
Breaking API change for `nu_protocol`.
2023-10-30 23:34:23 +01:00
d4cbab454e Change category of scope commands to core (#10892)
close #10802
2023-10-30 19:55:40 +01:00
3645178ff1 Convert "pure" macros to pure fn in config.rs (#10893)
# Description
These macros simply took a `Span` and a shared reference to `Config` and
returned a Value, for better readability and reasoning about their
behavior convert them to simple function as they don't do anything
relevant with their macro powers.


# User-Facing Changes
None

# Tests + Formatting
(-)
2023-10-30 19:54:59 +01:00
005180f269 Add Record::remove/retain/retain_mut (#10876)
# Description
While we have now a few ways to add items or iterate over the
collection, we don't have a way to cleanly remove items from `Record`.

This PR fixes that:

- Add `Record.remove()` to remove by key
- makes the assumption that keys are unique, so can not be used
universally, yet (see #10875 for an important example)
- Add naive `Record.retain()` for inplace removal
- This follows the two separate `retain`/`retain_mut` in the Rust std
library types, compared to the value-mutating `retain` in `indexmap`
- Add `Record.retain_mut()` for one-pass pruning

Continuation of #10841 

# User-Facing Changes
None yet.

# Tests + Formatting
Doctests for the `retain`ing fun
2023-10-30 19:51:28 +01:00
72f7b9b7cc Add umkdir command (#10785)
A `mkdir` command, which uses `uu_mkdir` as backend.

close #10515.
2023-10-30 07:59:48 -05:00
3f61ca19f0 Bump hustcer/setup-nu from 3.6 to 3.7 (#10878) 2023-10-30 12:53:22 +00:00
d8c59eddb3 Bump rust-ini from 0.19.0 to 0.20.0 (#10882) 2023-10-30 11:56:13 +00:00
ac43372618 Bump scraper from 0.17.1 to 0.18.1 (#10879) 2023-10-30 11:53:26 +00:00
dccb2b48f3 Bump crate-ci/typos from 1.16.20 to 1.16.21 (#10877) 2023-10-30 10:19:51 +00:00
2e68e6ddbf allow sort-by to work with records (#10870)
# Description

This PR restores and old functionality that must of been broken with the
input_output_types() updating. It allows commands like this to work
again.

```nushell
open $nu.history-path | 
  get history.command_line | 
  split column ' ' cmd | 
  group-by cmd --to-table | 
  update items {|u| $u.items | length} | 
  sort-by items -r | 
  first 10 | 
  table -n 1
```
output
```
╭#─┬group─┬items╮
│1 │exit  │ 3004│
│2 │ls    │ 2591│
│3 │git   │ 1678│
│4 │help  │ 1549│
│5 │open  │ 1374│
│6 │cd    │ 1186│
│7 │cargo │  944│
│8 │let   │  784│
│9 │source│  755│
│10│z     │  486│
╰#─┴group─┴items╯
```

# 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-29 08:22:20 -05:00
3dfe1a4f0e group-by now returns a table instead of a record (#10848)
# Description

Previously `group-by` returned a record containing each group as a
column. This data layout is hard to work with for some tasks because you
have to further manipulate the result to do things like determine the
number of items in each group, or the number of groups. `transpose` will
turn the record returned by `group-by` into a table, but this is
expensive when `group-by` is run on a large input.

In a discussion with @fdncred [several
workarounds](https://github.com/nushell/nushell/discussions/10462) to
common tasks were discussed, but they seem unsatisfying in general.

Now when `group-by --to-table` is used a table is returned with the
columns "groups" and "items" making it easier to do things like count
the number of groups (`| length`) or count the number of items in each
group (`| each {|g| $g.items | length`)

# User-Facing Changes

* `group-by` returns a `table` with "group" and "items" columns instead
of a `record` with one column per group name

# Tests + Formatting

Tests for `group-by` were updated

# After Submitting

* No breaking changes were made. The new `--to-table` switch should be
added automatically to the [`group-by`
documentation](https://www.nushell.sh/commands/docs/group-by.html)
2023-10-28 14:15:14 -05:00
c87bac04c0 Add common map-like API to nu_protocol::Record (#10841)
# Description

> Our `Record` looks like a map, quacks like a map, so let's treat it
with the API for a map

Implement common methods found on e.g. `std::collections::HashMap` or
the insertion-ordered [indexmap](https://docs.rs/indexmap).

This allows contributors to not have to worry about how to get to the
relevant items and not mess up the assumptions of a Nushell record.

## Record assumptions
- `cols` and `vals` are of equal length
- for all practical purposes, keys/columns should be unique

## End goal

The end goal of the upcoming series of PR's is to allow us to make
`cols` and `vals` private.
Then it would be possible to exchange the backing datastructure to best
fit the expected workload.
This could be statically (by finding the best balance) or dynamically by
using an `enum` of potential representations.

## Parts
- Add validating explicit part constructor
`Record::from_raw_cols_vals()`
- Add `Record.columns()` iterator
- Add `Record.values()` iterator
- Add consuming `Record.into_values()` iterator
- Add `Record.contains()` helper
- Add `Record.insert()` that respects existing keys
- Add key-based `.get()`/`.get_mut()` to `Record`
- Add `Record.get_index()` for index-based access
- Implement `Extend` for `Record` naively
- Use checked constructor in `record!` macro
- Add `Record.index_of()` to get index by key

# User-Facing Changes
None directly

# Developer facing changes
You don't have to roll your own record handling and can use a familiar
API

# Tests + Formatting
No explicit unit tests yet. Wouldn't be too tricky to validate core
properties directly.
Will be exercised by the following PRs using the new
methods/traits/iterators.
2023-10-28 15:18:41 +02:00
4b301710d3 Convert more examples and tests to record! macro (#10840)
# Description
Use `record!` macro instead of defining two separate `vec!` for `cols`
and `vals` when appropriate.
This visually aligns the key with the value.
Further more you don't have to deal with the construction of `Record {
cols, vals }` so we can hide the implementation details in the future.

## State

Not covering all possible commands yet, also some tests/examples are
better expressed by creating cols and vals separately.

# User/Developer-Facing Changes
The examples and tests should read more natural. No relevant functional
change

# Bycatch

Where I noticed it I replaced usage of `Value` constructors with
`Span::test_data()` or `Span::unknown()` to the `Value::test_...`
constructors. This should make things more readable and also simplify
changes to the `Span` system in the future.
2023-10-28 14:52:31 +02:00
7d67ca3652 [nu-cmd-base] add missing LICENSE text (#10855)
# Description
Adds license text to the `nu-cmd-base` crate, copied from `nu-cmd-lang`

# User-Facing Changes
N/A

# Tests + Formatting
```
$ cargo package --allow-dirty --no-verify
$ bsdtar tf ../../target/package/nu-cmd-base-0.86.1.crate | grep LICENSE
```

# After Submitting
N/A

Signed-off-by: Michel Lind <salimma@fedoraproject.org>
2023-10-27 15:55:03 -05:00
01d8961eb7 use to_lowercase in str downcase (#10850)
# Description
as we can see in the [documentation of
`str.to_lowercase`](https://doc.rust-lang.org/std/primitive.str.html#method.to_lowercase),
not only ASCII symbols have lower and upper variants.

- `str upcase` uses the correct method to convert the string

7ac5a01e2f/crates/nu-command/src/strings/str_/case/upcase.rs (L93)
- `str downcase` incorrectly converts only ASCII characters

7ac5a01e2f/crates/nu-command/src/strings/str_/case/downcase.rs (L124)

this PR uses `str.to_lower_case` instead of `str.to_ascii_lowercase` in
`str downcase`.

# User-Facing Changes
- upcase still works fine
```nushell
~ l> "ὀδυσσεύς" | str upcase
ὈΔΥΣΣΕΎΣ
```
- downcase now works

👉 before
```nushell
~ l> "ὈΔΥΣΣΕΎΣ" | str downcase
ὈΔΥΣΣΕΎΣ
```
👉 after
```nushell
~ l> "ὈΔΥΣΣΕΎΣ" | str downcase
ὀδυσσεύς
```

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

adds two tests
- `non_ascii_upcase`
- `non_ascii_downcase`

# After Submitting
2023-10-27 19:16:17 +02:00
7ac5a01e2f deprecate glob --not in favor of glob --exclude (#10827)
# Description
looking at the [Wax documentation about
`wax::Walk.not`](https://docs.rs/wax/latest/wax/struct.Walk.html#examples),
especially
> therefore does not read directory trees from the file system when a
directory matches an [exhaustive glob
expression](https://docs.rs/wax/latest/wax/trait.Pattern.html#tymethod.is_exhaustive)

> **Important**
> in the following of this PR description, i talk about *pruning* and a
`--prune` option, but this has been changed to *exclusion* and
`--exclude` after a discussion with @fdncred.

this looks like a *pruning* operation to me, right? 😮 
i wanted to make the `glob` option `--not` clearer about that, because
>   -n, --not <List(String)> - Patterns to exclude from the results

from `help glob` is not very explicit about whether the search is pruned
when entering a directory matching a pattern in `--not` or just removing
it from the output 😕

## changelog
this PR proposes to rename the `glob --not` option to `glob --prune` and
make it's documentation more explicit 😋

## benchmarking
to support the *pruning* behaviour put forward above, i've run a
benchmark
1. define two closures to compare the behaviour between removing
patterns manually or using `--not`
```nushell
let where = {
    [.*/\.local/.*, .*/documents/.*, .*/\.config/.*]
        | reduce --fold (glob **) {|pat, acc| $acc | where $it !~ $pat}
        | length
}
```
```nushell
let not = { glob ** --not [**/.local/**, **/documents/**, **/.config/**] | length }
```
2. run the two to make sure they give similar results
```nushell
> do $where
33424
```
```nushell
> do $not
33420
```
👌 
3. measure the performance
```nushell
use std bench
```
```nushell
> bench --verbose --pretty --rounds 25 $not
44ms 52µs 285ns +/- 977µs 571ns
```
```nushell
> bench --verbose --pretty --rounds 5 $where
1sec 250ms 187µs 99ns +/- 8ms 538µs 57ns
```

👉 we can see that the results are (almost) the same but
`--not` is much faster, looks like pruning 😋

# User-Facing Changes
- `--not` will give a warning message but still work
- `--prune` will work just as `--not` without warning and with a more
explicit doc
- `--prune` and `--not` at the same time will give an error

# Tests + Formatting
this PR fixes the examples of `glob` using the `--not` option.

# After Submitting
prepare the removal PR and mention in release notes.
2023-10-25 17:11:57 +02:00
e2fb0e5b82 implement whoami using uutils (#10488)
<!--
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.
-->

Implements `whoami` using the `whoami` command from uutils as backend.
This is a draft because it depends on
https://github.com/uutils/coreutils/pull/5310 and a new release of
uutils needs to be made (and the paths in `Cargo.toml` should be
updated). At this point, this is more of a proof of concept 😄

Additionally, this implements a (simple and naive) conversion from the
uutils `UResult` to the nushell `ShellError`, which should help with the
integration of other utils, too. I can split that off into a separate PR
if desired.

I put this command in the "platform" category. If it should go somewhere
else, let me know!

The tests will currently fail, because I've used a local path to uutils.
Once the PR on the uutils side is merged, I'll update it to a git path
so that it can be tested and runs on more machines than just mine.

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

New `whoami` command. This might break some users who expect the system
`whoami` command. However, the result of this new command should be very
close, just with a nicer help message, at least for Linux users. The
default `whoami` on Windows is quite different from this implementation:
https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/whoami

# 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>
2023-10-25 09:53:52 -05:00
a11e41332c expand paths and split PATH in std path add (#10710)
related to
-
https://discord.com/channels/601130461678272522/614593951969574961/1162406310155923626

# Description
this PR
- does a bit of minor refactoring
- makes sure the input paths get expanded
- makes sure the input PATH gets split on ":"
- adds a test
- fixes the other tests

# User-Facing Changes
should give a better overall experience with `std path add`

# Tests + Formatting
adds a new test case to the `path_add` test and fixes the others.

# After Submitting
2023-10-25 16:43:27 +02:00
f3656f7822 sync $env.config.filesize.metric (#10277)
# Description
just noticed `$env.config.filesize.metric` is not the same in
`default_config.nu` and `config.rs`

# User-Facing Changes
filesizes will show in "binary" mode by default when using the default
config files, i.e. `kib` instead of `kb`.

# Tests + Formatting

# After Submitting
2023-10-25 16:42:24 +02:00
38f4ab0bc9 updated NU_LIB_DIRS delimiter for command line (#10837)
# Description

This PR corrects some help text by stating what the real delimiter is
for the `--include-path` command line parameter which is `char
record_sep` aka `\x1e`. Up to this point, this has really only been used
for the vscode extension to setup the NU_LIB_DIRS env var correctly. We
tried `:` and `;` and neither would work so we had to choose something
that wouldn't be confused so easily.

# 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-25 09:38:20 -05:00
f35741d50e redirection: fix internal commands error with o+e> redirection (#10816)
# Description
Currently the following command is broken:
```nushell
echo a o+e> 1.txt
```

It's because we don't redirect output of `echo` command. This pr is
trying to fix it.
2023-10-25 16:35:51 +02:00
d93315d8f5 Fix describe -d for lazy records (#10836)
<!--
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 fixes an overlook from a previous PR. It now correctly returns
the details on lazy records.

# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->
Describe detailed now returns the expected result.
2023-10-25 08:04:37 -05:00
8429aec57f readd update flag to cp command (#10824)
# Description
- this PR should close #10819


# User-Facing Changes
Behaviour is similar to pre 0.86.0 behaviour of the cp command and
should as such not have a user-facing change, only compared to the
current version, were the option is readded.


# After Submitting
I guess the documentation will be automatically updated and as this
feature is no further highlighted, probably, no more work will be needed
here.

# Considerations
coreutils actually allows a third option:
```
pub enum UpdateMode {
    // --update=`all`,
    ReplaceAll,
    // --update=`none`
    ReplaceNone,
    // --update=`older`
    // -u
    ReplaceIfOlder,
}
```
namely `ReplaceNone`, which I have not added. Also I think that
specifying `--update 'abc'` is non functional.
2023-10-25 11:30:13 +02:00
f043a8a8ff redirect should have a target (#10835)
# Description
Fixes:  #10830 

The issue happened during lite-parsing, when we want to put a
`LiteElement` to a `LitePipeline`, we do nothing if relative redirection
target is empty.

So the command `echo aaa o> | ignore` will be interpreted to `echo aaa |
ignore`.

This pr is going to check and return an error if redirection target is
empty.

# User-Facing Changes
## Before
```
❯ echo aaa o> | ignore   # nothing happened
```

## After
```nushell
❯ echo aaa o> | ignore
Error: nu::parser::parse_mismatch

  × Parse mismatch during operation.
   ╭─[entry #1:1:1]
 1 │ echo aaa o> | ignore
   ·          ─┬
   ·           ╰── expected redirection target
   ╰────
```
2023-10-25 11:19:35 +02:00
c6016d7659 Dataframe support for small int types (#10828)
Turned features to allow signed and unsigned 8 and 16 bit types.

---------

Co-authored-by: Jack Wright <jack.wright@disqo.com>
2023-10-24 21:25:21 -05:00
78b4472b32 Support pattern matching null literals (#10829)
# Description
Support pattern matching against the `null` literal.  Fixes #10799 

### Before
```nushell
> match null { null => "success", _ => "failure" }
failure
```

### After
```nushell
> match null { null => "success", _ => "failure" }
success
```

# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->
Users can pattern match against a `null` literal.
2023-10-25 06:30:45 +08:00
cb754befe9 fix: Ensure consistent vals and cols when parsing with --flexible (#10814)
# Description
`from tsv` and `from csv` both support a `--flexible` flag. This flag
can be used to "allow the number of fields in records to be variable".

Previously, a record's invariant that `rec.cols.len() == rec.vals.len()`
could be broken during parsing. This can cause runtime errors as in
#10693. Other commands, like `select` were also affected.

The inconsistencies are somewhat hard to see, as most nushell code
assumes an equal number of columns and values.

# Before

### Fewer values than columns
```nushell
> let record = (echo "one,two\n1" | from csv --flexible | first)
# There are two columns
> $record | columns | to nuon
[one, two]
# But only one value
> $record | values | to nuon
[1]
# And printing the record doesn't show the second column!
> $record | to nuon
{one: 1}
```

### More values than columns
```nushell
> let record = (echo "one,two\n1,2,3" | from csv --flexible | first)
# There are two columns
> $record | columns | to nuon
[one, two]
# But three values
> $record | values | to nuon
[1, 2, 3]
# And printing the record doesn't show the third value!
> $record | to nuon
{one: 1, two: 2}
```
# After

### Fewer values than columns
```nushell
> let record = (echo "one,two\n1" | from csv --flexible | first)
# There are two columns
> $record | columns | to nuon
[one, two]
# And a matching number of values
> $record | values | to nuon
[1, null]
# And printing the record works as expected
> $record | to nuon
{one: 1, two: null}
```

### More values than columns
```nushell
> let record = (echo "one,two\n1,2,3" | from csv --flexible | first)
# There are two columns
> $record | columns | to nuon
[one, two]
# And a matching number of values
> $record | values | to nuon
[1, 2]
# And printing the record works as expected
> $record | to nuon
{one: 1, two: 2}
```

# User-Facing Changes
Using the `--flexible` flag with `from csv` and `from tsv` will not
result in corrupted record state.

# 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-24 15:54:26 -05:00
0588a4fc19 Make debug info lazy (#10728)
<!--
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.
-->

* Makes the `debug info` lazy which greatly improves performance.
* Adds a `thread id` attribute

![Screenshot 2023-10-15
211940](https://github.com/nushell/nushell/assets/25441359/b8457a30-ebf7-4731-9e13-17635501f029)

![image](https://github.com/nushell/nushell/assets/25441359/010ed35b-9f50-4fc6-8650-b68b29d5a9cd)


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

`threadid` column added.

---------

Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2023-10-24 12:48:05 -05:00
ff3a0a0de3 fix main not building due to errors later found in describe (#10821)
# Description

This is just a fixup PR. There was a describe PR that passed CI but then
later didn't pass main. This PR fixes that issue.

# 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-23 13:22:32 -05:00
c799f77577 Add detailed flag for describe (#10795)
- Add `detailed` flag for `describe`

- Improve detailed describe and better format when running examples.

# Rationale

For now, neither `describe` nor any of the `debug` commands provide an
easy and structured way of inspecting the data's type and more. This
flag provides a structured way of getting such information. Allows also
to avoid the rather hacky solution
```nu
$in | describe | str replace --regex '<.*' ''
```

# User-facing changes

Adds a new flag to ``describe`.
2023-10-23 09:12:11 -05:00
d3182a6737 Revert "Bump regex from 1.9.6 to 1.10.2" (#10818)
Reverts nushell/nushell#10812

This goes back to a version of `regex` and its dependencies that is
shared with a lot of our other dependencies. Before this we did not
duplicate big dependencies of `regex` that affect binary size and
compile time.

As there is no known bug or security problem we suffer from, we can wait
on receiving the performance improvements to `regex` with the rest of
our `regex` dependents.
2023-10-23 09:11:32 -05:00
b5e09b8a30 Improve registry value return types (#10806)
r? @fdncred
Last one, I hope. At least short of completely redesigning `registry
query`'s interface. (Which I wouldn't implement without asking around
first.)

# Description

User-Facing Changes has the general overview. Inline comments provide a
lot of justification on specific choices. Most of the type conversions
should be reasonably noncontroversial, but expanding `REG_EXPAND_SZ`
needs some justification. First, an example of the behavior there:

```shell
> # release nushell:
> version | select version commit_hash | to md --pretty
| version | commit_hash                              |
| ------- | ---------------------------------------- |
| 0.85.0  | a6f62e05ae |
> registry query --hkcu Environment TEMP | get value
%USERPROFILE%\AppData\Local\Temp

> # with this patch:
> version | select version commit_hash | to md --pretty
| version | commit_hash                              |
| ------- | ---------------------------------------- |
| 0.86.1  | 0c5a4c991f |
> registry query --hkcu Environment TEMP | get value
C:\Users\CAD\AppData\Local\Temp

> # Microsoft CLI tooling behavior:
> ^pwsh -c `(Get-ItemProperty HKCU:\Environment).TEMP`
C:\Users\CAD\AppData\Local\Temp
> ^reg query HKCU\Environment /v TEMP
HKEY_CURRENT_USER\Environment
    TEMP    REG_EXPAND_SZ    %USERPROFILE%\AppData\Local\Temp
```

As noted in the inline comments, I'm arguing that it makes more sense to
eagerly expand the %EnvironmentString% placeholders, as none of
Nushell's path functionality will interpret these placeholders. This
makes the behavior of `registry query` match the behavior of pwsh's
`Get-ItemProperty` registry access, and means that paths (the most
common use of `REG_EXPAND_SZ`) are actually usable.

This does *not* break nu_script's
[`update-path`](https://github.com/nushell/nu_scripts/blob/main/sourced/update-path.nu);
it will just be slightly inefficient as it will not find any
`%Placeholder%`s to manually expand anymore. But also, note that
`update-path` is currently *wrong*, as a path including
`%LocalAppData%Low` is perfectly valid and sometimes used (to go to
`Appdata\LocalLow`); expansion isn't done solely on a path segment
basis, as is implemented by `update-path`.

I believe that the type conversions implemented by this patch are
essentially always desired. But if we want to keep `registry query`
"pure", we could easily introduce a `registry get`[^get] which does the
more complete interpretation of registry types, and leave `registry
query` alone as doing the bare minimum. Or we could teach `path expand`
to do `ExpandEnvironmentStringsW`. But REG_EXPAND_SZ being the odd one
out of not getting its registry type semantics decoded by `registry
query` seems wrong.

[^get]: This is the potential redesign I alluded to at the top. One
potential change could be to make `registry get Environment` produce
`record<Path: string, TEMP: string, TMP: string>` instead of `registry
query`'s `table<name: string, value: string, type: string>`, the idea
being to make it feel as native as possible. We could even translate
between Nu's cell-path and registry paths -- cell paths with spaces do
actually work, if a bit awkwardly -- or even introduce lazy records so
the registry can be traversed with normal data manipulation ... but that
all seems a bit much.

# User-Facing Changes

- `registry query`'s produced `value` has changed. Specifically:
-  Rows `where type == REG_EXPAND_SZ` now expand `%EnvironmentVarable%`
placeholders for you. For example, `registry query --hkcu Environment
TEMP | get value` returns `C:\Users\CAD\AppData\Local\Temp` instead of
`%USERPROFILE%\AppData\Local\Temp`.
- You can restore the old behavior and preserve the placeholders by
passing a new `--no-expand` switch.
- Rows `where type == REG_MULTI_SZ` now provide a `list<string>` value.
They previously had that same list, but `| str join "\n"`.
- Rows `where type == REG_DWORD_BIG_ENDIAN` now provide the correct
numeric value instead of a byte-swapped value.
- Rows `where type == REG_QWORD` now provide the correct numeric
value[^sign] instead of the value modulo 2<sup>32</sup>.
- Rows `where type == REG_LINK` now provide a string value of the link
target registry path instead of an internal debug string representation.
(This should never be visible, as links should be transparently
followed.)
- Rows `where type =~ RESOURCE` now provide a binary value instead of an
internal debug string representation.

[^sign]: Nu's `int` is a signed 64-bit integer. As such, values >=
2<sup>63</sup> will be reported as their negative two's compliment
value. This might sometimes be the correct interpretation -- the
registry does not distinguish between signed and unsigned integer values
-- but regedit and pwsh display all values as unsigned.
2023-10-23 07:21:27 -05:00
05efd735b9 Bump which from 4.4.2 to 5.0.0 (#10811) 2023-10-23 14:14:28 +08:00
5e0499fcf9 Bump uuid from 1.4.1 to 1.5.0 (#10810) 2023-10-23 14:14:08 +08:00
74d3f3c1d6 Bump regex from 1.9.6 to 1.10.2 (#10812) 2023-10-23 14:13:57 +08:00
de6edf18d9 Bump crate-ci/typos from 1.16.19 to 1.16.20 (#10813) 2023-10-23 14:13:44 +08:00
a35ecb4837 Finish removing profile command and related data (#10807) 2023-10-22 14:06:53 +03:00
a01ef85bda Remove registry clean_string hack (#10804)
# Description

Remove the `clean_string` hack used in `registry query`.

This was a workaround for a [bug][gentoo90/winreg-rs#52] in winreg which
has since [been fixed][edf9eef] and released in [winreg v0.12.0].

winreg now properly displays strings in RegKey's Display impl instead of
outputting their debug representation. We remove our `clean_string` such
that registry entries which happen to start/end with `"` or contain `\\`
won't get mangled. This is very important for entries in UNC path format
as those begin with a double backslash.

[gentoo90/winreg-rs#52]:
<https://github.com/gentoo90/winreg-rs/issues/52>
[edf9eef]:
<edf9eef38f>
[winreg v0.12.0]:
<https://github.com/gentoo90/winreg-rs/releases/tag/v0.12.0>

# User-Facing Changes

- `registry query` used to accidentally mangle values that contain a
literal `\\`, such as UNC paths. It no longer does so.

# Tests + Formatting

- [X] `toolkit check pr`
  - 🟢 `toolkit fmt`
  - 🟢 `toolkit clippy`
  - 🟢 `toolkit test`
  - 🟢 `toolkit test stdlib`
2023-10-21 18:50:34 -05:00
6445c4e7de Do not use white text in the default light theme (#10796)
Use instead 'dark_gray', the default fg color for the other primitives.

fixes #10636
2023-10-21 16:31:46 -05:00
066c9118ae Update Nushell version to v0.86 for release script (#10797)
# Description
Follow up https://github.com/nushell/nushell/pull/10762, align with the
latest version
2023-10-21 19:13:25 +02:00
52e8b0afb2 Deprecate size to str stats (#10798)
<!--
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.
-->

Rename `str size` to `str stats`, for more detail see:
https://github.com/nushell/nushell/pull/10772

# 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-21 11:21:34 -05:00
db3f3eaf5a Move ansi link from extra to default feature, close #10792 (#10801)
<!--
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.
-->

Move `ansi link` from extra to default feature, close #10792

# 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-21 11:04:37 -05:00
878f0cf6e1 Add long options for viewers (#10787)
![](http://s2.quickmeme.com/img/7f/7f77546945f948560cdc26b12b99d5ccd390c2e39d2849d3423ae7608dac066a.jpg)
2023-10-20 11:43:42 -05:00
7caf27b665 add toolkit run to run a Nushell revision (#10687)
# Description
when i try out a PR, i always end up running `cargo run` but then i
never know if i'm inside my install of Nushell or a PR 👀

in this PR i propose to add a `run` command to the `toolkit.nu` which
- runs the current revision inside `cargo run`
- adds a clear right prompt to make sure one knows they are in `cargo
run`

# User-Facing Changes
an example after running `toolkit run`

![tk-run](https://github.com/nushell/nushell/assets/44101798/1039f406-e413-495a-8e31-5aea99700aa4)


# Tests + Formatting

# After Submitting
2023-10-20 15:55:46 +02:00
22b375ccd4 Spell out our platform support policy (#10778)
This reflects how we currently distributed our efforts to supporting the
different platforms and clarifies which things get run by the Nushell
team and which rely on the help of third-parties or individual
contributors.

Feel free to propose improvements, as long as they can be backed up by
implemented practice as a result.
2023-10-20 11:35:16 +02:00
6a2539534f deprecate size to str size (#10772)
related to
-
https://discord.com/channels/601130461678272522/614613939334152217/1164530991931605062

# Description
it appears `size` is a command that operates on `string`s only and gives
the user information about the chars, graphemes and bytes of a string.
this looks like a command that should be a subcommand to `str` 😏 

this PR
- adds `str size`
- deprecates `size`

`size` is planned to be removed in 0.88

# User-Facing Changes
`str size` can be used for the same result as `size`.

# Tests + Formatting

# After Submitting
write a removal PR for `size`
2023-10-20 11:34:55 +02:00
f310a9be8c Make hints aware of the current directory (#10780)
This commit uses the new `CwdAwareHinter` in reedline. Closes #8883.

# Description

Currently, the history based hints show results from all directories,
while most commands make sense only in the directory they were run in.
This PR makes hints take the current directory into account.

# User-Facing Changes

Described above.

I haven't yet added a config option for this, because I personally
believe folks won't be against it once they try it out. We can add it if
people complain, there's some time before the next release.

Fish has this without a config option too.

# Tests + Formatting

If tests are needed, I'll need help as I'm not well versed with the
codebase.
2023-10-20 11:21:58 +02:00
d0dc6986dd Use long options for string (#10777) 2023-10-19 22:08:09 +02:00
11480c77be Add long options for path (#10775) 2023-10-19 22:07:01 +02:00
4fd2b702ee Add long options for platform and random (#10776) 2023-10-19 22:04:33 +02:00
030e55acbf add unfold back with a deprecation warning (#10771)
related to
- https://github.com/nushell/nushell/pull/10770

# Description
because some people look into `unfold` already (myself included lol) and
there will be 4 weeks with that new command which has a decent section
in the release note, i fear that
https://github.com/nushell/nushell/pull/10770 is a bit too brutal,
removing `unfold` without any warning...

this PR brings `unfold` back to life.
the `unfold` command will have a deprecation warning and will be removed
in 0.88.

# User-Facing Changes
`unfold` is only deprecated, not removed.

# Tests + Formatting

# After Submitting
2023-10-19 19:23:06 +02:00
c5e1b64b40 remove random integer in favor of random int (#10568)
related to
- https://github.com/nushell/nushell/pull/10520

# Description
this PR is a followup to https://github.com/nushell/nushell/pull/10520
and removes the `random integer` command completely, in favor of `random
int`.

# User-Facing Changes
`random integer` has been fully moved to `random int`
```nushell
> random integer 0..1
Error: nu::parser::extra_positional

  × Extra positional argument.
   ╭─[entry #1:1:1]
 1 │ random integer 0..1
   ·        ───┬───
   ·           ╰── extra positional argument
   ╰────
  help: Usage: random
```

# Tests + Formatting
tests have been moved from
`crates/nu-command/tests/commands/random/integer.rs` to
`crates/nu-command/tests/commands/random/int.rs`

# After Submitting
mention in 0.87.0 release notes
2023-10-19 18:42:07 +02:00
999f7b229f Remove to xml --pretty (#10668)
followup to
- https://github.com/nushell/nushell/pull/10660
2023-10-19 18:41:54 +02:00
de1c7bb39f remove the $nothing variable (#10567)
related to 
- https://github.com/nushell/nushell/pull/10478

# Description
this PR is the followup removal to
https://github.com/nushell/nushell/pull/10478.

# User-Facing Changes
`$nothing` is now an undefined variable, unless define by the user.
```nushell
> $nothing
Error: nu::parser::variable_not_found

  × Variable not found.
   ╭─[entry #1:1:1]
 1 │ $nothing
   · ────┬───
   ·     ╰── variable not found.
   ╰────
```

# Tests + Formatting

# After Submitting
mention that in release notes
2023-10-19 18:41:38 +02:00
54bc662e0e Add long options for generators and math (#10752) 2023-10-19 18:17:42 +02:00
5f2089a15b Add long options for misc and network (#10753) 2023-10-19 18:16:44 +02:00
adb99938f7 rename unfold to generate (#10770)
# Description

This PR renames the `unfold` command to `generate`.
closes #10760

# 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-19 09:30:34 -05:00
b907939916 Extract common logic for setting error in parse_short_flags (#10709)
# Description

Since the `else` clause for the nested branches check for the first
unmatched argument, this PR brings together all the conditions where the
positional argument shape is numeric using the `matches!` keyword. This
also allows us to and (`&&`) the condition with when no short flags are
found unlike the `if let ...` statements. Finally, we can handle any
`unmatched_short_flags` at one place.

# User-Facing Changes

No user facing changes.
2023-10-19 13:24:57 +02:00
27e6271402 Implement modulo for duration (#10745)
# Description
This PR adds the ability to use modulo with durations:

```nu
(2min + 31sec) mod 20sec # 11sec
```

# User-Facing Changes

Allows to use `<duration> mod <duration>`
2023-10-19 12:27:00 +02:00
0a8f27f6f2 Allow empty list inputs in group-by and return empty record (#10730)
# Description

Changed `group-by` behavior to accept empty list as input and return an
empty record instead of throwing an error. I also replaced
`errors_if_input_empty()` test to reflect the new expected behavior.

See #10713 

# User-Facing Changes
`[] | group-by` or `[] | group-by a` now returns empty record


# Tests + Formatting
1 test for emptied table i.e. list

---------

Signed-off-by: Oscar <71343264+0scvr@users.noreply.github.com>
2023-10-19 12:20:52 +02:00
1662e61ecb deprecate def-env and export def-env (#10715)
follow-up to
- https://github.com/nushell/nushell/pull/10566

# Description
this PR deprecates the use of `def-env` and `export def-env`

these two core commands will be removed in 0.88

# User-Facing Changes
using `def-env` will give a warning
```nushell
> def-env foo [] { print "foo" }; foo
Error:   × Deprecated command
   ╭─[entry #1:1:1]
 1 │ def-env foo [] { print "foo" }; foo
   · ───┬───
   ·    ╰── `def-env` is deprecated and will be removed in 0.88.
   ╰────
  help: Use `def --env` instead


foo
```

# Tests + Formatting

# After Submitting
2023-10-19 13:50:16 +08:00
b58819d51e deprecate extern-wrapped and export extern-wrapped (#10716)
follow-up to
- https://github.com/nushell/nushell/pull/10566

# Description
this PR deprecates the use of `extern-wrapped` and `export
extern-wrapped`

these two core commands will be removed in 0.88

# User-Facing Changes
using `extern-wrapped` will give a warning
```nushell
> extern-wrapped foo [...args] { print "foo" }; foo
Error:   × Deprecated command
   ╭─[entry #2:1:1]
 1 │ extern-wrapped foo [...args] { print "foo" }; foo
   · ───────┬──────
   ·        ╰── `extern-wrapped` is deprecated and will be removed in 0.88.
   ╰────
  help: Use `def --wrapped` instead


foo
```

# Tests + Formatting

# After Submitting
2023-10-19 13:50:00 +08:00
9692240b4f Add --ignore-error to reject (#10737)
Add `--ignore-errors` flag to reject.

This is a PR in reference to #10215 as select has the flag, but reject
hasn't

user can now add `-i` or `--ignore-errors` flag to turn every cell path
into option.

```nushell
> let arg = [0 5 a c]
> [[a b];[1 2] [3 4] [5 6]] | reject $a | to nuon
error index to large
# ----
> let arg = [0 5 a c]
> [[a b];[1 2] [3 4] [5 6]] | reject $a -i | to nuon
[[a, b]; [1, 2], [3, 4], [5, 6]]
```
2023-10-19 06:28:47 +08:00
d204defb68 Refactor: remove duplication to simplify lite_parsing logic. (#10735)
When looking into `lite_parse` function, I found that it contains some
duplicate code, and they can be expressed as an action called
`push_command_to(pipeline)`.

And I believe it will make our life easier to support something like
`o>> a.txt`, `e>> a.txt`.
2023-10-18 23:24:40 +02:00
9e7f84afb0 Refactor: simplify lex_item impl (#10744)
In the final match of `lex_item`, we'll return `Err(ParseError)` in rare
case, normally we'll return None.

So I think making error part mutable can reduce some code, and it's
better if we want to add more lex items.
2023-10-18 23:23:17 +02:00
ed8dee04b6 remove the last mention to let-env (#10718)
# Description
just caught a last mention to `let-env` in the `CONTRIBUTING.md`
document 😋

# User-Facing Changes

# Tests + Formatting

# After Submitting
2023-10-18 23:15:04 +02:00
4171c654a5 update release-pkg.nu with updated manual instructions (#10759)
# Description

This PR updates the release-pkg.nu script with updated instructions for
performing the release manually. These are there specifically because
winget fails so often and creating a x86_64 windows msi is not trivial.
There are also a couple minor changes to the script's syntax.

# 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-18 16:04:59 -05:00
JT
22ee041002 fix the flag type on release-pkg.nu (#10762)
# Description

Fix a breaking change based on how we do boolean flags in release-pkg.nu
2023-10-18 23:03:21 +02:00
7162d4d9aa Escape path that could be a flag (#10721)
# Description
Files that begin with dashes can be ambiguous when passed to commands
like `ls`. For example if there exists a file `--help`, it might be
considered a flag if not properly escaped. This PR escapes any file that
begins with a dash.

# User-Facing Changes

Files beginning with dashes will be escaped.

# Tests + Formatting

Tests are added.
2023-10-18 23:02:11 +02:00
9c70c68914 Bump csv from 1.2.2 to 1.3.0 (#10733) 2023-10-18 21:01:14 +00:00
93b4aa5fcf Bump lru from 0.11.1 to 0.12.0 (#10732) 2023-10-18 21:00:11 +00:00
71b0e12b57 Bump rustix from 0.36.15 to 0.36.16 (#10761) 2023-10-18 20:59:05 +00:00
09b3dab35d Allow filesystem commands to access files with glob metachars in name (#10694)
(squashed version of #10557, clean commit history and review thread)

Fixes #10571, also potentially: #10364, #10211, #9558, #9310,


# Description
Changes processing of arguments to filesystem commands that are source
paths or globs.
Applies to `cp, cp-old, mv, rm, du` but not `ls` (because it uses a
different globbing interface) or `glob` (because it uses a different
globbing library).

The core of the change is to lookup the argument first as a file and
only glob if it is not. That way,
a path containing glob metacharacters can be referenced without glob
quoting, though it will have to be single quoted to avoid nushell
parsing.

Before: A file path that looks like a glob is not matched by the glob
specified as a (source) argument and takes some thinking about to
access. You might say the glob pattern shadows a file with the same
spelling.
```
> ls a*
╭───┬────────┬──────┬──────┬────────────────╮
│ # │  name  │ type │ size │    modified    │
├───┼────────┼──────┼──────┼────────────────┤
│ 0 │ a[bc]d │ file │  0 B │ 34 seconds ago │
│ 1 │ abd    │ file │  0 B │ now            │
│ 2 │ acd    │ file │  0 B │ now            │
╰───┴────────┴──────┴──────┴────────────────╯

> cp --verbose 'a[bc]d' dest
copied /home/bobhy/src/rust/work/r4/abd to /home/bobhy/src/rust/work/r4/dest/abd
copied /home/bobhy/src/rust/work/r4/acd to /home/bobhy/src/rust/work/r4/dest/acd

> ## Note -- a[bc]d *not* copied, and seemingly hard to access.
> cp --verbose 'a\[bc\]d' dest
Error:   × No matches found
   ╭─[entry #33:1:1]
 1 │ cp --verbose 'a\[bc\]d' dest
   ·              ─────┬────
   ·                   ╰── no matches found
   ╰────

> #.. but is accessible with enough glob quoting.
> cp --verbose 'a[[]bc[]]d' dest
copied /home/bobhy/src/rust/work/r4/a[bc]d to /home/bobhy/src/rust/work/r4/dest/a[bc]d
```
Before_2: if file has glob metachars but isn't a valid pattern, user
gets a confusing error:

```
> touch 'a[b'
> cp 'a[b' dest
Error:   × Pattern syntax error near position 30: invalid range pattern
   ╭─[entry #13:1:1]
 1 │ cp 'a[b' dest
   ·    ──┬──
   ·      ╰── invalid pattern
   ╰────
```

After: Args to cp, mv, etc. are tried first as literal files, and only
as globs if not found to be files.

```
> cp --verbose 'a[bc]d' dest
copied /home/bobhy/src/rust/work/r4/a[bc]d to /home/bobhy/src/rust/work/r4/dest/a[bc]d
> cp --verbose '[a][bc]d' dest
copied /home/bobhy/src/rust/work/r4/abd to /home/bobhy/src/rust/work/r4/dest/abd
copied /home/bobhy/src/rust/work/r4/acd to /home/bobhy/src/rust/work/r4/dest/acd
```
After_2: file with glob metachars but invalid pattern just works.
(though Windows does not allow file name to contain `*`.).

```
> cp --verbose 'a[b' dest
copied /home/bobhy/src/rust/work/r4/a[b to /home/bobhy/src/rust/work/r4/dest/a[b
```

So, with this fix, a file shadows a glob pattern with the same spelling.
If you have such a file and really want to use the glob pattern, you
will have to glob quote some of the characters in the pattern. I think
that's less confusing to the user: if ls shows a file with a weird name,
s/he'll still be able to copy, rename or delete it.

# User-Facing Changes
Could break some existing scripts. If user happened to have a file with
a globbish name but was using a glob pattern with the same spelling, the
new version will process the file and not expand the glob.

# 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>
2023-10-18 13:31:15 -05:00
88a87158c2 Bump version to 0.86.1 (#10755)
To dev or to patch that is the question
2023-10-18 13:00:51 -05:00
faf84e69b4 Fix winget release submission error (#10757)
<!--
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.
-->

Fix winget release submission error, more details could be found here:
https://github.com/nushell/nushell/pull/5812#issuecomment-1768294811

@fdncred @wolimst 

# 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>
2023-10-18 13:00:19 -05:00
752 changed files with 25828 additions and 17798 deletions

1
.github/.typos.toml vendored
View File

@ -12,3 +12,4 @@ IIF = "IIF"
numer = "numer"
ratatui = "ratatui"
doas = "doas"
wheres = "wheres"

View File

@ -9,6 +9,7 @@ name: continuous-integration
env:
NUSHELL_CARGO_PROFILE: ci
NU_LOG_LEVEL: DEBUG
# If changing these settings also change toolkit.nu
CLIPPY_OPTIONS: "-D warnings -D clippy::unwrap_used"
jobs:
@ -40,16 +41,17 @@ jobs:
- uses: actions/checkout@v4
- name: Setup Rust toolchain and cache
uses: actions-rust-lang/setup-rust-toolchain@v1.5.0
uses: actions-rust-lang/setup-rust-toolchain@v1.6.0
with:
rustflags: ""
- name: cargo fmt
run: cargo fmt --all -- --check
# If changing these settings also change toolkit.nu
- name: Clippy
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
@ -83,13 +85,24 @@ jobs:
- uses: actions/checkout@v4
- name: Setup Rust toolchain and cache
uses: actions-rust-lang/setup-rust-toolchain@v1.5.0
uses: actions-rust-lang/setup-rust-toolchain@v1.6.0
with:
rustflags: ""
- name: Tests
run: cargo test --workspace --profile ci --exclude nu_plugin_* ${{ matrix.flags }}
- name: Check for clean repo
shell: bash
run: |
if [ -n "$(git status --porcelain)" ]; then
echo "there are changes";
git status --porcelain
exit 1
else
echo "no changes in working directory";
fi
std-lib-and-python-virtualenv:
strategy:
fail-fast: true
@ -104,7 +117,7 @@ jobs:
- uses: actions/checkout@v4
- name: Setup Rust toolchain and cache
uses: actions-rust-lang/setup-rust-toolchain@v1.5.0
uses: actions-rust-lang/setup-rust-toolchain@v1.6.0
with:
rustflags: ""
@ -115,7 +128,7 @@ jobs:
run: nu -c 'use std testing; testing run-tests --path crates/nu-std'
- name: Setup Python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: "3.10"
@ -127,6 +140,17 @@ jobs:
run: nu scripts/test_virtualenv.nu
shell: bash
- name: Check for clean repo
shell: bash
run: |
if [ -n "$(git status --porcelain)" ]; then
echo "there are changes";
git status --porcelain
exit 1
else
echo "no changes in working directory";
fi
plugins:
strategy:
fail-fast: true
@ -139,7 +163,7 @@ jobs:
- uses: actions/checkout@v4
- name: Setup Rust toolchain and cache
uses: actions-rust-lang/setup-rust-toolchain@v1.5.0
uses: actions-rust-lang/setup-rust-toolchain@v1.6.0
with:
rustflags: ""
@ -148,3 +172,14 @@ jobs:
- name: Tests
run: cargo test --profile ci --package nu_plugin_*
- name: Check for clean repo
shell: bash
run: |
if [ -n "$(git status --porcelain)" ]; then
echo "there are changes";
git status --porcelain
exit 1
else
echo "no changes in working directory";
fi

View File

@ -36,10 +36,10 @@ jobs:
token: ${{ secrets.WORKFLOW_TOKEN }}
- name: Setup Nushell
uses: hustcer/setup-nu@v3.6
uses: hustcer/setup-nu@v3.8
if: github.repository == 'nushell/nightly'
with:
version: 0.85.0
version: 0.86.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@ -119,7 +119,7 @@ jobs:
os: ubuntu-20.04
target_rustflags: ''
- target: riscv64gc-unknown-linux-gnu
os: ubuntu-20.04
os: ubuntu-latest
target_rustflags: ''
runs-on: ${{matrix.os}}
@ -135,12 +135,15 @@ jobs:
echo "targets = ['${{matrix.target}}']" >> rust-toolchain.toml
- name: Setup Rust toolchain and cache
uses: actions-rust-lang/setup-rust-toolchain@v1.5.0
uses: actions-rust-lang/setup-rust-toolchain@v1.6.0
# WARN: Keep the rustflags to prevent from the winget submission error: `CAQuietExec: Error 0xc0000135`
with:
rustflags: ''
- name: Setup Nushell
uses: hustcer/setup-nu@v3.6
uses: hustcer/setup-nu@v3.8
with:
version: 0.85.0
version: 0.86.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@ -246,12 +249,15 @@ jobs:
echo "targets = ['${{matrix.target}}']" >> rust-toolchain.toml
- name: Setup Rust toolchain and cache
uses: actions-rust-lang/setup-rust-toolchain@v1.5.0
uses: actions-rust-lang/setup-rust-toolchain@v1.6.0
# WARN: Keep the rustflags to prevent from the winget submission error: `CAQuietExec: Error 0xc0000135`
with:
rustflags: ''
- name: Setup Nushell
uses: hustcer/setup-nu@v3.6
uses: hustcer/setup-nu@v3.8
with:
version: 0.85.0
version: 0.86.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@ -315,9 +321,9 @@ jobs:
ref: main
- name: Setup Nushell
uses: hustcer/setup-nu@v3.6
uses: hustcer/setup-nu@v3.8
with:
version: 0.85.0
version: 0.86.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -9,34 +9,36 @@
# Instructions for manually creating an MSI for Winget Releases when they fail
# Added 2022-11-29 when Windows packaging wouldn't work
# Updated again on 2023-02-23 because msis are still failing validation
# Update on 2023-10-18 to use RELEASE_TYPE env var to determine if full or not
# To run this manual for windows here are the steps I take
# checkout the release you want to publish
# 1. git checkout 0.76.0
# 1. git checkout 0.86.0
# unset CARGO_TARGET_DIR if set (I have to do this in the parent shell to get it to work)
# 2. $env:CARGO_TARGET_DIR = ""
# 2. hide-env CARGO_TARGET_DIR
# 3. $env.TARGET = 'x86_64-pc-windows-msvc'
# 4. $env.TARGET_RUSTFLAGS = ''
# 5. $env.GITHUB_WORKSPACE = 'C:\Users\dschroeder\source\repos\forks\nushell'
# 6. $env.GITHUB_OUTPUT = 'C:\Users\dschroeder\source\repos\forks\nushell\output\out.txt'
# 5. $env.GITHUB_WORKSPACE = 'D:\nushell'
# 6. $env.GITHUB_OUTPUT = 'D:\nushell\output\out.txt'
# 7. $env.OS = 'windows-latest'
# 8. $env.RELEASE_TYPE = '' # There is full and '' for normal releases
# make sure 7z.exe is in your path https://www.7-zip.org/download.html
# 8. $env.Path = ($env.Path | append 'c:\apps\7-zip')
# 9. $env.Path = ($env.Path | append 'c:\apps\7-zip')
# make sure aria2c.exe is in your path https://github.com/aria2/aria2
# 9. $env.Path = ($env.Path | append 'c:\path\to\aria2c')
# 10. $env.Path = ($env.Path | append 'c:\path\to\aria2c')
# make sure you have the wixtools installed https://wixtoolset.org/
# 10. $env.Path = ($env.Path | append 'C:\Users\dschroeder\AppData\Local\tauri\WixTools')
# 11. $env.Path = ($env.Path | append 'C:\Users\dschroeder\AppData\Local\tauri\WixTools')
# You need to run the release-pkg twice. The first pass, with _EXTRA_ as 'bin', makes the output
# folder and builds everything. The second pass, that generates the msi file, with _EXTRA_ as 'msi'
# 11. $env._EXTRA_ = 'bin'
# 12. source .github\workflows\release-pkg.nu
# 13. cd ..
# 14. $env._EXTRA_ = 'msi'
# 15. source .github\workflows\release-pkg.nu
# 12. $env._EXTRA_ = 'bin'
# 13. source .github\workflows\release-pkg.nu
# 14. cd ..
# 15. $env._EXTRA_ = 'msi'
# 16. source .github\workflows\release-pkg.nu
# After msi is generated, you have to update winget-pkgs repo, you'll need to patch the release
# by deleting the existing msi and uploading this new msi. Then you'll need to update the hash
# on the winget-pkgs PR. To generate the hash, run this command
# 16. open target\wix\nu-0.74.0-x86_64-pc-windows-msvc.msi | hash sha256
# 17. open target\wix\nu-0.74.0-x86_64-pc-windows-msvc.msi | hash sha256
# Then, just take the output and put it in the winget-pkgs PR for the hash on the msi
@ -80,8 +82,8 @@ print $'Start building ($bin)...'; hr-line
# ----------------------------------------------------------------------------
# Build for Ubuntu and macOS
# ----------------------------------------------------------------------------
if $os in [$USE_UBUNTU, 'macos-latest'] {
if $os == $USE_UBUNTU {
if $os in [$USE_UBUNTU, 'macos-latest', 'ubuntu-latest'] {
if $os starts-with ubuntu {
sudo apt update
sudo apt-get install libxcb-composite0-dev -y
}
@ -104,7 +106,7 @@ if $os in [$USE_UBUNTU, 'macos-latest'] {
_ => {
# musl-tools to fix 'Failed to find tool. Is `musl-gcc` installed?'
# Actually just for x86_64-unknown-linux-musl target
if $os == $USE_UBUNTU { sudo apt install musl-tools -y }
if $os starts-with ubuntu { sudo apt install musl-tools -y }
cargo-build-nu $flags
}
}
@ -134,10 +136,8 @@ print (ls -f $executable); sleep 1sec
print $'(char nl)Copying release files...'; hr-line
"To use Nu plugins, use the register command to tell Nu where to find the plugin. For example:
> register ./nu_plugin_query" | save $'($dist)/README.txt'
> register ./nu_plugin_query" | save $'($dist)/README.txt' -f
[LICENSE $executable] | each {|it| cp -rv $it $dist } | flatten
# Sleep a few seconds to make sure the cp process finished successfully
sleep 3sec
print $'(char nl)Check binary release version detail:'; hr-line
let ver = if $os == 'windows-latest' {
@ -146,14 +146,14 @@ let ver = if $os == 'windows-latest' {
(do -i { ./output/nu -c 'version' }) | str join
}
if ($ver | str trim | is-empty) {
print $'(ansi r)Incompatible nu binary...(ansi reset)'
print $'(ansi r)Incompatible Nu binary: The binary cross compiled is not runnable on current arch...(ansi reset)'
} else { print $ver }
# ----------------------------------------------------------------------------
# Create a release archive and send it to output for the following steps
# ----------------------------------------------------------------------------
cd $dist; print $'(char nl)Creating release archive...'; hr-line
if $os in [$USE_UBUNTU, 'macos-latest'] {
if $os in [$USE_UBUNTU, 'macos-latest', 'ubuntu-latest'] {
let files = (ls | get name)
let dest = if $env.RELEASE_TYPE == 'full' { $'($bin)-($version)-($FULL_NAME)' } else { $'($bin)-($version)-($target)' }
@ -225,7 +225,7 @@ def 'cargo-build-nu' [ options: string ] {
# Print a horizontal line marker
def 'hr-line' [
--blank-line(-b): bool
--blank-line(-b)
] {
print $'(ansi g)---------------------------------------------------------------------------->(ansi reset)'
if $blank_line { char nl }

View File

@ -66,7 +66,7 @@ jobs:
os: ubuntu-20.04
target_rustflags: ''
- target: riscv64gc-unknown-linux-gnu
os: ubuntu-20.04
os: ubuntu-latest
target_rustflags: ''
runs-on: ${{matrix.os}}
@ -79,12 +79,15 @@ jobs:
echo "targets = ['${{matrix.target}}']" >> rust-toolchain.toml
- name: Setup Rust toolchain and cache
uses: actions-rust-lang/setup-rust-toolchain@v1.5.0
uses: actions-rust-lang/setup-rust-toolchain@v1.6.0
# WARN: Keep the rustflags to prevent from the winget submission error: `CAQuietExec: Error 0xc0000135`
with:
rustflags: ''
- name: Setup Nushell
uses: hustcer/setup-nu@v3.6
uses: hustcer/setup-nu@v3.8
with:
version: 0.85.0
version: 0.86.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@ -167,12 +170,15 @@ jobs:
echo "targets = ['${{matrix.target}}']" >> rust-toolchain.toml
- name: Setup Rust toolchain and cache
uses: actions-rust-lang/setup-rust-toolchain@v1.5.0
uses: actions-rust-lang/setup-rust-toolchain@v1.6.0
# WARN: Keep the rustflags to prevent from the winget submission error: `CAQuietExec: Error 0xc0000135`
with:
rustflags: ''
- name: Setup Nushell
uses: hustcer/setup-nu@v3.6
uses: hustcer/setup-nu@v3.8
with:
version: 0.85.0
version: 0.86.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

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

View File

@ -10,11 +10,16 @@ Welcome to Nushell and thank you for considering contributing!
- [Useful commands](#useful-commands)
- [Debugging tips](#debugging-tips)
- [Git etiquette](#git-etiquette)
- [Our Rust style](#our-rust-style)
- [Generally discouraged](#generally-discouraged)
- [Things we want to get better at](#things-we-want-to-get-better-at)
- [License](#license)
## Other helpful resources
More resources can be found in the nascent [developer documentation](devdocs/README.md) in this repo.
- [Developer FAQ](FAQ.md)
- [Platform support policy](PLATFORM_SUPPORT.md)
- [Our Rust style](devdocs/rust_style.md)
## Proposing design changes
First of all, before diving into the code, if you want to create a new feature, change something significantly, and especially if the change is user-facing, it is a good practice to first get an approval from the core team before starting to work on it.
@ -63,74 +68,74 @@ Read cargo's documentation for more details: https://doc.rust-lang.org/cargo/ref
- Build and run Nushell:
```shell
```nushell
cargo run
```
- Build and run with dataframe support.
```shell
```nushell
cargo run --features=dataframe
```
- Run Clippy on Nushell:
```shell
```nushell
cargo clippy --workspace -- -D warnings -D clippy::unwrap_used
```
or via the `toolkit.nu` command:
```shell
```nushell
use toolkit.nu clippy
clippy
```
- Run all tests:
```shell
```nushell
cargo test --workspace
```
along with dataframe tests
```shell
```nushell
cargo test --workspace --features=dataframe
```
or via the `toolkit.nu` command:
```shell
```nushell
use toolkit.nu test
test
```
- Run all tests for a specific command
```shell
```nushell
cargo test --package nu-cli --test main -- commands::<command_name_here>
```
- Check to see if there are code formatting issues
```shell
```nushell
cargo fmt --all -- --check
```
or via the `toolkit.nu` command:
```shell
```nushell
use toolkit.nu fmt
fmt --check
```
- Format the code in the project
```shell
```nushell
cargo fmt --all
```
or via the `toolkit.nu` command:
```shell
```nushell
use toolkit.nu fmt
fmt
```
- Set up `git` hooks to check formatting and run `clippy` before committing and pushing:
```shell
```nushell
use toolkit.nu setup-git-hooks
setup-git-hooks
```
@ -140,12 +145,12 @@ Read cargo's documentation for more details: https://doc.rust-lang.org/cargo/ref
- To view verbose logs when developing, enable the `trace` log level.
```shell
```nushell
cargo run --release -- --log-level trace
```
- To redirect trace logs to a file, enable the `--log-target file` switch.
```shell
```nushell
cargo run --release -- --log-level trace --log-target file
open $"($nu.temp-path)/nu-($nu.pid).log"
```
@ -237,51 +242,6 @@ You can help us to make the review process a smooth experience:
- Feel free to notify your reviewers or affected PR authors if your change might cause larger conflicts with another change.
- During the rollup of multiple PRs, we may choose to resolve merge conflicts and CI failures ourselves. (Allow maintainers to push to your branch to enable us to do this quickly.)
## Our Rust style
To make the collaboration on a project the scale of Nushell easy, we want to work towards a style of Rust code that can easily be understood by all of our contributors. We conservatively rely on most of [`clippy`s suggestions](https://github.com/rust-lang/rust-clippy) to get to the holy grail of "idiomatic" code. Good code in our eyes is not the most clever use of all available language features or with the most unique personal touch but readable and strikes a balance between being concise, and also unsurprising and explicit in the places where it matters.
One example of this philosophy is that we generally avoid to fight the borrow-checker in our data model but rather try to get to a correct and simple solution first and then figure out where we should reuse data to achieve the necessary performance. As we are still pre-1.0 this served us well to be able to quickly refactor or change larger parts of the code base.
### Generally discouraged
#### `+nightly` language features or things only available in the most recent `+stable`
To make life for the people easier that maintain the Nushell packages in various distributions with their own release cycle of `rustc` we typically rely on slightly older Rust versions. We do not make explicit guarantees how far back in the past we live but you can find out in our [`rust-toolchain.toml`](https://github.com/nushell/nushell/blob/main/rust-toolchain.toml)
(As a rule of thumb this has been typically been approximately 2 releases behind the newest stable compiler.)
The use of nightly features is prohibited.
#### Panicking
As Nushell aims to provide a reliable foundational way for folks to interact with their computer, we cannot carelessly crash the execution of their work by panicking Nushell.
Thus panicking is not an allowed error handling strategy for anything that could be triggered by user input OR behavior of the outside system. If Nushell panics this is a bug or we are against all odds already in an unrecoverable state (The system stopped cooperating, we went out of memory). The use of `.unwrap()` is thus outright banned and any uses of `.expect()` or related panicking macros like `unreachable!` should include a helpful description which assumptions have been violated.
#### `unsafe` code
For any use of `unsafe` code we need to require even higher standards and additional review. If you add or alter `unsafe` blocks you have to be familiar with the promises you need to uphold as found in the [Rustonomicon](https://doc.rust-lang.org/nomicon/intro.html). All `unsafe` uses should include `// SAFETY:` comments explaining how the invariants are upheld and thus alerting you what to watch out for when making a change.
##### FFI with system calls and the outside world
As a shell Nushell needs to interact with system APIs in several places, for which FFI code with unsafe blocks may be necessary. In some cases this can be handled by safe API wrapper crates but in some cases we may choose to directly do those calls.
If you do so you need to document the system behavior on top of the Rust memory model guarantees that you uphold. This means documenting whether using a particular system call is safe to use in a particular context and all failure cases are properly recovered.
##### Implementing self-contained data structures
Another motivation for reaching to `unsafe` code might be to try to implement a particular data structure that is not expressible on safe `std` library APIs. Doing so in the Nushell code base would have to clear a high bar for need based on profiling results. Also you should first do a survey of the [crate ecosystem](https://crates.io) that there doesn't exist a usable well vetted crate that already provides safe APIs to the desired datastructure.
##### Make things go faster by removing checks
This is probably a bad idea if you feel tempted to do so. Don't
#### Macros
Another advanced feature people feel tempted to use to work around perceived limitations of Rusts syntax and we are not particularly fans of are custom macros.
They have clear downsides not only in terms of readability if they locally introduce a different syntax. Most tooling apart from the compiler will struggle more with them. This limits for example consistent automatic formatting or automated refactors with `rust-analyzer`.
That you can fluently read `macro_rules!` is less likely than regular code. This can lead people to introduce funky behavior when using a macro. Be it because a macro is not following proper hygiene rules or because it introduces excessive work at compile time.
So we generally discourage the addition of macros. In a lot of cases your macro may start do something that can be expressed with functions or generics in a much more reusable fashion.
The only exceptions we may allow need to demonstrate that the macro can fix something that is otherwise extremely unreadable, error-prone, or consistently worse at compile time.
### Things we want to get better at
These are things we did pretty liberally to get Nushell off the ground, that make things harder for a high quality stable product. You may run across them but shouldn't take them as an endorsed example.
#### Liberal use of third-party dependencies
The amazing variety of crates on [crates.io](https://crates.io) allowed us to quickly get Nushell into a feature rich state but it left us with a bunch of baggage to clean up.
Each dependency introduces a compile time cost and duplicated code can add to the overall binary size. Also vetting more for correct and secure implementations takes unreasonably more time as this is also a continuous process of reacting to updates or potential vulnerabilities.
Thus we only want to accept dependencies that are essential and well tested implementations of a particular requirement of Nushells codebase.
Also as a project for the move to 1.0 we will try to unify among a set of dependencies if they possibly implement similar things in an area. We don't need three different crates with potentially perfect fit for three problems but rather one reliable crate with a maximized overlap between what it provides and what we need.
We will favor crates that are well tested and used and promise to be more stable and still frequently maintained.
#### Deeply nested code
As Nushell uses a lot of enums in its internal data representation there are a lot of `match` expressions. Combined with the need to handle a lot of edge cases and be defensive about any errors this has led to some absolutely hard to read deeply nested code (e.g. in the parser but also in the implementation of several commands).
This can be observed both as a "rightward drift" where the main part of the code is found after many levels of indentations or by long function bodies with several layers of branching with seemingly repeated branching inside the higher branch level.
This can also be exacerbated by "quick" bugfixes/enhancements that may just try to add a special case to catch a previously unexpected condition. The likelihood of introducing a bug in a sea of code duplication is high.
To combat this, consider using the early-`return` pattern to reject invalid data early in one place instead of building a tree through Rust's expression constructs with a lot of duplicated paths. Unpacking data into a type that expresses that the necessary things already have been checked and using functions to properly deal with separate and common behavior can also help.
## License
We use the [MIT License](https://github.com/nushell/nushell/blob/main/LICENSE) in all of our Nushell projects. If you are including or referencing a crate that uses the [GPL License](https://www.gnu.org/licenses/gpl-3.0.en.html#license-text) unfortunately we will not be able to accept your PR.

1735
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -10,8 +10,8 @@ homepage = "https://www.nushell.sh"
license = "MIT"
name = "nu"
repository = "https://github.com/nushell/nushell"
rust-version = "1.60"
version = "0.86.0"
rust-version = "1.72.1"
version = "0.88.2"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -33,6 +33,11 @@ members = [
"crates/nu-cmd-lang",
"crates/nu-cmd-dataframe",
"crates/nu-command",
"crates/nu-color-config",
"crates/nu-explore",
"crates/nu-json",
"crates/nu-lsp",
"crates/nu-pretty-hex",
"crates/nu-protocol",
"crates/nu-plugin",
"crates/nu_plugin_inc",
@ -42,32 +47,36 @@ members = [
"crates/nu_plugin_custom_values",
"crates/nu_plugin_formats",
"crates/nu-std",
"crates/nu-table",
"crates/nu-term-grid",
"crates/nu-utils",
]
[dependencies]
nu-cli = { path = "./crates/nu-cli", version = "0.86.0" }
nu-color-config = { path = "./crates/nu-color-config", version = "0.86.0" }
nu-cmd-base = { path = "./crates/nu-cmd-base", version = "0.86.0" }
nu-cmd-lang = { path = "./crates/nu-cmd-lang", version = "0.86.0" }
nu-cmd-dataframe = { path = "./crates/nu-cmd-dataframe", version = "0.86.0", features = ["dataframe"], optional = true }
nu-cmd-extra = { path = "./crates/nu-cmd-extra", version = "0.86.0", optional = true }
nu-command = { path = "./crates/nu-command", version = "0.86.0" }
nu-engine = { path = "./crates/nu-engine", version = "0.86.0" }
nu-explore = { path = "./crates/nu-explore", version = "0.86.0" }
nu-json = { path = "./crates/nu-json", version = "0.86.0" }
nu-parser = { path = "./crates/nu-parser", version = "0.86.0" }
nu-path = { path = "./crates/nu-path", version = "0.86.0" }
nu-plugin = { path = "./crates/nu-plugin", optional = true, version = "0.86.0" }
nu-pretty-hex = { path = "./crates/nu-pretty-hex", version = "0.86.0" }
nu-protocol = { path = "./crates/nu-protocol", version = "0.86.0" }
nu-system = { path = "./crates/nu-system", version = "0.86.0" }
nu-table = { path = "./crates/nu-table", version = "0.86.0" }
nu-term-grid = { path = "./crates/nu-term-grid", version = "0.86.0" }
nu-std = { path = "./crates/nu-std", version = "0.86.0" }
nu-utils = { path = "./crates/nu-utils", version = "0.86.0" }
nu-cli = { path = "./crates/nu-cli", version = "0.88.2" }
nu-color-config = { path = "./crates/nu-color-config", version = "0.88.2" }
nu-cmd-base = { path = "./crates/nu-cmd-base", version = "0.88.2" }
nu-cmd-lang = { path = "./crates/nu-cmd-lang", version = "0.88.2" }
nu-cmd-dataframe = { path = "./crates/nu-cmd-dataframe", version = "0.88.2", features = ["dataframe"], optional = true }
nu-cmd-extra = { path = "./crates/nu-cmd-extra", version = "0.88.2", optional = true }
nu-command = { path = "./crates/nu-command", version = "0.88.2" }
nu-engine = { path = "./crates/nu-engine", version = "0.88.2" }
nu-explore = { path = "./crates/nu-explore", version = "0.88.2" }
nu-json = { path = "./crates/nu-json", version = "0.88.2" }
nu-lsp = { path = "./crates/nu-lsp/", version = "0.88.2" }
nu-parser = { path = "./crates/nu-parser", version = "0.88.2" }
nu-path = { path = "./crates/nu-path", version = "0.88.2" }
nu-plugin = { path = "./crates/nu-plugin", optional = true, version = "0.88.2" }
nu-pretty-hex = { path = "./crates/nu-pretty-hex", version = "0.88.2" }
nu-protocol = { path = "./crates/nu-protocol", version = "0.88.2" }
nu-system = { path = "./crates/nu-system", version = "0.88.2" }
nu-table = { path = "./crates/nu-table", version = "0.88.2" }
nu-term-grid = { path = "./crates/nu-term-grid", version = "0.88.2" }
nu-std = { path = "./crates/nu-std", version = "0.88.2" }
nu-utils = { path = "./crates/nu-utils", version = "0.88.2" }
nu-ansi-term = "0.49.0"
reedline = { version = "0.25.0", features = ["bashisms", "sqlite"] }
reedline = { version = "0.27.0", features = ["bashisms", "sqlite"] }
crossterm = "0.27"
ctrlc = "3.4"
@ -95,7 +104,7 @@ nix = { version = "0.27", default-features = false, features = [
] }
[dev-dependencies]
nu-test-support = { path = "./crates/nu-test-support", version = "0.86.0" }
nu-test-support = { path = "./crates/nu-test-support", version = "0.88.2" }
assert_cmd = "2.0"
criterion = "0.5"
pretty_assertions = "1.4"
@ -164,7 +173,7 @@ bench = false
# To use a development version of a dependency please use a global override here
# changing versions in each sub-crate of the workspace is tedious
[patch.crates-io]
# reedline = { git = "https://github.com/nushell/reedline.git", branch = "main" }
reedline = { git = "https://github.com/nushell/reedline.git", branch = "main" }
# nu-ansi-term = {git = "https://github.com/nushell/nu-ansi-term.git", branch = "main"}
# uu_cp = { git = "https://github.com/uutils/coreutils.git", branch = "main" }

View File

@ -54,6 +54,7 @@ Detailed installation instructions can be found in the [installation chapter of
[![Packaging status](https://repology.org/badge/vertical-allrepos/nushell.svg)](https://repology.org/project/nushell/versions)
For details about which platforms the Nushell team actively supports, see [our platform support policy](devdocs/PLATFORM_SUPPORT.md).
## Configuration
@ -198,7 +199,7 @@ topics that have been presented.
Nu adheres closely to a set of goals that make up its design philosophy. As features are added, they are checked against these goals.
- First and foremost, Nu is cross-platform. Commands and techniques should work across platforms and Nu has first-class support for Windows, macOS, and Linux.
- First and foremost, Nu is cross-platform. Commands and techniques should work across platforms and Nu has [first-class support for Windows, macOS, and Linux](devdocs/PLATFORM_SUPPORT.md).
- Nu ensures compatibility with existing platform-specific executables.

View File

@ -4,10 +4,31 @@ use nu_parser::parse;
use nu_plugin::{EncodingType, PluginResponse};
use nu_protocol::{engine::EngineState, PipelineData, Span, Value};
use nu_utils::{get_default_config, get_default_env};
use std::path::{Path, PathBuf};
fn load_bench_commands() -> EngineState {
nu_command::add_shell_command_context(nu_cmd_lang::create_default_context())
}
fn canonicalize_path(engine_state: &EngineState, path: &Path) -> PathBuf {
let cwd = engine_state.current_work_dir();
if path.exists() {
match nu_path::canonicalize_with(path, cwd) {
Ok(canon_path) => canon_path,
Err(_) => path.to_owned(),
}
} else {
path.to_owned()
}
}
fn get_home_path(engine_state: &EngineState) -> PathBuf {
nu_path::home_dir()
.map(|path| canonicalize_path(engine_state, &path))
.unwrap_or_default()
}
// FIXME: All benchmarks live in this 1 file to speed up build times when benchmarking.
// When the *_benchmarks functions were in different files, `cargo bench` would build
// an executable for every single one - incredibly slowly. Would be nice to figure out
@ -15,10 +36,12 @@ fn load_bench_commands() -> EngineState {
fn parser_benchmarks(c: &mut Criterion) {
let mut engine_state = load_bench_commands();
// parsing config.nu breaks without PWD set
let home_path = get_home_path(&engine_state);
// parsing config.nu breaks without PWD set, so set a valid path
engine_state.add_env_var(
"PWD".into(),
Value::string("/some/dir".to_string(), Span::test_data()),
Value::string(home_path.to_string_lossy(), Span::test_data()),
);
let default_env = get_default_env().as_bytes();
@ -41,7 +64,6 @@ fn parser_benchmarks(c: &mut Criterion) {
c.bench_function("eval default_env.nu", |b| {
b.iter(|| {
let mut engine_state = load_bench_commands();
let mut stack = nu_protocol::engine::Stack::new();
eval_source(
&mut engine_state,
@ -56,12 +78,6 @@ fn parser_benchmarks(c: &mut Criterion) {
c.bench_function("eval default_config.nu", |b| {
b.iter(|| {
let mut engine_state = load_bench_commands();
// parsing config.nu breaks without PWD set
engine_state.add_env_var(
"PWD".into(),
Value::string("/some/dir".to_string(), Span::test_data()),
);
let mut stack = nu_protocol::engine::Stack::new();
eval_source(
&mut engine_state,
@ -76,9 +92,17 @@ fn parser_benchmarks(c: &mut Criterion) {
}
fn eval_benchmarks(c: &mut Criterion) {
let mut engine_state = load_bench_commands();
let home_path = get_home_path(&engine_state);
// parsing config.nu breaks without PWD set, so set a valid path
engine_state.add_env_var(
"PWD".into(),
Value::string(home_path.to_string_lossy(), Span::test_data()),
);
c.bench_function("eval default_env.nu", |b| {
b.iter(|| {
let mut engine_state = load_bench_commands();
let mut stack = nu_protocol::engine::Stack::new();
eval_source(
&mut engine_state,
@ -93,12 +117,6 @@ fn eval_benchmarks(c: &mut Criterion) {
c.bench_function("eval default_config.nu", |b| {
b.iter(|| {
let mut engine_state = load_bench_commands();
// parsing config.nu breaks without PWD set
engine_state.add_env_var(
"PWD".into(),
Value::string("/some/dir".to_string(), Span::test_data()),
);
let mut stack = nu_protocol::engine::Stack::new();
eval_source(
&mut engine_state,

View File

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

View File

@ -34,7 +34,7 @@ impl Command for History {
"Show long listing of entries for sqlite history",
Some('l'),
)
.category(Category::Misc)
.category(Category::History)
}
fn run(
@ -107,7 +107,7 @@ impl Command for History {
)
})
})
.ok_or(ShellError::FileNotFound(head))?
.ok_or(ShellError::FileNotFound { span: head })?
.into_pipeline_data(ctrlc)),
HistoryFileFormat::Sqlite => Ok(history_reader
.and_then(|h| {
@ -119,12 +119,12 @@ impl Command for History {
create_history_record(idx, entry, long, head)
})
})
.ok_or(ShellError::FileNotFound(head))?
.ok_or(ShellError::FileNotFound { span: head })?
.into_pipeline_data(ctrlc)),
}
}
} else {
Err(ShellError::FileNotFound(head))
Err(ShellError::FileNotFound { span: head })
}
}

View File

@ -18,7 +18,7 @@ impl Command for HistorySession {
fn signature(&self) -> nu_protocol::Signature {
Signature::build("history session")
.category(Category::Misc)
.category(Category::History)
.input_output_types(vec![(Type::Nothing, Type::Int)])
}

View File

@ -0,0 +1,5 @@
mod history_;
mod history_session;
pub use history_::History;
pub use history_session::HistorySession;

View File

@ -36,7 +36,7 @@ impl Command for KeybindingsList {
vec![
Example {
description: "Get list of key modifiers",
example: "keybindings list -m",
example: "keybindings list --modifiers",
result: None,
},
Example {

View File

@ -45,13 +45,13 @@ impl Command for KeybindingsListen {
Ok(v) => Ok(v.into_pipeline_data()),
Err(e) => {
terminal::disable_raw_mode()?;
Err(ShellError::GenericError(
"Error with input".to_string(),
"".to_string(),
None,
Some(e.to_string()),
Vec::new(),
))
Err(ShellError::GenericError {
error: "Error with input".into(),
msg: "".into(),
span: None,
help: Some(e.to_string()),
inner: vec![],
})
}
}
}

View File

@ -1,15 +1,13 @@
mod commandline;
mod default_context;
mod history;
mod history_session;
mod keybindings;
mod keybindings_default;
mod keybindings_list;
mod keybindings_listen;
pub use commandline::Commandline;
pub use history::History;
pub use history_session::HistorySession;
pub use history::{History, HistorySession};
pub use keybindings::Keybindings;
pub use keybindings_default::KeybindingsDefault;
pub use keybindings_list::KeybindingsList;

View File

@ -1,6 +1,6 @@
use crate::completions::{
CommandCompletion, Completer, CompletionOptions, CustomCompletion, DirectoryCompletion,
DotNuCompletion, FileCompletion, FlagCompletion, MatchAlgorithm, VariableCompletion,
DotNuCompletion, FileCompletion, FlagCompletion, VariableCompletion,
};
use nu_engine::eval_block;
use nu_parser::{flatten_expression, parse, FlatShape};
@ -39,15 +39,12 @@ impl NuCompleter {
) -> Vec<Suggestion> {
let config = self.engine_state.get_config();
let mut options = CompletionOptions {
let options = CompletionOptions {
case_sensitive: config.case_sensitive_completions,
match_algorithm: config.completion_algorithm.into(),
..Default::default()
};
if config.completion_algorithm == "fuzzy" {
options.match_algorithm = MatchAlgorithm::Fuzzy;
}
// Fetch
let mut suggestions =
completer.fetch(working_set, prefix.clone(), new_span, offset, pos, &options);
@ -70,7 +67,7 @@ impl NuCompleter {
let mut callee_stack = stack.gather_captures(&self.engine_state, &block.captures);
// Line
if let Some(pos_arg) = block.signature.required_positional.get(0) {
if let Some(pos_arg) = block.signature.required_positional.first() {
if let Some(var_id) = pos_arg.var_id {
callee_stack.add_var(
var_id,
@ -125,11 +122,13 @@ impl NuCompleter {
for pipeline_element in pipeline.elements {
match pipeline_element {
PipelineElement::Expression(_, expr)
| PipelineElement::Redirection(_, _, expr)
| PipelineElement::Redirection(_, _, expr, _)
| PipelineElement::And(_, expr)
| PipelineElement::Or(_, expr)
| PipelineElement::SameTargetRedirection { cmd: (_, expr), .. }
| PipelineElement::SeparateRedirection { out: (_, expr), .. } => {
| PipelineElement::SeparateRedirection {
out: (_, expr, _), ..
} => {
let flattened: Vec<_> = flatten_expression(&working_set, &expr);
let mut spans: Vec<String> = vec![];
@ -144,18 +143,24 @@ impl NuCompleter {
let current_span = working_set.get_span_contents(flat.0).to_vec();
let current_span_str = String::from_utf8_lossy(&current_span);
let is_last_span = pos >= flat.0.start && pos < flat.0.end;
// Skip the last 'a' as span item
if flat_idx == flattened.len() - 1 {
let mut chars = current_span_str.chars();
chars.next_back();
let current_span_str = chars.as_str().to_owned();
spans.push(current_span_str.to_string());
if is_last_span {
let offset = pos - flat.0.start;
if offset == 0 {
spans.push(String::new())
} else {
let mut current_span_str = current_span_str.to_string();
current_span_str.remove(offset);
spans.push(current_span_str);
}
} else {
spans.push(current_span_str.to_string());
}
// Complete based on the last span
if pos >= flat.0.start && pos < flat.0.end {
if is_last_span {
// Context variables
let most_left_var =
most_left_variable(flat_idx, &working_set, flattened.clone());
@ -245,7 +250,9 @@ impl NuCompleter {
working_set.get_span_contents(previous_expr.0).to_vec();
// Completion for .nu files
if prev_expr_str == b"use" || prev_expr_str == b"source-env"
if prev_expr_str == b"use"
|| prev_expr_str == b"overlay use"
|| prev_expr_str == b"source-env"
{
let mut completer =
DotNuCompletion::new(self.engine_state.clone());

View File

@ -1,5 +1,6 @@
use crate::completions::{matches, CompletionOptions};
use nu_path::home_dir;
use nu_protocol::{engine::StateWorkingSet, Span};
use std::path::{is_separator, Component, Path, PathBuf, MAIN_SEPARATOR as SEP};
fn complete_rec(
@ -21,7 +22,10 @@ fn complete_rec(
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))
completions.extend(complete_rec(partial, &path, options, dir, isdir));
if entry_name.eq(base) {
break;
}
} else {
completions.push(path)
}
@ -152,9 +156,44 @@ pub fn complete_item(
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() {
let maybe_flag = path.starts_with('-');
let maybe_number = path.parse::<f64>().is_ok();
if filename_contaminated || dirname_contaminated || maybe_flag || maybe_number {
format!("`{path}`")
} else {
path
}
}
pub struct AdjustView {
pub prefix: String,
pub span: Span,
pub readjusted: bool,
}
pub fn adjust_if_intermediate(
prefix: &[u8],
working_set: &StateWorkingSet,
mut span: nu_protocol::Span,
) -> AdjustView {
let span_contents = String::from_utf8_lossy(working_set.get_span_contents(span)).to_string();
let mut prefix = String::from_utf8_lossy(prefix).to_string();
// A difference of 1 because of the cursor's unicode code point in between.
// Using .chars().count() because unicode and Windows.
let readjusted = span_contents.chars().count() - prefix.chars().count() > 1;
if readjusted {
let remnant: String = span_contents
.chars()
.skip(prefix.chars().count() + 1)
.take_while(|&c| !is_separator(c))
.collect();
prefix.push_str(&remnant);
span = Span::new(span.start, span.start + prefix.chars().count() + 1);
}
AdjustView {
prefix,
span,
readjusted,
}
}

View File

@ -2,6 +2,7 @@ use std::fmt::Display;
use fuzzy_matcher::{skim::SkimMatcherV2, FuzzyMatcher};
use nu_parser::trim_quotes_str;
use nu_protocol::CompletionAlgorithm;
#[derive(Copy, Clone)]
pub enum SortBy {
@ -55,6 +56,15 @@ impl MatchAlgorithm {
}
}
impl From<CompletionAlgorithm> for MatchAlgorithm {
fn from(value: CompletionAlgorithm) -> Self {
match value {
CompletionAlgorithm::Prefix => MatchAlgorithm::Prefix,
CompletionAlgorithm::Fuzzy => MatchAlgorithm::Fuzzy,
}
}
}
impl TryFrom<String> for MatchAlgorithm {
type Error = InvalidMatchAlgorithm;

View File

@ -5,6 +5,7 @@ use nu_protocol::{
engine::{EngineState, Stack, StateWorkingSet},
PipelineData, Span, Type, Value,
};
use nu_utils::IgnoreCaseExt;
use reedline::Suggestion;
use std::collections::HashMap;
use std::sync::Arc;
@ -79,21 +80,20 @@ impl Completer for CustomCompletion {
.map(|pd| {
let value = pd.into_value(span);
match &value {
Value::Record { .. } => {
let completions = value
.get_data_by_key("completions")
Value::Record { val, .. } => {
let completions = val
.get("completions")
.and_then(|val| {
val.as_list()
.ok()
.map(|it| map_value_completions(it.iter(), span, offset))
})
.unwrap_or_default();
let options = value.get_data_by_key("options");
let options = val.get("options");
if let Some(Value::Record { .. }) = &options {
let options = options.unwrap_or_default();
if let Some(Value::Record { val: options, .. }) = &options {
let should_sort = options
.get_data_by_key("sort")
.get("sort")
.and_then(|val| val.as_bool().ok())
.unwrap_or(false);
@ -103,11 +103,11 @@ impl Completer for CustomCompletion {
custom_completion_options = Some(CompletionOptions {
case_sensitive: options
.get_data_by_key("case_sensitive")
.get("case_sensitive")
.and_then(|val| val.as_bool().ok())
.unwrap_or(true),
positional: options
.get_data_by_key("positional")
.get("positional")
.and_then(|val| val.as_bool().ok())
.unwrap_or(true),
sort_by: if should_sort {
@ -115,9 +115,7 @@ impl Completer for CustomCompletion {
} else {
SortBy::None
},
match_algorithm: match options
.get_data_by_key("completion_algorithm")
{
match_algorithm: match options.get("completion_algorithm") {
Some(option) => option
.as_string()
.ok()
@ -156,8 +154,8 @@ fn filter(prefix: &[u8], items: Vec<Suggestion>, options: &CompletionOptions) ->
(true, true) => it.value.as_bytes().starts_with(prefix),
(true, false) => it.value.contains(std::str::from_utf8(prefix).unwrap_or("")),
(false, positional) => {
let value = it.value.to_lowercase();
let prefix = std::str::from_utf8(prefix).unwrap_or("").to_lowercase();
let value = it.value.to_folded_case();
let prefix = std::str::from_utf8(prefix).unwrap_or("").to_folded_case();
if positional {
value.starts_with(&prefix)
} else {

View File

@ -1,4 +1,7 @@
use crate::completions::{completion_common::complete_item, Completer, CompletionOptions, SortBy};
use crate::completions::{
completion_common::{adjust_if_intermediate, complete_item, AdjustView},
Completer, CompletionOptions, SortBy,
};
use nu_protocol::{
engine::{EngineState, StateWorkingSet},
levenshtein_distance, Span,
@ -21,19 +24,19 @@ impl DirectoryCompletion {
impl Completer for DirectoryCompletion {
fn fetch(
&mut self,
_: &StateWorkingSet,
working_set: &StateWorkingSet,
prefix: Vec<u8>,
span: Span,
offset: usize,
_: usize,
options: &CompletionOptions,
) -> Vec<Suggestion> {
let partial = String::from_utf8_lossy(&prefix).to_string();
let AdjustView { prefix, span, .. } = adjust_if_intermediate(&prefix, working_set, span);
// Filter only the folders
let output: Vec<_> = directory_completion(
span,
&partial,
&prefix,
&self.engine_state.current_work_dir(),
options,
)

View File

@ -5,7 +5,7 @@ use nu_protocol::{
};
use reedline::Suggestion;
use std::{
path::{is_separator, MAIN_SEPARATOR as SEP, MAIN_SEPARATOR_STR},
path::{is_separator, Path, MAIN_SEPARATOR as SEP, MAIN_SEPARATOR_STR},
sync::Arc,
};
@ -91,16 +91,21 @@ impl Completer for DotNuCompletion {
// and transform them into suggestions
let output: Vec<Suggestion> = search_dirs
.into_iter()
.flat_map(|it| {
file_path_completion(span, &partial, &it, options)
.flat_map(|search_dir| {
let completions = file_path_completion(span, &partial, &search_dir, options);
completions
.into_iter()
.filter(|it| {
.filter(move |it| {
// Different base dir, so we list the .nu files or folders
if !is_current_folder {
it.1.ends_with(".nu") || it.1.ends_with(SEP)
} else {
// Lib dirs, so we filter only the .nu files
it.1.ends_with(".nu")
// Lib dirs, so we filter only the .nu files or directory modules
if it.1.ends_with(SEP) {
Path::new(&search_dir).join(&it.1).join("mod.nu").exists()
} else {
it.1.ends_with(".nu")
}
}
})
.map(move |x| Suggestion {

View File

@ -1,8 +1,12 @@
use crate::completions::{completion_common::complete_item, Completer, CompletionOptions, SortBy};
use crate::completions::{
completion_common::{adjust_if_intermediate, complete_item, AdjustView},
Completer, CompletionOptions, SortBy,
};
use nu_protocol::{
engine::{EngineState, StateWorkingSet},
levenshtein_distance, Span,
};
use nu_utils::IgnoreCaseExt;
use reedline::Suggestion;
use std::path::{Path, MAIN_SEPARATOR as SEP};
use std::sync::Arc;
@ -21,15 +25,21 @@ impl FileCompletion {
impl Completer for FileCompletion {
fn fetch(
&mut self,
_: &StateWorkingSet,
working_set: &StateWorkingSet,
prefix: Vec<u8>,
span: Span,
offset: usize,
_: usize,
options: &CompletionOptions,
) -> Vec<Suggestion> {
let prefix = String::from_utf8_lossy(&prefix).to_string();
let output: Vec<_> = file_path_completion(
let AdjustView {
prefix,
span,
readjusted,
} = adjust_if_intermediate(&prefix, working_set, span);
let output: Vec<_> = complete_item(
readjusted,
span,
&prefix,
&self.engine_state.current_work_dir(),
@ -116,7 +126,7 @@ pub fn matches(partial: &str, from: &str, options: &CompletionOptions) -> bool {
if !options.case_sensitive {
return options
.match_algorithm
.matches_str(&from.to_ascii_lowercase(), &partial.to_ascii_lowercase());
.matches_str(&from.to_folded_case(), &partial.to_folded_case());
}
options.match_algorithm.matches_str(from, partial)

View File

@ -43,10 +43,8 @@ impl Completer for VariableCompletion {
options: &CompletionOptions,
) -> Vec<Suggestion> {
let mut output = vec![];
let builtins = ["$nu", "$in", "$env", "$nothing"];
let var_str = std::str::from_utf8(&self.var_context.0)
.unwrap_or("")
.to_lowercase();
let builtins = ["$nu", "$in", "$env"];
let var_str = std::str::from_utf8(&self.var_context.0).unwrap_or("");
let var_id = working_set.find_variable(&self.var_context.0);
let current_span = reedline::Span {
start: span.start - offset,
@ -57,7 +55,7 @@ impl Completer for VariableCompletion {
// Completions for the given variable
if !var_str.is_empty() {
// Completion for $env.<tab>
if var_str.as_str() == "$env" {
if var_str == "$env" {
let env_vars = self.stack.get_env_vars(&self.engine_state);
// Return nested values
@ -109,7 +107,7 @@ impl Completer for VariableCompletion {
}
// Completions for $nu.<tab>
if var_str.as_str() == "$nu" {
if var_str == "$nu" {
// Eval nu var
if let Ok(nuval) = eval_variable(
&self.engine_state,
@ -237,9 +235,9 @@ fn nested_suggestions(
match value {
Value::Record { val, .. } => {
// Add all the columns as completion
for item in val.cols {
for (col, _) in val.into_iter() {
output.push(Suggestion {
value: item,
value: col,
description: None,
extra: None,
span: current_span,

View File

@ -28,13 +28,17 @@ pub fn evaluate_commands(
let (block, delta) = {
if let Some(ref t_mode) = table_mode {
let mut config = engine_state.get_config().clone();
config.table_mode = t_mode.as_string()?;
engine_state.set_config(&config);
config.table_mode = t_mode.as_string()?.parse().unwrap_or_default();
engine_state.set_config(config);
}
let mut working_set = StateWorkingSet::new(engine_state);
let output = parse(&mut working_set, None, commands.item.as_bytes(), false);
if let Some(warning) = working_set.parse_warnings.first() {
report_error(&working_set, warning);
}
if let Some(err) = working_set.parse_errors.first() {
report_error(&working_set, err);
@ -55,7 +59,7 @@ pub fn evaluate_commands(
Ok(pipeline_data) => {
let mut config = engine_state.get_config().clone();
if let Some(t_mode) = table_mode {
config.table_mode = t_mode.as_string()?;
config.table_mode = t_mode.as_string()?.parse().unwrap_or_default();
}
crate::eval_file::print_table_or_error(engine_state, stack, pipeline_data, &mut config)
}

View File

@ -35,10 +35,10 @@ pub fn evaluate_file(
let working_set = StateWorkingSet::new(engine_state);
report_error(
&working_set,
&ShellError::FileNotFoundCustom(
format!("Could not access file '{}': {:?}", path, e.to_string()),
Span::unknown(),
),
&ShellError::FileNotFoundCustom {
msg: format!("Could not access file '{}': {:?}", path, e.to_string()),
span: Span::unknown(),
},
);
std::process::exit(1);
});
@ -47,13 +47,13 @@ pub fn evaluate_file(
let working_set = StateWorkingSet::new(engine_state);
report_error(
&working_set,
&ShellError::NonUtf8Custom(
format!(
&ShellError::NonUtf8Custom {
msg: format!(
"Input file name '{}' is not valid UTF8",
file_path.to_string_lossy()
),
Span::unknown(),
),
span: Span::unknown(),
},
);
std::process::exit(1);
});
@ -64,14 +64,14 @@ pub fn evaluate_file(
let working_set = StateWorkingSet::new(engine_state);
report_error(
&working_set,
&ShellError::FileNotFoundCustom(
format!(
&ShellError::FileNotFoundCustom {
msg: format!(
"Could not read file '{}': {:?}",
file_path_str,
e.to_string()
),
Span::unknown(),
),
span: Span::unknown(),
},
);
std::process::exit(1);
});
@ -82,10 +82,10 @@ pub fn evaluate_file(
let working_set = StateWorkingSet::new(engine_state);
report_error(
&working_set,
&ShellError::FileNotFoundCustom(
format!("The file path '{file_path_str}' does not have a parent"),
Span::unknown(),
),
&ShellError::FileNotFoundCustom {
msg: format!("The file path '{file_path_str}' does not have a parent"),
span: Span::unknown(),
},
);
std::process::exit(1);
});
@ -98,6 +98,10 @@ pub fn evaluate_file(
"CURRENT_FILE".to_string(),
Value::string(file_path.to_string_lossy(), Span::unknown()),
);
stack.add_env_var(
"PROCESS_PATH".to_string(),
Value::string(path, Span::unknown()),
);
let source_filename = file_path
.file_name()
@ -135,7 +139,7 @@ pub fn evaluate_file(
false,
);
let pipeline_data = match pipeline_data {
Err(ShellError::Return(_, _)) => {
Err(ShellError::Return { .. }) => {
// allows early exists before `main` is run.
return Ok(());
}
@ -195,7 +199,7 @@ pub(crate) fn print_table_or_error(
};
// Change the engine_state config to use the passed in configuration
engine_state.set_config(config);
engine_state.set_config(config.clone());
if let PipelineData::Value(Value::Error { error, .. }, ..) = &pipeline_data {
let working_set = StateWorkingSet::new(engine_state);

View File

@ -1,5 +1,6 @@
use nu_engine::documentation::get_flags_section;
use nu_protocol::{engine::EngineState, levenshtein_distance};
use nu_utils::IgnoreCaseExt;
use reedline::{Completer, Suggestion};
use std::fmt::Write;
use std::sync::Arc;
@ -13,21 +14,19 @@ impl NuHelpCompleter {
fn completion_helper(&self, line: &str, pos: usize) -> Vec<Suggestion> {
let full_commands = self.0.get_signatures_with_examples(false);
let folded_line = line.to_folded_case();
//Vec<(Signature, Vec<Example>, bool, bool)> {
let mut commands = full_commands
.iter()
.filter(|(sig, _, _, _, _)| {
sig.name.to_lowercase().contains(&line.to_lowercase())
|| sig.usage.to_lowercase().contains(&line.to_lowercase())
sig.name.to_folded_case().contains(&folded_line)
|| sig.usage.to_folded_case().contains(&folded_line)
|| sig
.search_terms
.iter()
.any(|term| term.to_lowercase().contains(&line.to_lowercase()))
|| sig
.extra_usage
.to_lowercase()
.contains(&line.to_lowercase())
.any(|term| term.to_folded_case().contains(&folded_line))
|| sig.extra_usage.to_folded_case().contains(&folded_line)
})
.collect::<Vec<_>>();

View File

@ -80,24 +80,18 @@ fn convert_to_suggestions(
only_buffer_difference: bool,
) -> Vec<Suggestion> {
match value {
Value::Record { .. } => {
let text = value
.get_data_by_key("value")
Value::Record { val, .. } => {
let text = val
.get("value")
.and_then(|val| val.as_string().ok())
.unwrap_or_else(|| "No value key".to_string());
let description = value
.get_data_by_key("description")
.and_then(|val| val.as_string().ok());
let description = val.get("description").and_then(|val| val.as_string().ok());
let span = match value.get_data_by_key("span") {
Some(span @ Value::Record { .. }) => {
let start = span
.get_data_by_key("start")
.and_then(|val| val.as_int().ok());
let end = span
.get_data_by_key("end")
.and_then(|val| val.as_int().ok());
let span = match val.get("span") {
Some(Value::Record { val: span, .. }) => {
let start = span.get("start").and_then(|val| val.as_int().ok());
let end = span.get("end").and_then(|val| val.as_int().ok());
match (start, end) {
(Some(start), Some(end)) => {
let start = start.min(end);
@ -126,12 +120,12 @@ fn convert_to_suggestions(
},
};
let extra = match value.get_data_by_key("extra") {
let extra = match val.get("extra") {
Some(Value::List { vals, .. }) => {
let extra: Vec<String> = vals
.into_iter()
.iter()
.filter_map(|extra| match extra {
Value::String { val, .. } => Some(val),
Value::String { val, .. } => Some(val.clone()),
_ => None,
})
.collect();

View File

@ -1,3 +1,4 @@
use crate::prompt_update::{POST_PROMPT_MARKER, PRE_PROMPT_MARKER};
#[cfg(windows)]
use nu_utils::enable_vt_processing;
use reedline::DefaultPrompt;
@ -11,6 +12,7 @@ use {
/// Nushell prompt definition
#[derive(Clone)]
pub struct NushellPrompt {
shell_integration: bool,
left_prompt_string: Option<String>,
right_prompt_string: Option<String>,
default_prompt_indicator: Option<String>,
@ -20,15 +22,10 @@ pub struct NushellPrompt {
render_right_prompt_on_last_line: bool,
}
impl Default for NushellPrompt {
fn default() -> Self {
NushellPrompt::new()
}
}
impl NushellPrompt {
pub fn new() -> NushellPrompt {
pub fn new(shell_integration: bool) -> NushellPrompt {
NushellPrompt {
shell_integration,
left_prompt_string: None,
right_prompt_string: None,
default_prompt_indicator: None,
@ -111,7 +108,11 @@ impl Prompt for NushellPrompt {
.to_string()
.replace('\n', "\r\n");
prompt.into()
if self.shell_integration {
format!("{PRE_PROMPT_MARKER}{prompt}{POST_PROMPT_MARKER}").into()
} else {
prompt.into()
}
}
}

View File

@ -7,8 +7,6 @@ use nu_protocol::{
Config, PipelineData, Value,
};
use reedline::Prompt;
use std::borrow::Cow;
use std::sync::Arc;
// Name of environment variable where the prompt could be stored
pub(crate) const PROMPT_COMMAND: &str = "PROMPT_COMMAND";
@ -28,8 +26,8 @@ pub(crate) const TRANSIENT_PROMPT_MULTILINE_INDICATOR: &str =
"TRANSIENT_PROMPT_MULTILINE_INDICATOR";
// According to Daniel Imms @Tyriar, we need to do these this way:
// <133 A><prompt><133 B><command><133 C><command output>
const PRE_PROMPT_MARKER: &str = "\x1b]133;A\x1b\\";
const POST_PROMPT_MARKER: &str = "\x1b]133;B\x1b\\";
pub(crate) const PRE_PROMPT_MARKER: &str = "\x1b]133;A\x1b\\";
pub(crate) const POST_PROMPT_MARKER: &str = "\x1b]133;B\x1b\\";
fn get_prompt_string(
prompt: &str,
@ -40,13 +38,9 @@ fn get_prompt_string(
stack
.get_env_var(engine_state, prompt)
.and_then(|v| match v {
Value::Closure {
val: block_id,
captures,
..
} => {
let block = engine_state.get_block(block_id);
let mut stack = stack.captures_to_stack(&captures);
Value::Closure { val, .. } => {
let block = engine_state.get_block(val.block_id);
let mut stack = stack.captures_to_stack(val.captures);
// Use eval_subexpression to force a redirection of output, so we can use everything in prompt
let ret_val =
eval_subexpression(engine_state, &mut stack, block, PipelineData::empty());
@ -102,12 +96,12 @@ fn get_prompt_string(
})
}
pub(crate) fn update_prompt<'prompt>(
pub(crate) fn update_prompt(
config: &Config,
engine_state: &EngineState,
stack: &Stack,
nu_prompt: &'prompt mut NushellPrompt,
) -> &'prompt dyn Prompt {
nu_prompt: &mut NushellPrompt,
) {
let mut stack = stack.clone();
let left_prompt_string = get_prompt_string(PROMPT_COMMAND, config, engine_state, &mut stack);
@ -150,125 +144,55 @@ pub(crate) fn update_prompt<'prompt>(
(prompt_vi_insert_string, prompt_vi_normal_string),
config.render_right_prompt_on_last_line,
);
let ret_val = nu_prompt as &dyn Prompt;
trace!("update_prompt {}:{}:{}", file!(), line!(), column!());
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,
/// Construct the transient prompt based on the normal nu_prompt
pub(crate) fn make_transient_prompt(
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))
}
nu_prompt: &NushellPrompt,
) -> Box<dyn Prompt> {
let mut nu_prompt = nu_prompt.clone();
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()
if let Some(s) = get_prompt_string(TRANSIENT_PROMPT_COMMAND, config, engine_state, stack) {
nu_prompt.update_prompt_left(Some(s))
}
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()
if let Some(s) = get_prompt_string(TRANSIENT_PROMPT_COMMAND_RIGHT, config, engine_state, stack)
{
nu_prompt.update_prompt_right(Some(s), config.render_right_prompt_on_last_line)
}
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()
if let Some(s) = get_prompt_string(TRANSIENT_PROMPT_INDICATOR, config, engine_state, stack) {
nu_prompt.update_prompt_indicator(Some(s))
}
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 {
if let Some(s) = get_prompt_string(
TRANSIENT_PROMPT_INDICATOR_VI_INSERT,
config,
engine_state,
stack: stack.clone(),
})
stack,
) {
nu_prompt.update_prompt_vi_insert(Some(s))
}
if let Some(s) = get_prompt_string(
TRANSIENT_PROMPT_INDICATOR_VI_NORMAL,
config,
engine_state,
stack,
) {
nu_prompt.update_prompt_vi_normal(Some(s))
}
if let Some(s) = get_prompt_string(
TRANSIENT_PROMPT_MULTILINE_INDICATOR,
config,
engine_state,
stack,
) {
nu_prompt.update_prompt_multiline(Some(s))
}
Box::new(nu_prompt)
}

View File

@ -7,8 +7,8 @@ use nu_parser::parse;
use nu_protocol::{
create_menus,
engine::{EngineState, Stack, StateWorkingSet},
extract_value, Config, ParsedKeybinding, ParsedMenu, PipelineData, Record, ShellError, Span,
Value,
extract_value, Config, EditBindings, ParsedKeybinding, ParsedMenu, PipelineData, Record,
ShellError, Span, Value,
};
use reedline::{
default_emacs_keybindings, default_vi_insert_keybindings, default_vi_normal_keybindings,
@ -139,18 +139,18 @@ fn add_menu(
"columnar" => add_columnar_menu(line_editor, menu, engine_state, stack, config),
"list" => add_list_menu(line_editor, menu, engine_state, stack, config),
"description" => add_description_menu(line_editor, menu, engine_state, stack, config),
_ => Err(ShellError::UnsupportedConfigValue(
"columnar, list or description".to_string(),
menu.menu_type.into_abbreviated_string(config),
menu.menu_type.span(),
)),
_ => Err(ShellError::UnsupportedConfigValue {
expected: "columnar, list or description".to_string(),
value: menu.menu_type.into_abbreviated_string(config),
span: menu.menu_type.span(),
}),
}
} else {
Err(ShellError::UnsupportedConfigValue(
"only record type".to_string(),
menu.menu_type.into_abbreviated_string(config),
menu.menu_type.span(),
))
Err(ShellError::UnsupportedConfigValue {
expected: "only record type".to_string(),
value: menu.menu_type.into_abbreviated_string(config),
span: menu.menu_type.span(),
})
}
}
@ -248,11 +248,11 @@ pub(crate) fn add_columnar_menu(
Value::Nothing { .. } => {
Ok(line_editor.with_menu(ReedlineMenu::EngineCompleter(Box::new(columnar_menu))))
}
Value::Closure { val, captures, .. } => {
Value::Closure { val, .. } => {
let menu_completer = NuMenuCompleter::new(
*val,
val.block_id,
span,
stack.captures_to_stack(captures),
stack.captures_to_stack(val.captures.clone()),
engine_state,
only_buffer_difference,
);
@ -261,11 +261,11 @@ pub(crate) fn add_columnar_menu(
completer: Box::new(menu_completer),
}))
}
_ => Err(ShellError::UnsupportedConfigValue(
"block or omitted value".to_string(),
menu.source.into_abbreviated_string(config),
_ => Err(ShellError::UnsupportedConfigValue {
expected: "block or omitted value".to_string(),
value: menu.source.into_abbreviated_string(config),
span,
)),
}),
}
}
@ -330,11 +330,11 @@ pub(crate) fn add_list_menu(
Value::Nothing { .. } => {
Ok(line_editor.with_menu(ReedlineMenu::HistoryMenu(Box::new(list_menu))))
}
Value::Closure { val, captures, .. } => {
Value::Closure { val, .. } => {
let menu_completer = NuMenuCompleter::new(
*val,
val.block_id,
span,
stack.captures_to_stack(captures),
stack.captures_to_stack(val.captures.clone()),
engine_state,
only_buffer_difference,
);
@ -343,11 +343,11 @@ pub(crate) fn add_list_menu(
completer: Box::new(menu_completer),
}))
}
_ => Err(ShellError::UnsupportedConfigValue(
"block or omitted value".to_string(),
menu.source.into_abbreviated_string(config),
menu.source.span(),
)),
_ => Err(ShellError::UnsupportedConfigValue {
expected: "block or omitted value".to_string(),
value: menu.source.into_abbreviated_string(config),
span: menu.source.span(),
}),
}
}
@ -448,11 +448,11 @@ pub(crate) fn add_description_menu(
completer,
}))
}
Value::Closure { val, captures, .. } => {
Value::Closure { val, .. } => {
let menu_completer = NuMenuCompleter::new(
*val,
val.block_id,
span,
stack.captures_to_stack(captures),
stack.captures_to_stack(val.captures.clone()),
engine_state,
only_buffer_difference,
);
@ -461,11 +461,11 @@ pub(crate) fn add_description_menu(
completer: Box::new(menu_completer),
}))
}
_ => Err(ShellError::UnsupportedConfigValue(
"closure or omitted value".to_string(),
menu.source.into_abbreviated_string(config),
menu.source.span(),
)),
_ => Err(ShellError::UnsupportedConfigValue {
expected: "closure or omitted value".to_string(),
value: menu.source.into_abbreviated_string(config),
span: menu.source.span(),
}),
}
}
@ -537,11 +537,11 @@ pub(crate) fn create_keybindings(config: &Config) -> Result<KeybindingsMode, She
let mut insert_keybindings = default_vi_insert_keybindings();
let mut normal_keybindings = default_vi_normal_keybindings();
match config.edit_mode.as_str() {
"emacs" => {
match config.edit_mode {
EditBindings::Emacs => {
add_menu_keybindings(&mut emacs_keybindings);
}
_ => {
EditBindings::Vi => {
add_menu_keybindings(&mut insert_keybindings);
add_menu_keybindings(&mut normal_keybindings);
}
@ -557,9 +557,9 @@ pub(crate) fn create_keybindings(config: &Config) -> Result<KeybindingsMode, She
)?
}
match config.edit_mode.as_str() {
"emacs" => Ok(KeybindingsMode::Emacs(emacs_keybindings)),
_ => Ok(KeybindingsMode::Vi {
match config.edit_mode {
EditBindings::Emacs => Ok(KeybindingsMode::Emacs(emacs_keybindings)),
EditBindings::Vi => Ok(KeybindingsMode::Vi {
insert_keybindings,
normal_keybindings,
}),
@ -580,11 +580,11 @@ fn add_keybinding(
"emacs" => add_parsed_keybinding(emacs_keybindings, keybinding, config),
"vi_insert" => add_parsed_keybinding(insert_keybindings, keybinding, config),
"vi_normal" => add_parsed_keybinding(normal_keybindings, keybinding, config),
m => Err(ShellError::UnsupportedConfigValue(
"emacs, vi_insert or vi_normal".to_string(),
m.to_string(),
m => Err(ShellError::UnsupportedConfigValue {
expected: "emacs, vi_insert or vi_normal".to_string(),
value: m.to_string(),
span,
)),
}),
},
Value::List { vals, .. } => {
for inner_mode in vals {
@ -600,11 +600,11 @@ fn add_keybinding(
Ok(())
}
v => Err(ShellError::UnsupportedConfigValue(
"string or list of strings".to_string(),
v.into_abbreviated_string(config),
v.span(),
)),
v => Err(ShellError::UnsupportedConfigValue {
expected: "string or list of strings".to_string(),
value: v.into_abbreviated_string(config),
span: v.span(),
}),
}
}
@ -616,7 +616,7 @@ fn add_parsed_keybinding(
let modifier = match keybinding
.modifier
.into_string("", config)
.to_lowercase()
.to_ascii_lowercase()
.as_str()
{
"control" => KeyModifiers::CONTROL,
@ -630,18 +630,18 @@ fn add_parsed_keybinding(
KeyModifiers::CONTROL | KeyModifiers::ALT | KeyModifiers::SHIFT
}
_ => {
return Err(ShellError::UnsupportedConfigValue(
"CONTROL, SHIFT, ALT or NONE".to_string(),
keybinding.modifier.into_abbreviated_string(config),
keybinding.modifier.span(),
))
return Err(ShellError::UnsupportedConfigValue {
expected: "CONTROL, SHIFT, ALT or NONE".to_string(),
value: keybinding.modifier.into_abbreviated_string(config),
span: keybinding.modifier.span(),
})
}
};
let keycode = match keybinding
.keycode
.into_string("", config)
.to_lowercase()
.to_ascii_lowercase()
.as_str()
{
"backspace" => KeyCode::Backspace,
@ -654,11 +654,11 @@ fn add_parsed_keybinding(
let char = if let (Some(char), None) = (pos1, pos2) {
char
} else {
return Err(ShellError::UnsupportedConfigValue(
"char_<CHAR: unicode codepoint>".to_string(),
c.to_string(),
keybinding.keycode.span(),
));
return Err(ShellError::UnsupportedConfigValue {
expected: "char_<CHAR: unicode codepoint>".to_string(),
value: c.to_string(),
span: keybinding.keycode.span(),
});
};
KeyCode::Char(char)
@ -681,21 +681,21 @@ fn add_parsed_keybinding(
.parse()
.ok()
.filter(|num| matches!(num, 1..=20))
.ok_or(ShellError::UnsupportedConfigValue(
"(f1|f2|...|f20)".to_string(),
format!("unknown function key: {c}"),
keybinding.keycode.span(),
))?;
.ok_or(ShellError::UnsupportedConfigValue {
expected: "(f1|f2|...|f20)".to_string(),
value: format!("unknown function key: {c}"),
span: keybinding.keycode.span(),
})?;
KeyCode::F(fn_num)
}
"null" => KeyCode::Null,
"esc" | "escape" => KeyCode::Esc,
_ => {
return Err(ShellError::UnsupportedConfigValue(
"crossterm KeyCode".to_string(),
keybinding.keycode.into_abbreviated_string(config),
keybinding.keycode.span(),
))
return Err(ShellError::UnsupportedConfigValue {
expected: "crossterm KeyCode".to_string(),
value: keybinding.keycode.into_abbreviated_string(config),
span: keybinding.keycode.span(),
})
}
};
if let Some(event) = parse_event(&keybinding.event, config)? {
@ -719,7 +719,10 @@ impl<'config> EventType<'config> {
.map(Self::Send)
.or_else(|_| extract_value("edit", record, span).map(Self::Edit))
.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 {
missing_value: "send, edit or until".to_string(),
span,
})
}
}
@ -728,7 +731,7 @@ fn parse_event(value: &Value, config: &Config) -> Result<Option<ReedlineEvent>,
match value {
Value::Record { val: record, .. } => match EventType::try_from_record(record, span)? {
EventType::Send(value) => event_from_record(
value.into_string("", config).to_lowercase().as_str(),
value.into_string("", config).to_ascii_lowercase().as_str(),
record,
config,
span,
@ -736,7 +739,7 @@ fn parse_event(value: &Value, config: &Config) -> Result<Option<ReedlineEvent>,
.map(Some),
EventType::Edit(value) => {
let edit = edit_from_record(
value.into_string("", config).to_lowercase().as_str(),
value.into_string("", config).to_ascii_lowercase().as_str(),
record,
config,
span,
@ -749,11 +752,11 @@ fn parse_event(value: &Value, config: &Config) -> Result<Option<ReedlineEvent>,
.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(),
)),
None => Err(ShellError::UnsupportedConfigValue {
expected: "List containing valid events".to_string(),
value: "Nothing value (null)".to_string(),
span: value.span(),
}),
Some(event) => Ok(event),
},
Err(e) => Err(e),
@ -762,11 +765,11 @@ fn parse_event(value: &Value, config: &Config) -> Result<Option<ReedlineEvent>,
Ok(Some(ReedlineEvent::UntilFound(events)))
}
v => Err(ShellError::UnsupportedConfigValue(
"list of events".to_string(),
v.into_abbreviated_string(config),
v.span(),
)),
v => Err(ShellError::UnsupportedConfigValue {
expected: "list of events".to_string(),
value: v.into_abbreviated_string(config),
span: v.span(),
}),
},
},
Value::List { vals, .. } => {
@ -774,11 +777,11 @@ fn parse_event(value: &Value, config: &Config) -> Result<Option<ReedlineEvent>,
.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(),
)),
None => Err(ShellError::UnsupportedConfigValue {
expected: "List containing valid events".to_string(),
value: "Nothing value (null)".to_string(),
span: value.span(),
}),
Some(event) => Ok(event),
},
Err(e) => Err(e),
@ -788,11 +791,11 @@ fn parse_event(value: &Value, config: &Config) -> Result<Option<ReedlineEvent>,
Ok(Some(ReedlineEvent::Multiple(events)))
}
Value::Nothing { .. } => Ok(None),
v => Err(ShellError::UnsupportedConfigValue(
"record or list of records, null to unbind key".to_string(),
v.into_abbreviated_string(config),
v.span(),
)),
v => Err(ShellError::UnsupportedConfigValue {
expected: "record or list of records, null to unbind key".to_string(),
value: v.into_abbreviated_string(config),
span: v.span(),
}),
}
}
@ -840,11 +843,11 @@ fn event_from_record(
ReedlineEvent::ExecuteHostCommand(cmd.into_string("", config))
}
v => {
return Err(ShellError::UnsupportedConfigValue(
"Reedline event".to_string(),
v.to_string(),
return Err(ShellError::UnsupportedConfigValue {
expected: "Reedline event".to_string(),
value: v.to_string(),
span,
))
})
}
};
@ -954,11 +957,11 @@ fn edit_from_record(
}
"complete" => EditCommand::Complete,
e => {
return Err(ShellError::UnsupportedConfigValue(
"reedline EditCommand".to_string(),
e.to_string(),
return Err(ShellError::UnsupportedConfigValue {
expected: "reedline EditCommand".to_string(),
value: e.to_string(),
span,
))
})
}
};
@ -971,18 +974,23 @@ fn extract_char(value: &Value, config: &Config) -> Result<char, ShellError> {
.into_string("", config)
.chars()
.next()
.ok_or_else(|| ShellError::MissingConfigValue("char to insert".to_string(), span))
.ok_or_else(|| ShellError::MissingConfigValue {
missing_value: "char to insert".to_string(),
span,
})
}
#[cfg(test)]
mod test {
use nu_protocol::record;
use super::*;
#[test]
fn test_send_event() {
let cols = vec!["send".to_string()];
let vals = vec![Value::test_string("Enter")];
let event = Record { vals, cols };
let event = record! {
"send" => Value::test_string("Enter"),
};
let span = Span::test_data();
let b = EventType::try_from_record(&event, span).unwrap();
@ -997,9 +1005,9 @@ mod test {
#[test]
fn test_edit_event() {
let cols = vec!["edit".to_string()];
let vals = vec![Value::test_string("Clear")];
let event = Record { vals, cols };
let event = record! {
"edit" => Value::test_string("Clear"),
};
let span = Span::test_data();
let b = EventType::try_from_record(&event, span).unwrap();
@ -1017,12 +1025,10 @@ mod test {
#[test]
fn test_send_menu() {
let cols = vec!["send".to_string(), "name".to_string()];
let vals = vec![
Value::test_string("Menu"),
Value::test_string("history_menu"),
];
let event = Record { vals, cols };
let event = record! {
"send" => Value::test_string("Menu"),
"name" => Value::test_string("history_menu"),
};
let span = Span::test_data();
let b = EventType::try_from_record(&event, span).unwrap();
@ -1040,28 +1046,19 @@ mod test {
#[test]
fn test_until_event() {
// Menu event
let cols = vec!["send".to_string(), "name".to_string()];
let vals = vec![
Value::test_string("Menu"),
Value::test_string("history_menu"),
];
let menu_event = Value::test_record(Record { cols, vals });
// Enter event
let cols = vec!["send".to_string()];
let vals = vec![Value::test_string("Enter")];
let enter_event = Value::test_record(Record { cols, vals });
// Until event
let cols = vec!["until".to_string()];
let vals = vec![Value::list(
vec![menu_event, enter_event],
Span::test_data(),
)];
let event = Record { cols, vals };
let menu_event = Value::test_record(record! {
"send" => Value::test_string("Menu"),
"name" => Value::test_string("history_menu"),
});
let enter_event = Value::test_record(record! {
"send" => Value::test_string("Enter"),
});
let event = record! {
"until" => Value::list(
vec![menu_event, enter_event],
Span::test_data(),
),
};
let span = Span::test_data();
let b = EventType::try_from_record(&event, span).unwrap();
@ -1082,22 +1079,13 @@ mod test {
#[test]
fn test_multiple_event() {
// Menu event
let cols = vec!["send".to_string(), "name".to_string()];
let vals = vec![
Value::test_string("Menu"),
Value::test_string("history_menu"),
];
let menu_event = Value::test_record(Record { cols, vals });
// Enter event
let cols = vec!["send".to_string()];
let vals = vec![Value::test_string("Enter")];
let enter_event = Value::test_record(Record { cols, vals });
// Multiple event
let menu_event = Value::test_record(record! {
"send" => Value::test_string("Menu"),
"name" => Value::test_string("history_menu"),
});
let enter_event = Value::test_record(record! {
"send" => Value::test_string("Enter"),
});
let event = Value::list(vec![menu_event, enter_event], Span::test_data());
let config = Config::default();
@ -1113,12 +1101,12 @@ mod test {
#[test]
fn test_error() {
let cols = vec!["not_exist".to_string()];
let vals = vec![Value::test_string("Enter")];
let event = Record { cols, vals };
let event = record! {
"not_exist" => Value::test_string("Enter"),
};
let span = Span::test_data();
let b = EventType::try_from_record(&event, span);
assert!(matches!(b, Err(ShellError::MissingConfigValue(_, _))));
assert!(matches!(b, Err(ShellError::MissingConfigValue { .. })));
}
}

View File

@ -22,8 +22,8 @@ use nu_protocol::{
};
use nu_utils::utils::perf;
use reedline::{
CursorConfig, DefaultHinter, EditCommand, Emacs, FileBackedHistory, HistorySessionId, Reedline,
SqliteBackedHistory, Vi,
CursorConfig, CwdAwareHinter, EditCommand, Emacs, FileBackedHistory, HistorySessionId,
Reedline, SqliteBackedHistory, Vi,
};
use std::{
env::temp_dir,
@ -32,7 +32,7 @@ use std::{
sync::atomic::Ordering,
time::Instant,
};
use sysinfo::SystemExt;
use sysinfo::System;
// According to Daniel Imms @Tyriar, we need to do these this way:
// <133 A><prompt><133 B><command><133 C><command output>
@ -54,7 +54,8 @@ pub fn evaluate_repl(
) -> Result<()> {
use nu_cmd_base::hook;
use reedline::Signal;
let use_color = engine_state.get_config().use_ansi_coloring;
let config = engine_state.get_config();
let use_color = config.use_ansi_coloring;
// Guard against invocation without a connected terminal.
// reedline / crossterm event polling will fail without a connected tty
@ -68,7 +69,7 @@ pub fn evaluate_repl(
let mut entry_num = 0;
let mut nu_prompt = NushellPrompt::new();
let mut nu_prompt = NushellPrompt::new(config.shell_integration);
let start_time = std::time::Instant::now();
// Translate environment variables from Strings to Values
@ -108,16 +109,8 @@ pub fn evaluate_repl(
use_color,
);
let config = engine_state.get_config();
if config.bracketed_paste {
// try to enable bracketed paste
// It doesn't work on windows system: https://github.com/crossterm-rs/crossterm/issues/737
#[cfg(not(target_os = "windows"))]
let _ = line_editor.enable_bracketed_paste();
}
// Setup history_isolation aka "history per session"
let history_isolation = config.history_isolation;
let history_isolation = engine_state.get_config().history_isolation;
let history_session_id = if history_isolation {
Reedline::create_history_session_id()
} else {
@ -142,17 +135,6 @@ pub fn evaluate_repl(
use_color,
);
start_time = std::time::Instant::now();
let sys = sysinfo::System::new();
perf(
"get sysinfo",
start_time,
file!(),
line!(),
column!(),
use_color,
);
if let Some(s) = prerun_command {
eval_source(
engine_state,
@ -182,12 +164,8 @@ 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");
}
if engine_state.get_config().use_kitty_protocol && !reedline::kitty_protocol_available() {
warn!("Terminal doesn't support use_kitty_protocol config");
}
loop {
@ -224,20 +202,6 @@ pub fn evaluate_repl(
use_color,
);
start_time = std::time::Instant::now();
// Reset the SIGQUIT handler
if let Some(sig_quit) = engine_state.get_sig_quit() {
sig_quit.store(false, Ordering::SeqCst);
}
perf(
"reset sig_quit",
start_time,
file!(),
line!(),
column!(),
use_color,
);
start_time = std::time::Instant::now();
let config = engine_state.get_config();
@ -245,15 +209,9 @@ pub fn evaluate_repl(
// Find the configured cursor shapes for each mode
let cursor_config = CursorConfig {
vi_insert: config
.cursor_shape_vi_insert
.map(map_nucursorshape_to_cursorshape),
vi_normal: config
.cursor_shape_vi_normal
.map(map_nucursorshape_to_cursorshape),
emacs: config
.cursor_shape_emacs
.map(map_nucursorshape_to_cursorshape),
vi_insert: map_nucursorshape_to_cursorshape(config.cursor_shape_vi_insert),
vi_normal: map_nucursorshape_to_cursorshape(config.cursor_shape_vi_normal),
emacs: map_nucursorshape_to_cursorshape(config.cursor_shape_emacs),
};
perf(
"get config/cursor config",
@ -267,6 +225,10 @@ pub fn evaluate_repl(
start_time = std::time::Instant::now();
line_editor = line_editor
.use_kitty_keyboard_enhancement(config.use_kitty_protocol)
// try to enable bracketed paste
// It doesn't work on windows system: https://github.com/crossterm-rs/crossterm/issues/737
.use_bracketed_paste(cfg!(not(target_os = "windows")) && config.bracketed_paste)
.with_highlighter(Box::new(NuHighlighter {
engine_state: engine_reference.clone(),
config: config.clone(),
@ -281,11 +243,7 @@ pub fn evaluate_repl(
.with_quick_completions(config.quick_completions)
.with_partial_completions(config.partial_completions)
.with_ansi_colors(config.use_ansi_coloring)
.with_cursor_config(cursor_config)
.with_transient_prompt(prompt_update::transient_prompt(
engine_reference.clone(),
stack,
));
.with_cursor_config(cursor_config);
perf(
"reedline builder",
start_time,
@ -302,7 +260,7 @@ pub fn evaluate_repl(
line_editor.with_hinter(Box::new({
// As of Nov 2022, "hints" color_config closures only get `null` passed in.
let style = style_computer.compute("hints", &Value::nothing(Span::unknown()));
DefaultHinter::default().with_style(style)
CwdAwareHinter::default().with_style(style)
}))
} else {
line_editor.disable_hints()
@ -438,7 +396,9 @@ pub fn evaluate_repl(
start_time = std::time::Instant::now();
let config = &engine_state.get_config().clone();
let prompt = prompt_update::update_prompt(config, engine_state, stack, &mut nu_prompt);
prompt_update::update_prompt(config, engine_state, stack, &mut nu_prompt);
let transient_prompt =
prompt_update::make_transient_prompt(config, engine_state, stack, &nu_prompt);
perf(
"update_prompt",
start_time,
@ -451,12 +411,13 @@ pub fn evaluate_repl(
entry_num += 1;
start_time = std::time::Instant::now();
let input = line_editor.read_line(prompt);
line_editor = line_editor.with_transient_prompt(transient_prompt);
let input = line_editor.read_line(&nu_prompt);
let shell_integration = config.shell_integration;
match input {
Ok(Signal::Success(s)) => {
let hostname = sys.host_name();
let hostname = System::host_name();
let history_supports_meta =
matches!(config.history_file_format, HistoryFileFormat::Sqlite);
if history_supports_meta && !s.is_empty() && line_editor.has_last_command_context()
@ -516,10 +477,10 @@ pub fn evaluate_repl(
report_error(
&working_set,
&ShellError::DirectoryNotFound(
tokens.0[0].span,
path.to_string_lossy().to_string(),
),
&ShellError::DirectoryNotFound {
dir: path.to_string_lossy().to_string(),
span: tokens.0[0].span,
},
);
}
let path = nu_path::canonicalize_with(path, &cwd)
@ -596,10 +557,6 @@ pub fn evaluate_repl(
PipelineData::empty(),
false,
);
if engine_state.get_config().bracketed_paste {
#[cfg(not(target_os = "windows"))]
let _ = line_editor.enable_bracketed_paste();
}
}
let cmd_duration = start_time.elapsed();
@ -626,19 +583,29 @@ pub fn evaluate_repl(
if let Some(cwd) = stack.get_env_var(engine_state, "PWD") {
let path = cwd.as_string()?;
// Communicate the path as OSC 7 (often used for spawning new tabs in the same dir)
run_ansi_sequence(&format!(
"\x1b]7;file://{}{}{}\x1b\\",
percent_encoding::utf8_percent_encode(
&hostname.unwrap_or_else(|| "localhost".to_string()),
percent_encoding::CONTROLS
),
if path.starts_with('/') { "" } else { "/" },
percent_encoding::utf8_percent_encode(
&path,
percent_encoding::CONTROLS
)
))?;
// Supported escape sequences of Microsoft's Visual Studio Code (vscode)
// https://code.visualstudio.com/docs/terminal/shell-integration#_supported-escape-sequences
if stack.get_env_var(engine_state, "TERM_PROGRAM")
== Some(Value::test_string("vscode"))
{
// If we're in vscode, run their specific ansi escape sequence.
// This is helpful for ctrl+g to change directories in the terminal.
run_ansi_sequence(&format!("\x1b]633;P;Cwd={}\x1b\\", path))?;
} else {
// Otherwise, communicate the path as OSC 7 (often used for spawning new tabs in the same dir)
run_ansi_sequence(&format!(
"\x1b]7;file://{}{}{}\x1b\\",
percent_encoding::utf8_percent_encode(
&hostname.unwrap_or_else(|| "localhost".to_string()),
percent_encoding::CONTROLS
),
if path.starts_with('/') { "" } else { "/" },
percent_encoding::utf8_percent_encode(
&path,
percent_encoding::CONTROLS
)
))?;
}
// Try to abbreviate string for windows title
let maybe_abbrev_path = if let Some(p) = nu_path::home_dir() {
@ -760,18 +727,19 @@ fn update_line_editor_history(
Ok(line_editor)
}
fn map_nucursorshape_to_cursorshape(shape: NuCursorShape) -> SetCursorStyle {
fn map_nucursorshape_to_cursorshape(shape: NuCursorShape) -> Option<SetCursorStyle> {
match shape {
NuCursorShape::Block => SetCursorStyle::SteadyBlock,
NuCursorShape::UnderScore => SetCursorStyle::SteadyUnderScore,
NuCursorShape::Line => SetCursorStyle::SteadyBar,
NuCursorShape::BlinkBlock => SetCursorStyle::BlinkingBlock,
NuCursorShape::BlinkUnderScore => SetCursorStyle::BlinkingUnderScore,
NuCursorShape::BlinkLine => SetCursorStyle::BlinkingBar,
NuCursorShape::Block => Some(SetCursorStyle::SteadyBlock),
NuCursorShape::UnderScore => Some(SetCursorStyle::SteadyUnderScore),
NuCursorShape::Line => Some(SetCursorStyle::SteadyBar),
NuCursorShape::BlinkBlock => Some(SetCursorStyle::BlinkingBlock),
NuCursorShape::BlinkUnderScore => Some(SetCursorStyle::BlinkingUnderScore),
NuCursorShape::BlinkLine => Some(SetCursorStyle::BlinkingBar),
NuCursorShape::Inherit => None,
}
}
pub fn get_command_finished_marker(stack: &Stack, engine_state: &EngineState) -> String {
fn get_command_finished_marker(stack: &Stack, engine_state: &EngineState) -> String {
let exit_code = stack
.get_env_var(engine_state, "LAST_EXIT_CODE")
.and_then(|e| e.as_i64().ok());
@ -780,23 +748,21 @@ pub fn get_command_finished_marker(stack: &Stack, engine_state: &EngineState) ->
}
fn run_ansi_sequence(seq: &str) -> Result<(), ShellError> {
io::stdout().write_all(seq.as_bytes()).map_err(|e| {
ShellError::GenericError(
"Error writing ansi sequence".into(),
e.to_string(),
Some(Span::unknown()),
None,
Vec::new(),
)
})?;
io::stdout().flush().map_err(|e| {
ShellError::GenericError(
"Error flushing stdio".into(),
e.to_string(),
Some(Span::unknown()),
None,
Vec::new(),
)
io::stdout()
.write_all(seq.as_bytes())
.map_err(|e| ShellError::GenericError {
error: "Error writing ansi sequence".into(),
msg: e.to_string(),
span: Some(Span::unknown()),
help: None,
inner: vec![],
})?;
io::stdout().flush().map_err(|e| ShellError::GenericError {
error: "Error flushing stdio".into(),
msg: e.to_string(),
span: Some(Span::unknown()),
help: None,
inner: vec![],
})
}

View File

@ -2,7 +2,7 @@ use log::trace;
use nu_ansi_term::Style;
use nu_color_config::{get_matching_brackets_style, get_shape_color};
use nu_parser::{flatten_block, parse, FlatShape};
use nu_protocol::ast::{Argument, Block, Expr, Expression, PipelineElement};
use nu_protocol::ast::{Argument, Block, Expr, Expression, PipelineElement, RecordItem};
use nu_protocol::engine::{EngineState, StateWorkingSet};
use nu_protocol::{Config, Span};
use reedline::{Highlighter, StyledText};
@ -17,10 +17,27 @@ impl Highlighter for NuHighlighter {
fn highlight(&self, line: &str, _cursor: usize) -> StyledText {
trace!("highlighting: {}", line);
let highlight_resolved_externals =
self.engine_state.get_config().highlight_resolved_externals;
let mut working_set = StateWorkingSet::new(&self.engine_state);
let block = parse(&mut working_set, None, line.as_bytes(), false);
let (shapes, global_span_offset) = {
let shapes = flatten_block(&working_set, &block);
let mut shapes = flatten_block(&working_set, &block);
// Highlighting externals has a config point because of concerns that using which to resolve
// externals may slow down things too much.
if highlight_resolved_externals {
for (span, shape) in shapes.iter_mut() {
if *shape == FlatShape::External {
let str_contents =
working_set.get_span_contents(Span::new(span.start, span.end));
let str_word = String::from_utf8_lossy(str_contents).to_string();
if which::which(str_word).ok().is_some() {
*shape = FlatShape::ExternalResolved;
}
}
}
}
(shapes, self.engine_state.next_span_start())
};
@ -91,6 +108,7 @@ impl Highlighter for NuHighlighter {
FlatShape::InternalCall(_) => add_colored_token(&shape.1, next_token),
FlatShape::External => add_colored_token(&shape.1, next_token),
FlatShape::ExternalArg => add_colored_token(&shape.1, next_token),
FlatShape::ExternalResolved => add_colored_token(&shape.1, next_token),
FlatShape::Keyword => add_colored_token(&shape.1, next_token),
FlatShape::Literal => add_colored_token(&shape.1, next_token),
FlatShape::Operator => add_colored_token(&shape.1, next_token),
@ -234,11 +252,11 @@ fn find_matching_block_end_in_block(
for e in &p.elements {
match e {
PipelineElement::Expression(_, e)
| PipelineElement::Redirection(_, _, e)
| PipelineElement::Redirection(_, _, e, _)
| PipelineElement::And(_, e)
| PipelineElement::Or(_, e)
| PipelineElement::SameTargetRedirection { cmd: (_, e), .. }
| PipelineElement::SeparateRedirection { out: (_, e), .. } => {
| PipelineElement::SeparateRedirection { out: (_, e, _), .. } => {
if e.span.contains(global_cursor_offset) {
if let Some(pos) = find_matching_block_end_in_expr(
line,
@ -311,10 +329,10 @@ fn find_matching_block_end_in_expr(
Expr::ImportPattern(_) => None,
Expr::Overlay(_) => None,
Expr::Signature(_) => None,
Expr::MatchPattern(_) => None,
Expr::MatchBlock(_) => None,
Expr::Nothing => None,
Expr::Garbage => None,
Expr::Spread(_) => None,
Expr::Table(hdr, rows) => {
if expr_last == global_cursor_offset {
@ -346,9 +364,16 @@ fn find_matching_block_end_in_expr(
Some(expr_last)
} else {
// cursor is inside record
for (k, v) in exprs {
find_in_expr_or_continue!(k);
find_in_expr_or_continue!(v);
for expr in exprs {
match expr {
RecordItem::Pair(k, v) => {
find_in_expr_or_continue!(k);
find_in_expr_or_continue!(v);
}
RecordItem::Spread(_, record) => {
find_in_expr_or_continue!(record);
}
}
}
None
}
@ -360,6 +385,7 @@ fn find_matching_block_end_in_expr(
Argument::Named((_, _, opt_expr)) => opt_expr.as_ref(),
Argument::Positional(inner_expr) => Some(inner_expr),
Argument::Unknown(inner_expr) => Some(inner_expr),
Argument::Spread(inner_expr) => Some(inner_expr),
};
if let Some(inner_expr) = opt_expr {

View File

@ -43,13 +43,13 @@ fn gather_env_vars(
let working_set = StateWorkingSet::new(engine_state);
report_error(
&working_set,
&ShellError::GenericError(
format!("Environment variable was not captured: {env_str}"),
"".to_string(),
None,
Some(msg.into()),
Vec::new(),
),
&ShellError::GenericError {
error: format!("Environment variable was not captured: {env_str}"),
msg: "".into(),
span: None,
help: Some(msg.into()),
inner: vec![],
},
);
}
@ -75,15 +75,15 @@ fn gather_env_vars(
let working_set = StateWorkingSet::new(engine_state);
report_error(
&working_set,
&ShellError::GenericError(
"Current directory is not a valid utf-8 path".to_string(),
"".to_string(),
None,
Some(format!(
&ShellError::GenericError {
error: "Current directory is not a valid utf-8 path".into(),
msg: "".into(),
span: None,
help: Some(format!(
"Retrieving current directory failed: {init_cwd:?} not a valid utf-8 path"
)),
Vec::new(),
),
inner: vec![],
},
);
}
}
@ -111,7 +111,7 @@ fn gather_env_vars(
let name = if let Some(Token {
contents: TokenContents::Item,
span,
}) = parts.get(0)
}) = parts.first()
{
let mut working_set = StateWorkingSet::new(engine_state);
let bytes = working_set.get_span_contents(*span);
@ -220,6 +220,10 @@ pub fn eval_source(
source,
false,
);
if let Some(warning) = working_set.parse_warnings.first() {
report_error(&working_set, warning);
}
if let Some(err) = working_set.parse_errors.first() {
set_last_exit_code(stack, 1);
report_error(&working_set, err);

View File

@ -59,6 +59,29 @@ fn extern_completer() -> NuCompleter {
NuCompleter::new(std::sync::Arc::new(engine), stack)
}
#[fixture]
fn custom_completer() -> NuCompleter {
// Create a new engine
let (dir, _, mut engine, mut stack) = new_engine();
// Add record value as example
let record = r#"
let external_completer = {|spans|
$spans
}
$env.config.completions.external = {
enable: true
max_results: 100
completer: $external_completer
}
"#;
assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack, dir).is_ok());
// Instantiate a new completer
NuCompleter::new(std::sync::Arc::new(engine), stack)
}
#[test]
fn variables_dollar_sign_with_varialblecompletion() {
let (_, _, engine, stack) = new_engine();
@ -68,7 +91,7 @@ fn variables_dollar_sign_with_varialblecompletion() {
let target_dir = "$ ";
let suggestions = completer.complete(target_dir, target_dir.len());
assert_eq!(7, suggestions.len());
assert_eq!(8, suggestions.len());
}
#[rstest]
@ -121,15 +144,34 @@ fn dotnu_completions() {
let completion_str = "source-env ".to_string();
let suggestions = completer.complete(&completion_str, completion_str.len());
assert_eq!(1, suggestions.len());
assert_eq!("custom_completion.nu", suggestions.get(0).unwrap().value);
assert_eq!(2, suggestions.len());
assert_eq!("custom_completion.nu", suggestions.first().unwrap().value);
#[cfg(windows)]
assert_eq!("directory_completion\\", suggestions.get(1).unwrap().value);
#[cfg(not(windows))]
assert_eq!("directory_completion/", suggestions.get(1).unwrap().value);
// Test use completion
let completion_str = "use ".to_string();
let suggestions = completer.complete(&completion_str, completion_str.len());
assert_eq!(1, suggestions.len());
assert_eq!("custom_completion.nu", suggestions.get(0).unwrap().value);
assert_eq!(2, suggestions.len());
assert_eq!("custom_completion.nu", suggestions.first().unwrap().value);
#[cfg(windows)]
assert_eq!("directory_completion\\", suggestions.get(1).unwrap().value);
#[cfg(not(windows))]
assert_eq!("directory_completion/", suggestions.get(1).unwrap().value);
// Test overlay use completion
let completion_str = "overlay use ".to_string();
let suggestions = completer.complete(&completion_str, completion_str.len());
assert_eq!(2, suggestions.len());
assert_eq!("custom_completion.nu", suggestions.first().unwrap().value);
#[cfg(windows)]
assert_eq!("directory_completion\\", suggestions.get(1).unwrap().value);
#[cfg(not(windows))]
assert_eq!("directory_completion/", suggestions.get(1).unwrap().value);
}
#[test]
@ -141,7 +183,7 @@ fn external_completer_trailing_space() {
let suggestions = run_external_completion(block, &input);
assert_eq!(3, suggestions.len());
assert_eq!("gh", suggestions.get(0).unwrap().value);
assert_eq!("gh", suggestions.first().unwrap().value);
assert_eq!("alias", suggestions.get(1).unwrap().value);
assert_eq!("", suggestions.get(2).unwrap().value);
}
@ -153,7 +195,7 @@ fn external_completer_no_trailing_space() {
let suggestions = run_external_completion(block, &input);
assert_eq!(2, suggestions.len());
assert_eq!("gh", suggestions.get(0).unwrap().value);
assert_eq!("gh", suggestions.first().unwrap().value);
assert_eq!("alias", suggestions.get(1).unwrap().value);
}
@ -164,7 +206,7 @@ fn external_completer_pass_flags() {
let suggestions = run_external_completion(block, &input);
assert_eq!(3, suggestions.len());
assert_eq!("gh", suggestions.get(0).unwrap().value);
assert_eq!("gh", suggestions.first().unwrap().value);
assert_eq!("api", suggestions.get(1).unwrap().value);
assert_eq!("--", suggestions.get(2).unwrap().value);
}
@ -185,6 +227,7 @@ fn file_completions() {
let expected_paths: Vec<String> = vec![
folder(dir.join("another")),
file(dir.join("custom_completion.nu")),
folder(dir.join("directory_completion")),
file(dir.join("nushell")),
folder(dir.join("test_a")),
folder(dir.join("test_b")),
@ -300,6 +343,7 @@ fn command_ls_with_filecompletion() {
let expected_paths: Vec<String> = vec![
"another\\".to_string(),
"custom_completion.nu".to_string(),
"directory_completion\\".to_string(),
"nushell".to_string(),
"test_a\\".to_string(),
"test_b\\".to_string(),
@ -310,6 +354,7 @@ fn command_ls_with_filecompletion() {
let expected_paths: Vec<String> = vec![
"another/".to_string(),
"custom_completion.nu".to_string(),
"directory_completion/".to_string(),
"nushell".to_string(),
"test_a/".to_string(),
"test_b/".to_string(),
@ -332,6 +377,7 @@ fn command_open_with_filecompletion() {
let expected_paths: Vec<String> = vec![
"another\\".to_string(),
"custom_completion.nu".to_string(),
"directory_completion\\".to_string(),
"nushell".to_string(),
"test_a\\".to_string(),
"test_b\\".to_string(),
@ -342,6 +388,7 @@ fn command_open_with_filecompletion() {
let expected_paths: Vec<String> = vec![
"another/".to_string(),
"custom_completion.nu".to_string(),
"directory_completion/".to_string(),
"nushell".to_string(),
"test_a/".to_string(),
"test_b/".to_string(),
@ -365,6 +412,7 @@ fn command_rm_with_globcompletion() {
let expected_paths: Vec<String> = vec![
"another\\".to_string(),
"custom_completion.nu".to_string(),
"directory_completion\\".to_string(),
"nushell".to_string(),
"test_a\\".to_string(),
"test_b\\".to_string(),
@ -375,6 +423,7 @@ fn command_rm_with_globcompletion() {
let expected_paths: Vec<String> = vec![
"another/".to_string(),
"custom_completion.nu".to_string(),
"directory_completion/".to_string(),
"nushell".to_string(),
"test_a/".to_string(),
"test_b/".to_string(),
@ -398,6 +447,7 @@ fn command_cp_with_globcompletion() {
let expected_paths: Vec<String> = vec![
"another\\".to_string(),
"custom_completion.nu".to_string(),
"directory_completion\\".to_string(),
"nushell".to_string(),
"test_a\\".to_string(),
"test_b\\".to_string(),
@ -408,6 +458,7 @@ fn command_cp_with_globcompletion() {
let expected_paths: Vec<String> = vec![
"another/".to_string(),
"custom_completion.nu".to_string(),
"directory_completion/".to_string(),
"nushell".to_string(),
"test_a/".to_string(),
"test_b/".to_string(),
@ -431,6 +482,7 @@ fn command_save_with_filecompletion() {
let expected_paths: Vec<String> = vec![
"another\\".to_string(),
"custom_completion.nu".to_string(),
"directory_completion\\".to_string(),
"nushell".to_string(),
"test_a\\".to_string(),
"test_b\\".to_string(),
@ -441,6 +493,7 @@ fn command_save_with_filecompletion() {
let expected_paths: Vec<String> = vec![
"another/".to_string(),
"custom_completion.nu".to_string(),
"directory_completion/".to_string(),
"nushell".to_string(),
"test_a/".to_string(),
"test_b/".to_string(),
@ -464,6 +517,7 @@ fn command_touch_with_filecompletion() {
let expected_paths: Vec<String> = vec![
"another\\".to_string(),
"custom_completion.nu".to_string(),
"directory_completion\\".to_string(),
"nushell".to_string(),
"test_a\\".to_string(),
"test_b\\".to_string(),
@ -474,6 +528,7 @@ fn command_touch_with_filecompletion() {
let expected_paths: Vec<String> = vec![
"another/".to_string(),
"custom_completion.nu".to_string(),
"directory_completion/".to_string(),
"nushell".to_string(),
"test_a/".to_string(),
"test_b/".to_string(),
@ -497,6 +552,7 @@ fn command_watch_with_filecompletion() {
let expected_paths: Vec<String> = vec![
"another\\".to_string(),
"custom_completion.nu".to_string(),
"directory_completion\\".to_string(),
"nushell".to_string(),
"test_a\\".to_string(),
"test_b\\".to_string(),
@ -507,6 +563,7 @@ fn command_watch_with_filecompletion() {
let expected_paths: Vec<String> = vec![
"another/".to_string(),
"custom_completion.nu".to_string(),
"directory_completion/".to_string(),
"nushell".to_string(),
"test_a/".to_string(),
"test_b/".to_string(),
@ -527,6 +584,10 @@ fn file_completion_quoted() {
let suggestions = completer.complete(target_dir, target_dir.len());
let expected_paths: Vec<String> = vec![
"`--help`".to_string(),
"`-42`".to_string(),
"`-inf`".to_string(),
"`4.2`".to_string(),
"`te st.txt`".to_string(),
"`te#st.txt`".to_string(),
"`te'st.txt`".to_string(),
@ -598,6 +659,7 @@ fn folder_with_directorycompletions() {
// Create the expected values
let expected_paths: Vec<String> = vec![
folder(dir.join("another")),
folder(dir.join("directory_completion")),
folder(dir.join("test_a")),
folder(dir.join("test_b")),
folder(dir.join(".hidden_folder")),
@ -791,7 +853,7 @@ fn run_external_completion(block: &str, input: &str) -> Vec<Suggestion> {
// Change config adding the external completer
let mut config = engine_state.get_config().clone();
config.external_completer = Some(latest_block_id);
engine_state.set_config(&config);
engine_state.set_config(config);
// Instantiate a new completer
let mut completer = NuCompleter::new(std::sync::Arc::new(engine_state), stack);
@ -812,6 +874,7 @@ fn unknown_command_completion() {
let expected_paths: Vec<String> = vec![
"another\\".to_string(),
"custom_completion.nu".to_string(),
"directory_completion\\".to_string(),
"nushell".to_string(),
"test_a\\".to_string(),
"test_b\\".to_string(),
@ -822,6 +885,7 @@ fn unknown_command_completion() {
let expected_paths: Vec<String> = vec![
"another/".to_string(),
"custom_completion.nu".to_string(),
"directory_completion/".to_string(),
"nushell".to_string(),
"test_a/".to_string(),
"test_b/".to_string(),
@ -872,6 +936,7 @@ fn filecompletions_triggers_after_cursor() {
let expected_paths: Vec<String> = vec![
"another\\".to_string(),
"custom_completion.nu".to_string(),
"directory_completion\\".to_string(),
"nushell".to_string(),
"test_a\\".to_string(),
"test_b\\".to_string(),
@ -882,6 +947,7 @@ fn filecompletions_triggers_after_cursor() {
let expected_paths: Vec<String> = vec![
"another/".to_string(),
"custom_completion.nu".to_string(),
"directory_completion/".to_string(),
"nushell".to_string(),
"test_a/".to_string(),
"test_b/".to_string(),
@ -934,6 +1000,34 @@ fn extern_complete_flags(mut extern_completer: NuCompleter) {
match_suggestions(expected, suggestions);
}
#[rstest]
fn custom_completer_triggers_cursor_before_word(mut custom_completer: NuCompleter) {
let suggestions = custom_completer.complete("cmd foo bar", 8);
let expected: Vec<String> = vec!["cmd".into(), "foo".into(), "".into()];
match_suggestions(expected, suggestions);
}
#[rstest]
fn custom_completer_triggers_cursor_on_word_left_boundary(mut custom_completer: NuCompleter) {
let suggestions = custom_completer.complete("cmd foo bar", 8);
let expected: Vec<String> = vec!["cmd".into(), "foo".into(), "".into()];
match_suggestions(expected, suggestions);
}
#[rstest]
fn custom_completer_triggers_cursor_next_to_word(mut custom_completer: NuCompleter) {
let suggestions = custom_completer.complete("cmd foo bar", 11);
let expected: Vec<String> = vec!["cmd".into(), "foo".into(), "bar".into()];
match_suggestions(expected, suggestions);
}
#[rstest]
fn custom_completer_triggers_cursor_after_word(mut custom_completer: NuCompleter) {
let suggestions = custom_completer.complete("cmd foo bar ", 12);
let expected: Vec<String> = vec!["cmd".into(), "foo".into(), "bar".into(), "".into()];
match_suggestions(expected, suggestions);
}
#[ignore = "was reverted, still needs fixing"]
#[rstest]
fn alias_offset_bug_7648() {

View File

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

View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 - 2023 The Nushell Project Developers
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,205 @@
// utilities for expanding globs in command arguments
use nu_glob::{glob_with_parent, MatchOptions, Paths};
use nu_protocol::{ShellError, Spanned};
use std::fs;
use std::path::{Path, PathBuf};
// standard glob options to use for filesystem command arguments
const GLOB_PARAMS: MatchOptions = MatchOptions {
case_sensitive: true,
require_literal_separator: false,
require_literal_leading_dot: false,
recursive_match_hidden_dir: true,
};
// handle an argument that could be a literal path or a glob.
// if literal path, return just that (whether user can access it or not).
// if glob, expand into matching paths, using GLOB_PARAMS options.
pub fn arg_glob(
pattern: &Spanned<String>, // alleged path or glob
cwd: &Path, // current working directory
) -> Result<Paths, ShellError> {
arg_glob_opt(pattern, cwd, GLOB_PARAMS)
}
// variant of [arg_glob] that requires literal dot prefix in pattern to match dot-prefixed path.
pub fn arg_glob_leading_dot(pattern: &Spanned<String>, cwd: &Path) -> Result<Paths, ShellError> {
arg_glob_opt(
pattern,
cwd,
MatchOptions {
require_literal_leading_dot: true,
..GLOB_PARAMS
},
)
}
fn arg_glob_opt(
pattern: &Spanned<String>,
cwd: &Path,
options: MatchOptions,
) -> Result<Paths, ShellError> {
// remove ansi coloring (?)
let pattern = {
Spanned {
item: nu_utils::strip_ansi_string_unlikely(pattern.item.clone()),
span: pattern.span,
}
};
// if there's a file with same path as the pattern, just return that.
let pp = cwd.join(&pattern.item);
let md = fs::metadata(pp);
#[allow(clippy::single_match)]
match md {
Ok(_metadata) => {
return Ok(Paths::single(&PathBuf::from(pattern.item), cwd));
}
// file not found, but also "invalid chars in file" (e.g * on Windows). Fall through and glob
Err(_) => {}
}
// user wasn't referring to a specific thing in filesystem, try to glob it.
match glob_with_parent(&pattern.item, options, cwd) {
Ok(p) => Ok(p),
Err(pat_err) => Err(ShellError::InvalidGlobPattern {
msg: pat_err.msg.into(),
span: pattern.span,
}),
}
}
#[cfg(test)]
mod test {
use super::*;
use nu_glob::GlobResult;
use nu_protocol::{Span, Spanned};
use nu_test_support::fs::Stub::EmptyFile;
use nu_test_support::playground::Playground;
use rstest::rstest;
fn spanned_string(str: &str) -> Spanned<String> {
Spanned {
item: str.to_string(),
span: Span::test_data(),
}
}
#[test]
fn does_something() {
let act = arg_glob(&spanned_string("*"), &PathBuf::from("."));
assert!(act.is_ok());
for f in act.expect("checked ok") {
match f {
Ok(p) => {
assert!(!p.to_str().unwrap().is_empty());
}
Err(e) => panic!("unexpected error {:?}", e),
};
}
}
#[test]
fn glob_format_error() {
let act = arg_glob(&spanned_string(r#"ab]c[def"#), &PathBuf::from("."));
assert!(act.is_err());
}
#[rstest]
#[case("*", 4, "no dirs")]
#[case("**/*", 7, "incl dirs")]
fn glob_subdirs(#[case] pat: &str, #[case] exp_count: usize, #[case] case: &str) {
Playground::setup("glob_subdirs", |dirs, sandbox| {
sandbox.with_files(vec![
EmptyFile("yehuda.txt"),
EmptyFile("jttxt"),
EmptyFile("andres.txt"),
]);
sandbox.mkdir(".children");
sandbox.within(".children").with_files(vec![
EmptyFile("timothy.txt"),
EmptyFile("tiffany.txt"),
EmptyFile("trish.txt"),
]);
let p: Vec<GlobResult> = arg_glob(&spanned_string(pat), &dirs.test)
.expect("no error")
.collect();
assert_eq!(
exp_count,
p.iter().filter(|i| i.is_ok()).count(),
" case: {case} ",
);
// expected behavior -- that directories are included in results (if name matches pattern)
let t = p
.iter()
.any(|i| i.as_ref().unwrap().to_string_lossy().contains(".children"));
assert!(t, "check for dir, case {case}");
})
}
#[rstest]
#[case("yehuda.txt", true, 1, "matches literal path")]
#[case("*", false, 3, "matches glob")]
#[case(r#"bad[glob.foo"#, true, 1, "matches literal, would be bad glob pat")]
fn exact_vs_glob(
#[case] pat: &str,
#[case] exp_matches_input: bool,
#[case] exp_count: usize,
#[case] case: &str,
) {
Playground::setup("exact_vs_glob", |dirs, sandbox| {
sandbox.with_files(vec![
EmptyFile("yehuda.txt"),
EmptyFile("jttxt"),
EmptyFile("bad[glob.foo"),
]);
let res = arg_glob(&spanned_string(pat), &dirs.test)
.expect("no error")
.collect::<Vec<GlobResult>>();
eprintln!("res: {:?}", res);
if exp_matches_input {
assert_eq!(
exp_count,
res.len(),
" case {case}: matches input, but count not 1? "
);
assert_eq!(
&res[0].as_ref().unwrap().to_string_lossy(),
pat, // todo: is it OK for glob to return relative paths (not to current cwd, but to arg cwd of arg_glob)?
);
} else {
assert_eq!(exp_count, res.len(), " case: {}: matched glob", case);
}
})
}
#[rstest]
#[case(r#"realbad[glob.foo"#, true, 1, "error, bad glob")]
fn exact_vs_bad_glob(
// if path doesn't exist but pattern is not valid glob, should get error.
#[case] pat: &str,
#[case] _exp_matches_input: bool,
#[case] _exp_count: usize,
#[case] _tag: &str,
) {
Playground::setup("exact_vs_bad_glob", |dirs, sandbox| {
sandbox.with_files(vec![
EmptyFile("yehuda.txt"),
EmptyFile("jttxt"),
EmptyFile("bad[glob.foo"),
]);
let res = arg_glob(&spanned_string(pat), &dirs.test);
assert!(res
.expect_err("expected error")
.to_string()
.contains("Invalid glob pattern"));
})
}
}

View File

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

View File

@ -2,7 +2,6 @@ use crate::util::get_guaranteed_cwd;
use miette::Result;
use nu_engine::{eval_block, eval_block_with_early_return};
use nu_parser::parse;
use nu_protocol::ast::PathMember;
use nu_protocol::cli_error::{report_error, report_error_new};
use nu_protocol::engine::{EngineState, Stack, StateWorkingSet};
use nu_protocol::{BlockId, PipelineData, PositionalArg, ShellError, Span, Type, Value, VarId};
@ -62,28 +61,8 @@ pub fn eval_hook(
value: &Value,
hook_name: &str,
) -> Result<PipelineData, ShellError> {
let value_span = value.span();
// Hooks can optionally be a record in this form:
// {
// condition: {|before, after| ... } # block that evaluates to true/false
// code: # block or a string
// }
// The condition block will be run to check whether the main hook (in `code`) should be run.
// If it returns true (the default if a condition block is not specified), the hook should be run.
let condition_path = PathMember::String {
val: "condition".to_string(),
span: value_span,
optional: false,
};
let mut output = PipelineData::empty();
let code_path = PathMember::String {
val: "code".to_string(),
span: value_span,
optional: false,
};
let span = value.span();
match value {
Value::String { val, .. } => {
@ -111,11 +90,11 @@ pub fn eval_hook(
if let Some(err) = working_set.parse_errors.first() {
report_error(&working_set, err);
return Err(ShellError::UnsupportedConfigValue(
"valid source code".into(),
"source code with syntax errors".into(),
return Err(ShellError::UnsupportedConfigValue {
expected: "valid source code".into(),
value: "source code with syntax errors".into(),
span,
));
});
}
(output, working_set.render(), vars)
@ -161,46 +140,47 @@ pub fn eval_hook(
)?;
}
}
Value::Record { .. } => {
let do_run_hook = if let Ok(condition) =
value.clone().follow_cell_path(&[condition_path], false)
{
Value::Record { val, .. } => {
// Hooks can optionally be a record in this form:
// {
// condition: {|before, after| ... } # block that evaluates to true/false
// code: # block or a string
// }
// The condition block will be run to check whether the main hook (in `code`) should be run.
// If it returns true (the default if a condition block is not specified), the hook should be run.
let do_run_hook = if let Some(condition) = val.get("condition") {
let other_span = condition.span();
match condition {
Value::Block { val: block_id, .. } | Value::Closure { val: block_id, .. } => {
match run_hook_block(
engine_state,
stack,
block_id,
None,
arguments.clone(),
other_span,
) {
Ok(pipeline_data) => {
if let PipelineData::Value(Value::Bool { val, .. }, ..) =
pipeline_data
{
val
} else {
return Err(ShellError::UnsupportedConfigValue(
"boolean output".to_string(),
"other PipelineData variant".to_string(),
other_span,
));
}
}
Err(err) => {
return Err(err);
if let Ok(block_id) = condition.as_block() {
match run_hook_block(
engine_state,
stack,
block_id,
None,
arguments.clone(),
other_span,
) {
Ok(pipeline_data) => {
if let PipelineData::Value(Value::Bool { val, .. }, ..) = pipeline_data
{
val
} else {
return Err(ShellError::UnsupportedConfigValue {
expected: "boolean output".to_string(),
value: "other PipelineData variant".to_string(),
span: other_span,
});
}
}
Err(err) => {
return Err(err);
}
}
other => {
return Err(ShellError::UnsupportedConfigValue(
"block".to_string(),
format!("{}", other.get_type()),
other_span,
));
}
} else {
return Err(ShellError::UnsupportedConfigValue {
expected: "block".to_string(),
value: format!("{}", condition.get_type()),
span: other_span,
});
}
} else {
// always run the hook
@ -208,7 +188,13 @@ pub fn eval_hook(
};
if do_run_hook {
let follow = value.clone().follow_cell_path(&[code_path], false)?;
let Some(follow) = val.get("code") else {
return Err(ShellError::CantFindColumn {
col_name: "code".into(),
span,
src_span: span,
});
};
let source_span = follow.span();
match follow {
Value::String { val, .. } => {
@ -236,11 +222,11 @@ pub fn eval_hook(
if let Some(err) = working_set.parse_errors.first() {
report_error(&working_set, err);
return Err(ShellError::UnsupportedConfigValue(
"valid source code".into(),
"source code with syntax errors".into(),
source_span,
));
return Err(ShellError::UnsupportedConfigValue {
expected: "valid source code".into(),
value: "source code with syntax errors".into(),
span: source_span,
});
}
(output, working_set.render(), vars)
@ -274,28 +260,28 @@ pub fn eval_hook(
run_hook_block(
engine_state,
stack,
block_id,
*block_id,
input,
arguments,
source_span,
)?;
}
Value::Closure { val: block_id, .. } => {
Value::Closure { val, .. } => {
run_hook_block(
engine_state,
stack,
block_id,
val.block_id,
input,
arguments,
source_span,
)?;
}
other => {
return Err(ShellError::UnsupportedConfigValue(
"block or string".to_string(),
format!("{}", other.get_type()),
source_span,
));
return Err(ShellError::UnsupportedConfigValue {
expected: "block or string".to_string(),
value: format!("{}", other.get_type()),
span: source_span,
});
}
}
}
@ -303,15 +289,15 @@ pub fn eval_hook(
Value::Block { val: block_id, .. } => {
output = run_hook_block(engine_state, stack, *block_id, input, arguments, span)?;
}
Value::Closure { val: block_id, .. } => {
output = run_hook_block(engine_state, stack, *block_id, input, arguments, span)?;
Value::Closure { val, .. } => {
output = run_hook_block(engine_state, stack, val.block_id, input, arguments, span)?;
}
other => {
return Err(ShellError::UnsupportedConfigValue(
"string, block, record, or list of commands".into(),
format!("{}", other.get_type()),
other.span(),
));
return Err(ShellError::UnsupportedConfigValue {
expected: "string, block, record, or list of commands".into(),
value: format!("{}", other.get_type()),
span: other.span(),
});
}
}

View File

@ -1,4 +1,7 @@
mod arg_glob;
pub mod formats;
pub mod hook;
pub mod input_handler;
pub mod util;
pub use arg_glob::arg_glob;
pub use arg_glob::arg_glob_leading_dot;

View File

@ -72,22 +72,22 @@ fn get_editor_commandline(
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![],
)),
_ => Err(ShellError::GenericError {
error: "Editor executable is missing".into(),
msg: "Set the first element to an executable".into(),
span: Some(value.span()),
help: Some(HELP_MSG.into()),
inner: 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![],
)),
Value::String { .. } | Value::List { .. } => Err(ShellError::GenericError {
error: format!("{var_name} should be a non-empty string or list<String>"),
msg: "Specify an executable here".into(),
span: Some(value.span()),
help: Some(HELP_MSG.into()),
inner: vec![],
}),
x => Err(ShellError::CantConvert {
to_type: "string or list<string>".into(),
from_type: x.get_type().to_string(),
@ -114,13 +114,14 @@ pub fn get_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![],
))
Err(ShellError::GenericError {
error: "No editor configured".into(),
msg:
"Please specify one via `$env.config.buffer_editor` or `$env.EDITOR`/`$env.VISUAL`"
.into(),
span: Some(span),
help: Some(HELP_MSG.into()),
inner: vec![],
})
}
}

View File

@ -5,7 +5,7 @@ edition = "2021"
license = "MIT"
name = "nu-cmd-dataframe"
repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cmd-dataframe"
version = "0.86.0"
version = "0.88.2"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -13,18 +13,22 @@ version = "0.86.0"
bench = false
[dependencies]
nu-engine = { path = "../nu-engine", version = "0.86.0" }
nu-parser = { path = "../nu-parser", version = "0.86.0" }
nu-protocol = { path = "../nu-protocol", version = "0.86.0" }
nu-engine = { path = "../nu-engine", version = "0.88.2" }
nu-parser = { path = "../nu-parser", version = "0.88.2" }
nu-protocol = { path = "../nu-protocol", version = "0.88.2" }
# Potential dependencies for extras
chrono = { version = "0.4", features = ["std", "unstable-locales"], default-features = false }
fancy-regex = "0.11"
indexmap = { version = "2.0" }
chrono-tz = "0.8"
fancy-regex = "0.12"
indexmap = { version = "2.1" }
num = { version = "0.4", optional = true }
serde = { version = "1.0", features = ["derive"] }
sqlparser = { version = "0.36.1", optional = true }
polars-io = { version = "0.33", features = ["avro"], optional = true }
sqlparser = { version = "0.39", optional = true }
polars-io = { version = "0.35", features = ["avro"], optional = true }
polars-arrow = { version = "0.35", optional = true }
polars-ops = { version = "0.35", optional = true }
polars-plan = { version = "0.35", optional = true }
[dependencies.polars]
features = [
@ -38,6 +42,10 @@ features = [
"dtype-categorical",
"dtype-datetime",
"dtype-struct",
"dtype-i8",
"dtype-i16",
"dtype-u8",
"dtype-u16",
"dynamic_group_by",
"ipc",
"is_in",
@ -54,12 +62,12 @@ features = [
"to_dummies",
]
optional = true
version = "0.33"
version = "0.35"
[features]
dataframe = ["num", "polars", "polars-io", "sqlparser"]
dataframe = ["num", "polars", "polars-io", "polars-arrow", "polars-ops", "polars-plan", "sqlparser"]
default = []
[dev-dependencies]
nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.86.0" }
nu-test-support = { path = "../nu-test-support", version = "0.86.0" }
nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.88.2" }
nu-test-support = { path = "../nu-test-support", version = "0.88.2" }

View File

@ -68,26 +68,24 @@ fn command(
let df = NuDataFrame::try_from_pipeline(input, call.head)?;
let new_df = col_string
.get(0)
.ok_or_else(|| {
ShellError::GenericError(
"Empty names list".into(),
"No column names were found".into(),
Some(col_span),
None,
Vec::new(),
)
.first()
.ok_or_else(|| ShellError::GenericError {
error: "Empty names list".into(),
msg: "No column names were found".into(),
span: Some(col_span),
help: None,
inner: vec![],
})
.and_then(|col| {
df.as_ref().drop(&col.item).map_err(|e| {
ShellError::GenericError(
"Error dropping column".into(),
e.to_string(),
Some(col.span),
None,
Vec::new(),
)
})
df.as_ref()
.drop(&col.item)
.map_err(|e| ShellError::GenericError {
error: "Error dropping column".into(),
msg: e.to_string(),
span: Some(col.span),
help: None,
inner: vec![],
})
})?;
// If there are more columns in the drop selection list, these
@ -96,15 +94,15 @@ fn command(
.iter()
.skip(1)
.try_fold(new_df, |new_df, col| {
new_df.drop(&col.item).map_err(|e| {
ShellError::GenericError(
"Error dropping column".into(),
e.to_string(),
Some(col.span),
None,
Vec::new(),
)
})
new_df
.drop(&col.item)
.map_err(|e| ShellError::GenericError {
error: "Error dropping column".into(),
msg: e.to_string(),
span: Some(col.span),
help: None,
inner: vec![],
})
})
.map(|df| PipelineData::Value(NuDataFrame::dataframe_into_value(df, call.head), None))
}

View File

@ -100,14 +100,12 @@ fn command(
df.as_ref()
.unique(subset_slice, keep_strategy, None)
.map_err(|e| {
ShellError::GenericError(
"Error dropping duplicates".into(),
e.to_string(),
Some(col_span),
None,
Vec::new(),
)
.map_err(|e| ShellError::GenericError {
error: "Error dropping duplicates".into(),
msg: e.to_string(),
span: Some(col_span),
help: None,
inner: vec![],
})
.map(|df| PipelineData::Value(NuDataFrame::dataframe_into_value(df, call.head), None))
}

View File

@ -115,14 +115,12 @@ fn command(
df.as_ref()
.drop_nulls(subset_slice)
.map_err(|e| {
ShellError::GenericError(
"Error dropping nulls".into(),
e.to_string(),
Some(col_span),
None,
Vec::new(),
)
.map_err(|e| ShellError::GenericError {
error: "Error dropping nulls".into(),
msg: e.to_string(),
span: Some(col_span),
help: None,
inner: vec![],
})
.map(|df| PipelineData::Value(NuDataFrame::dataframe_into_value(df, call.head), None))
}

View File

@ -1,10 +1,10 @@
use super::super::values::{Column, NuDataFrame};
use super::super::values::NuDataFrame;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, Type, Value,
Category, Example, PipelineData, ShellError, Signature, Span, Type,
};
use polars::prelude::DataFrameOps;
use polars::{prelude::*, series::Series};
#[derive(Clone)]
pub struct Dummies;
@ -34,24 +34,15 @@ impl Command for Dummies {
description: "Create new dataframe with dummy variables from a dataframe",
example: "[[a b]; [1 2] [3 4]] | dfr into-df | dfr dummies",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new(
"a_1".to_string(),
vec![Value::test_int(1), Value::test_int(0)],
),
Column::new(
"a_3".to_string(),
vec![Value::test_int(0), Value::test_int(1)],
),
Column::new(
"b_2".to_string(),
vec![Value::test_int(1), Value::test_int(0)],
),
Column::new(
"b_4".to_string(),
vec![Value::test_int(0), Value::test_int(1)],
),
])
NuDataFrame::try_from_series(
vec![
Series::new("a_1", &[1_u8, 0]),
Series::new("a_3", &[0_u8, 1]),
Series::new("b_2", &[1_u8, 0]),
Series::new("b_4", &[0_u8, 1]),
],
Span::test_data(),
)
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
@ -60,38 +51,14 @@ impl Command for Dummies {
description: "Create new dataframe with dummy variables from a series",
example: "[1 2 2 3 3] | dfr into-df | dfr dummies",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new(
"0_1".to_string(),
vec![
Value::test_int(1),
Value::test_int(0),
Value::test_int(0),
Value::test_int(0),
Value::test_int(0),
],
),
Column::new(
"0_2".to_string(),
vec![
Value::test_int(0),
Value::test_int(1),
Value::test_int(1),
Value::test_int(0),
Value::test_int(0),
],
),
Column::new(
"0_3".to_string(),
vec![
Value::test_int(0),
Value::test_int(0),
Value::test_int(0),
Value::test_int(1),
Value::test_int(1),
],
),
])
NuDataFrame::try_from_series(
vec![
Series::new("0_1", &[1_u8, 0, 0, 0, 0]),
Series::new("0_2", &[0_u8, 1, 1, 0, 0]),
Series::new("0_3", &[0_u8, 0, 0, 1, 1]),
],
Span::test_data(),
)
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
@ -121,14 +88,12 @@ fn command(
df.as_ref()
.to_dummies(None, drop_first)
.map_err(|e| {
ShellError::GenericError(
"Error calculating dummies".into(),
e.to_string(),
Some(call.head),
Some("The only allowed column types for dummies are String or Int".into()),
Vec::new(),
)
.map_err(|e| ShellError::GenericError {
error: "Error calculating dummies".into(),
msg: e.to_string(),
span: Some(call.head),
help: Some("The only allowed column types for dummies are String or Int".into()),
inner: vec![],
})
.map(|df| PipelineData::Value(NuDataFrame::dataframe_into_value(df, call.head), None))
}

View File

@ -105,26 +105,22 @@ fn command_eager(
))
} else {
let mask = NuDataFrame::try_from_value(mask_value)?.as_series(mask_span)?;
let mask = mask.bool().map_err(|e| {
ShellError::GenericError(
"Error casting to bool".into(),
e.to_string(),
Some(mask_span),
Some("Perhaps you want to use a series with booleans as mask".into()),
Vec::new(),
)
let mask = mask.bool().map_err(|e| ShellError::GenericError {
error: "Error casting to bool".into(),
msg: e.to_string(),
span: Some(mask_span),
help: Some("Perhaps you want to use a series with booleans as mask".into()),
inner: vec![],
})?;
df.as_ref()
.filter(mask)
.map_err(|e| {
ShellError::GenericError(
"Error filtering dataframe".into(),
e.to_string(),
Some(call.head),
Some("The only allowed column types for dummies are String or Int".into()),
Vec::new(),
)
.map_err(|e| ShellError::GenericError {
error: "Error filtering dataframe".into(),
msg: e.to_string(),
span: Some(call.head),
help: Some("The only allowed column types for dummies are String or Int".into()),
inner: vec![],
})
.map(|df| PipelineData::Value(NuDataFrame::dataframe_into_value(df, call.head), None))
}

View File

@ -70,14 +70,12 @@ fn command(
df.as_ref()
.select(col_string)
.map_err(|e| {
ShellError::GenericError(
"Error selecting columns".into(),
e.to_string(),
Some(col_span),
None,
Vec::new(),
)
.map_err(|e| ShellError::GenericError {
error: "Error selecting columns".into(),
msg: e.to_string(),
span: Some(col_span),
help: None,
inner: vec![],
})
.map(|df| PipelineData::Value(NuDataFrame::dataframe_into_value(df, call.head), None))
}

View File

@ -152,38 +152,34 @@ fn command(
let mut res = df
.as_ref()
.melt(&id_col_string, &val_col_string)
.map_err(|e| {
ShellError::GenericError(
"Error calculating melt".into(),
e.to_string(),
Some(call.head),
None,
Vec::new(),
)
.map_err(|e| ShellError::GenericError {
error: "Error calculating melt".into(),
msg: e.to_string(),
span: Some(call.head),
help: None,
inner: vec![],
})?;
if let Some(name) = &variable_name {
res.rename("variable", &name.item).map_err(|e| {
ShellError::GenericError(
"Error renaming column".into(),
e.to_string(),
Some(name.span),
None,
Vec::new(),
)
})?;
res.rename("variable", &name.item)
.map_err(|e| ShellError::GenericError {
error: "Error renaming column".into(),
msg: e.to_string(),
span: Some(name.span),
help: None,
inner: vec![],
})?;
}
if let Some(name) = &value_name {
res.rename("value", &name.item).map_err(|e| {
ShellError::GenericError(
"Error renaming column".into(),
e.to_string(),
Some(name.span),
None,
Vec::new(),
)
})?;
res.rename("value", &name.item)
.map_err(|e| ShellError::GenericError {
error: "Error renaming column".into(),
msg: e.to_string(),
span: Some(name.span),
help: None,
inner: vec![],
})?;
}
Ok(PipelineData::Value(
@ -198,50 +194,50 @@ fn check_column_datatypes<T: AsRef<str>>(
col_span: Span,
) -> Result<(), ShellError> {
if cols.is_empty() {
return Err(ShellError::GenericError(
"Merge error".into(),
"empty column list".into(),
Some(col_span),
None,
Vec::new(),
));
return Err(ShellError::GenericError {
error: "Merge error".into(),
msg: "empty column list".into(),
span: Some(col_span),
help: None,
inner: vec![],
});
}
// Checking if they are same type
if cols.len() > 1 {
for w in cols.windows(2) {
let l_series = df.column(w[0].as_ref()).map_err(|e| {
ShellError::GenericError(
"Error selecting columns".into(),
e.to_string(),
Some(col_span),
None,
Vec::new(),
)
})?;
let l_series = df
.column(w[0].as_ref())
.map_err(|e| ShellError::GenericError {
error: "Error selecting columns".into(),
msg: e.to_string(),
span: Some(col_span),
help: None,
inner: vec![],
})?;
let r_series = df.column(w[1].as_ref()).map_err(|e| {
ShellError::GenericError(
"Error selecting columns".into(),
e.to_string(),
Some(col_span),
None,
Vec::new(),
)
})?;
let r_series = df
.column(w[1].as_ref())
.map_err(|e| ShellError::GenericError {
error: "Error selecting columns".into(),
msg: e.to_string(),
span: Some(col_span),
help: None,
inner: vec![],
})?;
if l_series.dtype() != r_series.dtype() {
return Err(ShellError::GenericError(
"Merge error".into(),
"found different column types in list".into(),
Some(col_span),
Some(format!(
return Err(ShellError::GenericError {
error: "Merge error".into(),
msg: "found different column types in list".into(),
span: Some(col_span),
help: Some(format!(
"datatypes {} and {} are incompatible",
l_series.dtype(),
r_series.dtype()
)),
Vec::new(),
));
inner: vec![],
});
}
}
}

View File

@ -121,15 +121,15 @@ fn command(
"json" => from_json(engine_state, stack, call),
"jsonl" => from_jsonl(engine_state, stack, call),
"avro" => from_avro(engine_state, stack, call),
_ => Err(ShellError::FileNotFoundCustom(
format!("{msg}. Supported values: csv, tsv, parquet, ipc, arrow, json"),
blamed,
)),
_ => Err(ShellError::FileNotFoundCustom {
msg: format!("{msg}. Supported values: csv, tsv, parquet, ipc, arrow, json"),
span: blamed,
}),
},
None => Err(ShellError::FileNotFoundCustom(
"File without extension".into(),
file.span,
)),
None => Err(ShellError::FileNotFoundCustom {
msg: "File without extension".into(),
span: file.span,
}),
}
.map(|value| PipelineData::Value(value, None))
}
@ -150,17 +150,16 @@ fn from_parquet(
low_memory: false,
cloud_options: None,
use_statistics: false,
hive_partitioning: false,
};
let df: NuLazyFrame = LazyFrame::scan_parquet(file, args)
.map_err(|e| {
ShellError::GenericError(
"Parquet reader error".into(),
format!("{e:?}"),
Some(call.head),
None,
Vec::new(),
)
.map_err(|e| ShellError::GenericError {
error: "Parquet reader error".into(),
msg: format!("{e:?}"),
span: Some(call.head),
help: None,
inner: vec![],
})?
.into();
@ -169,14 +168,12 @@ fn from_parquet(
let file: Spanned<PathBuf> = call.req(engine_state, stack, 0)?;
let columns: Option<Vec<String>> = call.get_flag(engine_state, stack, "columns")?;
let r = File::open(&file.item).map_err(|e| {
ShellError::GenericError(
"Error opening file".into(),
e.to_string(),
Some(file.span),
None,
Vec::new(),
)
let r = File::open(&file.item).map_err(|e| ShellError::GenericError {
error: "Error opening file".into(),
msg: e.to_string(),
span: Some(file.span),
help: None,
inner: vec![],
})?;
let reader = ParquetReader::new(r);
@ -187,14 +184,12 @@ fn from_parquet(
let df: NuDataFrame = reader
.finish()
.map_err(|e| {
ShellError::GenericError(
"Parquet reader error".into(),
format!("{e:?}"),
Some(call.head),
None,
Vec::new(),
)
.map_err(|e| ShellError::GenericError {
error: "Parquet reader error".into(),
msg: format!("{e:?}"),
span: Some(call.head),
help: None,
inner: vec![],
})?
.into();
@ -210,14 +205,12 @@ fn from_avro(
let file: Spanned<PathBuf> = call.req(engine_state, stack, 0)?;
let columns: Option<Vec<String>> = call.get_flag(engine_state, stack, "columns")?;
let r = File::open(&file.item).map_err(|e| {
ShellError::GenericError(
"Error opening file".into(),
e.to_string(),
Some(file.span),
None,
Vec::new(),
)
let r = File::open(&file.item).map_err(|e| ShellError::GenericError {
error: "Error opening file".into(),
msg: e.to_string(),
span: Some(file.span),
help: None,
inner: vec![],
})?;
let reader = AvroReader::new(r);
@ -228,14 +221,12 @@ fn from_avro(
let df: NuDataFrame = reader
.finish()
.map_err(|e| {
ShellError::GenericError(
"Avro reader error".into(),
format!("{e:?}"),
Some(call.head),
None,
Vec::new(),
)
.map_err(|e| ShellError::GenericError {
error: "Avro reader error".into(),
msg: format!("{e:?}"),
span: Some(call.head),
help: None,
inner: vec![],
})?
.into();
@ -258,14 +249,12 @@ fn from_ipc(
};
let df: NuLazyFrame = LazyFrame::scan_ipc(file, args)
.map_err(|e| {
ShellError::GenericError(
"IPC reader error".into(),
format!("{e:?}"),
Some(call.head),
None,
Vec::new(),
)
.map_err(|e| ShellError::GenericError {
error: "IPC reader error".into(),
msg: format!("{e:?}"),
span: Some(call.head),
help: None,
inner: vec![],
})?
.into();
@ -274,14 +263,12 @@ fn from_ipc(
let file: Spanned<PathBuf> = call.req(engine_state, stack, 0)?;
let columns: Option<Vec<String>> = call.get_flag(engine_state, stack, "columns")?;
let r = File::open(&file.item).map_err(|e| {
ShellError::GenericError(
"Error opening file".into(),
e.to_string(),
Some(file.span),
None,
Vec::new(),
)
let r = File::open(&file.item).map_err(|e| ShellError::GenericError {
error: "Error opening file".into(),
msg: e.to_string(),
span: Some(file.span),
help: None,
inner: vec![],
})?;
let reader = IpcReader::new(r);
@ -292,14 +279,12 @@ fn from_ipc(
let df: NuDataFrame = reader
.finish()
.map_err(|e| {
ShellError::GenericError(
"IPC reader error".into(),
format!("{e:?}"),
Some(call.head),
None,
Vec::new(),
)
.map_err(|e| ShellError::GenericError {
error: "IPC reader error".into(),
msg: format!("{e:?}"),
span: Some(call.head),
help: None,
inner: vec![],
})?
.into();
@ -313,14 +298,12 @@ fn from_json(
call: &Call,
) -> Result<Value, ShellError> {
let file: Spanned<PathBuf> = call.req(engine_state, stack, 0)?;
let file = File::open(&file.item).map_err(|e| {
ShellError::GenericError(
"Error opening file".into(),
e.to_string(),
Some(file.span),
None,
Vec::new(),
)
let file = File::open(&file.item).map_err(|e| ShellError::GenericError {
error: "Error opening file".into(),
msg: e.to_string(),
span: Some(file.span),
help: None,
inner: vec![],
})?;
let buf_reader = BufReader::new(file);
@ -328,14 +311,12 @@ fn from_json(
let df: NuDataFrame = reader
.finish()
.map_err(|e| {
ShellError::GenericError(
"Json reader error".into(),
format!("{e:?}"),
Some(call.head),
None,
Vec::new(),
)
.map_err(|e| ShellError::GenericError {
error: "Json reader error".into(),
msg: format!("{e:?}"),
span: Some(call.head),
help: None,
inner: vec![],
})?
.into();
@ -349,14 +330,12 @@ fn from_jsonl(
) -> Result<Value, ShellError> {
let infer_schema: Option<usize> = call.get_flag(engine_state, stack, "infer-schema")?;
let file: Spanned<PathBuf> = call.req(engine_state, stack, 0)?;
let file = File::open(&file.item).map_err(|e| {
ShellError::GenericError(
"Error opening file".into(),
e.to_string(),
Some(file.span),
None,
Vec::new(),
)
let file = File::open(&file.item).map_err(|e| ShellError::GenericError {
error: "Error opening file".into(),
msg: e.to_string(),
span: Some(file.span),
help: None,
inner: vec![],
})?;
let buf_reader = BufReader::new(file);
@ -366,14 +345,12 @@ fn from_jsonl(
let df: NuDataFrame = reader
.finish()
.map_err(|e| {
ShellError::GenericError(
"Json lines reader error".into(),
format!("{e:?}"),
Some(call.head),
None,
Vec::new(),
)
.map_err(|e| ShellError::GenericError {
error: "Json lines reader error".into(),
msg: format!("{e:?}"),
span: Some(call.head),
help: None,
inner: vec![],
})?
.into();
@ -399,19 +376,19 @@ fn from_csv(
None => csv_reader,
Some(d) => {
if d.item.len() != 1 {
return Err(ShellError::GenericError(
"Incorrect delimiter".into(),
"Delimiter has to be one character".into(),
Some(d.span),
None,
Vec::new(),
));
return Err(ShellError::GenericError {
error: "Incorrect delimiter".into(),
msg: "Delimiter has to be one character".into(),
span: Some(d.span),
help: None,
inner: vec![],
});
} else {
let delimiter = match d.item.chars().next() {
Some(d) => d as u8,
None => unreachable!(),
};
csv_reader.with_delimiter(delimiter)
csv_reader.with_separator(delimiter)
}
}
};
@ -430,14 +407,12 @@ fn from_csv(
let df: NuLazyFrame = csv_reader
.finish()
.map_err(|e| {
ShellError::GenericError(
"Parquet reader error".into(),
format!("{e:?}"),
Some(call.head),
None,
Vec::new(),
)
.map_err(|e| ShellError::GenericError {
error: "Parquet reader error".into(),
msg: format!("{e:?}"),
span: Some(call.head),
help: None,
inner: vec![],
})?
.into();
@ -445,14 +420,12 @@ fn from_csv(
} else {
let file: Spanned<PathBuf> = call.req(engine_state, stack, 0)?;
let csv_reader = CsvReader::from_path(&file.item)
.map_err(|e| {
ShellError::GenericError(
"Error creating CSV reader".into(),
e.to_string(),
Some(file.span),
None,
Vec::new(),
)
.map_err(|e| ShellError::GenericError {
error: "Error creating CSV reader".into(),
msg: e.to_string(),
span: Some(file.span),
help: None,
inner: vec![],
})?
.with_encoding(CsvEncoding::LossyUtf8);
@ -460,19 +433,19 @@ fn from_csv(
None => csv_reader,
Some(d) => {
if d.item.len() != 1 {
return Err(ShellError::GenericError(
"Incorrect delimiter".into(),
"Delimiter has to be one character".into(),
Some(d.span),
None,
Vec::new(),
));
return Err(ShellError::GenericError {
error: "Incorrect delimiter".into(),
msg: "Delimiter has to be one character".into(),
span: Some(d.span),
help: None,
inner: vec![],
});
} else {
let delimiter = match d.item.chars().next() {
Some(d) => d as u8,
None => unreachable!(),
};
csv_reader.with_delimiter(delimiter)
csv_reader.with_separator(delimiter)
}
}
};
@ -496,14 +469,12 @@ fn from_csv(
let df: NuDataFrame = csv_reader
.finish()
.map_err(|e| {
ShellError::GenericError(
"Parquet reader error".into(),
format!("{e:?}"),
Some(call.head),
None,
Vec::new(),
)
.map_err(|e| ShellError::GenericError {
error: "Parquet reader error".into(),
msg: format!("{e:?}"),
span: Some(call.head),
help: None,
inner: vec![],
})?
.into();

View File

@ -76,15 +76,15 @@ fn command(
let mut ctx = SQLContext::new();
ctx.register("df", &df.df);
let df_sql = ctx.execute(&sql_query).map_err(|e| {
ShellError::GenericError(
"Dataframe Error".into(),
e.to_string(),
Some(call.head),
None,
Vec::new(),
)
})?;
let df_sql = ctx
.execute(&sql_query)
.map_err(|e| ShellError::GenericError {
error: "Dataframe Error".into(),
msg: e.to_string(),
span: Some(call.head),
help: None,
inner: vec![],
})?;
let lazy = NuLazyFrame::new(false, df_sql);
let eager = lazy.collect(call.head)?;

View File

@ -130,15 +130,15 @@ fn command_eager(
let new_names = extract_strings(new_names)?;
for (from, to) in columns.iter().zip(new_names.iter()) {
df.as_mut().rename(from, to).map_err(|e| {
ShellError::GenericError(
"Error renaming".into(),
e.to_string(),
Some(call.head),
None,
Vec::new(),
)
})?;
df.as_mut()
.rename(from, to)
.map_err(|e| ShellError::GenericError {
error: "Error renaming".into(),
msg: e.to_string(),
span: Some(call.head),
help: None,
inner: vec![],
})?;
}
Ok(PipelineData::Value(df.into_value(call.head), None))

View File

@ -4,6 +4,8 @@ use nu_protocol::{
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Spanned, SyntaxShape, Type,
};
use polars::prelude::NamedFrom;
use polars::series::Series;
use super::super::values::NuDataFrame;
@ -81,7 +83,7 @@ fn command(
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let rows: Option<Spanned<usize>> = call.get_flag(engine_state, stack, "n-rows")?;
let rows: Option<Spanned<i64>> = call.get_flag(engine_state, stack, "n-rows")?;
let fraction: Option<Spanned<f64>> = call.get_flag(engine_state, stack, "fraction")?;
let seed: Option<u64> = call
.get_flag::<i64>(engine_state, stack, "seed")?
@ -94,42 +96,38 @@ fn command(
match (rows, fraction) {
(Some(rows), None) => df
.as_ref()
.sample_n(rows.item, replace, shuffle, seed)
.map_err(|e| {
ShellError::GenericError(
"Error creating sample".into(),
e.to_string(),
Some(rows.span),
None,
Vec::new(),
)
.sample_n(&Series::new("s", &[rows.item]), replace, shuffle, seed)
.map_err(|e| ShellError::GenericError {
error: "Error creating sample".into(),
msg: e.to_string(),
span: Some(rows.span),
help: None,
inner: vec![],
}),
(None, Some(frac)) => df
.as_ref()
.sample_frac(frac.item, replace, shuffle, seed)
.map_err(|e| {
ShellError::GenericError(
"Error creating sample".into(),
e.to_string(),
Some(frac.span),
None,
Vec::new(),
)
.sample_frac(&Series::new("frac", &[frac.item]), replace, shuffle, seed)
.map_err(|e| ShellError::GenericError {
error: "Error creating sample".into(),
msg: e.to_string(),
span: Some(frac.span),
help: None,
inner: vec![],
}),
(Some(_), Some(_)) => Err(ShellError::GenericError(
"Incompatible flags".into(),
"Only one selection criterion allowed".into(),
Some(call.head),
None,
Vec::new(),
)),
(None, None) => Err(ShellError::GenericError(
"No selection".into(),
"No selection criterion was found".into(),
Some(call.head),
Some("Perhaps you want to use the flag -n or -f".into()),
Vec::new(),
)),
(Some(_), Some(_)) => Err(ShellError::GenericError {
error: "Incompatible flags".into(),
msg: "Only one selection criterion allowed".into(),
span: Some(call.head),
help: None,
inner: vec![],
}),
(None, None) => Err(ShellError::GenericError {
error: "No selection".into(),
msg: "No selection criterion was found".into(),
span: Some(call.head),
help: Some("Perhaps you want to use the flag -n or -f".into()),
inner: vec![],
}),
}
.map(|df| PipelineData::Value(NuDataFrame::dataframe_into_value(df, call.head), None))
}

View File

@ -2,7 +2,8 @@ use crate::dataframe::eager::sql_expr::parse_sql_expr;
use polars::error::{ErrString, PolarsError};
use polars::prelude::{col, DataFrame, DataType, IntoLazy, LazyFrame};
use sqlparser::ast::{
Expr as SqlExpr, Select, SelectItem, SetExpr, Statement, TableFactor, Value as SQLValue,
Expr as SqlExpr, GroupByExpr, Select, SelectItem, SetExpr, Statement, TableFactor,
Value as SQLValue,
};
use sqlparser::dialect::GenericDialect;
use sqlparser::parser::Parser;
@ -29,7 +30,7 @@ impl SQLContext {
fn execute_select(&self, select_stmt: &Select) -> Result<LazyFrame, PolarsError> {
// Determine involved dataframe
// Implicit join require some more work in query parsers, Explicit join are preferred for now.
let tbl = select_stmt.from.get(0).ok_or_else(|| {
let tbl = select_stmt.from.first().ok_or_else(|| {
PolarsError::ComputeError(ErrString::from("No table found in select statement"))
})?;
let mut alias_map = HashMap::new();
@ -37,7 +38,7 @@ impl SQLContext {
TableFactor::Table { name, alias, .. } => {
let tbl_name = name
.0
.get(0)
.first()
.ok_or_else(|| {
PolarsError::ComputeError(ErrString::from(
"No table found in select statement",
@ -96,8 +97,13 @@ impl SQLContext {
.collect::<Result<Vec<_>, PolarsError>>()?;
// Check for group by
// After projection since there might be number.
let group_by = select_stmt
.group_by
let group_by = match &select_stmt.group_by {
GroupByExpr::All =>
Err(
PolarsError::ComputeError("Group-By Error: Only positive number or expression are supported, not all".into())
)?,
GroupByExpr::Expressions(expressions) => expressions
}
.iter()
.map(
|e|match e {
@ -182,7 +188,7 @@ impl SQLContext {
))
} else {
let ast = ast
.get(0)
.first()
.ok_or_else(|| PolarsError::ComputeError(ErrString::from("No statement found")))?;
Ok(match ast {
Statement::Query(query) => {

View File

@ -2,8 +2,8 @@ use polars::error::PolarsError;
use polars::prelude::{col, lit, DataType, Expr, LiteralValue, PolarsResult as Result, TimeUnit};
use sqlparser::ast::{
BinaryOperator as SQLBinaryOperator, DataType as SQLDataType, Expr as SqlExpr,
Function as SQLFunction, Value as SqlValue, WindowType,
ArrayElemTypeDef, BinaryOperator as SQLBinaryOperator, DataType as SQLDataType,
Expr as SqlExpr, Function as SQLFunction, Value as SqlValue, WindowType,
};
fn map_sql_polars_datatype(data_type: &SQLDataType) -> Result<DataType> {
@ -13,7 +13,7 @@ fn map_sql_polars_datatype(data_type: &SQLDataType) -> Result<DataType> {
| SQLDataType::Uuid
| SQLDataType::Clob(_)
| SQLDataType::Text
| SQLDataType::String => DataType::Utf8,
| SQLDataType::String(_) => DataType::Utf8,
SQLDataType::Float(_) => DataType::Float32,
SQLDataType::Real => DataType::Float32,
SQLDataType::Double => DataType::Float64,
@ -31,9 +31,12 @@ fn map_sql_polars_datatype(data_type: &SQLDataType) -> Result<DataType> {
SQLDataType::Time(_, _) => DataType::Time,
SQLDataType::Timestamp(_, _) => DataType::Datetime(TimeUnit::Microseconds, None),
SQLDataType::Interval => DataType::Duration(TimeUnit::Microseconds),
SQLDataType::Array(inner_type) => match inner_type {
Some(inner_type) => DataType::List(Box::new(map_sql_polars_datatype(inner_type)?)),
None => {
SQLDataType::Array(array_type_def) => match array_type_def {
ArrayElemTypeDef::AngleBracket(inner_type)
| ArrayElemTypeDef::SquareBracket(inner_type) => {
DataType::List(Box::new(map_sql_polars_datatype(inner_type)?))
}
_ => {
return Err(PolarsError::ComputeError(
"SQL Datatype Array(None) was not supported in polars-sql yet!".into(),
))
@ -114,7 +117,11 @@ pub fn parse_sql_expr(expr: &SqlExpr) -> Result<Expr> {
binary_op_(left, right, op)?
}
SqlExpr::Function(sql_function) => parse_sql_function(sql_function)?,
SqlExpr::Cast { expr, data_type } => cast_(parse_sql_expr(expr)?, data_type)?,
SqlExpr::Cast {
expr,
data_type,
format: _,
} => cast_(parse_sql_expr(expr)?, data_type)?,
SqlExpr::Nested(expr) => parse_sql_expr(expr)?,
SqlExpr::Value(value) => literal_expr(value)?,
_ => {
@ -152,7 +159,7 @@ fn apply_window_spec(expr: Expr, window_type: Option<&WindowType>) -> Result<Exp
fn parse_sql_function(sql_function: &SQLFunction) -> Result<Expr> {
use sqlparser::ast::{FunctionArg, FunctionArgExpr};
// Function name mostly do not have name space, so it mostly take the first args
let function_name = sql_function.name.0[0].value.to_lowercase();
let function_name = sql_function.name.0[0].value.to_ascii_lowercase();
let args = sql_function
.args
.iter()

View File

@ -127,23 +127,23 @@ fn command(
if (&0.0..=&1.0).contains(&val) {
Ok(*val)
} else {
Err(ShellError::GenericError(
"Incorrect value for quantile".to_string(),
"value should be between 0 and 1".to_string(),
Some(span),
None,
Vec::new(),
))
Err(ShellError::GenericError {
error: "Incorrect value for quantile".into(),
msg: "value should be between 0 and 1".into(),
span: Some(span),
help: None,
inner: vec![],
})
}
}
Value::Error { error, .. } => Err(*error.clone()),
_ => Err(ShellError::GenericError(
"Incorrect value for quantile".to_string(),
"value should be a float".to_string(),
Some(span),
None,
Vec::new(),
)),
_ => Err(ShellError::GenericError {
error: "Incorrect value for quantile".into(),
msg: "value should be a float".into(),
span: Some(span),
help: None,
inner: vec![],
}),
}
})
.collect::<Result<Vec<f64>, ShellError>>()
@ -250,14 +250,12 @@ fn command(
let res = head.chain(tail).collect::<Vec<Series>>();
DataFrame::new(res)
.map_err(|e| {
ShellError::GenericError(
"Dataframe Error".into(),
e.to_string(),
Some(call.head),
None,
Vec::new(),
)
.map_err(|e| ShellError::GenericError {
error: "Dataframe Error".into(),
msg: e.to_string(),
span: Some(call.head),
help: None,
inner: vec![],
})
.map(|df| PipelineData::Value(NuDataFrame::dataframe_into_value(df, call.head), None))
}

View File

@ -97,47 +97,41 @@ fn command(
let index = NuDataFrame::try_from_value(index_value)?.as_series(index_span)?;
let casted = match index.dtype() {
DataType::UInt32 | DataType::UInt64 | DataType::Int32 | DataType::Int64 => {
index.cast(&DataType::UInt32).map_err(|e| {
ShellError::GenericError(
"Error casting index list".into(),
e.to_string(),
Some(index_span),
None,
Vec::new(),
)
})
}
_ => Err(ShellError::GenericError(
"Incorrect type".into(),
"Series with incorrect type".into(),
Some(call.head),
Some("Consider using a Series with type int type".into()),
Vec::new(),
)),
DataType::UInt32 | DataType::UInt64 | DataType::Int32 | DataType::Int64 => index
.cast(&DataType::UInt32)
.map_err(|e| ShellError::GenericError {
error: "Error casting index list".into(),
msg: e.to_string(),
span: Some(index_span),
help: None,
inner: vec![],
}),
_ => Err(ShellError::GenericError {
error: "Incorrect type".into(),
msg: "Series with incorrect type".into(),
span: Some(call.head),
help: Some("Consider using a Series with type int type".into()),
inner: vec![],
}),
}?;
let indices = casted.u32().map_err(|e| {
ShellError::GenericError(
"Error casting index list".into(),
e.to_string(),
Some(index_span),
None,
Vec::new(),
)
let indices = casted.u32().map_err(|e| ShellError::GenericError {
error: "Error casting index list".into(),
msg: e.to_string(),
span: Some(index_span),
help: None,
inner: vec![],
})?;
NuDataFrame::try_from_pipeline(input, call.head).and_then(|df| {
df.as_ref()
.take(indices)
.map_err(|e| {
ShellError::GenericError(
"Error taking values".into(),
e.to_string(),
Some(call.head),
None,
Vec::new(),
)
.map_err(|e| ShellError::GenericError {
error: "Error taking values".into(),
msg: e.to_string(),
span: Some(call.head),
help: None,
inner: vec![],
})
.map(|df| PipelineData::Value(NuDataFrame::dataframe_into_value(df, call.head), None))
})

View File

@ -58,25 +58,23 @@ fn command(
let mut df = NuDataFrame::try_from_pipeline(input, call.head)?;
let mut file = File::create(&file_name.item).map_err(|e| {
ShellError::GenericError(
"Error with file name".into(),
e.to_string(),
Some(file_name.span),
None,
Vec::new(),
)
let mut file = File::create(&file_name.item).map_err(|e| ShellError::GenericError {
error: "Error with file name".into(),
msg: e.to_string(),
span: Some(file_name.span),
help: None,
inner: vec![],
})?;
IpcWriter::new(&mut file).finish(df.as_mut()).map_err(|e| {
ShellError::GenericError(
"Error saving file".into(),
e.to_string(),
Some(file_name.span),
None,
Vec::new(),
)
})?;
IpcWriter::new(&mut file)
.finish(df.as_mut())
.map_err(|e| ShellError::GenericError {
error: "Error saving file".into(),
msg: e.to_string(),
span: Some(file_name.span),
help: None,
inner: vec![],
})?;
let file_value = Value::string(format!("saved {:?}", &file_name.item), file_name.span);

View File

@ -85,27 +85,23 @@ fn command(
let mut df = NuDataFrame::try_from_pipeline(input, call.head)?;
let file = File::create(&file_name.item).map_err(|e| {
ShellError::GenericError(
"Error with file name".into(),
e.to_string(),
Some(file_name.span),
None,
Vec::new(),
)
let file = File::create(&file_name.item).map_err(|e| ShellError::GenericError {
error: "Error with file name".into(),
msg: e.to_string(),
span: Some(file_name.span),
help: None,
inner: vec![],
})?;
AvroWriter::new(file)
.with_compression(compression)
.finish(df.as_mut())
.map_err(|e| {
ShellError::GenericError(
"Error saving file".into(),
e.to_string(),
Some(file_name.span),
None,
Vec::new(),
)
.map_err(|e| ShellError::GenericError {
error: "Error saving file".into(),
msg: e.to_string(),
span: Some(file_name.span),
help: None,
inner: vec![],
})?;
let file_value = Value::string(format!("saved {:?}", &file_name.item), file_name.span);

View File

@ -74,55 +74,53 @@ fn command(
let mut df = NuDataFrame::try_from_pipeline(input, call.head)?;
let mut file = File::create(&file_name.item).map_err(|e| {
ShellError::GenericError(
"Error with file name".into(),
e.to_string(),
Some(file_name.span),
None,
Vec::new(),
)
let mut file = File::create(&file_name.item).map_err(|e| ShellError::GenericError {
error: "Error with file name".into(),
msg: e.to_string(),
span: Some(file_name.span),
help: None,
inner: vec![],
})?;
let writer = CsvWriter::new(&mut file);
let writer = if no_header {
writer.has_header(false)
writer.include_header(false)
} else {
writer.has_header(true)
writer.include_header(true)
};
let mut writer = match delimiter {
None => writer,
Some(d) => {
if d.item.len() != 1 {
return Err(ShellError::GenericError(
"Incorrect delimiter".into(),
"Delimiter has to be one char".into(),
Some(d.span),
None,
Vec::new(),
));
return Err(ShellError::GenericError {
error: "Incorrect delimiter".into(),
msg: "Delimiter has to be one char".into(),
span: Some(d.span),
help: None,
inner: vec![],
});
} else {
let delimiter = match d.item.chars().next() {
Some(d) => d as u8,
None => unreachable!(),
};
writer.with_delimiter(delimiter)
writer.with_separator(delimiter)
}
}
};
writer.finish(df.as_mut()).map_err(|e| {
ShellError::GenericError(
"Error writing to file".into(),
e.to_string(),
Some(file_name.span),
None,
Vec::new(),
)
})?;
writer
.finish(df.as_mut())
.map_err(|e| ShellError::GenericError {
error: "Error writing to file".into(),
msg: e.to_string(),
span: Some(file_name.span),
help: None,
inner: vec![],
})?;
let file_value = Value::string(format!("saved {:?}", &file_name.item), file_name.span);

View File

@ -58,27 +58,23 @@ fn command(
let mut df = NuDataFrame::try_from_pipeline(input, call.head)?;
let file = File::create(&file_name.item).map_err(|e| {
ShellError::GenericError(
"Error with file name".into(),
e.to_string(),
Some(file_name.span),
None,
Vec::new(),
)
let file = File::create(&file_name.item).map_err(|e| ShellError::GenericError {
error: "Error with file name".into(),
msg: e.to_string(),
span: Some(file_name.span),
help: None,
inner: vec![],
})?;
let buf_writer = BufWriter::new(file);
JsonWriter::new(buf_writer)
.finish(df.as_mut())
.map_err(|e| {
ShellError::GenericError(
"Error saving file".into(),
e.to_string(),
Some(file_name.span),
None,
Vec::new(),
)
.map_err(|e| ShellError::GenericError {
error: "Error saving file".into(),
msg: e.to_string(),
span: Some(file_name.span),
help: None,
inner: vec![],
})?;
let file_value = Value::string(format!("saved {:?}", &file_name.item), file_name.span);

View File

@ -2,7 +2,7 @@ use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, Record, ShellError, Signature, Span, SyntaxShape, Type, Value,
record, Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
};
use crate::dataframe::values::NuExpression;
@ -39,18 +39,20 @@ impl Command for ToNu {
}
fn examples(&self) -> Vec<Example> {
let cols = vec!["index".into(), "a".into(), "b".into()];
let rec_1 = Value::test_record(Record {
cols: cols.clone(),
vals: vec![Value::test_int(0), Value::test_int(1), Value::test_int(2)],
let rec_1 = Value::test_record(record! {
"index" => Value::test_int(0),
"a" => Value::test_int(1),
"b" => Value::test_int(2),
});
let rec_2 = Value::test_record(Record {
cols: cols.clone(),
vals: vec![Value::test_int(1), Value::test_int(3), Value::test_int(4)],
let rec_2 = Value::test_record(record! {
"index" => Value::test_int(1),
"a" => Value::test_int(3),
"b" => Value::test_int(4),
});
let rec_3 = Value::test_record(Record {
cols,
vals: vec![Value::test_int(2), Value::test_int(3), Value::test_int(4)],
let rec_3 = Value::test_record(record! {
"index" => Value::test_int(2),
"a" => Value::test_int(3),
"b" => Value::test_int(4),
});
vec![
@ -67,9 +69,9 @@ impl Command for ToNu {
Example {
description: "Convert a col expression into a nushell value",
example: "dfr col a | dfr into-nu",
result: Some(Value::test_record(Record {
cols: vec!["expr".into(), "value".into()],
vals: vec![Value::test_string("column"), Value::test_string("a")],
result: Some(Value::test_record(record! {
"expr" => Value::test_string("column"),
"value" => Value::test_string("a"),
})),
},
]

View File

@ -58,25 +58,23 @@ fn command(
let mut df = NuDataFrame::try_from_pipeline(input, call.head)?;
let file = File::create(&file_name.item).map_err(|e| {
ShellError::GenericError(
"Error with file name".into(),
e.to_string(),
Some(file_name.span),
None,
Vec::new(),
)
let file = File::create(&file_name.item).map_err(|e| ShellError::GenericError {
error: "Error with file name".into(),
msg: e.to_string(),
span: Some(file_name.span),
help: None,
inner: vec![],
})?;
ParquetWriter::new(file).finish(df.as_mut()).map_err(|e| {
ShellError::GenericError(
"Error saving file".into(),
e.to_string(),
Some(file_name.span),
None,
Vec::new(),
)
})?;
ParquetWriter::new(file)
.finish(df.as_mut())
.map_err(|e| ShellError::GenericError {
error: "Error saving file".into(),
msg: e.to_string(),
span: Some(file_name.span),
help: None,
inner: vec![],
})?;
let file_value = Value::string(format!("saved {:?}", &file_name.item), file_name.span);

View File

@ -151,14 +151,12 @@ fn command_eager(
df.as_mut()
.with_column(series)
.map_err(|e| {
ShellError::GenericError(
"Error adding column to dataframe".into(),
e.to_string(),
Some(column_span),
None,
Vec::new(),
)
.map_err(|e| ShellError::GenericError {
error: "Error adding column to dataframe".into(),
msg: e.to_string(),
span: Some(column_span),
help: None,
inner: vec![],
})
.map(|df| {
PipelineData::Value(

View File

@ -4,7 +4,7 @@ use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, Record, ShellError, Signature, SyntaxShape, Type, Value,
record, Category, Example, PipelineData, ShellError, Signature, SyntaxShape, Type, Value,
};
#[derive(Clone)]
@ -38,20 +38,12 @@ impl Command for ExprAlias {
description: "Creates and alias expression",
example: "dfr col a | dfr as new_a | dfr into-nu",
result: {
let cols = vec!["expr".into(), "value".into()];
let expr = Value::test_string("column");
let value = Value::test_string("a");
let expr = Value::test_record(Record {
cols,
vals: vec![expr, value],
});
let cols = vec!["expr".into(), "alias".into()];
let value = Value::test_string("new_a");
let record = Value::test_record(Record {
cols,
vals: vec![expr, value],
let record = Value::test_record(record! {
"expr" => Value::test_record(record! {
"expr" => Value::test_string("column"),
"value" => Value::test_string("a"),
}),
"alias" => Value::test_string("new_a"),
});
Some(record)

View File

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

View File

@ -124,12 +124,12 @@ impl Command for ExprDatePart {
"microsecond" => expr_dt.microsecond(),
"nanosecond" => expr_dt.nanosecond(),
_ => {
return Err(ShellError::UnsupportedInput(
format!("{} is not a valid datepart, expected one of year, month, day, hour, minute, second, millisecond, microsecond, nanosecond", part.item),
"value originates from here".to_string(),
call.head,
part.span,
));
return Err(ShellError::UnsupportedInput {
msg: format!("{} is not a valid datepart, expected one of year, month, day, hour, minute, second, millisecond, microsecond, nanosecond", part.item),
input: "value originates from here".to_string(),
msg_span: call.head,
input_span: part.span,
});
}
}.into();

View File

@ -319,7 +319,7 @@ macro_rules! lazy_expr_command {
expr_command!(
ExprList,
"dfr implode",
"Aggregates a group to a Series",
"Aggregates a group to a Series.",
vec![Example {
description: "",
example: "",
@ -334,7 +334,7 @@ expr_command!(
expr_command!(
ExprAggGroups,
"dfr agg-groups",
"creates an agg_groups expression",
"Creates an agg_groups expression.",
vec![Example {
description: "",
example: "",
@ -349,7 +349,7 @@ expr_command!(
expr_command!(
ExprCount,
"dfr count",
"creates a count expression",
"Creates a count expression.",
vec![Example {
description: "",
example: "",
@ -364,7 +364,7 @@ expr_command!(
expr_command!(
ExprNot,
"dfr expr-not",
"creates a not expression",
"Creates a not expression.",
vec![Example {
description: "Creates a not expression",
example: "(dfr col a) > 2) | dfr expr-not",
@ -379,7 +379,7 @@ expr_command!(
lazy_expr_command!(
ExprMax,
"dfr max",
"Creates a max expression or aggregates columns to their max value",
"Creates a max expression or aggregates columns to their max value.",
vec![
Example {
description: "Max value from columns in a dataframe",
@ -424,7 +424,7 @@ lazy_expr_command!(
lazy_expr_command!(
ExprMin,
"dfr min",
"Creates a min expression or aggregates columns to their min value",
"Creates a min expression or aggregates columns to their min value.",
vec![
Example {
description: "Min value from columns in a dataframe",
@ -469,7 +469,7 @@ lazy_expr_command!(
lazy_expr_command!(
ExprSum,
"dfr sum",
"Creates a sum expression for an aggregation or aggregates columns to their sum value",
"Creates a sum expression for an aggregation or aggregates columns to their sum value.",
vec![
Example {
description: "Sums all columns in a dataframe",
@ -514,7 +514,7 @@ lazy_expr_command!(
lazy_expr_command!(
ExprMean,
"dfr mean",
"Creates a mean expression for an aggregation or aggregates columns to their mean value",
"Creates a mean expression for an aggregation or aggregates columns to their mean value.",
vec![
Example {
description: "Mean value from columns in a dataframe",
@ -559,7 +559,7 @@ lazy_expr_command!(
expr_command!(
ExprMedian,
"dfr median",
"Creates a median expression for an aggregation",
"Creates a median expression for an aggregation.",
vec![Example {
description: "Median aggregation for a group-by",
example: r#"[[a b]; [one 2] [one 4] [two 1]]
@ -590,7 +590,7 @@ expr_command!(
lazy_expr_command!(
ExprStd,
"dfr std",
"Creates a std expression for an aggregation of std value from columns in a dataframe",
"Creates a std expression for an aggregation of std value from columns in a dataframe.",
vec![
Example {
description: "Std value from columns in a dataframe",
@ -636,7 +636,7 @@ lazy_expr_command!(
lazy_expr_command!(
ExprVar,
"dfr var",
"Create a var expression for an aggregation",
"Create a var expression for an aggregation.",
vec![
Example {
description:

View File

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

View File

@ -15,7 +15,7 @@ impl Command for ExprOtherwise {
}
fn usage(&self) -> &str {
"completes a when expression."
"Completes a when expression."
}
fn signature(&self) -> Signature {

View File

@ -125,13 +125,13 @@ impl Command for LazyAggregate {
let dtype = schema.get(name.as_str());
if matches!(dtype, Some(DataType::Object(..))) {
return Err(ShellError::GenericError(
"Object type column not supported for aggregation".into(),
format!("Column '{name}' is type Object"),
Some(call.head),
Some("Aggregations cannot be performed on Object type columns. Use dtype command to check column types".into()),
Vec::new(),
));
return Err(ShellError::GenericError {
error: "Object type column not supported for aggregation".into(),
msg: format!("Column '{name}' is type Object"),
span: Some(call.head),
help: Some("Aggregations cannot be performed on Object type columns. Use dtype command to check column types".into()),
inner: vec![],
});
}
}
}
@ -171,7 +171,7 @@ fn get_col_name(expr: &Expr) -> Option<String> {
| Expr::Slice { input: expr, .. }
| Expr::Cast { expr, .. }
| Expr::Sort { expr, .. }
| Expr::Take { expr, .. }
| Expr::Gather { expr, .. }
| Expr::SortBy { expr, .. }
| Expr::Exclude(expr, _)
| Expr::Alias(expr, _)
@ -189,6 +189,7 @@ fn get_col_name(expr: &Expr) -> Option<String> {
| Expr::RenameAlias { .. }
| Expr::Count
| Expr::Nth(_)
| Expr::SubPlan(_, _)
| Expr::Selector(_) => None,
}
}

View File

@ -16,7 +16,7 @@ impl Command for LazyFetch {
}
fn usage(&self) -> &str {
"collects the lazyframe to the selected rows."
"Collects the lazyframe to the selected rows."
}
fn signature(&self) -> Signature {
@ -67,14 +67,12 @@ impl Command for LazyFetch {
let eager: NuDataFrame = lazy
.into_polars()
.fetch(rows as usize)
.map_err(|e| {
ShellError::GenericError(
"Error fetching rows".into(),
e.to_string(),
Some(call.head),
None,
Vec::new(),
)
.map_err(|e| ShellError::GenericError {
error: "Error fetching rows".into(),
msg: e.to_string(),
span: Some(call.head),
help: None,
inner: vec![],
})?
.into();

View File

@ -17,7 +17,7 @@ impl Command for LazyFlatten {
}
fn usage(&self) -> &str {
"An alias for dfr explode"
"An alias for dfr explode."
}
fn signature(&self) -> Signature {

View File

@ -121,7 +121,7 @@ lazy_command!(
"dfr reverse",
"Reverses the LazyFrame",
vec![Example {
description: "Reverses the dataframe",
description: "Reverses the dataframe.",
example: "[[a b]; [6 2] [4 2] [2 2]] | dfr into-df | dfr reverse",
result: Some(
NuDataFrame::try_from_columns(vec![
@ -147,7 +147,7 @@ lazy_command!(
lazy_command!(
LazyCache,
"dfr cache",
"Caches operations in a new LazyFrame",
"Caches operations in a new LazyFrame.",
vec![Example {
description: "Caches the result into a new LazyFrame",
example: "[[a b]; [6 2] [4 2] [2 2]] | dfr into-df | dfr reverse | dfr cache",

View File

@ -16,7 +16,7 @@ impl Command for LazySortBy {
}
fn usage(&self) -> &str {
"sorts a lazy dataframe based on expression(s)."
"Sorts a lazy dataframe based on expression(s)."
}
fn signature(&self) -> Signature {
@ -118,13 +118,13 @@ impl Command for LazySortBy {
.get_flag::<Value>(engine_state, stack, "reverse")?
.expect("already checked and it exists")
.span();
return Err(ShellError::GenericError(
"Incorrect list size".into(),
"Size doesn't match expression list".into(),
Some(span),
None,
Vec::new(),
));
return Err(ShellError::GenericError {
error: "Incorrect list size".into(),
msg: "Size doesn't match expression list".into(),
span: Some(span),
help: None,
inner: vec![],
});
} else {
list
}

View File

@ -78,14 +78,12 @@ fn command(
let df = NuDataFrame::try_from_pipeline(input, call.head)?;
let series = df.as_series(call.head)?;
let bool = series.bool().map_err(|_| {
ShellError::GenericError(
"Error converting to bool".into(),
"all-false only works with series of type bool".into(),
Some(call.head),
None,
Vec::new(),
)
let bool = series.bool().map_err(|_| ShellError::GenericError {
error: "Error converting to bool".into(),
msg: "all-false only works with series of type bool".into(),
span: Some(call.head),
help: None,
inner: vec![],
})?;
let value = Value::bool(!bool.any(), call.head);

View File

@ -78,14 +78,12 @@ fn command(
let df = NuDataFrame::try_from_pipeline(input, call.head)?;
let series = df.as_series(call.head)?;
let bool = series.bool().map_err(|_| {
ShellError::GenericError(
"Error converting to bool".into(),
"all-false only works with series of type bool".into(),
Some(call.head),
None,
Vec::new(),
)
let bool = series.bool().map_err(|_| ShellError::GenericError {
error: "Error converting to bool".into(),
msg: "all-false only works with series of type bool".into(),
span: Some(call.head),
help: None,
inner: vec![],
})?;
let value = Value::bool(bool.all(), call.head);

View File

@ -8,6 +8,7 @@ use nu_protocol::{
Value,
};
use polars::prelude::{DataType, IntoSeries};
use polars_ops::prelude::{cum_max, cum_min, cum_sum};
enum CumType {
Min,
@ -21,13 +22,13 @@ impl CumType {
"min" => Ok(Self::Min),
"max" => Ok(Self::Max),
"sum" => Ok(Self::Sum),
_ => Err(ShellError::GenericError(
"Wrong operation".into(),
"Operation not valid for cumulative".into(),
Some(span),
Some("Allowed values: max, min, sum".into()),
Vec::new(),
)),
_ => Err(ShellError::GenericError {
error: "Wrong operation".into(),
msg: "Operation not valid for cumulative".into(),
span: Some(span),
help: Some("Allowed values: max, min, sum".into()),
inner: vec![],
}),
}
}
@ -108,21 +109,28 @@ fn command(
let series = df.as_series(call.head)?;
if let DataType::Object(_) = series.dtype() {
return Err(ShellError::GenericError(
"Found object series".into(),
"Series of type object cannot be used for cumulative operation".into(),
Some(call.head),
None,
Vec::new(),
));
return Err(ShellError::GenericError {
error: "Found object series".into(),
msg: "Series of type object cannot be used for cumulative operation".into(),
span: Some(call.head),
help: None,
inner: vec![],
});
}
let cum_type = CumType::from_str(&cum_type.item, cum_type.span)?;
let mut res = match cum_type {
CumType::Max => series.cummax(reverse),
CumType::Min => series.cummin(reverse),
CumType::Sum => series.cumsum(reverse),
};
CumType::Max => cum_max(&series, reverse),
CumType::Min => cum_min(&series, reverse),
CumType::Sum => cum_sum(&series, reverse),
}
.map_err(|e| ShellError::GenericError {
error: "Error creating cumulative".into(),
msg: e.to_string(),
span: Some(call.head),
help: None,
inner: vec![],
})?;
let name = format!("{}_{}", series.name(), cum_type.to_str());
res.rename(&name);

View File

@ -68,14 +68,12 @@ fn command(
let df = NuDataFrame::try_from_pipeline(input, call.head)?;
let series = df.as_series(call.head)?;
let casted = series.utf8().map_err(|e| {
ShellError::GenericError(
"Error casting to string".into(),
e.to_string(),
Some(call.head),
None,
Vec::new(),
)
let casted = series.utf8().map_err(|e| ShellError::GenericError {
error: "Error casting to string".into(),
msg: e.to_string(),
span: Some(call.head),
help: None,
inner: vec![],
})?;
let res = if not_exact {
@ -85,14 +83,12 @@ fn command(
};
let mut res = res
.map_err(|e| {
ShellError::GenericError(
"Error creating datetime".into(),
e.to_string(),
Some(call.head),
None,
Vec::new(),
)
.map_err(|e| ShellError::GenericError {
error: "Error creating datetime".into(),
msg: e.to_string(),
span: Some(call.head),
help: None,
inner: vec![],
})?
.into_series();

View File

@ -132,14 +132,12 @@ fn command(
let df = NuDataFrame::try_from_pipeline(input, call.head)?;
let series = df.as_series(call.head)?;
let casted = series.utf8().map_err(|e| {
ShellError::GenericError(
"Error casting to string".into(),
e.to_string(),
Some(call.head),
None,
Vec::new(),
)
let casted = series.utf8().map_err(|e| ShellError::GenericError {
error: "Error casting to string".into(),
msg: e.to_string(),
span: Some(call.head),
help: None,
inner: vec![],
})?;
let res = if not_exact {
@ -162,14 +160,12 @@ fn command(
};
let mut res = res
.map_err(|e| {
ShellError::GenericError(
"Error creating datetime".into(),
e.to_string(),
Some(call.head),
None,
Vec::new(),
)
.map_err(|e| ShellError::GenericError {
error: "Error creating datetime".into(),
msg: e.to_string(),
span: Some(call.head),
help: None,
inner: vec![],
})?
.into_series();

View File

@ -65,14 +65,12 @@ fn command(
let df = NuDataFrame::try_from_pipeline(input, call.head)?;
let series = df.as_series(call.head)?;
let casted = series.datetime().map_err(|e| {
ShellError::GenericError(
"Error casting to datetime type".into(),
e.to_string(),
Some(call.head),
None,
Vec::new(),
)
let casted = series.datetime().map_err(|e| ShellError::GenericError {
error: "Error casting to datetime type".into(),
msg: e.to_string(),
span: Some(call.head),
help: None,
inner: vec![],
})?;
let res = casted.day().into_series();

View File

@ -65,14 +65,12 @@ fn command(
let df = NuDataFrame::try_from_pipeline(input, call.head)?;
let series = df.as_series(call.head)?;
let casted = series.datetime().map_err(|e| {
ShellError::GenericError(
"Error casting to datetime type".into(),
e.to_string(),
Some(call.head),
None,
Vec::new(),
)
let casted = series.datetime().map_err(|e| ShellError::GenericError {
error: "Error casting to datetime type".into(),
msg: e.to_string(),
span: Some(call.head),
help: None,
inner: vec![],
})?;
let res = casted.hour().into_series();

View File

@ -65,14 +65,12 @@ fn command(
let df = NuDataFrame::try_from_pipeline(input, call.head)?;
let series = df.as_series(call.head)?;
let casted = series.datetime().map_err(|e| {
ShellError::GenericError(
"Error casting to datetime type".into(),
e.to_string(),
Some(call.head),
None,
Vec::new(),
)
let casted = series.datetime().map_err(|e| ShellError::GenericError {
error: "Error casting to datetime type".into(),
msg: e.to_string(),
span: Some(call.head),
help: None,
inner: vec![],
})?;
let res = casted.minute().into_series();

View File

@ -65,14 +65,12 @@ fn command(
let df = NuDataFrame::try_from_pipeline(input, call.head)?;
let series = df.as_series(call.head)?;
let casted = series.datetime().map_err(|e| {
ShellError::GenericError(
"Error casting to datetime type".into(),
e.to_string(),
Some(call.head),
None,
Vec::new(),
)
let casted = series.datetime().map_err(|e| ShellError::GenericError {
error: "Error casting to datetime type".into(),
msg: e.to_string(),
span: Some(call.head),
help: None,
inner: vec![],
})?;
let res = casted.month().into_series();

View File

@ -65,14 +65,12 @@ fn command(
let df = NuDataFrame::try_from_pipeline(input, call.head)?;
let series = df.as_series(call.head)?;
let casted = series.datetime().map_err(|e| {
ShellError::GenericError(
"Error casting to datetime type".into(),
e.to_string(),
Some(call.head),
None,
Vec::new(),
)
let casted = series.datetime().map_err(|e| ShellError::GenericError {
error: "Error casting to datetime type".into(),
msg: e.to_string(),
span: Some(call.head),
help: None,
inner: vec![],
})?;
let res = casted.nanosecond().into_series();

View File

@ -65,14 +65,12 @@ fn command(
let df = NuDataFrame::try_from_pipeline(input, call.head)?;
let series = df.as_series(call.head)?;
let casted = series.datetime().map_err(|e| {
ShellError::GenericError(
"Error casting to datetime type".into(),
e.to_string(),
Some(call.head),
None,
Vec::new(),
)
let casted = series.datetime().map_err(|e| ShellError::GenericError {
error: "Error casting to datetime type".into(),
msg: e.to_string(),
span: Some(call.head),
help: None,
inner: vec![],
})?;
let res = casted.ordinal().into_series();

View File

@ -65,14 +65,12 @@ fn command(
let df = NuDataFrame::try_from_pipeline(input, call.head)?;
let series = df.as_series(call.head)?;
let casted = series.datetime().map_err(|e| {
ShellError::GenericError(
"Error casting to datetime type".into(),
e.to_string(),
Some(call.head),
None,
Vec::new(),
)
let casted = series.datetime().map_err(|e| ShellError::GenericError {
error: "Error casting to datetime type".into(),
msg: e.to_string(),
span: Some(call.head),
help: None,
inner: vec![],
})?;
let res = casted.second().into_series();

View File

@ -65,14 +65,12 @@ fn command(
let df = NuDataFrame::try_from_pipeline(input, call.head)?;
let series = df.as_series(call.head)?;
let casted = series.datetime().map_err(|e| {
ShellError::GenericError(
"Error casting to datetime type".into(),
e.to_string(),
Some(call.head),
None,
Vec::new(),
)
let casted = series.datetime().map_err(|e| ShellError::GenericError {
error: "Error casting to datetime type".into(),
msg: e.to_string(),
span: Some(call.head),
help: None,
inner: vec![],
})?;
let res = casted.week().into_series();

View File

@ -65,14 +65,12 @@ fn command(
let df = NuDataFrame::try_from_pipeline(input, call.head)?;
let series = df.as_series(call.head)?;
let casted = series.datetime().map_err(|e| {
ShellError::GenericError(
"Error casting to datetime type".into(),
e.to_string(),
Some(call.head),
None,
Vec::new(),
)
let casted = series.datetime().map_err(|e| ShellError::GenericError {
error: "Error casting to datetime type".into(),
msg: e.to_string(),
span: Some(call.head),
help: None,
inner: vec![],
})?;
let res = casted.weekday().into_series();

View File

@ -65,14 +65,12 @@ fn command(
let df = NuDataFrame::try_from_pipeline(input, call.head)?;
let series = df.as_series(call.head)?;
let casted = series.datetime().map_err(|e| {
ShellError::GenericError(
"Error casting to datetime type".into(),
e.to_string(),
Some(call.head),
None,
Vec::new(),
)
let casted = series.datetime().map_err(|e| ShellError::GenericError {
error: "Error casting to datetime type".into(),
msg: e.to_string(),
span: Some(call.head),
help: None,
inner: vec![],
})?;
let res = casted.year().into_series();

View File

@ -67,13 +67,13 @@ fn command(
let df = NuDataFrame::try_from_pipeline(input, call.head)?;
let columns = df.as_ref().get_column_names();
if columns.len() > 1 {
return Err(ShellError::GenericError(
"Error using as series".into(),
"dataframe has more than one column".into(),
Some(call.head),
None,
Vec::new(),
));
return Err(ShellError::GenericError {
error: "Error using as series".into(),
msg: "dataframe has more than one column".into(),
span: Some(call.head),
help: None,
inner: vec![],
});
}
match columns.first() {
@ -85,25 +85,23 @@ fn command(
.lazy()
.select(&[expression])
.collect()
.map_err(|err| {
ShellError::GenericError(
"Error creating index column".into(),
err.to_string(),
Some(call.head),
None,
Vec::new(),
)
.map_err(|err| ShellError::GenericError {
error: "Error creating index column".into(),
msg: err.to_string(),
span: Some(call.head),
help: None,
inner: vec![],
})?;
let value = NuDataFrame::dataframe_into_value(res, call.head);
Ok(PipelineData::Value(value, None))
}
_ => Err(ShellError::UnsupportedInput(
"Expected the dataframe to have a column".to_string(),
"".to_string(),
call.head,
call.head,
)),
_ => Err(ShellError::UnsupportedInput {
msg: "Expected the dataframe to have a column".to_string(),
input: "".to_string(),
msg_span: call.head,
input_span: call.head,
}),
}
}

View File

@ -69,14 +69,12 @@ fn command(
let mut res = df
.as_series(call.head)?
.arg_unique()
.map_err(|e| {
ShellError::GenericError(
"Error extracting unique values".into(),
e.to_string(),
Some(call.head),
None,
Vec::new(),
)
.map_err(|e| ShellError::GenericError {
error: "Error extracting unique values".into(),
msg: e.to_string(),
span: Some(call.head),
help: None,
inner: vec![],
})?
.into_series();
res.rename("arg_unique");

View File

@ -86,36 +86,33 @@ fn command(
let indices = NuDataFrame::try_from_value(indices_value)?.as_series(indices_span)?;
let casted = match indices.dtype() {
DataType::UInt32 | DataType::UInt64 | DataType::Int32 | DataType::Int64 => {
indices.as_ref().cast(&DataType::UInt32).map_err(|e| {
ShellError::GenericError(
"Error casting indices".into(),
e.to_string(),
Some(indices_span),
None,
Vec::new(),
)
})
}
_ => Err(ShellError::GenericError(
"Incorrect type".into(),
"Series with incorrect type".into(),
Some(indices_span),
Some("Consider using a Series with type int type".into()),
Vec::new(),
)),
DataType::UInt32 | DataType::UInt64 | DataType::Int32 | DataType::Int64 => indices
.as_ref()
.cast(&DataType::UInt32)
.map_err(|e| ShellError::GenericError {
error: "Error casting indices".into(),
msg: e.to_string(),
span: Some(indices_span),
help: None,
inner: vec![],
}),
_ => Err(ShellError::GenericError {
error: "Incorrect type".into(),
msg: "Series with incorrect type".into(),
span: Some(indices_span),
help: Some("Consider using a Series with type int type".into()),
inner: vec![],
}),
}?;
let indices = casted
.u32()
.map_err(|e| {
ShellError::GenericError(
"Error casting indices".into(),
e.to_string(),
Some(indices_span),
None,
Vec::new(),
)
.map_err(|e| ShellError::GenericError {
error: "Error casting indices".into(),
msg: e.to_string(),
span: Some(indices_span),
help: None,
inner: vec![],
})?
.into_iter()
.flatten();
@ -124,92 +121,85 @@ fn command(
let series = df.as_series(call.head)?;
let span = value.span();
let res = match value {
Value::Int { val, .. } => {
let chunked = series.i64().map_err(|e| {
ShellError::GenericError(
"Error casting to i64".into(),
e.to_string(),
Some(span),
None,
Vec::new(),
)
})?;
let res = chunked.set_at_idx(indices, Some(val)).map_err(|e| {
ShellError::GenericError(
"Error setting value".into(),
e.to_string(),
Some(span),
None,
Vec::new(),
)
})?;
NuDataFrame::try_from_series(vec![res.into_series()], call.head)
}
Value::Float { val, .. } => {
let chunked = series.f64().map_err(|e| {
ShellError::GenericError(
"Error casting to f64".into(),
e.to_string(),
Some(span),
None,
Vec::new(),
)
})?;
let res = chunked.set_at_idx(indices, Some(val)).map_err(|e| {
ShellError::GenericError(
"Error setting value".into(),
e.to_string(),
Some(span),
None,
Vec::new(),
)
})?;
NuDataFrame::try_from_series(vec![res.into_series()], call.head)
}
Value::String { val, .. } => {
let chunked = series.utf8().map_err(|e| {
ShellError::GenericError(
"Error casting to string".into(),
e.to_string(),
Some(span),
None,
Vec::new(),
)
})?;
let res = chunked
.set_at_idx(indices, Some(val.as_ref()))
.map_err(|e| {
ShellError::GenericError(
"Error setting value".into(),
e.to_string(),
Some(span),
None,
Vec::new(),
)
let res =
match value {
Value::Int { val, .. } => {
let chunked = series.i64().map_err(|e| ShellError::GenericError {
error: "Error casting to i64".into(),
msg: e.to_string(),
span: Some(span),
help: None,
inner: vec![],
})?;
let mut res = res.into_series();
res.rename("string");
let res = chunked.set_at_idx(indices, Some(val)).map_err(|e| {
ShellError::GenericError {
error: "Error setting value".into(),
msg: e.to_string(),
span: Some(span),
help: None,
inner: vec![],
}
})?;
NuDataFrame::try_from_series(vec![res.into_series()], call.head)
}
_ => Err(ShellError::GenericError(
"Incorrect value type".into(),
format!(
"this value cannot be set in a series of type '{}'",
series.dtype()
),
Some(span),
None,
Vec::new(),
)),
};
NuDataFrame::try_from_series(vec![res.into_series()], call.head)
}
Value::Float { val, .. } => {
let chunked = series.f64().map_err(|e| ShellError::GenericError {
error: "Error casting to f64".into(),
msg: e.to_string(),
span: Some(span),
help: None,
inner: vec![],
})?;
let res = chunked.set_at_idx(indices, Some(val)).map_err(|e| {
ShellError::GenericError {
error: "Error setting value".into(),
msg: e.to_string(),
span: Some(span),
help: None,
inner: vec![],
}
})?;
NuDataFrame::try_from_series(vec![res.into_series()], call.head)
}
Value::String { val, .. } => {
let chunked = series.utf8().map_err(|e| ShellError::GenericError {
error: "Error casting to string".into(),
msg: e.to_string(),
span: Some(span),
help: None,
inner: vec![],
})?;
let res = chunked
.set_at_idx(indices, Some(val.as_ref()))
.map_err(|e| ShellError::GenericError {
error: "Error setting value".into(),
msg: e.to_string(),
span: Some(span),
help: None,
inner: vec![],
})?;
let mut res = res.into_series();
res.rename("string");
NuDataFrame::try_from_series(vec![res.into_series()], call.head)
}
_ => Err(ShellError::GenericError {
error: "Incorrect value type".into(),
msg: format!(
"this value cannot be set in a series of type '{}'",
series.dtype()
),
span: Some(span),
help: None,
inner: vec![],
}),
};
res.map(|df| PipelineData::Value(NuDataFrame::into_value(df, call.head), None))
}

View File

@ -94,14 +94,12 @@ fn command(
let mut res = df
.as_ref()
.is_duplicated()
.map_err(|e| {
ShellError::GenericError(
"Error finding duplicates".into(),
e.to_string(),
Some(call.head),
None,
Vec::new(),
)
.map_err(|e| ShellError::GenericError {
error: "Error finding duplicates".into(),
msg: e.to_string(),
span: Some(call.head),
help: None,
inner: vec![],
})?
.into_series();

View File

@ -79,14 +79,12 @@ fn command(
let other = other_df.as_series(other_span)?;
let mut res = is_in(&df, &other)
.map_err(|e| {
ShellError::GenericError(
"Error finding in other".into(),
e.to_string(),
Some(call.head),
None,
Vec::new(),
)
.map_err(|e| ShellError::GenericError {
error: "Error finding in other".into(),
msg: e.to_string(),
span: Some(call.head),
help: None,
inner: vec![],
})?
.into_series();

View File

@ -93,14 +93,12 @@ fn command(
let mut res = df
.as_ref()
.is_unique()
.map_err(|e| {
ShellError::GenericError(
"Error finding unique values".into(),
e.to_string(),
Some(call.head),
None,
Vec::new(),
)
.map_err(|e| ShellError::GenericError {
error: "Error finding unique values".into(),
msg: e.to_string(),
span: Some(call.head),
help: None,
inner: vec![],
})?
.into_series();

View File

@ -68,14 +68,12 @@ fn command(
) -> Result<PipelineData, ShellError> {
let series = df.as_series(call.head)?;
let bool = series.bool().map_err(|e| {
ShellError::GenericError(
"Error inverting mask".into(),
e.to_string(),
Some(call.head),
None,
Vec::new(),
)
let bool = series.bool().map_err(|e| ShellError::GenericError {
error: "Error inverting mask".into(),
msg: e.to_string(),
span: Some(call.head),
help: None,
inner: vec![],
})?;
let res = bool.not();

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