mirror of
https://github.com/nushell/nushell.git
synced 2026-10-28 08:54:52 +08:00
main
12071
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
e56aca9da6 |
fix(table): stop table --expand hanging when a nested table is wider than its column (#19212)
## Description
`open Cargo.toml | [ $in ] | table -e -w 183` on main grows memory until
the OOM killer ends nu. A debug build panics instead.
### Before, debug build of main:
```nushell
> open Cargo.toml | [ $in ] | table -e -w 183 | ignore
Error: × Main thread panicked.
├─▶ at .../papergrid-0.18.0/src/grid/peekable.rs:985:20
╰─▶ attempt to subtract with overflow
```
Before, release build of main (0.116.2 at
|
||
|
|
6f7c91f790 |
Use whoami's own uucore locale in the whoami command (#19144)
## Description
`whoami` sets up uutils' error translations with
`localized_help_template("touch")`, so it loads `touch`'s translations
instead of `whoami`'s. Any `uu_whoami` error message ID would then be
looked up in the wrong translations and could show up as a raw ID. This
PR passes `"whoami"`, like the other uutils-backed commands (`mktemp`,
`mv`, `cp`, `mkdir`, `touch`, `uname`) already do for their own utils.
This is the nushell-side fix I mentioned in #19004. The main cause of
that issue (uucore keeping whichever util's translations loaded first)
is upstream and tracked in uutils/coreutils#15040.
## User-facing changes (Release notes)
- Fixed `whoami` loading translations for the wrong command, which could
make its error messages show up untranslated.
## Additional notes
Related #19004
|
||
|
|
af37214641 |
detect duration type (#19204)
## Description Derive a duration regex from `DURATION_UNIT_GROUPS` that, when matched, uses the string branch of `into duration` ## User-facing changes (Release notes) `detect type` understands how to parse common duration formats. ``` "1hr" | detect type | describe # duration "11:11:11" | detect type | describe # duration ``` Closes #19203 Depends on e6d2b60ac38c266b03f57236128d286ecdd86772 |
||
|
|
246cd631a3 |
group-by --to-table keep original types (#18853)
## Description
`group-by` always grouped by `Value::to_expanded_string`. That is
required for the default record output, because record keys are strings.
`--to-table` has no such constraint, but it used the same string keys
anyway.
That caused three user-visible bugs:
1. **Type is lost.** Group columns become `string` even when the source
column is `filesize`, `int`, `datetime`, `list`, etc.
```nu
ls | group-by size --to-table | describe
# table<size: string, items: table<... size: filesize ...>>
```
2. **Distinct values collapse** when they share a display string.
Default filesize formatting uses one decimal place, so `1MB` and
`1.001MB` both render as `1.0 MB` / `1,0 MB` and land in one group, even
though they compare as different.
```nu
[[size]; [1MB] [1.001MB]]
| tee { if $in.0 == $in.1 { print same } else { print different } }
| group-by size --to-table
# different
# one group, both rows under the same string key
```
3. **Round-trip is locale-broken.** The key is a localized display
string, so `into filesize` fails unless the user first does `str replace
, .`.
```nu
[[size]; [1MB] [1.001MB]] | group-by size --to-table
# Error: can't convert string to filesize
```
## User-facing changes (Release notes)
### `group-by --to-table` keeps original key types
`group-by --to-table` no longer converts group keys to display strings.
The group columns keep the original type, and rows are grouped by typed
value identity (same type and payload), not by how the value would
print.
```nu
[{n: 1} {n: 2} {n: 1}] | group-by n --to-table
# n is int, not string
```
```nu
[[k v]; [a [1]] [b [1]]] | group-by v --to-table
# one group, v is list<int> [1]
```
```nu
[[size]; [1MB] [1.001MB]] | group-by size --to-table | describe
# table<size: filesize, items: table<size: filesize>>
```
Distinct filesizes that used to share a formatted string (`1MB` and
`1.001MB` both display as `1.0 MB`) are now separate groups. The group
key can be used as a filesize again without `str replace` / `into
filesize` workarounds:
```nu
[[size]; [1MB] [1.001MB]] | group-by size --to-table
```
Default `group-by` (record output) is unchanged: keys are still display
strings, `"true"` and `true` still share a group, and filesize/datetime
still follow config. Use `--to-table` when you need the original type.
This is a breaking change for scripts that assumed `--to-table` keys
were strings (`str replace`, `into filesize` after stringify, string
compares). `"true"` and `true` are now separate `--to-table` groups.
## Additional notes
closes https://github.com/nushell/nushell/issues/12226
|
||
|
|
6bb2c173f0 |
fix(into-duration): into duration overflow (#19075)
Use core `Unit` over arithmetic calculations to properly handle duration overflow cases. This PR depends on #19073 This PR closes https://github.com/nushell/nushell/issues/19074 ## User-facing changes - Reject overflow durations in `into duration` - Reject empty duration strings in `into duration` |
||
|
|
251b392769 |
fix(math variance): use a numerically stable two-pass formula for numbers (#19108)
## Description
`math variance` (and `math stddev`, which reuses it) computed the sum of
squared deviations with the single-pass identity `SS = sum(x²) −
(sum(x))²/n`. When the values are large but close together, the two
terms nearly cancel and `f64` loses the low-order digits, so the result
is wrong (0.0) or even **negative**, and `math stddev` returns **NaN**:
```nushell
[506250000.0 506250001.0] | math variance # -32.0 (should be 0.25)
[506250000.0 506250001.0] | math stddev # NaN
[1000000000 1000000001 1000000002] | math variance # 0.0 (should be 0.667)
```
The duration/filesize path in the **same file** already used a
numerically stable two-pass form in `f64`. This change routes every
numeric input through `variance_unit_f64`, which now measures deviations
from a **shifted origin**: residuals `r = x - min`, their mean, then
`Sum(r - mean_r)^2 / denom`. Subtracting the smallest value is exact for
every input, so a constant sequence still comes out exactly 0, and
summing residuals cannot overflow where summing x does. The result type
is unchanged (a plain float, as before - integer inputs already produced
floats via the division).
## User-facing changes (Release notes)
- Fixed `math variance` and `math stddev` returning incorrect (zero or
negative) values, or `NaN`, for large values that are close together, by
using a numerically stable two-pass formula.
- `math variance` and `math stddev` no longer fail with
`OperatorOverflow` on integers whose square exceeds `i64` (roughly above
3×10⁹, depending on how many values are summed); they are computed as
`f64`. Integers above 2⁵³ are exact in `i64` but not in `f64`, so such
inputs now return an approximate result instead of an error — the same
precision trade-off `math avg` already makes.
## Additional notes
- The stable two-pass form was already present in the file for the
duration/filesize units; this routes the `Number` path through it too,
shifts the origin to the smallest value before averaging so the mean
cannot overflow, and removes the now-unused single-pass `sum_of_squares`
helper.
- Added a regression example for large, close values, plus nine
integration tests in `crates/nu-command/tests/commands/math/variance.rs`
and one in `stddev.rs`: the float case (which previously returned
`-32.0`, a negative variance), the integer case (previously `0.0`), the
`--sample` denominator, that integer input still yields `float`, a
`describe` check on `math stddev`, both sides of the integer boundary -
`[4000000000 4000000001]`, which used to fail with `OperatorOverflow`,
and `[9007199254740993 9007199254740994]`, which as `f64` lands on 2^53
and 2^53 + 2 and therefore has an exact variance of `1.0` - and three
that pin the shifted origin itself: `1..64 | each { 1e150 }` -> 0,
`[1e308 1e308]` -> 0, `[4503599627370496 4503599627370497]` -> 0.25.
- `Number` results now carry the input span instead of the call head,
matching the duration/filesize path already in this file.
- Checked locally against the pinned toolchain: `cargo fmt --all
--check`, `cargo clippy --workspace --all-targets --exclude nu-explore
--exclude nu_plugin_* -- -D warnings`, `cargo test -p nu-command --lib`
(822 cases), `cargo test -p nu-command --test tests --
commands::math::variance commands::math::stddev` (21 cases) and `typos`
all pass.
- This change was drafted with AI assistance (Claude); I verified the
reproduction and the fix against a local build.
|
||
|
|
949b1215da | chore: bump reedline to d704744 (#19202) | ||
|
|
73f0a8983a |
fix(math log): reject invalid bases and a NaN input value (#19127)
## Description `math log` validates the base against `<= 0` but not against `1` (or `NaN`), so: ``` > 2 | math log 1 Inf > 1 | math log 1 NaN ``` while other invalid bases already error: ``` > 2 | math log 0 Error: nu::shell::unsupported_input × Base has to be greater 0 ``` A logarithm is only defined for a base in `(0, 1) ∪ (1, Inf)`. This extends the base validation in `crates/nu-command/src/math/log.rs` to also reject `1`, `inf` and `NaN` — `base <= 0` already covered `-inf` and every other non-positive value — and updates the error message accordingly. `!is_finite()` covers `NaN` and both infinities in one test, and mirrors how #16934 handled non-finite values in `math round`. In the same command the *input* was tested with `if val <= 0.0`, which is false for `NaN`, so `NaN | math log 2` silently returned `NaN`. Testing positivity instead (`if val > 0.0 { … } else { error }`, the form `math ln` already uses) routes it to the existing "undefined for values outside the open interval (0, Inf)" error. ## User-facing changes (Release notes) - `math log` now rejects the invalid bases `1`, `inf` and `NaN` with an error, instead of silently returning `Inf`, `0.0` or `NaN`. - `math log` now errors on a `NaN` input value instead of silently returning `NaN`. ## Additional notes - Regression tests in `crates/nu-command/tests/commands/math/log.rs`, grouped with `rstest`: rejected bases `1` / `1.0` / `0` / `-2` / `NaN` / `inf` / `-inf` (the last two guard `base <= 0`, which already worked, against future edits); accepted bases `2` / `10` / `4` / `0.5` — the `(0, 1)` half of the domain had no coverage at all, and these use bases whose results are exact, unlike `ln(e)`, which sits within 0.021 ulp of a rounding boundary; and `NaN | math log 2` now errors. - Checked locally against the pinned toolchain: `cargo fmt --all --check`, `cargo clippy -p nu-command --all-targets --profile ci -- -D warnings -D clippy::unwrap_used -D clippy::unchecked_time_subtraction`, `cargo test -p nu-command --lib -- math::log` (includes `test_examples`, so the doc examples are executed), `cargo test -p nu-command --test tests -- math::log` (15 cases) and `typos` all pass. --------- Co-authored-by: Master-Norna <263870076+Master-Norna@users.noreply.github.com> |
||
|
|
65a22bfa45 |
fix(bytes remove): keep input unchanged when --end pattern is not found (#19107)
## Description `bytes remove --end` (without `--all`) silently drops leading bytes whenever the pattern is **not** present in the input. The backward-scan branch walks right-to-left and only stops early when the pattern matches. When it does **not** match, the loop runs to the front and `left` ends at `-1`. The follow-up guard `if left > 0` then skips re-appending the leading bytes the scan had already stepped over, so `pattern.len() - 1` leading bytes are lost — or the **entire** input, when the pattern is longer than the input: ```nushell 0x[10 11 12 13] | bytes remove --end 0x[AA BB] # 0x[11 12 13] (0x10 lost) 0x[10 11] | bytes remove --end 0x[AA BB CC] # 0x[] (whole input gone) ``` This contradicts the command's own documented example *"Remove find binary from end not found"*, which promises the input is returned unchanged. That example uses a **1-byte** pattern, where `pattern.len() - 1 == 0`, so no leading byte is lost and the bug was invisible to the example suite. The fix replaces the hand-rolled `isize` backward walk with the same backward search `bytes index-of --end` already uses — `input.windows(pattern_len).rposition(|w| w == pattern)` — and splices out the match. Not found now simply returns the input, and the branch loses the casts, the push-then-reverse and the two full copies the not-found path used to make. `bytes remove` rejects an empty pattern in `run` (as it has since before this bug), so `windows` cannot panic here; a comment records that dependency. One multi-byte regression example is added; the cases that do not need to sit in the help text — match at offset 0, pattern equal to the input, an overlapping pattern, pattern longer than the input — are covered by six unit tests in `remove.rs` instead. ## User-facing changes (Release notes) - Fixed an issue where `bytes remove --end` silently dropped leading bytes (or the whole input) when the pattern was not present **in the input**. `--end` removes the last occurrence anywhere in the input, not only a suffix. ## Additional notes - Related to #11426, which reported a **panic** in this same branch (fixed in v0.89.0 by switching to `isize`). That fix removed the panic but left the silent data loss in place. - Only the `--end` without `--all` path is affected. `--all` ignores `--end` and uses the forward scan, so for **overlapping** patterns `--end --all` removes a different occurrence than `--end` alone: `0x[01 02 01 02 01] | bytes remove --end --all 0x[01 02 01]` gives `0x[02 01]` while `--end` gives `0x[01 02]`, and `index-of --end --all` reports `[2]`. That is pre-existing and left for a follow-up. - Pre-existing and unchanged here: a no-op `bytes remove` still clears `content_type` on a stream (introduced in #16500), so `open foo.png | bytes remove --end 0x[AA BB]` keeps its bytes but loses the `image/png` metadata. Worth a separate discussion. - Checked locally against the pinned toolchain: `cargo fmt --all --check`, `cargo clippy -p nu-command --all-targets --profile ci -- -D warnings -D clippy::unwrap_used -D clippy::unchecked_time_subtraction`, `cargo test -p nu-command --lib -- bytes::remove` (7 cases: the pre-existing example test plus the six new unit tests), `cargo test -p nu-command --test tests -- commands::bytes` (21 cases) and `typos` all pass. The rewrite was also compared with the previous implementation on every input of length 0–6 over a three-symbol alphabet against every pattern of length 1–4 (131,160 pairs, byte-identical) and on 4,732 command-level cases through built binaries; `0x[AA] | bytes remove --end 0x[]` errors rather than panicking, which is what keeps `windows(0)` out of reach. - This change was drafted with AI assistance (Claude); I verified the reproduction and the fix against a local build. |
||
|
|
8696b5246f |
Escape NUL as \\0 in nuon output instead of writing a raw byte (#19161)
## Description
`to nuon` writes a NUL as a raw byte, and does not quote the string
around it, so it emits a document that the nuon reader is specified to
reject.
```
"a\u{0}b" | to nuon # => "a<NUL>b" — raw 0 byte inside the quotes
["a\u{0}b"] | to nuon # => [a<NUL>b] — raw 0 byte, and not quoted at all
```
Two things are wrong there. The byte is written raw, and `needs_quoting`
does not treat NUL as quote-forcing, so inside a container the string
comes out as a bare word with a NUL in the middle of it.
The spec (`crates/nuon/spec/nuon_formal_specification.md`) says a raw
NUL "should be rejected" by the reader and that an explicit `\u{0}` or
`\0` "is a stated intent and is accepted", and its entry for this case
reads *"escape NUL as `\0`, and add it to the set that forces quoting"*.
So today the writer and the reader are wrong together in a way that
cancels: an implementation that follows the spec's reader rule and the
spec's writer rule at the same time cannot round-trip. I have ticked
that entry as the file's header asks.
`escape_quote_string` now escapes NUL as `\0` and `needs_quoting` forces
quoting for it, and both of the spec's normative quote-forcing sets list
NUL. The nuon reader already accepted the escape — `parse_literals.rs`
maps `\0` to `b'\0'` — so the round trip works:
```
"a\u{0}b" | to nuon | from nuon # => string "a\0b"
["a\u{0}b"] | to nuon | from nuon | to nuon # => ["a\0b"]
```
`escape_quote_string` is also how `PathMember` serializes, and the
cell-path reader in `nu-protocol` had no `\0` arm, so a NUL in a path
member parsed as the two ordinary characters `\` and `0`. That reader is
taught the escape too, matching the main parser's table, with a
round-trip test.
The `--raw-strings` path needed a second pass, and the shared-helper
blast radius, the red/green evidence and the verification run are below.
## User-facing changes (Release notes)
Fixed `to nuon` writing a raw NUL byte into its output; a NUL is now
escaped as `\0` and forces quoting, so the output round-trips.
## Additional notes
This is bug 10 in `crates/nuon/spec/bugs_to_fix.md`. Its entry is about
the writer, so it stays ticked; the reader half, which would reject
documents nushell accepts today, is now tracked separately as bug 11.
<details><summary>Details</summary>
The `--raw-strings` path needed a second pass. `quote_string`
(`crates/nuon/src/to.rs:472-477`) tries `as_raw_string` before
`escape_quote_string`, and `as_raw_string` opted any value holding a
quote or a backslash into the raw form without ever looking for a NUL. A
raw string reproduces its content byte for byte, so it cannot represent
`\0` at all, and `a\0"b` came back out as `r#'a\0\"b'#` with the NUL
still raw inside it. The first version of this PR fixed the quoted form
and left that one intact. `as_raw_string` now refuses a NUL-bearing
value, which hands it to `escape_quote_string`.
These two functions are shared helpers, not nuon-private ones, so the
change reaches past `to nuon`. Callers outside `crates/nuon`, verified
in the tree:
`escape_quote_string` (9 sites): `nu-parser/src/deparse.rs:38,49` (an
AST deparsed back to source), `nu-cli/src/util.rs:67,69` (the generated
env file), `nu-cli/src/completions/exportable_completions.rs:16`,
`nu-cli/src/completions/command_completions.rs:171`,
`nu-cli/src/commands/commandline/complete.rs:147`,
`nu-protocol/src/ast/cell_path.rs:206`.
`needs_quoting` (3 sites):
`nu-cli/src/completions/exportable_completions.rs:15`,
`nu-cli/src/completions/command_completions.rs:170`,
`nu-protocol/src/ast/cell_path.rs:205`.
In every one of them the change is the safe direction: a value holding a
NUL now comes out as `\0` instead of a raw 0 byte. For the deparser and
the env-file writer a raw NUL in generated text is not usable anyway.
The only shape that behaves differently is a value containing a NUL, and
that value previously produced a raw NUL in all of them. The one place
the reader had to learn the escape as well is the cell path, covered
above.
Verified on this branch at `88206d7e7`:
```
cargo test -p nu-utils --lib 28 passed
cargo test -p nuon --lib 58 passed, 1 ignored
cargo test -p nu-protocol --test tests 170 passed
cargo fmt --check clean
cargo clippy -p nu-utils -p nuon -p nu-protocol --all-targets clean
```
I did not run the full workspace suite, and I did not rebuild the `nu`
binary in this pass, so the `to nuon` examples above come from the crate
tests rather than a fresh binary run.
Red/green, reverting only the file under test to its pre-fix state:
```
cargo test -p nuon --lib raw_strings
before raw_strings_fall_through_to_escaping_when_the_value_has_a_nul FAILED
--raw-strings wrote a raw NUL for "a\0\"b": "r#'a\0\"b'#"
after passes
cargo test -p nu-protocol --test tests a_nul_in_a_member
before 3 of 4 cases FAILED
left: "$.\"a\\\\0b\"" right: "$.\"a\\0b\"" # the backslash read as a literal
after passes
```
`raw_strings_still_use_raw_syntax_when_no_nul_is_present` and
`raw_string_is_refused_when_the_value_has_a_nul` are both controls, so
neither the fallback nor the new guard can spread to values that were
already fine.
A detail worth flagging since it is easy to get wrong: the quote-forcing
set is a `fancy_regex` character class, so the NUL has to be written
`\x00` there. Writing `\0` puts a literal NUL byte in the pattern, which
makes the `LazyLock` panic on first use with an "internal error:
NEEDS_QUOTING_REGEX didn't compile".
</details>
---------
Co-authored-by: feiiiiii5 <feiiiiii5@users.noreply.github.com>
|
||
|
|
996de1f9a4 |
fix(std/dt): compute the day remainder directly in datetime-diff (#19109)
## Description
`std/dt`'s `datetime-diff` derives year/month/day by successive
"borrowing". When the earlier date sits at the **end of a month** (e.g.
Jan 31) and the later date is the 1st of a month two months on (e.g. Mar
1), borrowing one month by table lookup adds the days of the month
actually crossed (28/29 for February) — fewer than the 31 days of the
earlier date — so the day comes out **negative** or one short:
```nushell
datetime-diff 2023-03-01T00:00:00Z 2023-01-31T00:00:00Z # {month: 1, day: -2}
datetime-diff 2024-03-01T00:00:00Z 2024-01-31T00:00:00Z # {month: 1, day: -1} (leap)
datetime-diff 2023-07-01T00:00:00Z 2023-05-31T00:00:00Z # {month: 1, day: 0} (should be day: 1)
```
This violates the module's own invariant — *"datetime-diff can't return
negative units"* (see `test_dt.nu`) — and the "round-trips exactly"
property of the #19064 refactor that introduced the table-lookup borrow:
`2023-01-31 + 1mo + (-2)d = 2023-02-26`, not `2023-03-01`.
The fix counts the whole months that fit between the two dates from the
**raw day-of-month** (falling back to the time of day when both dates
carry the same day number), then takes the remaining days from the
clamped anchor date. The `day` is therefore never negative and the
result always adds back up to the later date. Sub-day units still use
the existing borrow chain.
Counting whole months from the raw day rather than from the clamped date
is deliberate: it keeps every result `main` already got right, so the
fix does not smuggle in a month-splitting behaviour change — `2023-01-31
→ 2023-02-28` stays `28 days`, `2023-03-31 → 2023-04-30` stays `30
days`, `2024-02-29 → 2025-02-28` stays `11 months 30 days`.
## User-facing changes (Release notes)
- Fixed `std/dt` `datetime-diff` returning a negative or incorrect `day`
value when the earlier date is at the end of a month (for example Jan 31
→ Mar 1).
## Additional notes
- This is a regression from #19064 (the "borrow the crossed month"
change, merged 2026-09-22). That change fixed mid-month `earlier` dates
but under-borrows month-end earlier dates.
- All pre-existing `test_dt` cases still pass; seven regression tests
are added, covering month-end spans, the time-of-day boundary,
cross-year spans, and non-month-end dates that get clamped.
- Verified against a locally built `nu` 0.116.0: all 20 `test_dt` cases
pass under `testing run-tests`. The `nu-std` suite as a whole is not
green here for an unrelated reason — two `path_add_expand` cases need
Windows privileges to create symlinks and fail identically on unmodified
`main`.
- The old and new month-counting rules were compared with a Python
replica of both, cross-checked against a built `nu`. Each figure below
covers what its check actually inspects:
- **29,418,285 pairs** (every `earlier ≤ later` day pair at midnight,
2010–2030) — full old-vs-new output comparison, with every differing
pair classified by which side is wrong: 4,403 where the old rule returns
a negative `day`, 345,254 where it does not add back up to the later
date. The buckets reserved for "the new rule is the broken one", "the
previous clamped-anchor rule is the broken one" and "both reconstruct
but split the months differently" came back **empty**, which is what
shows the fix touches only results that were already wrong. Negative
`day`: 4,403 old, 0 new.
- **3,000,000 random pairs including a time of day** — same full
comparison: 0 round-trip failures new, 35,683 old.
- **29,418,285 + 157,950,360 combinations** (midnight pairs, then
month-end/month-start dates × 120 time-of-day pairs) — *invariant*
checks on the new rule only: anchor month is always the later month or
the one before, the anchor never overshoots the later date, month count
never negative, `//`/`mod` agree with the previous floor-division
helper, day remainder never negative. All zero violations; these runs do
not compare against `main`.
- **94,478,400 ordered time-of-day pairs** (two fixed dates, 9,720 clock
values) — checks that the sub-day borrow chain reaches `borrow-day`
exactly when the later clock is earlier than the first, and that every
sub-day unit stays in range: 0 disagreements.
- In all of the above the new rule never enters
`borrow-month`/`borrow-year`, which is why this change also drops them
as dead code.
- Scope note: this keeps `main`'s month-counting semantics rather than
aligning with `dateutil.relativedelta`, which reports a whole month for
`2023-01-31 → 2023-02-28`. Spot-checked against `relativedelta` on a
1-in-97 sample of the midnight domain (303,281 pairs, comparing the
year/month split only): it agrees with the clamped-anchor rule in every
sampled case and with this rule in all but 152. Intentional, so that
fixing the negative `day` does not also change output that was already
correct.
- This change was drafted with AI assistance (Claude); I verified the
reproduction and the fix against a local build.
|
||
|
|
c3b7a5aebe |
fix: reject out-of-range decimals in into string (#19191)
## Description
`into string -d <precision>` panics when the precision is large enough
that `10_f64.powi(precision as i32)` underflows to zero. The division
then produces NaN, and `format!("{:.*}", precision, NaN)` panics with
"Formatting argument out of range".
Repro: `1.5 | into string -d 2147483648`
The `i64` precision is cast to `i32` for `powi`, so values above
`i32::MAX` wrap to negative, producing `10^(-2147483648) = 0`, then
`NaN`. The `is_finite()` guard earlier in the function only checks the
input value, not the rounded result.
Return the original value's string form when the rounding produces NaN.
## User-facing changes
`into string` with a very large `-d` value no longer panics; it returns
the unrounded value.
## Additional notes
Verified with a standalone Rust repro that `(1.5 *
10^(-2147483648)).round() / 10^(-2147483648)` is NaN and
`format!("{:.*}`, 2147483648, NaN)` panics.
|
||
|
|
bc1ff565b0 |
char --list: group aliases of same char, fix misalignment (#19091)
<!-- Thanks for contributing to Nushell! Before submitting, please read the contributing guide: https://github.com/nushell/nushell/blob/main/CONTRIBUTING.md This template helps reviewers understand your changes and allows us to generate high-quality release notes. --> ## Description `char --list` has a bunch of duplicate names for the same alias, which makes it hard to read. this PR (statically) groups the aliases together into a new `aliases` column. this reduces the number of table entries from 118 to 56. it makes the following decisions: 1. the `name` of a character is the first entry in the original map (please suggest a different candidate name if preferred) 2. platform-dependant chars like path separators are kept as their own group instead of becoming aliases 3. I kept the char itself as a `String` instead of `&'static str` 4. I kept the original section comments from the original map. because why not. **additionally**, this PR contains a fix for `char --list` misalignment. when control characters are outputted, the table gets misaligned, but we forgot to account for `1c`, `1d`, `1e` and `1f` (we manually enumerated the control chars). now we instead use `char::is_control`, so no misalignment. ## User-facing changes (Release notes) `char --list` now groups alternate name for the same character, into a new `aliases` column. additionally, it fixes a potential misalignment issue when displaying the table. |
||
|
|
2d9adcda29 |
Reject command names with irregular whitespace at definition time (#18969)
`def "foo bar" [] {}` is accepted, but `foo bar` can never be called:
`command_name_from_spans` in `crates/nu-parser/src/parse_calls.rs`
rebuilds the name from the lexed words with single spaces, so the call
looks up `foo bar` and falls through to an external. Leading or trailing
whitespace and tabs fail the same way. As sholderbach suggested on the
issue, refusing such definitions is the sensible fix.
`def`, `extern` and `alias` now reject a name unless it equals its words
joined by single spaces, reusing `CommandDefNotValid` and
`AliasNotValid` with their labels extended. Parser tests cover the
rejected shapes for all three keywords and check that single-space names
still work; `cargo test -p nu-parser`, clippy with `-D warnings` on
`nu-parser` and `nu-protocol`, and `cargo fmt --all -- --check` pass.
## User-facing changes (Release notes)
Defining a command or alias whose name contains consecutive, leading, or
trailing whitespace is now a parse error, since such a command could
never be called.
Fixes #15539
---------
Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
|
||
|
|
e01865bdec |
build(deps): bump uuid from 1.26.0 to 1.27.0 (#19179)
Bumps [uuid](https://github.com/uuid-rs/uuid) from 1.26.0 to 1.27.0. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/uuid-rs/uuid/releases">uuid's releases</a>.</em></p> <blockquote> <h2>v1.27.0</h2> <h2>What's Changed</h2> <ul> <li>Accept case-insensitive urn:uuid: prefixes when parsing by <a href="https://github.com/jaideeppyne"><code>@jaideeppyne</code></a> in <a href="https://redirect.github.com/uuid-rs/uuid/pull/912">uuid-rs/uuid#912</a></li> <li>Fix ordering of V7 UUIDs created by earlier seconds with later subsec nanos by <a href="https://github.com/KodrAus"><code>@KodrAus</code></a> in <a href="https://redirect.github.com/uuid-rs/uuid/pull/915">uuid-rs/uuid#915</a></li> <li>Prepare for 1.27.0 release by <a href="https://github.com/KodrAus"><code>@KodrAus</code></a> in <a href="https://redirect.github.com/uuid-rs/uuid/pull/917">uuid-rs/uuid#917</a></li> </ul> <h2>New Contributors</h2> <ul> <li><a href="https://github.com/jaideeppyne"><code>@jaideeppyne</code></a> made their first contribution in <a href="https://redirect.github.com/uuid-rs/uuid/pull/912">uuid-rs/uuid#912</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/uuid-rs/uuid/compare/v1.26.1...v1.27.0">https://github.com/uuid-rs/uuid/compare/v1.26.1...v1.27.0</a></p> <h2>v1.26.1</h2> <h2>What's Changed</h2> <ul> <li>Seat the v7 counter below the version nibble by <a href="https://github.com/lenamonj"><code>@lenamonj</code></a> in <a href="https://redirect.github.com/uuid-rs/uuid/pull/907">uuid-rs/uuid#907</a></li> <li>Don't panic in overflowing Timestamp to SystemTime conversion by <a href="https://github.com/KodrAus"><code>@KodrAus</code></a> in <a href="https://redirect.github.com/uuid-rs/uuid/pull/909">uuid-rs/uuid#909</a></li> <li>Prepare for 1.26.1 release by <a href="https://github.com/KodrAus"><code>@KodrAus</code></a> in <a href="https://redirect.github.com/uuid-rs/uuid/pull/910">uuid-rs/uuid#910</a></li> </ul> <h2>New Contributors</h2> <ul> <li><a href="https://github.com/lenamonj"><code>@lenamonj</code></a> made their first contribution in <a href="https://redirect.github.com/uuid-rs/uuid/pull/907">uuid-rs/uuid#907</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/uuid-rs/uuid/compare/v1.26.0...v1.26.1">https://github.com/uuid-rs/uuid/compare/v1.26.0...v1.26.1</a></p> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/uuid-rs/uuid/commit/b62154e8be41ce42127cba08ee5e5cef3e2ea971"><code>b62154e</code></a> Merge pull request <a href="https://redirect.github.com/uuid-rs/uuid/issues/917">#917</a> from uuid-rs/cargo/v1.27.0</li> <li><a href="https://github.com/uuid-rs/uuid/commit/ffd8ec55f20006fa2b5978cc03a1e671835040e9"><code>ffd8ec5</code></a> prepare for 1.27.0 release</li> <li><a href="https://github.com/uuid-rs/uuid/commit/4b6c10f9dd9cf37809460859ab88071d43703398"><code>4b6c10f</code></a> Merge pull request <a href="https://redirect.github.com/uuid-rs/uuid/issues/915">#915</a> from uuid-rs/fix/v7-ordering</li> <li><a href="https://github.com/uuid-rs/uuid/commit/a1aa126f97cdc8d9c5c25d56efa0e7bcb9ab0514"><code>a1aa126</code></a> Merge pull request <a href="https://redirect.github.com/uuid-rs/uuid/issues/912">#912</a> from jaideeppyne/fix/urn-prefix-case-insensitive</li> <li><a href="https://github.com/uuid-rs/uuid/commit/4639d67b0f117a94cf0add01e4c68e674691b49c"><code>4639d67</code></a> fix ordering of V7 UUIDs created by earlier seconds with later subsec nanos</li> <li><a href="https://github.com/uuid-rs/uuid/commit/272370344a977ee0641ffa4d01b7ad3ca0eda687"><code>2723703</code></a> bump MSRV to 1.89.0</li> <li><a href="https://github.com/uuid-rs/uuid/commit/a3e64faaf7fdf583260fc18a594b099677855eea"><code>a3e64fa</code></a> refactor: simplify URN prefix parsing</li> <li><a href="https://github.com/uuid-rs/uuid/commit/5055fd41c7f33c16a1eac3198eac6224ec18b61d"><code>5055fd4</code></a> refactor: inline case-insensitive URN prefix checks</li> <li><a href="https://github.com/uuid-rs/uuid/commit/cb8b1d51421df4828c11ebca6b54c5986caafef6"><code>cb8b1d5</code></a> refactor: simplify case-insensitive URN parsing</li> <li><a href="https://github.com/uuid-rs/uuid/commit/285967db45b800ffda5032d12c32e3d4e2620902"><code>285967d</code></a> Accept case-insensitive urn:uuid: prefixes when parsing</li> <li>Additional commits viewable in <a href="https://github.com/uuid-rs/uuid/compare/v1.26.0...v1.27.0">compare view</a></li> </ul> </details> <br /> [](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 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> |
||
|
|
9bb7c9dfdf |
build(deps): bump taiki-e/install-action from 2.87.21 to 2.87.24 (#19177)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.87.21 to 2.87.24. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/taiki-e/install-action/releases">taiki-e/install-action's releases</a>.</em></p> <blockquote> <h2>2.87.24</h2> <ul> <li> <p>Update <code>wasmtime@latest</code> to 49.0.2.</p> </li> <li> <p>Update <code>dprint@latest</code> to 0.59.0.</p> </li> <li> <p>Update <code>cargo-leptos@latest</code> to 0.3.11.</p> </li> <li> <p>Update <code>cargo-insta@latest</code> to 1.49.0.</p> </li> <li> <p>Update <code>cargo-binstall@latest</code> to 1.25.0.</p> </li> </ul> <h2>2.87.23</h2> <ul> <li> <p>Update <code>wasm-tools@latest</code> to 1.261.0.</p> </li> <li> <p>Update <code>uv@latest</code> to 0.12.22.</p> </li> <li> <p>Update <code>trivy@latest</code> to 0.75.0.</p> </li> <li> <p>Update <code>tombi@latest</code> to 1.7.1.</p> </li> <li> <p>Update <code>protoc-gen-connect-openapi@latest</code> to 0.28.0.</p> </li> <li> <p>Update <code>mise@latest</code> to 2026.10.0.</p> </li> <li> <p>Update <code>kingfisher@latest</code> to 2.9.1.</p> </li> <li> <p>Update <code>kache@latest</code> to 0.28.1.</p> </li> <li> <p>Update <code>espup@latest</code> to 0.18.0.</p> </li> <li> <p>Update <code>dprint@latest</code> to 0.58.0.</p> </li> <li> <p>Update <code>cargo-crap@latest</code> to 0.6.1.</p> </li> <li> <p>Update <code>cargo-auditable@latest</code> to 0.7.7.</p> </li> <li> <p>Update <code>biome@latest</code> to 2.5.15.</p> </li> <li> <p>Update <code>syft@latest</code> to 1.54.0.</p> </li> </ul> <h2>2.87.22</h2> <ul> <li> <p>Update <code>typos@latest</code> to 1.50.3.</p> </li> <li> <p>Update <code>tombi@latest</code> to 1.5.8.</p> </li> <li> <p>Update <code>prek@latest</code> to 0.5.4.</p> </li> <li> <p>Update <code>mise@latest</code> to 2026.9.16.</p> </li> <li> <p>Update <code>kache@latest</code> to 0.28.0.</p> </li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md">taiki-e/install-action's changelog</a>.</em></p> <blockquote> <h1>Changelog</h1> <p>All notable changes to this project will be documented in this file.</p> <p>This project adheres to <a href="https://semver.org">Semantic Versioning</a>.</p> <!-- raw HTML omitted --> <h2>[Unreleased]</h2> <h2>[2.87.26] - 2026-10-06</h2> <ul> <li> <p>Update <code>tombi@latest</code> to 1.7.2.</p> </li> <li> <p>Update <code>prek@latest</code> to 0.5.5.</p> </li> <li> <p>Update <code>mise@latest</code> to 2026.10.3.</p> </li> <li> <p>Update <code>kache@latest</code> to 1.0.0.</p> </li> <li> <p>Update <code>hyperfine@latest</code> to 1.21.0.</p> </li> </ul> <h2>[2.87.25] - 2026-10-05</h2> <ul> <li> <p>Update <code>uv@latest</code> to 0.12.23.</p> </li> <li> <p>Update <code>mise@latest</code> to 2026.10.2.</p> </li> <li> <p>Update <code>kingfisher@latest</code> to 2.10.0.</p> </li> <li> <p>Update <code>dprint@latest</code> to 0.60.1.</p> </li> <li> <p>Update <code>cargo-semver-checks@latest</code> to 0.51.0.</p> </li> <li> <p>Update <code>cargo-binstall@latest</code> to 1.25.1.</p> </li> </ul> <h2>[2.87.24] - 2026-10-04</h2> <ul> <li> <p>Update <code>wasmtime@latest</code> to 49.0.2.</p> </li> <li> <p>Update <code>dprint@latest</code> to 0.59.0.</p> </li> <li> <p>Update <code>cargo-leptos@latest</code> to 0.3.11.</p> </li> <li> <p>Update <code>cargo-insta@latest</code> to 1.49.0.</p> </li> <li> <p>Update <code>cargo-binstall@latest</code> to 1.25.0.</p> </li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/taiki-e/install-action/commit/e407f7bafb71fd004bc5c2da3032e5470cbb6ef0"><code>e407f7b</code></a> Release 2.87.24</li> <li><a href="https://github.com/taiki-e/install-action/commit/cf05ef864e9f66eb375f5000cc71cb3f90bede2b"><code>cf05ef8</code></a> Update wasmtime manifest</li> <li><a href="https://github.com/taiki-e/install-action/commit/a9843d29aa80dad318a30939972ff077b7c0c1ed"><code>a9843d2</code></a> Update <code>wasmtime@latest</code> to 49.0.2</li> <li><a href="https://github.com/taiki-e/install-action/commit/b53f18d3272788dee0a574080a98fc2dbe92f0aa"><code>b53f18d</code></a> Update uv manifest</li> <li><a href="https://github.com/taiki-e/install-action/commit/432553710dc21b4f7270c670f4620f829d5c9375"><code>4325537</code></a> Update kingfisher manifest</li> <li><a href="https://github.com/taiki-e/install-action/commit/28c75969bb18dc23fe25a37a2f47b5fd2af27dd1"><code>28c7596</code></a> Update <code>dprint@latest</code> to 0.59.0</li> <li><a href="https://github.com/taiki-e/install-action/commit/c9ccaaeffe99c9f74245f88f8e736dc8b8524c8f"><code>c9ccaae</code></a> Update cargo-semver-checks manifest</li> <li><a href="https://github.com/taiki-e/install-action/commit/6a93a472a4fadcaa3c041e569eee39d762923f84"><code>6a93a47</code></a> Update <code>cargo-leptos@latest</code> to 0.3.11</li> <li><a href="https://github.com/taiki-e/install-action/commit/32465026f914ad462743179999c65b9773d2d9ff"><code>3246502</code></a> Update <code>cargo-insta@latest</code> to 1.49.0</li> <li><a href="https://github.com/taiki-e/install-action/commit/944f981294fb92b4c2bb873d2fa0b5fd61f613bb"><code>944f981</code></a> Update <code>cargo-binstall@latest</code> to 1.25.0</li> <li>Additional commits viewable in <a href="https://github.com/taiki-e/install-action/compare/4cef1412cce204788f482e778a0b9187f9626a29...e407f7bafb71fd004bc5c2da3032e5470cbb6ef0">compare view</a></li> </ul> </details> <br /> [](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 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> |
||
|
|
8ca2234705 |
Path relative to walkup (#19089)
Disclosure: the code was written by an AI agent (Claude) under my direction; I can't review Rust line-by-line myself. ## Description In this PR, I added a `--walk-up` flag to `path relative-to`: when the argument path is not a parent of the input, its leftover components become `..`. ```nu > '/a/b/c' | path relative-to '/a/d/e' --walk-up ../../b/c ``` - **Opt-in**, as @WindSoilder asked in #14055, following Python's `relative_to(walk_up=True)`. Without the flag, the error still works as an "is inside" check (Neovim kept `vim.fs.relpath` parent-only for this reason, neovim/neovim#31790). Spelled `--walk-up` rather than the proposed `--walkup`, to match nu-command's kebab-case flags. - **Symlinks** (@sholderbach's question): the command stays lexical and `const`; the help text warns that a symlink in the argument path can make `..` point elsewhere. - **Refused with `--walk-up`:** absolute mixed with relative, different Windows drives, and `.` or `..` in the argument after the shared part — none of these can be answered from the text alone. - One component walk replaces `strip_prefix` plus the case-insensitive fallback from #16310, so case folding applies to `--walk-up` too. - Output without the flag changes in three cases: a leading ./ is ignored ('./a/b' | path relative-to 'a' returns b instead of an error); an absolute input against an empty base is refused ('/a' | path relative-to '' returned /a); and a pair with different roots is refused as "different roots" with a hint, instead of "not a parent". The error hints at `--walk-up` only when the flag would give a result. Easier to review commit by commit: the first is a refactor with no behaviour change, the second adds the flag on top of it. ## User-facing changes (Release notes) `path relative-to` has a new `--walk-up` flag that returns a path with `..` when the argument path is not a parent of the input: `'/a/b/c' | path relative-to '/a/d/e' --walk-up` returns `../../b/c`. ## Additional notes - closes #13969 - supersedes #14055 (closed unmerged after going stale) - related #16310, neovim/neovim#31790 Windows-only tests (the example output and the different-drive refusal) were not run locally. --------- Co-authored-by: Claude <claude@anthropic.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
8fbb4d6f92 |
fix(into-duration): reject duplicate hh:mm:ss (#19073)
Hoist the attempt to parse as `hh:mm:ss` This closes #19072 ## User-facing changes - fixed an issue where repeating clock timestamps were wrongly accepted for `into duration` |
||
|
|
76126ffcb2 |
Clear sqlite history with SQL instead of deleting the file (#19092)
## Description `history --clear` deleted the sqlite history file with `std::fs::remove_file`, leaving a TODO about the `-wal`/`-shm` files. That goes wrong in several ways: - the running REPL still holds a connection to the deleted file, so every later command in that session is written to an unlinked file and lost; - the leftover `-wal`/`-shm` files don't match the new database, so the next session can fail with `disk I/O error` (as reported in the issue) or `no such table: history`; - on Windows the file is in use and can't be deleted at all (the reason #11049 was shelved). As suggested in #11049, this clears the sqlite history in place through reedline's `SqliteBackedHistory::clear`, which runs `delete from history` followed by `VACUUM`. The table stays, so the REPL's open connection keeps working and new sessions open the database normally. Plaintext history is unchanged. Tests added in `crates/nu-cli/tests/commands/history_output.rs`: - `sqlite_history_clear_removes_all_entries`: import records, `history --clear`, `history | length` is 0; - `sqlite_history_clear_keeps_database_usable`: a connection opened before the clear (standing in for the REPL) and a fresh `SqliteBackedHistory::with_file` can both add entries afterwards, and `history` shows both. Without this fix, the entry written through the pre-existing connection is lost. ## User-facing changes (Release notes) Fixed `history --clear` with sqlite history: it now empties the history database in place instead of deleting the file, so the current session keeps recording history and new sessions no longer fail to start with a "disk I/O error". It also works on Windows while Nushell is running. ## Additional notes Fixes #14244 Supersedes #11049 |
||
|
|
55006c3917 |
Fix(LSP) lsp crash on symbol requests for unopened or closed documents (#19194)
## Description fix to issue #19192 A `textDocument/documentSymbol` request can crash the language server when the document was never opened or was already closed. The handler now checks document availability before updating the symbol cache. It returns `null` for unavailable documents and keeps the server running. Two regression tests cover these cases. Each confirms that a later valid symbol request succeeds on the same server connection. ## User-facing changes (Release notes) Fixed a language server crash when an editor requests symbols for an unopened or closed document. The server now continues to handle later requests. ## Additional notes Related to SmiteshP/nvim-navic#174. Validation on macOS: - Workspace tests: 9,806 passed; 91 ignored. - Documentation tests: 235 passed; 18 ignored. - Formatting, compiler, build, Clippy, and spelling checks passed. - Standard library and virtualenv tests passed. - WebAssembly and both fuzz project checks passed. Linux and Windows jobs were not run locally. The virtualenv test used Python 3.13; CI specifies Python 3.10. |
||
|
|
04a0444435 |
Don't allow duplicate column names in Rename (#19196)
## Description Rename allows renaming columns of a table with duplicate names, even though duplicate column names are disallowed. I fixed this by checking the column names for duplicates using a HashSet. Otherwise valid records are discarded and a nu::shell::column_defined_twice error is thrown if there are duplicates. ## User-facing changes (Release notes) Fixed an issue where rename allowed setting duplicate column names on a table ## Additional notes Closes https://github.com/nushell/nushell/issues/19195 |
||
|
|
67edfb6eca |
record family of commands (#19190)
## Description This PR adds the `record` family of commands that makes working with records easier and more fun. There are four record commands as discussed in #19061. Each one takes a record and returns a record, so the common jobs no longer need a `transpose k v | ... | transpose -r -d` or `items {..} | into record` round trip. Each one also takes a table and streams one record per row. ```text record help text listing the subcommands record where keep the fields where closure(key, value) is true --keys --values record each rebuild the record from what closure(key, value) returns record walk run closure(value, path) on every nested leaf --containers --no-lists record apply run a record of closures on the matching fields --strict ``` ## User-facing changes (Release notes) Added `record where`, `record each`, `record walk` and `record apply` for working with records directly, without converting them to tables and back. Each one also takes a table and streams one record per row. ```nushell # keep the fields whose value is greater than one {a: 1, b: 2, c: 3} | record where value > 1 # => {b: 2, c: 3} # keep the fields whose key starts with NU_ {NU_LOG: debug, HOME: /home/me} | record where key starts-with NU_ # => {NU_LOG: debug} # change keys and values in one pass {a: 1, b: 2} | record each {|key, value| {($key | str uppercase): ($value * 10)}} # => {A: 10, B: 20} # redact nested values by their cell path {db: {host: prod, password: hunter2}, api: {token: abc}} | record walk {|value, path| if ($path | to text) =~ "(?i)secret|token|password" { "***" } else { $value } } # => {db: {host: prod, password: ***}, api: {token: ***}} # convert several fields with a reusable record of closures {age: "42", email: "A@B.COM", tags: [x]} | record apply {age: {into int}, email: {str lowercase}} # => {age: 42, email: a@b.com, tags: [x]} # convert a column of every row of a table [{name: a, size: "1"} {name: b, size: "2"}] | record apply {size: {into int}} # => [[name, size]; [a, 1], [b, 2]] ``` `record where` takes a row condition on `key` and `value`, or a closure that gets the key and value as arguments. `--keys` or `--values`, placed before the condition, pass only the key or only the value. `record walk` takes `--containers` to also visit nested records and lists, and `--no-lists` to treat lists as single values. `record apply` takes `--strict` to error on transforms for fields the input doesn't have. ## Additional notes closes #19061 |
||
|
|
145a0609c6 |
Write line breaks in to md table cells as <br> (#19189)
## Description `to md` wrote line breaks inside table cells as-is, so a multi-line value split its row and broke the table: ```nushell > [[name note]; [a "line 1\nline 2"] [b ok]] | to md | name | note | | --- | --- | | a | line 1 line 2 | | b | ok | ``` A Markdown table row can't span lines, so this rendered as a one-row table followed by a stray paragraph. Pipes in cells are already escaped for the same reason. With this change, line breaks (`\n` and `\r\n`) in table cells and headers are written as `<br>`, which GitHub and other common renderers show as a line break inside the cell: ```nushell > [[name note]; [a "line 1\nline 2"] [b ok]] | to md | name | note | | --- | --- | | a | line 1<br>line 2 | | b | ok | ``` Lists and single values are not tables and are unchanged. ## User-facing changes (Release notes) Fixed `to md` producing broken tables when a cell contains a line break; line breaks in table cells are now written as `<br>`. ## Additional notes Added `test_line_breaks_in_table_cells`, which fails on `main` and passes with this change. `cargo fmt --all -- --check` and `cargo clippy -p nu-command --all-targets -- -D warnings` pass. `cargo test -p nu-command` passes apart from four tests that depend on file permissions or DNS (`cd_permission_denied_folder`, `mkdir_continues_creating_directories_after_error`, `rm_prints_filenames_on_error`, `helpful_dns_error_for_unknown_domain`), which fail in my sandbox because it runs as root without network access. |
||
|
|
9149ea5ede |
MCP: Added allowed-hosts and allowed-origins flags (#19076)
## Description Added MCP flags for allowed-hosts and allowed-origins. This is required if you wish to bind the mcp server to other interfaces than localhost. I also fixed some missing parts portions for bind-host. ## User-facing changes (Release notes) Added MCP flags for allowed-hosts and allowed-origins. This is required if you wish to bind the mcp server to other interfaces than localhost. --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> |
||
|
|
a2138a8e26 |
fix(cell-path):in and not-in between cell paths, and a panic on an empty cell path (#19187)
## Description
This PR compares each window against the left path, and treats the empty
path as contained in every path, the same way `"" in "abc"` is `true`.
`not-in` now negates `in`, the way `has` already calls `in`, so the two
arms can't disagree again.
I'm guessing this was a typo
## User-facing changes (Release notes)
Fixed `in` and `not-in` between two cell paths. They now report whether
the left path appears as a contiguous run in the right one, so `[$.x] |
each {|p| $p in $.a }` is `[false]` and `let p: any = $.b.c; $p in
$.a.b.c.d` is `true`. An empty cell path on the left no longer crashes
Nushell; it is in every cell path.
Evidence, with each left path held in an `any`-typed variable:
| left | `in` right | main | this PR |
| --------- | ------------- | ----- | ------- |
| `$.a` | `$.a` | true | true |
| `$.x` | `$.a` | true | false |
| `$.b.c` | `$.a.b.c.d` | false | true |
| `$.0` | `$.items.0` | false | true |
| `$.a.c` | `$.a.b.c` | false | false |
| `$.a.b` | `$.a` | false | false |
| (empty) | `$.a` | panic | true |
## Additional notes
<!--
Optional.
Examples:
- fixes #123
- closes #456
- related #789
Anything else reviewers should know.
Remove this section if not needed.
-->
|
||
|
|
f88b5a8976 |
impl Hash for Value and inner types in nu-protocol (#18933)
<!-- Thanks for contributing to Nushell! Before submitting, please read the contributing guide: https://github.com/nushell/nushell/blob/main/CONTRIBUTING.md This template helps reviewers understand your changes and allows us to generate high-quality release notes. --> ## Description This PR implements hash for Value. This should later allow Value to be used as a key in group-by. <!-- Explain what this PR does and why. This section is intentionally flexible: - Describe the problem - Explain your approach - Include technical details if relevant Good examples: - "In this PR, I fixed..." - "In this PR, I added support for..." - "This change improves X by..." Write as much or as little as needed for reviewers to understand your changes. --> ## User-facing changes (Release notes) <!-- This section is used (mostly as-is) for https://www.nushell.sh/blog/ Describe how Nushell behavior changes from a user's perspective. Do NOT describe internal Rust changes here. Write in a release note style, for example: - "Added support for..." - "Fixed an issue where..." - "Nushell now supports..." - "Improved performance of..." If your changes do NOT affect users (internal refactors, cleanup, etc.), just write: - "n/a" - "nan" - or similar This tells us the change should not appear in the changelog. Tips: - Focus on observable behavior - Include examples if helpful - Keep it concise You can: - Write a short paragraph (will appear as a bullet point), OR - Use headings (###) if your change needs more structure Avoid writing things like: - "In this PR, I refactored..." - "This updates internal code..." You may leave this blank until the PR is ready. --> ## Additional notes <!-- Optional. Examples: - fixes #123 - closes #456 - related #789 Anything else reviewers should know. Remove this section if not needed. --> |
||
|
|
abcf4f8c5f |
Fix crash if buffer editor is invalid (#19185)
## Description Nushell crashes when opening the buffer editor by pressing CTRL+O if it can't find the specified editor. We first try getting the editor from $env.config.buffer_editor, and if that doesn't exist, we fall back to $env.VISUAL and $env.EDITOR [source](https://www.nushell.sh/book/configuration.html#configuration-overview). If any of these is checked and invalid, the bug happens. Now instead of crashing it simply does nothing, which I suppose is better. The editor is verified by checking whether a file with the name exists in the current directory or in the path. Maybe an error message could be added as well to improve user experience. Closes https://github.com/nushell/nushell/issues/19184 ## User-facing changes (Release notes) n/a |
||
|
|
74ed8ed6e8 |
feat(lsp): report serverInfo in the initialize response (#19180)
## Description `nu --lsp` did not include `serverInfo` in its `initialize` response, so editors and other LSP clients could not tell which version of the language server was running. The server called `Connection::initialize_while` from `lsp-server`, which only sends `capabilities`. I replaced it with `initialize_start_while` and `initialize_finish_while`, so the server builds the `InitializeResult` itself and can add `serverInfo`. The name is `Nushell`. The version is `CARGO_PKG_VERSION`, which `nu-mcp` also reports as its version. I added a test, `initialize_reports_server_info`, that checks the response. ## User-facing changes (Release notes) The language server (`nu --lsp`) now reports its name and version in the LSP `initialize` response (`serverInfo`), so editors can show which Nushell version is running. ## Additional notes fixes #19176 |
||
|
|
b14e65b77d |
feat(find): add only matching output flag (#19150)
## Description `find` can filter and highlight matches, but it did not have a way to return only the matched text. This makes it harder to replace simple `grep -o` style workflows with Nushell. This change adds `find --only-matching` with short flag `-o`. It returns each non-empty match as a separate value and supports the existing matching modes, including regex, ignore case, multiline, and `--rfind`. `--invert` is rejected with `--only-matching` because inverted output has no clear matched substring to return. ## User-facing changes (Release notes) Added `find --only-matching` and `find -o` to return only matched text, similar to `grep -o`. ## Additional notes Fixes #18982 Tests: - `cargo test -p nu-command filters::find::tests::test_examples` |
||
|
|
549e72d518 |
Measure nuon table column widths in runes, not bytes (#19165)
## Description
`to nuon --pretty` measures table column widths in bytes while padding
in runes, so a column containing a multi-byte cell is padded wider than
the format asks for. This makes the column as wide as the widest cell's
byte length instead of its rune count.
This is a canonicalization fix, not a terminal-alignment fix, and I want
to be accurate about which is which.
```
[[a, b]; ["日本", 1], ["abcde", 2]] | to nuon --pretty
main this branch
[a, b]; [a, b];
[日本, 1], [日本, 1],
[abcde, 2] [abcde, 2]
```
`日本` is 2 runes and 6 bytes. Byte widths make the first column 6 wide
where 5 is the widest cell's rune count, so every row in that column
gets one space of padding nobody asked for. Rows still lined up with
each other before this change, and they still do; what changes is the
width of the column, not the alignment between rows.
## The fix
Measure the widths in the same unit the padding uses:
```rust
// Column widths = max of header and cell widths per column.
// Counted in chars, not bytes: the padding below is applied with `{:<width$}`,
// which counts chars, so a byte length pads the column wider than any cell in
// it actually needs.
let mut widths: Vec<usize> = col_names.iter().map(|h| h.chars().count()).collect();
```
This is bug 6 in `crates/nuon/spec/bugs_to_fix.md`, whose entry I have
ticked as that file asks. The spec asks for one measure on both sides,
which is what this does.
**Terminal display width, and why not.** Display width is the measure
that would make CJK and ASCII line up visually, and it is available —
`unicode-width` is already a workspace dependency and `nu-term-grid`
uses it. I deliberately did not use it here. Display width is a property
of the rendering target rather than of the value, so a NUON document's
bytes would come to depend on which terminal reads it, and
ambiguous-width characters resolve differently per terminal and locale.
For a format that gets written to files and diffed, one deterministic
measure on both sides is the right invariant, and `nu-term-grid` is
already the layer that handles width for display. Happy to take a
follow-up PR if you would rather the writer target the terminal.
## User-facing changes (Release notes)
Fixed `to nuon --pretty` padding table columns wider than their contents
require when a cell contains multi-byte characters.
## Additional notes
Verified against `main` at `c14a6f38`:
```
cargo test -p nuon --lib 56 passed, 1 ignored
cargo test -p nu-command --test tests format_conversions::nuon 48 passed
cargo fmt -p nuon -- --check clean
cargo clippy -p nuon --all-targets -- -D warnings clean
```
Red/green, reverting only `crates/nuon/src/to.rs`:
```
cargo test -p nuon --lib
without the fix 55 passed, 1 failed
tests::table_column_alignment_with_non_ascii_cells FAILED
with the fix 56 passed, 1 ignored
```
Only one test is red without the fix, and the reason is worth stating
since it is easy to assume otherwise. A single multibyte rune such as
`…` produces identical output either way: its 3-byte length does inflate
the column, but never past the 5 needed by `abcde`, so the inflated
width is not the maximum and nothing observable changes. Only a cell
whose byte length actually *is* the column maximum — the CJK case —
differs. I kept the `…` case as a control, so the width change cannot be
widened into something that breaks the shapes that already worked.
I also corrected the alignment assertion from my first version. It took
the char count after `rfind(',')`, which on these rows is the row's
*trailing* comma, so every collected value was 0 and the assertion held
because `0 == 0` — only the indent case, whose sole comma is the
separator, measured anything. It now skips the bracket-only lines and
the `;`-terminated header, finds the separator inside `[...]`, and reads
the offset at the first non-whitespace character after it. Restoring the
old helper and adding a non-zero requirement turns the two non-ASCII
tests red, which is how I confirmed the new one is measuring.
Worth being plain about the limit of that assertion: byte-derived widths
satisfied it too. A shared width plus `{:<width$}` pads every cell to
the same char count either way, so the invariant holds on both sides and
it is the exact-output assertion that pins this change. I would rather
say that than leave a test implying it guards more than it does.
Both new tests still round-trip: `from_nuon` on the output returns the
original value.
I tested the `nuon` crate and `nu-command`'s nuon conversion tests. I
did not run the full workspace suite, and I did not rebuild the `nu`
binary in this pass, so the samples above come from the crate tests
rather than a fresh binary run.
---------
Co-authored-by: feiiiiii5 <feiiiiii5@users.noreply.github.com>
|
||
|
|
6fe6b91b2c |
Fix IDE completion with an out of bounds location (#19183)
## Description Fixes an issue where Nushell would crash when listing IDE completions with an invalid cursor position. Instead of trusting user input as is, we first clamp the user given location to [0, line.len()] and then find the closest valid index such that the slice would be valid UTF-8 by using [floor_char_boundary](https://dev-doc.rust-lang.org/beta/std/primitive.str.html#method.floor_char_boundary). Closes https://github.com/nushell/nushell/issues/19182 ## User-facing changes (Release notes) No crashes when `nu --ide-complete` uses an out of range value like `"nu --ide-complete -1 a.nu"` |
||
|
|
86e6517abc |
fix(nix): take libx11 instead of the deprecated xorg set (#19181)
## Description nixpkgs turned the `xorg` set into a warning alias, thus `scripts/nix/default.nix` printed `'xorg.libX11' has been renamed to 'libx11'` on every evaluation. This takes the top-level `libx11` instead. `libX11` exists at the top level too, but only as an alias, so `libx11` is the name that stays. ## User-facing changes (Release notes) n/a ## Additional notes Checked against current nixos-unstable, evaluates without the warning. |
||
|
|
e1756290ff | build(deps): bump hustcer/setup-nu from 3.27 to 3.28 (#19178) | ||
|
|
88bf737d8d |
chore: bump reedline to e9fcfdb (#19175)
## Description Bumps reedline to `e9fcfdb`, eight PRs past the 0.52.1 release: - nushell/reedline#1240 `fix(helix): give h and l the arrow keys' fallbacks in normal mode` - nushell/reedline#1239 `fix(engine): keep auto-pairs out of menu queries and hint before trailing closers` - nushell/reedline#1234 `docs(engine): spell out what a templated buffer editor keeps, test envs` - nushell/reedline#1233 `fix(painter): hide the cursor before the anchor query` - nushell/reedline#1224 `docs: fill Completion and VI sections in UX_TESTING.md` - nushell/reedline#1188 `feat(editor): Add helix match selection` - nushell/reedline#1041 `feat: accept templated command for OpenEditor` - nushell/reedline#1236 `fix(painter): saturate the large buffer line math for 0/1-row terminals` #1188 replaced the `CutInsidePair`, `CopyInsidePair`, `CutAroundPair` and `CopyAroundPair` edit commands with the text object ones and added `SelectTextObject`, `AddTextObject`, `RemoveTextObject` and `ReplaceTextObject`. This PR brings the keybinding config in line with that, so every text object command reedline has can be bound. The four removed names still parse, onto the matching text object command, so existing configs keep working. ## User-facing changes (Release notes) - In helix mode `h` and `l` now step through an open menu, and `l` accepts a history hint, as the arrow keys and vi's `h`/`l` do. - Helix mode gained the match commands under `m`: select inside or around a pair, add one around the selection, and delete or replace the nearest one. - The cursor no longer shows at the start of the next line while the prompt waits on the terminal's position report. - Text object edit commands take more values in the keybinding config: - `object_type` takes `word`, `bigword`, `brackets` and `quotes` as before, plus a single pair: `parentheses`, `square_brackets`, `curly_brackets`, `angle_brackets`, `single_quotes`, `double_quotes` or `backticks`. Any other pair is a record, `{ left: "|", right: "|" }`. - `brackets` now includes `<>`. - `CutTextObject`, `CopyTextObject` and the new `SelectTextObject` take an optional `check_next` (default `true`): with the cursor outside any match, act on the next one. - New `AddTextObject` and `RemoveTextObject` take `object_type`, and `ReplaceTextObject` takes `old` and `new`. These need a single pair, so `word`, `brackets` or `quotes` is an error there. ```nushell { edit: SelectTextObject, scope: inner, object_type: parentheses } { edit: AddTextObject, object_type: { left: "*", right: "*" } } { edit: ReplaceTextObject, old: parentheses, new: square_brackets } ``` ## Additional notes `CutInsidePair` and friends are no longer listed by `keybindings list`, but still accepted. |
||
|
|
3b08da67d1 |
chore: remove x86_64-darwin target in flake.nix (#19173)
## Description Remove `x86_64-darwin` (Intel Mac) from the Nix flake's supported systems because nixos-unstable after 26.05 has dropped support for this platform, causing evaluation to fail. This removes Intel Mac outputs from `packages`, `legacyPackages`, and `devShells`. Apple Silicon Mac support remains available through `aarch64-darwin`. Also update `flake.lock` to refresh the `nixpkgs` and `rust-overlay` inputs. ## User-facing changes (Release notes) Removed Intel Mac (`x86_64-darwin`) support from the Nushell Nix flake following its removal from upstream Nixpkgs. Apple Silicon Macs remain supported. |
||
|
|
15b810275b |
Correct float into string conversions (#19166)
## Description Fix #16772 by implementing string-based decimal grouping for `into string` on floats and adding locale support. Because floating point conversion into decimal strings is tricky, continue to use Rust's implementation, then modify it's output with grouping and locale strings. The rounding behavior of into string was also inconsistent with `math round`. See these results: ``` [[base]; [0.5] [1.5]] | insert math {$in.base | math round} | insert str { $in.base | into string -d 0} # base math str ─────────────────────── 0 0.50 1 0 1 1.50 2 2 ``` Manually round the floats in the same manner in both places. Update to use the slightly more efficient `f64.powi()` method instead of `f64.powf()`. ## User-facing changes (Release notes) Added support to `into string` for locales and `--group-digits` with floating point input. Made the `into string` rounding match `math round`. ## Additional notes fixes #16772 |
||
|
|
043ae4e425 |
fix(match): allow .. and ..$rest anywhere in a match list pattern, like Rust (#19172)
## Description
In a `match` list pattern, `..` and `..$rest` only worked as the last
item. The parser stopped reading the list at the first rest pattern and
dropped everything after it without an error:
- `[.., 2]` parsed as `[..]`, so it matched every list.
- `[.., 2, ..]` also parsed as `[..]`.
- `[$a, ..$rest, $b]` never declared `$b`, so the arm body failed with
"Variable not found".
The matcher made the same assumption and only handled a rest pattern at
the end.
Rest patterns in a list now follow Rust's slice-pattern rules:
- A list pattern can hold one `..` or `..$rest`, at any position. Items
before it match the start of the list, items after it match the end, and
`..$rest` binds the values in between (an empty list when there are
none).
- A second `..` or `..$rest` in the same list pattern is a parse error,
as in Rust ("`..` can only be used once per slice pattern"). Each nested
list gets its own, so `[[.., 2], ..]` is fine.
- Without a rest pattern, the list must have as many values as the
pattern has items. This is unchanged.
### Before and after
```nushell
match [2] { [.., 1] => "one", [.., 2] => "two" }
match [1 2 3] { [$a, ..$rest, $b] => [$a $rest $b] }
match [2] { [.., 1, ..] => "one", [.., 2, ..] => "two" }
```
Before (0.116.2):
```text
one
Error: nu::parser::variable_not_found (points at `$b` in the arm body)
one
```
After:
```text
two
[1, [2], 3]
Error: nu::parser::error
× `..` can only be used once per list pattern
╭─[source:1:21]
1 │ match [2] { [.., 1, ..] => "one", [.., 2, ..] => "two" }
· ─┬
· ╰── extra rest pattern
╰────
help: Keep one `..` or `..$name` and remove the others.
```
## User-facing changes (Release notes)
`match` list patterns now accept `..` and `..$rest` anywhere in the
list, as in Rust, not only at
the end:
```nushell
match [1 2 3 4] { [$first, ..$middle, $last] => $middle } # [2 3]
match $steps { [.., "done"] => "finished", _ => "running" }
```
Before, every item after `..` was silently ignored, so `[.., "done"]`
matched any list. Using `..`
or `..$rest` more than once in the same list pattern is now a parse
error.
## Additional notes
closes https://github.com/nushell/nushell/issues/19169
|
||
|
|
c14a6f3836 |
bug: debug adapter inspect deadlock (#19167)
## Description This fixes an deadlock condition in the DAP crate for inspecting the variables ## User-facing changes (Release notes) The vscode UI no longer hangs after inspecting a variable --------- Co-authored-by: Ronald van Helden <ronald.van.helden@wortell.nl> |
||
|
|
6771d58127 |
perf(parser): parse real scripts about 1.3x faster (#19138)
## Description
This is a big PR. I've been working on it for a while. It contains 17
parser speed up changes and some fixes. Instead of doing stacked PRs I
just made them each a separate commit. Each commit has a description of
what it contains. The grammar and the parser test fixtures that were in
this PR have moved to their own follow-up PRs.
This PR makes `nu-parser` parse real files about **1.33x faster**,
without changing what it produces for valid code. The exceptions are a
few compile errors of invalid code (commits 16 and 18) and two lexer
bugs it fixes (commit 18).
Parsing happens on every REPL line, every config file, every `use`d
module and every script, so this shortens startup (which loads the
config and the standard library) as well as running scripts.
Each commit is one self-contained change with its own explanation,
builds on its own, and can be reviewed on its own:
| # | Commit | Instructions |
| ---: | --- | ---: |
| 1 | bench: parse real files in the shell's engine
(parser_parse_shell_*) | benchmarks only |
| 2 | perf(parser): lex each file's bracket structure once | -4.34% |
| 3 | perf(parser): parse a list with the tokens the table parser
already lexed | -0.34% |
| 4 | perf(compile): store IR comments and AST references sparsely |
-2.08% |
| 5 | perf(parser): answer declared-variable membership from a set in
capture discovery | -1.41% |
| 6 | perf(parser): cache command signatures on the EngineState instead
of per parse | -2.83% |
| 7 | perf(parser): remember the output type of each command for each
input type | -0.58% |
| 8 | perf(parser): reject non-numeric tokens by their first byte before
decoding them | -1.58% |
| 9 | perf(parser): keep the first VisibilityStack frames inline |
-1.69% |
| 10 | perf(parser): hash declaration names with FxHash | -1.15% |
| 11 | perf(parser): move the def body's signature instead of cloning it
| -0.85% |
| 12 | perf(parser): take delta blocks out instead of cloning them in
replace_in_variable | -0.51% |
| 13 | perf(parser): skip command-name candidates longer than any
declared name | -1.16% |
| 14 | perf(parser): skip speculative range parses of tokens without
`..` | -0.25% |
| 15 | perf(parser): check the last file a span lookup found before
scanning | -2.55% |
| 16 | perf(parser): compile each def body once instead of twice |
-5.87% |
| 17 | perf(parser): check identifier bytes with a match instead of
searching a list | -1.15% |
| 18 | fix(parser): fix regressions and lexer bugs found in review |
fixes |
| 19 | fix(parser): fix issues found in a second review | fixes, not
measured |
"Instructions" is the change in instructions executed to parse the
benchmark corpus caused by that commit, measured against the commit
before it. The effects compound: together, commits 1 to 17 execute 25.2%
fewer instructions than `main` which translates to a 1.34x speedup.
## User-facing changes (Release notes)
- Parsing is about 30% faster: the REPL, scripts, modules, `use std/...`
and loading the config all parse faster. What gets parsed doesn't change
for valid code.
- A `def` whose body fails to compile now reports its compile error once
instead of twice. Commands that show compile errors already showed only
the first, so this is not visible from the command line.
- `break` or `continue` in a closure or `def` body inside a `try`'s
`catch` or `finally` clause is now reported when the script is parsed.
Before, `try { } catch { do { break } }` parsed, and the closure failed
when it ran with "Can't evaluate block in IR mode".
- Inside brackets, `#` starts a comment only when whitespace comes right
before it, whatever the character before it is. `[voilà#tag]` is now the
list `["voilà#tag"]`, like `[café#tag]`, instead of an "Unclosed
delimiter" error.
- The "Extra tokens" error for a `;` right after `|` (`ls |; ls`) now
points at the `;`.
- `def --help foo [] { ... }` only shows the help of `def` and defines
nothing. Calling `foo` afterwards used to crash the shell ("can't run a
predeclaration without a body").
- An unclosed list (`[1 2`) reports its "Unclosed delimiter" error once
instead of twice.
- `view ir` separates the items of list and record patterns with commas.
## Additional notes
### Where the time goes now, and what could make it faster
A sampling profile of commit 17 parsing the benchmark corpus in a loop
(12,014 samples inside `parse`, macOS `sample`) splits parse time like
this:
| Part of the parse | Share |
| --- | ---: |
| Syntax: expressions, literals, blocks, pipelines | 23.7% |
| Lexing and `lite_parse` | 19.6% |
| Argument parsing from signatures (`parse_internal_call`, flags,
keywords) | 15.0% |
| Compiling to IR and capture discovery | 14.0% |
| Name resolution, scopes and overlays | 9.6% |
| Type checking | 1.9% |
| Everything else (constant evaluation, output types, file access,
errors, ...) | 15.0% |
Across all of these, `malloc`/`free`/`realloc` take 22.4% of parse time,
`memmove`/`memcpy` 4.7% and dropping values 3.5%.
None of the following is part of this PR. Each was found while
profiling; shares are of parse time in the profile above, and gains are
estimates unless marked as measured.
So, there still is some room to approve parsing performance.
|
||
|
|
9a3a106ce6 |
minor updates to AGENTS.md and CONTRIBUTING.md (#19164)
<!-- Thanks for contributing to Nushell! Before submitting, please read the contributing guide: https://github.com/nushell/nushell/blob/main/CONTRIBUTING.md This template helps reviewers understand your changes and allows us to generate high-quality release notes. --> ## Description These are just minor updates for more accuracy <!-- Explain what this PR does and why. This section is intentionally flexible: - Describe the problem - Explain your approach - Include technical details if relevant Good examples: - "In this PR, I fixed..." - "In this PR, I added support for..." - "This change improves X by..." Write as much or as little as needed for reviewers to understand your changes. --> ## User-facing changes (Release notes) <!-- This section is used (mostly as-is) for https://www.nushell.sh/blog/ Describe how Nushell behavior changes from a user's perspective. Do NOT describe internal Rust changes here. Write in a release note style, for example: - "Added support for..." - "Fixed an issue where..." - "Nushell now supports..." - "Improved performance of..." If your changes do NOT affect users (internal refactors, cleanup, etc.), just write: - "n/a" - "nan" - or similar This tells us the change should not appear in the changelog. Tips: - Focus on observable behavior - Include examples if helpful - Keep it concise You can: - Write a short paragraph (will appear as a bullet point), OR - Use headings (###) if your change needs more structure Avoid writing things like: - "In this PR, I refactored..." - "This updates internal code..." You may leave this blank until the PR is ready. --> ## Additional notes <!-- Optional. Examples: - fixes #123 - closes #456 - related #789 Anything else reviewers should know. Remove this section if not needed. --> |
||
|
|
fd5721afce |
bmp rust toolchain to 1.97.1 (#19160)
## Description This PR bumps the rust toolchain to 1.97.1 since 1.99 was recently released and we try to stay 2 versions behind it. <!-- Explain what this PR does and why. This section is intentionally flexible: - Describe the problem - Explain your approach - Include technical details if relevant Good examples: - "In this PR, I fixed..." - "In this PR, I added support for..." - "This change improves X by..." Write as much or as little as needed for reviewers to understand your changes. --> ## User-facing changes (Release notes) <!-- This section is used (mostly as-is) for https://www.nushell.sh/blog/ Describe how Nushell behavior changes from a user's perspective. Do NOT describe internal Rust changes here. Write in a release note style, for example: - "Added support for..." - "Fixed an issue where..." - "Nushell now supports..." - "Improved performance of..." If your changes do NOT affect users (internal refactors, cleanup, etc.), just write: - "n/a" - "nan" - or similar This tells us the change should not appear in the changelog. Tips: - Focus on observable behavior - Include examples if helpful - Keep it concise You can: - Write a short paragraph (will appear as a bullet point), OR - Use headings (###) if your change needs more structure Avoid writing things like: - "In this PR, I refactored..." - "This updates internal code..." You may leave this blank until the PR is ready. --> ## Additional notes <!-- Optional. Examples: - fixes #123 - closes #456 - related #789 Anything else reviewers should know. Remove this section if not needed. --> |
||
|
|
fcbf51c402 |
Allow TZ_VARIANTS in into datetime --timezone (#19139)
<!-- Thanks for contributing to Nushell! Before submitting, please read the contributing guide: https://github.com/nushell/nushell/blob/main/CONTRIBUTING.md This template helps reviewers understand your changes and allows us to generate high-quality release notes. --> ## Description <!-- Explain what this PR does and why. This section is intentionally flexible: - Describe the problem - Explain your approach - Include technical details if relevant Good examples: - "In this PR, I fixed..." - "In this PR, I added support for..." - "This change improves X by..." Write as much or as little as needed for reviewers to understand your changes. --> This PR allows using all timezones from `date list-timezone` (from `chrono_tz::TZ_VARIANTS`) to be used in the `--timezone` flag for `into datetime`. This also includes the completion to make it easy to use: <img width="855" height="392" alt="timezone autocomplete" src="https://github.com/user-attachments/assets/7476713a-0d74-4554-af8a-ab6c245312e9" /> ## User-facing changes (Release notes) <!-- This section is used (mostly as-is) for https://www.nushell.sh/blog/ Describe how Nushell behavior changes from a user's perspective. Do NOT describe internal Rust changes here. Write in a release note style, for example: - "Added support for..." - "Fixed an issue where..." - "Nushell now supports..." - "Improved performance of..." If your changes do NOT affect users (internal refactors, cleanup, etc.), just write: - "n/a" - "nan" - or similar This tells us the change should not appear in the changelog. Tips: - Focus on observable behavior - Include examples if helpful - Keep it concise You can: - Write a short paragraph (will appear as a bullet point), OR - Use headings (###) if your change needs more structure Avoid writing things like: - "In this PR, I refactored..." - "This updates internal code..." You may leave this blank until the PR is ready. --> `into datetime --timezone` now accepts all timezones from `date list-timezone`. ## Additional notes <!-- Optional. Examples: - fixes #123 - closes #456 - related #789 Anything else reviewers should know. Remove this section if not needed. --> - fixes #19132 |
||
|
|
1746089921 |
Start non-interactively when running as MCP server (#19153)
## Description This PR makes nushell start non-interactively when started as an MCP server, just like is done when it is launched as an LSP or DAP server. In the source code it is stated that MCP servers should run non-interactively, which is not currently the case: https://github.com/nushell/nushell/blob/bd30843743bf1c9f46f67597eaa45fa7871571e2/crates/nu-mcp/src/lib.rs#L84 <!-- Explain what this PR does and why. This section is intentionally flexible: - Describe the problem - Explain your approach - Include technical details if relevant Good examples: - "In this PR, I fixed..." - "In this PR, I added support for..." - "This change improves X by..." Write as much or as little as needed for reviewers to understand your changes. --> ## User-facing changes (Release notes) MCP mode is now set to non-interactive ## Additional notes closes https://github.com/nushell/nushell/issues/19152 |
||
|
|
b6671f5cdc |
fix(ps): list every process and report the same columns on every platform (#19145)
## Description This PR refactors the `ps` command and consolidates some code with `nu_system::ProcessInfo` while also making it more portable having the same columns on all operating systems with `ps` and `ps -l`. It also fixes some bugs where all the processes weren't being seen on MacOS. Also there was some debate as to whether 0 was valid for cpu. `cpu` is the percent of one core used during a ~100ms sample, like `top`. Most processes are idle during any 100ms, and `/bin/ps` agrees. Per-process values won't always match `/bin/ps`: macOS's `%CPU` is the kernel's decaying recent average (a process stopped after 3 seconds at 100% shows 0.0 five seconds later), and Linux's `ps` shows lifetime average CPU. ## User-facing changes (Release notes) - `ps` now lists every process on macOS (zombies included) and Windows (all but the System Idle Process), including other users' and protected processes. Values the operating system doesn't make available for a process (on macOS, the CPU, memory and threads of other users' processes unless you run as root) are null instead of the process being left out. - `ps` and `ps -l` now return the same columns on every platform. A column is null when the platform or the process doesn't provide that value. - `ps`: `pid ppid name user status cpu cpu_time mem` - `ps -l` adds: `virtual private command exe start_time user_id process_group_id session_id priority nice threads read written cwd environment` - New columns: - `cpu_time`: total CPU time the process has used. - `private`: the memory only the process uses, the number Activity Monitor and Task Manager show as "Memory". - `nice`: the nice value; on Windows, the priority class on the nice scale. - `read` and `written`: bytes of storage I/O since the process started (all I/O on Windows). - `exe`: the path of the executable. - Also new on the platforms that were missing them: `user`, `user_id`, `process_group_id`, `session_id`, `threads`, `cwd` and `environment`, and `start_time` on the BSDs. - Changed columns: - `user` is now in `ps`, and `virtual` is now only in `ps -l`. - `process_threads` is renamed to `threads`. - `working` (always the same as `mem`) and `paged` are removed. Use `private` for the memory a process uses by itself. - Linux: - `cpu` is now measured to the nanosecond instead of in 10% steps. - `name` is no longer cut to 15 characters when argv[0] or the executable shows the full name. - `cwd` and `environment` are null for processes you can't read (other users' processes unless you are root); `cwd` used to be an empty string. - Windows: - `ps` now has a `status` column (`Running`, `Sleeping` or `Suspended`). - `user_sid` is replaced by `user_id`, which holds the SID string (for example `S-1-5-18`). - `virtual` is now the virtual address space size, as on other platforms. - `priority` is the base priority (8 for normal priority). - `nice` is the priority class on the nice scale, as libuv and Node.js map it (normal 0, high -14, idle 19). - `process_group_id` is the console process group, the one `CREATE_NEW_PROCESS_GROUP` starts and `GenerateConsoleCtrlEvent` sends Ctrl+Break to. - macOS: - `cwd` is now the current working directory rather than the directory the process started in. - `status` now uses `Sleeping` instead of `Sleep` and `Waiting`, matching the other platforms, and zombies are listed as `Zombie`. - `kernel_task` (pid 0) is now listed, as Activity Monitor does. - FreeBSD, NetBSD and OpenBSD: - Zombies and other processes whose arguments can't be read are now listed, under the kernel's process name. - On FreeBSD, `cpu` now includes threads that start or exit during the sample. - On OpenBSD, `virtual` is no longer always 0. - `command` shows newlines and tabs in arguments as spaces on Windows and the BSDs too, as it already did on Linux and macOS. - Null sorts after every number, so the examples now drop nulls first: `ps | compact cpu | sort-by cpu | last 3`. Matching a text column that can be null with `=~` is an error, so also drop those rows first: `ps | compact status | where status =~ Run`. ## Additional notes closes #18358 Let this serve as documentation about what the columns mean per platform. The column set follows what top, htop, btop, btm, procs, Task Manager and Activity Monitor show: | column | Linux | macOS | Windows | FreeBSD | NetBSD / OpenBSD | | --- | --- | --- | --- | --- | --- | | `user` | name of the effective uid | same | account of the token's SID | same as Linux | same as Linux | | `status` | `stat` state | thread states; zombie/stopped for all | thread states | `ki_stat` | `p_stat` | | `cpu` | process CPU-time clock (ns), or `stat` ticks | task times | process times | `ki_runtime` | `p_rtime` | | `cpu_time` | `utime + stime` | task times | user + kernel time | `ki_runtime` | `p_rtime` (null for zombies) | | `mem` | RSS | resident size | working set | RSS | RSS | | `virtual` | VSZ | virtual size | virtual size | VSZ | VSZ | | `private` | `RssAnon` | physical footprint (own processes) | private working set | resident pages of anonymous mappings from `KERN_PROC_VMMAP` (own processes) | null: no private-memory figure | | `exe` | `/proc/<pid>/exe` (own processes) | `proc_pidpath` | `QueryFullProcessImageNameW` | `KERN_PROC_PATHNAME` | `KERN_PROC_PATHNAME`; null on OpenBSD, which doesn't expose it | | `start_time` | `stat` | `kinfo_proc` | creation time | `ki_start` | `p_ustart` (null for zombies) | | `user_id` | effective uid | effective uid | SID string | `ki_uid` | `p_uid` | | `process_group_id` | `stat` | short BSD info | console process group from the process parameters | `ki_pgid` | `p__pgid` | | `session_id` | `stat` | `getsid` (null for kernel_task) | Terminal Services session | `ki_sid` | `p_sid` | | `priority` | kernel priority | task priority (own processes) | base priority | `ki_pri.pri_level` | `p_priority` | | `nice` | `stat` | `kinfo_proc` | priority class on the nice scale | `ki_nice` | `p_nice` | | `threads` | `stat` | task info (own processes) | snapshot | `ki_numthreads` | `p_nlwps`; null on OpenBSD, whose `kinfo_proc` has no thread count | | `read` / `written` | storage bytes from `/proc/<pid>/io` (own processes) | storage bytes from `proc_pid_rusage` (own processes) | all I/O bytes, including pipes and network | null: the kernel counts block operations, not bytes | null: the kernel counts block operations, not bytes | | `cwd` | `/proc/<pid>/cwd` (own processes) | `PROC_PIDVNODEPATHINFO` (own processes) | process parameters | `KERN_PROC_CWD` (own processes) | `KERN_PROC_CWD` (own processes) | | `environment` | `/proc/<pid>/environ` (own processes) | `KERN_PROCARGS2` (own processes) | process parameters | `KERN_PROC_ENV` (own processes) | `KERN_PROC_ENV` (own processes) | "Own processes" means the current user's processes, or every process when running as root. Every backend reads each column from the kernel. These have no kernel interface to read from and stay null, with the reason in a comment where the backend sets them: `read`/`written` on the BSDs, `private` on NetBSD and OpenBSD, and `exe` and `threads` on OpenBSD. |
||
|
|
f92634ceb7 |
Reject to nuon --raw --no-commas, which writes no separator (#19158)
## Description
`to nuon --raw --no-commas` writes no separator at all, so lists lose
their arity and tables lose their column boundaries. The output is still
valid nuon, so nothing downstream can detect the loss.
`--raw` removes the space after the comma, `--no-commas` removes the
comma, and the two compose by subtraction into nothing:
```
[1 2 3] | to nuon --raw --no-commas # => [123]
[true false null] | to nuon --raw --no-commas # => [truefalsenull]
[[name age]; [Alice 30] [Bob 25]] | to nuon --raw --no-commas
# => [[nameage];[Alice30][Bob25]]
```
Read back, `[1 2 3]` is the single integer `123`, `[true false null]` is
a single **string** `"truefalsenull"` — both arity and types change —
and the table reads back as a one-column table named `nameage`. The
written form parses cleanly, so a caller has nothing to detect.
The fix rejects the combination rather than picking a separator. The
spec's own argument for this is that it costs nothing: emitting one
space would produce output the same size as `--raw` alone, since
dropping a comma and adding a space is a one-for-one byte swap — so the
pair has no size advantage over `--raw` once it is correct, and the only
thing it buys today is the corrupt output.
The check lives in `to nuon`'s `run()`, alongside the other
mutually-exclusive flag checks in this module (`to kdl` and `to yaml`
use the same `ShellError::IncompatibleParameters`):
```
[1 2 3] | to nuon --raw --no-commas
# Error: nu::shell::incompatible_parameters
# x Incompatible parameters.
# ,-[source:1:19]
# 1 | [1 2 3] | to nuon --raw --no-commas
# : ^^|^^ ^^^^^|^^^^^
# : | `-- `--no-commas` drops the separator `--raw` keeps, so the pair writes no separator at all
# : `-- this with
```
`to nuon` is the only place in the workspace that sets `use_commas`, so
this closes the combination for every caller rather than only for the
CLI spelling of it.
## User-facing changes (Release notes)
Fixed `to nuon` writing corrupt output when `--raw` and `--no-commas`
were combined; the two flags are now rejected as incompatible.
## Additional notes
This is bug 5 in `crates/nuon/spec/bugs_to_fix.md`, whose entry I have
ticked as that file asks.
```
cargo test -p nu-command --test tests format_conversions
without the fix 46 passed, 2 failed
to_nuon_rejects_raw_with_no_commas FAILED
to_nuon_raw_with_no_commas_rejected_for_records_and_tables_too FAILED
with the fix 48 passed
cargo test -p nu-command --test tests format_conversions 215 passed, 6 ignored
cargo clippy -p nu-command --lib clean
cargo fmt -p nu-command -- --check clean
```
The three tests cover a list, a record, a table and a list of mixed
types, plus a check that each flag still works alone (`--raw` →
`[1,2,3]`, `--no-commas` → `[1 2 3]`, neither → `[1, 2, 3]`), so
rejecting the pair cannot be mistaken for breaking either flag.
I put the check at the command layer rather than inside `to_nuon`,
because the composing behaviour is a property of the two flags being
combined, not of the writer. If you would rather `to_nuon` refuse it too
— so a library caller cannot reach the corrupt output — that is a small
move and I would do it that way if you prefer.
I tested `nu-command`'s conversion tests and built the `nu` binary; I
did not run the full workspace test suite.
Co-authored-by: feiiiiii5 <feiiiiii5@users.noreply.github.com>
|
||
|
|
04680006c0 |
Strip one leading byte order mark in from nuon (#19157)
## Description
`from nuon` rejects any document that starts with a UTF-8 byte order
mark, so a `.nuon` file written by PowerShell's `Out-File` or a Windows
editor cannot be loaded at all.
`from_nuon` hands its input straight to `nu_parser::parse`. `U+FEFF` is
neither whitespace nor a delimiter, so it glues onto the first token and
the document parses as a command call:
```
"\u{feff}1" | from nuon # => error: calls not supported in nuon
"\u{feff}[1]" | from nuon # => error: calls not supported in nuon
```
`U+FEFF` also appears mid-document as a zero-width no-break space, so
stripping it everywhere would corrupt legitimate content. The fix is
`strip_prefix` — exactly one leading BOM, nothing else — applied before
parsing.
This is bug 1 in `crates/nuon/spec/bugs_to_fix.md`, which the spec
already specifies: *"a leading utf-8 bom is stripped, exactly one and
only at the start."* I have ticked that entry, as the file's header
asks.
## User-facing changes (Release notes)
Fixed an issue where `from nuon` failed to load a document starting with
a UTF-8 byte order mark, such as one written by PowerShell's `Out-File`
or a Windows editor.
## Additional notes
Two tests in `crates/nuon/src/from.rs`, each written to kill a specific
wrong implementation rather than just to pass:
```
cargo test -p nuon --lib
without the fix 49 passed, 1 FAILED
nuon_parse_strips_one_leading_bom FAILED a leading bom should be stripped
with trim_start_matches instead of strip_prefix nuon_parse_keeps_a_lone_bom_and_inner_boms FAILED
"only one leading bom is stripped"
with the fix 50 passed, 1 ignored
cargo clippy -p nuon --lib clean
cargo fmt -p nuon -- --check clean
```
The first test asserts a leading BOM decodes to exactly the value the
same document decodes to without one. The second pins the "exactly one"
part: a BOM inside a string body stays content, and two leading BOMs
still fail rather than both being stripped.
A document that is *only* a BOM decodes to `Nothing`. That is the
empty-document case, which is bug 2 in the same list, so I left it alone
rather than widening this change.
I built and tested `nuon` only, not the full workspace.
Co-authored-by: feiiiiii5 <feiiiiii5@users.noreply.github.com>
|
||
|
|
046dea5dc8 |
fix(nuon): error on a duration head that overflows (#19087)
## Description
`convert_to_value` in `crates/nuon/src/from.rs` scaled a duration's head
with `*` for the microsecond, millisecond, second, minute and hour arms,
while the day and week arms right next to them already used
`checked_mul`:
```rust
Unit::Nanosecond => Ok(Value::duration(size, span)),
Unit::Microsecond => Ok(Value::duration(size * 1000, span)),
Unit::Millisecond => Ok(Value::duration(size * 1000 * 1000, span)),
Unit::Second => Ok(Value::duration(size * 1000 * 1000 * 1000, span)),
Unit::Minute => Ok(Value::duration(size * 1000 * 1000 * 1000 * 60, span)),
Unit::Hour => Ok(Value::duration(size * 1000 * 1000 * 1000 * 60 * 60, span)),
Unit::Day => match size.checked_mul(1000 * 1000 * 1000 * 60 * 60 * 24) { ... }
```
`size` is an `i64` that the parser has already clamped to `i64::MAX` for
an out-of-range literal, keeping the unit it folded to. So `[1e30sec]`
arrives as `Int(i64::MAX)` plus `Unit::Millisecond`, and `size * 1000 *
1000` overflows: a panic on user-supplied file content in debug builds,
and `-1000000ns` in release ones. That is a valid negative duration that
no downstream check will question, which is what `bugs_to_fix.md` calls
the serious case.
The spec already states the required behaviour,
`crates/nuon/spec/nuon_formal_specification.md`:
> overflow is an **error**; it must not wrap or saturate. a positive
literal must never read back as a negative duration.
and `crates/nuon/spec/bugs_to_fix.md` lists this as bug 8 with the note
"**do not reproduce.** error on overflow." This PR fixes the reader-side
overflow for the scaled units it can detect; bug 8 remains open because
the parser still clamps out-of-range `ns` and `us` literals before the
reader sees them. The reader gets `Int(i64::MAX)` plus `Nanosecond` and
cannot distinguish that from an exact `9223372036854775807ns`. Fixing
that means touching `parse_literals.rs`, which open PR #18970 also
edits, so it stays out of this PR.
This is bug 8 only. Bug 9, negative and saturating filesizes, is a
different arm and a different spec bullet.
## User-facing changes (Release notes)
- Fixed: reading a NUON document whose duration literal overflows, such
as `[1e30sec]`, no longer wraps into a negative duration. `ms`, `sec`,
`min` and `hr` now report an error, as `day` and `wk` already did.
## Additional notes
<details>
<summary>Testing plan</summary>
`main` at `ac000bbbae917f562a8b7c8602d9853f9d1094e0`, Rust 1.98.0,
aarch64-apple-darwin. `from_nuon` is a pure function over a string, so
this needs no shell, no fixture and no network.
Four tests in the existing `mod tests` in `from.rs`.
`duration_overflow_is_rejected` covers each overflowing unit;
`duration_overflow_error_points_at_the_literal` checks that the label
points to the literal rather than the caller span;
`in_range_durations_still_decode` covers ordinary literals through the
parser; and `scaled_duration_units_still_decode` constructs an AST
directly because the parser folds valid literals to nanoseconds,
covering each scaled `Unit::build_value` success path.
Before the fix, with only the tests added:
```
test from::tests::in_range_durations_still_decode ... ok
test from::tests::duration_overflow_is_rejected ... FAILED
thread 'from::tests::duration_overflow_is_rejected' panicked at crates/nuon/src/from.rs:438:57:
attempt to multiply with overflow
```
After:
```
$ cargo test -p nuon --offline
test result: ok. 52 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 0.02s
```
Gates: `cargo fmt -p nuon -- --check` clean; `cargo clippy -p nuon
--all-targets --offline -- -D warnings -D clippy::unwrap_used` clean.
Round-trip safety: the writer always emits `ns`
(`nuon_formal_specification.md`, "the writer emits durations in `ns`,
always"), so it can never produce a literal the new check rejects.
</details>
---------
Co-authored-by: feiiiiii5 <feiiiiii5@users.noreply.github.com>
|
||
|
|
e191d52cb2 |
Fix it-if typo in chained error doc comment (#19143)
Noticed this while reading the tester code, the neighbors all say if it is one so I fixed the outlier to match. Comment only, no behavior change. I checked rustfmt is clean on the file. Co-authored-by: GhostCoder6969 <ghostcoder6969@users.noreply.github.com> |
||
|
|
652be0a888 |
build(deps): bump xxhash-rust from 0.8.15 to 0.8.19 (#19155)
Bumps [xxhash-rust](https://github.com/DoumanAsh/xxhash-rust) from 0.8.15 to 0.8.19. <details> <summary>Commits</summary> <ul> <li>See full diff in <a href="https://github.com/DoumanAsh/xxhash-rust/commits">compare view</a></li> </ul> </details> <br /> [](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 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) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/nushell/nushell/network/alerts). </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
9883c113af |
Update CI artifact uploading (#19106)
<!-- Thanks for contributing to Nushell! Before submitting, please read the contributing guide: https://github.com/nushell/nushell/blob/main/CONTRIBUTING.md This template helps reviewers understand your changes and allows us to generate high-quality release notes. --> ## Description <!-- Explain what this PR does and why. This section is intentionally flexible: - Describe the problem - Explain your approach - Include technical details if relevant Good examples: - "In this PR, I fixed..." - "In this PR, I added support for..." - "This change improves X by..." Write as much or as little as needed for reviewers to understand your changes. --> This PR changes how the CI uploads its artifacts to further testing and for download via the toolkit. In fact this PR is a complete rewrite of our `ci.yml` to be hopefully more straightforward. I also fixed the `toolkit run pr` command on windows. And the binaries built by ci include in their `version` command a `build_pr` field that references the pr that caused this binary to build. ## User-facing changes (Release notes) <!-- This section is used (mostly as-is) for https://www.nushell.sh/blog/ Describe how Nushell behavior changes from a user's perspective. Do NOT describe internal Rust changes here. Write in a release note style, for example: - "Added support for..." - "Fixed an issue where..." - "Nushell now supports..." - "Improved performance of..." If your changes do NOT affect users (internal refactors, cleanup, etc.), just write: - "n/a" - "nan" - or similar This tells us the change should not appear in the changelog. Tips: - Focus on observable behavior - Include examples if helpful - Keep it concise You can: - Write a short paragraph (will appear as a bullet point), OR - Use headings (###) if your change needs more structure Avoid writing things like: - "In this PR, I refactored..." - "This updates internal code..." You may leave this blank until the PR is ready. --> n/a --------- Co-authored-by: Bahex <17417311+Bahex@users.noreply.github.com> |