Compare commits

..

179 Commits

Author SHA1 Message Date
6e1e824473 Bump version to 0.98.0 (#13865) 2024-09-18 00:48:46 -07:00
af77bc60e2 Improved null handling when converting from nu -> dataframe. (#13855)
# Description
Fixes: #12726 and #13185

Previously converting columns that contained null caused polars to force
a dtype of object even when using a schema.

Now:
1. When using a schema, the type the schema defines for the column will
always be used.
2. When a schema is not used, the previous type is used when a value is
null.

# User-Facing Changes
- The type defined by the schema we be respected when passing in a null
value `[a]; [null] | polars into-df -s {a: str}` will create a df with
an str dtype column with one null value versus a column of type object.
- *BREAKING CHANGE* If you define a schema, all columns must be in the
schema.
2024-09-16 18:07:13 -05:00
9ca0fb772d Make IR the default evaluator (#13718)
# Description

Makes IR the default evaluator, in preparation to remove the non-IR
evaluator in a future release.

# User-Facing Changes

* Remove `NU_USE_IR` option
* Add `NU_DISABLE_IR` option
* IR is enabled unless `NU_DISABLE_IR` is set

# After Submitting
- [ ] release notes
2024-09-15 14:54:38 -07:00
c535c24d03 catch unwrap on panics with polars collect (#13850)
# Description
This resurrects the work from #12866 and fixes #12732. 

Polars panics for a plethora or reasons. While handling panics is
generally frowned upon, in cases like with `polars collect` a panic
cause a lot of work to be lost. Often you might have multiple dataframes
in memory and you are trying one operation and lose all state.

While it possible the panic can leave things a strange state, it is
pretty unlikely as part of a polars pipeline. Most of the time polars
objects are not manipulating dataframes in memory mutability, but rather
creating a new dataframe the operations being applied. This is always
the case with a lazy pipeline. After the collect call, the original
dataframes are intact still and I haven't observed any side effects.
2024-09-15 07:21:02 -05:00
c9cb62067c Fix dockerfile and reset Nu config to default (#13851)
<!--
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 dockerfile and reset Nu config to default, fetching config file from
the remote may cause compatible issues
2024-09-15 20:03:22 +08:00
ebc7b80c23 allow tab to be retained with find (#13848)
# Description

This PR allows the tab character to be retained when using `find`.

### Before

![image](https://github.com/user-attachments/assets/92d78f55-58fb-42f4-be8f-82992292c900)

### After

![image](https://github.com/user-attachments/assets/fbd8e47f-9806-4e30-89a1-6c88b12a612c)


closes #13846

# 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 toolkit.nu; toolkit test stdlib"` 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-09-14 08:51:00 -05:00
aaaab8e070 Update Nu for release workflow and fix build warning of musl targets (#13840)
<!--
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

1. Update Nushell to v0.97.1 for release workflow
2. Fix musl targets cross compiling warning like: `warning: File system
loop found:
/home/runner/work/nightly/nightly/aarch64-linux-musl-cross/usr points to
an ancestor /home/runner/work/nightly/nightly/aarch64-linux-musl-cross/`

Tested in
https://github.com/nushell/nightly/actions/runs/10849647834/job/30109290106
2024-09-13 22:03:31 +08:00
a59477205d Fix try: Add set_last_error() to prepare_error_handler() for IR eval (#13838)
# Description

Fixes a bug with `set_last_error()` introduced by @IanManske not being
called during the jump to an error handler in IR eval. Without this,
`$env.LAST_EXIT_CODE` wasn't getting set in the `catch` block for an
external.

# Tests + Formatting

Added a `tests/eval` test to cover this in both IR and non-IR eval
2024-09-13 00:07:22 -07:00
5101b5e306 Add --number flag to split column (#13831)
This allows parsing of data (e.g. key-value pairs) where the last column
may contain the delimiter.

- this PR should close #13742

# Description

Adds a `--number (-n)` flag to `split column`, analogous to `split row
--number`.

```
~> ['author: Salina Yoon' r#'title: Where's Ellie?: A Hide-and-Seek Book'#] | split column --number 2 ': ' key value
╭───┬────────┬──────────────────────────────────────╮
│ # │  key   │                value                 │
├───┼────────┼──────────────────────────────────────┤
│ 0 │ author │ Salina Yoon                          │
│ 1 │ title  │ Where's Ellie?: A Hide-and-Seek Book │
╰───┴────────┴──────────────────────────────────────╯
```

# User-Facing Changes
* `split column` gains a `--number` option

# Tests + Formatting
Tests included in strings::split::column::test::test_examples and
commands::split_column::to_column.

# After Submitting
Reference documentation is auto-generated from code. No other
documentation updates necessary.
2024-09-12 07:16:33 -05:00
fb34a4fc6c Make polars save return an empty pipeline (#13833)
# Description
In order to be more consistent with it's nu counterpart, `polars save`
now returns an empty pipeline instead of a message of the saved file.

# User-Facing Changes
- `polars save` no longer displays a save message, making it consistent
with `save` behavior.
2024-09-12 06:23:40 -05:00
1bcceafd93 Improve #12008 UX, clear scrollback by default on clear (#13821)
<!--
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.
-->

Related to #11693. It looks like there is no reason for Nu shell's
`clear` to behave differently than other shells' `clear`. To improve the
UX and fulfill the user expectations, the default has been adjusted to
work the same as in other shells by clearing the scrollback buffer. For
edge cases where someone depends on the current behavior of keeping the
scrollback, a `-k` option has been added.

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

- Improve the UX of `clear` by changing the default behavior to the same
as other popular shells, i.e clear scrollback by default.
- Remove `-a --all` flag, make it the default behavior to clear the
scrollback
- Add `-k --keep-scrollback` flag for backward compat to keep the
scrollback buffer

# 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 toolkit.nu; toolkit test stdlib"` 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
> ```
-->

This is a simple change flipping the flag and default behavior, no tests
should be needed.

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

- [ ] update the `clear` command docs

---------

Co-authored-by: Douglas <32344964+NotTheDr01ds@users.noreply.github.com>
Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2024-09-11 15:33:20 -05:00
217eb4ed70 fix path exists on a non-directory file (#13763)
# Description
Fixes:  #13460

The issue is caused by `try_exists` method on path, it will return
`Err(NotADirectory)` if user tried to check for a path under a regular
file.
To fix it, I think it's ok to use `exists` rather than `try_exists`,
although
[Path::exists()](https://doc.rust-lang.org/std/path/struct.Path.html#method.exists)
only checks whether or not a path was both found and readable. I think
it's ok, and we can add this information under `extra_description`.

# User-Facing Changes
The following code will no longer raise error:
```
touch a; 'a/b' | path exists
```

# Tests + Formatting
Added 1 test.
2024-09-11 12:45:39 -05:00
78af66f2ce Config: change ctrl-k to cuttolineend event (#13801)
# Description
According to emacs doc, I think `ctrl-k` should map to `cuttolineend`.

# User-Facing Changes
`ctrl-k` will no longer cut to the end of buffer
2024-09-11 12:45:12 -05:00
f63cecc316 add metadata access command (#13785)
# Description
Add `metadata access`, which allows accessing/inspecting the metadata of
a stream in a closure.
```nu
ls | metadata access {|meta|
    ...
}
```

- The metadata is provided as an argument to the closure, identical to
the record obtained with `metadata` command.

- `metadata access` passes its input stream into the closure as it is.

- Within the closure, both the metadata and the stream are available.
The closure may modify, collect or pass the stream as it is.

# Motivation
- Without this command, nu code can't act on metadata without losing the
stream, use cases requiring both the stream and metadata must be
implemented either as a built-in or a plugin.

- This command allows users to enhance presentation of data, similar to
`table` coloring the output of `ls`.
2024-09-11 12:44:06 -05:00
8d60c0d35d Migrating polars commands away from macros, removed custom DataFrame comparison. (#13829)
# Description
This PR:
- Removes the lazy_command, expr_command macros and migrates the
commands that were utilizing them.
- Removes the custom logic in DataFrameValues::is_equals to use the
polars DataFrame version of PartialEq
- Adds examples to commands that previously did not have examples or had
inadequate ones.

NOTE: A lot of examples now have a `polars sort` at the end. This is
needed due to the comparison in the result. The new polars version of
equals cares about the ordering. I removed the custom equals logic as it
causes comparisons to lock up when comparing dataframes that contain a
row that contains a list. I discovered this issue when adding examples
to `polars implode`
2024-09-11 10:33:05 -07:00
0c139c7411 Fix padding issue with header_on_border (#13808)
close #13803 

For your @amtoine  example we get

```
#┬c-a┬c-b┬c-c┬c-d─┬─c-e─
0│  1│ 12│123│1234│12345
─┴───┴───┴───┴────┴─────
```
2024-09-11 06:12:53 -05:00
c4bac90b35 Bump crate-ci/typos from 1.24.4 to 1.24.5 (#13826)
Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.24.4 to
1.24.5.
<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.24.5</h2>
<h2>[1.24.5] - 2024-09-04</h2>
<h3>Features</h3>
<ul>
<li><em>(action)</em> Support windows</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.24.5] - 2024-09-04</h2>
<h3>Features</h3>
<ul>
<li><em>(action)</em> Support windows</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="945d407a5f"><code>945d407</code></a>
chore: Release</li>
<li><a
href="e972e95d22"><code>e972e95</code></a>
docs: Update changelog</li>
<li><a
href="fcfade456a"><code>fcfade4</code></a>
Merge pull request <a
href="https://redirect.github.com/crate-ci/typos/issues/1095">#1095</a>
from zyf722/actions-windows</li>
<li><a
href="264f549c13"><code>264f549</code></a>
feat(action): Add Windows support to actions</li>
<li>See full diff in <a
href="https://github.com/crate-ci/typos/compare/v1.24.4...v1.24.5">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.24.4&new-version=1.24.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>
2024-09-11 14:35:46 +08:00
2ab8751ff9 Bump hustcer/setup-nu from 3.12 to 3.13 (#13827)
Bumps [hustcer/setup-nu](https://github.com/hustcer/setup-nu) from 3.12
to 3.13.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/hustcer/setup-nu/releases">hustcer/setup-nu's
releases</a>.</em></p>
<blockquote>
<h2>v3.13</h2>
<h2>[3.13] - 2024-09-07</h2>
<h3>Features</h3>
<ul>
<li>Add <code>aarch64_linux</code> and <code>aarch64_windows</code>
runners support</li>
</ul>
<h3>Deps</h3>
<ul>
<li>Upgrade
<code>@​octokit/rest</code>,globby,<code>@​biomejs/biome</code>,lefthook,
etc.</li>
<li>Upgrade semver,lefthook,<code>@​octokit/rest</code> and
@typescript-eslint/*</li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/hustcer/setup-nu/compare/v3.12...v3.13">https://github.com/hustcer/setup-nu/compare/v3.12...v3.13</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/hustcer/setup-nu/blob/main/CHANGELOG.md">hustcer/setup-nu's
changelog</a>.</em></p>
<blockquote>
<h2>[3.13] - 2024-09-07</h2>
<h3>Features</h3>
<ul>
<li>Add <code>aarch64_linux</code> and <code>aarch64_windows</code>
runners support</li>
</ul>
<h3>Deps</h3>
<ul>
<li>Upgrade
<code>@​octokit/rest</code>,globby,<code>@​biomejs/biome</code>,lefthook,
etc.</li>
<li>Upgrade semver,lefthook,<code>@​octokit/rest</code> and
@typescript-eslint/*</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="5dfe3b1a9e"><code>5dfe3b1</code></a>
Bump to v3.13</li>
<li><a
href="7f30320d51"><code>7f30320</code></a>
deps: Upgrade <code>@​octokit/rest</code>, lefthook and
@typescript-eslint/*</li>
<li><a
href="aed3675fdb"><code>aed3675</code></a>
deps: Upgrade semver,lefthook,<code>@​octokit/rest</code> and
@typescript-eslint/*</li>
<li><a
href="cb4476b15e"><code>cb4476b</code></a>
deps: Upgrade
<code>@​octokit/rest</code>,globby,<code>@​biomejs/biome</code>,lefthook
and <a
href="https://github.com/typescript-es"><code>@​typescript-es</code></a>...</li>
<li><a
href="25c9361cd1"><code>25c9361</code></a>
feat: Add aarch64_linux and aarch64_windows runners support</li>
<li>See full diff in <a
href="https://github.com/hustcer/setup-nu/compare/v3.12...v3.13">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=hustcer/setup-nu&package-manager=github_actions&previous-version=3.12&new-version=3.13)](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-09-11 14:35:38 +08:00
d192d854d6 Bump shadow-rs from 0.33.0 to 0.34.0 (#13825)
Bumps [shadow-rs](https://github.com/baoyachi/shadow-rs) from 0.33.0 to
0.34.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/baoyachi/shadow-rs/releases">shadow-rs's
releases</a>.</em></p>
<blockquote>
<h2>v0.34.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Make using the CARGO_METADATA object simpler by <a
href="https://github.com/baoyachi"><code>@​baoyachi</code></a> in <a
href="https://redirect.github.com/baoyachi/shadow-rs/pull/181">baoyachi/shadow-rs#181</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/baoyachi/shadow-rs/compare/v0.33.0...v0.34.0">https://github.com/baoyachi/shadow-rs/compare/v0.33.0...v0.34.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="ccb09f154b"><code>ccb09f1</code></a>
Merge pull request <a
href="https://redirect.github.com/baoyachi/shadow-rs/issues/181">#181</a>
from baoyachi/issue/179</li>
<li><a
href="65c56630da"><code>65c5663</code></a>
fix cargo clippy check</li>
<li><a
href="998d000023"><code>998d000</code></a>
Make using the CARGO_METADATA object simpler</li>
<li>See full diff in <a
href="https://github.com/baoyachi/shadow-rs/compare/v0.33.0...v0.34.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.33.0&new-version=0.34.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-09-11 14:35:27 +08:00
6b5906613c Fix remaining mismatch for env handling in IR (#13796)
# Description

This fixes a couple of remaining differences between the IR evaluator's
handling of env vars and the AST evaluator's handling of env vars.

Blocker for #13718 (this is why those tests failed)

# User-Facing Changes

1. Handles checking overlays for hidden env vars properly, when getting
an env var from IR instruction
2. Updates config properly when doing `redirect_env()` (these probably
shouldn't be separate functions anyway, though, they're basically the
same. I did this because I intended to remove one, but now it's just
like that)

# Tests + Formatting

The `nu_repl` testbin now handles `NU_USE_IR` properly, so these tests
now work as expected.

# After Submitting

- [ ] check in on #13718 again
2024-09-10 11:03:06 +08:00
493850b1bf Fix IR for try (#13811)
# Description
Fixes a bug in the IR for `try` to match that of the regular evaluator
(continuing from #13515):
```nushell
# without IR:
try { ^false } catch { 'caught' } # == 'caught'

# with IR:
try { ^false } catch { 'caught' } # error, non-zero exit code
```

In this PR, both now evaluate to `caught`. For the implementation, I had
to add another instruction, and feel free to suggest better
alternatives. In the future, it might be possible to get rid of this
extra instruction.

# User-Facing Changes
Bug fix, `try { ^false } catch { 'caught' }` now works in IR.
2024-09-09 19:44:04 -07:00
6600b3edfb Expand multiple dots in path in completions (#13725)
# Description
This is my first PR, and I'm looking for feedback to help me improve! 

This PR fixes #13380 by expanding the path prior to parsing it.
Also I've removed some unused code in
[completion_common.rs](84e92bb02c/crates/nu-cli/src/completions/completion_common.rs
)
# User-Facing Changes

Auto-completion for "cd .../" now works by expanding to "cd ../../". 

# Tests + Formatting

Formatted and added 2 tests for triple dots in the middle of a path and
at the end.
Also added a test for the expand_ndots() function.
2024-09-09 14:39:18 -04:00
aff974552a Add aarch64-unknown-linux-musl and armv7-unknown-linux-musleabihf targets to release workflow (#13800)
# Description

Add aarch64-unknown-linux-musl and armv7-unknown-linux-musleabihf
targets to release workflow. This PR and
https://github.com/nushell/nushell/pull/13775 will close:
https://github.com/nushell/nushell/issues/10444

It works well here:
https://github.com/nushell/nightly/releases/tag/nightly-2d360fd
2024-09-09 09:47:59 +08:00
2afc6a974e bump rust version to 1.79.0 (#13809)
# Description

This PR bumps our rust version from 1.78 to 1.79.0 due to the 1.81.0
release.

# 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 toolkit.nu; toolkit test stdlib"` 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-09-08 16:15:54 -05:00
1e64f59220 Added documentation explanation explaining how to select all columns with polars col (#13806)
# Description
Previously there were no examples or explanations that you can use '*'
to select all columns. Updated description and added a new example.
2024-09-08 17:12:03 +00:00
3e074bc447 Refining error handling in http post (#13805)
Related to #13701

# Description
Refining some of the error handling related to http post command
2024-09-07 23:57:34 +02:00
3d008e2c4e Error on non-zero exit statuses (#13515)
# Description
This PR makes it so that non-zero exit codes and termination by signal
are treated as a normal `ShellError`. Currently, these are silent
errors. That is, if an external command fails, then it's code block is
aborted, but the parent block can sometimes continue execution. E.g.,
see #8569 and this example:
```nushell
[1 2] | each { ^false }
```

Before this would give:
```
╭───┬──╮
│ 0 │  │
│ 1 │  │
╰───┴──╯
```

Now, this shows an error:
```
Error: nu:🐚:eval_block_with_input

  × Eval block failed with pipeline input
   ╭─[entry #1:1:2]
 1 │ [1 2] | each { ^false }
   ·  ┬
   ·  ╰── source value
   ╰────

Error: nu:🐚:non_zero_exit_code

  × External command had a non-zero exit code
   ╭─[entry #1:1:17]
 1 │ [1 2] | each { ^false }
   ·                 ──┬──
   ·                   ╰── exited with code 1
   ╰────
```

This PR fixes #12874, fixes #5960, fixes #10856, and fixes #5347. This
PR also partially addresses #10633 and #10624 (only the last command of
a pipeline is currently checked). It looks like #8569 is already fixed,
but this PR will make sure it is definitely fixed (fixes #8569).

# User-Facing Changes
- Non-zero exit codes and termination by signal now cause an error to be
thrown.
- The error record value passed to a `catch` block may now have an
`exit_code` column containing the integer exit code if the error was due
to an external command.
- Adds new config values, `display_errors.exit_code` and
`display_errors.termination_signal`, which determine whether an error
message should be printed in the respective error cases. For
non-interactive sessions, these are set to `true`, and for interactive
sessions `display_errors.exit_code` is false (via the default config).

# Tests
Added a few tests.

# After Submitting
- Update docs and book.
- Future work:
- Error if other external commands besides the last in a pipeline exit
with a non-zero exit code. Then, deprecate `do -c` since this will be
the default behavior everywhere.
- Add a better mechanism for exit codes and deprecate
`$env.LAST_EXIT_CODE` (it's buggy).
2024-09-07 06:44:26 +00:00
6c1c7f9509 Added expression support for polars cumulative (#13799)
# Description
Provides the ability to use `polars cumulative` as an expression:

<img width="1266" alt="Screenshot 2024-09-06 at 17 47 15"
src="https://github.com/user-attachments/assets/73c11f79-598c-4efa-bfcd-755e536ead66">

# User-Facing Changes
- `polars cumulative` can now be used as an expression.
2024-09-06 22:03:51 -05:00
f531cc2058 Polars command reorg (#13798)
# Description
House keeping. Restructures polars modules as discussed in:
https://docs.google.com/spreadsheets/d/1gyA58i_yTXKCJ5DbO_RxBNAlK6S7C1M22ppKwVLZltc/edit?usp=sharing
2024-09-06 13:46:37 -07:00
edd69aa283 update the latest reedline (#13797)
# Description

I swear, I only did `cargo update -p reedline`. However, I feel down the
dependency rabbit hole. We need to get nushell on crossterm 28.1 and
ratatui on 28.1 but we can't because tabled uses papergrid which uses an
older version of unicode-width that can't be upgraded apparently. Ugh.
I've opened an issue at the tabled repo about this.

# 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 toolkit.nu; toolkit test stdlib"` 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-09-06 09:57:45 -05:00
3d20c53904 make a user friendly message when use_grid_icons is used in config (#13795)
# Description
After merging #13788, I get an error message which says that
`use_grid_icons` is invalid.

I think it's good to report the specific error, and guide user to delete
it.
2024-09-06 06:39:52 -05:00
2d360fda7f String values should pass their content-type correctly on http requests with a body (e.g. http post) (#13731)
# Description
The content-type was not being handled appropriately when sending
requests with a string value.

# User-Facing Changes
- Passing a string value through a pipeline with a content-type set as
metadata is handled correctly
- Passing a string value as a parameter with a content-type set as a
flag is handled correctly.
2024-09-05 16:29:50 -07:00
d0c2adabf7 remove config use_grid_icons, move to parameter of grid command (#13788)
# Description

After looking at #13751 I noticed that the config setting
`use_grid_icons` seems out of place. So, I removed it from the config
and made it a parameter to the `grid` command.
2024-09-06 07:25:43 +08:00
870eb2530c fixed issue with find not working with symbols that should be escaped (#13792)
# Description

Thanks to @weirdan's suggestion, this now works.

![image](https://github.com/user-attachments/assets/34522c7b-b012-4f73-883d-9913142e85b9)

Closes #13789
2024-09-06 07:22:03 +08:00
b2cab3274b fix --ide-ast when there are errors (#13737)
# Description

This PR fixes #13732. However, I don't think it's a proper fix.
1. It doesn't really show what the problem is.
2. It kind of side-steps the error entirely.

I do think the change in span.rs may be valid because I don't think
span.end should ever be 0. In the example in 13732 the span end was
always 0 and so that made contains_span() return true, which seems like
a false positive.

The `checked_sub()` in ide.rs kind of just stops it from failing
outloud.

I'll leave it to smarter folks than me to land this if they think it's
worthy.
2024-09-06 07:17:40 +08:00
92091599ff Fixup serde feature selection in nu-protocol (#13793)
Discovered by @cptpiepmatz that #13749 broke the standalone check for
`nu-protocol`

Explicit use of the feature as workspace root also disables all features
for `serde`. Alternatively we could reconsider this there.
2024-09-06 00:57:36 +02:00
4d2d553cca Use String::contains instead of exact match when matching content types for http requests. (#13791)
# Description
The existing code uses exact matches on content type. This can caused
things like "application/json; charset=utf-8" that contain a charset not
using send_json method.

NOTE: The charset portion in the above example would still be ignored as
we rely on serde and the client library to control the encoding, it is
still better to catch the json case.

---------

Co-authored-by: Ian Manske <ian.manske@pm.me>
2024-09-05 13:08:19 -05:00
dc53c20628 Renamed polars concatenate and added expression support. (#13781)
# Description
In order to be more consistent with the nushell terminology and with
polars expression terminology `polars concatenate` is now `polars
str-join`. `polars str-join` can also be used as expression.

<img width="857" alt="Screenshot 2024-09-04 at 12 41 25"
src="https://github.com/user-attachments/assets/8cc5a0c2-194c-49ec-9fe1-65ec4825414d">


# User-Facing Changes
- `polars concatenate` is now `polars str-join`
- `polars str-join` can be used as an expression
2024-09-05 09:28:34 -07:00
e7c5f83460 Added expression support for polars str-lengths (#13782)
# Description
Allows `polars str-lengths` to be used as an expression:

<img width="826" alt="Screenshot 2024-09-04 at 13 57 45"
src="https://github.com/user-attachments/assets/b74139e0-e8ba-4910-84c2-cf4be4a084b6">

# User-Facing Changes
- `polars str-lengths` can be used as an expression.
- char length is now the default. Use the --bytes flag to get bytes
length.
2024-09-05 09:26:09 -07:00
f611196373 Expression support for polars str-slice (#13783)
# Description
Provides expression support for `polars str-slice`:
<img width="893" alt="Screenshot 2024-09-04 at 18 03 05"
src="https://github.com/user-attachments/assets/d8a8a2a7-53cf-4c3a-ae7a-dfdaf48a05ee">

# User-Facing Changes
- `polars str-slice` can now be used as an expression
2024-09-05 09:06:37 -07:00
abd230e12e Use IntoValue in config code (#13751)
# Description

Cleans up and refactors the config code using the `IntoValue` macro.
Shoutout to @cptpiepmatz for making the macro!

# User-Facing Changes

Should be none.

# After Submitting

Somehow refactor the reverse transformation.
2024-09-05 09:44:23 +02:00
4792328d0e Refactor send_request in client.rs (#13701)
Closes #13687
Closes #13686

# Description
Light refactoring of `send_request `in `client.rs`. In the end there are
more lines but now the logic is more concise and facilitates adding new
conditions in the future. Unit tests ran fine and I tested a few cases
manually.
Cool project btw, I'll be using nushell from now on.
2024-09-04 23:05:39 +02:00
63b94dbd28 Added expression support for polars contains (#13769)
# Description
Adds the ability to use `polars contains` as an expression:
<img width="785" alt="Screenshot 2024-09-03 at 14 39 03"
src="https://github.com/user-attachments/assets/35c0d4e5-6bef-4974-a31f-463c7203bd03">


# User-Facing Changes
- `polars contains` can now be used with expressions
2024-09-04 12:19:45 +02:00
eb0de25d19 Expression support for polars strftime (#13767)
# Description
Allows `polars strftime` to be used as an expression:
<img width="849" alt="Screenshot 2024-09-03 at 13 14 11"
src="https://github.com/user-attachments/assets/2a987fdf-cf00-4c57-b6e1-0b706c594c20">

# User-Facing Changes
- `polars strftime` can now be used as an expression.
2024-09-04 12:19:29 +02:00
ebe42241fe Add #[nu_value(rename = "...")] as helper attribute on members for derive macros (#13761)
# Description

This PR allows the helper attribute `nu_value(rename = "...")` to be
used on struct fields and enum variants. This allows renaming keys and
variants just like [`#[serde(rename =
"name")]`](https://serde.rs/field-attrs.html#rename). This has no
singular variants for `IntoValue` or `FromValue`, both need to use the
same (but I think this shouldn't be an issue for now).

# User-Facing Changes

Users of the derive macros `IntoValue` and `FromValue` may now use
`#[nu_value(rename = "...")]` to rename single fields, but no already
existing code will break.
2024-09-04 11:27:21 +02:00
fa4f9b083e Bump crate-ci/typos from 1.24.1 to 1.24.4 (#13770)
Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.24.1 to
1.24.4.
<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.24.4</h2>
<h2>[1.24.4] - 2024-09-03</h2>
<h3>Fixes</h3>
<ul>
<li>Offer a correction for <code>grather</code></li>
</ul>
<h2>v1.24.3</h2>
<h2>[1.24.3] - 2024-08-30</h2>
<h3>Fixes</h3>
<ul>
<li>Updated the dictionary with the <a
href="https://redirect.github.com/crate-ci/typos/issues/1069">August
2024</a> changes</li>
</ul>
<h2>v1.24.2</h2>
<h2>[1.24.2] - 2024-08-30</h2>
<h3>Performance</h3>
<ul>
<li>Cap unbounded parsing to avoid worst case performance (hit with test
data)</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.24.4] - 2024-09-03</h2>
<h3>Fixes</h3>
<ul>
<li>Offer a correction for <code>grather</code></li>
</ul>
<h2>[1.24.3] - 2024-08-30</h2>
<h3>Fixes</h3>
<ul>
<li>Updated the dictionary with the <a
href="https://redirect.github.com/crate-ci/typos/issues/1069">August
2024</a> changes</li>
</ul>
<h2>[1.24.2] - 2024-08-30</h2>
<h3>Performance</h3>
<ul>
<li>Cap unbounded parsing to avoid worst case performance (hit with test
data)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="853bbe8898"><code>853bbe8</code></a>
chore: Release</li>
<li><a
href="b5f56600b2"><code>b5f5660</code></a>
docs: Update changelog</li>
<li><a
href="39f678e520"><code>39f678e</code></a>
Merge pull request <a
href="https://redirect.github.com/crate-ci/typos/issues/1093">#1093</a>
from kachick/grather-suggest-candidates</li>
<li><a
href="bb6905fdc9"><code>bb6905f</code></a>
Merge pull request <a
href="https://redirect.github.com/crate-ci/typos/issues/1092">#1092</a>
from crate-ci/renovate/embarkstudios-cargo-deny-acti...</li>
<li><a
href="786c825f17"><code>786c825</code></a>
fix(dict): Add suggestions for the typo &quot;grather&quot;</li>
<li><a
href="340058181b"><code>3400581</code></a>
chore(deps): Update EmbarkStudios/cargo-deny-action action to v2</li>
<li><a
href="9ad6f5c054"><code>9ad6f5c</code></a>
chore: Release</li>
<li><a
href="12e101ec51"><code>12e101e</code></a>
docs: Update changelog</li>
<li><a
href="8c58591ec4"><code>8c58591</code></a>
Merge pull request <a
href="https://redirect.github.com/crate-ci/typos/issues/1091">#1091</a>
from epage/august</li>
<li><a
href="250dcc73e6"><code>250dcc7</code></a>
fix(dict): Aug updates</li>
<li>Additional commits viewable in <a
href="https://github.com/crate-ci/typos/compare/v1.24.1...v1.24.4">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.24.1&new-version=1.24.4)](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-09-04 10:03:07 +08:00
e7b7c7f39a Bump nix from 0.28.0 to 0.29.0 (#13773)
Bumps [nix](https://github.com/nix-rust/nix) from 0.28.0 to 0.29.0.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/nix-rust/nix/blob/master/CHANGELOG.md">nix's
changelog</a>.</em></p>
<blockquote>
<h2>[0.29.0] - 2024-05-24</h2>
<h3>Added</h3>
<ul>
<li>Add <code>getregset()/setregset()</code> for
Linux/glibc/x86/x86_64/aarch64/riscv64 and
<code>getregs()/setregs()</code> for Linux/glibc/aarch64/riscv64
(<a
href="https://redirect.github.com/nix-rust/nix/pull/2044">#2044</a>)</li>
<li>Add socket option Ipv6Ttl for apple targets.
(<a
href="https://redirect.github.com/nix-rust/nix/pull/2287">#2287</a>)</li>
<li>Add socket option UtunIfname.
(<a
href="https://redirect.github.com/nix-rust/nix/pull/2325">#2325</a>)</li>
<li>make SigAction repr(transparent) &amp; can be converted to the libc
raw type
(<a
href="https://redirect.github.com/nix-rust/nix/pull/2326">#2326</a>)</li>
<li>Add <code>From</code> trait implementation for conversions between
<code>sockaddr_in</code> and
<code>SockaddrIn</code>, <code>sockaddr_in6</code> and
<code>SockaddrIn6</code>
(<a
href="https://redirect.github.com/nix-rust/nix/pull/2328">#2328</a>)</li>
<li>Add socket option ReusePortLb for FreeBSD.
(<a
href="https://redirect.github.com/nix-rust/nix/pull/2332">#2332</a>)</li>
<li>Added support for openat2 on linux.
(<a
href="https://redirect.github.com/nix-rust/nix/pull/2339">#2339</a>)</li>
<li>Add if_indextoname function.
(<a
href="https://redirect.github.com/nix-rust/nix/pull/2340">#2340</a>)</li>
<li>Add <code>mount</code> and <code>unmount</code> API for apple
targets.
(<a
href="https://redirect.github.com/nix-rust/nix/pull/2347">#2347</a>)</li>
<li>Added <code>_PC_MIN_HOLE_SIZE</code> for <code>pathconf</code> and
<code>fpathconf</code>.
(<a
href="https://redirect.github.com/nix-rust/nix/pull/2349">#2349</a>)</li>
<li>Added <code>impl AsFd for pty::PtyMaster</code>
(<a
href="https://redirect.github.com/nix-rust/nix/pull/2355">#2355</a>)</li>
<li>Add <code>open</code> flag <code>O_SEARCH</code> to AIX,
Empscripten, FreeBSD, Fuchsia, solarish,
WASI (<a
href="https://redirect.github.com/nix-rust/nix/pull/2374">#2374</a>)</li>
<li>Add prctl function <code>prctl_set_vma_anon_name</code> for
Linux/Android.
(<a
href="https://redirect.github.com/nix-rust/nix/pull/2378">#2378</a>)</li>
<li>Add <code>sync(2)</code> for
<code>apple_targets/solarish/haiku/aix/hurd</code>,
<code>syncfs(2)</code> for
<code>hurd</code> and <code>fdatasync(2)</code> for
<code>aix/hurd</code>
(<a
href="https://redirect.github.com/nix-rust/nix/pull/2379">#2379</a>)</li>
<li>Add fdatasync support for Apple targets.
(<a
href="https://redirect.github.com/nix-rust/nix/pull/2380">#2380</a>)</li>
<li>Add <code>fcntl::OFlag::O_PATH</code> for FreeBSD and Fuchsia
(<a
href="https://redirect.github.com/nix-rust/nix/pull/2382">#2382</a>)</li>
<li>Added <code>PathconfVar::MIN_HOLE_SIZE</code> for apple_targets.
(<a
href="https://redirect.github.com/nix-rust/nix/pull/2388">#2388</a>)</li>
<li>Add <code>open</code> flag <code>O_SEARCH</code> to apple_targets
(<a
href="https://redirect.github.com/nix-rust/nix/pull/2391">#2391</a>)</li>
<li><code>O_DSYNC</code> may now be used with <code>aio_fsync</code> and
<code>fcntl</code> on FreeBSD.
(<a
href="https://redirect.github.com/nix-rust/nix/pull/2404">#2404</a>)</li>
<li>Added <code>Flock::relock</code> for upgrading and downgrading
locks.
(<a
href="https://redirect.github.com/nix-rust/nix/pull/2407">#2407</a>)</li>
</ul>
<h3>Changed</h3>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="1dad4d8d04"><code>1dad4d8</code></a>
chore: prepare for 0.29.0</li>
<li><a
href="f7431971b4"><code>f743197</code></a>
fix ControlMessageOwned::UdpGroSegments UDP packets processing type. (<a
href="https://redirect.github.com/nix-rust/nix/issues/2406">#2406</a>)</li>
<li><a
href="208b80b65d"><code>208b80b</code></a>
recvmsg: Check if CMSG buffer was too small and return an error (<a
href="https://redirect.github.com/nix-rust/nix/issues/2413">#2413</a>)</li>
<li><a
href="ecd12a9990"><code>ecd12a9</code></a>
test: remove test of inode count in test_statfs.rs (<a
href="https://redirect.github.com/nix-rust/nix/issues/2414">#2414</a>)</li>
<li><a
href="663506a602"><code>663506a</code></a>
fix: only close <code>fanotify</code> events with a valid fd (<a
href="https://redirect.github.com/nix-rust/nix/issues/2399">#2399</a>)</li>
<li><a
href="1604723757"><code>1604723</code></a>
revert: impl From&lt;sigaction&gt; for SigAction (<a
href="https://redirect.github.com/nix-rust/nix/issues/2410">#2410</a>)</li>
<li><a
href="ec4beb5a22"><code>ec4beb5</code></a>
docs: correct limit value of FAN_UNLIMITED_QUEUE and
FAN_UNLIMITED_MARKS[skip...</li>
<li><a
href="84c0444c3a"><code>84c0444</code></a>
chore: bump libc to 0.2.155 (<a
href="https://redirect.github.com/nix-rust/nix/issues/2409">#2409</a>)</li>
<li><a
href="c5af4adffd"><code>c5af4ad</code></a>
Add Flock::relock (<a
href="https://redirect.github.com/nix-rust/nix/issues/2407">#2407</a>)</li>
<li><a
href="e7acaff07f"><code>e7acaff</code></a>
Enable O_DSYNC on FreeBSD with fcntl and aio_fsync (<a
href="https://redirect.github.com/nix-rust/nix/issues/2404">#2404</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/nix-rust/nix/compare/v0.28.0...v0.29.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=nix&package-manager=cargo&previous-version=0.28.0&new-version=0.29.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-09-04 10:03:02 +08:00
6be458c686 Bump itertools from 0.12.1 to 0.13.0 (#13774)
Bumps [itertools](https://github.com/rust-itertools/itertools) from
0.12.1 to 0.13.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.13.0</h2>
<h3>Breaking</h3>
<ul>
<li>Removed implementation of <code>DoubleEndedIterator</code> for
<code>ConsTuples</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/853">#853</a>)</li>
<li>Made <code>MultiProduct</code> fused and fixed on an empty iterator
(<a
href="https://redirect.github.com/rust-itertools/itertools/issues/835">#835</a>,
<a
href="https://redirect.github.com/rust-itertools/itertools/issues/834">#834</a>)</li>
<li>Changed <code>iproduct!</code> to return tuples for maxi one
iterator too (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/870">#870</a>)</li>
<li>Changed <code>PutBack::put_back</code> to return the old value (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/880">#880</a>)</li>
<li>Removed deprecated <code>repeat_call, Itertools::{foreach, step,
map_results, fold_results}</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/878">#878</a>)</li>
<li>Removed <code>TakeWhileInclusive::new</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/912">#912</a>)</li>
</ul>
<h3>Added</h3>
<ul>
<li>Added <code>Itertools::{smallest_by, smallest_by_key, largest,
largest_by, largest_by_key}</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/654">#654</a>,
<a
href="https://redirect.github.com/rust-itertools/itertools/issues/885">#885</a>)</li>
<li>Added <code>Itertools::tail</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/899">#899</a>)</li>
<li>Implemented <code>DoubleEndedIterator</code> for
<code>ProcessResults</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/910">#910</a>)</li>
<li>Implemented <code>Debug</code> for <code>FormatWith</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/931">#931</a>)</li>
<li>Added <code>Itertools::get</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/891">#891</a>)</li>
</ul>
<h3>Changed</h3>
<ul>
<li>Deprecated <code>Itertools::group_by</code> (renamed
<code>chunk_by</code>) (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/866">#866</a>,
<a
href="https://redirect.github.com/rust-itertools/itertools/issues/879">#879</a>)</li>
<li>Deprecated <code>unfold</code> (use <code>std::iter::from_fn</code>
instead) (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/871">#871</a>)</li>
<li>Optimized <code>GroupingMapBy</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/873">#873</a>,
<a
href="https://redirect.github.com/rust-itertools/itertools/issues/876">#876</a>)</li>
<li>Relaxed <code>Fn</code> bounds to <code>FnMut</code> in
<code>diff_with, Itertools::into_group_map_by</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/886">#886</a>)</li>
<li>Relaxed <code>Debug/Clone</code> bounds for <code>MapInto</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/889">#889</a>)</li>
<li>Documented the <code>use_alloc</code> feature (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/887">#887</a>)</li>
<li>Optimized <code>Itertools::set_from</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/888">#888</a>)</li>
<li>Removed badges in <code>README.md</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/890">#890</a>)</li>
<li>Added &quot;no-std&quot; categories in <code>Cargo.toml</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/894">#894</a>)</li>
<li>Fixed <code>Itertools::k_smallest</code> on short unfused iterators
(<a
href="https://redirect.github.com/rust-itertools/itertools/issues/900">#900</a>)</li>
<li>Deprecated <code>Itertools::tree_fold1</code> (renamed
<code>tree_reduce</code>) (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/895">#895</a>)</li>
<li>Deprecated <code>GroupingMap::fold_first</code> (renamed
<code>reduce</code>) (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/902">#902</a>)</li>
<li>Fixed <code>Itertools::k_smallest(0)</code> to consume the iterator,
optimized <code>Itertools::k_smallest(1)</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/909">#909</a>)</li>
<li>Specialized <code>Combinations::nth</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/914">#914</a>)</li>
<li>Specialized <code>MergeBy::fold</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/920">#920</a>)</li>
<li>Specialized <code>CombinationsWithReplacement::nth</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/923">#923</a>)</li>
<li>Specialized <code>FlattenOk::{fold, rfold}</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/927">#927</a>)</li>
<li>Specialized <code>Powerset::nth</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/924">#924</a>)</li>
<li>Documentation fixes (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/882">#882</a>,
<a
href="https://redirect.github.com/rust-itertools/itertools/issues/936">#936</a>)</li>
<li>Fixed <code>assert_equal</code> for iterators longer than
<code>i32::MAX</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/932">#932</a>)</li>
<li>Updated the <code>must_use</code> message of non-lazy
<code>KMergeBy</code> and <code>TupleCombinations</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/939">#939</a>)</li>
</ul>
<h3>Notable Internal Changes</h3>
<ul>
<li>Tested iterator laziness (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/792">#792</a>)</li>
<li>Created <code>CONTRIBUTING.md</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/767">#767</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="d5084d15e9"><code>d5084d1</code></a>
Prepare v0.13.0 release (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/937">#937</a>)</li>
<li><a
href="d7c99d55da"><code>d7c99d5</code></a>
<code>TupleCombinations</code> is not lazy but must be used
nonetheless</li>
<li><a
href="074c7fcc07"><code>074c7fc</code></a>
<code>KMergeBy</code> is not lazy but must be used nonetheless</li>
<li><a
href="2ad9e07ae8"><code>2ad9e07</code></a>
<code>assert_equal</code>: fix
<code>clippy::default_numeric_fallback</code></li>
<li><a
href="0d4efc8432"><code>0d4efc8</code></a>
Remove free function <code>get</code></li>
<li><a
href="05cc0ee256"><code>05cc0ee</code></a>
<code>get(s..=usize::MAX)</code> should be fine when <code>s !=
0</code></li>
<li><a
href="3c16f14baa"><code>3c16f14</code></a>
<code>get</code>: when is it ESI and/or DEI</li>
<li><a
href="4dd6ba0e7c"><code>4dd6ba0</code></a>
<code>get</code>: panics if the range includes
<code>usize::MAX</code></li>
<li><a
href="7a9ce56fc5"><code>7a9ce56</code></a>
<code>get(r: Range)</code> as <code>Skip\&lt;Take&gt;</code></li>
<li><a
href="f676f2f964"><code>f676f2f</code></a>
Remove the unspecified check about
<code>.get(exhausted_range_inclusive)</code></li>
<li>Additional commits viewable in <a
href="https://github.com/rust-itertools/itertools/compare/v0.12.1...v0.13.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.12.1&new-version=0.13.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-09-04 10:02:48 +08:00
348c59b740 Bump indexmap from 2.4.0 to 2.5.0 (#13772)
Bumps [indexmap](https://github.com/indexmap-rs/indexmap) from 2.4.0 to
2.5.0.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/indexmap-rs/indexmap/blob/master/RELEASES.md">indexmap's
changelog</a>.</em></p>
<blockquote>
<h2>2.5.0</h2>
<ul>
<li>Added an <code>insert_before</code> method to <code>IndexMap</code>
and <code>IndexSet</code>, as an
alternative to <code>shift_insert</code> with different behavior on
existing entries.</li>
<li>Added <code>first_entry</code> and <code>last_entry</code> methods
to <code>IndexMap</code>.</li>
<li>Added <code>From</code> implementations between
<code>IndexedEntry</code> and <code>OccupiedEntry</code>.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="48ed49017c"><code>48ed490</code></a>
Release 2.5.0</li>
<li><a
href="139d7addfb"><code>139d7ad</code></a>
Merge pull request <a
href="https://redirect.github.com/indexmap-rs/indexmap/issues/340">#340</a>
from cuviper/insert-bounds</li>
<li><a
href="1d9b5e3d03"><code>1d9b5e3</code></a>
Add doc examples for <code>insert_before</code> and
<code>shift_insert</code></li>
<li><a
href="8ca01b0df7"><code>8ca01b0</code></a>
Use <code>insert_before</code> for &quot;new&quot; entries in
<code>insert_sorted</code></li>
<li><a
href="7224def010"><code>7224def</code></a>
Add <code>insert_before</code> as an alternate to
<code>shift_insert</code></li>
<li><a
href="0247a1555d"><code>0247a15</code></a>
Document and assert index bounds in <code>shift_insert</code></li>
<li><a
href="922c6ad1af"><code>922c6ad</code></a>
Update the CI badge</li>
<li><a
href="e482e1768a"><code>e482e17</code></a>
Merge pull request <a
href="https://redirect.github.com/indexmap-rs/indexmap/issues/342">#342</a>
from cuviper/btree-like</li>
<li><a
href="b63e4a1556"><code>b63e4a1</code></a>
Merge pull request <a
href="https://redirect.github.com/indexmap-rs/indexmap/issues/341">#341</a>
from cuviper/from-entry</li>
<li><a
href="264e5b7304"><code>264e5b7</code></a>
Add doc aliases like <code>BTreeMap</code>/<code>BTreeSet</code></li>
<li>Additional commits viewable in <a
href="https://github.com/indexmap-rs/indexmap/compare/2.4.0...2.5.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=indexmap&package-manager=cargo&previous-version=2.4.0&new-version=2.5.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-09-04 10:02:01 +08:00
2c827d2bf4 Try to add aarch64-unknown-linux-musl and armv7-unknown-linux-musleabihf release target (#13775)
Related: https://github.com/nushell/nushell/issues/10444

<!--
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
Try to add `aarch64-unknown-linux-musl` and
`armv7-unknown-linux-musleabihf` release target
I will test these two new targets in the nightly workflow, It should
work:
https://github.com/nushell/nightly/actions/runs/10692449465/job/29640875827,
and check the release binaries. If everything goes well we can add the
`musl` targets in the next release
2024-09-04 09:28:00 +08:00
61544eecd6 add version and path to plugin executable help (#13764)
# Description

This change allows one to see the version of their plugin file without
trying to register it.


![image](https://github.com/user-attachments/assets/9f1ddbd7-f63f-47f7-87c8-0d839f5e4b1f)


# 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 toolkit.nu; toolkit test stdlib"` 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-09-03 12:46:36 -05:00
c150af4279 Don't panic on detect columns with --guess flag (#13752)
# Description
This pr addresses the comment:
https://github.com/nushell/nushell/issues/11791#issuecomment-2308384155

It's caused by if the last row have a very different format to the first
row, the value of `end_char` will exceed the `line_char_boundaries`.
Adding a guard for it should avoid such panic.

# User-Facing Changes
The following code should no longer panic:
```shell
"nu_plugin_highlight = '1.2.2+0.97.1'    # A nushell plugin for syntax highlighting
trace_nu_plugin = '0.3.1'               # A wrapper to trace Nu plugins
nu_plugin_bash_env = '0.13.0'           # Nu plugin bash-env
nu_plugin_from_sse = '0.4.0'            # Nushell plugin to convert a HTTP server sent event stream to structured data
... and 90 crates more (use --limit N to see more)" | detect columns -n --guess
```

# Tests + Formatting
Added 1 test.
2024-09-02 16:29:53 +02:00
39bda8986e Make tee work more nicely with non-collections (#13652)
# Description

This changes the behavior of `tee` to be more transparent when given a
value that isn't a list or range. Previously, anything that wasn't a
byte stream would converted to a list stream using the iterator
implementation, which led to some surprising results. Instead, now, if
the value is a string or binary, it will be treated the same way a byte
stream is, and the output of `tee` is a byte stream instead of the
original value. This is done so that we can synchronize with the other
thread on collect, and potentially capture any error produced by the
closure.

For values that can't be converted to streams, the closure is just run
with a clone of the value instead on another thread. Because we can't
wait for the other thread, there is no way to send an error back to the
original thread, so instead it's just written to stderr using
`report_error_new()`.

There are a couple of follow up edge cases I see where byte streams
aren't necessarily treated exactly the same way strings are, but this
should mostly be a good experience.

Fixes #13489.

# User-Facing Changes

Breaking change.

- `tee` now outputs and sends string/binary stream for string/binary
input.
- `tee` now outputs and sends the original value for any other input
other than lists/ranges.

# Tests + Formatting

Added for new behavior.

# After Submitting

- [ ] release notes: breaking change, command change
2024-09-01 19:03:46 +02:00
ee997ef3dd Remove unneeded serde feature on byte-unit dep (#13749)
removing the `std` feature as well would drop some dependencies tied to
`rust_decimal` from the `Cargo.lock` but unclear to me what the actual
impact on compile times is.

We may want to consider dropping the `byte-unit` dependency altogether
as we have a significant fraction of our own logic to support the byte
units with 1024 and 1000 prefixes. Not sure which fraction is covered by
us or the dependency.
2024-09-01 19:02:28 +02:00
e3f59910b8 Implement IntoValue for more types (#13744)
# Description

Implements `IntoValue` for `&str` and `DateTime` as well as other
nushell types like `Record` and `Closure`. Also allows `HashMap`s with
keys besides `String` to implement `IntoValue`.
2024-09-01 19:02:12 +02:00
f4940e115f Remove bincode and use MessagePack instead for plugin custom values (#13745)
# Description

This changes the serialization of custom values within the plugin
protocol to use MessagePack instead of bincode, removing the dependency
on bincode entirely.

Bincode does not seem to be very maintained anymore, and the externally
tagged enum representation doesn't seem to always work now even though
it should. Since we use MessagePack already anyway for the plugin
protocol, this seems like an obvious choice. This uses the unnamed
variant of the serialization rather than the named variant, which is
what the plugin protocol in general uses. The unnamed variant does not
include field names, which aren't really required here, so this should
give us something that's more or less as efficient as bincode is.

Should fix #13743.

# User-Facing Changes

- Will need to recompile plugins (but always do anyway)
- Doesn't technically break the plugin protocol (custom value data is a
black box / plugin implementation specific), but breaks compatibility
between `nu-plugin-engine` and `nu-plugin` so they do need to both be
updated to match.

# Tests + Formatting

All tests pass.

# After Submitting

- [ ] release notes
2024-09-01 17:33:10 +02:00
3f31ca7b8e remove cfg_atter tarpaulin (#13739)
# Description

Remove the `#[cfg_attr(tarpaulin, ignore)]` code coverage attributes to
get rid warnings when compiling plugins with a more recent rust version
than nushell.
2024-08-31 16:45:15 +02:00
0119534f61 Expression support polars replace and polars replace-all (#13726)
# Description
Adds the ability for `polars replace` and `polars replace-all` to work
as expressions.

# User-Facing Changes
- `polars replace` can be used with polars expressions
- `polars replace-all` can be used with polars expressions
2024-08-29 13:59:44 -07:00
84e1ac27e5 Setup global cargo lint configuration (#13691)
# Description
`cargo` somewhat recently gained the capability to store `lints`
settings for the crate and workspace, that can override the defaults
from `rustc` and `clippy` lints. This means we can enforce some lints
without having to actively pass them to clippy via `cargo clippy -- -W
...`. So users just forking the repo have an easier time to follow
similar requirements like our CI.

## Limitation

An exception that remains is that those lints apply to both the primary
code base and the tests. Thus we can't include e.g. `unwrap_used`
without generating noise in the tests. Here the setup in the CI remains
the most helpful.

## Included lints

- Add `clippy::unchecked_duration_subtraction` (added by #12549)
# User-Facing Changes
Running `cargo clippy --workspace` should be closer to the CI. This has
benefits for editor configured runs of clippy and saves you from having
to use `toolkit` to be close to CI in more cases.
2024-08-28 23:37:17 +02:00
644bebf4c6 Expression support for polars uppercase and polars lowercase (#13724) 2024-08-28 14:08:16 -07:00
f58a4b5017 Add split cell-path (#13705)
this PR should close #12168

# Description
Add `split cell-path`, inverse of `into cell-path`.

# User-Facing Changes
Currently there is no way to make use of cell-path values as a user,
other than passing them to builtin commands. This PR makes more use
cases possible.
2024-08-28 23:01:26 +02:00
ae0e13733d Fix parsing record values containing colons (#13413)
This PR is an attempt to fix #8257 and fix #10985 (which is
duplicate-ish)

# Description
The parser currently doesn't know how to deal with colons appearing
while lexing whitespace-terminated tokens specifying a record value.
Most notably, this means you can't use datetime literals in record value
position (and as a consequence, `| to nuon | from nuon` roundtrips can
fail), but it also means that bare words containing colons cause a
non-useful error message.

![image](https://github.com/user-attachments/assets/f04a8417-ee18-44e7-90eb-a0ecef943a0f)

`parser::parse_record` calls `lex::lex` with the `:` colon character in
the `special_tokens` argument. This allows colons to terminate record
keys, but as a side effect, it also causes colons to terminate record
*values*. I added a new function `lex::lex_n_tokens`, which allows the
caller to drive the lexing process more explicitly, and used it in
`parser::parse_record` to let colons terminate record keys while not
giving them special treatment when appearing in record values.

This PR description previously said: *Another approach suggested in one
of the issues was to support an additional datetime literal format that
doesn't require colons. I like that that wouldn't require new
`lex::lex_internal` behaviour, but an advantage of my approach is that
it also newly allows for string record values given as bare words
containing colons. I think this eliminates another possible source of
confusion.* It was determined that this is undesirable, and in the
current state of this PR, bare word record values with colons are
rejected explicitly. The better error message is still a win.

# User-Facing Changes
In addition to the above, this PR also disables the use of "special"
(non-item) tokens in record key and value position, and the use of a
single bare `:` as a record key.

Examples of behaviour *before* this PR:
```nu
{ a: b } # Valid, same as { 'a': 'b' }
{ a: b:c } # Error: expected ':'
{ a: 2024-08-13T22:11:09 } # Error: expected ':'
{ :: 1 } # Valid, same as { ':': 1 }
{ ;: 1 } # Valid, same as { ';': 1 }
{ a: || } # Valid, same as { 'a': '||' }
```

Examples of behaviour *after* this PR:
```nu
{ a: b } # (Unchanged) Valid, same as { 'a': 'b' }
{ a: b:c } # Error: colon in bare word specifying record value
{ a: 2024-08-13T22:11:09 } # Valid, same as { a: (2024-08-13T22:11:09) }
{ :: 1 } # Error: colon in bare word specifying record key
{ ;: 1 } # Error: expected item in record key position
{ a: || } # Error: expected item in record value position
```

# Tests + Formatting
I added tests, but I'm not sure if they're sufficient and in the right
place.

# After Submitting
I don't think documentation changes are needed for this, but please let
me know if you disagree.
2024-08-28 22:53:56 +02:00
2c379cba71 Remove system-clipboard from the default build (#13694)
# Description
This feature tried to connect reedline with the system clipboard for
three special bindings.
To do so it uses the `arboard` crate with heavy dependencies for the
system X or Wayland server or the Windows APIs. We had issues in the
headless CI with it and builds with musl seem to stall.

Removing it from the default build should negatively impact only a small
subset of users aware of the extra bindings. You can still use the
internal clipboard for binding based selection and the terminals extra
bindings to copy arbitrary content into the system clipboard.

For all other users it removes potential sources of failure and a whole
1 MB of release mode binary size (> 2% reduction). Furthermore a
potentially substantial attack surface for Nushell is gone for default
builds.

- Should resolve #13019
- Work in the spirit of #13603


# User-Facing Changes

The `edit` entries
`copyselectionsystem`/`copyselectionsystem`/`pastesystem` for
keybindings are gone in the default build

If you strictly depend on this behavior, you can still build with the
addition of `--features system-clipboard`
2024-08-28 22:19:13 +02:00
7171c9b84a Bump shadow-rs from 0.31.1 to 0.33.0 (#13713) 2024-08-28 13:05:11 +00:00
055d7e27e9 Use heck instead of convert_case for nu-derive-value (#13708)
<!--
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.
-->
@sholderbach mentioned that I introduced `convert_case` as a dependency
while we already had `heck` for case conversion. So in this PR replaced
the use `convert_case` with `heck`. Mostly I rebuilt the `convert_case`
API with `heck` to work with it as I like the API of `convert_case` more
than `heck`.

# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->
Nothing changed, the use of `convert_case` wasn't exposed anywhere and
all case conversions are still available.

# 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 toolkit.nu; toolkit test stdlib"` 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
> ```
-->
No new tests required but my tests in `test_derive` captured some errors
I made while developing this change, (hurray, tests work 🎉)
- 🟢 `toolkit fmt`
- 🟢 `toolkit clippy`
- 🟢 `toolkit test`
- 🟢 `toolkit test stdlib`

# After Submitting
<!-- If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
-->
2024-08-28 08:02:25 -05:00
af76e11dd6 Remove str deunicode (#13693)
# Description
Closes #13677

Remove the command `str deunicode`, as it has a narrow application, is
loosely defined by the data provided by the `deunicode` crate and thus a
stabilization liability post-1.0.

Furthermore the data to perform the look-up is quite substantial.

Removing the command and the `deunicode` dependency saves 0.9 MB of
binary data in release mode (~ 2% of total)

(checked via `cargo bloat --release` for a linux x86 build)


# User-Facing Changes
The `str deunicode` command recently added in #13270 is gone
2024-08-28 07:58:38 -05:00
7dda39a89e Simplify our bug reporting form (#13695)
The two additional boxes for "additional context" and screenshots may be
somewhat redundant to the primary `Steps to reproduce`. Sadly folks are
already a bit lazy with the core task of providing a succinct
reproducing example. Having additional fields may not actually improve
the quality and lead to waffling or if left empty some deadspace to
scroll past.
2024-08-28 07:58:10 -05:00
4f822e263f Respect user-defined $env.NU_LOG_FORMAT and $env.NU_LOG_DATE_FORMAT (#13692)
Fixes nushell/nushell#13689

# Description

Respect user-defined `$env.NU_LOG_FORMAT` and `$env.NU_LOG_DATE_FORMAT`

Additionally I fixed `nu_with_std!()` macro (it was not working
correctly)

# User-Facing Changes

Users now may set `$env.NU_LOG_FORMAT` and `$env.NU_LOG_DATE_FORMAT` in
`env.nu` and it will work even if `use std` is used after that.

# Tests + Formatting

Added a couple of tests for the new functionality.

# After Submitting
2024-08-28 07:57:43 -05:00
a39e94de8a Added polars commands for converting string columns to integer and decimal columns (#13711)
# Description
Introduces two new polars commands for converting string columns to
decimal and integer columns:

<img width="740" alt="Screenshot 2024-08-27 at 15 32 28"
src="https://github.com/user-attachments/assets/f9573b6e-48f6-4bbf-8782-39ffb95eb934">

<img width="720" alt="Screenshot 2024-08-27 at 15 33 46"
src="https://github.com/user-attachments/assets/90a66bb5-fa78-4ed3-8b2b-ae05cddd2f3a">

# User-Facing Changes
- Addition of the `polars integer` command
- Addition of the `polars decimal` command
2024-08-28 07:54:31 -05:00
a88f46c6c9 update virtual terminal processing (#13710)
# Description

With Windows Terminal Canary 1.23.240826001-llm, this enables nushell to
query the terminal and receive a response.


![image](https://github.com/user-attachments/assets/c4c43328-c431-47e4-b377-8b3a2bc12b74)

The red component here is
```nushell
❯ ("0c0c" | into int -r 16) / 256 | math round | fmt | get lowerhex
0xc
```

This example queries the background and the response is a r/g/b color.
The response really should be
```
␛]11;1;rgb:0c0c/0c0c/0c0c
```
I'm not sure why nushell's input is eating the first part.

# 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 toolkit.nu; toolkit test stdlib"` 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-08-28 07:54:01 -05:00
4ca1f95b6c Bump crate-ci/typos from 1.23.6 to 1.24.1 (#13716) 2024-08-28 12:36:03 +00:00
71ced35987 Changed category for panic and added search terms and examples (#13707)
# Description
Cosmetic changes around `panic` command. Changed category, added search
terms, and examples.

# User-Facing Changes
See above
2024-08-27 16:58:05 -07:00
1128df2d29 Added record key renaming for derive macros IntoValue and FromValue (#13699)
# Description

Using derived `IntoValue` and `FromValue` implementations on structs
with named fields currently produce `Value::Record`s where each key is
the key of the Rust struct. For records like the `$nu` constant, that
won't work as this record uses `kebab-case` for it's keys. To accomodate
this, I upgraded the `#[nu_value(rename_all = "...")]` helper attribute
to also work on structs with named fields which will rename the keys via
the same case conversion as the enums already have.

# User-Facing Changes
Users of these macros may choose different key styles for their in
`Value` representation.

# Tests + Formatting
I added the same test suite as enums already have and updated the traits
documentation with more examples that also pass the doc test.

# After Submitting
I played around with the `$nu` constant but got stuck at the point that
these keys are kebab-cased, with this, I can play around more with it.
2024-08-27 20:00:44 +02:00
da98c23ab3 Use right options in custom completions (#13698)
<!--
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 issue was reported by kira in
[Discord](https://discord.com/channels/601130461678272522/1276981416307069019).
In https://github.com/nushell/nushell/pull/13311, I accidentally made it
so that custom completions are filtered according to the user's
configured completion options (`$env.config.completions`) rather than
the completion options provided as part of the custom completions. This
PR is a quick fix for that.

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

It should once again be possible to override match algorithm, case
sensitivity, and substring matching (`positional`) in custom
completions.

# 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 toolkit.nu; toolkit test stdlib"` to run the
tests for the standard library

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

Added a couple tests.

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

fdncred and I discussed this in Discord a bit and we thought it might be
better to not allow custom completions to override the user's config.
However, `positional` can't currently be set inside one's config, so you
can only do strict prefix matching, no substring matching. Another PR
could do one of the following:
- Document the fact that you can provide completion options inside
custom completions
- Remove the ability to provide completion options with custom
completions and add a `$env.config.completions.positional: true` option
- Remove the ability to provide completion options with custom
completions and add a new match algorithm `substring` (this is the one I
like most, since `positional` only applies to prefix matching anyway)

Separately from these options, we could also allow completers to specify
that they don't Nushell to do any filtering and sorting on the provided
custom completions.
2024-08-26 12:14:57 -05:00
e3efc8da9f Remove unnecessary sort in explore search fn (#13690)
Noticed when playing with the `stable_sort_primitive` lint that the
elements from `enumerate` are already sorted.
2024-08-25 20:13:05 +02:00
3f332bef35 Fix encode/decode todo's (#13683)
Mistakes have been made. I forgot about a bunch of `todo`s in the helper
functions. So, this PR replaces them with proper errors. It also adds
tests for parse-time evaluation, because one `todo` I missed was in a
`run_const` function.
2024-08-24 09:02:02 -05:00
525eac1afd [DRAFT] Check fix for emojie, wrap issues (#13430)
Hi there

Here I am using latest tabled.

My tests shows it does fixes panics, but I am wanna be sure.

@fdncred could you verify that it does fixes those panics/errors?

Closes #13405 
Closes #12786
2024-08-23 17:35:42 -05:00
7003b007d5 doc: fix broken doc links (#13644)
Some broken doc links I saw when compiling with `cargo +stable doc
--no-deps --document-private-items --workspace --open`
2024-08-23 21:17:44 +02:00
dfdb2b5d31 Improve help output for scripts (#13445)
# 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.
-->
Currently the parser and the documentation generation use the signature
of the command, which means that it doesn't pick up on the changed name
of the `main` block, and therefore shows the name of the command as
"main" and doesn't find the subcommands. This PR changes the
aforementioned places to use the block signature to fix these issues.
This closes #13397. Incidentally it also causes input/output types to be
shown in the help, which is kinda pointless for scripts since they don't
operate on structured data but maybe not worth the effort to remove.

# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->
```
# example.nu
export def main [] { help main }
export def 'main sub' [] { print 'sub' }
```
Before:

![image](https://github.com/user-attachments/assets/49fdcf8d-e56a-4c27-b7c8-7d2902c2a807)

![image](https://github.com/user-attachments/assets/4d1f4faa-5928-4269-b0b5-fd654563bb8b)


After:

![image](https://github.com/user-attachments/assets/a7232a1f-f997-4988-808c-8fa957e39bae)

![image](https://github.com/user-attachments/assets/c5628dc6-69b5-443a-b103-9e5faa9bb4ba)

# Tests
<!--
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 toolkit.nu; toolkit test stdlib"` to run the
tests for the standard library

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

Tests are still missing for the subcommands and the input/output types

---------

Co-authored-by: Stefan Holderbach <sholderbach@users.noreply.github.com>
2024-08-23 21:08:27 +02:00
822007dbbb Remove unused same-file workspace dependency (#13678)
A small no-op change. It was used in a two years old `mv` fix
(848550771a, pre `uu_mv`). But now it's redundant.
2024-08-23 20:51:34 +02:00
0560826414 encode/decode for multiple alphabets (#13428)
Based on the discussion in #13419.


## Description

Reworks the `decode`/`encode` commands by adding/changing the following
bases:

- `base32`
- `base32hex`
- `hex`
- `new-base64`

The `hex` base is compatible with the previous version of `hex` out of
the box (it only adds more flags). `base64` isn't, so the PR adds a new
version and deprecates the old one.

All commands have `string -> binary` signature for decoding and `string
| binary -> string` signature for encoding. A few `base64` encodings,
which are not a part of the
[RFC4648](https://datatracker.ietf.org/doc/html/rfc4648#section-6), have
been dropped.


## Example usage

```Nushell
~/fork/nushell> "string" | encode base32 | decode base32 | decode
string
```

```Nushell
~/fork/nushell> "ORSXG5A=" | decode base32
# `decode` always returns a binary value
Length: 4 (0x4) bytes | printable whitespace ascii_other non_ascii
00000000:   74 65 73 74                                          test
```


## User-Facing Changes

- New commands: `encode/decode base32/base32hex`.
- `encode hex` gets a `--lower` flag.
- `encode/decode base64` deprecated in favor of `encode/decode
new-base64`.
2024-08-23 11:18:51 -05:00
39b0f3bdda Change expected type for derived FromValue implementations via attribute (#13647)
<!--
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.
-->
In this PR I expanded the helper attribute `#[nu_value]` on
`#[derive(FromValue)]`. It now allows the usage of `#[nu_value(type_name
= "...")]` to set a type name for the `FromValue::expected_type`
implementation. Currently it only uses the default implementation but
I'd like to change that without having to manually implement the entire
trait on my own.

# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->
Users that derive `FromValue` may now change the name of the expected
type.

# 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 toolkit.nu; toolkit test stdlib"` 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
> ```
-->
I added some tests that check if this feature work and updated the
documentation about the derive macro.

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

# After Submitting
<!-- If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
-->
2024-08-23 06:47:15 -05:00
712fec166d Improve working with IntoValue and FromValue for byte collections (#13641)
<!--
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.
-->
I was working with byte collections like `Vec<u8>` and
[`bytes::Bytes`](https://docs.rs/bytes/1.7.1/bytes/struct.Bytes.html),
both are currently not possible to be used directly in a struct that
derives `IntoValue` and `FromValue` at the same time. The `Vec<u8>` will
convert itself into a `Value::List` but expects a `Value::String` or
`Value::Binary` to load from. I now also implemented that it can load
from `Value::List` just like the other `Vec<uX>` versions. For further
working with byte collections the type `bytes::Bytes` is wildly used,
therefore I added a implementation for it. `bytes` is already part of
the dependency graph as many crates (more than 5000 to crates.io) use
it.

# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->
User of `nu-protocol` as library, e.g. plugin developers, can now use
byte collections more easily in their data structures and derive
`IntoValue` and `FromValue` for it.

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

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

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used` 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 toolkit.nu; toolkit test stdlib"` 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
> ```
-->
I added a few tests that check that these byte collections are correctly
translated in and from `Value`. They live in `test_derive.rs` as part of
the `ByteContainer` and I also explicitely tested that `FromValue` for
`Vec<u8>` works as expected.

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

# After Submitting
<!-- If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
-->
Maybe it should be explored if `Value::Binary` should use `bytes::Bytes`
instead of `Vec<u8>`.
2024-08-22 17:59:00 -05:00
43dcf19ac3 Fix bits ror/bits rol implementation (#13673)
# Description
`bits rol` and `bits ror` were both undefined for the full byte rotates
and panicked when exceeding the byte rotation range.
`bits ror` further more produced nonsensical results by pulling bits
from the following byte instead of the preceding byte.

Those bugs are now fixed

# User-Facing Changes
Sound Nushell `IncorrectValue` error when exceeding the available bits

# Tests + Formatting
Added the necessary tests
2024-08-22 21:22:10 +02:00
ffddee5678 add more granularity for into record with dates (#13650)
# Description

This PR adds a little more granularity when using `into record` with
dates.

### Before
```nushell
❯ date now | into record
╭──────────┬────────╮
│ year     │ 2024   │
│ month    │ 8      │
│ day      │ 19     │
│ hour     │ 18     │
│ minute   │ 31     │
│ second   │ 27     │
│ timezone │ -05:00 │
╰──────────┴────────╯
```

### After
```nushell
❯ date now | into record
╭─────────────┬────────╮
│ year        │ 2024   │
│ month       │ 8      │
│ day         │ 19     │
│ hour        │ 18     │
│ minute      │ 30     │
│ second      │ 51     │
│ millisecond │ 928    │
│ microsecond │ 980    │
│ nanosecond  │ 0      │
│ timezone    │ -05:00 │
╰─────────────┴────────╯
```
2024-08-22 12:09:27 +02:00
95b78eee25 Change the usage misnomer to "description" (#13598)
# Description
    
The meaning of the word usage is specific to describing how a command
function is *used* and not a synonym for general description. Usage can
be used to describe the SYNOPSIS or EXAMPLES sections of a man page
where the permitted argument combinations are shown or example *uses*
are given.
Let's not confuse people and call it what it is a description.

Our `help` command already creates its own *Usage* section based on the
available arguments and doesn't refer to the description with usage.

# User-Facing Changes

`help commands` and `scope commands` will now use `description` or
`extra_description`
`usage`-> `description`
`extra_usage` -> `extra_description`

Breaking change in the plugin protocol:

In the signature record communicated with the engine.
`usage`-> `description`
`extra_usage` -> `extra_description`

The same rename also takes place for the methods on
`SimplePluginCommand` and `PluginCommand`

# Tests + Formatting
- Updated plugin protocol specific changes
# After Submitting
- [ ] update plugin protocol doc
2024-08-22 12:02:08 +02:00
3ab9f0b90a Fix bugs and UB in bit shifting ops (#13663)
# Description
Fixes #11267

Shifting by a `shift >= num_bits` is undefined in the underlying
operation. Previously we also had an overflow on negative shifts for the
operators `bit-shl` and `bit-shr`
Furthermore I found a severe bug in the implementation of shifting of
`binary` data with the commands `bits shl` and `bits shr`, this
categorically produced incorrect results with shifts that were not
`shift % 4 == 0`. `bits shr` also was able to produce outputs with
different size to the input if the shift was exceeding the length of the
input data by more than a byte.

# User-Facing Changes
It is now an error trying to shift by more than the available bits with:
- `bit-shl` operator
- `bit-shr` operator
- command `bits shl`
- command `bits shr`

# Tests + Formatting
Added testing for all relevant cases
2024-08-22 11:54:27 +02:00
9261c0c55a Be explicit about reduce args and input (#13646)
# Description

`run_with_value` is meant for running simple closures with one arg.
Using `run_with_value` after `add_arg` is slightly confusing.
2024-08-22 11:39:21 +02:00
7a888c9e9b Change behavior of into record on lists to be more useful (#13637)
# Description

The previous behaviour of `into record` on lists was to create a new
record with each list index as the key. This was not very useful for
creating meaningful records, though, and most people would end up using
commands like `headers` or `transpose` to turn a list of keys and values
into a record.

This PR changes that instead to do what I think the most ergonomic thing
is, and instead:

- A list of records is merged into one record.
- A list of pairs (two element lists) is folded into a record with the
first element of each pair being the key, and the second being the
value.

The former is just generally more useful than having to use `reduce`
with `merge` for such a common operation, and the latter is useful
because it means that `$a | zip $b | into record` *just works* in the
way that seems most obvious.

Example:

```nushell
[[foo bar] [baz quux]] | into record # => {foo: bar, baz: quux}
[{foo: bar} {baz: quux}] | into record # => {foo: bar, baz: quux}
[foo baz] | zip [bar quux] | into record # => {foo: bar, baz: quux}
```

The support for range input has been removed, as it would no longer
reflect the treatment of an equivalent list.

The following is equivalent to the old behavior, in case that's desired:

```
0.. | zip [a b c] | into record # => {0: a, 1: b, 2: c}
```

# User-Facing Changes
- `into record` changed as described above (breaking)
- `into record` no longer supports range input (breaking)

# Tests + Formatting
Examples changed to match, everything works. Some usage in stdlib and
`nu_plugin_nu_example` had to be changed.

# After Submitting
- [ ] release notes (commands, breaking change)
2024-08-22 11:38:43 +02:00
e211b7ba53 Bump version to 0.97.2 (#13666) 2024-08-22 11:36:32 +02:00
60769ac1ba Bump version to 0.97.1 (#13659)
# Description

Bump version to `0.97.1`, which will be the actual next major release.
(`0.97.0` had a bug.)
2024-08-20 20:21:12 -07:00
34e7bd861c Fix bug introduced by #13595 (#13658)
<!--
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.
-->

@devyn found that https://github.com/nushell/nushell/pull/13595, which
made ranges be type-checked at parse time, introduced a bug that caused
`../foo` to be parsed as a string rather than a command call. This was
caused by `parse_range` returning a `Some` despite there being parse
errors (`/foo` doesn't match `SyntaxShape::Number`). To go back to the
old behavior, `parse_range` now returns `None` anytime there's any parse
errors met while parsing the range.

Unfortunately, this means that something like `..$foo` will be parsed as
a string if `$foo` isn't defined and as a range if it is defined. That
was the behavior before #13595, and it should probably be fixed at some
point, but I'm just trying to quickly fix the bug.

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

Things should go back to the way they were before #13595, except the
type-checking stuff from that PR is still here.

# 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 toolkit.nu; toolkit test stdlib"` to run the
tests for the standard library

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

Added a test. Reverted another test that tests that `0..<$day` is parsed
successfully as a string if the variable isn't defined.

# 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-08-20 19:35:13 -07:00
d667b3c0bc bumped version number to 0.97 (#13655) 2024-08-20 16:28:19 -07:00
b63c3514c4 Fix clippy lints (#13645) 2024-08-19 11:12:45 +02:00
7e9d32d64e Drop outdated touch -d example (#13631)
Fixes nushell/nushell#8723

# Description

The example was showing the flag that no longer exists.

# User-Facing Changes

Help no longer shows the example with `-d` flag.

# Tests + Formatting

I trust in CI.

# After Submitting

Nothing.
2024-08-15 23:57:25 +02:00
621fb25670 update to latest reedline f2b4 (#13629)
# Description

Update to the latest reedline comment. BTW `f2b4` sounds like a new star
wars droid. 😆
2024-08-15 21:03:13 +02:00
a80273bd7b Drop unused fs_extra and hamcrest2 dependencies (#13628)
Fixes nushell/nushell#7995

# Description

This dependency is no longer used by nushell itself.

# User-Facing Changes

None.

# Tests + Formatting

Pased.

# After Submitting

None.
2024-08-15 19:25:50 +02:00
5473def7ef Prefer process name over executable path (#13618)
# Description
Prefer process name over executable path. This in practice causes the
`name` column to use just the base executable name.

Also set start_time to nothing on error, because why not.

# User-Facing Changes

Before:

> /opt/google/chrome/chrome

After:

> chrome

Also picks up changes due to `echo test-proc > /proc/$$/comm`.

# Tests + Formatting

No new coverage.
2024-08-15 13:44:01 +08:00
04746b8e2d add osc633e (#13625)
# Description

This PR adds OSC 633E for vscode users to enable `Terminal: Run Recent
Command` with ctrl-shift-p.


![image](https://github.com/user-attachments/assets/21b92206-3c44-4060-aa0b-78718c099336)
2024-08-15 13:40:34 +08:00
31b3104af7 Remove code duplication in glob (#13626) 2024-08-14 23:11:00 +02:00
803bc9c63f Incrementing the eager dataframe cache value before returning it (#13624)
# Description

Fixes issue [12828](https://github.com/nushell/nushell/issues/12828).

When attempting a `polars collect` on an eager dataframe, we return
dataframe as is. However, before this fix I failed to increment the
internal cache reference count. This caused the value to be dropped from
the internal cache when the references were decremented again.

This fix adds a call to cache.get to increment the value before
returning.
2024-08-14 15:38:46 -05:00
e690e7aac0 Fallback to extension-based content type detection when parsing Content-Type header fails (#13610)
# Description

Previously when nushell failed to parse the content type header, it
would emit an error instead of returning the response. Now it will fall
back to `text/plain` (which, in turn, will trigger type detection based
on file extension).

May fix (potentially) nushell/nushell#11927

Refs:
https://discord.com/channels/601130461678272522/614593951969574961/1272895236489613366

Supercedes: #13609 

# User-Facing Changes

It's now possible to fetch content even if the server returns an invalid
content type header. Users may need to parse the response manually, but
it's still better than not getting the response at all.

# Tests + Formatting

Added a test for the new behaviour.

# After Submitting
2024-08-14 09:47:01 -05:00
e841fce0f9 Bump indexmap from 2.3.0 to 2.4.0 (#13617)
Bumps [indexmap](https://github.com/indexmap-rs/indexmap) from 2.3.0 to
2.4.0.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/indexmap-rs/indexmap/blob/master/RELEASES.md">indexmap's
changelog</a>.</em></p>
<blockquote>
<h2>2.4.0</h2>
<ul>
<li>Added methods <code>IndexMap::append</code> and
<code>IndexSet::append</code>, moving all items from
one map or set into another, and leaving the original capacity for
reuse.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="b66bbfe282"><code>b66bbfe</code></a>
Merge pull request <a
href="https://redirect.github.com/indexmap-rs/indexmap/issues/337">#337</a>
from cuviper/append</li>
<li><a
href="a288bf3b3a"><code>a288bf3</code></a>
Add a README note for <code>ordermap</code></li>
<li><a
href="0b2b4b9a78"><code>0b2b4b9</code></a>
Release 2.4.0</li>
<li><a
href="8c0a1cd4be"><code>8c0a1cd</code></a>
Add <code>append</code> methods</li>
<li>See full diff in <a
href="https://github.com/indexmap-rs/indexmap/compare/2.3.0...2.4.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=indexmap&package-manager=cargo&previous-version=2.3.0&new-version=2.4.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-08-14 15:21:39 +08:00
d7b0dc1275 Bump shadow-rs from 0.30.0 to 0.31.1 (#13616)
Bumps [shadow-rs](https://github.com/baoyachi/shadow-rs) from 0.30.0 to
0.31.1.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/baoyachi/shadow-rs/releases">shadow-rs's
releases</a>.</em></p>
<blockquote>
<h2>[Improvement] Correct git command directory</h2>
<p>ref: <a
href="https://redirect.github.com/baoyachi/shadow-rs/issues/170">#170</a></p>
<p>Thx <a
href="https://github.com/MichaelScofield"><code>@​MichaelScofield</code></a></p>
<h2>Make build_with function public</h2>
<p>ref:<a
href="https://redirect.github.com/baoyachi/shadow-rs/issues/169">#169</a></p>
<p>Thx <a
href="https://github.com/MichaelScofield"><code>@​MichaelScofield</code></a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="aa804ec8a2"><code>aa804ec</code></a>
Update Cargo.toml</li>
<li><a
href="b3fbe36403"><code>b3fbe36</code></a>
Merge pull request <a
href="https://redirect.github.com/baoyachi/shadow-rs/issues/170">#170</a>
from MichaelScofield/find-right-branch</li>
<li><a
href="fe6f940f8b"><code>fe6f940</code></a>
execute &quot;git&quot; command in the right path</li>
<li><a
href="458be25e74"><code>458be25</code></a>
Merge pull request <a
href="https://redirect.github.com/baoyachi/shadow-rs/issues/169">#169</a>
from MichaelScofield/flexible-for-submodule</li>
<li><a
href="1521a288b4"><code>1521a28</code></a>
Expose the &quot;build&quot; function to let projects with submodules
control where to ...</li>
<li><a
href="ee12741fa0"><code>ee12741</code></a>
Merge pull request <a
href="https://redirect.github.com/baoyachi/shadow-rs/issues/168">#168</a>
from baoyachi/issue/149</li>
<li><a
href="dfb8b24adb"><code>dfb8b24</code></a>
cargo fmt</li>
<li><a
href="a3be8680aa"><code>a3be868</code></a>
fix clippy</li>
<li><a
href="c8e7cd5704"><code>c8e7cd5</code></a>
Fix compilation failures caused by unwrap</li>
<li>See full diff in <a
href="https://github.com/baoyachi/shadow-rs/compare/v0.30.0...v0.31.1">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.30.0&new-version=0.31.1)](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-08-14 14:41:12 +08:00
5627c95916 Bump sysinfo from 0.30.11 to 0.30.13 (#13615)
Bumps [sysinfo](https://github.com/GuillaumeGomez/sysinfo) from 0.30.11
to 0.30.13.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/GuillaumeGomez/sysinfo/blob/master/CHANGELOG.md">sysinfo's
changelog</a>.</em></p>
<blockquote>
<h1>0.30.13</h1>
<ul>
<li>macOS: Fix segfault when calling
<code>Components::refresh_list</code> multiple times.</li>
<li>Windows: Fix CPU arch retrieval.</li>
</ul>
<h1>0.30.12</h1>
<ul>
<li>FreeBSD: Fix network interfaces retrieval (one was always
missing).</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="1639d74765"><code>1639d74</code></a>
Merge pull request <a
href="https://redirect.github.com/GuillaumeGomez/sysinfo/issues/1306">#1306</a>
from GuillaumeGomez/update</li>
<li><a
href="4bcded7fa7"><code>4bcded7</code></a>
Update crate version to 0.30.13</li>
<li><a
href="9feeff00a3"><code>9feeff0</code></a>
Add CHANGELOG for 0.30.13</li>
<li><a
href="3e7c8f23d2"><code>3e7c8f2</code></a>
Merge pull request <a
href="https://redirect.github.com/GuillaumeGomez/sysinfo/issues/1305">#1305</a>
from GuillaumeGomez/backport</li>
<li><a
href="5ec06633a0"><code>5ec0663</code></a>
Fix new clippy lints</li>
<li><a
href="53d066ebf1"><code>53d066e</code></a>
Fix fmt</li>
<li><a
href="6a6838bc81"><code>6a6838b</code></a>
Fix minor typo in a doc comment</li>
<li><a
href="0662e60ac4"><code>0662e60</code></a>
Fix CPU arch retrieval on Windows (<a
href="https://redirect.github.com/GuillaumeGomez/sysinfo/issues/1296">#1296</a>)</li>
<li><a
href="57ea114d10"><code>57ea114</code></a>
Fix segfault when call calling Components::refresh_list multiple times
on M-...</li>
<li><a
href="57d6b32300"><code>57d6b32</code></a>
Merge pull request <a
href="https://redirect.github.com/GuillaumeGomez/sysinfo/issues/1271">#1271</a>
from GuillaumeGomez/update</li>
<li>Additional commits viewable in <a
href="https://github.com/GuillaumeGomez/sysinfo/compare/v0.30.11...v0.30.13">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=sysinfo&package-manager=cargo&previous-version=0.30.11&new-version=0.30.13)](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-08-14 14:41:00 +08:00
f122065772 create a better error message for bad glob patterns (#13613)
# Description

@sholderbach pointed out that I could've made this error message better.
So, here's my attempt to make it better.

This should work. I had a hard time figuring out how to trigger the
error anyway because the type checker doesn't allow "bad" parameters to
begin with.

### Before

![image](https://github.com/user-attachments/assets/ac60ce27-4b9a-49ca-910c-74422ae31bc4)


### After

![image](https://github.com/user-attachments/assets/fe939339-67df-4d30-a8dd-5ce3fe623a95)


# 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 toolkit.nu; toolkit test stdlib"` 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-08-13 18:40:17 -05:00
4732507f46 allow glob to take a glob or a string as the input (#13612)
# Description

This PR changes glob to take either a string or a glob as a parameter.

Closes #13611

# 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 toolkit.nu; toolkit test stdlib"` 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-08-13 14:27:42 -05:00
5f45f6c223 add more helpful error with text/xml (#13609)
# Description

This PR is meant to provide a more helpful error message when using http
get and the content type can't be parsed.

### Before

![image](https://github.com/user-attachments/assets/4e6176e2-ec35-48d8-acb3-af5d1cda4327)

### After

![image](https://github.com/user-attachments/assets/aa498ef7-f1ca-495b-8790-484593f02e35)
The span isn't perfect but there's no way to get the span of the content
type that I can see.

In the middle of fixing this error, I also discovered how to fix the
problem in general. Since you can now see the error message complaining
about double quotes (char 22 at position 0. 22 hex is `"`). The fix is
just to remove all the double quotes from the content_type and then you
get this.

### After After

![image](https://github.com/user-attachments/assets/2223d34f-4563-4dea-90eb-83326e808af1)

The discussion on Discord about this is that `--raw` or
`--ignore-errors` should eat this error and it "just work" as well as
default to text or binary when the mime parsing fails. I agree but this
PR does not implement that.

# 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 toolkit.nu; toolkit test stdlib"` 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-08-13 14:27:28 -05:00
a55d172e52 make ls -lf outputs full path in symbolic target (#13605)
# Description
Fixes: #13479 

# User-Facing Changes
Given the following setup:
```
cd /tmp
touch src_file.txt
ln -s src_file.txt link1
```
### Before 
```
ls -lf link1 | get target.0  # It outputs src_file.txt
```
### After
```
ls -lf link1 | get target.0  # It outputs /tmp/src_file.txt
```
# Tests + Formatting
Added a test for the change
2024-08-13 06:34:10 -05:00
48e401834d Fix handling of spaces in executable names (#13596)
# Description
The original code assumed a full single-string command line could be
split by space to get the original argv.

# User-Facing Changes
Fixes an issue where `ps` would display incomplete process name if it
contained space(s).

# Tests + Formatting
Fixes existing code, no new coverage. Existing code doesn't seem to be
covered, we could be it would be somewhat involved and the fix was
simple, so didn't bother..
2024-08-13 06:29:40 -05:00
d5946a9667 Parse time type checking for range (#13595)
# Description

As part of fixing https://github.com/nushell/nushell/issues/13586, this
PR checks the types of the operands when creating a range. Stuff like
`0..(glob .)` will be rejected at parse time. Additionally, `0..$x` will
be treated as a range and rejected if `x` is not defined, rather than
being treated as a string. A separate PR will need to be made to do
reject streams at runtime, so that stuff like `0..(open /dev/random)`
doesn't hang.

Internally, this PR adds a `ParseError::UnsupportedOperationTernary`
variant, for when you have a range like `1..2..(glob .)`.

# User-Facing Changes

Users will now receive an error if any of the operands in the ranges
they construct have types that aren't compatible with `Type::Number`.

Additionally, if a piece of code looks like a range but some parse error
is encountered while parsing it, that piece of code will still be
treated as a range and the user will be shown the parse error. This
means that a piece of code like `0..$x` will be treated as a range no
matter what. Previously, if `x` weren't the expression would've been
treated as a string `"0..$x"`. I feel like it makes the language less
complicated if we make it less context-sensitive.

Here's an example of the error you get:
```
> 0..(glob .)
Error: nu::parser::unsupported_operation

  × range is not supported between int and any.
   ╭─[entry #1:1:1]
 1 │ 0..(glob .)
   · ─────┬─────┬┬
   ·      │     │╰── any
   ·      │     ╰── int
   ·      ╰── doesn't support these values
   ╰────
```

And as an image:

![image](https://github.com/user-attachments/assets/5c76168d-27db-481b-b541-861dac899dbf)

Note: I made the operands themselves (above, `(glob .)`) be garbage,
rather than the `..` operator itself. This doesn't match the behavior of
the math operators (if you do `1 + "foo"`, `+` gets highlighted red).
This is because with ranges, the range operators aren't `Expression`s
themselves, so they can't be turned into garbage. I felt like here, it
makes more sense to highlight the individual operand anyway.
2024-08-13 15:05:34 +08:00
a432bf94ec support SyntaxShape::OneOf in named args (#13553)
# Description
Fixes: #13253

The issue is because nushell use `parse_value` to parse named args, but
`parse_value` doesn't parse `OneOf` syntax shape.

# User-Facing Changes
`OneOf` in named args should works again.

# Tests + Formatting
I think it's hard to add a test, because nushell doesn't support `oneof`
syntax in custom command yet.

# After Submitting
NaN
2024-08-13 06:50:12 +08:00
0eabbb88dd Replace only leading home path with ~ in the title (#13600)
# Description :
- This pull request addresses issue #13594 where any substring of the
path that matches the home directory is replaced with `~` in the title
bar. This was problematic because partial matches within the path were
also being replaced.


---------

Signed-off-by: Aakash788 <aakashparmar788@gmail.com>
Co-authored-by: sholderbach <sholderbach@users.noreply.github.com>
2024-08-12 16:43:59 +02:00
80c8edcfb4 Include only *.nu files in the vendor autoload (#13599)
# Description
Fixes #13587

# User-Facing Changes
Files without ending or non-`*.nu` files will not be loaded as
vendor/configuration files.

# Tests + Formatting
So far we don't have any tests for that..
2024-08-12 22:02:57 +08:00
059167ac96 Make error-message more helpful when user invokes a non-executable file (#13589)
# Description

Fixes Issue #13477 
This adds a check to see if a user is trying to invoke a
(non-executable) file as a command and returns a helpful error if so.
EDIT: this will not work on Windows, and is arguably not relevant there,
because of the different semantics of executables. I think the
equivalent on Windows would be if a user tries to invoke `./foo`, we
should look for `foo.exe` or `foo.bat` in the directory and recommend
that if it exists.

# User-Facing Changes

When a user invokes an unrecognized command that is the path to an
existing file, the error used to say:
`{name} is neither a Nushell built-in or a known external command` 
This PR proposes to change the message to:
`{name} refers to a file that is not executable. Did you forget to to
set execute permissions?`

# Tests + Formatting
Ran cargo fmt, clippy and test on the workspace. 
EDIT: added test asserting the new behavior
2024-08-12 14:21:08 +02:00
4e205cd9a7 Add --raw switch to print for binary data (#13597)
# Description

Something I meant to add a long time ago. We currently don't have a
convenient way to print raw binary data intentionally. You can pipe it
through `cat` to turn it into an unknown stream, or write it to a file
and read it again, but we can't really just e.g. generate msgpack and
write it to stdout without this. For example:

```nushell
[abc def] | to msgpack | print --raw
```

This is useful for nushell scripts that will be piped into something
else. It also means that `nu_plugin_nu_example` probably doesn't need to
do this anymore, but I haven't adjusted it yet:

```nushell
def tell_nushell_encoding [] {
  print -n "\u{0004}json"
}
```

This happens to work because 0x04 is a valid UTF-8 character, but it
wouldn't be possible if it were something above 0x80.

`--raw` also formats other things without `table`, I figured the two
things kind of go together. The output is kind of like `to text`.
Debatable whether that should share the same flag, but it was easier
that way and seemed reasonable.

# User-Facing Changes
- `print` new flag: `--raw`

# Tests + Formatting
Added tests.

# After Submitting
- [ ] release notes (command modified)
2024-08-12 17:29:25 +08:00
18772b73b3 Add parse error for external commands used in assignment without caret (#13585)
# Description

As per our Wednesday meeting, this adds a parse error when something
that would be parsed as an external call is present at the top level,
unless the head of the external call begins with a caret (to make it
explicit).

I tried to make the error quite descriptive about what should be done.

# User-Facing Changes
These now cause a parse error:

```nushell
$foo = bar
$foo = `bar`
```

These would have been interpreted as strings before this version, but
now they'd be interpreted as external calls. This behavior is consistent
with `let`/`mut` (which is unaffected by this change).

Here is an example of the error:

```
Error:   × External command calls must be explicit in assignments
   ╭─[entry #3:1:8]
 1 │ $foo = bar
   ·        ─┬─
   ·         ╰── add a caret (^) before the command name if you intended to run and capture its output
   ╰────
  help: the parsing of assignments was changed in 0.97.0, and this would have previously been treated as a string.
        Alternatively, quote the string with single or double quotes to avoid it being interpreted as a command name. This
        restriction may be removed in a future release.
```

# Tests + Formatting

Tests added to cover the change. Note made about it being temporary.
2024-08-12 10:24:23 +02:00
983014cc40 Clean up key event handling (#13574)
# Description
Cleanups:
 - Add "key_press" to event reading function names to match reality
- Move the relevant comment about why only key press events are
interesting one layer up
 - Remove code duplication in handle_events
- Make `try_next` try harder (instead of bail on a boring event); I
think that was the original intention
- Remove recursion from `next` (I think that's clearer? but maybe just
what I'm used to)

# User-Facing Changes
None

# Tests + Formatting
This cleans up existing code, no new test coverage.
2024-08-09 18:07:50 -07:00
4ff33933dd Merge polars sink and polars to-* to polars save (#13568)
# Description
This pull request merges `polars sink` and `polars to-*` into one
command `polars save`.


# User-Facing Changes
- `polars to-*` commands have all been replaced with `polars save`. When
saving a lazy frame to a type that supports a polars sink operation, a
sink operation will be performed. Sink operations are much more
performant, performing a collect while streaming to the file system.
2024-08-08 09:46:45 -07:00
035308bb1d Bump typo with new ignore (#13563)
Supersedes #13554

(not sure how to narrow the word ignore to a file, maybe the better
course of action would be to mark this file as an ignore with all the
cryptic fileendings)
2024-08-08 06:50:28 +08:00
e530e7d654 Make the math commands const (#13566)
This PR closes [Issue
#13482](https://github.com/nushell/nushell/issues/13482)

# Description
This PR tend to make all math function to be constant. 

# User-Facing Changes
The math commands now can be used as constant methods.

### Some Example
```
> const MODE = [3 3 9 12 12 15] | math mode
> $MODE
╭───┬────╮
│ 0 │  3 │
│ 1 │ 12 │
╰───┴────╯

> const LOG = [16 8 4] | math log 2
> $LOG
╭───┬──────╮
│ 0 │ 4.00 │
│ 1 │ 3.00 │
│ 2 │ 2.00 │
╰───┴──────╯

> const VAR = [1 3 5] | math variance
> $VAR
2.6666666666666665
```

# Tests + Formatting
Tests are added for all of the math command to test there constant
behavior.

I mostly focused on the actual user experience, not the correctness of
the methods and algorithms.

# After Submitting
I think this change don't require any additional documentation. Feel
free to correct me in this topic please.
2024-08-07 22:20:33 +02:00
7d4449f021 Added polars sink command, that performs and streaming collect to t… (#13562)
# Description
This exposes the `LazyFrame::sink_*` functionality to allow a streaming
collect directly to the filesystem. This useful when working with data
that is too large to fit into memory.

# User-Facing Changes
- Introduction of the `polars sink` command
2024-08-07 10:59:49 -05:00
ec3e0e593d polars first and polars last will now handle lazy frames natively (#13555)
# Description
Prior this pull request `polars first` and `polars last` would collect a
lazy frame into an eager frame before performing operations. Now `polars
first` will to a `LazyFrame::limit` and `polars last` will perform a
`LazyFrame::tail`. This is really useful in working with very large
datasets.
2024-08-07 06:36:52 -05:00
ff09c7964e polars open will now open a lazy frame by default (#13556)
# Description
When opening a dataframe the default operation will be to create a lazy
frame if possible. This works much better with large datasets and
supports hive format.

# User-Facing Changes
- `--lazy` is nolonger a valid option. `--eager` must be used to
explicitly open an eager dataframe.
2024-08-07 06:36:08 -05:00
ce13ecfd10 Bump mockito from 1.4.0 to 1.5.0 (#13558)
Bumps [mockito](https://github.com/lipanski/mockito) from 1.4.0 to
1.5.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/lipanski/mockito/releases">mockito's
releases</a>.</em></p>
<blockquote>
<h2>1.5.0</h2>
<ul>
<li><strong>[Breaking]</strong> <a
href="https://redirect.github.com/lipanski/mockito/pull/198">Upgrade</a>
to hyper v1</li>
</ul>
<p>Thanks to <a
href="https://github.com/tottoto"><code>@​tottoto</code></a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="f1c3fe1b7f"><code>f1c3fe1</code></a>
Bump to 1.5.0</li>
<li><a
href="08f2fa322d"><code>08f2fa3</code></a>
Merge pull request <a
href="https://redirect.github.com/lipanski/mockito/issues/199">#199</a>
from tottoto/refactor-response-body</li>
<li><a
href="42e3efe734"><code>42e3efe</code></a>
Refactor response body</li>
<li><a
href="f477e54857"><code>f477e54</code></a>
Merge pull request <a
href="https://redirect.github.com/lipanski/mockito/issues/198">#198</a>
from tottoto/update-to-hyper-1</li>
<li><a
href="e8694ae991"><code>e8694ae</code></a>
Update to hyper 1</li>
<li><a
href="b152b76130"><code>b152b76</code></a>
Depend on some crate directly</li>
<li>See full diff in <a
href="https://github.com/lipanski/mockito/compare/1.4.0...1.5.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=mockito&package-manager=cargo&previous-version=1.4.0&new-version=1.5.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-08-07 11:09:23 +08:00
c18e6bfca0 Add type signature example for def command (#13561)
# Description

By popular demand (a.k.a.
https://github.com/nushell/nushell.github.io/issues/1035), provide an
example of a type signature in the `def` help.

# User-Facing Changes

Help/Doc

# Tests + Formatting

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

# After Submitting

N/A
2024-08-06 21:40:30 -05:00
bc6947cd09 Bump quick-xml from 0.31.0 to 0.32.0 (#13560)
Bumps [quick-xml](https://github.com/tafia/quick-xml) from 0.31.0 to
0.32.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/tafia/quick-xml/releases">quick-xml's
releases</a>.</em></p>
<blockquote>
<h2>v0.32.0</h2>
<h2>Significant Changes</h2>
<p>The method of reporting positions of errors has changed - use
<code>error_position()</code> to get an offset of the error position.
For <code>SyntaxError</code>s the range
<code>error_position()..buffer_position()</code> also will represent a
span of error.</p>
<h3>⚠️ Breaking Changes</h3>
<p>The way to configure parser has changed. Now all configuration is
contained in the <code>Config</code> struct and can be applied at once.
When <code>serde-types</code> feature is enabled, configuration is
serializable.</p>
<p>The way of resolve entities with <code>unescape_with</code> has
changed. Those methods no longer resolve predefined entities
(<code>lt</code>, <code>gt</code>, <code>apos</code>, <code>quot</code>,
<code>amp</code>). <code>NoEntityResolver</code> renamed to
<code>PredefinedEntityResolver</code>.</p>
<p><code>Writer::create_element</code> now accepts <code>impl
Into&lt;Cow&lt;str&gt;&gt;</code> instead of <code>&amp;impl
AsRef&lt;str&gt;</code>.</p>
<p>Minimum supported version of serde raised to 1.0.139</p>
<p>The full changelog is below.</p>
<h2>What's Changed</h2>
<h3>New Features</h3>
<ul>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/513">#513</a>:
Allow to continue parsing after getting new
<code>Error::IllFormed</code>.</li>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/677">#677</a>:
Added methods <code>config()</code> and <code>config_mut()</code> to
inspect and change the parser configuration. Previous builder methods on
<code>Reader</code> / <code>NsReader</code> was replaced by direct
access to fields of config using
<code>reader.config_mut().&lt;...&gt;</code>.</li>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/684">#684</a>:
Added a method <code>Config::enable_all_checks</code> to turn on or off
all well-formedness checks.</li>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/362">#362</a>:
Added <code>escape::minimal_escape()</code> which escapes only
<code>&amp;</code> and <code>&lt;</code>.</li>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/362">#362</a>:
Added <code>BytesCData::minimal_escape()</code> which escapes only
<code>&amp;</code> and <code>&lt;</code>.</li>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/362">#362</a>:
Added <code>Serializer::set_quote_level()</code> which allow to set
desired level of escaping.</li>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/705">#705</a>:
Added <code>NsReader::prefixes()</code> to list all the prefixes
currently declared.</li>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/629">#629</a>:
Added a default case to
<code>impl_deserialize_for_internally_tagged_enum</code> macro so that
it can handle every attribute that does not match existing cases within
an enum variant.</li>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/722">#722</a>:
Allow to pass owned strings to <code>Writer::create_element</code>. This
is breaking change!</li>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/275">#275</a>:
Added <code>ElementWriter::new_line()</code> which enables pretty
printing elements with multiple attributes.</li>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/743">#743</a>:
Added <code>Deserializer::get_ref()</code> to get XML Reader from serde
Deserializer</li>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/734">#734</a>:
Added helper functions to resolve predefined XML and HTML5 entities:
<ul>
<li><code>quick_xml::escape::resolve_predefined_entity</code></li>
<li><code>quick_xml::escape::resolve_xml_entity</code></li>
<li><code>quick_xml::escape::resolve_html5_entity</code></li>
</ul>
</li>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/753">#753</a>:
Added parser for processing instructions:
<code>quick_xml::reader::PiParser</code>.</li>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/754">#754</a>:
Added parser for elements:
<code>quick_xml::reader::ElementParser</code>.</li>
</ul>
<h3>Bug Fixes</h3>
<ul>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/622">#622</a>:
Fix wrong disregarding of not closed markup, such as lone
<code>&lt;</code>.</li>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/684">#684</a>:
Fix incorrect position reported for
<code>Error::IllFormed(DoubleHyphenInComment)</code>.</li>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/684">#684</a>:
Fix incorrect position reported for
<code>Error::IllFormed(MissingDoctypeName)</code>.</li>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/704">#704</a>:
Fix empty tags with attributes not being expanded when
<code>expand_empty_elements</code> is set to true.</li>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/683">#683</a>:
Use local tag name when check tag name against possible names for
field.</li>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/753">#753</a>:
Correctly determine end of processing instructions and XML
declaration.</li>
</ul>
<h3>Misc Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/675">#675</a>:
Minimum supported version of serde raised to 1.0.139</li>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/675">#675</a>:
Rework the <code>quick_xml::Error</code> type to provide more accurate
information:</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/tafia/quick-xml/blob/master/Changelog.md">quick-xml's
changelog</a>.</em></p>
<blockquote>
<h2>0.32.0 -- 2024-06-10</h2>
<p>The way to configure parser is changed. Now all configuration is
contained in the
<code>Config</code> struct and can be applied at once. When
<code>serde-types</code> feature is enabled,
configuration is serializable.</p>
<p>The method of reporting positions of errors has changed - use
<code>error_position()</code>
to get an offset of the error position. For <code>SyntaxError</code>s
the range
<code>error_position()..buffer_position()</code> also will represent a
span of error.</p>
<p>The way of resolve entities with <code>unescape_with</code> are
changed. Those methods no longer
resolve predefined entities.</p>
<h3>New Features</h3>
<ul>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/513">#513</a>:
Allow to continue parsing after getting new
<code>Error::IllFormed</code>.</li>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/677">#677</a>:
Added methods <code>config()</code> and <code>config_mut()</code> to
inspect and change the parser
configuration. Previous builder methods on <code>Reader</code> /
<code>NsReader</code> was replaced by
direct access to fields of config using
<code>reader.config_mut().&lt;...&gt;</code>.</li>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/684">#684</a>:
Added a method <code>Config::enable_all_checks</code> to turn on or off
all
well-formedness checks.</li>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/362">#362</a>:
Added <code>escape::minimal_escape()</code> which escapes only
<code>&amp;</code> and <code>&lt;</code>.</li>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/362">#362</a>:
Added <code>BytesCData::minimal_escape()</code> which escapes only
<code>&amp;</code> and <code>&lt;</code>.</li>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/362">#362</a>:
Added <code>Serializer::set_quote_level()</code> which allow to set
desired level of escaping.</li>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/705">#705</a>:
Added <code>NsReader::prefixes()</code> to list all the prefixes
currently declared.</li>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/629">#629</a>:
Added a default case to
<code>impl_deserialize_for_internally_tagged_enum</code> macro so that
it can handle every attribute that does not match existing cases within
an enum variant.</li>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/722">#722</a>:
Allow to pass owned strings to <code>Writer::create_element</code>. This
is breaking change!</li>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/275">#275</a>:
Added <code>ElementWriter::new_line()</code> which enables pretty
printing elements with multiple attributes.</li>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/743">#743</a>:
Added <code>Deserializer::get_ref()</code> to get XML Reader from serde
Deserializer</li>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/734">#734</a>:
Added helper functions to resolve predefined XML and HTML5 entities:
<ul>
<li><code>quick_xml::escape::resolve_predefined_entity</code></li>
<li><code>quick_xml::escape::resolve_xml_entity</code></li>
<li><code>quick_xml::escape::resolve_html5_entity</code></li>
</ul>
</li>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/753">#753</a>:
Added parser for processing instructions:
<code>quick_xml::reader::PiParser</code>.</li>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/754">#754</a>:
Added parser for elements:
<code>quick_xml::reader::ElementParser</code>.</li>
</ul>
<h3>Bug Fixes</h3>
<ul>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/622">#622</a>:
Fix wrong disregarding of not closed markup, such as lone
<code>&lt;</code>.</li>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/684">#684</a>:
Fix incorrect position reported for
<code>Error::IllFormed(DoubleHyphenInComment)</code>.</li>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/684">#684</a>:
Fix incorrect position reported for
<code>Error::IllFormed(MissingDoctypeName)</code>.</li>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/704">#704</a>:
Fix empty tags with attributes not being expanded when
<code>expand_empty_elements</code> is set to true.</li>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/683">#683</a>:
Use local tag name when check tag name against possible names for
field.</li>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/753">#753</a>:
Correctly determine end of processing instructions and XML
declaration.</li>
</ul>
<h3>Misc Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/675">#675</a>:
Minimum supported version of serde raised to 1.0.139</li>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/675">#675</a>:
Rework the <code>quick_xml::Error</code> type to provide more accurate
information:</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="8d38e4cc14"><code>8d38e4c</code></a>
Release 0.32.0</li>
<li><a
href="e6f7be47a7"><code>e6f7be4</code></a>
Add #[inline] to methods implementing XmlSource</li>
<li><a
href="33b9dc59c7"><code>33b9dc5</code></a>
Increase position outside of XmlSource::skip_one</li>
<li><a
href="704ce89239"><code>704ce89</code></a>
Generalize reading methods of PI and element</li>
<li><a
href="6f1a644dcc"><code>6f1a644</code></a>
Rewrite read_element like read_pi</li>
<li><a
href="0a6ecd6498"><code>0a6ecd6</code></a>
Add reusable parser for XML element and use it internally</li>
<li><a
href="02de8a51bf"><code>02de8a5</code></a>
Remove unnecessary block</li>
<li><a
href="0cb09fbda9"><code>0cb09fb</code></a>
Use <code>if let</code> instead of <code>match</code></li>
<li><a
href="6c58bef3ab"><code>6c58bef</code></a>
Implement XmlSource::read_pi like XmlSource::read_element</li>
<li><a
href="79b2fda9fe"><code>79b2fda</code></a>
Stop at the <code>&gt;</code> in PiParser which is consistent with other
search functions</li>
<li>Additional commits viewable in <a
href="https://github.com/tafia/quick-xml/compare/v0.31.0...v0.32.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=quick-xml&package-manager=cargo&previous-version=0.31.0&new-version=0.32.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-08-07 09:16:03 +08:00
faaa12838e Bump scraper from 0.19.0 to 0.20.0 (#13559)
Bumps [scraper](https://github.com/causal-agent/scraper) from 0.19.0 to
0.20.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/causal-agent/scraper/releases">scraper's
releases</a>.</em></p>
<blockquote>
<h2>0.20.0</h2>
<h2>What's Changed</h2>
<ul>
<li><code>is</code> and <code>has</code> support by <a
href="https://github.com/cfvescovo"><code>@​cfvescovo</code></a> in <a
href="https://redirect.github.com/causal-agent/scraper/pull/187">causal-agent/scraper#187</a></li>
<li>Make ElementRef Debug impl use Element by <a
href="https://github.com/gfaster"><code>@​gfaster</code></a> in <a
href="https://redirect.github.com/causal-agent/scraper/pull/190">causal-agent/scraper#190</a></li>
<li>Bump indexmap from 2.2.6 to 2.3.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/causal-agent/scraper/pull/194">causal-agent/scraper#194</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/gfaster"><code>@​gfaster</code></a> made
their first contribution in <a
href="https://redirect.github.com/causal-agent/scraper/pull/190">causal-agent/scraper#190</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/causal-agent/scraper/compare/v0.19.1...v0.20.0">https://github.com/causal-agent/scraper/compare/v0.19.1...v0.20.0</a></p>
<h2>0.19.1</h2>
<h2>What's Changed</h2>
<ul>
<li>Bump ahash from 0.8.9 to 0.8.11 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/causal-agent/scraper/pull/174">causal-agent/scraper#174</a></li>
<li>Bump indexmap from 2.2.3 to 2.2.5 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/causal-agent/scraper/pull/173">causal-agent/scraper#173</a></li>
<li>Bump html5ever from 0.26.0 to 0.27.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/causal-agent/scraper/pull/176">causal-agent/scraper#176</a></li>
<li>Bump indexmap from 2.2.5 to 2.2.6 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/causal-agent/scraper/pull/177">causal-agent/scraper#177</a></li>
<li>Select and Text are not fused iterators by <a
href="https://github.com/Noname-Official"><code>@​Noname-Official</code></a>
in <a
href="https://redirect.github.com/causal-agent/scraper/pull/184">causal-agent/scraper#184</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/Noname-Official"><code>@​Noname-Official</code></a>
made their first contribution in <a
href="https://redirect.github.com/causal-agent/scraper/pull/184">causal-agent/scraper#184</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/causal-agent/scraper/compare/v0.19.0...v0.19.1">https://github.com/causal-agent/scraper/compare/v0.19.0...v0.19.1</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="4d33a55f59"><code>4d33a55</code></a>
Version 0.20.0</li>
<li><a
href="5b6703e83a"><code>5b6703e</code></a>
Merge pull request <a
href="https://redirect.github.com/causal-agent/scraper/issues/194">#194</a>
from causal-agent/dependabot/cargo/indexmap-2.3.0</li>
<li><a
href="fd01b100ea"><code>fd01b10</code></a>
Bump indexmap from 2.2.6 to 2.3.0</li>
<li><a
href="9242d09e7d"><code>9242d09</code></a>
Merge pull request <a
href="https://redirect.github.com/causal-agent/scraper/issues/190">#190</a>
from gfaster/master</li>
<li><a
href="f5cc684a06"><code>f5cc684</code></a>
Make ElementRef Debug impl use Element</li>
<li><a
href="27dd786c06"><code>27dd786</code></a>
Merge pull request <a
href="https://redirect.github.com/causal-agent/scraper/issues/187">#187</a>
from causal-agent/support-has-selector</li>
<li><a
href="b3570f31e1"><code>b3570f3</code></a>
<code>is</code> and <code>has</code> support</li>
<li><a
href="e8e3cc4edb"><code>e8e3cc4</code></a>
Version 0.19.1</li>
<li><a
href="37b062ec65"><code>37b062e</code></a>
Merge pull request <a
href="https://redirect.github.com/causal-agent/scraper/issues/184">#184</a>
from Noname-Official/patch-1</li>
<li><a
href="3b8383dcc5"><code>3b8383d</code></a>
Text isn't a fused iterator</li>
<li>Additional commits viewable in <a
href="https://github.com/causal-agent/scraper/compare/v0.19.0...v0.20.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=scraper&package-manager=cargo&previous-version=0.19.0&new-version=0.20.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-08-07 09:07:19 +08:00
edee2a3c15 Bump indexmap from 2.2.6 to 2.3.0 (#13557)
Bumps [indexmap](https://github.com/indexmap-rs/indexmap) from 2.2.6 to
2.3.0.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/indexmap-rs/indexmap/blob/master/RELEASES.md">indexmap's
changelog</a>.</em></p>
<blockquote>
<h2>2.3.0</h2>
<ul>
<li>Added trait <code>MutableEntryKey</code> for opt-in mutable access
to map entry keys.</li>
<li>Added method <code>MutableKeys::iter_mut2</code> for opt-in mutable
iteration of map
keys and values.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="22c0b4e0f3"><code>22c0b4e</code></a>
Merge pull request <a
href="https://redirect.github.com/indexmap-rs/indexmap/issues/335">#335</a>
from epage/mut</li>
<li><a
href="39f7cc097a"><code>39f7cc0</code></a>
Release 2.3.0</li>
<li><a
href="6049d518a0"><code>6049d51</code></a>
feat(map): Add MutableKeys::iter_mut2</li>
<li><a
href="65c3c46e37"><code>65c3c46</code></a>
feat(map): Add MutableEntryKey</li>
<li><a
href="7f7d39f734"><code>7f7d39f</code></a>
Merge pull request <a
href="https://redirect.github.com/indexmap-rs/indexmap/issues/332">#332</a>
from waywardmonkeys/missing-indentation-in-doc-comment</li>
<li><a
href="8222a59a85"><code>8222a59</code></a>
Fix missing indentation in doc comment.</li>
<li><a
href="1a71dde63d"><code>1a71dde</code></a>
Merge pull request <a
href="https://redirect.github.com/indexmap-rs/indexmap/issues/327">#327</a>
from waywardmonkeys/dep-update-dev-dep-itertools</li>
<li><a
href="ac2a8a5a40"><code>ac2a8a5</code></a>
deps(dev): Update <code>itertools</code></li>
<li>See full diff in <a
href="https://github.com/indexmap-rs/indexmap/compare/2.2.6...2.3.0">compare
view</a></li>
</ul>
</details>
<br />


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

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

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

---

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

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


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-07 09:02:56 +08:00
2ced9e4d19 Add multipart/form-data uploads (#13532)
Fixes nushell/nushell#11046

# Description
This adds support for `multipart/form-data` (RFC 7578) uploads to
nushell.

Binary data is uploaded as files (`application/octet-stream`),
everything else is uploaded as plain text.

```console
$ http post https://echo.free.beeceptor.com --content-type multipart/form-data {cargo: (open -r Cargo.toml | into binary ), description: "It's some TOML"} | upsert ip "<redacted>"
╭───────────────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ method            │ POST                                                                                                                                                                    │
│ protocol          │ https                                                                                                                                                                   │
│ host              │ echo.free.beeceptor.com                                                                                                                                                 │
│ path              │ /                                                                                                                                                                       │
│ ip                │ <redacted>                                                                                                                                                              │
│                   │ ╭─────────────────┬────────────────────────────────────────────────────────────────────╮                                                                                │
│ headers           │ │ Host            │ echo.free.beeceptor.com                                            │                                                                                │
│                   │ │ User-Agent      │ nushell                                                            │                                                                                │
│                   │ │ Content-Length  │ 9453                                                               │                                                                                │
│                   │ │ Accept          │ */*                                                                │                                                                                │
│                   │ │ Accept-Encoding │ gzip                                                               │                                                                                │
│                   │ │ Content-Type    │ multipart/form-data; boundary=a15f6a14-5768-4a6a-b3a4-686a112d9e27 │                                                                                │
│                   │ ╰─────────────────┴────────────────────────────────────────────────────────────────────╯                                                                                │
│ parsedQueryParams │ {record 0 fields}                                                                                                                                                       │
│                   │ ╭─────────────────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │
│ parsedBody        │ │                 │ ╭─────────────┬────────────────╮                                                                                                                  │ │
│                   │ │ textFields      │ │ description │ It's some TOML │                                                                                                                  │ │
│                   │ │                 │ ╰─────────────┴────────────────╯                                                                                                                  │ │
│                   │ │                 │ ╭───┬───────┬──────────┬──────────────────────────┬───────────────────────────┬───────────────────────────────────────────┬────────────────╮      │ │
│                   │ │ files           │ │ # │ name  │ fileName │       Content-Type       │ Content-Transfer-Encoding │            Content-Disposition            │ Content-Length │      │ │
│                   │ │                 │ ├───┼───────┼──────────┼──────────────────────────┼───────────────────────────┼───────────────────────────────────────────┼────────────────┤      │ │
│                   │ │                 │ │ 0 │ cargo │ cargo    │ application/octet-stream │ binary                    │ form-data; name="cargo"; filename="cargo" │ 9101           │      │ │
│                   │ │                 │ ╰───┴───────┴──────────┴──────────────────────────┴───────────────────────────┴───────────────────────────────────────────┴────────────────╯      │ │
│                   │ ╰─────────────────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │
╰───────────────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
```
# User-Facing Changes
`http post --content-type multipart/form-data` now accepts a record
which is uploaded as `multipart/form-data`.
Binary data is uploaded as files (`application/octet-stream`),
everything else is uploaded as plain text.

Previously `http post --content-type multipart/form-data` rejected
records, so there's no BC break.

# Tests + Formatting

Added.

# After Submitting
- [ ] update docs to showcase new functionality
2024-08-06 15:28:38 -05:00
926331dbfb chore: Add nu_plugin_polars to build and install scripts (#13550)
- Add `nu_plugin_polars` to the list of plugins in
`build-all-maclin.sh`.
- Add `nu_plugin_polars` to the list of plugins in `build-all.nu`.
- Add `nu_plugin_polars` to the list of plugins in `install-all.ps1`.
- Add `nu_plugin_polars` to the list of plugins in `install-all.sh`.
- Add `nu_plugin_polars` to the list of plugins in `uninstall-all.sh`.

<!--
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 toolkit.nu; toolkit test stdlib"` 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-08-06 15:23:56 -05:00
eca2975b3d Fix a typo in an example (#13548)
Accidentally used the old name of the command, `random bytes`, instead
of the correct one.

Co-authored-by: Andrej Kolčin <self@kaathewise.net>
2024-08-06 13:18:49 +02:00
1cd0544a3f fix: relay Signals reset to plugins (#13510)
This PR will close #13501

# Description

This PR expands on [the relay of signals to running plugin
processes](https://github.com/nushell/nushell/pull/13181). The Ctrlc
relay has been generalized to SignalAction::Interrupt and when
reset_signal is called on the main EngineState, a SignalAction::Reset is
now relayed to running plugins.

# User-Facing Changes

The signal handler closure now takes a `signals::SignalAction`, while
previously it took no arguments. The handler will now be called on both
interrupt and reset. The method to register a handler on the plugin side
is now called `register_signal_handler` instead of
`register_ctrlc_handler`
[example](https://github.com/nushell/nushell/pull/13510/files#diff-3e04dff88fd0780a49778a3d1eede092ec729a1264b4ef07ca0d2baa859dad05L38).
This will only affect plugin authors who have started making use of
https://github.com/nushell/nushell/pull/13181, which isn't currently
part of an official release.

The change will also require all of user's plugins to be recompiled in
order that they don't error when a signal is received on the
PluginInterface.

# Testing

```
: example ctrlc
interrupt status: false
waiting for interrupt signal...
^Cinterrupt status: true
peace.
Error:   × Operation interrupted
   ╭─[display_output hook:1:1]
 1 │ if (term size).columns >= 100 { table -e } else { table }
   · ─┬
   ·  ╰── This operation was interrupted
   ╰────

: example ctrlc
interrupt status: false   <-- NOTE status is false
waiting for interrupt signal...
^Cinterrupt status: true
peace.
Error:   × Operation interrupted
   ╭─[display_output hook:1:1]
 1 │ if (term size).columns >= 100 { table -e } else { table }
   · ─┬
   ·  ╰── This operation was interrupted
   ╰────
   ```
2024-08-06 03:35:40 -07:00
73e8de9753 Attempt to guess the content type of a file when opening with --raw (#13521)
# Description
Attempt to guess the content type of a file when opening with --raw and
set it in the pipeline metadata.

<img width="644" alt="Screenshot 2024-08-02 at 11 30 10"
src="https://github.com/user-attachments/assets/071f0967-c4dd-405a-b8c8-f7aa073efa98">


# User-Facing Changes
- Content of files can be directly piped into commands like `http post`
with the content type set appropriately when using `--raw`.
2024-08-06 11:36:24 +02:00
4e83ccdf86 Allow int input when using a formatstring in into datetime (#13541)
# Description

When using a format string, `into datetime` would disallow an `int` even
when it logically made sense. This was mainly a problem when attempting
to convert a Unix epoch to Nushell `datetime`. Unix epochs are often
stored or returned as `int` in external data sources.

```nu
1722821463 | into datetime -f '%s'
Error: nu:🐚:only_supports_this_input_type

  × Input type not supported.
   ╭─[entry #3:1:1]
 1 │ 1722821463 | into datetime -f '%s'
   · ─────┬────   ──────┬──────
   ·      │             ╰── only string input data is supported
   ·      ╰── input type: int
   ╰────
```

While the solution was simply to `| to text` the `int`, this PR handles
the use-case automatically.

Essentially a ~5 line change that just moves the current parsing to a
closure that is called for both Strings and Ints-converted-to-Strings.

# User-Facing Changes

After the change:

```nu
[
  1722821463
  "1722821463"
  0
] | each { into datetime -f '%s' }
╭───┬──────────────╮
│ 0 │ 10 hours ago │
│ 1 │ 10 hours ago │
│ 2 │ 54 years ago │
╰───┴──────────────╯
```

# Tests + Formatting

Test case added.

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

# After Submitting
2024-08-05 20:05:32 -05:00
6d36941e55 Add completions.sort option (#13311) 2024-08-05 20:30:10 -04:00
2f44801414 Adding plist support (#13545)
# Description
Provides the ability convert from and to plist format.

<img width="1250" alt="Screenshot 2024-08-05 at 10 21 26"
src="https://github.com/user-attachments/assets/970f3366-eb70-4d74-a396-649374556f66">

<img width="730" alt="Screenshot 2024-08-05 at 10 22 38"
src="https://github.com/user-attachments/assets/6ec317d0-686e-47c6-bf35-8ab6e5d802db">

# User-Facing Changes
- Introduction of `from plist` command
- Introduction of `to plist`command

---------

Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2024-08-05 14:07:15 -07:00
9172b22985 Rework help generation internals (#13531)
Reworking some of the sprawling code we use to generate the `help cmd`
or `cmd --help` output.

This touches mainly the rendering and not the gathering of the necessary
data (see open bugs under
[label:help-system](https://github.com/nushell/nushell/issues?q=sort%3Aupdated-desc+is%3Aopen+label%3Ahelp-system))

Fixes #9076 
Fixes the syntax shape output on flags to be consistent.

## Example
```nushell
def test [
  positional: int,
  documented: float, # this has documentation
  default = 50,
  optional?,
  --a = "bla",
  --bla (-b) = "bla", # named with default
] {}
```

### before

![grafik](https://github.com/user-attachments/assets/1867984f-1289-4ad0-bdf5-c49ec56dfddb)


### after


![grafik](https://github.com/user-attachments/assets/8fca526f-d878-4d52-b970-fc41c7e8859c)
2024-08-05 22:44:24 +02:00
1c37f4b958 Create random binary command (#13542)
# Description/User-Facing Changes

Creates a new `random binary <LENGTH>` command, which returns random
bytes.

Resolve #13500
2024-08-05 21:07:12 +02:00
56ed532038 update to latest reedline commit 919292e (#13540)
# Description

This PR updates nushell to the latest reedline commit which has some vi
keyboard mode changes.

# 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 toolkit.nu; toolkit test stdlib"` 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-08-05 07:59:34 -05:00
b974f8f7e3 Include empty table data cells in query web tables (#13538)
# Description

Empty cells were being skipped, causing data to appear in the wrong
columns. By including the cells, data should appear in the correct
columns now. Fixes #10194.

Before:

```
$ [[a b c]; [1 null 3] [4 5 6]] | to html --partial | query web --as-table [a b c]
╭───┬───┬───┬─────────────────────╮
│ # │ a │ b │          c          │
├───┼───┼───┼─────────────────────┤
│ 0 │ 1 │ 3 │ Missing column: 'c' │
│ 1 │ 4 │ 5 │ 6                   │
╰───┴───┴───┴─────────────────────╯
```

After:

```
$ [[a b c]; [1 null 3] [4 5 6]] | to html --partial | query web --as-table [a b c]
╭───┬───┬───┬───╮
│ # │ a │ b │ c │
├───┼───┼───┼───┤
│ 0 │ 1 │   │ 3 │
│ 1 │ 4 │ 5 │ 6 │
╰───┴───┴───┴───╯
```

Co-authored-by: James Chen-Smith <jameschensmith@gmail.com>
2024-08-05 06:20:14 -05:00
802bfed173 feat: prefer exact match when completion mode is prefix (#13302)
<!--
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 #13204

# 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 the completion mode is set to `prefix`, path completions explicitly
check for and prefer an exact match for a basename instead of longer or
similar names.

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

Exact match is inactive since there's no trailing slash

```
~/Public/nushell| ls crates/nu-plugin<tab>
crates/nu-plugin/               crates/nu-plugin-core/          crates/nu-plugin-engine/        crates/nu-plugin-protocol/      
crates/nu-plugin-test-support/
```

Exact match is active

```
~/Public/nushell| ls crates/nu-plugin/<tab>
crates/nu-plugin/Cargo.toml  crates/nu-plugin/LICENSE     crates/nu-plugin/README.md   crates/nu-plugin/src/
```

Fuzzy matching persists its behavior

```
~/Public/nushell> $env.config.completions.algorithm = "fuzzy";
~/Public/nushell| ls crates/nu-plugin/car
crates/nu-cmd-plugin/Cargo.toml           crates/nu-plugin/Cargo.toml               crates/nu-plugin-core/Cargo.toml          crates/nu-plugin-engine/Cargo.toml        
crates/nu-plugin-protocol/Cargo.toml      crates/nu-plugin-test-support/Cargo.toml
```

# 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 toolkit.nu; toolkit test stdlib"` 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-08-04 06:06:10 -05:00
07e7c8c81f Fixup #13526 width flag for example (#13529)
# Description
This seems to be a minor copy paste mistake. cc @Embers-of-the-Fire

Followup to #13526

# User-Facing Changes
(-)

# Tests + Formatting
(-)
2024-08-03 16:42:30 +02:00
20b53067cd Fix overflow table display in command documentation (#13526)
# Description

Check and set table width beforehand.

Closes #13520.

# User-Facing Changes
Before:
```plain
❯ help net cmd1
network

Usage:
  > net cmd1

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

Input/output types:
  ╭───┬─────────┬─────────────────────────────────────────────────────────╮
  │ # │  input  │                         output                          │
  ├───┼─────────┼─────────────────────────────────────────────────────────┤
  │ 0 │ nothing │ table<name: string, description: string, mac: string,   │
  │   │         │ ips: table<type: string, addr: string, prefix: int>,
 │
  │   │         │ flags: record<is_up: bool, is_broadcast: bool,
 │
  │   │         │ is_loopback: bool, is_point_to_point: bool,
 │
  │   │         │ is_multicast: bool>>
 │
  ╰───┴─────────┴─────────────────────────────────────────────────────────╯
```

After:
```plain
❯ help net cmd1
network

Usage:
  > net cmd1

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

Input/output types:
  ╭───┬─────────┬───────────────────────────────────────────────────────╮
  │ # │  input  │                        output                         │
  ├───┼─────────┼───────────────────────────────────────────────────────┤
  │ 0 │ nothing │ table<name: string, description: string, mac: string, │
  │   │         │  ips: table<type: string, addr: string, prefix: int>, │
  │   │         │  flags: record<is_up: bool, is_broadcast: bool,       │
  │   │         │ is_loopback: bool, is_point_to_point: bool,           │
  │   │         │ is_multicast: bool>>                                  │
  ╰───┴─────────┴───────────────────────────────────────────────────────╯
```

# 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 toolkit.nu; toolkit test stdlib"` to run the
tests for the standard library


# After Submitting
- [x] Bug fix, no doc update.
2024-08-03 10:55:35 +02:00
f4c0d9d45b Path migration part 4: various tests (#13373)
# Description
Part 4 of replacing std::path types with nu_path types added in
https://github.com/nushell/nushell/pull/13115. This PR migrates various
tests throughout the code base.
2024-08-03 10:09:13 +02:00
85b06b22d9 Replace manual Record::get implementation (#13525)
Let's simplify here
2024-08-03 01:14:44 +02:00
63f00e78d1 Lift SharedCow::to_mut out of if let branches (#13524)
In some `if let`s we ran the `SharedCow::to_mut` for the test and to get
access to a mutable reference in the happy path. Internally
`Arc::into_mut` has to read atomics and if necessary clone.
For else branches, where we still want to modify the record we
previously called this again (not just in rust, confirmed in the asm).

This would have introduced a `call` instruction and its cost (even if it
would be guaranteed to take the short path in `Arc::into_mut`).
Lifting it get's rid of this.
2024-08-03 00:26:48 +02:00
ff1ad77130 Simplify column look-up in default (#13522)
# Description
Since we make the promise that record keys/columns are exclusice we
don't have to go through all columns after we have found the first one.
Should permit some short-circuiting if the column is found early.

# User-Facing Changes
(-)

# Tests + Formatting
(-)
2024-08-03 00:26:35 +02:00
af34d5c062 Fix internal panic for query web (#13507)
<!--
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.
-->
Original implementation contains multiple `expect` which can cause
internal runtime panic.

This pr forks the `css` selector impl and make it return an error that
nushell can recognize.

**Note:** The original impl is still used in pre-defined selector
implementations, but they
should never fail, so the `css` fn is preserved.

Closes #13496.

# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->
Now `query web` will not panic when the `query` parameter is not given
or has syntax error.

```plain
❯ .\target\debug\nu.exe -c "http get https://www.rust-lang.org | query web"
Error:   × CSS query parse error
   ╭─[source:1:38]
 1 │ http get https://www.rust-lang.org | query web
   ·                                      ────┬────
   ·                                          ╰─┤ Unexpected error occurred. Please report this to the developer
   ·                                            │ EmptySelector
   ╰────
  help: cannot parse query as a valid CSS selector
```

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

Make sure you've run and fixed any issues with these commands:
-->
- [x] `cargo fmt --all -- --check` to check standard code formatting
(`cargo fmt --all` applies these changes)
- [x] `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used`
to check that you're using the standard code style
- [x] `cargo test --workspace` to check that all tests pass (on Windows
make sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- [x] `cargo run -- -c "use toolkit.nu; toolkit test stdlib"` 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.
-->
- [x] Impl change, no doc update.

---------

Co-authored-by: Stefan Holderbach <sholderbach@users.noreply.github.com>
2024-08-02 21:47:18 +02:00
ed82f9ee18 Clarify default command help (#13519)
# Description

Updates `default` command description to be more clear and adds an
example for a missing values in a list-of-records.

# User-Facing Changes

Help/doc only

# Tests + Formatting

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

# After Submitting

- Update `nothing` doc in Book to reference `default` per
https://github.com/nushell/nushell.github.io/issues/1073 - This was a
bit of a rabbit trail on the path to that update. ;-)

---------

Co-authored-by: Stefan Holderbach <sholderbach@users.noreply.github.com>
2024-08-02 21:23:25 +02:00
d081e3386f Make pipeline metadata available to plugins (#13495)
# Description
Fixes an issue with pipeline metadata not being passed to plugins.
2024-08-02 11:01:20 -07:00
ca8eb856e8 Doc and examples for multi-dot directory traversal (#13513)
# Description

With this PR, we should be able to close
https://github.com/nushell/nushell.github.io/issues/1225

Help/doc/examples updated for:

* `cd` to show multi-dot traversal
* `cd` to show implicit `cd` with bare directory path
* Fixed/clarified another example that mentioned `$OLDPATH` while I was
in there
* `mv` and `cp` examples for multi-dot traversal
* Updated `cp` examples to use more consistent (and clear) filenames

# User-Facing Changes

Help/doc only

# Tests + Formatting

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

# After Submitting

N/A
2024-08-01 15:22:25 -05:00
168835ecd2 random chars doc clarifications (#13511)
# Description

Clarified `random chars` help/doc:

* Default string length in absence of a `--length` arg is 25
* Characters are *"uniformly distributed over ASCII letters and numbers:
a-z, A-Z and 0-9"* (copied from the [`rand` crate
doc](https://docs.rs/rand/latest/rand/distributions/struct.Alphanumeric.html).

# User-Facing Changes

Help/Doc only
2024-08-01 21:21:39 +02:00
4157ca711d Factor out style-setting code (#13406)
# Description
This is mainly cleanup, but introduces a slight (positive, if anything)
behavior change:

Some menu layouts support only a subset of styles, but with this change
the user will still be able to configure them. This seems strictly
better - if reedline starts supporting one of the existing styles for a
particular layout, there won't be any need to update nushell code.


# User-Facing Changes
None

# Tests + Formatting
This is simply factoring out existing code, old tests should still cover
it.

---------

Co-authored-by: sholderbach <sholderbach@users.noreply.github.com>
2024-08-01 11:17:58 +02:00
d34a24db33 setting content type metadata on all core to * commands (#13506)
# Description

All core `to *` set content type pipeline metadata. 

# User-Facing Changes
- For consistency, `from json` no longer sets the content type metadata

# Tests + Formatting
- 🟢 `toolkit fmt`
- 🟢 `toolkit clippy`
- 🟢 `toolkit test`
- 🟢 `toolkit test stdlib
2024-08-01 11:10:52 +02:00
2c6b1471e1 Contentious clippy fixes (#13498)
Lints from stable or nightly toolchain that may have questionable added
value.

- **Contentious lint to contract into single `if let`**
- **Potential false positive around `AsRef`/`Deref` fun**
2024-08-01 11:02:55 +02:00
ae5fed41ed Path migration part 3: $nu paths (#13368)
# Description
Part 3 of replacing `std::path` types with `nu_path` types added in
#13115. This PR targets the paths listed in `$nu`. That is, the home,
config, data, and cache directories.
2024-08-01 10:16:31 +02:00
ca73d85c09 Add --upgrade switch for mv command (#13505)
<!--
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.
-->
Add `--upgrade, -u` switch for `mv` command, corresponding to `cp`.

Closes #13458.

# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->
```plain
❯ help mv | find update
╭──────────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│        0 │   -u, --update - move and overwite only when the SOURCE file is newer than the destination file or when the destination file is missing       │
╰──────────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
```

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

Make sure you've run and fixed any issues with these commands:
-->
- [x] `cargo fmt --all -- --check` to check standard code formatting
(`cargo fmt --all` applies these changes)
- [x] `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used`
to check that you're using the standard code style
- [x] `cargo test --workspace` to check that all tests pass (on Windows
make sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- [x] `cargo run -- -c "use toolkit.nu; toolkit test stdlib"` 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
> ```
-->

P.S.  
The standard test kit (`nu-test-support`) doesn't provide utility to
create file with modification timestamp, and I didn't find any test for
this in `cp` command. I had tested on my local machine but I'm not sure
how to integrate it into ci. If unit testing is required, I may need
your guidance.

# 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.
-->
- [x] Command docs are auto generated.
2024-07-31 20:43:06 -05:00
f82c43f850 Consider numbers to be part of a word in split words (#13502)
# Description

Before this change, `"hash sha256 123 ok" | split words` would return
`[hash sha ok]` - which is surprising to say the least.

Now it will return `[hash sha256 123 ok]`.

Refs:
https://discord.com/channels/601130461678272522/615253963645911060/1268151658572025856

# User-Facing Changes
`split words` will no longer remove digits.

# Tests + Formatting
Added a test for this specific case.

# After Submitting
2024-07-31 16:35:41 -05:00
3dc9691aaa Clarify random int help (#13503)
# Description

Minor nitpicks, but the `random int` help and examples were a bit
ambiguous in several aspects. Updated to clarify that:

* An unconstrained `random int` returns a non-negative integer. That is,
the smallest potential value is 0. Technically integers include negative
numbers as well, and `random int` will never return one unless you pass
it a range with a negative lower-bound.

* To that end, changed the final example to demonstrate a negative
lower-bound.

* The range is inclusive. While most people would probably assume this,
the changes make this explicit in the examples and argument description.

# User-Facing Changes

Help only

# Tests + Formatting

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

# After Submitting

N/A
2024-07-31 16:34:38 -05:00
42531e017c Clippy fixes from stable and nightly (#13455)
- **Doccomment style fixes**
- **Forgotten stuff in `nu-pretty-hex`**
- **Don't `for` around an `Option`**
- and more

I think the suggestions here are a net positive, some of the suggestions
moved into #13498 feel somewhat arbitrary, I also raised
https://github.com/rust-lang/rust-clippy/issues/13188 as the nightly
`byte_char_slices` would require either a global allow or otherwise a
ton of granular allows or possibly confusing bytestring literals.
2024-07-31 20:37:40 +02:00
928c57db41 save: print to stderr for bytestream (#13422)
# Description
Fixes: #13260 

When user run a command like this:
```nushell
$env.FOO = " New";
$env.BAZ = " New Err";
do -i {nu -n -c 'nu --testbin echo_env FOO; nu --testbin echo_env_stderr BAZ'} | save -a -r save_test_22/log.txt
```

`save` command sinks the output of previous commands' stderr output. I
think it should be `stderr`.

# User-Facing Changes
```nushell
$env.FOO = " New";
$env.BAZ = " New Err";
do -i {nu -n -c 'nu --testbin echo_env FOO; nu --testbin echo_env_stderr BAZ'} | save -a -r save_test_22/log.txt
```
The command will output ` New Err` to stderr.

# Tests + Formatting
Added 2 cases.
2024-07-31 18:19:35 +02:00
d880241102 Bump rust toolchain (#13499)
Following the Rust 1.80 release update our supported Rust version to
1.78.0

Necessary clippy fixes in #13497
2024-07-31 18:14:50 +02:00
813aac89bd Clippy fixes for toolchain bump (#13497)
- **Suggested default impl for the new `*Stack`s**
- **Change a hashmap to make clippy happy**
- **Clone from fix**
- **Fix conditional unused in test**
- then **Bump rust toolchain**
2024-07-31 14:49:22 +02:00
d2bf82d22b Bump similar from 2.5.0 to 2.6.0 (#13492) 2024-07-31 08:10:33 +00:00
3f12b14053 Bump crate-ci/typos from 1.23.3 to 1.23.5 (#13491) 2024-07-31 02:12:50 +00:00
8e2917b9ae Make assignment and const consistent with let/mut (#13385)
# Description

This makes assignment operations and `const` behave the same way `let`
and `mut` do, absorbing the rest of the pipeline.

Changes the lexer to be able to recognize assignment operators as a
separate token, and then makes the lite parser continue to push spans
into the same command regardless of any redirections or pipes if an
assignment operator is encountered. Because the pipeline is no longer
split up by the lite parser at this point, it's trivial to just parse
the right hand side as if it were a subexpression not contained within
parentheses.

# User-Facing Changes
Big breaking change. These are all now possible:

```nushell
const path = 'a' | path join 'b'

mut x = 2
$x = random int
$x = [1 2 3] | math sum

$env.FOO = random chars
```

In the past, these would have led to (an attempt at) bare word string
parsing. So while `$env.FOO = bar` would have previously set the
environment variable `FOO` to the string `"bar"`, it now tries to run
the command named `bar`, hence the major breaking change.

However, this is desirable because it is very consistent - if you see
the `=`, you can just assume it absorbs everything else to the right of
it.

# Tests + Formatting
Added tests for the new behaviour. Adjusted some existing tests that
depended on the right hand side of assignments being parsed as
barewords.

# After Submitting
- [ ] release notes (breaking change!)
2024-07-30 18:55:22 -05:00
3c3ec7891c Links to security contacts (#13488)
# Description
Added links to the Discord server and the GitHub vulnerability report
form
2024-07-30 17:05:56 +02:00
6b839c3c32 Create security policy (#13486) 2024-07-30 16:08:24 +02:00
ea22c319b6 make math sqrt const (#13487)
# Description

Just a quick PR to demonstrate one way to make commands const.
related to https://github.com/nushell/nushell/issues/13482

# 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 toolkit.nu; toolkit test stdlib"` 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-07-30 08:53:41 -05:00
7432e67da1 don't force stripping ansi codes from strings in stor (#13464)
# Description

The current version of `stor` forces stripping ansi code coloring from
all the strings.
In this PR, I propose to keep strings unchanged.

The logic behind the proposed changes was best described in the
[discord](https://discord.com/channels/601130461678272522/601130461678272524/1266387441074442272):
<img width="773" alt="image"
src="https://github.com/user-attachments/assets/063cdebd-684f-46f1-aca1-faeb4827723d">

with proposed changes we can store colored output:
```
stor reset; stor create --table-name test --columns {a: str};
ls | table | {a: $in} | stor insert --table-name test | null;
stor open | query db 'select a from test' | get a.0 
```

<img width="704" alt="image"
src="https://github.com/user-attachments/assets/8f062808-18fc-498b-a77e-a118f6b9953a">


# User-Facing Changes

If one was using `stor` together with ansi colored input, and then was
querying `stor` with search operations, they might break. But I don't
think that it is a big problem, as one will just need to use `ansi
reset` before storing data.

# Tests + Formatting

Tests are okay.

Thanks to @fdncred for spending time to help me write these changes 🙏
2024-07-30 08:52:28 -05:00
0576794e74 reduce: supply <acc> to the closure as pipeline input as well (#13461)
<!--
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!
-->

resolve #13459

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

Make `reduce` supply the accumulator value to closure as pipeline input.

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

Mostly described in #13459

- Should not be a breaking change.
- Allows cleaner patterns like `... | reduce {|it| merge $it}`

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

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

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used` 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 toolkit.nu; toolkit test stdlib"` 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
> ```
-->
`cargo test --package nu-cli --test main -- commands::reduce` and
`toolkit test stdlib` report no issues
2024-07-30 08:51:51 -05:00
12f57dbc62 Add "--as-columns" flag to polars into-df (#13449)
<!--
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!
-->
Per discussion on
[Discord](https://discord.com/channels/601130461678272522/864228801851949077/1265718178927870045)
# 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.
-->

To facilitate column-oriented dataframe construction, this PR added a
`--as-columns` flag to `polars into-df` command so that when specified,
and when input shape is record of lists, each list will be treated as a
column rather than a cell value, i.e. `{a: [1 3], b: [2 4]} | polars
into-df --as-columns` returns the same dataframe as `[[a b];[1 2] [3 4]]
| polars into-df`


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

A new flag `--as-columns`, no change of semantics if this flag is
unspecified.

# 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 toolkit.nu; toolkit test stdlib"` 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: Ben Yang <ben@ya.ng>
2024-07-30 08:50:50 -05:00
fe57c5c22e fix: Make log respect use_ansi_coloring setting. (#13442)
# Very briefly
Fixes: #13317 
- Ignore ansi coloring on logs if this setting is true.
- Add a reset after the default left prompt (before prompt character)
which fixes all-red text when `use_ansi_coloring` is false.

# Description

## Firstly,
argumentation about the changes to `crates/nu-std/std/log.nu`

Previous behavior colored the output of all log, even when the setting
`use_ansi_coloring` was false.

![image](https://github.com/user-attachments/assets/a82991c4-ff46-455d-8dac-248de2456d78)

Current behavior honors the setting.

![image](https://github.com/user-attachments/assets/6d5365db-e05d-4d2a-8981-f22303dff081)

## Second,
While testing different scenarios, I found out that the default setting
on both (`0.95`, arch linux) and the source (`0.96`) all text was
displayed in red (the color used for the present-working-directory part
of the prompt) after setting `use_ansi_coloring` to `false` ([comment
with picture of the issue and reproduction
steps](https://github.com/nushell/nushell/issues/13317#issuecomment-2247439894)).
To which my response was adding a `(ansi reset)` at the end of the
directory part of the prompt in the default config
(`crates/nu-utils/src/sample_config/default_env.nu`) file. All later
parts follow the `use_ansi_coloring` setting and their assigned colors.

# User-Facing Changes
I would say the color, but don't know if that counts as "user-facing".

# Tests + Formatting
- Formatting was applied as advised.
- 1314 tests passed and 24 ignored, none failed.
- Clippy  did not pass due to an error on the following files:
`crates/nu-protocol/src/engine/argument.rs:81:5` and
`crates/nu-protocol/src/engine/error_handler.rs:19:5`
throwing the error `you should consider adding a 'Default'
implementation for 'ErrorHandlerStack'`.
As those files are out of the scope of the current issue, they have
**not** been changed.
2024-07-30 08:34:11 -05:00
18161e5707 Bump shadow-rs from 0.29.0 to 0.30.0 (#13436) 2024-07-30 13:33:21 +00:00
466b3899e0 Use the Default implementation of Suggestion (#13409)
# Description

Take advantage of the `Default` implementation of `Suggestion`. This in
particular should make code compatible forward-compatible with
https://github.com/nushell/reedline/pull/798.

# User-Facing Changes
None

# Tests + Formatting

Existing coverage.
2024-07-30 08:32:40 -05:00
7b82c6b482 feat: make ctrlc available to plugins (#13181)
# Description

This PR adds a new method to `EngineInterface`: `register_ctrlc_handler`
which takes a closure to run when the plugin's driving engine receives a
ctrlc-signal. It also adds a mirror of the `signals` attribute from the
main shell `EngineState`.

This is an example of how a plugin which makes a long poll http request
can end the request on ctrlc:
https://github.com/cablehead/nu_plugin_http/blob/main/src/commands/request.rs#L68-L77

To facilitate the feature, a new attribute has been added to
`EngineState`: `ctrlc_handlers`. This is a Vec of closures that will be
run when the engine's process receives a ctrlc signal.

When plugins are added to an `engine_state` during a `merge_delta`, the
engine passes the ctrlc_handlers to the plugin's
`.configure_ctrlc_handler` method, which gives the plugin a chance to
register a handler that sends a ctrlc packet through the
`PluginInterface`, if an instance of the plugin is currently running.

On the plugin side: `EngineInterface` also has a ctrlc_handlers Vec of
closures. Plugin calls can use `register_ctrlc_handler` to register a
closure that will be called in the plugin process when the
PluginInput::Ctrlc command is received.

For future reference these are some alternate places that were
investigated for tying the ctrlc trigger to transmitting a Ctrlc packet
through the `PluginInterface`:

- Directly from `src/signals.rs`: the handler there would need a
reference to the Vec<Arc<RegisteredPlugins>>, which would require us to
wrap the plugins in a Mutex, which we don't want to do.

- have `PersistentPlugin.get_plugin` pass down the engine's
CtrlcHandlers to .get and then to .spawn (if the plugin isn't already
running). Once we have CtrlcHandlers in spawn, we can register a handler
to write directly to PluginInterface. We don't want to double down on
passing engine_state to spawn this way though, as it's unpredictable
because it would depend on whether the plugin has already been spawned
or not.

- pass `ctrlc_handlers` to PersistentPlugin::new so it can store it on
itself so it's available to spawn.

- in `PersistentPlugin.spawn`, create a handler that sends to a clone of
the GC event loop's tx. this has the same issues with regards to how to
get CtrlcHandlers to the spawn method, and is more complicated than a
handler that writes directly to PluginInterface

# User-Facing Changes

No breaking changes

---------

Co-authored-by: Ian Manske <ian.manske@pm.me>
2024-07-30 08:29:18 -05:00
e3f78b8793 Keep forward slash when autocomplete on Windows (#13321)
Related #7044 

# 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 autocomplete path with `/` on Windows, paths keep with slash
instead of backslash(`\`).

If mixed both, path completion uses a last path seperator.


![image](https://github.com/nushell/nushell/assets/4014016/b09633fd-0e4a-4cd9-9c14-2bca30625804)


![image](https://github.com/nushell/nushell/assets/4014016/e1f228f8-4cce-43eb-a34a-dfa54efd2ebb)


![image](https://github.com/nushell/nushell/assets/4014016/0694443a-3017-4828-be60-5f39ffd96440)

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


![completion](https://github.com/nushell/nushell/assets/4014016/03626544-6a14-4d8b-a607-21a4472f8037)

# 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 toolkit.nu; toolkit test stdlib"` 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-07-30 08:28:41 -05:00
c31291753c Bump version to 0.96.2 (#13485)
This should be the new development version. We most likely don't need a
0.96.2 patch release. Should be free to merge PRs after this.
2024-07-29 17:20:55 -07:00
953 changed files with 18263 additions and 10433 deletions

View File

@ -13,7 +13,7 @@ body:
id: repro
attributes:
label: How to reproduce
description: Steps to reproduce the behavior
description: Steps to reproduce the behavior (including succinct code examples or screenshots of the observed behavior)
placeholder: |
1.
2.
@ -28,13 +28,6 @@ body:
placeholder: I expected nu to...
validations:
required: true
- type: textarea
id: screenshots
attributes:
label: Screenshots
description: Please add any relevant screenshots here, if any
validations:
required: false
- type: textarea
id: config
attributes:
@ -55,10 +48,3 @@ body:
| installed_plugins | binaryview, chart bar, chart line, fetch, from bson, from sqlite, inc, match, post, ps, query json, s3, selector, start, sys, textview, to bson, to sqlite, tree, xpath |
validations:
required: true
- type: textarea
id: context
attributes:
label: Additional context
description: Add any other context about the problem here.
validations:
required: false

View File

@ -57,11 +57,6 @@ jobs:
fail-fast: true
matrix:
platform: [windows-latest, macos-latest, ubuntu-20.04]
include:
- default-flags: ""
# linux CI cannot handle clipboard feature
- platform: ubuntu-20.04
default-flags: "--no-default-features --features=default-no-clipboard"
runs-on: ${{ matrix.platform }}
@ -72,7 +67,7 @@ jobs:
uses: actions-rust-lang/setup-rust-toolchain@v1.9.0
- name: Tests
run: cargo test --workspace --profile ci --exclude nu_plugin_* ${{ matrix.default-flags }}
run: cargo test --workspace --profile ci --exclude nu_plugin_*
- name: Check for clean repo
shell: bash
run: |

View File

@ -36,10 +36,10 @@ jobs:
token: ${{ secrets.WORKFLOW_TOKEN }}
- name: Setup Nushell
uses: hustcer/setup-nu@v3.12
uses: hustcer/setup-nu@v3.13
if: github.repository == 'nushell/nightly'
with:
version: 0.95.0
version: 0.97.1
# Synchronize the main branch of nightly repo with the main branch of Nushell official repo
- name: Prepare for Nightly Release
@ -78,7 +78,9 @@ jobs:
- x86_64-unknown-linux-gnu
- x86_64-unknown-linux-musl
- aarch64-unknown-linux-gnu
- aarch64-unknown-linux-musl
- armv7-unknown-linux-gnueabihf
- armv7-unknown-linux-musleabihf
- riscv64gc-unknown-linux-gnu
extra: ['bin']
include:
@ -104,8 +106,12 @@ jobs:
os: ubuntu-22.04
- target: aarch64-unknown-linux-gnu
os: ubuntu-22.04
- target: aarch64-unknown-linux-musl
os: ubuntu-22.04
- target: armv7-unknown-linux-gnueabihf
os: ubuntu-22.04
- target: armv7-unknown-linux-musleabihf
os: ubuntu-22.04
- target: riscv64gc-unknown-linux-gnu
os: ubuntu-latest
@ -128,9 +134,9 @@ jobs:
rustflags: ''
- name: Setup Nushell
uses: hustcer/setup-nu@v3.12
uses: hustcer/setup-nu@v3.13
with:
version: 0.95.0
version: 0.97.1
- name: Release Nu Binary
id: nu
@ -186,9 +192,9 @@ jobs:
ref: main
- name: Setup Nushell
uses: hustcer/setup-nu@v3.12
uses: hustcer/setup-nu@v3.13
with:
version: 0.95.0
version: 0.97.1
# Keep the last a few releases
- name: Delete Older Releases

View File

@ -84,6 +84,20 @@ if $os in ['macos-latest'] or $USE_UBUNTU {
$env.CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_LINKER = 'arm-linux-gnueabihf-gcc'
cargo-build-nu
}
'aarch64-unknown-linux-musl' => {
aria2c https://musl.cc/aarch64-linux-musl-cross.tgz
tar -xf aarch64-linux-musl-cross.tgz -C $env.HOME
$env.PATH = ($env.PATH | split row (char esep) | prepend $'($env.HOME)/aarch64-linux-musl-cross/bin')
$env.CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER = 'aarch64-linux-musl-gcc'
cargo-build-nu
}
'armv7-unknown-linux-musleabihf' => {
aria2c https://musl.cc/armv7r-linux-musleabihf-cross.tgz
tar -xf armv7r-linux-musleabihf-cross.tgz -C $env.HOME
$env.PATH = ($env.PATH | split row (char esep) | prepend $'($env.HOME)/armv7r-linux-musleabihf-cross/bin')
$env.CARGO_TARGET_ARMV7_UNKNOWN_LINUX_MUSLEABIHF_LINKER = 'armv7r-linux-musleabihf-gcc'
cargo-build-nu
}
_ => {
# musl-tools to fix 'Failed to find tool. Is `musl-gcc` installed?'
# Actually just for x86_64-unknown-linux-musl target

View File

@ -28,7 +28,9 @@ jobs:
- x86_64-unknown-linux-gnu
- x86_64-unknown-linux-musl
- aarch64-unknown-linux-gnu
- aarch64-unknown-linux-musl
- armv7-unknown-linux-gnueabihf
- armv7-unknown-linux-musleabihf
- riscv64gc-unknown-linux-gnu
extra: ['bin']
include:
@ -54,8 +56,12 @@ jobs:
os: ubuntu-22.04
- target: aarch64-unknown-linux-gnu
os: ubuntu-22.04
- target: aarch64-unknown-linux-musl
os: ubuntu-22.04
- target: armv7-unknown-linux-gnueabihf
os: ubuntu-22.04
- target: armv7-unknown-linux-musleabihf
os: ubuntu-22.04
- target: riscv64gc-unknown-linux-gnu
os: ubuntu-latest
@ -76,9 +82,9 @@ jobs:
rustflags: ''
- name: Setup Nushell
uses: hustcer/setup-nu@v3.12
uses: hustcer/setup-nu@v3.13
with:
version: 0.95.0
version: 0.97.1
- name: Release Nu Binary
id: nu

View File

@ -10,4 +10,4 @@ jobs:
uses: actions/checkout@v4.1.7
- name: Check spelling
uses: crate-ci/typos@v1.23.3
uses: crate-ci/typos@v1.24.5

1651
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.77.2"
version = "0.96.1"
rust-version = "1.79.0"
version = "0.98.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -69,18 +69,17 @@ base64 = "0.22.1"
bracoxide = "0.1.2"
brotli = "5.0"
byteorder = "1.5"
bytes = "1"
bytesize = "1.3"
calamine = "0.24.0"
chardetng = "0.1.17"
chrono = { default-features = false, version = "0.4.34" }
chrono-humanize = "0.2.3"
chrono-tz = "0.8"
convert_case = "0.6"
crossbeam-channel = "0.5.8"
crossterm = "0.27"
crossterm = "0.28.1"
csv = "1.3"
ctrlc = "3.4"
deunicode = "1.6.0"
dialoguer = { default-features = false, version = "0.11" }
digest = { default-features = false, version = "0.10" }
dirs = "5.0"
@ -90,16 +89,14 @@ encoding_rs = "0.8"
fancy-regex = "0.13"
filesize = "0.2"
filetime = "0.2"
fs_extra = "1.3"
fuzzy-matcher = "0.3"
hamcrest2 = "0.3"
heck = "0.5.0"
human-date-parser = "0.1.1"
indexmap = "2.2"
indexmap = "2.5"
indicatif = "0.17"
interprocess = "2.2.0"
is_executable = "1.0"
itertools = "0.12"
itertools = "0.13"
libc = "0.2"
libproc = "0.14"
log = "0.4"
@ -110,11 +107,12 @@ lsp-types = "0.95.0"
mach2 = "0.4"
md5 = { version = "0.10", package = "md-5" }
miette = "7.2"
mime = "0.3"
mime = "0.3.17"
mime_guess = "2.0"
mockito = { version = "1.4", default-features = false }
mockito = { version = "1.5", default-features = false }
multipart-rs = "0.1.11"
native-tls = "0.2"
nix = { version = "0.28", default-features = false }
nix = { version = "0.29", default-features = false }
notify-debouncer-full = { version = "0.3", default-features = false }
nu-ansi-term = "0.50.1"
num-format = "0.4"
@ -131,14 +129,15 @@ proc-macro-error = { version = "1.0", default-features = false }
proc-macro2 = "1.0"
procfs = "0.16.0"
pwd = "1.3"
quick-xml = "0.31.0"
quick-xml = "0.32.0"
quickcheck = "1.0"
quickcheck_macros = "1.0"
quote = "1.0"
rand = "0.8"
rand_chacha = "0.3.1"
ratatui = "0.26"
rayon = "1.10"
reedline = "0.33.0"
reedline = "0.35.0"
regex = "1.9.5"
rmp = "0.8"
rmp-serde = "1.3"
@ -147,8 +146,7 @@ roxmltree = "0.19"
rstest = { version = "0.18", default-features = false }
rusqlite = "0.31"
rust-embed = "8.5.0"
same-file = "1.0"
serde = { version = "1.0", default-features = false }
serde = { version = "1.0" }
serde_json = "1.0"
serde_urlencoded = "0.7.1"
serde_yaml = "0.9"
@ -156,7 +154,7 @@ sha2 = "0.10"
strip-ansi-escapes = "0.2.0"
syn = "2.0"
sysinfo = "0.30"
tabled = { version = "0.14.0", default-features = false }
tabled = { version = "0.16.0", default-features = false }
tempfile = "3.10"
terminal_size = "0.3"
titlecase = "2.0"
@ -182,23 +180,31 @@ windows = "0.54"
windows-sys = "0.48"
winreg = "0.52"
[workspace.lints.clippy]
# Warning: workspace lints affect library code as well as tests, so don't enable lints that would be too noisy in tests like that.
# todo = "warn"
unchecked_duration_subtraction = "warn"
[lints]
workspace = true
[dependencies]
nu-cli = { path = "./crates/nu-cli", version = "0.96.1" }
nu-cmd-base = { path = "./crates/nu-cmd-base", version = "0.96.1" }
nu-cmd-lang = { path = "./crates/nu-cmd-lang", version = "0.96.1" }
nu-cmd-plugin = { path = "./crates/nu-cmd-plugin", version = "0.96.1", optional = true }
nu-cmd-extra = { path = "./crates/nu-cmd-extra", version = "0.96.1" }
nu-command = { path = "./crates/nu-command", version = "0.96.1" }
nu-engine = { path = "./crates/nu-engine", version = "0.96.1" }
nu-explore = { path = "./crates/nu-explore", version = "0.96.1" }
nu-lsp = { path = "./crates/nu-lsp/", version = "0.96.1" }
nu-parser = { path = "./crates/nu-parser", version = "0.96.1" }
nu-path = { path = "./crates/nu-path", version = "0.96.1" }
nu-plugin-engine = { path = "./crates/nu-plugin-engine", optional = true, version = "0.96.1" }
nu-protocol = { path = "./crates/nu-protocol", version = "0.96.1" }
nu-std = { path = "./crates/nu-std", version = "0.96.1" }
nu-system = { path = "./crates/nu-system", version = "0.96.1" }
nu-utils = { path = "./crates/nu-utils", version = "0.96.1" }
nu-cli = { path = "./crates/nu-cli", version = "0.98.0" }
nu-cmd-base = { path = "./crates/nu-cmd-base", version = "0.98.0" }
nu-cmd-lang = { path = "./crates/nu-cmd-lang", version = "0.98.0" }
nu-cmd-plugin = { path = "./crates/nu-cmd-plugin", version = "0.98.0", optional = true }
nu-cmd-extra = { path = "./crates/nu-cmd-extra", version = "0.98.0" }
nu-command = { path = "./crates/nu-command", version = "0.98.0" }
nu-engine = { path = "./crates/nu-engine", version = "0.98.0" }
nu-explore = { path = "./crates/nu-explore", version = "0.98.0" }
nu-lsp = { path = "./crates/nu-lsp/", version = "0.98.0" }
nu-parser = { path = "./crates/nu-parser", version = "0.98.0" }
nu-path = { path = "./crates/nu-path", version = "0.98.0" }
nu-plugin-engine = { path = "./crates/nu-plugin-engine", optional = true, version = "0.98.0" }
nu-protocol = { path = "./crates/nu-protocol", version = "0.98.0" }
nu-std = { path = "./crates/nu-std", version = "0.98.0" }
nu-system = { path = "./crates/nu-system", version = "0.98.0" }
nu-utils = { path = "./crates/nu-utils", version = "0.98.0" }
reedline = { workspace = true, features = ["bashisms", "sqlite"] }
crossterm = { workspace = true }
@ -207,6 +213,7 @@ dirs = { workspace = true }
log = { workspace = true }
miette = { workspace = true, features = ["fancy-no-backtrace", "fancy"] }
mimalloc = { version = "0.1.42", default-features = false, optional = true }
multipart-rs = { workspace = true }
serde_json = { workspace = true }
simplelog = "0.12"
time = "0.3"
@ -227,9 +234,9 @@ nix = { workspace = true, default-features = false, features = [
] }
[dev-dependencies]
nu-test-support = { path = "./crates/nu-test-support", version = "0.96.1" }
nu-plugin-protocol = { path = "./crates/nu-plugin-protocol", version = "0.96.1" }
nu-plugin-core = { path = "./crates/nu-plugin-core", version = "0.96.1" }
nu-test-support = { path = "./crates/nu-test-support", version = "0.98.0" }
nu-plugin-protocol = { path = "./crates/nu-plugin-protocol", version = "0.98.0" }
nu-plugin-core = { path = "./crates/nu-plugin-core", version = "0.98.0" }
assert_cmd = "2.0"
dirs = { workspace = true }
tango-bench = "0.5"
@ -249,10 +256,8 @@ plugin = [
"nu-protocol/plugin",
"nu-engine/plugin",
]
default = ["default-no-clipboard", "system-clipboard"]
# Enables convenient omitting of the system-clipboard feature, as it leads to problems in ci on linux
# See https://github.com/nushell/nushell/pull/11535
default-no-clipboard = [
default = [
"plugin",
"trash-support",
"sqlite",
@ -266,6 +271,8 @@ stable = ["default"]
static-link-openssl = ["dep:openssl", "nu-cmd-lang/static-link-openssl"]
mimalloc = ["nu-cmd-lang/mimalloc", "dep:mimalloc"]
# Optional system clipboard support in `reedline`, this behavior has problematic compatibility with some systems.
# Missing X server/ Wayland can cause issues
system-clipboard = [
"reedline/system_clipboard",
"nu-cli/system-clipboard",
@ -305,7 +312,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]
[patch.crates-io]
# reedline = { git = "https://github.com/nushell/reedline", branch = "main" }
# nu-ansi-term = {git = "https://github.com/nushell/nu-ansi-term.git", branch = "main"}

29
SECURITY.md Normal file
View File

@ -0,0 +1,29 @@
# Security Policy
As a shell and programming language Nushell provides you with great powers and the potential to do dangerous things to your computer and data. Whenever there is a risk that a malicious actor can abuse a bug or a violation of documented behavior/assumptions in Nushell to harm you this is a *security* risk.
We want to fix those issues without exposing our users to unnecessary risk. Thus we want to explain our security policy.
Additional issues may be part of *safety* where the behavior of Nushell as designed and implemented can cause unintended harm or a bug causes damage without the involvement of a third party.
## Supported Versions
As Nushell is still under very active pre-stable development, the only version the core team prioritizes for security and safety fixes is the [most recent version as published on GitHub](https://github.com/nushell/nushell/releases/latest).
Only if you provide a strong reasoning and the necessary resources, will we consider blessing a backported fix with an official patch release for a previous version.
## Reporting a Vulnerability
If you suspect that a bug or behavior of Nushell can affect security or may be potentially exploitable, please report the issue to us in private.
Either reach out to the core team on [our Discord server](https://discord.gg/NtAbbGn) to arrange a private channel or use the [GitHub vulnerability reporting form](https://github.com/nushell/nushell/security/advisories/new).
Please try to answer the following questions:
- How can we reach you for further questions?
- What is the bug? Which system of Nushell may be affected?
- Do you have proof-of-concept for a potential exploit or have you observed an exploit in the wild?
- What is your assessment of the severity based on what could be impacted should the bug be exploited?
- Are additional people aware of the issue or deserve credit for identifying the issue?
We will try to get back to you within a week with:
- acknowledging the receipt of the report
- an initial plan of how we want to address this including the primary points of contact for further communication
- our preliminary assessment of how severe we judge the issue
- a proposal for how we can coordinate responsible disclosure (e.g. how we ship the bugfix, if we need to coordinate with distribution maintainers, when you can release a blog post if you want to etc.)
For purely *safety* related issues where the impact is severe by direct user action instead of malicious input or third parties, feel free to open a regular issue. If we deem that there may be an additional *security* risk on a *safety* issue we may continue discussions in a restricted forum.

View File

@ -46,8 +46,8 @@ fn setup_stack_and_engine_from_command(command: &str) -> (Stack, EngineState) {
let mut stack = Stack::new();
// Support running benchmarks with IR mode
stack.use_ir = std::env::var_os("NU_USE_IR").is_some();
// Support running benchmarks without IR mode
stack.use_ir = std::env::var_os("NU_DISABLE_IR").is_none();
evaluate_commands(
&commands,

View File

@ -5,27 +5,27 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cli"
edition = "2021"
license = "MIT"
name = "nu-cli"
version = "0.96.1"
version = "0.98.0"
[lib]
bench = false
[dev-dependencies]
nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.96.1" }
nu-command = { path = "../nu-command", version = "0.96.1" }
nu-test-support = { path = "../nu-test-support", version = "0.96.1" }
nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.98.0" }
nu-command = { path = "../nu-command", version = "0.98.0" }
nu-test-support = { path = "../nu-test-support", version = "0.98.0" }
rstest = { workspace = true, default-features = false }
tempfile = { workspace = true }
[dependencies]
nu-cmd-base = { path = "../nu-cmd-base", version = "0.96.1" }
nu-engine = { path = "../nu-engine", version = "0.96.1" }
nu-path = { path = "../nu-path", version = "0.96.1" }
nu-parser = { path = "../nu-parser", version = "0.96.1" }
nu-plugin-engine = { path = "../nu-plugin-engine", version = "0.96.1", optional = true }
nu-protocol = { path = "../nu-protocol", version = "0.96.1" }
nu-utils = { path = "../nu-utils", version = "0.96.1" }
nu-color-config = { path = "../nu-color-config", version = "0.96.1" }
nu-cmd-base = { path = "../nu-cmd-base", version = "0.98.0" }
nu-engine = { path = "../nu-engine", version = "0.98.0" }
nu-path = { path = "../nu-path", version = "0.98.0" }
nu-parser = { path = "../nu-parser", version = "0.98.0" }
nu-plugin-engine = { path = "../nu-plugin-engine", version = "0.98.0", optional = true }
nu-protocol = { path = "../nu-protocol", version = "0.98.0" }
nu-utils = { path = "../nu-utils", version = "0.98.0" }
nu-color-config = { path = "../nu-color-config", version = "0.98.0" }
nu-ansi-term = { workspace = true }
reedline = { workspace = true, features = ["bashisms", "sqlite"] }
@ -47,3 +47,6 @@ which = { workspace = true }
[features]
plugin = ["nu-plugin-engine"]
system-clipboard = ["reedline/system_clipboard"]
[lints]
workspace = true

View File

@ -14,7 +14,7 @@ impl Command for Commandline {
.category(Category::Core)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"View the current command line input buffer."
}

View File

@ -34,7 +34,7 @@ impl Command for SubCommand {
.category(Category::Core)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Modify the current command line input buffer."
}

View File

@ -16,7 +16,7 @@ impl Command for SubCommand {
.category(Category::Core)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Get the current cursor position."
}

View File

@ -22,7 +22,7 @@ impl Command for SubCommand {
.category(Category::Core)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Set the current cursor position."
}

View File

@ -13,7 +13,7 @@ impl Command for History {
"history"
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Get the command history."
}
@ -55,7 +55,7 @@ impl Command for History {
HistoryFileFormat::Sqlite => {
history_path.push("history.sqlite3");
}
HistoryFileFormat::PlainText => {
HistoryFileFormat::Plaintext => {
history_path.push("history.txt");
}
}
@ -67,7 +67,7 @@ impl Command for History {
} else {
let history_reader: Option<Box<dyn ReedlineHistory>> = match history.file_format {
HistoryFileFormat::Sqlite => {
SqliteBackedHistory::with_file(history_path.clone(), None, None)
SqliteBackedHistory::with_file(history_path.clone().into(), None, None)
.map(|inner| {
let boxed: Box<dyn ReedlineHistory> = Box::new(inner);
boxed
@ -75,9 +75,9 @@ impl Command for History {
.ok()
}
HistoryFileFormat::PlainText => FileBackedHistory::with_file(
HistoryFileFormat::Plaintext => FileBackedHistory::with_file(
history.max_size as usize,
history_path.clone(),
history_path.clone().into(),
)
.map(|inner| {
let boxed: Box<dyn ReedlineHistory> = Box::new(inner);
@ -87,7 +87,7 @@ impl Command for History {
};
match history.file_format {
HistoryFileFormat::PlainText => Ok(history_reader
HistoryFileFormat::Plaintext => Ok(history_reader
.and_then(|h| {
h.search(SearchQuery::everything(SearchDirection::Forward, None))
.ok()
@ -156,58 +156,34 @@ fn create_history_record(idx: usize, entry: HistoryItem, long: bool, head: Span)
//2. Create a record of either short or long columns and values
let item_id_value = Value::int(
match entry.id {
Some(id) => {
let ids = id.to_string();
match ids.parse::<i64>() {
Ok(i) => i,
_ => 0i64,
}
}
None => 0i64,
},
entry
.id
.and_then(|id| id.to_string().parse::<i64>().ok())
.unwrap_or_default(),
head,
);
let start_timestamp_value = Value::string(
match entry.start_timestamp {
Some(time) => time.to_string(),
None => "".into(),
},
entry
.start_timestamp
.map(|time| time.to_string())
.unwrap_or_default(),
head,
);
let command_value = Value::string(entry.command_line, head);
let session_id_value = Value::int(
match entry.session_id {
Some(sid) => {
let sids = sid.to_string();
match sids.parse::<i64>() {
Ok(i) => i,
_ => 0i64,
}
}
None => 0i64,
},
head,
);
let hostname_value = Value::string(
match entry.hostname {
Some(host) => host,
None => "".into(),
},
head,
);
let cwd_value = Value::string(
match entry.cwd {
Some(cwd) => cwd,
None => "".into(),
},
entry
.session_id
.and_then(|id| id.to_string().parse::<i64>().ok())
.unwrap_or_default(),
head,
);
let hostname_value = Value::string(entry.hostname.unwrap_or_default(), head);
let cwd_value = Value::string(entry.cwd.unwrap_or_default(), head);
let duration_value = Value::duration(
match entry.duration {
Some(d) => d.as_nanos().try_into().unwrap_or(0),
None => 0,
},
entry
.duration
.and_then(|d| d.as_nanos().try_into().ok())
.unwrap_or(0),
head,
);
let exit_status_value = Value::int(entry.exit_status.unwrap_or(0), head);

View File

@ -8,7 +8,7 @@ impl Command for HistorySession {
"history session"
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Get the command history session."
}

View File

@ -14,11 +14,11 @@ impl Command for Keybindings {
.input_output_types(vec![(Type::Nothing, Type::String)])
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Keybindings related commands."
}
fn extra_usage(&self) -> &str {
fn extra_description(&self) -> &str {
r#"You must use one of the following subcommands. Using this command as-is will only produce this help message.
For more information on input and keybindings, check:

View File

@ -15,7 +15,7 @@ impl Command for KeybindingsDefault {
.input_output_types(vec![(Type::Nothing, Type::table())])
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"List default keybindings."
}

View File

@ -23,7 +23,7 @@ impl Command for KeybindingsList {
.category(Category::Platform)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"List available options that can be used to create keybindings."
}

View File

@ -12,11 +12,11 @@ impl Command for KeybindingsListen {
"keybindings listen"
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Get input from the user."
}
fn extra_usage(&self) -> &str {
fn extra_description(&self) -> &str {
"This is an internal debugging tool. For better output, try `input listen --types [key]`"
}

View File

@ -1,5 +1,5 @@
use crate::{
completions::{Completer, CompletionOptions, MatchAlgorithm, SortBy},
completions::{Completer, CompletionOptions, MatchAlgorithm},
SuggestionKind,
};
use nu_parser::FlatShape;
@ -51,7 +51,9 @@ impl CommandCompletion {
if working_set
.permanent_state
.config
.max_external_completion_results
.completions
.external
.max_results
> executables.len() as i64
&& !executables.contains(
&item
@ -99,10 +101,9 @@ impl CommandCompletion {
suggestion: Suggestion {
value: String::from_utf8_lossy(&x.0).to_string(),
description: x.1,
style: None,
extra: None,
span: reedline::Span::new(span.start - offset, span.end - offset),
append_whitespace: true,
..Suggestion::default()
},
kind: Some(SuggestionKind::Command(x.2)),
})
@ -118,11 +119,9 @@ impl CommandCompletion {
.map(move |x| SemanticSuggestion {
suggestion: Suggestion {
value: x,
description: None,
style: None,
extra: None,
span: reedline::Span::new(span.start - offset, span.end - offset),
append_whitespace: true,
..Suggestion::default()
},
// TODO: is there a way to create a test?
kind: None,
@ -136,11 +135,9 @@ impl CommandCompletion {
results.push(SemanticSuggestion {
suggestion: Suggestion {
value: format!("^{}", external.suggestion.value),
description: None,
style: None,
extra: None,
span: external.suggestion.span,
append_whitespace: true,
..Suggestion::default()
},
kind: external.kind,
})
@ -198,11 +195,7 @@ impl Completer for CommandCompletion {
};
if !subcommands.is_empty() {
return sort_suggestions(
&String::from_utf8_lossy(&prefix),
subcommands,
SortBy::LevenshteinDistance,
);
return sort_suggestions(&String::from_utf8_lossy(&prefix), subcommands, options);
}
let config = working_set.get_config();
@ -220,18 +213,14 @@ impl Completer for CommandCompletion {
working_set,
span,
offset,
config.enable_external_completion,
config.completions.external.enable,
options.match_algorithm,
)
} else {
vec![]
};
sort_suggestions(
&String::from_utf8_lossy(&prefix),
commands,
SortBy::LevenshteinDistance,
)
sort_suggestions(&String::from_utf8_lossy(&prefix), commands, options)
}
}

View File

@ -46,8 +46,9 @@ impl NuCompleter {
let config = self.engine_state.get_config();
let options = CompletionOptions {
case_sensitive: config.case_sensitive_completions,
match_algorithm: config.completion_algorithm.into(),
case_sensitive: config.completions.case_sensitive,
match_algorithm: config.completions.algorithm.into(),
sort: config.completions.sort,
..Default::default()
};
@ -207,7 +208,7 @@ impl NuCompleter {
// We got no results for internal completion
// now we can check if external completer is set and use it
if let Some(closure) = config.external_completer.as_ref() {
if let Some(closure) = config.completions.external.completer.as_ref() {
if let Some(external_result) =
self.external_completion(closure, &spans, fake_offset, new_span)
{
@ -337,7 +338,9 @@ impl NuCompleter {
}
// Try to complete using an external completer (if set)
if let Some(closure) = config.external_completer.as_ref() {
if let Some(closure) =
config.completions.external.completer.as_ref()
{
if let Some(external_result) = self.external_completion(
closure,
&spans,
@ -443,14 +446,11 @@ pub fn map_value_completions<'a>(
return Some(SemanticSuggestion {
suggestion: Suggestion {
value: s,
description: None,
style: None,
extra: None,
span: reedline::Span {
start: span.start - offset,
end: span.end - offset,
},
append_whitespace: false,
..Suggestion::default()
},
kind: Some(SuggestionKind::Type(x.get_type())),
});
@ -460,14 +460,11 @@ pub fn map_value_completions<'a>(
if let Ok(record) = x.as_record() {
let mut suggestion = Suggestion {
value: String::from(""), // Initialize with empty string
description: None,
style: None,
extra: None,
span: reedline::Span {
start: span.start - offset,
end: span.end - offset,
},
append_whitespace: false,
..Suggestion::default()
};
// Iterate the cols looking for `value` and `description`

View File

@ -1,20 +1,19 @@
use super::MatchAlgorithm;
use crate::{
completions::{matches, CompletionOptions},
SemanticSuggestion,
};
use fuzzy_matcher::{skim::SkimMatcherV2, FuzzyMatcher};
use nu_ansi_term::Style;
use nu_engine::env_to_string;
use nu_path::dots::expand_ndots;
use nu_path::{expand_to_real_path, home_dir};
use nu_protocol::{
engine::{EngineState, Stack, StateWorkingSet},
levenshtein_distance, Span,
CompletionSort, Span,
};
use nu_utils::get_ls_colors;
use std::path::{
is_separator, Component, Path, PathBuf, MAIN_SEPARATOR as SEP, MAIN_SEPARATOR_STR,
};
use super::SortBy;
use std::path::{is_separator, Component, Path, PathBuf, MAIN_SEPARATOR as SEP};
#[derive(Clone, Default)]
pub struct PathBuiltFromString {
@ -22,22 +21,31 @@ pub struct PathBuiltFromString {
isdir: bool,
}
fn complete_rec(
/// Recursively goes through paths that match a given `partial`.
/// built: State struct for a valid matching path built so far.
///
/// `isdir`: whether the current partial path has a trailing slash.
/// Parsing a path string into a pathbuf loses that bit of information.
///
/// want_directory: Whether we want only directories as completion matches.
/// Some commands like `cd` can only be run on directories whereas others
/// like `ls` can be run on regular files as well.
pub fn complete_rec(
partial: &[&str],
built: &PathBuiltFromString,
cwd: &Path,
options: &CompletionOptions,
dir: bool,
want_directory: bool,
isdir: bool,
) -> Vec<PathBuiltFromString> {
let mut completions = vec![];
if let Some((&base, rest)) = partial.split_first() {
if (base == "." || base == "..") && (isdir || !rest.is_empty()) {
if base.chars().all(|c| c == '.') && (isdir || !rest.is_empty()) {
let mut built = built.clone();
built.parts.push(base.to_string());
built.isdir = true;
return complete_rec(rest, &built, cwd, options, dir, isdir);
return complete_rec(rest, &built, cwd, options, want_directory, isdir);
}
}
@ -58,24 +66,41 @@ fn complete_rec(
built.parts.push(entry_name.clone());
built.isdir = entry_isdir;
if !dir || entry_isdir {
if !want_directory || entry_isdir {
entries.push((entry_name, built));
}
}
let prefix = partial.first().unwrap_or(&"");
let sorted_entries = sort_completions(prefix, entries, SortBy::Ascending, |(entry, _)| entry);
let sorted_entries = sort_completions(prefix, entries, options, |(entry, _)| entry);
for (entry_name, built) in sorted_entries {
match partial.split_first() {
Some((base, rest)) => {
if matches(base, &entry_name, options) {
// We use `isdir` to confirm that the current component has
// at least one next component or a slash.
// Serves as confirmation to ignore longer completions for
// components in between.
if !rest.is_empty() || isdir {
completions.extend(complete_rec(rest, &built, cwd, options, dir, isdir));
completions.extend(complete_rec(
rest,
&built,
cwd,
options,
want_directory,
isdir,
));
} else {
completions.push(built);
}
}
if entry_name.eq(base)
&& matches!(options.match_algorithm, MatchAlgorithm::Prefix)
&& isdir
{
break;
}
}
None => {
completions.push(built);
@ -93,16 +118,16 @@ enum OriginalCwd {
}
impl OriginalCwd {
fn apply(&self, mut p: PathBuiltFromString) -> String {
fn apply(&self, mut p: PathBuiltFromString, path_separator: char) -> String {
match self {
Self::None => {}
Self::Home => p.parts.insert(0, "~".to_string()),
Self::Prefix(s) => p.parts.insert(0, s.clone()),
};
let mut ret = p.parts.join(MAIN_SEPARATOR_STR);
let mut ret = p.parts.join(&path_separator.to_string());
if p.isdir {
ret.push(SEP);
ret.push(path_separator);
}
ret
}
@ -131,10 +156,27 @@ pub fn complete_item(
engine_state: &EngineState,
stack: &Stack,
) -> Vec<(nu_protocol::Span, String, Option<Style>)> {
let partial = surround_remove(partial);
let isdir = partial.ends_with(is_separator);
let cleaned_partial = surround_remove(partial);
let isdir = cleaned_partial.ends_with(is_separator);
let expanded_partial = expand_ndots(Path::new(&cleaned_partial));
let should_collapse_dots = expanded_partial != Path::new(&cleaned_partial);
let mut partial = expanded_partial.to_string_lossy().to_string();
#[cfg(unix)]
let path_separator = SEP;
#[cfg(windows)]
let path_separator = cleaned_partial
.chars()
.rfind(|c: &char| is_separator(*c))
.unwrap_or(SEP);
// Handle the trailing dot case
if cleaned_partial.ends_with(&format!("{path_separator}.")) {
partial.push_str(&format!("{path_separator}."));
}
let cwd_pathbuf = Path::new(cwd).to_path_buf();
let ls_colors = (engine_state.config.use_ls_colors_completions
let ls_colors = (engine_state.config.completions.use_ls_colors
&& engine_state.config.use_ansi_coloring)
.then(|| {
let ls_colors_env_str = match stack.get_env_var(engine_state, "LS_COLORS") {
@ -152,16 +194,11 @@ pub fn complete_item(
match components.peek().cloned() {
Some(c @ Component::Prefix(..)) => {
// windows only by definition
components.next();
if let Some(Component::RootDir) = components.peek().cloned() {
components.next();
};
cwd = [c, Component::RootDir].iter().collect();
prefix_len = c.as_os_str().len();
original_cwd = OriginalCwd::Prefix(c.as_os_str().to_string_lossy().into_owned());
}
Some(c @ Component::RootDir) => {
components.next();
// This is kind of a hack. When joining an empty string with the rest,
// we add the slash automagically
cwd = PathBuf::from(c.as_os_str());
@ -169,8 +206,7 @@ pub fn complete_item(
original_cwd = OriginalCwd::Prefix(String::new());
}
Some(Component::Normal(home)) if home.to_string_lossy() == "~" => {
components.next();
cwd = home_dir().unwrap_or(cwd_pathbuf);
cwd = home_dir().map(Into::into).unwrap_or(cwd_pathbuf);
prefix_len = 1;
original_cwd = OriginalCwd::Home;
}
@ -194,8 +230,11 @@ pub fn complete_item(
isdir,
)
.into_iter()
.map(|p| {
let path = original_cwd.apply(p);
.map(|mut p| {
if should_collapse_dots {
p = collapse_ndots(p);
}
let path = original_cwd.apply(p, path_separator);
let style = ls_colors.as_ref().map(|lsc| {
lsc.style_for_path_with_metadata(
&path,
@ -273,33 +312,71 @@ pub fn adjust_if_intermediate(
pub fn sort_suggestions(
prefix: &str,
items: Vec<SemanticSuggestion>,
sort_by: SortBy,
options: &CompletionOptions,
) -> Vec<SemanticSuggestion> {
sort_completions(prefix, items, sort_by, |it| &it.suggestion.value)
sort_completions(prefix, items, options, |it| &it.suggestion.value)
}
/// # Arguments
/// * `prefix` - What the user's typed, for sorting by Levenshtein distance
/// * `prefix` - What the user's typed, for sorting by fuzzy matcher score
pub fn sort_completions<T>(
prefix: &str,
mut items: Vec<T>,
sort_by: SortBy,
options: &CompletionOptions,
get_value: fn(&T) -> &str,
) -> Vec<T> {
// Sort items
match sort_by {
SortBy::LevenshteinDistance => {
if options.sort == CompletionSort::Smart && options.match_algorithm == MatchAlgorithm::Fuzzy {
let mut matcher = SkimMatcherV2::default();
if options.case_sensitive {
matcher = matcher.respect_case();
} else {
matcher = matcher.ignore_case();
};
items.sort_by(|a, b| {
let a_distance = levenshtein_distance(prefix, get_value(a));
let b_distance = levenshtein_distance(prefix, get_value(b));
a_distance.cmp(&b_distance)
let a_str = get_value(a);
let b_str = get_value(b);
let a_score = matcher.fuzzy_match(a_str, prefix).unwrap_or_default();
let b_score = matcher.fuzzy_match(b_str, prefix).unwrap_or_default();
b_score.cmp(&a_score).then(a_str.cmp(b_str))
});
}
SortBy::Ascending => {
} else {
items.sort_by(|a, b| get_value(a).cmp(get_value(b)));
}
SortBy::None => {}
};
items
}
/// Collapse multiple ".." components into n-dots.
///
/// It performs the reverse operation of `expand_ndots`, collapsing sequences of ".." into n-dots,
/// such as "..." and "....".
///
/// The resulting path will use platform-specific path separators, regardless of what path separators were used in the input.
fn collapse_ndots(path: PathBuiltFromString) -> PathBuiltFromString {
let mut result = PathBuiltFromString {
parts: Vec::with_capacity(path.parts.len()),
isdir: path.isdir,
};
let mut dot_count = 0;
for part in path.parts {
if part == ".." {
dot_count += 1;
} else {
if dot_count > 0 {
result.parts.push(".".repeat(dot_count + 1));
dot_count = 0;
}
result.parts.push(part);
}
}
// Add any remaining dots
if dot_count > 0 {
result.parts.push(".".repeat(dot_count + 1));
}
result
}

View File

@ -1,17 +1,10 @@
use fuzzy_matcher::{skim::SkimMatcherV2, FuzzyMatcher};
use nu_parser::trim_quotes_str;
use nu_protocol::CompletionAlgorithm;
use nu_protocol::{CompletionAlgorithm, CompletionSort};
use std::fmt::Display;
#[derive(Copy, Clone)]
pub enum SortBy {
LevenshteinDistance,
Ascending,
None,
}
/// Describes how suggestions should be matched.
#[derive(Copy, Clone, Debug)]
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum MatchAlgorithm {
/// Only show suggestions which begin with the given input
///
@ -96,6 +89,7 @@ pub struct CompletionOptions {
pub case_sensitive: bool,
pub positional: bool,
pub match_algorithm: MatchAlgorithm,
pub sort: CompletionSort,
}
impl Default for CompletionOptions {
@ -104,6 +98,7 @@ impl Default for CompletionOptions {
case_sensitive: true,
positional: true,
match_algorithm: MatchAlgorithm::Prefix,
sort: Default::default(),
}
}
}

View File

@ -1,13 +1,13 @@
use crate::completions::{
completer::map_value_completions, Completer, CompletionOptions, MatchAlgorithm,
SemanticSuggestion, SortBy,
SemanticSuggestion,
};
use nu_engine::eval_call;
use nu_protocol::{
ast::{Argument, Call, Expr, Expression},
debugger::WithoutDebug,
engine::{Stack, StateWorkingSet},
PipelineData, Span, Type, Value,
CompletionSort, PipelineData, Span, Type, Value,
};
use nu_utils::IgnoreCaseExt;
use std::collections::HashMap;
@ -18,7 +18,6 @@ pub struct CustomCompletion {
stack: Stack,
decl_id: usize,
line: String,
sort_by: SortBy,
}
impl CustomCompletion {
@ -27,7 +26,6 @@ impl CustomCompletion {
stack,
decl_id,
line,
sort_by: SortBy::None,
}
}
}
@ -93,10 +91,6 @@ impl Completer for CustomCompletion {
.and_then(|val| val.as_bool().ok())
.unwrap_or(false);
if should_sort {
self.sort_by = SortBy::Ascending;
}
custom_completion_options = Some(CompletionOptions {
case_sensitive: options
.get("case_sensitive")
@ -114,6 +108,11 @@ impl Completer for CustomCompletion {
.unwrap_or(MatchAlgorithm::Prefix),
None => completion_options.match_algorithm,
},
sort: if should_sort {
CompletionSort::Alphabetical
} else {
CompletionSort::Smart
},
});
}
@ -124,12 +123,11 @@ impl Completer for CustomCompletion {
})
.unwrap_or_default();
let suggestions = if let Some(custom_completion_options) = custom_completion_options {
filter(&prefix, suggestions, &custom_completion_options)
} else {
filter(&prefix, suggestions, completion_options)
};
sort_suggestions(&String::from_utf8_lossy(&prefix), suggestions, self.sort_by)
let options = custom_completion_options
.as_ref()
.unwrap_or(completion_options);
let suggestions = filter(&prefix, suggestions, options);
sort_suggestions(&String::from_utf8_lossy(&prefix), suggestions, options)
}
}

View File

@ -48,14 +48,12 @@ impl Completer for DirectoryCompletion {
.map(move |x| SemanticSuggestion {
suggestion: Suggestion {
value: x.1,
description: None,
style: x.2,
extra: None,
span: reedline::Span {
start: x.0.start - offset,
end: x.0.end - offset,
},
append_whitespace: false,
..Suggestion::default()
},
// TODO????
kind: None,

View File

@ -6,7 +6,7 @@ use nu_protocol::{
use reedline::Suggestion;
use std::path::{is_separator, Path, MAIN_SEPARATOR as SEP, MAIN_SEPARATOR_STR};
use super::{completion_common::sort_suggestions, SemanticSuggestion, SortBy};
use super::{completion_common::sort_suggestions, SemanticSuggestion};
#[derive(Clone, Default)]
pub struct DotNuCompletion {}
@ -116,14 +116,13 @@ impl Completer for DotNuCompletion {
.map(move |x| SemanticSuggestion {
suggestion: Suggestion {
value: x.1,
description: None,
style: x.2,
extra: None,
span: reedline::Span {
start: x.0.start - offset,
end: x.0.end - offset,
},
append_whitespace: true,
..Suggestion::default()
},
// TODO????
kind: None,
@ -131,6 +130,6 @@ impl Completer for DotNuCompletion {
})
.collect();
sort_suggestions(&prefix_str, output, SortBy::Ascending)
sort_suggestions(&prefix_str, output, options)
}
}

View File

@ -53,14 +53,12 @@ impl Completer for FileCompletion {
.map(move |x| SemanticSuggestion {
suggestion: Suggestion {
value: x.1,
description: None,
style: x.2,
extra: None,
span: reedline::Span {
start: x.0.start - offset,
end: x.0.end - offset,
},
append_whitespace: false,
..Suggestion::default()
},
// TODO????
kind: None,

View File

@ -1,6 +1,4 @@
use crate::completions::{
completion_common::sort_suggestions, Completer, CompletionOptions, SortBy,
};
use crate::completions::{completion_common::sort_suggestions, Completer, CompletionOptions};
use nu_protocol::{
ast::{Expr, Expression},
engine::{Stack, StateWorkingSet},
@ -51,13 +49,12 @@ impl Completer for FlagCompletion {
suggestion: Suggestion {
value: String::from_utf8_lossy(&named).to_string(),
description: Some(flag_desc.to_string()),
style: None,
extra: None,
span: reedline::Span {
start: span.start - offset,
end: span.end - offset,
},
append_whitespace: true,
..Suggestion::default()
},
// TODO????
kind: None,
@ -78,13 +75,12 @@ impl Completer for FlagCompletion {
suggestion: Suggestion {
value: String::from_utf8_lossy(&named).to_string(),
description: Some(flag_desc.to_string()),
style: None,
extra: None,
span: reedline::Span {
start: span.start - offset,
end: span.end - offset,
},
append_whitespace: true,
..Suggestion::default()
},
// TODO????
kind: None,
@ -92,7 +88,7 @@ impl Completer for FlagCompletion {
}
}
return sort_suggestions(&String::from_utf8_lossy(&prefix), output, SortBy::Ascending);
return sort_suggestions(&String::from_utf8_lossy(&prefix), output, options);
}
vec![]

View File

@ -13,7 +13,7 @@ mod variable_completions;
pub use base::{Completer, SemanticSuggestion, SuggestionKind};
pub use command_completions::CommandCompletion;
pub use completer::NuCompleter;
pub use completion_options::{CompletionOptions, MatchAlgorithm, SortBy};
pub use completion_options::{CompletionOptions, MatchAlgorithm};
pub use custom_completions::CustomCompletion;
pub use directory_completions::DirectoryCompletion;
pub use dotnu_completions::DotNuCompletion;

View File

@ -9,7 +9,7 @@ use nu_protocol::{
use reedline::Suggestion;
use std::str;
use super::{completion_common::sort_suggestions, SortBy};
use super::completion_common::sort_suggestions;
#[derive(Clone)]
pub struct VariableCompletion {
@ -72,7 +72,7 @@ impl Completer for VariableCompletion {
}
}
return sort_suggestions(&prefix_str, output, SortBy::Ascending);
return sort_suggestions(&prefix_str, output, options);
}
} else {
// No nesting provided, return all env vars
@ -85,18 +85,15 @@ impl Completer for VariableCompletion {
output.push(SemanticSuggestion {
suggestion: Suggestion {
value: env_var.0,
description: None,
style: None,
extra: None,
span: current_span,
append_whitespace: false,
..Suggestion::default()
},
kind: Some(SuggestionKind::Type(env_var.1.get_type())),
});
}
}
return sort_suggestions(&prefix_str, output, SortBy::Ascending);
return sort_suggestions(&prefix_str, output, options);
}
}
@ -120,7 +117,7 @@ impl Completer for VariableCompletion {
}
}
return sort_suggestions(&prefix_str, output, SortBy::Ascending);
return sort_suggestions(&prefix_str, output, options);
}
}
@ -142,7 +139,7 @@ impl Completer for VariableCompletion {
}
}
return sort_suggestions(&prefix_str, output, SortBy::Ascending);
return sort_suggestions(&prefix_str, output, options);
}
}
}
@ -157,11 +154,8 @@ impl Completer for VariableCompletion {
output.push(SemanticSuggestion {
suggestion: Suggestion {
value: builtin.to_string(),
description: None,
style: None,
extra: None,
span: current_span,
append_whitespace: false,
..Suggestion::default()
},
// TODO is there a way to get the VarId to get the type???
kind: None,
@ -184,11 +178,8 @@ impl Completer for VariableCompletion {
output.push(SemanticSuggestion {
suggestion: Suggestion {
value: String::from_utf8_lossy(v.0).to_string(),
description: None,
style: None,
extra: None,
span: current_span,
append_whitespace: false,
..Suggestion::default()
},
kind: Some(SuggestionKind::Type(
working_set.get_variable(*v.1).ty.clone(),
@ -215,11 +206,8 @@ impl Completer for VariableCompletion {
output.push(SemanticSuggestion {
suggestion: Suggestion {
value: String::from_utf8_lossy(v.0).to_string(),
description: None,
style: None,
extra: None,
span: current_span,
append_whitespace: false,
..Suggestion::default()
},
kind: Some(SuggestionKind::Type(
working_set.get_variable(*v.1).ty.clone(),
@ -229,7 +217,7 @@ impl Completer for VariableCompletion {
}
}
output = sort_suggestions(&prefix_str, output, SortBy::Ascending);
output = sort_suggestions(&prefix_str, output, options);
output.dedup(); // TODO: Removes only consecutive duplicates, is it intended?
@ -255,11 +243,8 @@ fn nested_suggestions(
output.push(SemanticSuggestion {
suggestion: Suggestion {
value: col.clone(),
description: None,
style: None,
extra: None,
span: current_span,
append_whitespace: false,
..Suggestion::default()
},
kind: Some(kind.clone()),
});
@ -272,11 +257,8 @@ fn nested_suggestions(
output.push(SemanticSuggestion {
suggestion: Suggestion {
value: column_name,
description: None,
style: None,
extra: None,
span: current_span,
append_whitespace: false,
..Suggestion::default()
},
kind: Some(kind.clone()),
});

View File

@ -2,10 +2,10 @@ use crate::util::eval_source;
#[cfg(feature = "plugin")]
use nu_path::canonicalize_with;
#[cfg(feature = "plugin")]
use nu_protocol::{engine::StateWorkingSet, report_error, ParseError, PluginRegistryFile, Spanned};
use nu_protocol::{engine::StateWorkingSet, ParseError, PluginRegistryFile, Spanned};
use nu_protocol::{
engine::{EngineState, Stack},
report_error_new, HistoryFileFormat, PipelineData,
report_shell_error, HistoryFileFormat, PipelineData,
};
#[cfg(feature = "plugin")]
use nu_utils::perf;
@ -36,7 +36,7 @@ pub fn read_plugin_file(
.and_then(|p| Path::new(&p.item).extension())
.is_some_and(|ext| ext == "nu")
{
report_error_new(
report_shell_error(
engine_state,
&ShellError::GenericError {
error: "Wrong plugin file format".into(),
@ -81,7 +81,7 @@ pub fn read_plugin_file(
return;
}
} else {
report_error_new(
report_shell_error(
engine_state,
&ShellError::GenericError {
error: format!(
@ -113,7 +113,7 @@ pub fn read_plugin_file(
Ok(contents) => contents,
Err(err) => {
log::warn!("Failed to read plugin registry file: {err:?}");
report_error_new(
report_shell_error(
engine_state,
&ShellError::GenericError {
error: format!(
@ -146,7 +146,7 @@ pub fn read_plugin_file(
nu_plugin_engine::load_plugin_file(&mut working_set, &contents, span);
if let Err(err) = engine_state.merge_delta(working_set.render()) {
report_error_new(engine_state, &err);
report_shell_error(engine_state, &err);
return;
}
@ -166,7 +166,7 @@ pub fn add_plugin_file(
) {
use std::path::Path;
let working_set = StateWorkingSet::new(engine_state);
use nu_protocol::report_parse_error;
if let Ok(cwd) = engine_state.cwd_as_string(None) {
if let Some(plugin_file) = plugin_file {
@ -181,8 +181,8 @@ pub fn add_plugin_file(
engine_state.plugin_path = Some(path)
} else {
// It's an error if the directory for the plugin file doesn't exist.
report_error(
&working_set,
report_parse_error(
&StateWorkingSet::new(engine_state),
&ParseError::FileNotFound(
path_dir.to_string_lossy().into_owned(),
plugin_file.span,
@ -192,7 +192,8 @@ pub fn add_plugin_file(
} else if let Some(mut plugin_path) = nu_path::config_dir() {
// Path to store plugins signatures
plugin_path.push(storage_path);
let mut plugin_path = canonicalize_with(&plugin_path, &cwd).unwrap_or(plugin_path);
let mut plugin_path =
canonicalize_with(&plugin_path, &cwd).unwrap_or(plugin_path.into());
plugin_path.push(PLUGIN_FILE);
let plugin_path = canonicalize_with(&plugin_path, &cwd).unwrap_or(plugin_path);
engine_state.plugin_path = Some(plugin_path);
@ -213,7 +214,8 @@ pub fn eval_config_contents(
let prev_file = engine_state.file.take();
engine_state.file = Some(config_path.clone());
eval_source(
// TODO: ignore this error?
let _ = eval_source(
engine_state,
stack,
&contents,
@ -229,11 +231,11 @@ pub fn eval_config_contents(
match engine_state.cwd(Some(stack)) {
Ok(cwd) => {
if let Err(e) = engine_state.merge_env(stack, cwd) {
report_error_new(engine_state, &e);
report_shell_error(engine_state, &e);
}
}
Err(e) => {
report_error_new(engine_state, &e);
report_shell_error(engine_state, &e);
}
}
}
@ -244,10 +246,10 @@ pub(crate) fn get_history_path(storage_path: &str, mode: HistoryFileFormat) -> O
nu_path::config_dir().map(|mut history_path| {
history_path.push(storage_path);
history_path.push(match mode {
HistoryFileFormat::PlainText => HISTORY_FILE_TXT,
HistoryFileFormat::Plaintext => HISTORY_FILE_TXT,
HistoryFileFormat::Sqlite => HISTORY_FILE_SQLITE,
});
history_path
history_path.into()
})
}
@ -279,7 +281,7 @@ pub fn migrate_old_plugin_file(engine_state: &EngineState, storage_path: &str) -
let old_contents = match std::fs::read(&old_plugin_file_path) {
Ok(old_contents) => old_contents,
Err(err) => {
report_error_new(
report_shell_error(
engine_state,
&ShellError::GenericError {
error: "Can't read old plugin file to migrate".into(),
@ -348,7 +350,7 @@ pub fn migrate_old_plugin_file(engine_state: &EngineState, storage_path: &str) -
.map_err(|e| e.into())
.and_then(|file| contents.write_to(file, None))
{
report_error_new(
report_shell_error(
&engine_state,
&ShellError::GenericError {
error: "Failed to save migrated plugin file".into(),

View File

@ -2,9 +2,10 @@ use log::info;
use nu_engine::{convert_env_values, eval_block};
use nu_parser::parse;
use nu_protocol::{
cli_error::report_compile_error,
debugger::WithoutDebug,
engine::{EngineState, Stack, StateWorkingSet},
report_error, PipelineData, ShellError, Spanned, Value,
report_parse_error, report_parse_warning, PipelineData, ShellError, Spanned, Value,
};
use std::sync::Arc;
@ -53,7 +54,7 @@ pub fn evaluate_commands(
// Parse the source code
let (block, delta) = {
if let Some(ref t_mode) = table_mode {
Arc::make_mut(&mut engine_state.config).table_mode =
Arc::make_mut(&mut engine_state.config).table.mode =
t_mode.coerce_str()?.parse().unwrap_or_default();
}
@ -61,16 +62,16 @@ pub fn evaluate_commands(
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);
report_parse_warning(&working_set, warning);
}
if let Some(err) = working_set.parse_errors.first() {
report_error(&working_set, err);
report_parse_error(&working_set, err);
std::process::exit(1);
}
if let Some(err) = working_set.compile_errors.first() {
report_error(&working_set, err);
report_compile_error(&working_set, err);
// Not a fatal error, for now
}
@ -88,15 +89,11 @@ pub fn evaluate_commands(
}
if let Some(t_mode) = table_mode {
Arc::make_mut(&mut engine_state.config).table_mode =
Arc::make_mut(&mut engine_state.config).table.mode =
t_mode.coerce_str()?.parse().unwrap_or_default();
}
if let Some(status) = pipeline.print(engine_state, stack, no_newline, false)? {
if status.code() != 0 {
std::process::exit(status.code())
}
}
pipeline.print(engine_state, stack, no_newline, false)?;
info!("evaluate {}:{}:{}", file!(), line!(), column!());

View File

@ -4,9 +4,10 @@ use nu_engine::{convert_env_values, eval_block};
use nu_parser::parse;
use nu_path::canonicalize_with;
use nu_protocol::{
cli_error::report_compile_error,
debugger::WithoutDebug,
engine::{EngineState, Stack, StateWorkingSet},
report_error, PipelineData, ShellError, Span, Value,
report_parse_error, report_parse_warning, PipelineData, ShellError, Span, Value,
};
use std::sync::Arc;
@ -77,17 +78,17 @@ pub fn evaluate_file(
let block = parse(&mut working_set, Some(file_path_str), &file, false);
if let Some(warning) = working_set.parse_warnings.first() {
report_error(&working_set, warning);
report_parse_warning(&working_set, warning);
}
// If any parse errors were found, report the first error and exit.
if let Some(err) = working_set.parse_errors.first() {
report_error(&working_set, err);
report_parse_error(&working_set, err);
std::process::exit(1);
}
if let Some(err) = working_set.compile_errors.first() {
report_error(&working_set, err);
report_compile_error(&working_set, err);
// Not a fatal error, for now
}
@ -118,11 +119,7 @@ pub fn evaluate_file(
};
// Print the pipeline output of the last command of the file.
if let Some(status) = pipeline.print(engine_state, stack, true, false)? {
if status.code() != 0 {
std::process::exit(status.code())
}
}
pipeline.print(engine_state, stack, true, false)?;
// Invoke the main command with arguments.
// Arguments with whitespaces are quoted, thus can be safely concatenated by whitespace.
@ -140,7 +137,7 @@ pub fn evaluate_file(
};
if exit_code != 0 {
std::process::exit(exit_code)
std::process::exit(exit_code);
}
info!("evaluate {}:{}:{}", file!(), line!(), column!());

View File

@ -1,4 +1,4 @@
use nu_engine::documentation::get_flags_section;
use nu_engine::documentation::{get_flags_section, HelpStyle};
use nu_protocol::{engine::EngineState, levenshtein_distance, Config};
use nu_utils::IgnoreCaseExt;
use reedline::{Completer, Suggestion};
@ -20,6 +20,9 @@ impl NuHelpCompleter {
fn completion_helper(&self, line: &str, pos: usize) -> Vec<Suggestion> {
let folded_line = line.to_folded_case();
let mut help_style = HelpStyle::default();
help_style.update_from_config(&self.engine_state, &self.config);
let mut commands = self
.engine_state
.get_decls_sorted(false)
@ -27,12 +30,15 @@ impl NuHelpCompleter {
.filter_map(|(_, decl_id)| {
let decl = self.engine_state.get_decl(decl_id);
(decl.name().to_folded_case().contains(&folded_line)
|| decl.usage().to_folded_case().contains(&folded_line)
|| decl.description().to_folded_case().contains(&folded_line)
|| decl
.search_terms()
.into_iter()
.any(|term| term.to_folded_case().contains(&folded_line))
|| decl.extra_usage().to_folded_case().contains(&folded_line))
|| decl
.extra_description()
.to_folded_case()
.contains(&folded_line))
.then_some(decl)
})
.collect::<Vec<_>>();
@ -44,15 +50,15 @@ impl NuHelpCompleter {
.map(|decl| {
let mut long_desc = String::new();
let usage = decl.usage();
if !usage.is_empty() {
long_desc.push_str(usage);
let description = decl.description();
if !description.is_empty() {
long_desc.push_str(description);
long_desc.push_str("\r\n\r\n");
}
let extra_usage = decl.extra_usage();
if !extra_usage.is_empty() {
long_desc.push_str(extra_usage);
let extra_desc = decl.extra_description();
if !extra_desc.is_empty() {
long_desc.push_str(extra_desc);
long_desc.push_str("\r\n\r\n");
}
@ -60,12 +66,9 @@ impl NuHelpCompleter {
let _ = write!(long_desc, "Usage:\r\n > {}\r\n", sig.call_signature());
if !sig.named.is_empty() {
long_desc.push_str(&get_flags_section(
Some(&self.engine_state),
Some(&self.config),
&sig,
|v| v.to_parsable_string(", ", &self.config),
))
long_desc.push_str(&get_flags_section(&sig, &help_style, |v| {
v.to_parsable_string(", ", &self.config)
}))
}
if !sig.required_positional.is_empty()
@ -110,13 +113,12 @@ impl NuHelpCompleter {
Suggestion {
value: decl.name().into(),
description: Some(long_desc),
style: None,
extra: Some(extra),
span: reedline::Span {
start: pos - line.len(),
end: pos,
},
append_whitespace: false,
..Suggestion::default()
}
})
.collect()

View File

@ -142,10 +142,9 @@ fn convert_to_suggestions(
vec![Suggestion {
value: text,
description,
style: None,
extra,
span,
append_whitespace: false,
..Suggestion::default()
}]
}
Value::List { vals, .. } => vals
@ -154,9 +153,6 @@ fn convert_to_suggestions(
.collect(),
_ => vec![Suggestion {
value: format!("Not a record: {value:?}"),
description: None,
style: None,
extra: None,
span: reedline::Span {
start: if only_buffer_difference {
pos - line.len()
@ -169,7 +165,7 @@ fn convert_to_suggestions(
line.len()
},
},
append_whitespace: false,
..Suggestion::default()
}],
}
}

View File

@ -17,7 +17,7 @@ impl Command for NuHighlight {
.input_output_types(vec![(Type::String, Type::String)])
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Syntax highlight the input string."
}

View File

@ -22,14 +22,19 @@ impl Command for Print {
Some('n'),
)
.switch("stderr", "print to stderr instead of stdout", Some('e'))
.switch(
"raw",
"print without formatting (including binary data)",
Some('r'),
)
.category(Category::Strings)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Print the given values to stdout."
}
fn extra_usage(&self) -> &str {
fn extra_description(&self) -> &str {
r#"Unlike `echo`, this command does not return any value (`print | describe` will return "nothing").
Since this command has no output, there is no point in piping it with other commands.
@ -50,16 +55,26 @@ Since this command has no output, there is no point in piping it with other comm
let args: Vec<Value> = call.rest(engine_state, stack, 0)?;
let no_newline = call.has_flag(engine_state, stack, "no-newline")?;
let to_stderr = call.has_flag(engine_state, stack, "stderr")?;
let raw = call.has_flag(engine_state, stack, "raw")?;
// This will allow for easy printing of pipelines as well
if !args.is_empty() {
for arg in args {
if raw {
arg.into_pipeline_data()
.print_raw(engine_state, no_newline, to_stderr)?;
} else {
arg.into_pipeline_data()
.print(engine_state, stack, no_newline, to_stderr)?;
}
}
} else if !input.is_nothing() {
if raw {
input.print_raw(engine_state, no_newline, to_stderr)?;
} else {
input.print(engine_state, stack, no_newline, to_stderr)?;
}
}
Ok(PipelineData::empty())
}
@ -76,6 +91,11 @@ Since this command has no output, there is no point in piping it with other comm
example: r#"print (2 + 3)"#,
result: None,
},
Example {
description: "Print 'ABC' from binary data",
example: r#"0x[41 42 43] | print --raw"#,
result: None,
},
]
}
}

View File

@ -3,7 +3,7 @@ use log::trace;
use nu_engine::ClosureEvalOnce;
use nu_protocol::{
engine::{EngineState, Stack},
report_error_new, Config, PipelineData, Value,
report_shell_error, Config, PipelineData, Value,
};
use reedline::Prompt;
@ -46,7 +46,10 @@ pub(crate) const VSCODE_POST_EXECUTION_MARKER_PREFIX: &str = "\x1b]633;D;";
#[allow(dead_code)]
pub(crate) const VSCODE_POST_EXECUTION_MARKER_SUFFIX: &str = "\x1b\\";
#[allow(dead_code)]
pub(crate) const VSCODE_COMMANDLINE_MARKER: &str = "\x1b]633;E\x1b\\";
//"\x1b]633;E;{}\x1b\\"
pub(crate) const VSCODE_COMMANDLINE_MARKER_PREFIX: &str = "\x1b]633;E;";
#[allow(dead_code)]
pub(crate) const VSCODE_COMMANDLINE_MARKER_SUFFIX: &str = "\x1b\\";
#[allow(dead_code)]
// "\x1b]633;P;Cwd={}\x1b\\"
pub(crate) const VSCODE_CWD_PROPERTY_MARKER_PREFIX: &str = "\x1b]633;P;Cwd=";
@ -77,7 +80,7 @@ fn get_prompt_string(
result
.map_err(|err| {
report_error_new(engine_state, &err);
report_shell_error(engine_state, &err);
})
.ok()
}
@ -115,13 +118,13 @@ pub(crate) fn update_prompt(
// Now that we have the prompt string lets ansify it.
// <133 A><prompt><133 B><command><133 C><command output>
let left_prompt_string = if config.shell_integration_osc633 {
let left_prompt_string = if config.shell_integration.osc633 {
if stack.get_env_var(engine_state, "TERM_PROGRAM") == Some(Value::test_string("vscode")) {
// We're in vscode and we have osc633 enabled
Some(format!(
"{VSCODE_PRE_PROMPT_MARKER}{configured_left_prompt_string}{VSCODE_POST_PROMPT_MARKER}"
))
} else if config.shell_integration_osc133 {
} else if config.shell_integration.osc133 {
// If we're in VSCode but we don't find the env var, but we have osc133 set, then use it
Some(format!(
"{PRE_PROMPT_MARKER}{configured_left_prompt_string}{POST_PROMPT_MARKER}"
@ -129,7 +132,7 @@ pub(crate) fn update_prompt(
} else {
configured_left_prompt_string.into()
}
} else if config.shell_integration_osc133 {
} else if config.shell_integration.osc133 {
Some(format!(
"{PRE_PROMPT_MARKER}{configured_left_prompt_string}{POST_PROMPT_MARKER}"
))

View File

@ -159,8 +159,8 @@ fn add_menu(
stack: &Stack,
config: Arc<Config>,
) -> Result<Reedline, ShellError> {
let span = menu.menu_type.span();
if let Value::Record { val, .. } = &menu.menu_type {
let span = menu.r#type.span();
if let Value::Record { val, .. } = &menu.r#type {
let layout = extract_value("layout", val, span)?.to_expanded_string("", &config);
match layout.as_str() {
@ -170,15 +170,15 @@ fn add_menu(
"description" => add_description_menu(line_editor, menu, engine_state, stack, config),
_ => Err(ShellError::UnsupportedConfigValue {
expected: "columnar, list, ide or description".to_string(),
value: menu.menu_type.to_abbreviated_string(&config),
span: menu.menu_type.span(),
value: menu.r#type.to_abbreviated_string(&config),
span: menu.r#type.span(),
}),
}
} else {
Err(ShellError::UnsupportedConfigValue {
expected: "only record type".to_string(),
value: menu.menu_type.to_abbreviated_string(&config),
span: menu.menu_type.span(),
value: menu.r#type.to_abbreviated_string(&config),
span: menu.r#type.span(),
})
}
}
@ -193,6 +193,29 @@ fn get_style(record: &Record, name: &str, span: Span) -> Option<Style> {
})
}
fn set_menu_style<M: MenuBuilder>(mut menu: M, style: &Value) -> M {
let span = style.span();
let Value::Record { val, .. } = &style else {
return menu;
};
if let Some(style) = get_style(val, "text", span) {
menu = menu.with_text_style(style);
}
if let Some(style) = get_style(val, "selected_text", span) {
menu = menu.with_selected_text_style(style);
}
if let Some(style) = get_style(val, "description_text", span) {
menu = menu.with_description_text_style(style);
}
if let Some(style) = get_style(val, "match_text", span) {
menu = menu.with_match_text_style(style);
}
if let Some(style) = get_style(val, "selected_match_text", span) {
menu = menu.with_selected_match_text_style(style);
}
menu
}
// Adds a columnar menu to the editor engine
pub(crate) fn add_columnar_menu(
line_editor: Reedline,
@ -201,11 +224,11 @@ pub(crate) fn add_columnar_menu(
stack: &Stack,
config: &Config,
) -> Result<Reedline, ShellError> {
let span = menu.menu_type.span();
let span = menu.r#type.span();
let name = menu.name.to_expanded_string("", config);
let mut columnar_menu = ColumnarMenu::default().with_name(&name);
if let Value::Record { val, .. } = &menu.menu_type {
if let Value::Record { val, .. } = &menu.r#type {
columnar_menu = match extract_value("columns", val, span) {
Ok(columns) => {
let columns = columns.as_int()?;
@ -231,24 +254,7 @@ pub(crate) fn add_columnar_menu(
};
}
let span = menu.style.span();
if let Value::Record { val, .. } = &menu.style {
if let Some(style) = get_style(val, "text", span) {
columnar_menu = columnar_menu.with_text_style(style);
}
if let Some(style) = get_style(val, "selected_text", span) {
columnar_menu = columnar_menu.with_selected_text_style(style);
}
if let Some(style) = get_style(val, "description_text", span) {
columnar_menu = columnar_menu.with_description_text_style(style);
}
if let Some(style) = get_style(val, "match_text", span) {
columnar_menu = columnar_menu.with_match_text_style(style);
}
if let Some(style) = get_style(val, "selected_match_text", span) {
columnar_menu = columnar_menu.with_selected_match_text_style(style);
}
}
columnar_menu = set_menu_style(columnar_menu, &menu.style);
let marker = menu.marker.to_expanded_string("", config);
columnar_menu = columnar_menu.with_marker(&marker);
@ -293,8 +299,8 @@ pub(crate) fn add_list_menu(
let name = menu.name.to_expanded_string("", &config);
let mut list_menu = ListMenu::default().with_name(&name);
let span = menu.menu_type.span();
if let Value::Record { val, .. } = &menu.menu_type {
let span = menu.r#type.span();
if let Value::Record { val, .. } = &menu.r#type {
list_menu = match extract_value("page_size", val, span) {
Ok(page_size) => {
let page_size = page_size.as_int()?;
@ -304,18 +310,7 @@ pub(crate) fn add_list_menu(
};
}
let span = menu.style.span();
if let Value::Record { val, .. } = &menu.style {
if let Some(style) = get_style(val, "text", span) {
list_menu = list_menu.with_text_style(style);
}
if let Some(style) = get_style(val, "selected_text", span) {
list_menu = list_menu.with_selected_text_style(style);
}
if let Some(style) = get_style(val, "description_text", span) {
list_menu = list_menu.with_description_text_style(style);
}
}
list_menu = set_menu_style(list_menu, &menu.style);
let marker = menu.marker.to_expanded_string("", &config);
list_menu = list_menu.with_marker(&marker);
@ -357,11 +352,11 @@ pub(crate) fn add_ide_menu(
stack: &Stack,
config: Arc<Config>,
) -> Result<Reedline, ShellError> {
let span = menu.menu_type.span();
let span = menu.r#type.span();
let name = menu.name.to_expanded_string("", &config);
let mut ide_menu = IdeMenu::default().with_name(&name);
if let Value::Record { val, .. } = &menu.menu_type {
if let Value::Record { val, .. } = &menu.r#type {
ide_menu = match extract_value("min_completion_width", val, span) {
Ok(min_completion_width) => {
let min_completion_width = min_completion_width.as_int()?;
@ -496,24 +491,7 @@ pub(crate) fn add_ide_menu(
};
}
let span = menu.style.span();
if let Value::Record { val, .. } = &menu.style {
if let Some(style) = get_style(val, "text", span) {
ide_menu = ide_menu.with_text_style(style);
}
if let Some(style) = get_style(val, "selected_text", span) {
ide_menu = ide_menu.with_selected_text_style(style);
}
if let Some(style) = get_style(val, "description_text", span) {
ide_menu = ide_menu.with_description_text_style(style);
}
if let Some(style) = get_style(val, "match_text", span) {
ide_menu = ide_menu.with_match_text_style(style);
}
if let Some(style) = get_style(val, "selected_match_text", span) {
ide_menu = ide_menu.with_selected_match_text_style(style);
}
}
ide_menu = set_menu_style(ide_menu, &menu.style);
let marker = menu.marker.to_expanded_string("", &config);
ide_menu = ide_menu.with_marker(&marker);
@ -558,8 +536,8 @@ pub(crate) fn add_description_menu(
let name = menu.name.to_expanded_string("", &config);
let mut description_menu = DescriptionMenu::default().with_name(&name);
let span = menu.menu_type.span();
if let Value::Record { val, .. } = &menu.menu_type {
let span = menu.r#type.span();
if let Value::Record { val, .. } = &menu.r#type {
description_menu = match extract_value("columns", val, span) {
Ok(columns) => {
let columns = columns.as_int()?;
@ -601,18 +579,7 @@ pub(crate) fn add_description_menu(
};
}
let span = menu.style.span();
if let Value::Record { val, .. } = &menu.style {
if let Some(style) = get_style(val, "text", span) {
description_menu = description_menu.with_text_style(style);
}
if let Some(style) = get_style(val, "selected_text", span) {
description_menu = description_menu.with_selected_text_style(style);
}
if let Some(style) = get_style(val, "description_text", span) {
description_menu = description_menu.with_description_text_style(style);
}
}
description_menu = set_menu_style(description_menu, &menu.style);
let marker = menu.marker.to_expanded_string("", &config);
description_menu = description_menu.with_marker(&marker);

View File

@ -1,6 +1,7 @@
use crate::prompt_update::{
POST_EXECUTION_MARKER_PREFIX, POST_EXECUTION_MARKER_SUFFIX, PRE_EXECUTION_MARKER,
RESET_APPLICATION_MODE, VSCODE_CWD_PROPERTY_MARKER_PREFIX, VSCODE_CWD_PROPERTY_MARKER_SUFFIX,
RESET_APPLICATION_MODE, VSCODE_COMMANDLINE_MARKER_PREFIX, VSCODE_COMMANDLINE_MARKER_SUFFIX,
VSCODE_CWD_PROPERTY_MARKER_PREFIX, VSCODE_CWD_PROPERTY_MARKER_SUFFIX,
VSCODE_POST_EXECUTION_MARKER_PREFIX, VSCODE_POST_EXECUTION_MARKER_SUFFIX,
VSCODE_PRE_EXECUTION_MARKER,
};
@ -26,7 +27,7 @@ use nu_parser::{lex, parse, trim_quotes_str};
use nu_protocol::{
config::NuCursorShape,
engine::{EngineState, Stack, StateWorkingSet},
report_error_new, HistoryConfig, HistoryFileFormat, PipelineData, ShellError, Span, Spanned,
report_shell_error, HistoryConfig, HistoryFileFormat, PipelineData, ShellError, Span, Spanned,
Value,
};
use nu_utils::{
@ -71,11 +72,11 @@ pub fn evaluate_repl(
let mut entry_num = 0;
// Let's grab the shell_integration configs
let shell_integration_osc2 = config.shell_integration_osc2;
let shell_integration_osc7 = config.shell_integration_osc7;
let shell_integration_osc9_9 = config.shell_integration_osc9_9;
let shell_integration_osc133 = config.shell_integration_osc133;
let shell_integration_osc633 = config.shell_integration_osc633;
let shell_integration_osc2 = config.shell_integration.osc2;
let shell_integration_osc7 = config.shell_integration.osc7;
let shell_integration_osc9_9 = config.shell_integration.osc9_9;
let shell_integration_osc133 = config.shell_integration.osc133;
let shell_integration_osc633 = config.shell_integration.osc633;
let nu_prompt = NushellPrompt::new(
shell_integration_osc133,
@ -87,7 +88,7 @@ pub fn evaluate_repl(
let start_time = std::time::Instant::now();
// Translate environment variables from Strings to Values
if let Err(e) = convert_env_values(engine_state, &unique_stack) {
report_error_new(engine_state, &e);
report_shell_error(engine_state, &e);
}
perf!("translate env vars", start_time, use_color);
@ -97,7 +98,7 @@ pub fn evaluate_repl(
Value::string("0823", Span::unknown()),
);
unique_stack.add_env_var("LAST_EXIT_CODE".into(), Value::int(0, Span::unknown()));
unique_stack.set_last_exit_code(0, Span::unknown());
let mut line_editor = get_line_editor(engine_state, nushell_path, use_color)?;
let temp_file = temp_dir().join(format!("{}.nu", uuid::Uuid::new_v4()));
@ -131,7 +132,26 @@ pub fn evaluate_repl(
run_shell_integration_osc9_9(engine_state, &mut unique_stack, use_color);
}
if shell_integration_osc633 {
run_shell_integration_osc633(engine_state, &mut unique_stack, use_color);
// escape a few things because this says so
// https://code.visualstudio.com/docs/terminal/shell-integration#_vs-code-custom-sequences-osc-633-st
let cmd_text = line_editor.current_buffer_contents().to_string();
let replaced_cmd_text = cmd_text
.chars()
.map(|c| match c {
'\n' => '\x0a',
'\r' => '\x0d',
'\x1b' => '\x1b',
_ => c,
})
.collect();
run_shell_integration_osc633(
engine_state,
&mut unique_stack,
use_color,
replaced_cmd_text,
);
}
engine_state.set_startup_time(entire_start_time.elapsed().as_nanos() as i64);
@ -266,11 +286,11 @@ fn loop_iteration(ctx: LoopContext) -> (bool, Stack, Reedline) {
// Before doing anything, merge the environment from the previous REPL iteration into the
// permanent state.
if let Err(err) = engine_state.merge_env(&mut stack, cwd) {
report_error_new(engine_state, &err);
report_shell_error(engine_state, &err);
}
// Check whether $env.NU_USE_IR is set, so that the user can change it in the REPL
// Check whether $env.NU_DISABLE_IR is set, so that the user can change it in the REPL
// Temporary while IR eval is optional
stack.use_ir = stack.has_env_var(engine_state, "NU_USE_IR");
stack.use_ir = !stack.has_env_var(engine_state, "NU_DISABLE_IR");
perf!("merge env", start_time, use_color);
start_time = std::time::Instant::now();
@ -282,7 +302,7 @@ fn loop_iteration(ctx: LoopContext) -> (bool, Stack, Reedline) {
// fire the "pre_prompt" hook
if let Some(hook) = engine_state.get_config().hooks.pre_prompt.clone() {
if let Err(err) = eval_hook(engine_state, &mut stack, None, vec![], &hook, "pre_prompt") {
report_error_new(engine_state, &err);
report_shell_error(engine_state, &err);
}
}
perf!("pre-prompt hook", start_time, use_color);
@ -292,7 +312,7 @@ fn loop_iteration(ctx: LoopContext) -> (bool, Stack, Reedline) {
// fire the "env_change" hook
let env_change = engine_state.get_config().hooks.env_change.clone();
if let Err(error) = hook::eval_env_change_hook(env_change, engine_state, &mut stack) {
report_error_new(engine_state, &error)
report_shell_error(engine_state, &error)
}
perf!("env-change hook", start_time, use_color);
@ -302,9 +322,9 @@ fn loop_iteration(ctx: LoopContext) -> (bool, Stack, Reedline) {
start_time = std::time::Instant::now();
// Find the configured cursor shapes for each mode
let cursor_config = CursorConfig {
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),
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", start_time, use_color);
@ -332,8 +352,8 @@ fn loop_iteration(ctx: LoopContext) -> (bool, Stack, Reedline) {
// STACK-REFERENCE 2
stack_arc.clone(),
)))
.with_quick_completions(config.quick_completions)
.with_partial_completions(config.partial_completions)
.with_quick_completions(config.completions.quick)
.with_partial_completions(config.completions.partial)
.with_ansi_colors(config.use_ansi_coloring)
.with_cwd(Some(
engine_state
@ -366,7 +386,7 @@ fn loop_iteration(ctx: LoopContext) -> (bool, Stack, Reedline) {
trace!("adding menus");
line_editor =
add_menus(line_editor, engine_reference, &stack_arc, config).unwrap_or_else(|e| {
report_error_new(engine_state, &e);
report_shell_error(engine_state, &e);
Reedline::create()
});
@ -437,12 +457,12 @@ fn loop_iteration(ctx: LoopContext) -> (bool, Stack, Reedline) {
.with_completer(Box::<DefaultCompleter>::default());
// Let's grab the shell_integration configs
let shell_integration_osc2 = config.shell_integration_osc2;
let shell_integration_osc7 = config.shell_integration_osc7;
let shell_integration_osc9_9 = config.shell_integration_osc9_9;
let shell_integration_osc133 = config.shell_integration_osc133;
let shell_integration_osc633 = config.shell_integration_osc633;
let shell_integration_reset_application_mode = config.shell_integration_reset_application_mode;
let shell_integration_osc2 = config.shell_integration.osc2;
let shell_integration_osc7 = config.shell_integration.osc7;
let shell_integration_osc9_9 = config.shell_integration.osc9_9;
let shell_integration_osc133 = config.shell_integration.osc133;
let shell_integration_osc633 = config.shell_integration.osc633;
let shell_integration_reset_application_mode = config.shell_integration.reset_application_mode;
// TODO: we may clone the stack, this can lead to major performance issues
// so we should avoid it or making stack cheaper to clone.
@ -452,14 +472,19 @@ fn loop_iteration(ctx: LoopContext) -> (bool, Stack, Reedline) {
let line_editor_input_time = std::time::Instant::now();
match input {
Ok(Signal::Success(s)) => {
Ok(Signal::Success(repl_cmd_line_text)) => {
let history_supports_meta = matches!(
engine_state.history_config().map(|h| h.file_format),
Some(HistoryFileFormat::Sqlite)
);
if history_supports_meta {
prepare_history_metadata(&s, hostname, engine_state, &mut line_editor);
prepare_history_metadata(
&repl_cmd_line_text,
hostname,
engine_state,
&mut line_editor,
);
}
// For pre_exec_hook
@ -470,7 +495,7 @@ fn loop_iteration(ctx: LoopContext) -> (bool, Stack, Reedline) {
if let Some(hook) = config.hooks.pre_execution.clone() {
// Set the REPL buffer to the current command for the "pre_execution" hook
let mut repl = engine_state.repl_state.lock().expect("repl state mutex");
repl.buffer = s.to_string();
repl.buffer = repl_cmd_line_text.to_string();
drop(repl);
if let Err(err) = eval_hook(
@ -481,7 +506,7 @@ fn loop_iteration(ctx: LoopContext) -> (bool, Stack, Reedline) {
&hook,
"pre_execution",
) {
report_error_new(engine_state, &err);
report_shell_error(engine_state, &err);
}
}
@ -531,7 +556,7 @@ fn loop_iteration(ctx: LoopContext) -> (bool, Stack, Reedline) {
// Actual command execution logic starts from here
let cmd_execution_start_time = Instant::now();
match parse_operation(s.clone(), engine_state, &stack) {
match parse_operation(repl_cmd_line_text.clone(), engine_state, &stack) {
Ok(operation) => match operation {
ReplOperation::AutoCd { cwd, target, span } => {
do_auto_cd(target, cwd, &mut stack, engine_state, span);
@ -577,7 +602,7 @@ fn loop_iteration(ctx: LoopContext) -> (bool, Stack, Reedline) {
if history_supports_meta {
if let Err(e) = fill_in_result_related_history_metadata(
&s,
&repl_cmd_line_text,
engine_state,
cmd_duration,
&mut stack,
@ -597,7 +622,12 @@ fn loop_iteration(ctx: LoopContext) -> (bool, Stack, Reedline) {
run_shell_integration_osc9_9(engine_state, &mut stack, use_color);
}
if shell_integration_osc633 {
run_shell_integration_osc633(engine_state, &mut stack, use_color);
run_shell_integration_osc633(
engine_state,
&mut stack,
use_color,
repl_cmd_line_text,
);
}
if shell_integration_reset_application_mode {
run_shell_integration_reset_application_mode();
@ -778,7 +808,7 @@ fn do_auto_cd(
) {
let path = {
if !path.exists() {
report_error_new(
report_shell_error(
engine_state,
&ShellError::DirectoryNotFound {
dir: path.to_string_lossy().to_string(),
@ -790,7 +820,7 @@ fn do_auto_cd(
};
if let PermissionResult::PermissionDenied(reason) = have_permission(path.clone()) {
report_error_new(
report_shell_error(
engine_state,
&ShellError::IOError {
msg: format!("Cannot change directory to {path}: {reason}"),
@ -804,7 +834,7 @@ fn do_auto_cd(
//FIXME: this only changes the current scope, but instead this environment variable
//should probably be a block that loads the information from the state in the overlay
if let Err(err) = stack.set_cwd(&path) {
report_error_new(engine_state, &err);
report_shell_error(engine_state, &err);
return;
};
let cwd = Value::string(cwd, span);
@ -837,7 +867,7 @@ fn do_auto_cd(
"NUSHELL_LAST_SHELL".into(),
Value::int(last_shell as i64, span),
);
stack.add_env_var("LAST_EXIT_CODE".into(), Value::int(0, Span::unknown()));
stack.set_last_exit_code(0, Span::unknown());
}
///
@ -911,7 +941,12 @@ fn run_shell_integration_osc2(
// Try to abbreviate string for windows title
let maybe_abbrev_path = if let Some(p) = nu_path::home_dir() {
path.replace(&p.as_path().display().to_string(), "~")
let home_dir_str = p.as_path().display().to_string();
if path.starts_with(&home_dir_str) {
path.replacen(&home_dir_str, "~", 1)
} else {
path
}
} else {
path
};
@ -988,7 +1023,12 @@ fn run_shell_integration_osc9_9(engine_state: &EngineState, stack: &mut Stack, u
}
}
fn run_shell_integration_osc633(engine_state: &EngineState, stack: &mut Stack, use_color: bool) {
fn run_shell_integration_osc633(
engine_state: &EngineState,
stack: &mut Stack,
use_color: bool,
repl_cmd_line_text: String,
) {
#[allow(deprecated)]
if let Ok(path) = current_dir_str(engine_state, stack) {
// Supported escape sequences of Microsoft's Visual Studio Code (vscode)
@ -1008,6 +1048,27 @@ fn run_shell_integration_osc633(engine_state: &EngineState, stack: &mut Stack, u
start_time,
use_color
);
// escape a few things because this says so
// https://code.visualstudio.com/docs/terminal/shell-integration#_vs-code-custom-sequences-osc-633-st
let replaced_cmd_text: String = repl_cmd_line_text
.chars()
.map(|c| match c {
'\n' => '\x0a',
'\r' => '\x0d',
'\x1b' => '\x1b',
_ => c,
})
.collect();
//OSC 633 ; E ; <commandline> [; <nonce] ST - Explicitly set the command line with an optional nonce.
run_ansi_sequence(&format!(
"{}{}{}",
VSCODE_COMMANDLINE_MARKER_PREFIX,
replaced_cmd_text,
VSCODE_COMMANDLINE_MARKER_SUFFIX
));
}
}
}
@ -1080,7 +1141,7 @@ fn setup_keybindings(engine_state: &EngineState, line_editor: Reedline) -> Reedl
}
},
Err(e) => {
report_error_new(engine_state, &e);
report_shell_error(engine_state, &e);
line_editor
}
};
@ -1112,7 +1173,7 @@ fn update_line_editor_history(
history_session_id: Option<HistorySessionId>,
) -> Result<Reedline, ErrReport> {
let history: Box<dyn reedline::History> = match history.file_format {
HistoryFileFormat::PlainText => Box::new(
HistoryFileFormat::Plaintext => Box::new(
FileBackedHistory::with_file(history.max_size as usize, history_path)
.into_diagnostic()?,
),
@ -1150,10 +1211,10 @@ fn confirm_stdin_is_terminal() -> Result<()> {
fn map_nucursorshape_to_cursorshape(shape: NuCursorShape) -> Option<SetCursorStyle> {
match shape {
NuCursorShape::Block => Some(SetCursorStyle::SteadyBlock),
NuCursorShape::UnderScore => Some(SetCursorStyle::SteadyUnderScore),
NuCursorShape::Underscore => Some(SetCursorStyle::SteadyUnderScore),
NuCursorShape::Line => Some(SetCursorStyle::SteadyBar),
NuCursorShape::BlinkBlock => Some(SetCursorStyle::BlinkingBlock),
NuCursorShape::BlinkUnderScore => Some(SetCursorStyle::BlinkingUnderScore),
NuCursorShape::BlinkUnderscore => Some(SetCursorStyle::BlinkingUnderScore),
NuCursorShape::BlinkLine => Some(SetCursorStyle::BlinkingBar),
NuCursorShape::Inherit => None,
}
@ -1337,20 +1398,26 @@ fn are_session_ids_in_sync() {
#[cfg(test)]
mod test_auto_cd {
use super::{do_auto_cd, parse_operation, ReplOperation};
use nu_path::AbsolutePath;
use nu_protocol::engine::{EngineState, Stack};
use std::path::Path;
use tempfile::tempdir;
/// Create a symlink. Works on both Unix and Windows.
#[cfg(any(unix, windows))]
fn symlink(original: impl AsRef<Path>, link: impl AsRef<Path>) -> std::io::Result<()> {
fn symlink(
original: impl AsRef<AbsolutePath>,
link: impl AsRef<AbsolutePath>,
) -> std::io::Result<()> {
let original = original.as_ref();
let link = link.as_ref();
#[cfg(unix)]
{
std::os::unix::fs::symlink(original, link)
}
#[cfg(windows)]
{
if original.as_ref().is_dir() {
if original.is_dir() {
std::os::windows::fs::symlink_dir(original, link)
} else {
std::os::windows::fs::symlink_file(original, link)
@ -1362,11 +1429,11 @@ mod test_auto_cd {
/// `before`, and after `input` is parsed and evaluated, PWD should be
/// changed to `after`.
#[track_caller]
fn check(before: impl AsRef<Path>, input: &str, after: impl AsRef<Path>) {
fn check(before: impl AsRef<AbsolutePath>, input: &str, after: impl AsRef<AbsolutePath>) {
// Setup EngineState and Stack.
let mut engine_state = EngineState::new();
let mut stack = Stack::new();
stack.set_cwd(before).unwrap();
stack.set_cwd(before.as_ref()).unwrap();
// Parse the input. It must be an auto-cd operation.
let op = parse_operation(input.to_string(), &engine_state, &stack).unwrap();
@ -1382,54 +1449,66 @@ mod test_auto_cd {
// don't have to be byte-wise equal (on Windows, the 8.3 filename
// conversion messes things up),
let updated_cwd = std::fs::canonicalize(updated_cwd).unwrap();
let after = std::fs::canonicalize(after).unwrap();
let after = std::fs::canonicalize(after.as_ref()).unwrap();
assert_eq!(updated_cwd, after);
}
#[test]
fn auto_cd_root() {
let tempdir = tempdir().unwrap();
let root = if cfg!(windows) { r"C:\" } else { "/" };
check(&tempdir, root, root);
let tempdir = AbsolutePath::try_new(tempdir.path()).unwrap();
let input = if cfg!(windows) { r"C:\" } else { "/" };
let root = AbsolutePath::try_new(input).unwrap();
check(tempdir, input, root);
}
#[test]
fn auto_cd_tilde() {
let tempdir = tempdir().unwrap();
let tempdir = AbsolutePath::try_new(tempdir.path()).unwrap();
let home = nu_path::home_dir().unwrap();
check(&tempdir, "~", home);
check(tempdir, "~", home);
}
#[test]
fn auto_cd_dot() {
let tempdir = tempdir().unwrap();
check(&tempdir, ".", &tempdir);
let tempdir = AbsolutePath::try_new(tempdir.path()).unwrap();
check(tempdir, ".", tempdir);
}
#[test]
fn auto_cd_double_dot() {
let tempdir = tempdir().unwrap();
let dir = tempdir.path().join("foo");
let tempdir = AbsolutePath::try_new(tempdir.path()).unwrap();
let dir = tempdir.join("foo");
std::fs::create_dir_all(&dir).unwrap();
check(dir, "..", &tempdir);
check(dir, "..", tempdir);
}
#[test]
fn auto_cd_triple_dot() {
let tempdir = tempdir().unwrap();
let dir = tempdir.path().join("foo").join("bar");
let tempdir = AbsolutePath::try_new(tempdir.path()).unwrap();
let dir = tempdir.join("foo").join("bar");
std::fs::create_dir_all(&dir).unwrap();
check(dir, "...", &tempdir);
check(dir, "...", tempdir);
}
#[test]
fn auto_cd_relative() {
let tempdir = tempdir().unwrap();
let foo = tempdir.path().join("foo");
let bar = tempdir.path().join("bar");
let tempdir = AbsolutePath::try_new(tempdir.path()).unwrap();
let foo = tempdir.join("foo");
let bar = tempdir.join("bar");
std::fs::create_dir_all(&foo).unwrap();
std::fs::create_dir_all(&bar).unwrap();
let input = if cfg!(windows) { r"..\bar" } else { "../bar" };
check(foo, input, bar);
}
@ -1437,32 +1516,35 @@ mod test_auto_cd {
#[test]
fn auto_cd_trailing_slash() {
let tempdir = tempdir().unwrap();
let dir = tempdir.path().join("foo");
std::fs::create_dir_all(&dir).unwrap();
let tempdir = AbsolutePath::try_new(tempdir.path()).unwrap();
let dir = tempdir.join("foo");
std::fs::create_dir_all(&dir).unwrap();
let input = if cfg!(windows) { r"foo\" } else { "foo/" };
check(&tempdir, input, dir);
check(tempdir, input, dir);
}
#[test]
fn auto_cd_symlink() {
let tempdir = tempdir().unwrap();
let dir = tempdir.path().join("foo");
std::fs::create_dir_all(&dir).unwrap();
let link = tempdir.path().join("link");
symlink(&dir, &link).unwrap();
let tempdir = AbsolutePath::try_new(tempdir.path()).unwrap();
let dir = tempdir.join("foo");
std::fs::create_dir_all(&dir).unwrap();
let link = tempdir.join("link");
symlink(&dir, &link).unwrap();
let input = if cfg!(windows) { r".\link" } else { "./link" };
check(&tempdir, input, link);
check(tempdir, input, link);
}
#[test]
#[should_panic(expected = "was not parsed into an auto-cd operation")]
fn auto_cd_nonexistent_directory() {
let tempdir = tempdir().unwrap();
let dir = tempdir.path().join("foo");
let tempdir = AbsolutePath::try_new(tempdir.path()).unwrap();
let dir = tempdir.join("foo");
let input = if cfg!(windows) { r"foo\" } else { "foo/" };
check(&tempdir, input, dir);
check(tempdir, input, dir);
}
}

View File

@ -2,9 +2,11 @@ use nu_cmd_base::hook::eval_hook;
use nu_engine::{eval_block, eval_block_with_early_return};
use nu_parser::{escape_quote_string, lex, parse, unescape_unquote_string, Token, TokenContents};
use nu_protocol::{
cli_error::report_compile_error,
debugger::WithoutDebug,
engine::{EngineState, Stack, StateWorkingSet},
report_error, report_error_new, PipelineData, ShellError, Span, Value,
report_parse_error, report_parse_warning, report_shell_error, PipelineData, ShellError, Span,
Value,
};
#[cfg(windows)]
use nu_utils::enable_vt_processing;
@ -39,7 +41,7 @@ fn gather_env_vars(
init_cwd: &Path,
) {
fn report_capture_error(engine_state: &EngineState, env_str: &str, msg: &str) {
report_error_new(
report_shell_error(
engine_state,
&ShellError::GenericError {
error: format!("Environment variable was not captured: {env_str}"),
@ -70,7 +72,7 @@ fn gather_env_vars(
}
None => {
// Could not capture current working directory
report_error_new(
report_shell_error(
engine_state,
&ShellError::GenericError {
error: "Current directory is not a valid utf-8 path".into(),
@ -210,18 +212,19 @@ pub fn eval_source(
let start_time = std::time::Instant::now();
let exit_code = match evaluate_source(engine_state, stack, source, fname, input, allow_return) {
Ok(code) => code.unwrap_or(0),
Ok(failed) => {
let code = failed.into();
stack.set_last_exit_code(code, Span::unknown());
code
}
Err(err) => {
report_error_new(engine_state, &err);
1
report_shell_error(engine_state, &err);
let code = err.exit_code();
stack.set_last_error(&err);
code
}
};
stack.add_env_var(
"LAST_EXIT_CODE".to_string(),
Value::int(exit_code.into(), Span::unknown()),
);
// reset vt processing, aka ansi because illbehaved externals can break it
#[cfg(windows)]
{
@ -244,7 +247,7 @@ fn evaluate_source(
fname: &str,
input: PipelineData,
allow_return: bool,
) -> Result<Option<i32>, ShellError> {
) -> Result<bool, ShellError> {
let (block, delta) = {
let mut working_set = StateWorkingSet::new(engine_state);
let output = parse(
@ -254,16 +257,16 @@ fn evaluate_source(
false,
);
if let Some(warning) = working_set.parse_warnings.first() {
report_error(&working_set, warning);
report_parse_warning(&working_set, warning);
}
if let Some(err) = working_set.parse_errors.first() {
report_error(&working_set, err);
return Ok(Some(1));
report_parse_error(&working_set, err);
return Ok(true);
}
if let Some(err) = working_set.compile_errors.first() {
report_error(&working_set, err);
report_compile_error(&working_set, err);
// Not a fatal error, for now
}
@ -278,10 +281,9 @@ fn evaluate_source(
eval_block::<WithoutDebug>(engine_state, stack, &block, input)
}?;
let status = if let PipelineData::ByteStream(..) = pipeline {
pipeline.print(engine_state, stack, false, false)?
} else {
if let Some(hook) = engine_state.get_config().hooks.display_output.clone() {
if let PipelineData::ByteStream(..) = pipeline {
pipeline.print(engine_state, stack, false, false)
} else if let Some(hook) = engine_state.get_config().hooks.display_output.clone() {
let pipeline = eval_hook(
engine_state,
stack,
@ -293,10 +295,9 @@ fn evaluate_source(
pipeline.print(engine_state, stack, false, false)
} else {
pipeline.print(engine_state, stack, true, false)
}?
};
}?;
Ok(status.map(|status| status.code()))
Ok(false)
}
#[cfg(test)]
@ -321,16 +322,10 @@ mod test {
let env = engine_state.render_env_vars();
assert!(
matches!(env.get(&"FOO".to_string()), Some(&Value::String { val, .. }) if val == "foo")
);
assert!(
matches!(env.get(&"SYMBOLS".to_string()), Some(&Value::String { val, .. }) if val == symbols)
);
assert!(
matches!(env.get(&symbols.to_string()), Some(&Value::String { val, .. }) if val == "symbols")
);
assert!(env.get(&"PWD".to_string()).is_some());
assert!(matches!(env.get("FOO"), Some(&Value::String { val, .. }) if val == "foo"));
assert!(matches!(env.get("SYMBOLS"), Some(&Value::String { val, .. }) if val == symbols));
assert!(matches!(env.get(symbols), Some(&Value::String { val, .. }) if val == "symbols"));
assert!(env.contains_key("PWD"));
assert_eq!(env.len(), 4);
}
}

View File

@ -32,7 +32,6 @@ fn completer() -> NuCompleter {
fn completer_strings() -> NuCompleter {
// Create a new engine
let (dir, _, mut engine, mut stack) = new_engine();
// Add record value as example
let record = r#"def animals [] { ["cat", "dog", "eel" ] }
def my-command [animal: string@animals] { print $animal }"#;
@ -62,6 +61,32 @@ fn extern_completer() -> NuCompleter {
NuCompleter::new(Arc::new(engine), Arc::new(stack))
}
#[fixture]
fn completer_strings_with_options() -> NuCompleter {
// Create a new engine
let (dir, _, mut engine, mut stack) = new_engine();
// Add record value as example
let record = r#"
# To test that the config setting has no effect on the custom completions
$env.config.completions.algorithm = "fuzzy"
def animals [] {
{
# Very rare and totally real animals
completions: ["Abcdef", "Foo Abcdef", "Acd Bar" ],
options: {
completion_algorithm: "prefix",
positional: false,
case_sensitive: false,
}
}
}
def my-command [animal: string@animals] { print $animal }"#;
assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack, dir).is_ok());
// Instantiate a new completer
NuCompleter::new(Arc::new(engine), Arc::new(stack))
}
#[fixture]
fn custom_completer() -> NuCompleter {
// Create a new engine
@ -90,14 +115,12 @@ fn subcommand_completer() -> NuCompleter {
// Create a new engine
let (dir, _, mut engine, mut stack) = new_engine();
// Use fuzzy matching, because subcommands are sorted by Levenshtein distance,
// and that's not very useful with prefix matching
let commands = r#"
$env.config.completions.algorithm = "fuzzy"
def foo [] {}
def "foo bar" [] {}
def "foo abaz" [] {}
def "foo aabrr" [] {}
def "foo aabcrr" [] {}
def food [] {}
"#;
assert!(support::merge_input(commands.as_bytes(), &mut engine, &mut stack, dir).is_ok());
@ -106,6 +129,22 @@ fn subcommand_completer() -> NuCompleter {
NuCompleter::new(Arc::new(engine), Arc::new(stack))
}
/// Use fuzzy completions but sort in alphabetical order
#[fixture]
fn fuzzy_alpha_sort_completer() -> NuCompleter {
// Create a new engine
let (dir, _, mut engine, mut stack) = new_engine();
let config = r#"
$env.config.completions.algorithm = "fuzzy"
$env.config.completions.sort = "alphabetical"
"#;
assert!(support::merge_input(config.as_bytes(), &mut engine, &mut stack, dir).is_ok());
// Instantiate a new completer
NuCompleter::new(Arc::new(engine), Arc::new(stack))
}
#[test]
fn variables_dollar_sign_with_variablecompletion() {
let (_, _, engine, stack) = new_engine();
@ -123,28 +162,28 @@ fn variables_double_dash_argument_with_flagcompletion(mut completer: NuCompleter
let suggestions = completer.complete("tst --", 6);
let expected: Vec<String> = vec!["--help".into(), "--mod".into()];
// dbg!(&expected, &suggestions);
match_suggestions(expected, suggestions);
match_suggestions(&expected, &suggestions);
}
#[rstest]
fn variables_single_dash_argument_with_flagcompletion(mut completer: NuCompleter) {
let suggestions = completer.complete("tst -", 5);
let expected: Vec<String> = vec!["--help".into(), "--mod".into(), "-h".into(), "-s".into()];
match_suggestions(expected, suggestions);
match_suggestions(&expected, &suggestions);
}
#[rstest]
fn variables_command_with_commandcompletion(mut completer_strings: NuCompleter) {
let suggestions = completer_strings.complete("my-c ", 4);
let expected: Vec<String> = vec!["my-command".into()];
match_suggestions(expected, suggestions);
match_suggestions(&expected, &suggestions);
}
#[rstest]
fn variables_subcommands_with_customcompletion(mut completer_strings: NuCompleter) {
let suggestions = completer_strings.complete("my-command ", 11);
let expected: Vec<String> = vec!["cat".into(), "dog".into(), "eel".into()];
match_suggestions(expected, suggestions);
match_suggestions(&expected, &suggestions);
}
#[rstest]
@ -153,7 +192,21 @@ fn variables_customcompletion_subcommands_with_customcompletion_2(
) {
let suggestions = completer_strings.complete("my-command ", 11);
let expected: Vec<String> = vec!["cat".into(), "dog".into(), "eel".into()];
match_suggestions(expected, suggestions);
match_suggestions(&expected, &suggestions);
}
#[rstest]
fn customcompletions_substring_matching(mut completer_strings_with_options: NuCompleter) {
let suggestions = completer_strings_with_options.complete("my-command Abcd", 15);
let expected: Vec<String> = vec!["Abcdef".into(), "Foo Abcdef".into()];
match_suggestions(&expected, &suggestions);
}
#[rstest]
fn customcompletions_case_insensitive(mut completer_strings_with_options: NuCompleter) {
let suggestions = completer_strings_with_options.complete("my-command foo", 14);
let expected: Vec<String> = vec!["Foo Abcdef".into()];
match_suggestions(&expected, &suggestions);
}
#[test]
@ -182,19 +235,19 @@ fn dotnu_completions() {
let completion_str = "source-env ".to_string();
let suggestions = completer.complete(&completion_str, completion_str.len());
match_suggestions(expected.clone(), suggestions);
match_suggestions(&expected, &suggestions);
// Test use completion
let completion_str = "use ".to_string();
let suggestions = completer.complete(&completion_str, completion_str.len());
match_suggestions(expected.clone(), suggestions);
match_suggestions(&expected, &suggestions);
// Test overlay use completion
let completion_str = "overlay use ".to_string();
let suggestions = completer.complete(&completion_str, completion_str.len());
match_suggestions(expected, suggestions);
match_suggestions(&expected, &suggestions);
}
#[test]
@ -258,8 +311,22 @@ fn file_completions() {
folder(dir.join(".hidden_folder")),
];
#[cfg(windows)]
{
let separator = '/';
let target_dir = format!("cp {dir_str}{separator}");
let slash_suggestions = completer.complete(&target_dir, target_dir.len());
let expected_slash_paths: Vec<String> = expected_paths
.iter()
.map(|s| s.replace('\\', "/"))
.collect();
match_suggestions(&expected_slash_paths, &slash_suggestions);
}
// Match the results
match_suggestions(expected_paths, suggestions);
match_suggestions(&expected_paths, &suggestions);
// Test completions for a file
let target_dir = format!("cp {}", folder(dir.join("another")));
@ -269,17 +336,91 @@ fn file_completions() {
let expected_paths: Vec<String> = vec![file(dir.join("another").join("newfile"))];
// Match the results
match_suggestions(expected_paths, suggestions);
match_suggestions(&expected_paths, &suggestions);
// Test completions for hidden files
let target_dir = format!("ls {}/.", folder(dir.join(".hidden_folder")));
let target_dir = format!("ls {}", file(dir.join(".hidden_folder").join(".")));
let suggestions = completer.complete(&target_dir, target_dir.len());
let expected_paths: Vec<String> =
vec![file(dir.join(".hidden_folder").join(".hidden_subfile"))];
#[cfg(windows)]
{
let target_dir = format!("ls {}/.", folder(dir.join(".hidden_folder")));
let slash_suggestions = completer.complete(&target_dir, target_dir.len());
let expected_slash: Vec<String> = expected_paths
.iter()
.map(|s| s.replace('\\', "/"))
.collect();
match_suggestions(&expected_slash, &slash_suggestions);
}
// Match the results
match_suggestions(expected_paths, suggestions);
match_suggestions(&expected_paths, &suggestions);
}
#[cfg(windows)]
#[test]
fn file_completions_with_mixed_separators() {
// Create a new engine
let (dir, dir_str, engine, stack) = new_dotnu_engine();
// Instantiate a new completer
let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack));
// Create Expected values
let expected_paths: Vec<String> = vec![
file(dir.join("lib-dir1").join("bar.nu")),
file(dir.join("lib-dir1").join("baz.nu")),
file(dir.join("lib-dir1").join("xyzzy.nu")),
];
let expected_slash_paths: Vec<String> = expected_paths
.iter()
.map(|s| s.replace(MAIN_SEPARATOR, "/"))
.collect();
let target_dir = format!("ls {dir_str}/lib-dir1/");
let suggestions = completer.complete(&target_dir, target_dir.len());
match_suggestions(&expected_slash_paths, &suggestions);
let target_dir = format!("cp {dir_str}\\lib-dir1/");
let suggestions = completer.complete(&target_dir, target_dir.len());
match_suggestions(&expected_slash_paths, &suggestions);
let target_dir = format!("ls {dir_str}/lib-dir1\\/");
let suggestions = completer.complete(&target_dir, target_dir.len());
match_suggestions(&expected_slash_paths, &suggestions);
let target_dir = format!("ls {dir_str}\\lib-dir1\\/");
let suggestions = completer.complete(&target_dir, target_dir.len());
match_suggestions(&expected_slash_paths, &suggestions);
let target_dir = format!("ls {dir_str}\\lib-dir1\\");
let suggestions = completer.complete(&target_dir, target_dir.len());
match_suggestions(&expected_paths, &suggestions);
let target_dir = format!("ls {dir_str}/lib-dir1\\");
let suggestions = completer.complete(&target_dir, target_dir.len());
match_suggestions(&expected_paths, &suggestions);
let target_dir = format!("ls {dir_str}/lib-dir1/\\");
let suggestions = completer.complete(&target_dir, target_dir.len());
match_suggestions(&expected_paths, &suggestions);
let target_dir = format!("ls {dir_str}\\lib-dir1/\\");
let suggestions = completer.complete(&target_dir, target_dir.len());
match_suggestions(&expected_paths, &suggestions);
}
#[test]
@ -303,7 +444,7 @@ fn partial_completions() {
];
// Match the results
match_suggestions(expected_paths, suggestions);
match_suggestions(&expected_paths, &suggestions);
// Test completions for the files whose name begin with "h"
// and are present under directories whose names begin with "pa"
@ -324,7 +465,7 @@ fn partial_completions() {
];
// Match the results
match_suggestions(expected_paths, suggestions);
match_suggestions(&expected_paths, &suggestions);
// Test completion for all files under directories whose names begin with "pa"
let dir_str = folder(dir.join("pa"));
@ -345,7 +486,7 @@ fn partial_completions() {
];
// Match the results
match_suggestions(expected_paths, suggestions);
match_suggestions(&expected_paths, &suggestions);
// Test completion for a single file
let dir_str = file(dir.join("fi").join("so"));
@ -356,7 +497,7 @@ fn partial_completions() {
let expected_paths: Vec<String> = vec![file(dir.join("final_partial").join("somefile"))];
// Match the results
match_suggestions(expected_paths, suggestions);
match_suggestions(&expected_paths, &suggestions);
// Test completion where there is a sneaky `..` in the path
let dir_str = file(dir.join("par").join("..").join("fi").join("so"));
@ -392,7 +533,7 @@ fn partial_completions() {
];
// Match the results
match_suggestions(expected_paths, suggestions);
match_suggestions(&expected_paths, &suggestions);
// Test completion for all files under directories whose names begin with "pa"
let file_str = file(dir.join("partial-a").join("have"));
@ -406,7 +547,7 @@ fn partial_completions() {
];
// Match the results
match_suggestions(expected_paths, suggestions);
match_suggestions(&expected_paths, &suggestions);
// Test completion for all files under directories whose names begin with "pa"
let file_str = file(dir.join("partial-a").join("have_ext."));
@ -420,7 +561,59 @@ fn partial_completions() {
];
// Match the results
match_suggestions(expected_paths, suggestions);
match_suggestions(&expected_paths, &suggestions);
}
#[test]
fn partial_completion_with_dot_expansions() {
let (dir, _, engine, stack) = new_partial_engine();
let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack));
let dir_str = file(
dir.join("par")
.join("...")
.join("par")
.join("fi")
.join("so"),
);
let target_dir = format!("rm {dir_str}");
let suggestions = completer.complete(&target_dir, target_dir.len());
// Create the expected values
let expected_paths: Vec<String> = vec![
file(
dir.join("partial")
.join("...")
.join("partial_completions")
.join("final_partial")
.join("somefile"),
),
file(
dir.join("partial-a")
.join("...")
.join("partial_completions")
.join("final_partial")
.join("somefile"),
),
file(
dir.join("partial-b")
.join("...")
.join("partial_completions")
.join("final_partial")
.join("somefile"),
),
file(
dir.join("partial-c")
.join("...")
.join("partial_completions")
.join("final_partial")
.join("somefile"),
),
];
// Match the results
match_suggestions(&expected_paths, &suggestions);
}
#[test]
@ -455,15 +648,16 @@ fn command_ls_with_filecompletion() {
".hidden_folder/".to_string(),
];
match_suggestions(expected_paths, suggestions);
match_suggestions(&expected_paths, &suggestions);
let target_dir = "ls custom_completion.";
let suggestions = completer.complete(target_dir, target_dir.len());
let expected_paths: Vec<String> = vec!["custom_completion.nu".to_string()];
match_suggestions(expected_paths, suggestions)
match_suggestions(&expected_paths, &suggestions);
}
#[test]
fn command_open_with_filecompletion() {
let (_, _, engine, stack) = new_engine();
@ -496,14 +690,14 @@ fn command_open_with_filecompletion() {
".hidden_folder/".to_string(),
];
match_suggestions(expected_paths, suggestions);
match_suggestions(&expected_paths, &suggestions);
let target_dir = "open custom_completion.";
let suggestions = completer.complete(target_dir, target_dir.len());
let expected_paths: Vec<String> = vec!["custom_completion.nu".to_string()];
match_suggestions(expected_paths, suggestions)
match_suggestions(&expected_paths, &suggestions);
}
#[test]
@ -538,7 +732,7 @@ fn command_rm_with_globcompletion() {
".hidden_folder/".to_string(),
];
match_suggestions(expected_paths, suggestions)
match_suggestions(&expected_paths, &suggestions)
}
#[test]
@ -573,7 +767,7 @@ fn command_cp_with_globcompletion() {
".hidden_folder/".to_string(),
];
match_suggestions(expected_paths, suggestions)
match_suggestions(&expected_paths, &suggestions)
}
#[test]
@ -608,7 +802,7 @@ fn command_save_with_filecompletion() {
".hidden_folder/".to_string(),
];
match_suggestions(expected_paths, suggestions)
match_suggestions(&expected_paths, &suggestions)
}
#[test]
@ -643,7 +837,7 @@ fn command_touch_with_filecompletion() {
".hidden_folder/".to_string(),
];
match_suggestions(expected_paths, suggestions)
match_suggestions(&expected_paths, &suggestions)
}
#[test]
@ -678,7 +872,7 @@ fn command_watch_with_filecompletion() {
".hidden_folder/".to_string(),
];
match_suggestions(expected_paths, suggestions)
match_suggestions(&expected_paths, &suggestions)
}
#[rstest]
@ -686,19 +880,19 @@ fn subcommand_completions(mut subcommand_completer: NuCompleter) {
let prefix = "foo br";
let suggestions = subcommand_completer.complete(prefix, prefix.len());
match_suggestions(
vec!["foo bar".to_string(), "foo aabrr".to_string()],
suggestions,
&vec!["foo bar".to_string(), "foo aabcrr".to_string()],
&suggestions,
);
let prefix = "foo b";
let suggestions = subcommand_completer.complete(prefix, prefix.len());
match_suggestions(
vec![
&vec![
"foo bar".to_string(),
"foo aabcrr".to_string(),
"foo abaz".to_string(),
"foo aabrr".to_string(),
],
suggestions,
&suggestions,
);
}
@ -724,7 +918,7 @@ fn file_completion_quoted() {
format!("`{}`", folder("test dir")),
];
match_suggestions(expected_paths, suggestions);
match_suggestions(&expected_paths, &suggestions);
let dir: PathBuf = "test dir".into();
let target_dir = format!("open '{}'", folder(dir.clone()));
@ -735,7 +929,7 @@ fn file_completion_quoted() {
format!("`{}`", file(dir.join("single quote"))),
];
match_suggestions(expected_paths, suggestions)
match_suggestions(&expected_paths, &suggestions)
}
#[test]
@ -770,7 +964,7 @@ fn flag_completions() {
];
// Match results
match_suggestions(expected, suggestions);
match_suggestions(&expected, &suggestions);
}
#[test]
@ -794,8 +988,207 @@ fn folder_with_directorycompletions() {
folder(dir.join(".hidden_folder")),
];
#[cfg(windows)]
{
let target_dir = format!("cd {dir_str}/");
let slash_suggestions = completer.complete(&target_dir, target_dir.len());
let expected_slash_paths: Vec<String> = expected_paths
.iter()
.map(|s| s.replace('\\', "/"))
.collect();
match_suggestions(&expected_slash_paths, &slash_suggestions);
}
// Match the results
match_suggestions(expected_paths, suggestions);
match_suggestions(&expected_paths, &suggestions);
}
#[test]
fn folder_with_directorycompletions_with_dots() {
// Create a new engine
let (dir, _, engine, stack) = new_engine();
let dir_str = dir
.join("directory_completion")
.join("folder_inside_folder")
.into_os_string()
.into_string()
.unwrap();
// Instantiate a new completer
let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack));
// Test completions for the current folder
let target_dir = format!("cd {dir_str}{MAIN_SEPARATOR}..{MAIN_SEPARATOR}");
let suggestions = completer.complete(&target_dir, target_dir.len());
// Create the expected values
let expected_paths: Vec<String> = vec![folder(
dir.join("directory_completion")
.join("folder_inside_folder")
.join("..")
.join("folder_inside_folder"),
)];
#[cfg(windows)]
{
let target_dir = format!("cd {dir_str}/../");
let slash_suggestions = completer.complete(&target_dir, target_dir.len());
let expected_slash_paths: Vec<String> = expected_paths
.iter()
.map(|s| s.replace('\\', "/"))
.collect();
match_suggestions(&expected_slash_paths, &slash_suggestions);
}
// Match the results
match_suggestions(&expected_paths, &suggestions);
}
#[test]
fn folder_with_directorycompletions_with_three_trailing_dots() {
// Create a new engine
let (dir, _, engine, stack) = new_engine();
let dir_str = dir
.join("directory_completion")
.join("folder_inside_folder")
.into_os_string()
.into_string()
.unwrap();
// Instantiate a new completer
let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack));
// Test completions for the current folder
let target_dir = format!("cd {dir_str}{MAIN_SEPARATOR}...{MAIN_SEPARATOR}");
let suggestions = completer.complete(&target_dir, target_dir.len());
// Create the expected values
let expected_paths: Vec<String> = vec![
folder(
dir.join("directory_completion")
.join("folder_inside_folder")
.join("...")
.join("another"),
),
folder(
dir.join("directory_completion")
.join("folder_inside_folder")
.join("...")
.join("directory_completion"),
),
folder(
dir.join("directory_completion")
.join("folder_inside_folder")
.join("...")
.join("test_a"),
),
folder(
dir.join("directory_completion")
.join("folder_inside_folder")
.join("...")
.join("test_b"),
),
folder(
dir.join("directory_completion")
.join("folder_inside_folder")
.join("...")
.join(".hidden_folder"),
),
];
#[cfg(windows)]
{
let target_dir = format!("cd {dir_str}/.../");
let slash_suggestions = completer.complete(&target_dir, target_dir.len());
let expected_slash_paths: Vec<String> = expected_paths
.iter()
.map(|s| s.replace('\\', "/"))
.collect();
match_suggestions(&expected_slash_paths, &slash_suggestions);
}
// Match the results
match_suggestions(&expected_paths, &suggestions);
}
#[test]
fn folder_with_directorycompletions_do_not_collapse_dots() {
// Create a new engine
let (dir, _, engine, stack) = new_engine();
let dir_str = dir
.join("directory_completion")
.join("folder_inside_folder")
.into_os_string()
.into_string()
.unwrap();
// Instantiate a new completer
let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack));
// Test completions for the current folder
let target_dir = format!("cd {dir_str}{MAIN_SEPARATOR}..{MAIN_SEPARATOR}..{MAIN_SEPARATOR}");
let suggestions = completer.complete(&target_dir, target_dir.len());
// Create the expected values
let expected_paths: Vec<String> = vec![
folder(
dir.join("directory_completion")
.join("folder_inside_folder")
.join("..")
.join("..")
.join("another"),
),
folder(
dir.join("directory_completion")
.join("folder_inside_folder")
.join("..")
.join("..")
.join("directory_completion"),
),
folder(
dir.join("directory_completion")
.join("folder_inside_folder")
.join("..")
.join("..")
.join("test_a"),
),
folder(
dir.join("directory_completion")
.join("folder_inside_folder")
.join("..")
.join("..")
.join("test_b"),
),
folder(
dir.join("directory_completion")
.join("folder_inside_folder")
.join("..")
.join("..")
.join(".hidden_folder"),
),
];
#[cfg(windows)]
{
let target_dir = format!("cd {dir_str}/../../");
let slash_suggestions = completer.complete(&target_dir, target_dir.len());
let expected_slash_paths: Vec<String> = expected_paths
.iter()
.map(|s| s.replace('\\', "/"))
.collect();
match_suggestions(&expected_slash_paths, &slash_suggestions);
}
// Match the results
match_suggestions(&expected_paths, &suggestions);
}
#[test]
@ -837,7 +1230,7 @@ fn variables_completions() {
];
// Match results
match_suggestions(expected, suggestions);
match_suggestions(&expected, &suggestions);
// Test completions for $nu.h (filter)
let suggestions = completer.complete("$nu.h", 5);
@ -851,7 +1244,7 @@ fn variables_completions() {
];
// Match results
match_suggestions(expected, suggestions);
match_suggestions(&expected, &suggestions);
// Test completions for $nu.os-info
let suggestions = completer.complete("$nu.os-info.", 12);
@ -863,7 +1256,7 @@ fn variables_completions() {
"name".into(),
];
// Match results
match_suggestions(expected, suggestions);
match_suggestions(&expected, &suggestions);
// Test completions for custom var
let suggestions = completer.complete("$actor.", 7);
@ -873,7 +1266,7 @@ fn variables_completions() {
let expected: Vec<String> = vec!["age".into(), "name".into()];
// Match results
match_suggestions(expected, suggestions);
match_suggestions(&expected, &suggestions);
// Test completions for custom var (filtering)
let suggestions = completer.complete("$actor.n", 8);
@ -883,7 +1276,7 @@ fn variables_completions() {
let expected: Vec<String> = vec!["name".into()];
// Match results
match_suggestions(expected, suggestions);
match_suggestions(&expected, &suggestions);
// Test completions for $env
let suggestions = completer.complete("$env.", 5);
@ -896,7 +1289,7 @@ fn variables_completions() {
let expected: Vec<String> = vec!["PATH".into(), "PWD".into(), "TEST".into()];
// Match results
match_suggestions(expected, suggestions);
match_suggestions(&expected, &suggestions);
// Test completions for $env
let suggestions = completer.complete("$env.T", 6);
@ -906,12 +1299,12 @@ fn variables_completions() {
let expected: Vec<String> = vec!["TEST".into()];
// Match results
match_suggestions(expected, suggestions);
match_suggestions(&expected, &suggestions);
let suggestions = completer.complete("$", 1);
let expected: Vec<String> = vec!["$actor".into(), "$env".into(), "$in".into(), "$nu".into()];
match_suggestions(expected, suggestions);
match_suggestions(&expected, &suggestions);
}
#[test]
@ -930,7 +1323,7 @@ fn alias_of_command_and_flags() {
#[cfg(not(windows))]
let expected_paths: Vec<String> = vec!["test_a/".to_string(), "test_b/".to_string()];
match_suggestions(expected_paths, suggestions)
match_suggestions(&expected_paths, &suggestions)
}
#[test]
@ -949,7 +1342,7 @@ fn alias_of_basic_command() {
#[cfg(not(windows))]
let expected_paths: Vec<String> = vec!["test_a/".to_string(), "test_b/".to_string()];
match_suggestions(expected_paths, suggestions)
match_suggestions(&expected_paths, &suggestions)
}
#[test]
@ -971,7 +1364,7 @@ fn alias_of_another_alias() {
#[cfg(not(windows))]
let expected_paths: Vec<String> = vec!["test_a/".to_string(), "test_b/".to_string()];
match_suggestions(expected_paths, suggestions)
match_suggestions(&expected_paths, &suggestions)
}
fn run_external_completion(completer: &str, input: &str) -> Vec<Suggestion> {
@ -1034,35 +1427,35 @@ fn unknown_command_completion() {
".hidden_folder/".to_string(),
];
match_suggestions(expected_paths, suggestions)
match_suggestions(&expected_paths, &suggestions)
}
#[rstest]
fn flagcompletion_triggers_after_cursor(mut completer: NuCompleter) {
let suggestions = completer.complete("tst -h", 5);
let expected: Vec<String> = vec!["--help".into(), "--mod".into(), "-h".into(), "-s".into()];
match_suggestions(expected, suggestions);
match_suggestions(&expected, &suggestions);
}
#[rstest]
fn customcompletion_triggers_after_cursor(mut completer_strings: NuCompleter) {
let suggestions = completer_strings.complete("my-command c", 11);
let expected: Vec<String> = vec!["cat".into(), "dog".into(), "eel".into()];
match_suggestions(expected, suggestions);
match_suggestions(&expected, &suggestions);
}
#[rstest]
fn customcompletion_triggers_after_cursor_piped(mut completer_strings: NuCompleter) {
let suggestions = completer_strings.complete("my-command c | ls", 11);
let expected: Vec<String> = vec!["cat".into(), "dog".into(), "eel".into()];
match_suggestions(expected, suggestions);
match_suggestions(&expected, &suggestions);
}
#[rstest]
fn flagcompletion_triggers_after_cursor_piped(mut completer: NuCompleter) {
let suggestions = completer.complete("tst -h | ls", 5);
let expected: Vec<String> = vec!["--help".into(), "--mod".into(), "-h".into(), "-s".into()];
match_suggestions(expected, suggestions);
match_suggestions(&expected, &suggestions);
}
#[test]
@ -1096,77 +1489,88 @@ fn filecompletions_triggers_after_cursor() {
".hidden_folder/".to_string(),
];
match_suggestions(expected_paths, suggestions);
match_suggestions(&expected_paths, &suggestions);
}
#[rstest]
fn extern_custom_completion_positional(mut extern_completer: NuCompleter) {
let suggestions = extern_completer.complete("spam ", 5);
let expected: Vec<String> = vec!["cat".into(), "dog".into(), "eel".into()];
match_suggestions(expected, suggestions);
match_suggestions(&expected, &suggestions);
}
#[rstest]
fn extern_custom_completion_long_flag_1(mut extern_completer: NuCompleter) {
let suggestions = extern_completer.complete("spam --foo=", 11);
let expected: Vec<String> = vec!["cat".into(), "dog".into(), "eel".into()];
match_suggestions(expected, suggestions);
match_suggestions(&expected, &suggestions);
}
#[rstest]
fn extern_custom_completion_long_flag_2(mut extern_completer: NuCompleter) {
let suggestions = extern_completer.complete("spam --foo ", 11);
let expected: Vec<String> = vec!["cat".into(), "dog".into(), "eel".into()];
match_suggestions(expected, suggestions);
match_suggestions(&expected, &suggestions);
}
#[rstest]
fn extern_custom_completion_long_flag_short(mut extern_completer: NuCompleter) {
let suggestions = extern_completer.complete("spam -f ", 8);
let expected: Vec<String> = vec!["cat".into(), "dog".into(), "eel".into()];
match_suggestions(expected, suggestions);
match_suggestions(&expected, &suggestions);
}
#[rstest]
fn extern_custom_completion_short_flag(mut extern_completer: NuCompleter) {
let suggestions = extern_completer.complete("spam -b ", 8);
let expected: Vec<String> = vec!["cat".into(), "dog".into(), "eel".into()];
match_suggestions(expected, suggestions);
match_suggestions(&expected, &suggestions);
}
#[rstest]
fn extern_complete_flags(mut extern_completer: NuCompleter) {
let suggestions = extern_completer.complete("spam -", 6);
let expected: Vec<String> = vec!["--foo".into(), "-b".into(), "-f".into()];
match_suggestions(expected, suggestions);
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);
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);
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);
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);
match_suggestions(&expected, &suggestions);
}
#[rstest]
fn sort_fuzzy_completions_in_alphabetical_order(mut fuzzy_alpha_sort_completer: NuCompleter) {
let suggestions = fuzzy_alpha_sort_completer.complete("ls nu", 5);
// Even though "nushell" is a better match, it should come second because
// the completions should be sorted in alphabetical order
match_suggestions(
&vec!["custom_completion.nu".into(), "nushell".into()],
&suggestions,
);
}
#[ignore = "was reverted, still needs fixing"]

View File

@ -186,7 +186,7 @@ pub fn new_partial_engine() -> (AbsolutePathBuf, String, EngineState, Stack) {
}
// match a list of suggestions with the expected values
pub fn match_suggestions(expected: Vec<String>, suggestions: Vec<Suggestion>) {
pub fn match_suggestions(expected: &Vec<String>, suggestions: &Vec<Suggestion>) {
let expected_len = expected.len();
let suggestions_len = suggestions.len();
if expected_len != suggestions_len {
@ -196,13 +196,13 @@ pub fn match_suggestions(expected: Vec<String>, suggestions: Vec<Suggestion>) {
Expected: {expected:#?}\n"
)
}
assert_eq!(
expected,
suggestions
.into_iter()
.map(|it| it.value)
.collect::<Vec<_>>()
);
let suggestoins_str = suggestions
.iter()
.map(|it| it.value.clone())
.collect::<Vec<_>>();
assert_eq!(expected, &suggestoins_str);
}
// append the separator to the converted path

View File

@ -5,15 +5,18 @@ edition = "2021"
license = "MIT"
name = "nu-cmd-base"
repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cmd-base"
version = "0.96.1"
version = "0.98.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lints]
workspace = true
[dependencies]
nu-engine = { path = "../nu-engine", version = "0.96.1" }
nu-parser = { path = "../nu-parser", version = "0.96.1" }
nu-path = { path = "../nu-path", version = "0.96.1" }
nu-protocol = { path = "../nu-protocol", version = "0.96.1" }
nu-engine = { path = "../nu-engine", version = "0.98.0" }
nu-parser = { path = "../nu-parser", version = "0.98.0" }
nu-path = { path = "../nu-path", version = "0.98.0" }
nu-protocol = { path = "../nu-protocol", version = "0.98.0" }
indexmap = { workspace = true }
miette = { workspace = true }

View File

@ -3,7 +3,7 @@ use miette::Result;
use nu_engine::{eval_block, eval_block_with_early_return};
use nu_parser::parse;
use nu_protocol::{
cli_error::{report_error, report_error_new},
cli_error::{report_parse_error, report_shell_error},
debugger::WithoutDebug,
engine::{Closure, EngineState, Stack, StateWorkingSet},
PipelineData, PositionalArg, ShellError, Span, Type, Value, VarId,
@ -91,7 +91,7 @@ pub fn eval_hook(
false,
);
if let Some(err) = working_set.parse_errors.first() {
report_error(&working_set, err);
report_parse_error(&working_set, err);
return Err(ShellError::UnsupportedConfigValue {
expected: "valid source code".into(),
@ -123,7 +123,7 @@ pub fn eval_hook(
output = pipeline_data;
}
Err(err) => {
report_error_new(engine_state, &err);
report_shell_error(engine_state, &err);
}
}
@ -223,7 +223,7 @@ pub fn eval_hook(
false,
);
if let Some(err) = working_set.parse_errors.first() {
report_error(&working_set, err);
report_parse_error(&working_set, err);
return Err(ShellError::UnsupportedConfigValue {
expected: "valid source code".into(),
@ -251,7 +251,7 @@ pub fn eval_hook(
output = pipeline_data;
}
Err(err) => {
report_error_new(engine_state, &err);
report_shell_error(engine_state, &err);
}
}

View File

@ -3,21 +3,26 @@ use nu_protocol::{
engine::{EngineState, Stack},
Range, ShellError, Span, Value,
};
use std::{ops::Bound, path::PathBuf};
use std::ops::Bound;
pub fn get_init_cwd() -> PathBuf {
std::env::current_dir().unwrap_or_else(|_| {
pub fn get_init_cwd() -> AbsolutePathBuf {
std::env::current_dir()
.ok()
.and_then(|path| AbsolutePathBuf::try_from(path).ok())
.or_else(|| {
std::env::var("PWD")
.map(Into::into)
.unwrap_or_else(|_| nu_path::home_dir().unwrap_or_default())
.ok()
.and_then(|path| AbsolutePathBuf::try_from(path).ok())
})
.or_else(nu_path::home_dir)
.expect("Failed to get current working directory")
}
pub fn get_guaranteed_cwd(engine_state: &EngineState, stack: &Stack) -> PathBuf {
pub fn get_guaranteed_cwd(engine_state: &EngineState, stack: &Stack) -> AbsolutePathBuf {
engine_state
.cwd(Some(stack))
.map(AbsolutePathBuf::into_std_path_buf)
.unwrap_or(crate::util::get_init_cwd())
.ok()
.unwrap_or_else(get_init_cwd)
}
type MakeRangeError = fn(&str, Span) -> ShellError;

View File

@ -5,21 +5,24 @@ edition = "2021"
license = "MIT"
name = "nu-cmd-extra"
repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cmd-extra"
version = "0.96.1"
version = "0.98.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
bench = false
[lints]
workspace = true
[dependencies]
nu-cmd-base = { path = "../nu-cmd-base", version = "0.96.1" }
nu-engine = { path = "../nu-engine", version = "0.96.1" }
nu-json = { version = "0.96.1", path = "../nu-json" }
nu-parser = { path = "../nu-parser", version = "0.96.1" }
nu-pretty-hex = { version = "0.96.1", path = "../nu-pretty-hex" }
nu-protocol = { path = "../nu-protocol", version = "0.96.1" }
nu-utils = { path = "../nu-utils", version = "0.96.1" }
nu-cmd-base = { path = "../nu-cmd-base", version = "0.98.0" }
nu-engine = { path = "../nu-engine", version = "0.98.0" }
nu-json = { version = "0.98.0", path = "../nu-json" }
nu-parser = { path = "../nu-parser", version = "0.98.0" }
nu-pretty-hex = { version = "0.98.0", path = "../nu-pretty-hex" }
nu-protocol = { path = "../nu-protocol", version = "0.98.0" }
nu-utils = { path = "../nu-utils", version = "0.98.0" }
# Potential dependencies for extras
heck = { workspace = true }
@ -33,6 +36,6 @@ v_htmlescape = { workspace = true }
itertools = { workspace = true }
[dev-dependencies]
nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.96.1" }
nu-command = { path = "../nu-command", version = "0.96.1" }
nu-test-support = { path = "../nu-test-support", version = "0.96.1" }
nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.98.0" }
nu-command = { path = "../nu-command", version = "0.98.0" }
nu-test-support = { path = "../nu-test-support", version = "0.98.0" }

View File

@ -37,7 +37,7 @@ impl Command for BitsAnd {
.category(Category::Bits)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Performs bitwise and for ints or binary values."
}

View File

@ -14,11 +14,11 @@ impl Command for Bits {
.input_output_types(vec![(Type::Nothing, Type::String)])
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Various commands for working with bits."
}
fn extra_usage(&self) -> &str {
fn extra_description(&self) -> &str {
"You must use one of the following subcommands. Using this command as-is will only produce this help message."
}

View File

@ -45,7 +45,7 @@ impl Command for BitsInto {
.category(Category::Conversions)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Convert value to a binary primitive."
}

View File

@ -44,6 +44,25 @@ enum InputNumType {
SignedEight,
}
impl InputNumType {
fn num_bits(self) -> u32 {
match self {
InputNumType::One => 8,
InputNumType::Two => 16,
InputNumType::Four => 32,
InputNumType::Eight => 64,
InputNumType::SignedOne => 8,
InputNumType::SignedTwo => 16,
InputNumType::SignedFour => 32,
InputNumType::SignedEight => 64,
}
}
fn is_permitted_bit_shift(self, bits: u32) -> bool {
bits < self.num_bits()
}
}
fn get_number_bytes(
number_bytes: Option<Spanned<usize>>,
head: Span,

View File

@ -51,7 +51,7 @@ impl Command for BitsNot {
.category(Category::Bits)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Performs logical negation on each bit."
}

View File

@ -38,7 +38,7 @@ impl Command for BitsOr {
.category(Category::Bits)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Performs bitwise or for ints or binary values."
}

View File

@ -1,11 +1,10 @@
use super::{get_input_num_type, get_number_bytes, InputNumType, NumberBytes};
use itertools::Itertools;
use nu_cmd_base::input_handler::{operate, CmdArgument};
use nu_engine::command_prelude::*;
struct Arguments {
signed: bool,
bits: usize,
bits: Spanned<usize>,
number_size: NumberBytes,
}
@ -53,7 +52,7 @@ impl Command for BitsRol {
.category(Category::Bits)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Bitwise rotate left for ints or binary values."
}
@ -69,7 +68,7 @@ impl Command for BitsRol {
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let head = call.head;
let bits: usize = call.req(engine_state, stack, 0)?;
let bits = call.req(engine_state, stack, 0)?;
let signed = call.has_flag(engine_state, stack, "signed")?;
let number_bytes: Option<Spanned<usize>> =
call.get_flag(engine_state, stack, "number-bytes")?;
@ -119,6 +118,8 @@ fn action(input: &Value, args: &Arguments, span: Span) -> Value {
number_size,
bits,
} = *args;
let bits_span = bits.span;
let bits = bits.item;
match input {
Value::Int { val, .. } => {
@ -127,6 +128,19 @@ fn action(input: &Value, args: &Arguments, span: Span) -> Value {
let bits = bits as u32;
let input_num_type = get_input_num_type(val, signed, number_size);
if bits > input_num_type.num_bits() {
return Value::error(
ShellError::IncorrectValue {
msg: format!(
"Trying to rotate by more than the available bits ({})",
input_num_type.num_bits()
),
val_span: bits_span,
call_span: span,
},
span,
);
}
let int = match input_num_type {
One => (val as u8).rotate_left(bits) as i64,
Two => (val as u16).rotate_left(bits) as i64,
@ -157,16 +171,28 @@ fn action(input: &Value, args: &Arguments, span: Span) -> Value {
Value::int(int, span)
}
Value::Binary { val, .. } => {
let len = val.len();
if bits > len * 8 {
return Value::error(
ShellError::IncorrectValue {
msg: format!(
"Trying to rotate by more than the available bits ({})",
len * 8
),
val_span: bits_span,
call_span: span,
},
span,
);
}
let byte_shift = bits / 8;
let bit_rotate = bits % 8;
let mut bytes = val
.iter()
.copied()
.circular_tuple_windows::<(u8, u8)>()
.map(|(lhs, rhs)| (lhs << bit_rotate) | (rhs >> (8 - bit_rotate)))
.collect::<Vec<u8>>();
bytes.rotate_left(byte_shift);
let bytes = if bit_rotate == 0 {
rotate_bytes_left(val, byte_shift)
} else {
rotate_bytes_and_bits_left(val, byte_shift, bit_rotate)
};
Value::binary(bytes, span)
}
@ -184,6 +210,34 @@ fn action(input: &Value, args: &Arguments, span: Span) -> Value {
}
}
fn rotate_bytes_left(data: &[u8], byte_shift: usize) -> Vec<u8> {
let len = data.len();
let mut output = vec![0; len];
output[..len - byte_shift].copy_from_slice(&data[byte_shift..]);
output[len - byte_shift..].copy_from_slice(&data[..byte_shift]);
output
}
fn rotate_bytes_and_bits_left(data: &[u8], byte_shift: usize, bit_shift: usize) -> Vec<u8> {
debug_assert!(byte_shift < data.len());
debug_assert!(
(1..8).contains(&bit_shift),
"Bit shifts of 0 can't be handled by this impl and everything else should be part of the byteshift");
let mut bytes = Vec::with_capacity(data.len());
let mut next_index = byte_shift;
for _ in 0..data.len() {
let curr_byte = data[next_index];
next_index += 1;
if next_index == data.len() {
next_index = 0;
}
let next_byte = data[next_index];
let new_byte = (curr_byte << bit_shift) | (next_byte >> (8 - bit_shift));
bytes.push(new_byte);
}
bytes
}
#[cfg(test)]
mod test {
use super::*;

View File

@ -1,11 +1,10 @@
use super::{get_input_num_type, get_number_bytes, InputNumType, NumberBytes};
use itertools::Itertools;
use nu_cmd_base::input_handler::{operate, CmdArgument};
use nu_engine::command_prelude::*;
struct Arguments {
signed: bool,
bits: usize,
bits: Spanned<usize>,
number_size: NumberBytes,
}
@ -53,7 +52,7 @@ impl Command for BitsRor {
.category(Category::Bits)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Bitwise rotate right for ints or binary values."
}
@ -69,7 +68,7 @@ impl Command for BitsRor {
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let head = call.head;
let bits: usize = call.req(engine_state, stack, 0)?;
let bits = call.req(engine_state, stack, 0)?;
let signed = call.has_flag(engine_state, stack, "signed")?;
let number_bytes: Option<Spanned<usize>> =
call.get_flag(engine_state, stack, "number-bytes")?;
@ -123,6 +122,8 @@ fn action(input: &Value, args: &Arguments, span: Span) -> Value {
number_size,
bits,
} = *args;
let bits_span = bits.span;
let bits = bits.item;
match input {
Value::Int { val, .. } => {
@ -131,6 +132,19 @@ fn action(input: &Value, args: &Arguments, span: Span) -> Value {
let bits = bits as u32;
let input_num_type = get_input_num_type(val, signed, number_size);
if bits > input_num_type.num_bits() {
return Value::error(
ShellError::IncorrectValue {
msg: format!(
"Trying to rotate by more than the available bits ({})",
input_num_type.num_bits()
),
val_span: bits_span,
call_span: span,
},
span,
);
}
let int = match input_num_type {
One => (val as u8).rotate_right(bits) as i64,
Two => (val as u16).rotate_right(bits) as i64,
@ -161,16 +175,28 @@ fn action(input: &Value, args: &Arguments, span: Span) -> Value {
Value::int(int, span)
}
Value::Binary { val, .. } => {
let len = val.len();
if bits > len * 8 {
return Value::error(
ShellError::IncorrectValue {
msg: format!(
"Trying to rotate by more than the available bits ({})",
len * 8
),
val_span: bits_span,
call_span: span,
},
span,
);
}
let byte_shift = bits / 8;
let bit_rotate = bits % 8;
let mut bytes = val
.iter()
.copied()
.circular_tuple_windows::<(u8, u8)>()
.map(|(lhs, rhs)| (lhs >> bit_rotate) | (rhs << (8 - bit_rotate)))
.collect::<Vec<u8>>();
bytes.rotate_right(byte_shift);
let bytes = if bit_rotate == 0 {
rotate_bytes_right(val, byte_shift)
} else {
rotate_bytes_and_bits_right(val, byte_shift, bit_rotate)
};
Value::binary(bytes, span)
}
@ -188,6 +214,35 @@ fn action(input: &Value, args: &Arguments, span: Span) -> Value {
}
}
fn rotate_bytes_right(data: &[u8], byte_shift: usize) -> Vec<u8> {
let len = data.len();
let mut output = vec![0; len];
output[byte_shift..].copy_from_slice(&data[..len - byte_shift]);
output[..byte_shift].copy_from_slice(&data[len - byte_shift..]);
output
}
fn rotate_bytes_and_bits_right(data: &[u8], byte_shift: usize, bit_shift: usize) -> Vec<u8> {
debug_assert!(byte_shift < data.len());
debug_assert!(
(1..8).contains(&bit_shift),
"Bit shifts of 0 can't be handled by this impl and everything else should be part of the byteshift"
);
let mut bytes = Vec::with_capacity(data.len());
let mut previous_index = data.len() - byte_shift - 1;
for _ in 0..data.len() {
let previous_byte = data[previous_index];
previous_index += 1;
if previous_index == data.len() {
previous_index = 0;
}
let curr_byte = data[previous_index];
let rotated_byte = (curr_byte >> bit_shift) | (previous_byte << (8 - bit_shift));
bytes.push(rotated_byte);
}
bytes
}
#[cfg(test)]
mod test {
use super::*;

View File

@ -7,7 +7,7 @@ use std::iter;
struct Arguments {
signed: bool,
bits: usize,
bits: Spanned<usize>,
number_size: NumberBytes,
}
@ -55,7 +55,7 @@ impl Command for BitsShl {
.category(Category::Bits)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Bitwise shift left for ints or binary values."
}
@ -71,7 +71,9 @@ impl Command for BitsShl {
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let head = call.head;
let bits: usize = call.req(engine_state, stack, 0)?;
// This restricts to a positive shift value (our underlying operations do not
// permit them)
let bits: Spanned<usize> = call.req(engine_state, stack, 0)?;
let signed = call.has_flag(engine_state, stack, "signed")?;
let number_bytes: Option<Spanned<usize>> =
call.get_flag(engine_state, stack, "number-bytes")?;
@ -131,14 +133,29 @@ fn action(input: &Value, args: &Arguments, span: Span) -> Value {
number_size,
bits,
} = *args;
let bits_span = bits.span;
let bits = bits.item;
match input {
Value::Int { val, .. } => {
use InputNumType::*;
let val = *val;
let bits = bits as u64;
let bits = bits as u32;
let input_num_type = get_input_num_type(val, signed, number_size);
if !input_num_type.is_permitted_bit_shift(bits) {
return Value::error(
ShellError::IncorrectValue {
msg: format!(
"Trying to shift by more than the available bits (permitted < {})",
input_num_type.num_bits()
),
val_span: bits_span,
call_span: span,
},
span,
);
}
let int = match input_num_type {
One => ((val as u8) << bits) as i64,
Two => ((val as u16) << bits) as i64,
@ -147,12 +164,14 @@ fn action(input: &Value, args: &Arguments, span: Span) -> Value {
let Ok(i) = i64::try_from((val as u64) << bits) else {
return Value::error(
ShellError::GenericError {
error: "result out of range for specified number".into(),
error: "result out of range for int".into(),
msg: format!(
"shifting left by {bits} is out of range for the value {val}"
),
span: Some(span),
help: None,
help: Some(
"Ensure the result fits in a 64-bit signed integer.".into(),
),
inner: vec![],
},
span,
@ -172,19 +191,26 @@ fn action(input: &Value, args: &Arguments, span: Span) -> Value {
let byte_shift = bits / 8;
let bit_shift = bits % 8;
use itertools::Position::*;
let bytes = val
.iter()
.copied()
.skip(byte_shift)
.circular_tuple_windows::<(u8, u8)>()
.with_position()
.map(|(pos, (lhs, rhs))| match pos {
Last | Only => lhs << bit_shift,
_ => (lhs << bit_shift) | (rhs >> bit_shift),
})
.chain(iter::repeat(0).take(byte_shift))
.collect::<Vec<u8>>();
// This is purely for symmetry with the int case and the fact that the
// shift right implementation in its current form panicked with an overflow
if bits > val.len() * 8 {
return Value::error(
ShellError::IncorrectValue {
msg: format!(
"Trying to shift by more than the available bits ({})",
val.len() * 8
),
val_span: bits_span,
call_span: span,
},
span,
);
}
let bytes = if bit_shift == 0 {
shift_bytes_left(val, byte_shift)
} else {
shift_bytes_and_bits_left(val, byte_shift, bit_shift)
};
Value::binary(bytes, span)
}
@ -202,6 +228,31 @@ fn action(input: &Value, args: &Arguments, span: Span) -> Value {
}
}
fn shift_bytes_left(data: &[u8], byte_shift: usize) -> Vec<u8> {
let len = data.len();
let mut output = vec![0; len];
output[..len - byte_shift].copy_from_slice(&data[byte_shift..]);
output
}
fn shift_bytes_and_bits_left(data: &[u8], byte_shift: usize, bit_shift: usize) -> Vec<u8> {
use itertools::Position::*;
debug_assert!((1..8).contains(&bit_shift),
"Bit shifts of 0 can't be handled by this impl and everything else should be part of the byteshift"
);
data.iter()
.copied()
.skip(byte_shift)
.circular_tuple_windows::<(u8, u8)>()
.with_position()
.map(|(pos, (lhs, rhs))| match pos {
Last | Only => lhs << bit_shift,
_ => (lhs << bit_shift) | (rhs >> (8 - bit_shift)),
})
.chain(iter::repeat(0).take(byte_shift))
.collect::<Vec<u8>>()
}
#[cfg(test)]
mod test {
use super::*;

View File

@ -1,13 +1,10 @@
use super::{get_input_num_type, get_number_bytes, InputNumType, NumberBytes};
use itertools::Itertools;
use nu_cmd_base::input_handler::{operate, CmdArgument};
use nu_engine::command_prelude::*;
use std::iter;
struct Arguments {
signed: bool,
bits: usize,
bits: Spanned<usize>,
number_size: NumberBytes,
}
@ -55,7 +52,7 @@ impl Command for BitsShr {
.category(Category::Bits)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Bitwise shift right for ints or binary values."
}
@ -71,7 +68,9 @@ impl Command for BitsShr {
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let head = call.head;
let bits: usize = call.req(engine_state, stack, 0)?;
// This restricts to a positive shift value (our underlying operations do not
// permit them)
let bits: Spanned<usize> = call.req(engine_state, stack, 0)?;
let signed = call.has_flag(engine_state, stack, "signed")?;
let number_bytes: Option<Spanned<usize>> =
call.get_flag(engine_state, stack, "number-bytes")?;
@ -121,6 +120,8 @@ fn action(input: &Value, args: &Arguments, span: Span) -> Value {
number_size,
bits,
} = *args;
let bits_span = bits.span;
let bits = bits.item;
match input {
Value::Int { val, .. } => {
@ -129,6 +130,19 @@ fn action(input: &Value, args: &Arguments, span: Span) -> Value {
let bits = bits as u32;
let input_num_type = get_input_num_type(val, signed, number_size);
if !input_num_type.is_permitted_bit_shift(bits) {
return Value::error(
ShellError::IncorrectValue {
msg: format!(
"Trying to shift by more than the available bits (permitted < {})",
input_num_type.num_bits()
),
val_span: bits_span,
call_span: span,
},
span,
);
}
let int = match input_num_type {
One => ((val as u8) >> bits) as i64,
Two => ((val as u16) >> bits) as i64,
@ -147,21 +161,27 @@ fn action(input: &Value, args: &Arguments, span: Span) -> Value {
let bit_shift = bits % 8;
let len = val.len();
use itertools::Position::*;
let bytes = iter::repeat(0)
.take(byte_shift)
.chain(
val.iter()
.copied()
.circular_tuple_windows::<(u8, u8)>()
.with_position()
.map(|(pos, (lhs, rhs))| match pos {
First | Only => lhs >> bit_shift,
_ => (lhs >> bit_shift) | (rhs << bit_shift),
})
.take(len - byte_shift),
)
.collect::<Vec<u8>>();
// This check is done for symmetry with the int case and the previous
// implementation would overflow byte indices leading to unexpected output
// lengths
if bits > len * 8 {
return Value::error(
ShellError::IncorrectValue {
msg: format!(
"Trying to shift by more than the available bits ({})",
len * 8
),
val_span: bits_span,
call_span: span,
},
span,
);
}
let bytes = if bit_shift == 0 {
shift_bytes_right(val, byte_shift)
} else {
shift_bytes_and_bits_right(val, byte_shift, bit_shift)
};
Value::binary(bytes, span)
}
@ -178,6 +198,35 @@ fn action(input: &Value, args: &Arguments, span: Span) -> Value {
),
}
}
fn shift_bytes_right(data: &[u8], byte_shift: usize) -> Vec<u8> {
let len = data.len();
let mut output = vec![0; len];
output[byte_shift..].copy_from_slice(&data[..len - byte_shift]);
output
}
fn shift_bytes_and_bits_right(data: &[u8], byte_shift: usize, bit_shift: usize) -> Vec<u8> {
debug_assert!(
bit_shift > 0 && bit_shift < 8,
"bit_shift should be in the range (0, 8)"
);
let len = data.len();
let mut output = vec![0; len];
for i in byte_shift..len {
let shifted_bits = data[i - byte_shift] >> bit_shift;
let carried_bits = if i > byte_shift {
data[i - byte_shift - 1] << (8 - bit_shift)
} else {
0
};
let shifted_byte = shifted_bits | carried_bits;
output[i] = shifted_byte;
}
output
}
#[cfg(test)]
mod test {

View File

@ -38,7 +38,7 @@ impl Command for BitsXor {
.category(Category::Bits)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Performs bitwise xor for ints or binary values."
}

View File

@ -9,7 +9,7 @@ impl Command for Fmt {
"fmt"
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Format a number."
}

View File

@ -9,7 +9,7 @@ impl Command for EachWhile {
"each while"
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Run a closure on each row of the input list until a null is found, then create a new list with the results."
}

View File

@ -18,11 +18,11 @@ impl Command for Roll {
.input_output_types(vec![(Type::Nothing, Type::String)])
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Rolling commands for tables."
}
fn extra_usage(&self) -> &str {
fn extra_description(&self) -> &str {
"You must use one of the following subcommands. Using this command as-is will only produce this help message."
}

View File

@ -21,7 +21,7 @@ impl Command for RollDown {
.category(Category::Filters)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Roll table rows down."
}

View File

@ -33,7 +33,7 @@ impl Command for RollLeft {
.category(Category::Filters)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Roll record or table columns left."
}

View File

@ -33,7 +33,7 @@ impl Command for RollRight {
.category(Category::Filters)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Roll table columns right."
}

View File

@ -21,7 +21,7 @@ impl Command for RollUp {
.category(Category::Filters)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Roll table rows up."
}

View File

@ -23,7 +23,7 @@ impl Command for Rotate {
.category(Category::Filters)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Rotates a table or record clockwise (default) or counter-clockwise (use --ccw flag)."
}

View File

@ -27,7 +27,7 @@ impl Command for UpdateCells {
.category(Category::Filters)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Update the table cells."
}

View File

@ -14,7 +14,7 @@ impl Command for FromUrl {
.category(Category::Formats)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Parse url-encoded string as a record."
}

View File

@ -138,11 +138,11 @@ impl Command for ToHtml {
]
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Convert table into simple HTML."
}
fn extra_usage(&self) -> &str {
fn extra_description(&self) -> &str {
"Screenshots of the themes can be browsed here: https://github.com/mbadolato/iTerm2-Color-Schemes."
}

View File

@ -22,7 +22,7 @@ impl Command for SubCommand {
.category(Category::Math)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Returns the arccosine of the number."
}

View File

@ -21,7 +21,7 @@ impl Command for SubCommand {
.category(Category::Math)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Returns the inverse of the hyperbolic cosine function."
}

View File

@ -22,7 +22,7 @@ impl Command for SubCommand {
.category(Category::Math)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Returns the arcsine of the number."
}

View File

@ -21,7 +21,7 @@ impl Command for SubCommand {
.category(Category::Math)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Returns the inverse of the hyperbolic sine function."
}

View File

@ -22,7 +22,7 @@ impl Command for SubCommand {
.category(Category::Math)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Returns the arctangent of the number."
}

View File

@ -21,7 +21,7 @@ impl Command for SubCommand {
.category(Category::Math)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Returns the inverse of the hyperbolic tangent function."
}

View File

@ -21,7 +21,7 @@ impl Command for SubCommand {
.category(Category::Math)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Returns the cosine of the number."
}

View File

@ -21,7 +21,7 @@ impl Command for SubCommand {
.category(Category::Math)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Returns the hyperbolic cosine of the number."
}

View File

@ -21,7 +21,7 @@ impl Command for SubCommand {
.category(Category::Math)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Returns e raised to the power of x."
}

View File

@ -21,7 +21,7 @@ impl Command for SubCommand {
.category(Category::Math)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Returns the natural logarithm. Base: (math e)."
}

View File

@ -21,7 +21,7 @@ impl Command for SubCommand {
.category(Category::Math)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Returns the sine of the number."
}

View File

@ -21,7 +21,7 @@ impl Command for SubCommand {
.category(Category::Math)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Returns the hyperbolic sine of the number."
}

View File

@ -21,7 +21,7 @@ impl Command for SubCommand {
.category(Category::Math)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Returns the tangent of the number."
}

View File

@ -21,7 +21,7 @@ impl Command for SubCommand {
.category(Category::Math)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Returns the hyperbolic tangent of the number."
}

View File

@ -45,8 +45,6 @@ pub fn add_extra_command_context(mut engine_state: EngineState) -> EngineState {
bind_command!(
strings::format::FormatPattern,
strings::encode_decode::EncodeHex,
strings::encode_decode::DecodeHex,
strings::str_::case::Str,
strings::str_::case::StrCamelCase,
strings::str_::case::StrKebabCase,

View File

@ -53,7 +53,7 @@ impl Command for SubCommand {
.category(Category::Platform)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Add a color gradient (using ANSI color codes) to the given string."
}

View File

@ -29,7 +29,7 @@ impl Command for DecodeHex {
.category(Category::Formats)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Hex decode a value."
}

View File

@ -29,7 +29,7 @@ impl Command for EncodeHex {
.category(Category::Formats)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Encode a binary value using hex."
}

View File

@ -1,192 +0,0 @@
use nu_cmd_base::input_handler::{operate as general_operate, CmdArgument};
use nu_engine::command_prelude::*;
enum HexDecodingError {
InvalidLength(usize),
InvalidDigit(usize, char),
}
fn hex_decode(value: &str) -> Result<Vec<u8>, HexDecodingError> {
let mut digits = value
.chars()
.enumerate()
.filter(|(_, c)| !c.is_whitespace());
let mut res = Vec::with_capacity(value.len() / 2);
loop {
let c1 = match digits.next() {
Some((ind, c)) => match c.to_digit(16) {
Some(d) => d,
None => return Err(HexDecodingError::InvalidDigit(ind, c)),
},
None => return Ok(res),
};
let c2 = match digits.next() {
Some((ind, c)) => match c.to_digit(16) {
Some(d) => d,
None => return Err(HexDecodingError::InvalidDigit(ind, c)),
},
None => {
return Err(HexDecodingError::InvalidLength(value.len()));
}
};
res.push((c1 << 4 | c2) as u8);
}
}
fn hex_digit(num: u8) -> char {
match num {
0..=9 => (num + b'0') as char,
10..=15 => (num - 10 + b'A') as char,
_ => unreachable!(),
}
}
fn hex_encode(bytes: &[u8]) -> String {
let mut res = String::with_capacity(bytes.len() * 2);
for byte in bytes {
res.push(hex_digit(byte >> 4));
res.push(hex_digit(byte & 0b1111));
}
res
}
#[derive(Clone)]
pub struct HexConfig {
pub action_type: ActionType,
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum ActionType {
Encode,
Decode,
}
struct Arguments {
cell_paths: Option<Vec<CellPath>>,
encoding_config: HexConfig,
}
impl CmdArgument for Arguments {
fn take_cell_paths(&mut self) -> Option<Vec<CellPath>> {
self.cell_paths.take()
}
}
pub fn operate(
action_type: ActionType,
engine_state: &EngineState,
stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let cell_paths: Vec<CellPath> = call.rest(engine_state, stack, 0)?;
let cell_paths = (!cell_paths.is_empty()).then_some(cell_paths);
let args = Arguments {
encoding_config: HexConfig { action_type },
cell_paths,
};
general_operate(action, args, input, call.head, engine_state.signals())
}
fn action(
input: &Value,
// only used for `decode` action
args: &Arguments,
command_span: Span,
) -> Value {
let hex_config = &args.encoding_config;
match input {
// Propagate existing errors.
Value::Error { .. } => input.clone(),
Value::Binary { val, .. } => match hex_config.action_type {
ActionType::Encode => Value::string(hex_encode(val.as_ref()), command_span),
ActionType::Decode => Value::error(
ShellError::UnsupportedInput { msg: "Binary data can only be encoded".to_string(), input: "value originates from here".into(), msg_span: command_span, input_span: input.span() },
command_span,
),
},
Value::String { val, .. } => {
match hex_config.action_type {
ActionType::Encode => Value::error(
ShellError::UnsupportedInput { msg: "String value can only be decoded".to_string(), input: "value originates from here".into(), msg_span: command_span, input_span: input.span() },
command_span,
),
ActionType::Decode => match hex_decode(val.as_ref()) {
Ok(decoded_value) => Value::binary(decoded_value, command_span),
Err(HexDecodingError::InvalidLength(len)) => Value::error(ShellError::GenericError {
error: "value could not be hex decoded".into(),
msg: format!("invalid hex input length: {len}. The length should be even"),
span: Some(command_span),
help: None,
inner: vec![],
},
command_span,
),
Err(HexDecodingError::InvalidDigit(index, digit)) => Value::error(ShellError::GenericError {
error: "value could not be hex decoded".into(),
msg: format!("invalid hex digit: '{digit}' at index {index}. Only 0-9, A-F, a-f are allowed in hex encoding"),
span: Some(command_span),
help: None,
inner: vec![],
},
command_span,
),
},
}
}
other => Value::error(
ShellError::TypeMismatch {
err_message: format!("string or binary, not {}", other.get_type()),
span: other.span(),
},
other.span(),
),
}
}
#[cfg(test)]
mod tests {
use super::{action, ActionType, Arguments, HexConfig};
use nu_protocol::{Span, Value};
#[test]
fn hex_encode() {
let word = Value::binary([77, 97, 110], Span::test_data());
let expected = Value::test_string("4D616E");
let actual = action(
&word,
&Arguments {
encoding_config: HexConfig {
action_type: ActionType::Encode,
},
cell_paths: None,
},
Span::test_data(),
);
assert_eq!(actual, expected);
}
#[test]
fn hex_decode() {
let word = Value::test_string("4D 61\r\n\n6E");
let expected = Value::binary([77, 97, 110], Span::test_data());
let actual = action(
&word,
&Arguments {
encoding_config: HexConfig {
action_type: ActionType::Decode,
},
cell_paths: None,
},
Span::test_data(),
);
assert_eq!(actual, expected);
}
}

View File

@ -1,6 +0,0 @@
mod decode_hex;
mod encode_hex;
mod hex;
pub(crate) use decode_hex::DecodeHex;
pub(crate) use encode_hex::EncodeHex;

View File

@ -24,7 +24,7 @@ impl Command for FormatPattern {
.category(Category::Strings)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Format columns into a string using a simple pattern."
}

View File

@ -1,3 +1,2 @@
pub(crate) mod encode_decode;
pub(crate) mod format;
pub(crate) mod str_;

View File

@ -30,7 +30,7 @@ impl Command for SubCommand {
.category(Category::Strings)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Convert a string to camelCase."
}

View File

@ -30,7 +30,7 @@ impl Command for SubCommand {
.category(Category::Strings)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Convert a string to kebab-case."
}

View File

@ -30,7 +30,7 @@ impl Command for SubCommand {
.category(Category::Strings)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Convert a string to PascalCase."
}

View File

@ -30,7 +30,7 @@ impl Command for SubCommand {
.category(Category::Strings)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Convert a string to SCREAMING_SNAKE_CASE."
}

View File

@ -30,7 +30,7 @@ impl Command for SubCommand {
.category(Category::Strings)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Convert a string to snake_case."
}

View File

@ -14,11 +14,11 @@ impl Command for Str {
.input_output_types(vec![(Type::Nothing, Type::String)])
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Various commands for working with string data."
}
fn extra_usage(&self) -> &str {
fn extra_description(&self) -> &str {
"You must use one of the following subcommands. Using this command as-is will only produce this help message."
}

View File

@ -30,7 +30,7 @@ impl Command for SubCommand {
.category(Category::Strings)
}
fn usage(&self) -> &str {
fn description(&self) -> &str {
"Convert a string to Title Case."
}

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