<!--
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.
-->
Rel: #14429, #16079
Finishes up a TODO in the assignment type checking.
- For regular assignment operations (only applies to `mut`), type
checking is now done using `type_compatible` (which is what `let` uses)
- This allows some mutable assignments to work which weren't allowed
before
Before:
```nushell
let x: glob = ""
# => ok, no error
mut x: glob = ""; $x = ""
# => Error: nu::parser::operator_incompatible_types
# =>
# => × Types 'glob' and 'string' are not compatible for the '=' operator.
# => ╭─[entry #6:1:19]
# => 1 │ mut x: glob = ""; $x = ""
# => · ─┬ ┬ ─┬
# => · │ │ ╰── string
# => · │ ╰── does not operate between 'glob' and 'string'
# => · ╰── glob
# => ╰────
let x: number = 1
# ok, no error
mut x: number = 1; $x = 2
# => Error: nu::parser::operator_incompatible_types
# =>
# => × Types 'number' and 'int' are not compatible for the '=' operator.
# => ╭─[source:1:20]
# => 1 │ mut x: number = 1; $x = 2
# => · ─┬ ┬ ┬
# => · │ │ ╰── int
# => · │ ╰── does not operate between 'number' and 'int'
# => · ╰── number
# => ╰────
```
After:
```nushell
let x: glob = ""
# ok, no error (same as before)
mut x: glob = ""; $x = ""
# ok, no error
let x: number = 1
# ok, no error (same as before)
mut x: number = 1; $x = 2
# ok, no error
```
- Properly type check compound operations. First checks if the operation
(eg. `+` for `+=`) type checks successfully, and then checks if the
assignment type checks successfully (also using `type_compatible`)
- This fixes some issues where the "long version" of a compound
assignment operator would error, but the compound assignment operator
itself would not
Before:
```nushell
mut x = 1; $x = $x / 2
# => Error: nu::parser::operator_incompatible_types
# =>
# => × Types 'int' and 'float' are not compatible for the '=' operator.
# => ╭─[entry #15:1:12]
# => 1 │ mut x = 1; $x = $x / 2
# => · ─┬ ┬ ───┬──
# => · │ │ ╰── float
# => · │ ╰── does not operate between 'int' and 'float'
# => · ╰── int
# => ╰────
mut x = 1; $x /= 2
# uh oh, no error...
mut x = (date now); $x = $x - 2019-05-10
# => Error: nu::parser::operator_incompatible_types
# =>
# => × Types 'datetime' and 'duration' are not compatible for the '=' operator.
# => ╭─[entry #1:1:21]
# => 1 │ mut x = (date now); $x = $x - 2019-05-10
# => · ─┬ ┬ ───────┬───────
# => · │ │ ╰── duration
# => · │ ╰── does not operate between 'datetime' and 'duration'
# => · ╰── datetime
# => ╰────
mut x = (date now); $x -= 2019-05-10
# uh oh, no error... (the result of this is a duration, not a datetime)
```
After:
```nushell
mut x = 1; $x = $x / 2
# => Error: nu::parser::operator_incompatible_types
# =>
# => × Types 'int' and 'float' are not compatible for the '=' operator.
# => ╭─[entry #5:1:12]
# => 1 │ mut x = 1; $x = $x / 2
# => · ─┬ ┬ ───┬──
# => · │ │ ╰── float
# => · │ ╰── does not operate between 'int' and 'float'
# => · ╰── int
# => ╰────
mut x = (date now); $x -= 2019-05-10
# => Error: nu::parser::operator_incompatible_types
# =>
# => × Types 'datetime' and 'datetime' are not compatible for the '-=' operator.
# => ╭─[entry #11:1:21]
# => 1 │ mut x = (date now); $x -= 2019-05-10
# => · ─┬ ─┬ ─────┬────
# => · │ │ ╰── datetime
# => · │ ╰── does not operate between 'datetime' and 'datetime'
# => · ╰── datetime
# => ╰────
# => help: The result type of this operation is not compatible with the type of the variable.
```
This is technically a breaking change if you relied on the old behavior
(for example, there was a test that broke after this change because it
relied on `/=` improperly type checking)
# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->
* Mutable assignment operations now use the same type checking rules as
normal assignments
* For example, `$x = 123` now uses the same type checking rules as `let
x = 123` or `mut x = 123`
* Compound assignment operations now type check using the same rules as
the operation they use
* Assignment errors will also now highlight the invalid assignment
operator in red
# 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
> ```
-->
Adds some tests for the examples given above
# 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.
-->
N/A
<!--
if this PR closes one or more issues, you can automatically link the PR
with
them by using one of the [*linking
keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword),
e.g.
- this PR should close #xxxx
- fixes #xxxx
you can also mention related issues, PRs or discussions!
-->
# Description
This is so the styling can be set and reset without resetting the color.
NB. I don't have any domain or language knowledge here so am trying to
stick with existing patterns but it might be good to find out why code
like `Style::new().bold().prefix()` was used instead of just the raw SGR
(Select Graphic Rendition) codes (eg. `"\x1b[1m"`)
# 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.
-->
# Description
This PR improves the `metadata set` command by returning a clear error
when both `--datasource-filepath` and `--datasource-ls` flags are used
together. These flags are meant to be mutually exclusive, and previously
this conflicting usage was silently ignored.
# User-Facing Changes
* Users will now see an error message if they use both
`--datasource-filepath` and `--datasource-ls` together in `metadata
set`.
# Tests + Formatting
* [x] Added test at
`crates/nu-command/tests/commands/debug/metadata_set.rs` to verify the
error behavior.
* [x] Ran `cargo fmt --all -- --check`
* [x] Ran `cargo clippy --workspace -- -D warnings -D
clippy::unwrap_used`
* [x] Ran `cargo test --workspace`
# After Submitting
N/A
1.88.0 was released today, clippy now lints (machine-applicable)
against:
- format strings with empty braces that could be inlined
- easy win
- `manual_abs_diff`
- returning of a stored result of the last expression.
- this can be somewhat contentious but touched only a few places
- fixes#16011
# Description
`Display` implementation for `f64` omits the decimal part for round
numbers, and by using it we did the same.
This affected:
- conversions to delimited formats: `csv`, `tsv`
- textual formats: `html`, `md`, `text`
- pretty printed `json` (`--raw` was unaffected)
- how single float values are displayed in the REPL
> [!TIP]
> This PR fixes our existing json pretty printing implementation.
> We can likely switch to using serde_json's impl using its
PrettyFormatter which allows arbitrary indent strings.
# User-Facing Changes
- Round trips through `csv`, `tsv`, and `json` preserve the type of
round floats.
- It's always clear whether a number is an integer or a float in the
REPL
```nushell
4 / 2
# => 2 # before: is this an int or a float?
4 / 2
# => 2.0 # after: clearly a float
```
# Tests + Formatting
Adjusted tests for the new behavior.
- 🟢 toolkit fmt
- 🟢 toolkit clippy
- 🟢 toolkit test
- 🟢 toolkit test stdlib
# After Submitting
N/A
---------
Co-authored-by: Bahex <17417311+Bahex@users.noreply.github.com>
It was brought up in the Discord that `default { open -r foo.txt }`
results in a string instead of streaming output. This changes `default`
such that closures now stream when given simple input.
# Description
If the value isn't expected to be cached, `default` just runs the
closure without caching the value, which allows its output to be
streamed
# User-Facing Changes
# Tests + Formatting
👍
# After Submitting
## ✅ Improve `drop nth` command to support spreadable arguments
### Summary
This PR updates the `drop nth` command to support **spreadable
arguments** in a way consistent with other commands like `which`,
enabling:
```nu
[1 2 3 4 5] | drop nth 0 2 4
```
### What's Changed
* **Previously**: only a single index or a single range was accepted as
the first argument, with rest arguments ignored for ranges.
* **Now**: the command accepts any combination of:
* Integers: to drop individual rows
* Ranges: to drop slices of rows
* Unbounded ranges: like `3..`, to drop from index onward
Example:
```nu
[one two three four five six] | drop nth 0 2 4..5
# drops "one", "three", "five", and "six"
```
### Test
Manual Test:

### Notes
As per feedback:
* We **only collect the list of indices** to drop, not the input stream.
* Unbounded ranges are handled by terminating the stream early.
Let me know if you'd like further changes
---------
Co-authored-by: Kumar Ujjawal <kumar.ujjawal@greenpista.com>
Co-authored-by: Kumar Ujjawal <kumarujjawal@Kumars-MacBook-Air.local>
# Description
Add 'double' table mode, that is similar to `compact_double` but with
left and right border lines. This is similar to how there exist both
`single` and `compact`, but there is no `double` to compliment
`compact_double`. Printing `[ { a: 1, b: 11 }, { a: 2, b:12 } ]` looks
like this:
```
╔═══╦═══╦════╗
║ # ║ a ║ b ║
╠═══╬═══╬════╣
║ 0 ║ 1 ║ 11 ║
║ 1 ║ 2 ║ 12 ║
╚═══╩═══╩════╝
```
The implementation is mostly a one-to-one of #15672 and #15681.
# User-Facing Changes
New value `double` to set as `$env.config.table.mode`.
# Tests + Formatting
Tests are added following the example of adding 'single' mode.
# After Submitting
# Description
Instead of converting nested structures into strings and
pattern-matching the strings, the `find` command will recursively search
the nested structures for matches.
- fixes#15618
# User-Facing Changes
Text in nested structures will now be highlighted as well.
Error values will always passed on instead of testing them against the
search term
There will be slight changes in match behavior, such as characters that
are part of the string representations of data structures no longer
matching all nested data structures.
I did a naive fix; which is probably all right.
But I want to spend some time to refactor a neighboring stuff.
And it's yet not to be released I guess;
I hope to add a few things beforehand.
I've just opened it so you can verify that it must be addressed.
close#15104, #14910, #15256
# Description
Simple `parse` patterns let you quickly put together simple parsers, but
sometimes you aren't actually interested in some of the output (such as
variable whitespace). This PR lets you use `{_}` to discard part of the
input.
Example:
```nushell
"hello world" | parse "{foo} {_}"
# => ╭───┬───────╮
# => │ # │ foo │
# => ├───┼───────┤
# => │ 0 │ hello │
# => ╰───┴───────╯
```
here's a simple parser for the `apropops` using the `_` placeholder to
discard the variable whitespace, without needing to resort to a full
regex pattern:
```nushell
apropos linux | parse "{name} ({section}) {_}- {topic}"
# => ╭───┬───────────────────────────────────────┬─────────┬─────────────────────────────────────────────────────────────────────╮
# => │ # │ name │ section │ topic │
# => ├───┼───────────────────────────────────────┼─────────┼─────────────────────────────────────────────────────────────────────┤
# => │ 0 │ PAM │ 8 │ Pluggable Authentication Modules for Linux │
# => │ 1 │ aarch64-linux-gnu-addr2line │ 1 │ convert addresses or symbol+offset into file names and line numbers │
# => │ 2 │ ... │ ... │ ... │
# => │ 3 │ xcb_selinux_set_window_create_context │ 3 │ (unknown subject) │
# => │ 4 │ xorriso-dd-target │ 1 │ Device evaluator and disk image copier for GNU/Linux │
# => ╰───┴───────────────────────────────────────┴─────────┴─────────────────────────────────────────────────────────────────────╯
```
# User-Facing Changes
* `parse` simple patterns can now discard input using `{_}`
# Tests + Formatting
N/A
# After Submitting
N/A
# Description
This test has failed a number of times specifically on macOS. I'm not
exactly sure what the issue is, it seemed to work fine before. We should
probably actually fix it, but flaky CI is worse than missing this one
test on macOS
cc @cosineblast
## Summary
This PR removes the required positional argument from the `which`
command, allowing it to accept input via the spread (`...`) operator.
This enables expressions like:
```nu
[notepad cmd] | which ...$in
```
Previously, this failed due to a missing required positional argument.
The Nushell runtime already handles empty input gracefully, so the
change aligns with existing behavior.
---
## Motivation
Making `which` compatible with splatted input improves composability and
aligns with user expectations in scriptable environments. It supports
patterns where the input may be constructed dynamically or piped in from
earlier commands.
---
## Changes
* Removed the `required` attribute from the positional argument in the
`which` command signature.
* No additional runtime logic required since empty input is handled
gracefully already.
---
## Examples
### Before
```nu
[notepad cmd] | which ...$in
# ❌ Error: Missing required positional argument
```
### After
```nu
[notepad cmd] | which ...$in
# ✅ Executes correctly
```
---
## Testing
* Ran `cargo test --all` and `cargo test -p nu-command`
* Manually tested using spread input with the `which` command
* Confirmed that empty and non-empty inputs behave correctly
---
## Related Issues
Closes
[[#15801](https://github.com/nushell/nushell/issues/15801)](https://github.com/nushell/nushell/issues/15801)
---------
Co-authored-by: Kumar Ujjawal <kumar.ujjawal@greenpista.com>
# Description
- Use #15770 to
- improve `get --sensitive` deprecation warning
- add deprecation warning for `filter`
- refactor `filter` to use `where` as its implementation
- replace usages of `filter` with `where` in `std`
# User-Facing Changes
- `get --sensitive` will raise a warning only once, during parsing
whereas before it was raised during runtime for each usage.
- using `filter` will raise a deprecation warning, once
# Tests + Formatting
No existing test broke or required tweaking. Additional tests covering
this case was added.
- 🟢 toolkit fmt
- 🟢 toolkit clippy
- 🟢 toolkit test
- 🟢 toolkit test stdlib
# After Submitting
N/A
---------
Co-authored-by: Bahex <17417311+Bahex@users.noreply.github.com>
# Description
Regex search and search with directly provided search terms used to
follow two different code paths. Now all possible search options get
turned into a regex, with optional additional search options, and
handled using a unified code path which mostly follows the logic of the
current term code path.
# User-Facing Changes
Regex search will now behave in the same way as non-regex search:
- split multiline strings into lists of lines, and filter out the lines
that don't match
- highlight matching string sections (unless --no-highlight flag is
used)
- search through the specified record columns if the --columns flag is
used
The behavior of non-regex search should be unaffected by this commit.
# Description
This pull request addresses an issue#15813 where passing a infinite
value in the random float 1.. command that causes a panic in the shell.
The root cause of this problem lies within the rng library, which is
responsible for generating random numbers.
Before

# User-Facing Changes
Users where seeing panic error when passed unbounded end into range.
# Tests + Formatting
added `generate_inf`
# After Submitting

No error should be there after
Edit history
1. Updated `After Submitting` section
---------
Co-authored-by: Ritik Ranjan <e02948@ritik.ranjan@hsc.com>
# Description
Fixes: https://github.com/nushell/nushell/issues/15749
When sourcing a file, the ir block might be empty because it has been
used before, this pr is going to make sure that the ir block is
compiled.
# User-Facing Changes
```
touch aaa.nu
use aaa.nu
source aaa.nu
```
Will no longer raise an error.
# Tests + Formatting
Added 1 test
# After Submitting
NaN
Related:
- #15683
- #14551
- #849
- #12701
- #11527
# Description
Currently various commands have differing behavior regarding cell-paths
```nushell
{a: 1, A: 2} | get a A
# => ╭───┬───╮
# => │ 0 │ 2 │
# => │ 1 │ 2 │
# => ╰───┴───╯
{a: 1, A: 2} | select a A
# => ╭───┬───╮
# => │ a │ 1 │
# => │ A │ 2 │
# => ╰───┴───╯
{A: 1} | update a 2
# => Error: nu:🐚:column_not_found
# =>
# => × Cannot find column 'a'
# => ╭─[entry #62:1:1]
# => 1 │ {A: 1} | update a 2
# => · ───┬── ┬
# => · │ ╰── cannot find column 'a'
# => · ╰── value originates here
# => ╰────
```
Proposal: making cell-path access case-sensitive by default and adding
new syntax for case-insensitive parts, similar to optional (?) parts.
```nushell
{FOO: BAR}.foo
# => Error: nu:🐚:name_not_found
# =>
# => × Name not found
# => ╭─[entry #60:1:21]
# => 1 │ {FOO: BAR}.foo
# => · ─┬─
# => · ╰── did you mean 'FOO'?
# => ╰────
{FOO: BAR}.foo!
# => BAR
```
This would solve the problem of case sensitivity for all commands
without causing an explosion of flags _and_ make it more granular
Assigning to a field using a case-insensitive path is case-preserving.
```nushell
mut val = {FOO: "I'm FOO"}; $val
# => ╭─────┬─────────╮
# => │ FOO │ I'm FOO │
# => ╰─────┴─────────╯
$val.foo! = "I'm still FOO"; $val
# => ╭─────┬───────────────╮
# => │ FOO │ I'm still FOO │
# => ╰─────┴───────────────╯
```
For `update`, case-insensitive is case-preserving.
```nushell
{FOO: 1} | update foo! { $in + 1 }
# => ╭─────┬───╮
# => │ FOO │ 2 │
# => ╰─────┴───╯
```
`insert` can insert values into nested values so accessing into existing
columns is case-insensitive, but creating new columns uses the cell-path
as it is.
So `insert foo! ...` and `insert FOO! ...` would work exactly as they do
without `!`
```nushell
{FOO: {quox: 0}}
# => ╭─────┬──────────────╮
# => │ │ ╭──────┬───╮ │
# => │ FOO │ │ quox │ 0 │ │
# => │ │ ╰──────┴───╯ │
# => ╰─────┴──────────────╯
{FOO: {quox: 0}} | insert foo.bar 1
# => ╭─────┬──────────────╮
# => │ │ ╭──────┬───╮ │
# => │ FOO │ │ quox │ 0 │ │
# => │ │ ╰──────┴───╯ │
# => │ │ ╭─────┬───╮ │
# => │ foo │ │ bar │ 1 │ │
# => │ │ ╰─────┴───╯ │
# => ╰─────┴──────────────╯
{FOO: {quox: 0}} | insert foo!.bar 1
# => ╭─────┬──────────────╮
# => │ │ ╭──────┬───╮ │
# => │ FOO │ │ quox │ 0 │ │
# => │ │ │ bar │ 1 │ │
# => │ │ ╰──────┴───╯ │
# => ╰─────┴──────────────╯
```
`upsert` is tricky, depending on the input, the data might end up with
different column names in rows. We can either forbid case-insensitive
cell-paths for `upsert` or trust the user to keep their data in a
sensible shape.
This would be a breaking change as it would make existing cell-path
accesses case-sensitive, however the case-sensitivity is already
inconsistent and any attempt at making it consistent would be a breaking
change.
> What about `$env`?
1. Initially special case it so it keeps its current behavior.
2. Accessing environment variables with non-matching paths gives a
deprecation warning urging users to either use exact casing or use the
new explicit case-sensitivity syntax
3. Eventuall remove `$env`'s special case, making `$env` accesses
case-sensitive by default as well.
> `$env.ENV_CONVERSIONS`?
In addition to `from_string` and `to_string` add an optional field to
opt into case insensitive/preserving behavior.
# User-Facing Changes
- `get`, `where` and other previously case-insensitive commands are now
case-sensitive by default.
- `get`'s `--sensitive` flag removed, similar to `--ignore-errors` there
is now an `--ignore-case` flag that treats all parts of the cell-path as
case-insensitive.
- Users can explicitly choose the case case-sensitivity of cell-path
accesses or commands.
# Tests + Formatting
Existing tests required minimal modification. ***However, new tests are
not yet added***.
- 🟢 toolkit fmt
- 🟢 toolkit clippy
- 🟢 toolkit test
- 🟢 toolkit test stdlib
# After Submitting
- Update the website to include the new syntax
- Update [tree-sitter-nu](https://github.com/nushell/tree-sitter-nu)
---------
Co-authored-by: Bahex <17417311+Bahex@users.noreply.github.com>
Closes#14469
# Description
- ~~Implement the ``--unit`` conversion in "into int" command~~
- New ``ShellError::InvalidUnit`` unit if users enter wrong units
- Made ``ShellError::CantConvertToDuration`` more generic: became
``CantConvertToUnit``
- Tried to improve the way we parse units and get the supported units.
It's not complete, though, I will continue this refactoring in another
PR. But I already did some small refactorings in the "format duration"
and "format filesize" commands
- Add tests for "format filesize" and "format duration"
# User-Facing Changes
```nu
~> 1MB | format filesize sec
Error: nu:🐚:invalid_unit
× Invalid unit
╭─[entry #7:1:23]
1 │ 1MB | format filesize sec
· ─┬─
· ╰── encountered here
╰────
help: Supported units are: B, kB, MB, GB, TB, PB, EB, KiB, MiB, GiB, TiB, PiB, EiB
```
# Description
This PR adds lazy closure evaluation to the `default` command (closes
#14160).
- For non-closure values and without providing a column name, `default`
acts the same as before
- The user can now provide multiple column names to populate if empty
- If the user provides a column name, the input must be a record or
list, otherwise an error is created.
- The user can now provide a closure as a default value
- This closure is run without any arguments or input
- The closure is never evaluated if the value isn't needed
- Even when column names are supplied, the closure is only run once (and
cached to prevent re-calling it)
For example:
```nushell
> default { 1 + 2 } # => 3
> null | default 3 a # => previously `null`, now errors
> 1 | default { sleep 5sec; 3 } # => `1`, without waiting 5 seconds
> let optional_var = null; $optional_var | default { input 'Enter value: ' } # => Returns user input
> 5 | default { input 'Enter value: ' } # => `5`, without prompting user
> ls | default { sleep 5sec; 'N/A' } name # => No-op since `name` column is never empty
> ls | default { sleep 5sec; 'N/A' } foo bar # => creates columns `foo` and `bar`; only takes 5 seconds since closure result is cached
# Old behavior is the same
> [] | default 'foo' # => []
> [] | default --empty 'foo' # => 'foo'
> default 5 # => 5
```
# User-Facing Changes
- Users can add default values to multiple columns now.
- Users can now use closures as the default value passed to `default`.
- To return a closure, the user must wrap the closure they want to
return inside another closure, which will be run (`default { $my_closure
}`).
# Tests + Formatting
All tests pass.
# After Submitting
---------
Co-authored-by: 132ikl <132@ikl.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!
-->
- fixes#14896
- related to #15163
# Description
<!--
Thank you for improving Nushell. Please, check our [contributing
guide](../CONTRIBUTING.md) and talk to the core team before making major
changes.
Description of your pull request goes here. **Provide examples and/or
screenshots** if your changes affect the user experience.
-->
This PR fixes the presence of ansi color codes in empty tables, when
`$env.config.table.show_empty = true` and `$env.config.use_ansi_coloring
= false`
# User-Facing Changes
Empty tables respect `$env.config.use_ansi_coloring`
# 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 for this case.
# After Submitting
Fixes#15716
# Description
Returns None early if the input iterator is depleted.
# User-Facing Changes
Should be none
# Tests + Formatting
+1
# After Submitting
# Description
Fixes#9942
This adds a new `--minified` flag to `to nuon` which removes all
possible white space. I added an example test to demonstrate the
functionality.
# User-Facing Changes
New flag becomes available to the user.
ref #15653
Thanks for reproducible.
So @Bahex indeed padding was not properly handled.
I am not sure whether there's more issues related to your examples
@fdncred but I seems like don't get them.
Also added a test for future regressions (well to be honest didn't
tested that it's failing on main but at least at may catch something)
PS: Also got some panic related to #15138 (which PR fixed) :(
There's nothing on my end stopping me releasing a WASM issue fix; I just
sort of always worrying with releasing a `patch` (`0.0.x`)......and
there's 1 quite big thing I wanna do before a minor release.......
<!--
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.
-->
- A few days back I've got this idea regarding recalculus of width.
Now it calculates step by step.
So 1 loop over all data was removed.
All though there's full recalculation in case of `header_on_border`
😞 (can be fixed..... but I decided to be short)
In perfect world it also shall be refactored ......
- Also have done small refactoring to switch build table from
`Vec<Vec<_>>>` to table itself. To hide internals (kind of still there's
things which I don't like).
It touched the `--expand` algorithm lightly you can see the tests
changes.
- And when doing that noticed one more opportunity, to remove HashMap
usage and directly use `tabled::ColoredConfig`. Which reduces copy
operations and allocations.
- And fixed a small issue where trailing column being using deleted
column styles.

To conclude optimizations;
I did small testing and it's not slower.
But I didn't get the faster results either.
But I believe it must be faster well in all cases, I think maybe bigger
tables must be tested.
Maybe someone could have a few runs to compare performance.
cc: @fdncred
# Description
This PR implements an experimental inter-job communication model,
through direct message passing, aka "mail"ing or "dm"ing:
- `job send <id>`: Sends a message the job with the given id, the root
job has id 0. Messages are stored in the recipient's "mailbox"
- `job recv`: Returns a stored message, blocks if the mailbox is empty
- `job flush`: Clear all messages from mailbox
Additionally, messages can be sent with a numeric tag, which can then be
filtered with `mail recv --tag`.
This is useful for spawning jobs and receiving messages specifically
from those jobs.
This PR is mostly a proof of concept for how inter-job communication
could look like, so people can provide feedback and suggestions
Closes #15199
May close#15220 since now jobs can access their own id.
# User-Facing Changes
Adds, `job id`, `job send`, `job recv` and `job flush` commands.
# Tests + Formatting
[X] TODO: Implement tests
[X] Consider rewriting some of the job-related tests to use this, to
make them a bit less fragile.
# After Submitting
# Description
Try to fixes https://github.com/nushell/nushell/issues/15326 in another
way.
The main point of this change is to avoid duplicate `write` and `close`
a redirected file. So during compile, if compiler know current element
is a sub-expression(defined by private `is_subexpression` function), it
will no longer invoke `finish_redirection`.
In this way, we can avoid duplicate `finish_redirection`.
# User-Facing Changes
`(^echo aa) o> /tmp/aaa` will no longer raise an error.
Here is the IR after the pr:
```
# 3 registers, 12 instructions, 11 bytes of data
# 1 file used for redirection
0: load-literal %1, string("aaa")
1: open-file file(0), %1, append = false
2: load-literal %1, glob-pattern("echo", no_expand = false)
3: load-literal %2, glob-pattern("true", no_expand = false)
4: push-positional %1
5: push-positional %2
6: redirect-out file(0)
7: redirect-err caller
8: call decl 135 "run-external", %0
9: write-file file(0), %0
10: close-file file(0)
11: return %0
```
# Tests + Formatting
Added 3 tests.
# After Submitting
Maybe need to update doc
https://github.com/nushell/nushell.github.io/pull/1876
---------
Co-authored-by: Stefan Holderbach <sholderbach@users.noreply.github.com>
Fixes#15559
# Description
The glob command wasn't working correctly with symlinks in the /sys
filesystem. This commit adds a new flag that allows users to explicitly
control whether symlinks should be followed, with special handling for
the /sys directory.
The issue was that the glob command didn't follow symbolic links when
traversing the /sys filesystem, resulting in an empty list even though
paths should be found. This implementation adds a new
`--follow-symlinks` flag that explicitly enables following symlinks. By
default, it now follows symlinks in most paths but has special handling
for /sys paths where the flag is required.
Example:
`
# Before: This would return an empty list on Linux systems
glob /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
# Now: This works as expected with the new flag
glob /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
--follow-symlinks
`
# User-Facing Changes
1. Added the --follow-symlinks (-l) flag to the glob command that allows
users to explicitly control whether symbolic links should be followed
2. Added a new example to the glob command help text demonstrating the
use of this flag
# Tests + Formatting
1. Added a test for the new --follow-symlinks flag
Fixes#13546
# Description
Previously, outer joins would remove rows without join columns, since
the "did not match" logic only executed when the row had the join
column.
To solve this, missing join columns are now treated the same as "exists
but did not match" cases. The logic now executes both when the join
column doesn't exist and when it exists but doesn't match, ensuring rows
without join columns are preserved. If the join column is not defined at
all, the previous behavior remains unchanged.
Example:
```
For the tables:
let left_side = [{a: a1 ref: 1} {a: a2 ref: 2} {a: a3}]
let right_side = [[b ref]; [b1 1] [b2 2] [b3 3]]
Running "$left_side | join -l $right_side ref" now outputs:
╭───┬────┬─────┬────╮
│ # │ a │ ref │ b │
├───┼────┼─────┼────┤
│ 0 │ a1 │ 1 │ b1 │
│ 1 │ a2 │ 2 │ b2 │
│ 2 │ a3 │ │ │
╰───┴────┴─────┴────╯
```
# User-Facing Changes
The ```join``` command will behave more similarly to SQL-style joins. In
this case, rows that lack the join column are preserved.
# Tests + Formatting
Added 2 test cases.
fmt + clippy OK.
# After Submitting
I don't believe anything is necessary.
# Description
This PR implements job tagging through the usage of a new `job tag`
command and a `--tag` for `job spawn`
Closes#15354
# User-Facing Changes
- New `job tag` command
- Job list may now have an additional `tag` column for the tag of jobs
(rows representing jobs without tags do not have this column filled)
- New `--tag` flag for `job spawn`
# Tests + Formatting
Integration tests are provided to test the newly implemented features
# After Submitting
Possibly document job tagging in the jobs documentation
Closes#15543
# Description
1. Simplify code in ``datetime.rs`` based on a suggestion in my last PR
on "datetime from record"
1. Make ``into duration`` work with durations inside a record, provided
as a cell path
1. Make ``into duration`` work with durations as record
# User-Facing Changes
```nushell
# Happy paths
~> {d: '1hr'} | into duration d
╭───┬─────╮
│ d │ 1hr │
╰───┴─────╯
~> {week: 10, day: 2, sign: '+'} | into duration
10wk 2day
# Error paths and invalid usage
~> {week: 10, day: 2, sign: 'x'} | into duration
Error: nu:🐚:incorrect_value
× Incorrect value.
╭─[entry #4:1:26]
1 │ {week: 10, day: 2, sign: 'x'} | into duration
· ─┬─ ──────┬──────
· │ ╰── encountered here
· ╰── Invalid sign. Allowed signs are +, -
╰────
~> {week: 10, day: -2, sign: '+'} | into duration
Error: nu:🐚:incorrect_value
× Incorrect value.
╭─[entry #5:1:17]
1 │ {week: 10, day: -2, sign: '+'} | into duration
· ─┬ ──────┬──────
· │ ╰── encountered here
· ╰── number should be positive
╰────
~> {week: 10, day: '2', sign: '+'} | into duration
Error: nu:🐚:only_supports_this_input_type
× Input type not supported.
╭─[entry #6:1:17]
1 │ {week: 10, day: '2', sign: '+'} | into duration
· ─┬─ ──────┬──────
· │ ╰── only int input data is supported
· ╰── input type: string
╰────
~> {week: 10, unknown: 1} | into duration
Error: nu:🐚:unsupported_input
× Unsupported input
╭─[entry #7:1:1]
1 │ {week: 10, unknown: 1} | into duration
· ───────────┬────────── ──────┬──────
· │ ╰── Column 'unknown' is not valid for a structured duration. Allowed columns are: week, day, hour, minute, second, millisecond, microsecond, nanosecond, sign
· ╰── value originates from here
╰────
~> {week: 10, day: 2, sign: '+'} | into duration --unit sec
Error: nu:🐚:incompatible_parameters
× Incompatible parameters.
╭─[entry #2:1:33]
1 │ {week: 10, day: 2, sign: '+'} | into duration --unit sec
· ──────┬────── ─────┬────
· │ ╰── the units should be included in the record
· ╰── got a record as input
╰────
```
# Tests + Formatting
- Add examples and integration tests for ``into duration``
- Add one test for ``into duration``
# After Submitting
If this is merged in time, I'll update my PR on the "datetime handling
highlights" for the release notes.
Closes#12858
# Description
As explained in the ticket, easy to reproduce. Example: 1.07 minute is
1.07*60=64.2 secondes
```nushell
# before - wrong
> 1.07min
1min 4sec
# now - right
> 1.07min
1min 4sec 200ms
```
# User-Facing Changes
Bug is fixed when using ``into duration``.
# Tests + Formatting
Added a test for ``into duration``
Fixed ``parse_long_duration`` test: we gained precision 😄
# After Submitting
Release notes? Or blog is enough? Let me know
Closes #13972
# Description
First commit: a hotfix concerning my last PR #15544! I had a
``unwrap_or_default`` that resulted in all years before ~1800 being
considered as "now", because the ``num_nanoseconds()`` overflowed.
Cc @fdncred
Second: about #13972
Negative years are not allowed with RFC 2822 formatting, so I fallback
RTC 3339 in such cases.
If you want you might Rebase and Merge, and not squash.
# User-Facing Changes
On master 🔴 :
```nu
~> {year: 1900} | into datetime
Mon, 1 Jan 1900 00:00:00 +0200 (125 years ago)
# OK
~> {year: 1000} | into datetime
Wed, 1 Jan 1000 00:00:00 +0200 (now)
# NOT OK: now?
~> {year: -1000} | into datetime
-1000-01-01T00:00:00+02:00 (now)
# NOT OK: now?
~> {year: -1000} | into datetime | format date
Error: × Main thread panicked.
├─▶ at C:\Users\RIL1RT\.cargo\registry\src\index.crates.io-6f17d22bba15001f\chrono-0.4.39\src\datetime\mod.rs:626:14
╰─▶ writing rfc2822 datetime to string should never fail: Error
help: set the `RUST_BACKTRACE=1` environment variable to display a backtrace.
# NOT OK: panics
```
On this branch 🟢 :
```nu
~> {year: 1900} | into datetime
Mon, 1 Jan 1900 00:00:00 +0200 (in 125 years)
~> {year: 1000} | into datetime
Wed, 1 Jan 1000 00:00:00 +0200 (1025 years ago)
~> {year: -1000} | into datetime
-1000-01-01T00:00:00+02:00 (3025 years ago)
~> {year: -1000} | into datetime | format date
-1000-01-01T00:00:00+02:00
~> '3000 years ago' | date from-human | format date
-0975-04-11T18:18:24.301641100+02:00
```
# Tests + Formatting
# After Submitting
Nothing required IMO
This addresses color issue; Yeees just got forgotten it :(
As far as I understand an acceptance test can't be created because ansi
got stripped in `nu!`. (for future regressions)
But wrapping I need to take a deeper look.
Maybe in an hour.
cc: @fdncred
Issue #12289, can be closed when this is merged
# Description
Currently, the ``into datetime`` command's signature indicates that it
supports input as record, but it was actually not supported.
This PR implements this feature.
# User-Facing Changes
``into datetime``'s signature changed (see comments)
**Happy paths**
Note: I'm in +02:00 timezone.
```nushell
> date now | into record | into datetime
Fri, 4 Apr 2025 18:32:34 +0200 (now)
> {year: 2025, month: 12, day: 6, second: 59} | into datetime | into record
╭─────────────┬────────╮
│ year │ 2025 │
│ month │ 12 │
│ day │ 6 │
│ hour │ 0 │
│ minute │ 0 │
│ second │ 59 │
│ millisecond │ 0 │
│ microsecond │ 0 │
│ nanosecond │ 0 │
│ timezone │ +02:00 │
╰─────────────┴────────╯
> {day: 6, second: 59, timezone: '-06:00'} | into datetime | into record
╭─────────────┬────────╮
│ year │ 2025 │
│ month │ 4 │
│ day │ 6 │
│ hour │ 0 │
│ minute │ 0 │
│ second │ 59 │
│ millisecond │ 0 │
│ microsecond │ 0 │
│ nanosecond │ 0 │
│ timezone │ -06:00 │
╰─────────────┴────────╯
```
**Edge cases**
```nushell
{} | into datetime
Fri, 4 Apr 2025 18:35:19 +0200 (now)
```
**Error paths**
- A key has a wrong type
```nushell
> {month: 12, year: '2023'} | into datetime
Error: nu:🐚:only_supports_this_input_type
× Input type not supported.
╭─[entry #8:1:19]
1 │ {month: 12, year: '2023'} | into datetime
· ───┬── ──────┬──────
· │ ╰── only int input data is supported
· ╰── input type: string
╰────
```
```nushell
> {month: 12, year: 2023, timezone: 100} | into datetime
Error: nu:🐚:only_supports_this_input_type
× Input type not supported.
╭─[entry #10:1:35]
1 │ {month: 12, year: 2023, timezone: 100} | into datetime
· ─┬─ ──────┬──────
· │ ╰── only string input data is supported
· ╰── input type: int
╰────
```
- Key has the right type but value invalid (e.g. month=13, or day=0)
```nushell
> {month: 13, year: 2023} | into datetime
Error: nu:🐚:incorrect_value
× Incorrect value.
╭─[entry #9:1:1]
1 │ {month: 13, year: 2023} | into datetime
· ───────────┬─────────── ──────┬──────
· │ ╰── one of more values are incorrect and do not represent valid date
· ╰── encountered here
╰────
```
```nushell
> {hour: 1, minute: 1, second: 70} | into datetime
Error: nu:🐚:incorrect_value
× Incorrect value.
╭─[entry #3:1:1]
1 │ {hour: 1, minute: 1, second: 70} | into datetime
· ────────────────┬─────────────── ──────┬──────
· │ ╰── one of more values are incorrect and do not represent valid time
· ╰── encountered here
╰────
```
- Timezone has right type but is invalid
```nushell
> {month: 12, year: 2023, timezone: "+100:00"} | into datetime
Error: nu:🐚:incorrect_value
× Incorrect value.
╭─[entry #11:1:35]
1 │ {month: 12, year: 2023, timezone: "+100:00"} | into datetime
· ────┬──── ──────┬──────
· │ ╰── encountered here
· ╰── invalid timezone
╰────
```
- Record contains an invalid key
```nushell
> {month: 12, year: 2023, unknown: 1} | into datetime
Error: nu:🐚:unsupported_input
× Unsupported input
╭─[entry #12:1:1]
1 │ {month: 12, year: 2023, unknown: 1} | into datetime
· ─────────────────┬───────────────── ──────┬──────
· │ ╰── Column 'unknown' is not valid for a structured datetime. Allowed
columns are: year, month, day, hour, minute, second, millisecond,
microsecond, nanosecond, timezone
· ╰── value originates from here
╰────
```
- If several issues are present, the user can get the error msg for only
one, though
```nushell
> {month: 20, year: '2023'} | into datetime
Error: nu:🐚:only_supports_this_input_type
× Input type not supported.
╭─[entry #7:1:19]
1 │ {month: 20, year: '2023'} | into datetime
· ───┬── ──────┬──────
· │ ╰── only int input data is supported
· ╰── input type: string
╰
```
# Tests + Formatting
Tests added
Fmt + clippy OK
# After Submitting
Maybe indicate that in the release notes
I added an example in the command, so the documentation will be
automatically updated.
# Description
As description, I think it's worth to move forward to update rand and
rand_chacha to 0.9.
# User-Facing Changes
Hopefully none
# Tests + Formatting
NaN
# After Submitting
NaN
Closes#15395
# User-Facing Changes
Certain errors no longer leave the argument stack in an unexpected
state:
```diff
let x: any = 1; try { $x | get path } catch { print caught }
-$.path # extra `print` argument from the failed `get` call
caught
```
# Description
If `eval_call` fails in `check_input_types` or `gather_arguments`, the
cleanup code is still executed.