mirror of
https://github.com/nushell/nushell.git
synced 2026-10-28 08:54:52 +08:00
main
12071
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
9970552848 |
Fix OSC 7 directory URL escaping (#19358)
Hello ## Description Use `Url::from_file_path` to encode OSC 7 directory paths. Keep the shell hostname for local paths, including numeric names. UNC paths now use the file server as the URL host. ## User-facing changes (Release notes) Fixed terminal directory tracking for directory names containing `#`, `?`, `%`, or `;`. UNC paths now report the file server as the host, so terminals that require a local host may ignore them. ## Additional notes Fixes #19357. |
||
|
|
c7c8ebaa9e |
Bump webpage and zstd-sys, ignore the other zstd advisories to clear the RustSec audit (#19359)
## Description The `Security audit` job fails on main and on every PR that touches `Cargo.toml` or `Cargo.lock` (#19358 is one). The advisory database now lists five vulnerabilities: | Crate | Locked | Fixed in | Advisory | This PR | | --- | --- | --- | --- | --- | | `webpage` | 2.0.1 | 2.1.0 | RUSTSEC-2026-0407 | bump | | `zstd-sys` | 2.0.16 | 2.1.2 | RUSTSEC-2026-0410 | bump (lockfile only) | | `zstd` | 0.13.3 | 0.14.3 | RUSTSEC-2026-0391 | ignore | | `zstd-safe` | 7.2.4 | 8.2.0 | RUSTSEC-2026-0398, -0403 | ignore | `webpage` is a direct dependency of `nu_plugin_query`. The advisory covers URL fetching (`HTTP::fetch`, `Webpage::from_url`), and the plugin never fetches. It only calls `HTML::from_string` on its input. Version 2.1.0 also moves `webpage` to html5ever 0.39, which `scraper` already uses, so the lockfile drops html5ever 0.27 and the seven crates that came with it. The zstd crates come only from polars 0.55.2 in `nu_plugin_polars`. zstd-safe 7.2.4 accepts `zstd-sys ^2.0.15`, so the lockfile can take zstd-sys 2.1.2. That fixes the wasm32 allocator bug in RUSTSEC-2026-0410. zstd and zstd-safe can't move, because polars 0.55.2 is the latest release and requires `zstd ^0.13`. polars main is already on zstd 0.14. Until polars releases, `.cargo/audit.toml` ignores the remaining 13 zstd-safe and zstd advisories, with a reason for each. Three of them are vulnerabilities and ten are `unsound` warnings: - 0391 is reachable. polars-parquet reuses one zstd context per column chunk through `Decoder::with_context`, so a crafted file can make a page start with leftover output from an earlier page. The context lives only as long as that column chunk's reader, so the leftover data always comes from the same file. - 0403 affects only `stream::write::Decoder`, and polars uses the read `Decoder`. - The other eleven need zstd features that are off (`experimental`, `seekable`, `zstdmt`), or APIs that neither polars nor the `zstd` crate's stream and bulk code call. ## User-facing changes (Release notes) ## Additional notes <!-- Optional. Examples: - fixes #123 - closes #456 - related #789 Anything else reviewers should know. Remove this section if not needed. --> |
||
|
|
131b82a921 |
fix(std/dirs): make dirs drop a no-op when only one directory is left (#19355)
## Description `dirs drop` says it has no effect when there's only one directory in the list. But it still called `_fetch -1 --forget_current --always_cd`, which `cd`s to whatever is saved in that one slot. That slot isn't updated when you plain `cd` somewhere, so it usually still holds the directory nushell started in (or wherever the module was loaded). So `cd /tmp; dirs drop` would jump you back to your home dir or the startup dir. Now `dirs drop` returns early when the list has one entry or less, so it really does nothing, as the help says. Dropping with two or more entries works like before. Added `dirs_drop_single_entry` to `crates/nu-std/tests/test_dirs.nu`. It fails on main (PWD goes back to the base dir) and passes with the fix. ## User-facing changes (Release notes) Fixed `dirs drop` changing the working directory when the directory list has only one entry. It now leaves you where you are. ## Additional notes Fixes #12578 |
||
|
|
36c057c973 |
feat(docs): document $env.cmd_duration_ms and how to check for startup with it (#19350)
<!-- 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 ref [discord](https://discord.com/channels/601130461678272522/615329862395101194/1564256320184524906) Make the way to check for startup (useful when creating a custom prompt) discoverable. ## User-facing changes (Release notes) Document in `config nu --doc` the `$env.CMD_DURATION_MS` variable and how to use it to determine startup. |
||
|
|
faa166c374 |
Don't let Tab's partial completion drop suggestions that replace a different span (#19344)
## Description With `completions.partial` on (the default), Tab inserts the prefix that every suggestion shares. nushell worked that prefix out itself in `partial_of`, using only the suggestions with the first suggestion's span. An extern's subcommands replace the whole `foo re`, while a file replaces only `re`. So when a file sorted first, it was the shared prefix on its own. In a directory with `README.md`, `foo re<Tab>` became `foo README.md` once the background completer answered. With a module of `git <sub>` externs loaded, `git re<Tab>` became `git README.md`. When the completer passes no prefix, reedline derives one. Since nushell/reedline#1261, which main picked up in #19342, reedline lines up suggestions that replace different spans and keeps only what all of them share. Any prefix `partial_of` returned was one reedline derives anyway, so this PR deletes `partial_of` and lets reedline decide. The stale fallback dropped a group too. After `foo r<Tab>`, Esc, `e<Tab>`, Tab answers at once from the cached `foo r` answer, narrowed to `foo re`. The narrowing kept only the suggestions sharing the last suggestion's span. Those were the subcommands, so reedline inserted `foo reb` and `README.md` was gone. Now a cached answer that mixes spans gives no fallback. Until the fresh answer arrives, Tab inserts nothing and an open menu keeps its last answer, as on the first Tab of a line. ## User-facing changes (Release notes) Fixed Tab replacing a partly typed subcommand with a file name, such as `git re<Tab>` becoming `git README.md` in a directory that has a `README.md`. ## Additional notes <!-- Optional. Examples: - fixes #123 - closes #456 - related #789 Anything else reviewers should know. Remove this section if not needed. --> |
||
|
|
706259d6f8 |
Shorter table escape sequences, and a new ansi opt command (#19340)
## Description With the default colors, nushell's tables repeat escape sequences that change nothing on screen. Every border character is written as `\e[39m│\e[0m`, and a cell colored with the default foreground is wrapped in `\e[39m…\e[0m`, which leaves two resets after every file name in `ls`. This PR does two things: 1. **Plain borders.** With the default separator style (`separator: default`), nu-table keeps the color only on the borders that start a line: every horizontal line, and the first vertical border of each row. It writes the other borders without color, and the cells colored only with the default foreground too. Every line looks the same, with fewer bytes: 19% fewer for `ls`, 28% for a nested table, 43% for a 300-row stream. 2. **`ansi opt`.** A new command shortens the escape sequences in a string, binary or byte stream with the [ansiopt](https://github.com/fdncred/ansiopt) optimizer, without changing what a terminal shows. It can also report what it changed. Nushell doesn't rewrite anything on its own at print time. Nothing but table rendering changes, and only in a way the screen can't show, for a whole table and for a line taken out of one. ### Before and After ``` main \e[39m╭───┬──────╮\e[0m \e[39m│\e[0m \e[1;32m#\e[0m \e[39m│\e[0m \e[1;32mname\e[0m \e[39m│\e[0m \e[39m├───┼──────┤\e[0m \e[39m│\e[0m \e[1;32m0\e[0m \e[39m│\e[0m \e[39m\e[38;5;81msrc\e[0m\e[0m \e[39m│\e[0m \e[39m╰───┴──────╯\e[0m branch \e[39m╭───┬──────╮\e[0m \e[39m│\e[0m \e[1;32m#\e[0m │ \e[1;32mname\e[0m │ \e[39m├───┼──────┤\e[0m \e[39m│\e[0m \e[1;32m0\e[0m │ \e[38;5;81msrc\e[0m │ \e[39m╰───┴──────╯\e[0m ``` `ansi opt` on a string: ```nushell > $'(ansi reset)(ansi reset)(ansi red)hi(ansi reset)' | ansi opt --show \e[;31mhi\e[m > "\e[0m\e[31m──── \e[0m \e[31m────\e[0m" | ansi opt --visual --rep --show \e[;31m─\e[3b ─\e[3b\e[m > $'(ansi reset)(ansi reset)(ansi red)hi(ansi reset)' | ansi opt --explain ╭───┬──────────┬─────────┬───────────┬─────────┬───────────────────╮ │ # │ sequence │ meaning │ outcome │ output │ why │ ├───┼──────────┼─────────┼───────────┼─────────┼───────────────────┤ │ 0 │ \e[0m │ reset │ folded │ \e[;31m │ │ │ 1 │ \e[0m │ reset │ no effect │ │ already in effect │ │ 2 │ \e[31m │ fg red │ folded │ \e[;31m │ │ │ 3 │ \e[0m │ reset │ folded │ \e[m │ │ ╰───┴──────────┴─────────┴───────────┴─────────┴───────────────────╯ ``` ## User-facing changes (Release notes) - Tables with the default colors are written with fewer escape sequences: about a fifth fewer bytes for `ls` and records, and up to two fifths for longer tables. They look exactly the same, also when a line is taken out of a table and printed on its own. - New `ansi opt` command, which shortens the ANSI escape sequences in a string, binary or byte stream without changing what a terminal shows. `--stats`, `--diff`, `--explain`, `--hotspot`, `--show` and `--html` return what it changed instead, as records, tables or an HTML report. ## Additional notes |
||
|
|
f3cc93329c |
fix(try): drain a piped stderr before collecting an external (#19339)
## Description
`ignore`, `save`, `complete` and `tee` ask for an external's stdout and
stderr on their own pipes (`PipeSeparate`), so an external at the end of
a `try` block that is piped into one of them gets a stderr pipe too. A
`try` with `catch` or `finally` then collects the block's output with
`try-collect`, and `collect` calls `into_value` on the child stream.
`ChildProcess::into_bytes` refuses a child that still has a stderr pipe
("internal error: stderr should not exist"), so the error went to
`catch` even though the external exited 0.
A value can't carry a separate stderr, so `try-collect` now leaves such
a child as a stream instead of turning it into a value:
- `ChildProcess::buffer_output` reads stdout and stderr to the end
(stderr on its own thread, with the reader that `wait_with_output`
already used, now shared as `collect_pipes`), waits for the child,
checks its exit status the way `into_bytes` does, and puts the output
back so it can still be read. `do` already rebuilds a finished child
from buffers in a similar way.
- `try_collect` in `eval_ir.rs` does this for a child with a stderr pipe
and passes it on, so the command after the `try` gets stdout, stderr and
the exit status as if there were no `try`. Failing externals still error
inside the `try`, so `catch` still runs for them. Everything else still
goes through `collect`.
- The pipes are read before the pipefail exit check. Waiting for the
exit first hung on a child that filled its stderr pipe.
- `finally` gets a copy of the result, and only a value can be copied.
So at `begin-finally`, a child passed on like this becomes its stdout,
and its stderr goes to the block's stderr, the same as for `let x =
^external`.
`into_bytes` keeps its check: a caller that wants a value can't keep
stderr.
## User-facing changes (Release notes)
Fixed `try { ^external } catch { ... } | ignore` (also with `save
--stderr`, `complete`, `tee --stderr`, and inside `do` or a custom
command) running the `catch` block with "internal error: stderr should
not exist" when the external succeeded. The external's stderr now
reaches the next command the same way it does without the `try`.
With `finally`, the `try` doesn't fail that way anymore either, but the
result is still turned into a value so `finally` can see it. The next
command gets the external's stdout as a value and its stderr is printed,
like for `let x = ^external`. So `save --stderr` after `try ... finally`
gets an empty stderr, and `complete` still says it only works with
external commands.
## Additional notes
Fixes #19335
Tests in `tests/shell/mod.rs`:
- `try_catch_keeps_a_piped_stderr_of_a_successful_external` runs `try {
X } catch { print caught } | C` and `X | C` and checks that stdout and
stderr match. `C` is each of `ignore`, `ignore --stdout`, `ignore
--stderr`, `complete`, and `save --stderr`. `X` is either a short
stdout+stderr external or one that writes 200KB to stderr.
- `try_catch_piped_into_ignore_catches_only_a_failing_external` covers
the same inside a `def`, `finally` with and without `catch`, and a
failing external that is still caught.
On main, 8 of the 14 cases fail, the 5 with 200KB of stderr hang until
killed, and only the failing-external case passes.
- `cargo test --test tests`: 2421 passed
- `cargo test -p nu-protocol -p nu-engine -p nu-cmd-lang`, `cargo test
-p nu-command -- complete ignore save tee try_`: passed
- `cargo fmt --all -- --check`, `cargo clippy -p nu-engine -p
nu-protocol -p nu-cmd-lang --all-targets --no-deps -- -D warnings`, and
`cargo check -p nu-engine --no-default-features` with `-D warnings`:
clean (toolchain 1.99.1)
More than 64KB of stdout with no stderr pipe still hangs with pipefail
on, as on 0.116.2; that path isn't touched here.
|
||
|
|
75eeb21fa6 |
chore: bump reedline to c8d81b2 (#19342)
## Description Bumps reedline to `c8d81b2`, five PRs past `39db5e3`: - nushell/reedline#1256 `fix(vi): repaint whenever the mode changes` - nushell/reedline#1244 `feat(hints): let hinters and highlighters handle hints before auto-pair closers` - nushell/reedline#1261 `fix(menu): take the partial completion across all suggestion spans` - nushell/reedline#1263 `fix(engine): treat Ctrl+J as a line ending when draining the input batch` - nushell/reedline#1257 `feat(external_printer): ungate the printer and commit messages in one frame` `#1244` replaces the unreleased `#1239` behavior with hooks that default to the last release, so hints before auto-pair closers come back with nushell/nushell#19199 `#1261` only changes the partial reedline derives itself, and nushell passes its own, so `foo re<Tab>` keeps its current behavior until the nushell side follows ### User-facing changes (Release notes) - Fixed the vi prompt indicator not switching to insert on `a`, `A` or `I` when the cursor does not move. - Fixed piped input with several LF-terminated lines dropping every line after the first. |
||
|
|
6d47cd0e72 |
chore: bump ctutils, tokio and clipboard-win to clear the RustSec audit (#19343)
## Description Clears the security audit, which fails on main since 2026-10-23 - `ctutils` 0.4.2 -> 0.4.5: RUSTSEC-2026-0385, non-constant-time comparisons. Only reaches `nu_plugin_polars`. - `tokio` 1.53.1 -> 1.54.1: RUSTSEC-2026-0386, `AsyncFd::new` unsound. - `clipboard-win` 5.4.1 -> 5.4.3: 5.4.1 is yanked. ## User-facing changes (Release notes) None. |
||
|
|
23392cdc47 |
fix(dc-glob): honor negated character classes (#19309)
## Description With the experimental dc-glob backend enabled, `glob '[!f]*'` selects `foo` instead of `bar` because `!` is treated as a member of a positive character class. Recognize a leading `!` as negation and invert the existing character membership check after case handling. A later `!` remains literal. Regression tests cover file traversal, ranges, Unicode, component boundaries, and the existing ASCII-only ignore-case behavior. Partially addresses #19256: this fixes negated character classes only. The invalid-pattern and relative-path traversal cases remain separate. ## User-facing changes (Release notes) Fixed negated character classes in the experimental dc-glob backend: patterns such as `[!f]*` now exclude names beginning with `f`. ## Additional notes Validation on Linux with Rust 1.97.1: - Both new regression tests fail against the unchanged base implementation. - `cargo test --locked --profile ci -p nu-glob`: 82 unit tests and 6 doctests pass; 1 doctest ignored. - `cargo fmt --all -- --check`, `cargo nuclippy`, and `typos` pass. - Built `nu` with `cargo build --locked --profile ci -p nu` and checked an actual `foo`/`bar` directory: both the legacy and dc-glob backends return `[bar]`. Full workspace tests and cross-platform CI were not run locally. AI assistance: Codex assisted the investigation, implementation, tests, and an independent agent review of the patch. --------- Co-authored-by: wangjianjun <passionworkeer@users.noreply.github.com> |
||
|
|
b1a32d194f |
Reset stale REPL interrupts before running a new command (#19337)
## Description Related to #18989 and follows up on #19163 The REPL resets interrupt signals at the start of each iteration, before evaluating the prompt An interrupted prompt can leave the signal set for the transient prompt, line editor callbacks, and the next command - Recover interrupted signals after normal prompt evaluation, before constructing the transient prompt and entering the line editor - Keep command-boundary recovery before pre-execution hooks for interruptions from editor callbacks - Only reset at these recovery points when interrupted, avoiding extra plugin Reset messages on normal commands - Keep normal prompt errors visible and retain cancellation of running commands - Extend the existing regression test to cover the interrupted prompt result, transient prompt, custom completion, and a subsequent editor interrupt followed by a hook and command - Disable all shell-integration flags in the regression test and explain why its expressions use `match` to reach signal checks ### Reproduction - Start an interactive session with a slow prompt closure such as `{ sleep 1min; "prompt" }` - Press Ctrl-C while the prompt is evaluating - Try a custom completer that polls interruption signals, or a transient prompt closure containing `sleep` - Without prompt-boundary recovery, these callbacks inherit the interrupt until the next command is submitted - Enter `match 1 { 1 => 42 }` - Without command-boundary recovery, the command and its pre-execution hooks can inherit an interrupt from the prompt or editor - With both recovery points, the transient prompt, completion, hook, and new command run normally The macOS PTY probe compared the previous PR commit `0c3e8f749` with the updated code The previous PR binary reported normal and transient prompt interruption errors and offered no custom completion before Enter The updated binary reported only the normal prompt interruption, offered completion before Enter, and rendered the transient prompt The next hook and command succeeded in both probes, including after a separate SIGINT while waiting for input A separate PTY probe kept a background thread job and a frozen external process registered during prompt interruption and verified cancellation of a later foreground command ## User-facing changes (Release notes) Fixed stale prompt interrupts affecting completions, transient prompts, and the next interactive command with its pre-execution hooks ## Validation Local checks on macOS aarch64 with Rust 1.97.1 at `2bcf4099e` | Command | Result | | --- | --- | | `cargo test --locked --profile ci -p nu-cli --lib -- command_after_interrupted_prompt_runs_hooks_and_command` | Fails without prompt-boundary recovery at the transient prompt assertion, passes with the fix | | `cargo build --locked --profile ci --bin nu` | Passed | | `cargo test --locked --profile ci -p nu-cli --no-fail-fast` | 200 unit tests and 295 integration tests passed, 2 ignored | | `cargo test --locked --profile ci --test tests -- shell::` | 341 passed, 6 ignored, including all 29 background-job tests | | `cargo test --locked --profile ci --bin nu -- signals::` | 3 passed | | `cargo nuclippy` | Passed | | `cargo check --locked --profile ci --no-default-features --bin nu` | Passed | | `cargo fmt --all` and `cargo fmt --all --check` | Passed | | `typos` 1.51.1 | Passed | | `git diff --check` | Passed | Manual PTY checks passed for prompt errors remaining visible, completion and transient-prompt recovery before Enter, subsequent hook and command execution, editor-interrupt recovery, background and frozen job preservation, and foreground cancellation The regression test emitted no shell-integration OSC or application-mode reset sequences ## Additional notes The command-boundary recovery retains a short race for a SIGINT arriving after Enter but before the reset This is a trade-off to recover editor interruptions, not a claim that the race is eliminated One initial baseline PTY launch in this follow-up timed out after 30 seconds without output, while the rerun and updated-binary probes passed The earlier validation also recorded one 60-second PTY startup timeout The causes were not established and the passing reruns do not erase those observations This reproduction did not demonstrate actual job deletion, so this PR does not claim to resolve every scenario in #18989 or close that issue Windows and Linux runtime validation is deferred to GitHub CI and is not included in the local results above |
||
|
|
1cc2a97be3 |
fix(cd): resolve Windows drive-relative paths like d: the way cmd does (#19332)
## Description On Windows, `cd d:` didn't work because `d:` is a drive-relative path and nu just joined it onto the current directory. This makes nu handle drive-relative paths (`d:`, `d:foo`, `d:..`) the way cmd does. It's one helper, `nu_path::resolve_drive_relative`, used by both `cd` and auto-cd: - If it's the same drive as `$env.PWD`, it resolves against `$env.PWD`. So `cd c:` in `C:\work` stays in `C:\work`, and `cd c:sub` goes to `C:\work\sub`. - If it's another drive, you end up in that drive's current directory inherited from the parent process, or its root. `cd -P` follows the same rule, and errors show the path as you typed it. ## User-facing changes (Release notes) On Windows, `cd d:`, `cd d:folder` and just typing `d:` (auto-cd) now work. If you're already on that drive you stay where you are. Otherwise you land in that drive's current directory from the parent shell, or its root. ## Additional notes Refs #13091 Used Claude Code to draft this change; I reviewed the diff and the test results. --------- Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com> |
||
|
|
e68ab52e43 |
Add generate completions to auto-generate extern definitions, with completions, from carapace, zsh, fish, man pages and --help (#19314)
## Description Nushell checks a call to an internal command before it runs, but an external command only gets that once someone writes an `extern` for it, flag by flag, and completions only once someone writes a completer for it. Other tools already describe thousands of commands: carapace specs, fish and zsh completion files, man pages, and each command's `--help`. `generate completions <command>` reads one of them and returns the text of a module of `export extern` definitions, with completer commands. You save that text and `use` or `source` it, or save it in an autoload dir. For `use`, the file needs a name other than the tool's, such as `git-completions.nu`, because `use` names the module after the file and a module can't export an extern with its own name. - carapace (`carapace <tool> export`), fish and zsh give the whole subcommand tree. man and `--help` give the flags of the named command, so `generate completions "git status"` reads `man git-status` or `git status --help`. - Without `--source`, the first source that knows any flags wins, in the order carapace, fish, zsh, man, help. `--source all` merges every source that knows any flags. When sources disagree, the earlier source wins. A flag they disagree on taking a value becomes a switch, and a flag any source says takes an optional value is left undeclared. - Piped text is read as the source `--source` names, as in `^git status -h | generate completions "git status" --source help`. - A signature can't declare flags with an optional value (`--color[=when]`) or single-dash long options (`-name`). Those are listed in each extern's extra description, and they still reach the tool. With `@complete external`, an external completer like carapace also lists the flags the signature declares, so flag completion showed each of them twice. Flag-name completion now drops command-wide suggestions that repeat a declared flag. ## User-facing changes (Release notes) - The new `generate completions` command writes `extern` definitions for an external command from its carapace spec, fish or zsh completions, man page or `--help` text, and `--source all` merges what every source knows: ```nushell generate completions git | save ($nu.user-autoload-dirs | first | path join git-completions.nu) ``` The module completes flag values and arguments the source knows about: fixed lists, commands that fish runs (git branches, remotes, tags), shared lists such as users and hosts, and, for tools built with cobra such as gh, docker and kubectl, the tool's own answers. - Flag-name completion no longer lists a flag twice when an extern with `@complete external` declares it and the external completer lists it too. ## Additional notes - Every module generated from fish's 1,070 completion files (782 modules, 186 with completers), zsh's 966 (681 modules) and Homebrew's 139 zsh files (129 modules) passes `nu-check --as-module`. So does every module from each source for git, ssh, make, rg, gh, tar, brew, curl, cargo, kubectl and docker, and from `--source all`. - `generate completions` refuses a command named like a nushell keyword (fish ships completions for `if`, `source`, `while`), since an extern can't have that name. - bash and PowerShell aren't sources. bash completions are code that mostly calls `_parse_help` on `--help`, which the help source already reads, and PowerShell's completers for native commands are script blocks registered at runtime. - The help source runs `<command> --help` with no input, the man source runs `man` with `MANPAGER=cat`, and a tool with a `completion` subcommand is asked `<tool> __complete ""` to find out whether it's built with cobra. |
||
|
|
8b3ce32f1b |
fix: don't rewrite path separators for external args that merely contain ... (#19333)
## Description `expand_ndots_safe` decided to run `expand_ndots` whenever the argument contained the substring `...`. `expand_ndots` normalizes the whole path, so on Windows an argument such as `origin/main...` (a git revision range) came out as `origin\main...`, breaking `git diff --name-only origin/main...`. Now n-dots expansion only runs when a whole path component (split on `/` or `\`) consists solely of 3+ dots (e.g. `.../foo`, `a/.../b`). `is_ndots` was hoisted from `expand_ndots` to module level to be shared. The `://` and `./` exclusions are unchanged. ## Before / after (Windows) ``` > cmd /c echo origin/main... origin\main... # before origin/main... # after > cmd /c echo a/b/... a\b\..\.. # unchanged (real n-dots component) ``` ## Tests - Added `dots_inside_component_untouched` in `nu-path` (`origin/main...`, `a.../b`). - `cargo test -p nu-path`: 68 passed; `cargo test --test tests -- dots external`: 158 passed. - `cargo fmt --all`, `cargo clippy -p nu-path --all-targets -- -D warnings -D clippy::unwrap_used` clean. ## User-facing changes (Release notes) External command arguments containing `...` inside a path component (e.g. `origin/main...`) are no longer rewritten with backslashes on Windows. ## Additional notes Fixes #16858 Used Claude Code to draft this change; I reviewed the diff and the test results. --------- Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com> |
||
|
|
a0b69c9f99 |
uniq: add --keep-last, matching uniq-by (#19326)
## Description
`uniq-by` has a `--keep-last` switch ("return the last occurrence of
each
unique value instead of the first"), but plain `uniq` never got the same
flag -- even though the shared `uniq()` function both commands call
already reads the `"keep-last"` flag unconditionally. Because `Uniq`'s
`signature()` never declared it, the parser wouldn't even let you type
`uniq --keep-last`.
This adds the same `--keep-last` switch to `uniq`, copying `uniq-by`'s
existing declaration. No new logic -- the shared `uniq()` function
already
implements the behavior. Also skips the sqlite `SELECT DISTINCT`
pushdown
optimization when the flag is set, since that pushdown can't honor "last
occurrence" semantics.
## User-facing changes (Release notes)
- Added a `--keep-last`/`-l` flag to `uniq`, matching `uniq-by`, to keep
the last occurrence of each duplicate value instead of the first.
## Additional notes
n/a
|
||
|
|
c77c34bc93 |
Add @structured attribute so an extern can return data (#19316)
## Description
Getting data out of an external tool means remembering its JSON flag and
piping it through `from json`, every time. `@structured [args] { decode
}` puts that in the extern once:
```nushell
@structured [--json=v2] { from json | get formulae }
extern "brew outdated" []
brew outdated | where pinned == false # nu runs `brew outdated --json=v2` and decodes it
brew outdated # brew's own text, as before
```
### Example
With the `@structured` in the script above:
```nushell
> brew outdated
brotli (1.2.0_1) < 1.2.1
node (26.12.0) < 26.12.1
pspg (5.8.16) < 5.9.0
ruby (4.0.7_1) < 4.0.8
```
But when you pipe it:
```nushell
> brew outdated | where pinned == false
╭───┬────────┬────────────────────┬─────────────────┬────────┬────────────────╮
│ # │ name │ installed_versions │ current_version │ pinned │ pinned_version │
├───┼────────┼────────────────────┼─────────────────┼────────┼────────────────┤
│ 0 │ brotli │ ╭───┬─────────╮ │ 1.2.1 │ false │ │
│ │ │ │ 0 │ 1.2.0_1 │ │ │ │ │
│ │ │ ╰───┴─────────╯ │ │ │ │
│ 1 │ node │ ╭───┬─────────╮ │ 26.12.1 │ false │ │
│ │ │ │ 0 │ 26.12.0 │ │ │ │ │
│ │ │ ╰───┴─────────╯ │ │ │ │
│ 2 │ pspg │ ╭───┬────────╮ │ 5.9.0 │ false │ │
│ │ │ │ 0 │ 5.8.16 │ │ │ │ │
│ │ │ ╰───┴────────╯ │ │ │ │
│ 3 │ ruby │ ╭───┬─────────╮ │ 4.0.8 │ false │ │
│ │ │ │ 0 │ 4.0.7_1 │ │ │ │ │
│ │ │ ╰───┴─────────╯ │ │ │ │
╰───┴────────┴────────────────────┴─────────────────┴────────┴────────────────╯
```
## User-facing changes (Release notes)
- The new `@structured [args] { decode }` attribute lets an extern
return data. When nushell uses the output as data (piped into an
internal command, or saved with `let`), it adds the args to the call and
decodes the output with the block. At the terminal, through `print`, in
a file or piped into another external command, the tool's own output is
unchanged:
```nushell
@structured [--porcelain] { lines | parse --regex '^(?<status>..)
(?<file>.+)$' }
extern "git status" []
git status | where status =~ M | get file # runs `git status
--porcelain` and parses it
git status # git's own text
```
When you run the extern by itself:
```nushell
> git status
On branch extern_structured
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: crates/nu-cli/src/commands/print.rs
modified: crates/nu-cmd-lang/src/core_commands/attr/mod.rs
modified: crates/nu-cmd-lang/src/core_commands/do_.rs
modified: crates/nu-cmd-lang/src/core_commands/ignore.rs
Untracked files:
(use "git add <file>..." to include in what will be committed)
crates/nu-cmd-lang/src/core_commands/attr/structured.rs
crates/nu-command/tests/commands/attr_structured.rs
no changes added to commit (use "git add" and/or "git commit -a")
```
But when you pipe it, it's now able to be converted to nushell data.
```nushell
> git status | where status =~ M
╭────┬────────┬──────────────────────────────────────────────────╮
│ # │ status │ file │
├────┼────────┼──────────────────────────────────────────────────┤
│ 0 │ M │ crates/nu-cli/src/commands/print.rs │
│ 1 │ M │ crates/nu-cmd-lang/src/core_commands/attr/mod.rs │
│ 2 │ M │ crates/nu-cmd-lang/src/core_commands/do_.rs │
│ 3 │ M │ crates/nu-cmd-lang/src/core_commands/ignore.rs │
╰────┴────────┴──────────────────────────────────────────────────╯
```
## Additional notes
- When the tool fails, the pipeline stops with the tool's own error
output and exit code, as `^tool --json | from json` does today.
- The user's arguments come after the structured args, so a flag that
picks another output format (`kubectl get pods -o wide | lines`) wins
and the decode fails. `^kubectl get pods -o wide` runs as written. When
an extern has more than one `@structured`, the last one is used. Both
are in `help attr structured`.
- `tee` gets the tool's own output and passes that text on, so `brew
outdated | tee { save -f log.txt } | lines` works on brew's text.
- Only errors raised while the decode block runs get the label at the
call. An error from a stream the block returns, read later, points at
the block only.
- `brew outdated | do { ^cat }` still decodes: the next command is `do`,
which doesn't look into its block for `pipe_redirection()`.
- `OutDest` and `RedirectMode` in `nu-protocol` each gain a variant, so
an exhaustive `match` on either outside this repo needs a `PipeRaw` arm.
|
||
|
|
d2340dc1c5 |
Remove file accidentially committed (#19331)
<!-- 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 just remove a file accidentally committed <!-- 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. --> |
||
|
|
02d39b88e9 |
Add extern --strict to reject undeclared flags (#19313)
## Description
An `extern` signature drives completions, but it doesn't guard anything.
`extern "git status" [--short(-s)]; git status --shrt` passes `--shrt`
to git, and git prints its own usage error. That's because externs
accept unknown arguments, so nushell can wrap a tool without declaring
every flag it has.
`extern --strict` (and `export extern --strict`) turns a flag the
signature doesn't declare into a parse error, with the "Did you mean"
hint that internal commands already give. Everything else an extern
accepts still works: positional arguments, `--` and the arguments after
it all reach the tool. `--help` is always allowed, so `git status
--help` still shows git's help. `-h` isn't exempt, since it means
something else for some tools (`ls -h`, `grep -h`).
### Before & After
| Command | Before PR | After PR |
| --- | --- | --- |
| `extern --strict "git status" [--short(-s)]; git status --shrt` |
``The `extern` command doesn't have flag `strict`.`` | ``The `git
status` command doesn't have flag `shrt`.``, help: ``Did you mean:
`--short`?`` |
| `extern --strict "git status" [--short(-s)]; git status -x` | same
`strict` error | ``The `git status` command doesn't have flag `-x`.`` |
| `extern --strict "git status" [--short(-s)]; git status -s -- --shrt`
| same `strict` error | runs `git status -s -- --shrt` |
| `extern --strict "git status" [--short(-s)]; git status --help` | same
`strict` error | git's help |
| `module g { export extern --strict "git status" [--short(-s)] }; use g
"git status"; git status --shrt` | same `strict` error | ``The `git
status` command doesn't have flag `shrt`.`` |
| `extern "git status" [--short(-s)]; git status --shrt` | git: ``error:
unknown option `shrt'`` | same |
| `extern --strict printf []; printf "%s\|" -10` | same `strict` error |
`-10\|` |
| `extern --strict printf []; let n = 3; let f = "x"; printf "%s\|" -$n
-($n) --($f)` | same `strict` error | `-$n\|-3\|--x\|` |
| `extern printf [--x: string]; printf "%s\|" --x (ls --bogus) hello` |
`--x\|hello\|` | ``The `ls` command doesn't have flag `bogus`.`` |
| `def --wrapped w [--x: string, ...rest] { $rest \| to nuon }; w --x
(ls --bogus) hello` | `[--x, hello]` | ``The `ls` command doesn't have
flag `bogus`.`` |
## User-facing changes (Release notes)
- `extern --strict` makes a flag that the signature doesn't declare a
parse error, with a "Did you mean" hint. `--`, the arguments after it,
and `--help` still reach the external command.
- An unknown flag inside the value of a declared flag, as in `cmd --x
(ls --bogus)`, is now reported for externs and `def --wrapped` commands.
Before, the error was dropped and `--x` reached the command without its
value.
## Additional notes
<!--
Optional.
Examples:
- fixes #123
- closes #456
- related #789
Anything else reviewers should know.
Remove this section if not needed.
-->
|
||
|
|
25639896e0 |
Allow Custom Types to be used in type signatures (#19311)
## Description
Changes the way that custom types are exposed in order to allow them to
be used in type signatures. This also enabled them to be resolved
correctly in the LSP.
## User-facing changes (Release notes)
- Custom types can now be used within type signatures. For plugins,
custom types for all installed plugins can be use. They will resolve
appropriately in the Nushell LSP. The following example show how to set
the return type for a command
```
def f [v: semver]: semver -> semver { $v } │
def ls-df [ ]: nothing -> polars_dataframe {
ls | polars into-df
}
```
|
||
|
|
89e6efe441 |
fix(nu-mcp): keep $history indices stable, run evaluations one at a time, and correct stale guidance in the MCP instructions and AGENTS.md (#19318)
## Description Once `$history` was full, each new evaluation shifted every older entry down by one. `History::push` returned the buffer length after evicting, so an index from an earlier response could point at a later result, while the instructions promised "indices do not shift, older ones simply become unavailable". This PR makes that promise true: indices only increase, and an evicted index reads as `null`. `push` also evicts until the buffer fits the limit instead of dropping one entry per push, so lowering `NU_MCP_HISTORY_LIMIT` trims `$history` to the new limit. Two `evaluate` calls sent at once (agents send parallel tool calls) each forked the same state, and the one that finished last overwrote the other. Both responses reported the same `history_index`, and the other call's `$history` entry and `$env` changes were lost. Evaluations now run one at a time, like lines typed into a REPL: a lock is held from fork to commit and released early when an evaluation is promoted to a background job. `list_commands` and `command_help` don't wait for it. The rest of the text `nu --mcp` sends to agents (`instructions.md`, `evaluate_tool.md`, and the `list_commands` / `command_help` descriptions) also gave advice that nushell contradicts. It said `ls **/*` walks hidden directories and `glob` avoids them, when the reverse is true. It used a `job spawn --tag` flag that was renamed in #17496, and said `command_help` shows input/output types, which it doesn't. The `evaluate` tool description still told agents to avoid large output, which contradicts the server instructions sent in the same session. This PR rewrites those passages to match nushell, tones down the all-caps "THE RULE" section while keeping the rule and its reason, and fills in the two short tool descriptions with their real output format and limits. In `AGENTS.md`, it fixes the claim that `cargo nuclippy-tests` runs all tests (it runs clippy), says how integration-test targets are named in crates without a `tests` target, states three wordy or hedged rules more plainly, and fixes a typo. ## User-facing changes (Release notes) - In `nu --mcp`, `$history` indices no longer shift when old entries are evicted. An evicted index reads as `null`, and `$history | length` counts every result stored in the session. Lowering `NU_MCP_HISTORY_LIMIT` now trims `$history` to the new limit. - `nu --mcp` now runs `evaluate` calls one at a time. Before, two calls sent together could get the same `history_index`, and one call's `$history` entry and `$env` changes were lost. - The MCP server's instructions and tool descriptions now match nushell's behavior for `ls` vs `glob` on hidden directories, `job spawn --description`, `command_help` output, and `\u{...}` escapes. - The `evaluate` tool description no longer tells agents to avoid large output. Output over the limit already comes back as a `note` pointing at `$history`. ## Additional notes <!-- Optional. Examples: - fixes #123 - closes #456 - related #789 Anything else reviewers should know. Remove this section if not needed. --> |
||
|
|
de7d7584cb | Added the local_socket feature for nu-plugin-test-support for formats… (#19319) | ||
|
|
a12aca2606 |
Fix polars test breakages (#19317)
## Description The local_socket feature needed to be added to the nu-plugin-test-support dep. |
||
|
|
d1064f1ae1 |
fix(print): surface external failures instead of masking exit code (#19227) (#19260)
## Description Fixes #19227. `print` ignored failures of external commands because it called `ignore_error(true)` on the child's byte streams, so a pipeline such as a failing external command piped into `print` exited with 0 while the same failure from an internal command exited with 1. This removes the suppression so non-zero exits propagate. Tests were added to `pipefail_feature` (`fail 30 | print`, `print --raw`, `print -e`) plus `pipefail_print_keeps_output_before_failure` and `pipefail_print_stderr_keeps_output_before_failure`, which check that output still reaches stdout / stderr before the failure exit code. `^cmd | print <args>` still drops the piped input without waiting on the child, so with pipefail off it still exits 0, the same as `| ignore`. Tests run: `cargo test --test tests -- pipefail_feature`, `cargo clippy --tests`, `cargo fmt --all -- --check`. ## User-facing changes (Release notes) Fixed an issue where `print` hid the failure of an external command: a failing external command piped into `print` now makes the pipeline fail with its non-zero exit code instead of exiting with 0. This is a behavior change for scripts that relied on the old result, for example `^grep pat file | print` with no match now errors, and `do -i { ^false } | print` now fails like `do -i { ^false } | collect` already does. ## Additional notes fixes #19227 |
||
|
|
f196eaf8a7 |
fix(table): shrink the widest columns first and honor width priorities everywhere (#19303)
## Description Since #19007, `table --expand` squeezed short columns to 4 characters whenever another column held a nested table. The nested-table column took every spare character before any other column grew, so an `env` listing printed `SOME_BIG_SESSION_ENV_VAR` as seven 4-character lines. `table --expand` also ignored `metadata set --table-width-priority-columns`. So did `table` at 120 columns or less, unless wrapping and header-on-separator were both on. An `env`-style listing with nested values, `table -e`, header on the separator, 100 wide: ```nushell $env.config.table.header_on_separator = true; [[key value]; [CLAUDE_CODE_CHILD_SESSION 1] [HOME /Users/fdncred] [PATH [/Users/fdncred/.local/bin /usr/local/bin /opt/homebrew/opt/python/libexec/bin /Users/fdncred/.cargo/bin /opt/homebrew/opt/uutils-coreutils/libexec/uubin]] [FPATH "/Users/fdncred/.grok/completions/zsh:/Users/fdncred/.zsh:/opt/homebrew/share/zsh/site-functions:/usr/local/share/zsh/site-functions"]] | table -e -w 100 ``` Before: ```nushell ╭─#─┬─key──┬─────────────────────────────────────────value─────────────────────────────────────────╮ │ 0 │ CLAU │ 1 │ │ │ DE_C │ │ │ │ ODE_ │ │ │ │ CHIL │ │ │ │ D_SE │ │ │ │ SSIO │ │ │ │ N │ │ │ 1 │ HOME │ /Users/fdncred │ │ 2 │ PATH │ ╭───┬──────────────────────────────────────────────────╮ │ │ │ │ │ 0 │ /Users/fdncred/.local/bin │ │ │ │ │ │ 1 │ /usr/local/bin │ │ │ │ │ │ 2 │ /opt/homebrew/opt/python/libexec/bin │ │ │ │ │ │ 3 │ /Users/fdncred/.cargo/bin │ │ │ │ │ │ 4 │ /opt/homebrew/opt/uutils-coreutils/libexec/uubin │ │ │ │ │ ╰───┴──────────────────────────────────────────────────╯ │ │ 3 │ FPAT │ /Users/fdncred/.grok/completions/zsh:/Users/fdncred/.zsh:/opt/homebrew/share/zsh/site │ │ │ H │ -functions:/ │ │ │ │ usr/local/share/zsh/site-functions │ ╰───┴──────┴───────────────────────────────────────────────────────────────────────────────────────╯ ``` After: ```nushell ╭─#─┬────────────key────────────┬──────────────────────────────value───────────────────────────────╮ │ 0 │ CLAUDE_CODE_CHILD_SESSION │ 1 │ │ 1 │ HOME │ /Users/fdncred │ │ 2 │ PATH │ ╭───┬──────────────────────────────────────────────────╮ │ │ │ │ │ 0 │ /Users/fdncred/.local/bin │ │ │ │ │ │ 1 │ /usr/local/bin │ │ │ │ │ │ 2 │ /opt/homebrew/opt/python/libexec/bin │ │ │ │ │ │ 3 │ /Users/fdncred/.cargo/bin │ │ │ │ │ │ 4 │ /opt/homebrew/opt/uutils-coreutils/libexec/uubin │ │ │ │ │ ╰───┴──────────────────────────────────────────────────╯ │ │ 3 │ FPATH │ /Users/fdncred/.grok/completions/zsh:/Users/fdncred/.zsh:/opt/ho │ │ │ │ mebrew/share/zsh/site-functions:/usr/local/share/zsh/site-functi │ │ │ │ ons │ ╰───┴───────────────────────────┴──────────────────────────────────────────────────────────────────╯ ``` A `plugin list`-shaped table, `table -e`, 120 wide: ```nushell [[name version status pid filename shell commands]; [dns 4.0.13-alpha.1 loaded null C:\Users\x\.cargo\bin\nu_plugin_dns.exe null [[name description]; ["dns query" "Perform a DNS query"]]] [file 0.27.0 loaded null C:\Users\x\.cargo\bin\nu_plugin_file.exe null [[name description]; [file "View file format information"]]]] | table -e -w 120 ``` Before: ```nushell ╭───┬──────┬────────────────┬────────┬─────┬──────────────────────────────────────────┬───────┬────────────────────────╮ │ # │ name │ version │ status │ pid │ filename │ shell │ commands │ ├───┼──────┼────────────────┼────────┼─────┼──────────────────────────────────────────┼───────┼────────────────────────┤ │ 0 │ dns │ 4.0.13-alpha.1 │ loaded │ │ C:\Users\x\.cargo\bin\nu_plugin_dns.exe │ │ ╭───┬───────────╮ │ │ │ │ │ │ │ │ │ │ # │ name │ │ │ │ │ │ │ │ │ │ ├───┼───────────┤ │ │ │ │ │ │ │ │ │ │ 0 │ dns query │ │ │ │ │ │ │ │ │ │ ╰───┴───────────╯ │ │ 1 │ file │ 0.27.0 │ loaded │ │ C:\Users\x\.cargo\bin\nu_plugin_file.exe │ │ ╭───┬──────┬─────────╮ │ │ │ │ │ │ │ │ │ │ # │ name │ descrip │ │ │ │ │ │ │ │ │ │ │ │ │ tion │ │ │ │ │ │ │ │ │ │ ├───┼──────┼─────────┤ │ │ │ │ │ │ │ │ │ │ 0 │ file │ View │ │ │ │ │ │ │ │ │ │ │ │ │ file │ │ │ │ │ │ │ │ │ │ │ │ │ format │ │ │ │ │ │ │ │ │ │ │ │ │ informa │ │ │ │ │ │ │ │ │ │ │ │ │ tion │ │ │ │ │ │ │ │ │ │ ╰───┴──────┴─────────╯ │ ╰───┴──────┴────────────────┴────────┴─────┴──────────────────────────────────────────┴───────┴────────────────────────╯ ``` After: ```nushell ╭───┬──────┬────────────────┬────────┬─────┬─────────────────────────────────┬───────┬─────────────────────────────────╮ │ # │ name │ version │ status │ pid │ filename │ shell │ commands │ ├───┼──────┼────────────────┼────────┼─────┼─────────────────────────────────┼───────┼─────────────────────────────────┤ │ 0 │ dns │ 4.0.13-alpha.1 │ loaded │ │ C:\Users\x\.cargo\bin\nu_plugin │ │ ╭───┬───────────┬─────────────╮ │ │ │ │ │ │ │ _dns.exe │ │ │ # │ name │ description │ │ │ │ │ │ │ │ │ │ ├───┼───────────┼─────────────┤ │ │ │ │ │ │ │ │ │ │ 0 │ dns query │ Perform a │ │ │ │ │ │ │ │ │ │ │ │ │ DNS query │ │ │ │ │ │ │ │ │ │ ╰───┴───────────┴─────────────╯ │ │ 1 │ file │ 0.27.0 │ loaded │ │ C:\Users\x\.cargo\bin\nu_plugin │ │ ╭───┬──────┬──────────────────╮ │ │ │ │ │ │ │ _file.exe │ │ │ # │ name │ description │ │ │ │ │ │ │ │ │ │ ├───┼──────┼──────────────────┤ │ │ │ │ │ │ │ │ │ │ 0 │ file │ View file format │ │ │ │ │ │ │ │ │ │ │ │ │ information │ │ │ │ │ │ │ │ │ │ ╰───┴──────┴──────────────────╯ │ ╰───┴──────┴────────────────┴────────┴─────┴─────────────────────────────────┴───────┴─────────────────────────────────╯ ``` A record with a 100-character key, `table -w 60`: ```nushell {("k" | fill -c k -w 100): 1, b: 2} | table -w 60 ``` Before: ```nushell ╭────────────────────────────────────────────────────┬─────╮ │ kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk │ ... │ │ kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk │ │ │ b │ ... │ ╰────────────────────────────────────────────────────┴─────╯ ``` After: ```nushell ╭──────────────────────────────────────────────────────┬───╮ │ kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk │ 1 │ │ kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk │ │ │ b │ 2 │ ╰──────────────────────────────────────────────────────┴───╯ ``` CJK headers with `header_on_separator`, `table -e`: This intentionally doesn't draw the characters on the headers, even when the setting is set to true, in order to avoid misaligned tables. (images convey this better below) ```nushell $env.config.table.header_on_separator = true; [[id 名前 inner]; [1 漢字 [[鍵 a]; [x 1]]]] | table -e ``` Before: <img width="1672" height="718" alt="image" src="https://github.com/user-attachments/assets/773cd8f2-9fe1-4185-bf0c-c0a1637e7deb" /> After: <img width="1672" height="924" alt="image" src="https://github.com/user-attachments/assets/09cdbc27-0425-4547-a8e2-902ff725e6dd" /> ## User-facing changes (Release notes) - `table` and `table --expand` shrink the widest columns first, so short columns such as keys, names and sizes keep their width next to long text or nested tables. - `metadata set --table-width-priority-columns`, which `ls` and `ps` also set, now works with `table --expand` and at every terminal width. A priority column shows wherever it would without the priority, and columns to its right hide to leave it up to a third of the table width. - `table --expand` draws a nested table whenever it fits, hiding columns to its right first and collapsing the nested table's own columns behind `...`, instead of showing `[table N rows]`. Nested tables no longer drop columns without a `...` marker. - Tables keep each visible column at least 10 characters wide (or its natural width), hiding columns from the right when they don't fit. Without `header_on_separator` this shows more columns on narrow terminals; with it, fewer, since columns are no longer squeezed to 4 characters. - Record keys wrap when a key is too long for the terminal, instead of hiding the values. - With `header_on_separator`, headers with CJK characters, emoji or Arabic ligatures are drawn in their own row, so the table border lines up. ## Additional notes <!-- Optional. Examples: - fixes #123 - closes #456 - related #789 Anything else reviewers should know. Remove this section if not needed. --> |
||
|
|
68451e6b28 |
build(deps): bump tango-bench from 0.8.0 to 0.9.0 (#19305)
Bumps [tango-bench](https://github.com/bazhenov/tango) from 0.8.0 to 0.9.0. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/bazhenov/tango/releases">tango-bench's releases</a>.</em></p> <blockquote> <h2>v0.9.0</h2> <h2>What's Changed</h2> <ul> <li>Add --strip-candidate/--strip-baseline to compare benchmarks from the same executable by <a href="https://github.com/bazhenov"><code>@bazhenov</code></a> in <a href="https://redirect.github.com/bazhenov/tango/pull/83">bazhenov/tango#83</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/bazhenov/tango/compare/v0.8.0...v0.9.0">https://github.com/bazhenov/tango/compare/v0.8.0...v0.9.0</a></p> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/bazhenov/tango/commit/6226638e0b40a094e87e83ffd5da5aa66ddee26a"><code>6226638</code></a> Release 0.9.0</li> <li><a href="https://github.com/bazhenov/tango/commit/1d033ad9dc51d9bd7865c3b60b9170acb7a75c7c"><code>1d033ad</code></a> Adding script to check how stable cputime is in GH CI</li> <li><a href="https://github.com/bazhenov/tango/commit/c8150c430a1348a9b81bcd52e3e5ff32c842f5cf"><code>c8150c4</code></a> Increasing number of iterations in cputime test</li> <li><a href="https://github.com/bazhenov/tango/commit/a6b0547b84fcf886259390bad40e2ac61c16aa99"><code>a6b0547</code></a> IndexedBenchmark type added to protected agains index shifting when filtering...</li> <li><a href="https://github.com/bazhenov/tango/commit/03a24743a0cb1a900cd1a24acf9155e085504e46"><code>03a2474</code></a> Delete dead code</li> <li><a href="https://github.com/bazhenov/tango/commit/1ef340141e02398116b7c0b7d808db2cd1010584"><code>1ef3401</code></a> Merging binary search benchmarks into a single one</li> <li><a href="https://github.com/bazhenov/tango/commit/4a59272827e80c0e0c21dee11cbd4f4312438141"><code>4a59272</code></a> Preserving order of benchmarks</li> <li><a href="https://github.com/bazhenov/tango/commit/801fdf0e3739462c18023806d990274abae1c940"><code>801fdf0</code></a> Add --strip-candidate/--strip-baseline to compare benchmarks from the same ex...</li> <li>See full diff in <a href="https://github.com/bazhenov/tango/compare/v0.8.0...v0.9.0">compare view</a></li> </ul> </details> <br /> --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com> |
||
|
|
9a4454138f |
Take update cells columns as rest arguments and deprecate --columns (#19125)
## Description `update cells` now takes the columns to update as rest arguments, and `--columns` is deprecated. That's the direction agreed in #15477 and matches `select`, `reject` and the `into` commands. This picks up #17815, which was closed because the author stopped responding (credit to @tauanbinato for the original change). I rebased the idea onto current main, which also has `--recursive` now, and made the follow-up changes @fdncred asked for there: - the two `update cells -c [...]` calls in `crates/nu-std/tests/test_std-rfc_tables.nu` now use rest arguments - the `open` test in `crates/nu-command/tests/commands/open.rs` already uses no `-c`, so it didn't need a change A couple of details: - `--columns` still works and shows the deprecation warning on first use. If someone passes both, the two lists are merged. - `-c []` still means "update no columns", and an empty spread like `...$cols` with `$cols = []` means the same. Only calling it with no flag and no columns at all updates everything, same as before. - The rest parameter is named `rest`, like `select` and `reject`, so it doesn't share a name with the deprecated `--columns` flag. - Rest columns go through the same string coercion as `-c`, so int column names work either way (`let cols = [1]; {"1": 1} | update cells { $in + 1 } ...$cols`). - The deprecation `since` is `0.117.0`, since 0.116.0 shipped without it. Checked with a local build: ``` > {a: 1, b: 2, c: 3} | update cells { $in + 10 } a c | to nuon {a: 11, b: 2, c: 13} > {a: 1, b: 2, c: 3} | update cells -c [a] { $in + 10 } | to nuon # warns once, still works {a: 11, b: 2, c: 3} > {a: 1, b: 2, c: 3} | update cells -c [] { $in + 10 } | to nuon {a: 1, b: 2, c: 3} > {a: 1, b: 2, c: 3} | update cells -c [a] { $in + 10 } c | to nuon {a: 11, b: 2, c: 13} > let cols = []; {a: 1, b: 2, c: 3} | update cells { $in + 10 } ...$cols | to nuon {a: 1, b: 2, c: 3} > let cols = [1]; {"1": 1, b: 2} | update cells { $in + 1 } ...$cols | to nuon {"1": 2, b: 2} ``` The converted example fails on main with `ExtraPositional` and passes here. The new tests in `crates/nu-cmd-extra/tests/commands/filters/update_cells.rs` cover `--columns`, merging it with rest columns, empty column lists and int column names. `cargo fmt --all -- --check`, `cargo clippy -p nu-cmd-extra --all-targets -- -D warnings`, `cargo test -p nu-cmd-extra` and the std test suite (`testing run-tests --path crates/nu-std`, 251 tests) all pass. ## User-facing changes (Release notes) `update cells` now accepts the columns to update as rest arguments, and the `--columns` (`-c`) flag is deprecated: ```nushell # before [[name val1 val2]; [foo 1 4] [bar 8 3]] | update cells -c [val1 val2] { $in * 2 } # after [[name val1 val2]; [foo 1 4] [bar 8 3]] | update cells { $in * 2 } val1 val2 ``` ## Additional notes closes #15477 |
||
|
|
b05939d48c |
build(deps): bump arboard from 3.6.1 to 3.7.0 (#19307)
Bumps [arboard](https://github.com/1Password/arboard) from 3.6.1 to 3.7.0. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/1Password/arboard/releases">arboard's releases</a>.</em></p> <blockquote> <h2>v3.7.0</h2> <h2>What's Changed</h2> <ul> <li>Return a conversion failure error when CGImageCreate fails by <a href="https://github.com/complexspaces"><code>@complexspaces</code></a> in <a href="https://redirect.github.com/1Password/arboard/pull/205">1Password/arboard#205</a></li> <li>Properly encode/decode MIME=text/uri-list by <a href="https://github.com/luca020400"><code>@luca020400</code></a> in <a href="https://redirect.github.com/1Password/arboard/pull/217">1Password/arboard#217</a></li> <li>Increase windows-sys lower bound to 0.62 by <a href="https://github.com/T-256"><code>@T-256</code></a> in <a href="https://redirect.github.com/1Password/arboard/pull/220">1Password/arboard#220</a></li> <li>Add example to <code>Get</code> and <code>Set</code> by <a href="https://github.com/Its-Just-Nans"><code>@Its-Just-Nans</code></a> in <a href="https://redirect.github.com/1Password/arboard/pull/224">1Password/arboard#224</a></li> <li>Add a <code>wait_once</code> to support waiting for just one clipboard request by <a href="https://github.com/joshtriplett"><code>@joshtriplett</code></a> in <a href="https://redirect.github.com/1Password/arboard/pull/213">1Password/arboard#213</a></li> </ul> <h2>New Contributors</h2> <ul> <li><a href="https://github.com/luca020400"><code>@luca020400</code></a> made their first contribution in <a href="https://redirect.github.com/1Password/arboard/pull/217">1Password/arboard#217</a></li> <li><a href="https://github.com/T-256"><code>@T-256</code></a> made their first contribution in <a href="https://redirect.github.com/1Password/arboard/pull/220">1Password/arboard#220</a></li> <li><a href="https://github.com/Its-Just-Nans"><code>@Its-Just-Nans</code></a> made their first contribution in <a href="https://redirect.github.com/1Password/arboard/pull/224">1Password/arboard#224</a></li> <li><a href="https://github.com/joshtriplett"><code>@joshtriplett</code></a> made their first contribution in <a href="https://redirect.github.com/1Password/arboard/pull/213">1Password/arboard#213</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/1Password/arboard/compare/v3.6.1...v3.7.0">https://github.com/1Password/arboard/compare/v3.6.1...v3.7.0</a></p> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/1Password/arboard/commit/5f5c8637911ba219edee619105a19b4f74e66a9f"><code>5f5c863</code></a> Release 3.7.0</li> <li><a href="https://github.com/1Password/arboard/commit/ab9663be5d27478399b215c1ab57f1d6574f74fc"><code>ab9663b</code></a> Add example demonstrating <code>wait_once</code></li> <li><a href="https://github.com/1Password/arboard/commit/b9000b17a6a0c89e9c27f469f00d4e50c3910486"><code>b9000b1</code></a> Add a <code>wait_once</code> to support waiting for just one clipboard request</li> <li><a href="https://github.com/1Password/arboard/commit/2ea0ff6ddbcc80cc3b9f1a951879d416f775f753"><code>2ea0ff6</code></a> wayland: Factor out option setting into a method</li> <li><a href="https://github.com/1Password/arboard/commit/b7e47c8d3b6b1c2d90e02e55969d0f92c543c2ed"><code>b7e47c8</code></a> Update lib.rs</li> <li><a href="https://github.com/1Password/arboard/commit/2b2050eba1f6017721433a8640a9b2aae92014ba"><code>2b2050e</code></a> Bump step-security/setup-rust-toolchain from 1.16.1 to 2.0.0</li> <li><a href="https://github.com/1Password/arboard/commit/6b0968206393df5a14c66d584f0d9f1f4afe9a1a"><code>6b09682</code></a> Bump step-security/harden-runner from 2.20.0 to 2.21.1</li> <li><a href="https://github.com/1Password/arboard/commit/9f7b05ca9178e3c28ec5e59a522786a8ea591cce"><code>9f7b05c</code></a> Bump actions/checkout from 4.3.1 to 7.0.0</li> <li><a href="https://github.com/1Password/arboard/commit/890e919929125f927e6f292091f7fbf9b37889e1"><code>890e919</code></a> Apply GitHub Actions security best practices</li> <li><a href="https://github.com/1Password/arboard/commit/d7c6cc971baca5e7d6fe45c3c28cd828f351558e"><code>d7c6cc9</code></a> bump windows-sys lower bound</li> <li>Additional commits viewable in <a href="https://github.com/1Password/arboard/compare/v3.6.1...v3.7.0">compare view</a></li> </ul> </details> <br /> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
2d2108decd |
build(deps): bump serde-saphyr from 1.3.0 to 2.0.0 (#19306)
Bumps [serde-saphyr](https://github.com/bourumir-wyngs/serde-saphyr) from 1.3.0 to 2.0.0. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/bourumir-wyngs/serde-saphyr/releases">serde-saphyr's releases</a>.</em></p> <blockquote> <h2>2.0.0 Performance and compliance release</h2> <p>Breaking changes</p> <ul> <li>There is a new capture_comments feature that is default on and can be disabled, winning about 10 % percent of performance. This feature was the main reason to advance the first version digit, because formally this is a breaking change.</li> <li>Preserving inner error in alias errors in the newly added field in <code>AliasError</code>. The old field (text representation) is still present, but deprecated. Another formally breaking change, even if unlikely to be a problem.</li> <li>from_multiple, from_multiple_with_options, from_slice_multiple, and from_slice_multiple_with_options now accept T: Deserialize<'de> instead of T: DeserializeOwned, allowing values to borrow from the input. Direct calls require no changes. Function pointers or callbacks may need adjustments.</li> <li>granit_parser 2.0.0 has some corner formally breaking changes, but mostly in very obscure parts (see its changelog for details).</li> </ul> <p>All other changes are backward compatible:</p> <ul> <li>For projects aiming for very strict YAML compliance rather than drop-in compatibility with mainstream libraries, it is not possible to disable all compromises with <code>strict_indentation</code> flag in Options.</li> <li>Value serialization target can now receive <code>Inf</code> and <code>NaN</code> if so configured. Even if most common serde_json::Value cannot take them (produces <code>null</code> instead), many other abstract value receivers can.</li> <li>Made <code>huge_documents</code> and <code>serde_derived_types</code> enable <code>deserialize</code>, fixing isolated feature builds with <code>--no-default-features</code>, including autopkgtests of Debian team (as <a href="https://dfsg-new-queue.debian.org/reviews/rust-serde-saphyr">observed</a>).</li> <li>Fix borrow support for untagged enum (PR <a href="https://redirect.github.com/bourumir-wyngs/serde-saphyr/issues/195">#195</a>, thanks <a href="https://github.com/Guiguiprim"><code>@Guiguiprim</code></a> ).</li> <li>Added <code>SerializerOptions::no_lang_directive</code> (default <code>false</code>) to suppress the <code>%YAML 1.2</code> directive independently of <code>yaml_12</code>'s quoting (requirement obvious from <a href="https://github.com/nushell/nushell/blob/d7cb4e589ea53bd1a0bb29dd78d63b76fcb59862/crates/nu-heavy-utils/src/yaml/serialize.rs#L158-L200">Nushell code work work arrounds</a>).</li> <li>Property interpolation can now be configured to be fully Docker Compose compliant if preferred (we are not fans of undefined property defaulting to empty but may be opinion-based).</li> <li>It is possible to deserialize multiple documents into collection other than vector: <a href="https://docs.rs/serde-saphyr/latest/serde_saphyr/fn.from_str_multiple.html"><code>serde_saphyr::from_str_multiple</code></a> supports any collection implementing <code>Default + Extend<T></code>, such as <code>Vec<T></code>, <code>VecDeque<T></code>, <code>BTreeSet<T></code>, or custom storage like <a href="https://docs.rs/smallvec/latest/smallvec/struct.SmallVec.html"><code>SmallVec<T></code></a>.</li> </ul> <p>Other fixes</p> <ul> <li>Keep span offsets relative to the caller's input after a BOM (<a href="https://redirect.github.com/bourumir-wyngs/serde-saphyr/issues/212">#212</a>)</li> <li>Compare mapping keys regardless of entry order (<a href="https://redirect.github.com/bourumir-wyngs/serde-saphyr/issues/211">#211</a>)</li> <li>Report a collection where &str is expected, not end of input (<a href="https://redirect.github.com/bourumir-wyngs/serde-saphyr/issues/210">#210</a>)</li> <li>Replace non-printable characters in Commented comments (<a href="https://redirect.github.com/bourumir-wyngs/serde-saphyr/issues/209">#209</a>)</li> <li>Implement dedicated YAML trim (<a href="https://redirect.github.com/bourumir-wyngs/serde-saphyr/issues/206">#206</a>). Default Rust trim() considers special Unicode whitespace chars that YAML calls to be ignored.</li> <li>Improve multi-snippet error rendering (<a href="https://redirect.github.com/bourumir-wyngs/serde-saphyr/issues/208">#208</a>). Do not rely on error texts for functionallity.</li> <li>Fix serializer indentation after - and ? so output reads back- <a href="https://redirect.github.com/bourumir-wyngs/serde-saphyr/issues/207">#207</a></li> <li>Report a parser error after an implicit document end in single-document entry points- <a href="https://redirect.github.com/bourumir-wyngs/serde-saphyr/issues/220">#220</a> <a href="https://redirect.github.com/bourumir-wyngs/serde-saphyr/issues/220">#220</a>, thanks <a href="https://github.com/pcshrosbree"><code>@pcshrosbree</code></a></li> </ul> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/bourumir-wyngs/serde-saphyr/blob/master/CHANGELOG.md">serde-saphyr's changelog</a>.</em></p> <blockquote> <h2>2.0.0</h2> <h3>YAML changes</h3> <ul> <li>Tags selecting unit enum variants now reject non-null payloads instead of silently discarding them (<a href="https://redirect.github.com/bourumir-wyngs/serde-saphyr/issues/236">#236</a>). Use a bare variant name, a tag with empty content, or a tag followed by <code>~</code> or <code>null</code>; quoted strings and collections are rejected.</li> <li>Composite mapping keys are not compared regardless of entry order (thanks <a href="https://github.com/yuxi-liu-wired"><code>@yuxi-liu-wired</code></a>) .</li> <li>Commented<!-- raw HTML omitted --> now writes its output replacing characters not allowed in comments (non printable) by spaces.</li> </ul> <h3>Added</h3> <ul> <li>Added public <code>path_map::PathKind</code>, <code>PathKey::segments()</code>, and <code>PathMap::locations_for()</code> for inspecting validation paths and resolving their YAML use/definition locations, including best-effort spelling matches and recorded ancestor/root fallback.</li> <li>Added <code>RenderOptions::line_offset</code> and <code>RenderOptions::source_name</code> for displaying embedded YAML diagnostics at their containing document's line numbers and naming the root source in snippet headers, including the new <code>miette::to_miette_report_with_options</code> entry point. Included files retain their own names and coordinates, and stored error locations and spans are unchanged.</li> <li>Added <code>PropertySyntax::DockerCompose</code> for Compose-compatible property interpolation.</li> <li>Added the default-enabled <code>comments</code> feature, forwarding to granit-parser's matching feature. Builds with <code>default-features = false</code> must enable it to use <code>Commented<T></code>, <code>CommentPosition</code>, comment options, or comment budget fields and reports. Without it, YAML comments are still accepted and validated, but their text is not retained.</li> <li>Added <code>Options::non_finite_float_policy</code> with <code>NonFiniteFloatPolicy::{PassThrough, Reject, AsString}</code> to configure non-finite floats delivered through <code>deserialize_any</code>. Explicit policies override the legacy boolean; leaving the field unconfigured preserves its behavior.</li> <li>Added the <code>borrowed_context</code> example showing recursive <code>Serialize</code> adapters that borrow an existing value tree and per-call formatting context, composing with <code>Tagged<T></code> and style wrappers without building a second container tree or using thread-local state.</li> <li>Added <code>SerializerOptions::no_lang_directive</code> (default <code>false</code>) to suppress the <code>%YAML 1.2</code> directive and its leading <code>---</code> marker independently of <code>yaml_12</code>'s quoting.</li> <li>Added <code>from_str_multiple</code>, <code>from_bytes_multiple</code>, and their <code>_with_options</code> variants to deserialize multiple YAML documents into any <code>C: Default + Extend<T></code>, including vectors, queues, sets, and custom accumulators. Values can borrow from the input string or UTF-8 byte slice. Explicit type arguments specify both the document and collection types, for example <code>from_str_multiple::<String, Vec<_>>(input)</code>.</li> <li>Added an <code>error: Box<Error></code> field to <code>Error::AliasError</code>, which keeps the original error when an aliased value fails to deserialize. A custom <code>MessageFormatter</code> or <code>Localizer</code> now applies to that error, and <code>std::error::Error::source</code> returns it (<a href="https://redirect.github.com/bourumir-wyngs/serde-saphyr/issues/199">#199</a>).</li> </ul> <h3>Changed</h3> <ul> <li><strong>Breaking:</strong> <code>from_multiple</code>, <code>from_multiple_with_options</code>, <code>from_slice_multiple</code>, and <code>from_slice_multiple_with_options</code> now accept <code>T: Deserialize<'de></code> so values can borrow from the input. They retain their names, single type parameter, and <code>Vec<T></code> returns and are not deprecated. Ordinary calls, including <code>from_multiple::<Config>(input)</code> and generic callers with <code>T: DeserializeOwned</code>, continue to work. Function pointers or callbacks accepting arbitrary input lifetimes may need forwarding closures, such as <code>|input| from_multiple::<String>(input)</code>.</li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/bourumir-wyngs/serde-saphyr/commit/e3a4566ef2692f6b9c906a103f6841441a1924ba"><code>e3a4566</code></a> Clarified borrowing usage and fixed borrowing test.</li> <li><a href="https://github.com/bourumir-wyngs/serde-saphyr/commit/fc4c875c2d1ae7a3368b8900739d26b88d13d55d"><code>fc4c875</code></a> Merge remote-tracking branch 'origin/master'</li> <li><a href="https://github.com/bourumir-wyngs/serde-saphyr/commit/e2f8eb3d67d3043b137f00fdb586eab72beda43f"><code>e2f8eb3</code></a> Make fuzz and miri mandatory steps for release workflow. use granit-parser fr...</li> <li><a href="https://github.com/bourumir-wyngs/serde-saphyr/commit/9728ccb466d251059f05123dc44a8304c0eae35d"><code>9728ccb</code></a> Report a parser error after an implicit document end in single-document entry...</li> <li><a href="https://github.com/bourumir-wyngs/serde-saphyr/commit/fb50b1bc88fc1c4746cef4211ecba7712ae35f23"><code>fb50b1b</code></a> Improve documentation</li> <li><a href="https://github.com/bourumir-wyngs/serde-saphyr/commit/f3f3786b92c25d83b0d55cd73a6d2e7ccb4e568e"><code>f3f3786</code></a> Improve documentation</li> <li><a href="https://github.com/bourumir-wyngs/serde-saphyr/commit/d43a925d3b12dabbe3adfd3a6e4fbcb06f4db7a7"><code>d43a925</code></a> Removed some too aggressive deprecations, this is not required with the major...</li> <li><a href="https://github.com/bourumir-wyngs/serde-saphyr/commit/2db19936273a9b8382a0770f22b4cff0ebd9c683"><code>2db1993</code></a> bw/i205 (<a href="https://redirect.github.com/bourumir-wyngs/serde-saphyr/issues/215">#215</a>)</li> <li><a href="https://github.com/bourumir-wyngs/serde-saphyr/commit/c09c094ae054cafbb4b14daceb216546023d8ac0"><code>c09c094</code></a> Bump granit-parser from <code>03889c5</code> to <code>f4bf73a</code> (<a href="https://redirect.github.com/bourumir-wyngs/serde-saphyr/issues/216">#216</a>)</li> <li><a href="https://github.com/bourumir-wyngs/serde-saphyr/commit/70272b71d7d36254c5521585439714014bca5ed3"><code>70272b7</code></a> Update cargo to use granit parser 2.0.0</li> <li>Additional commits viewable in <a href="https://github.com/bourumir-wyngs/serde-saphyr/compare/1.3.0...2.0.0">compare view</a></li> </ul> </details> <br /> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
965ad78430 |
Bump webpki crates to clear the RustSec audit (#19308)
<!-- 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 The `Security audit` job fails on every PR that touches `Cargo.toml` or `Cargo.lock` (for example #19306). The advisory database now flags three crates for CVE-2026-111943. Their certificate checks can accept chains through emSign intermediates whose private keys have leaked. Each crate has a patched release, so this PR moves all three to it: | Crate | Old | New | Advisory | Pulled in by | | --- | --- | --- | --- | --- | | `rustls-webpki` | 0.103.15 | 0.103.16 | RUSTSEC-2026-0382 | `rustls` (all TLS connections) | | `webpki-roots` | 1.0.9 | 1.0.10 | RUSTSEC-2026-0381 | `nu-command` (direct workspace dependency) | | `webpki-root-certs` | 1.0.6 | 1.0.10 | RUSTSEC-2026-0383 | `rustls-platform-verifier` (wasm32 only) | `webpki-roots` is a direct workspace dependency, so `Cargo.toml` now requires the patched `1.0.10` instead of only pinning it in the lockfile. The other two crates are transitive, so only `Cargo.lock` changes for them (`cargo update -p rustls-webpki -p webpki-roots -p webpki-root-certs`). Nothing else in the lockfile moves. <!-- 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) - Bumped `rustls-webpki`, `webpki-roots` and `webpki-root-certs` for CVE-2026-111943 (distrusted emSign intermediates). <!-- 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 - `cargo audit` 0.22.2 (advisory database of 2026-10-21) on main's `Cargo.lock`: 3 vulnerabilities, exit 1. On this branch: 0 vulnerabilities, exit 0. - `cargo audit` still warns that `bincode` (RUSTSEC-2025-0141) and `yaml-rust` (RUSTSEC-2024-0320) are unmaintained, the same as on main. These warnings are informational, so the job does not fail on them. - CI's clippy step (`clippy --workspace --all-targets --profile ci -- -D warnings` with `.cargo/ci.toml`, plugins included) and `cargo nuclippy` both pass on macOS. <!-- Optional. Examples: - fixes #123 - closes #456 - related #789 Anything else reviewers should know. Remove this section if not needed. --> |
||
|
|
64915f00e4 |
Fix roll panic on empty lists and records (#19285)
## Description
`roll` panics when the input is empty. On current main:
> [] | roll down
panicked: assertion failed: k <= self.len()
> {} | roll left
panicked: assertion failed: mid <= self.len()
> [] | roll up --by 3
panicked: attempt to calculate the remainder with a divisor of zero
I found these by running commands against empty and edge-case input. The
cause is in `vertical_rotate_value` and `horizontal_rotate_value`. Both
do `n % len`, which divides by zero when the list or record is empty.
Without `--by`, the default rotation of 1 on an empty slice also
asserts.
The fix uses `checked_rem`, so an empty list or record gets a rotation
of 0 and is returned unchanged. I added tests for `roll up`, `roll
down`, `roll left` and `roll right` on empty input, one for empty
records inside a list, and one for a table where only one row is empty.
I ran the `roll` tests locally and they pass (13). I haven't run the
full test suite, so I'm relying on CI for that.
## User-facing changes (Release notes)
Fixed a panic when using `roll up`, `roll down`, `roll left` or `roll
right` on an empty list or record.
## Additional notes
n/a
---------
Signed-off-by: manoj-1407 <manojkumar148700@gmail.com>
Signed-off-by: G. Manoj Kumar <manojkumar148700@gmail.com>
|
||
|
|
dd0a08cd4b |
build(deps): bump taiki-e/install-action from 2.87.27 to 2.87.29 (#19304)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.87.27 to 2.87.29. <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.29</h2> <ul> <li> <p>Update <code>zizmor@latest</code> to 1.31.0.</p> </li> <li> <p>Update <code>wasmtime@latest</code> to 49.0.3.</p> </li> <li> <p>Update <code>wasm-tools@latest</code> to 1.262.0.</p> </li> <li> <p>Update <code>uv@latest</code> to 0.13.1.</p> </li> <li> <p>Update <code>trivy@latest</code> to 0.76.0.</p> </li> <li> <p>Update <code>tombi@latest</code> to 1.8.4.</p> </li> <li> <p>Update <code>release-plz@latest</code> to 0.3.172.</p> </li> <li> <p>Update <code>osv-scanner@latest</code> to 2.7.0.</p> </li> <li> <p>Update <code>mise@latest</code> to 2026.10.11.</p> </li> <li> <p>Update <code>mdbook-d2@latest</code> to 0.3.9.</p> </li> <li> <p>Update <code>kingfisher@latest</code> to 2.13.0.</p> </li> <li> <p>Update <code>kache@latest</code> to 1.2.1.</p> </li> <li> <p>Update <code>just@latest</code> to 1.59.0.</p> </li> <li> <p>Update <code>dprint@latest</code> to 0.63.0.</p> </li> <li> <p>Update <code>cargo-crap@latest</code> to 0.8.0.</p> </li> <li> <p>Update <code>bpf-linker@latest</code> to 0.12.0.</p> </li> </ul> <h2>2.87.28</h2> <ul> <li> <p>Update <code>dprint@latest</code> to 0.62.0.</p> </li> <li> <p>Update <code>vacuum@latest</code> to 0.33.0.</p> </li> <li> <p>Update <code>uv@latest</code> to 0.13.0.</p> </li> <li> <p>Update <code>tombi@latest</code> to 1.8.1.</p> </li> <li> <p>Update <code>release-plz@latest</code> to 0.3.171.</p> </li> <li> <p>Update <code>rclone@latest</code> to 1.75.2.</p> </li> <li> <p>Update <code>mise@latest</code> to 2026.10.7.</p> </li> <li> <p>Update <code>cargo-binstall@latest</code> to 1.25.3.</p> </li> </ul> </blockquote> </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.29] - 2026-10-16</h2> <ul> <li> <p>Update <code>zizmor@latest</code> to 1.31.0.</p> </li> <li> <p>Update <code>wasmtime@latest</code> to 49.0.3.</p> </li> <li> <p>Update <code>wasm-tools@latest</code> to 1.262.0.</p> </li> <li> <p>Update <code>uv@latest</code> to 0.13.1.</p> </li> <li> <p>Update <code>trivy@latest</code> to 0.76.0.</p> </li> <li> <p>Update <code>tombi@latest</code> to 1.8.4.</p> </li> <li> <p>Update <code>release-plz@latest</code> to 0.3.172.</p> </li> <li> <p>Update <code>osv-scanner@latest</code> to 2.7.0.</p> </li> <li> <p>Update <code>mise@latest</code> to 2026.10.11.</p> </li> <li> <p>Update <code>mdbook-d2@latest</code> to 0.3.9.</p> </li> <li> <p>Update <code>kingfisher@latest</code> to 2.13.0.</p> </li> <li> <p>Update <code>kache@latest</code> to 1.2.1.</p> </li> <li> <p>Update <code>just@latest</code> to 1.59.0.</p> </li> <li> <p>Update <code>dprint@latest</code> to 0.63.0.</p> </li> <li> <p>Update <code>cargo-crap@latest</code> to 0.8.0.</p> </li> <li> <p>Update <code>bpf-linker@latest</code> to 0.12.0.</p> </li> </ul> <h2>[2.87.28] - 2026-10-12</h2> <ul> <li>Update <code>dprint@latest</code> to 0.62.0.</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/8cca0918f8471c33515202b73f56ab27f2bed283"><code>8cca091</code></a> Release 2.87.29</li> <li><a href="https://github.com/taiki-e/install-action/commit/fc26824601b40bd3b26712c48942016e2b2d12f6"><code>fc26824</code></a> Update wasmtime manifest</li> <li><a href="https://github.com/taiki-e/install-action/commit/5018b2ebebbb2657068e91071ea73d9a53a44f2d"><code>5018b2e</code></a> Update <code>zizmor@latest</code> to 1.31.0</li> <li><a href="https://github.com/taiki-e/install-action/commit/d0e52041f440d731eae552c575c81c4cccd601c8"><code>d0e5204</code></a> Update <code>wasmtime@latest</code> to 49.0.3</li> <li><a href="https://github.com/taiki-e/install-action/commit/517774f2ae949bb5d89258edba4466e75f1a33be"><code>517774f</code></a> Update <code>wasm-tools@latest</code> to 1.262.0</li> <li><a href="https://github.com/taiki-e/install-action/commit/4bc69b1c8214eb6efb50b217dfb04ae04d8af1f5"><code>4bc69b1</code></a> Update vacuum manifest</li> <li><a href="https://github.com/taiki-e/install-action/commit/0470a3f16345a16a36a8b4b51fd72f0de5cc6b5b"><code>0470a3f</code></a> Update <code>uv@latest</code> to 0.13.1</li> <li><a href="https://github.com/taiki-e/install-action/commit/7a2b747eb5f89f888d956c73464777912a182a35"><code>7a2b747</code></a> Update <code>trivy@latest</code> to 0.76.0</li> <li><a href="https://github.com/taiki-e/install-action/commit/7efb5337f67975eb612c46a52d9c7790a5829f97"><code>7efb533</code></a> Update <code>tombi@latest</code> to 1.8.4</li> <li><a href="https://github.com/taiki-e/install-action/commit/e5d37d6fd4d56d59f3bdc428d4138afa60276954"><code>e5d37d6</code></a> Update <code>release-plz@latest</code> to 0.3.172</li> <li>Additional commits viewable in <a href="https://github.com/taiki-e/install-action/compare/ab6895351a88b908e96a4697860d4ffea5e57dbe...8cca0918f8471c33515202b73f56ab27f2bed283">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> |
||
|
|
7257a46841 |
fix(detect type): preserve whitespace-padded strings (#19299)
## Description In this PR I fixed #16872. detect type matches some strings as numbers or booleans but fails when parsing them. It now keeps the original input and metadata when conversion fails, including integers that are too large to fit in i64. Strings with leading or trailing whitespace now stay strings across all types, including durations. This follows panicbit’s suggestion in the issue discussion. Numeric patterns now use ASCII digits, and booleans use ASCII case-insensitive matching. Integers with a leading + are supported, while numbers with mixed separators, such as "1,000_000", stay strings. Updated the help text and regression tests. Each whitespace variant now runs as a separate test so failures are easier to identify. Fixes #16872 ## User-facing changes (Release notes) Fixed detect type returning conversion errors for whitespace-prefixed numbers, Unicode digits, and out-of-range integers. Inputs that fail conversion now remain unchanged. Strings with surrounding whitespace, including durations such as " 5ns", now stay strings. Integers with a leading +, such as "+42", are now converted. Numbers with mixed comma and underscore separators remain strings. ## Additional notes Adds tested help examples and regression tests covering whitespace, Unicode inputs, integer boundaries, invalid dates, metadata preservation, and existing conversions. Validation passed: > 861 library tests, including command examples; 2 ignored > 476 detect type integration tests > cargo fmt --all > cargo nuclippy > typos v1.51.1 > git diff --check |
||
|
|
324696443a |
fix(version check): propagate error and use github token (#19298)
<!-- 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. --> ## 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. --> Previously, the `version check` command would say you are on the latest release if the lookup failed, now, lookup errors will result in an error on the command too. Also, if a github token is available on the environment (`GITHUB_TOKEN` or `GH_TOKEN`) it will be used for the request to bypass the unauthenticated 60-requests-per-hour github api rate limit. |
||
|
|
77726d8d22 |
Fix table --abbreviated crash when the row count is too large to allocate (#19296)
## Description `table --abbreviated` crashes when the count is too large to allocate. On current main: > 1..5 | table --abbreviated 9223372036854775807 panicked: capacity overflow > [[a]; [1]] | table --abbreviated 9223372036854775807 panicked: capacity overflow `stream_collect_abbreviated` reserves the head and the tail with `with_capacity(size)`, where `size` is the number the user typed. Both buffers only ever hold rows that are actually read, so they are now sized from the iterator's size hint: `head` reserves `hint.min(2 * size + 1)`, which is its final length with the `...` row, and `tail` reserves `hint.saturating_sub(size).min(size)`. Inputs without a hint, like a range or `every`, start empty and grow. The output doesn't change: a count larger than the input shows every row, as before. This is the same problem as #19286 (`chunks`), #19288 (`window`) and #19295 (`last`). I added tests that a huge count prints the same table as a normal count, for a plain list and for a list stream, and a huge-count range case in `table_abbreviation_cut`. I ran the `table::abbreviation` tests locally and they pass. I did not run the full workspace suite. AI assistance: I used Claude to help find the issue and draft the change. I reviewed and tested it myself. ## User-facing changes (Release notes) Fixed a crash when `table --abbreviated` is given a row count too large to allocate, such as 9223372036854775807. ## Additional notes n/a --------- Signed-off-by: G. Manoj Kumar <manojkumar148700@gmail.com> |
||
|
|
ab781520a8 |
Fix window crash when the window size is too large to allocate (#19288)
## Description `window` crashes when the window size is too large to allocate. On current main: > [1 2 3] | window 9223372036854775807 panicked: capacity overflow > [1 2 3] | window 9223372036854775807 --stride 9223372036854775807 panicked: capacity overflow Both come from `Vec::with_capacity` taking the size the user typed. `WindowOverlapIter` reserved it in `new`, and `WindowGapIter` reserved it on every call to `next`. The overlapping iterator also used `self.window.capacity()` as the window size, so it depended on the reservation. It now keeps `size` as a field. The overlap buffer starts empty and is filled with `extend`, and the gap iterator collects its window, so neither reserves the typed size. This is the same problem that #19286 fixed for `chunks`. With `--remainder` and a stride equal to the size, `window` hands off to `chunks`, so that case works now too. I added tests for a huge size on a list, with a huge stride, on list streams (both iterators), and with `--remainder`, where they check the actual windows. I ran the `window` and `chunks` tests locally and they pass. I did not run the full workspace suite. AI assistance: I used Claude to help find the issue and draft the change. I reviewed and tested it myself. ## User-facing changes (Release notes) Fixed a crash when `window` is given a window size too large to allocate, such as 9223372036854775807. ## Additional notes n/a --------- Signed-off-by: G. Manoj Kumar <manojkumar148700@gmail.com> |
||
|
|
04ba9838b8 |
feat: enable spread operator for get command rest args (#18220)
## Summary `get` now takes its cell paths as a single `...rest` parameter, so a list of paths can be spread into it: `get ...$paths`. Before this, `get` required a first cell path followed by a rest, and there was no way to pass a dynamically built list of paths. ## Behavior - `get` with no paths returns its input unchanged. With an empty pipeline it reports `Pipeline empty`, the same as `select`. - `get a` with one cell path and no spread returns the value at that path, as before. - Several paths, or any spread argument, return a list with one value per path. A spread always produces a list, so `get ...$cols` has the same shape whatever `$cols` holds: one name gives a one-element list, and an empty spread gives an empty list. - Strings in a spread are single column names, so `...[a.b]` looks for a column named `a.b`. Nested paths are spread as cell-path values, for example `let paths = [$.a.b]` or `into cell-path`. ## Changes - `crates/nu-command/src/filters/get.rs`: the signature is `get ...(rest)`. `action` takes the full `Vec<CellPath>`, checks for an empty pipeline first, then branches on zero paths, one path without a spread, and everything else. A small helper reads whether the call has a spread argument (AST and IR calls). The help text and examples describe the zero, one and many cases and nested spread paths. - `crates/nu-command/tests/commands/get.rs`: tests for literal before and after a spread, one-element spreads on a table and a record, empty literal and variable spreads, a nested cell-path spread, a const spread, and the empty pipeline with no paths and with an empty spread. ## Testing On the merged branch: `cargo fmt --all -- --check`, `cargo clippy -p nu-command --all-targets -- -D warnings` (with `.cargo/ci.toml`), `cargo test -p nu-command --test tests -- commands::get` (39 passed) and the `get` examples test all pass. Against the previous `get.rs`, 8 of the 10 new tests fail; the two mixed-order tests pass on both, since that ordering already worked. ## Release notes - `get` accepts spread cell paths (`get ...$paths`). Its signature changes from `get <cell_path> ...(rest)` to `get ...(rest)`. - `get` with no arguments is no longer a parse error: it returns its input, or reports `Pipeline empty` when there is no input. - A `get` call with a spread argument always returns a list, one value per path. Fixes #15801 --------- Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
2deff7fc5b |
fix(cli): show the script name instead of main in errors about a script's arguments (#19282)
## Description `nu script.nu` runs the script's `main` by evaluating `main <args>`, so an error about the arguments showed `main` in the source snippet, even though the usage line already uses the script name: ``` Error: nu::parser::missing_positional × Missing required positional argument. ╭─[<commandline>:1:5] 1 │ main · ▲ · ╰── missing foo ╰──── help: Usage: script.nu <foo> . Use `--help` for more information. ``` `evaluate_file` already adds the script name to the overlay as another name for `main` (and `script.nu foo` for `main foo`), so the call can use it. This now builds the command line as `script.nu <args>` when that parses as a call to the script's renamed `main` (checked with a single probe parse), and falls back to `main <args>` otherwise. The snippet then shows `script.nu`: ``` ╭─[<commandline>:1:10] 1 │ script.nu · ▲ · ╰── missing foo ╰──── help: Usage: script.nu <foo> . Use `--help` for more information. ``` The script name is only used when it parses as a command. Scripts named after a parser keyword (`for`, `source`, `use`, `module`, `alias`, ...) always call `main` directly, and names that parse as something else, such as `10kb`, `true`, `it's.nu` or `a #b.nu`, still show `main`. Names with a space (`my script.nu`) use the script name. Scripts without a `main` aren't affected. Tests added in `tests/shell/mod.rs`: - `main_script_missing_argument_uses_script_name` - `main_script_subcommand_missing_argument_uses_script_name` - `main_script_with_space_in_name_uses_script_name` - `main_script_named_like_a_parser_keyword_still_runs` - `main_script_named_like_a_value_still_runs` (checks the fallback to `main`) - `script_without_main_is_unaffected` ## User-facing changes (Release notes) - Errors about the arguments passed to a script's `main` (such as a missing positional argument) now show the script name instead of `main`, when the script name parses as a command. Other names (for example `10kb` or `it's.nu`) still show `main`. ## Additional notes Fixes #10191 Tests + formatting: - `cargo fmt --all -- --check` - `cargo clippy -p nu-config -p nu-cmd-lang -p nu-command -p nu-cli -p nu-explore --all-targets -- -D warnings -D clippy::unwrap_used` - `cargo clippy -p nu -p nu-cli --all-targets -- -D warnings -D clippy::unwrap_used` - `cargo test --test tests -- shell::` - `cargo test -p nu-cli --lib eval_file` The script name is only used when the call resolves to main, so names like 10kb, it's.nu or main;… still show main. |
||
|
|
877ed65f0a |
fix(run-external): explain a missing shebang interpreter instead of showing an internal error (#19280)
## Description Running a script whose shebang interpreter doesn't exist gave an internal error that pointed at a Rust source location: ``` Error: nu::shell::io::not_found × Not found ╰─▶ × Could not spawn foreground child: No such file or directory (os error 2) ╭──── 1 │ crates/nu-command/src/system/run_external.rs:323:17 · ─────────────────────────┬───────────────────────── · ╰── Not found ╰──── ``` By the time the child is spawned, `which` has already found the executable, so on Unix a "not found" error from spawning means something the OS needs to start it is missing. Nushell now reads the first line of the file: if it starts with `#!` and that interpreter doesn't exist, the help names it, like bash, zsh and fish do. Otherwise it says a file the program needs (such as a shared library or its program loader) wasn't found, which is the `ldd` case in the issue. The help includes the resolved path, so it's clear which file was run: ``` Error: nu::shell::external_command × External command failed ╭─[entry #1:1:1] 1 │ ./script.sh · ─────┬───── · ╰── `./script.sh` exists but could not be started ╰──── help: `/path/to/script.sh` starts with `#!/nonexistent/interpreter`, but `/nonexistent/interpreter` was not found (No such file or directory (os error 2)) ``` This hint is Unix-only and only used when the file still exists; on Windows, or when the file was removed after `which` found it, you get the normal not-found error with the path. Other spawn errors (permission denied, argument list too long, exec format error) are now reported against the command and its path instead of a Rust source line. Tests in `crates/nu-command/tests/commands/run_external.rs` (Unix only, for the bare, `^` and `run-external` forms): - `missing_shebang_interpreter_error` - `non_executable_shebang_interpreter_error` (a `#!` pointing at a file that isn't executable, which now gives a permission error instead of the internal one) Both retry once if the run fails with `ExecutableFileBusy`, to avoid the Linux "Text file busy" flake. ## User-facing changes (Release notes) - Running a script whose shebang interpreter is missing now names the interpreter, and a program missing a file it needs (such as a shared library) says so, instead of showing an internal "Could not spawn foreground child" error with a Rust source location. Other errors from starting an external command point at the command and its path. ## Additional notes Fixes #15970 Tests + formatting: - `cargo fmt --all -- --check` - `cargo clippy -p nu-config -p nu-cmd-lang -p nu-command -p nu-cli -p nu-explore --all-targets -- -D warnings -D clippy::unwrap_used` - `cargo test -p nu-command --test tests -- commands::run_external` |
||
|
|
e03b706d72 |
Fix last crash when the count is too large to allocate (#19295)
## Description `last` crashes on byte streams when the count is too large to allocate. On current main: > random binary 16b | last 9223372036854775807 | length panicked: capacity overflow It comes from `VecDeque::with_capacity(rows + TAKE as usize)`, where `rows` is the number the user typed. The loop already drains the buffer down to `rows` after every read, so the buffer only needs to grow with the data that is actually read. The buffer now starts empty, so memory use follows the data and not the argument. This is the same problem as #19286 (`chunks`) and #19288 (`window`). I added tests for a huge count on a byte stream and on binary input, comparing the values. I ran the `last` tests locally and they pass. I did not run the full workspace suite. AI assistance: I used Claude to help find the issue and draft the change. I reviewed and tested it myself. ## User-facing changes (Release notes) Fixed a crash when `last` is given a count too large to allocate, such as 9223372036854775807, on byte stream input. ## Additional notes n/a Signed-off-by: G. Manoj Kumar <manojkumar148700@gmail.com> |
||
|
|
cb42a1a4c8 | Merge remote-tracking branch 'upstream/main' into fix_unlet_const | ||
|
|
27f09f90eb | fix(unlet): hide a constant's name instead of rejecting it | ||
|
|
199cf98b4f |
fix(du): count a hard-linked file once, not once per link (#19283)
## Description `du` walked every path and added each file's size independently, so a file with N hard links was counted N times and both size columns over-reported. The walk now tracks the identities of files it has already counted and skips the repeats. The set holds `uucore::fs::FileInformation` (device+inode on Unix, volume serial+file index on Windows) instead of a Unix-only `(dev, ino)` pair, so the dedup applies on Linux, macOS and Windows; the gate is `not(wasm32)`. One set covers the whole `du` invocation following the POSIX/GNU rule: a file counts once even across different path operands, so `du` and `du d1 d2` agree (first occurrence wins). Only files with more than one link enter the set; single-link files never touch it. `DirBuilder` stays settings-only — the set is threaded through as `&mut` rather than living in a cloned struct. `ls --du` uses the new signature; within each listed directory a hard-linked file now counts once, matching `du`. Adds regression tests: a file with multiple hard links contributes its size exactly once, including when the links sit under different path operands. ## User-facing changes (Release notes) - Fixed `du` over-reporting sizes for hard-linked files: a file with multiple hard links is now counted once instead of once per link, on all platforms (Linux, macOS, Windows). - `du --long` lists the first-seen link only, matching GNU `du -a`. - `ls --du` now counts a hard-linked file once inside each listed directory, like `du` does. - First link wins: when the same file is reachable through multiple hard links, only the first occurrence is counted and listed — e.g. `du c b a` on three links to one file shows a single row for `c`. This matches POSIX/BSD/GNU `du`, but scripts that expect one row per operand will see fewer rows. ## Additional notes - Fixes #19019 |
||
|
|
a4e1065511 |
disallow setting a negative indentation level in to xml (#19292)
## Description `to xml` allows setting a negative value for the `indent` argument, even though none of the other `to` commands with similar arguments allow doing so. Giving a value of -1 makes it warp into usize::MAX, which makes Nushell freeze regardless of the input. ## User-facing changes (Release notes) `to xml` now disallows setting a negative indentation amount. ## Additional notes Closes https://github.com/nushell/nushell/issues/19291 |
||
|
|
a714117bb0 |
Fix chunks crash when the chunk size is too large to allocate (#19286)
## Description `chunks` crashes when the chunk size is too large to allocate. On current main: > [1 2 3] | chunks 9223372036854775807 panicked: capacity overflow > 0x[11 22 33] | chunks 9223372036854775807 memory allocation of 9223372036854775807 bytes failed The stream versions (`[0 1 2] | every 1 | chunks 9223372036854775807` and `random binary 16b | chunks 9223372036854775807`) crash the same way, as pointed out in review. All of them come from `Vec::with_capacity(self.size)`, where `size` is the number the user typed. The whole chunk size is reserved before any input is read. For lists, each chunk is now built with `once(first).chain(..).collect()`. That has an exact size hint for list input, so it allocates once, and nothing is reserved from the user's number. For binary input, `ChunkRead` starts with an empty buffer and grows it with the bytes it reads. Trade-off: stream and binary input now grow by doubling instead of one up-front allocation, so there is a bit more copying. Memory use follows the data, not the argument. I added tests for a huge chunk size on a list, a list stream, a binary and a byte stream. I ran the `chunks` tests locally and they pass. I did not run the full workspace suite. `window` has the same pattern and I'm sending it as a separate PR. AI assistance: I used Claude to help find the issue and draft the change. I reviewed and tested it myself. ## User-facing changes (Release notes) Fixed a crash when `chunks` is given a chunk size too large to allocate, such as 9223372036854775807. ## Additional notes n/a --------- Signed-off-by: G. Manoj Kumar <manojkumar148700@gmail.com> |
||
|
|
9b7771489d |
test(parser): pin exact whole-number unit literals and scaled overflow (#18898)
## Description Filesize and duration literals lose precision because `parse_unit_value` parses the numeric part through an `f64`. `Filesize` is backed by an `i64`, so large exact integers get silently rounded — e.g. `6504534684301572998b` parses as `6504534684301573120b`, off by 122 bytes (#10612). This parses the numeric part as an `i64` when it's a whole number and computes the base-unit value (bytes / nanoseconds) with checked integer arithmetic. Fractional literals, and anything that would overflow `i64`, fall back to the existing `f64` path, so everything that already worked is unchanged. The unit factors are all whole numbers, so the integer conversion is lossless. ## User-facing changes (Release notes) - Fixed large whole-number filesize and duration literals (e.g. `6504534684301572998b`) losing precision when parsed. ## Additional notes Fixes #10612 |
||
|
|
684b4dff76 |
chore: bump reedline to 39db5e3 (#19290)
## Description Bumps reedline to `39db5e3`, six PRs past `d704744`: - nushell/reedline#1132 `feat(engine): add opt-in paste hooks for interception and burst detection` - nushell/reedline#1243 `fix(painter): print external messages from the prompt's start row` - nushell/reedline#1249 `test(painter): assert on a vt100 screen instead of emitted bytes` - nushell/reedline#1247 `chore: add .claude to gitignore` - nushell/reedline#1248 `feat(history)!: drop chrono from the public API with a millisecond HistoryTimestamp` - nushell/reedline#1254 `Fix large completion menus and synchronized repainting` #1248 needs the only change on the nushell side: `repl.rs` now stamps history with `HistoryTimestamp::now()`, and `history import` converts its `date` field to millis, so its input type stays the same. ## User-facing changes (Release notes) - Fixed external messages leaving prompt rows behind or erasing output above the prompt. - Fixed completion menus with more entries than fit in terminal coordinates. - Repaints are bracketed with synchronized terminal updates, which reduces flicker on supporting terminals. |
||
|
|
ae6793e49d |
Tone down the tutor echo intro (#19287)
## Description Fixes #12927. `tutor echo` opened by calling `echo` "a powerful tool for not only seeing values, but also for creating new ones", which oversells it. The intro now just says what `echo` does and points out that a value on its own, like `"Hello"`, works the same as `echo "Hello"`, as suggested in the issue. I also fixed a small grammar slip further down ("to later processes these values"). The examples are unchanged. ## User-facing changes (Release notes) - The `tutor echo` intro is now more accurate and mentions that a plain value works the same as passing it to `echo`. |
||
|
|
4089cf963a |
fix(into string): explain in help that binary input needs decode (#19284)
## Description Fixes #15513. `help into string` lists `binary -> string` as an input/output type, but `0x[31 32 33] | into string` always fails with `can't convert binary to string`. The help and the behaviour disagree. As noted in the issue, the easy fix (dropping `binary` from the signature) would make the parser reject binary input up front with a generic input type error, and users would no longer see the hint to use `decode`. So this PR keeps `binary` in the signature and makes the help say what actually happens: - `into string` now has an extra description explaining that binary input is only accepted so it can point you to `decode`, because `into string` does not decode bytes. It shows up in `help into string` right under the description. - The value path and the byte stream path now build the same error from one helper, and the hint is a bit more specific: "`into string` does not decode bytes; use the `decode` command instead, for example `decode utf-8`". - Added tests: binary input returns `CantConvert` from `binary` to `string` with a hint mentioning `decode`, and `help into string` mentions `decode`. I went with this over removing `binary` from the signature because it keeps the hint, and over decoding bytes as UTF-8 inside `into string` because that would duplicate `decode` and quietly pick an encoding for the user. ## User-facing changes (Release notes) `help into string` now explains that `into string` does not convert binary data: binary input returns an error that points to `decode`, for example `0x[68 69] | decode utf-8`. The error hint for binary input is also clearer. ## Additional notes Tests run locally: - `cargo fmt --all -- --check`: clean - `cargo clippy -p nu-command --all-targets -- -D warnings -D clippy::unwrap_used`: clean - `cargo test -p nu-command --lib conversions::into`: 126 passed - `cargo test -p nu-command --test tests -- into_string`: 54 passed (includes the 2 new tests) - `cargo test -p nu-command --lib test_examples`: 259 passed, 2 ignored |
||
|
|
f163d7c559 |
fix(tee): keep the last help example short (#19281)
## Description
The last example in `help tee` prints 10000 lines (`10000 | tee { 1..$in
| print } | $in * 5`), which is a lot of output for a help example and
can scroll everything else out of view. This changes it to 100 (result
500), which shows the same thing in a short example.
`tee.rs` had no example test, so I added one (`test_examples`). It runs
the examples that have a result and parses the rest.
## User-facing changes (Release notes)
- The last `help tee` example now prints 100 lines instead of 10000.
## Additional notes
Related: #16374. This keeps the help example short. It doesn't change
how large outputs are printed.
Tests + formatting:
- `cargo fmt --all -- --check`
- `cargo clippy -p nu-config -p nu-cmd-lang -p nu-command -p nu-cli -p
nu-explore --all-targets -- -D warnings -D clippy::unwrap_used`
- `cargo test -p nu-command --lib tee`
|
||
|
|
d214ff7175 |
fix(hide): describe the required argument as the name of what to hide (#19279)
## Description `hide`'s required argument was called `module` and described as "Module or module file.", but `hide` mostly takes the name of an alias, a custom command or a type alias, and all three examples in `help hide` do that. A module name works too (`hide spam` after `use spam`), with the optional `members` argument picking which of its members to hide. This renames the argument to `name` and describes it as "Alias, command, type alias, or module to hide.", so the signature matches the description and the examples. Only the help text changes; the parser handles `hide` as a keyword and doesn't look the argument up by name. Argument completion for `hide` (also mentioned in the issue) is not changed here. ## User-facing changes (Release notes) - `help hide` now describes the required argument as the name of the alias, command, type alias, or module to hide, instead of "Module or module file.". ## Additional notes Part of #15527 (the signature part; completion isn't touched). Tests + formatting: - `cargo fmt --all -- --check` - `cargo clippy -p nu-config -p nu-cmd-lang -p nu-command -p nu-cli -p nu-explore --all-targets -- -D warnings -D clippy::unwrap_used` - `cargo test -p nu-cmd-lang` |