mirror of
https://github.com/nushell/nushell.git
synced 2025-07-09 10:57:54 +02:00
f6d807bf36d54ec466d0f76c9a91d3c1f55f6bb8
2 Commits
Author | SHA1 | Message | Date | |
---|---|---|---|---|
0b202d55f0 |
Add only command to std-rfc/iter (#16015)
<!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> This PR adds the `only` command to `std-rfc/iter`, which is a command I wrote a while ago that I've found so useful that I think it could have a place in the standard library. It acts similarly to `get 0`, but ensures that the value actually exists, and there aren't additional values. I find this most useful when chained with `where`, when you want to be certain that no additional elements are accidentally selected when you only mean to get a single element. I'll copy the help page here for additional explanation: > Get the only element of a list or table, ensuring it exists and there are no extra elements. > > Similar to `first` with no arguments, but errors if there are no additional > items when there should only be one item. This can help avoid issues when more > than one row than expected matches some criteria. > > This command is useful when chained with `where` to ensure that only one row > meets the given condition. > > If a cell path is provided as an argument, it will be accessed after the first > element. For example, `only foo` is roughly equivalent to `get 0.foo`, with > the guarantee that there are no additional elements. > > Note that this command currently collects streams. > Examples: > > Get the only item in a list, ensuring it exists and there's no additional items > ```nushell > [5] | only > # => 5 > ``` > > Get the `name` column of the only row in a table > ```nushell > [{name: foo, id: 5}] | only name > # => foo > ``` > > Get the modification time of the file named foo.txt > ```nushell > ls | where name == "foo.txt" | only modified > ``` Here's some additional examples showing the errors:   Most of the time I chain this with a simple `where`, but here's a couple other real world examples of how I've used this: [With `parse`, which outputs a table](https://git.ikl.sh/132ikl/dotfiles/src/branch/main/.scripts/manage-nu#L53): ```nushell let commit = $selection | parse "{start}.g{commit}-{end}" | only commit ``` [Ensuring that only one row in a table has a name that ends with a certain suffix](https://git.ikl.sh/132ikl/dotfiles/src/branch/main/.scripts/btconnect): ```nushell $devices | where ($chosen_name ends-with $it.name) | only ``` Unfortunately to get these nice errors I had to collect the stream (and I think the errors are more useful for this). This should be to be mitigated with (something like) #16014. Putting this in `std/iter` might be pushing it, but it seems *just* close enough that I can't really justify putting it in a different/new module. # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> * Adds the `only` command to `std-rfc/iter`, which can be used to ensure that a table or list only has a single element. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass (on Windows make sure to [enable developer mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging)) - `cargo run -- -c "use toolkit.nu; toolkit test stdlib"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> Added a few tests for `only` including error cases # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. --> N/A --------- Co-authored-by: Bahex <Bahex@users.noreply.github.com> |
|||
e7d2717424 |
feat(std-rfc): add iter module and recurse command (#15840)
# Description `recurse` command is similar to `jq`'s `recurse`/`..` command. Along with values, it also returns their cell-paths relative to the "root" (initial input) By default it uses breadth-first traversal, collecting child items of all available sibling items before starting to process those child items. This means output is ordered in increasing depth. With the `--depth-first` flag it uses a stack based recursive descend, which results in output order identical to `jq`'s `recurse`. It can be used in the following ways: - `... | recurse`: Recursively traverses the input value, returns each value it finds as a stream. - `... | recurse foo.bar`: Only descend through the given cell-path. - `... | recurse {|parent| ... }`: Produce child values with a closure. ```nushell { "foo": { "egg": "X" "spam": "Y" } "bar": { "quox": ["A" "B"] } } | recurse | update item { to nuon } # => ╭───┬──────────────┬───────────────────────────────────────────────╮ # => │ # │ path │ item │ # => ├───┼──────────────┼───────────────────────────────────────────────┤ # => │ 0 │ $. │ {foo: {egg: X, spam: Y}, bar: {quox: [A, B]}} │ # => │ 1 │ $.foo │ {egg: X, spam: Y} │ # => │ 2 │ $.bar │ {quox: [A, B]} │ # => │ 3 │ $.foo.egg │ "X" │ # => │ 4 │ $.foo.spam │ "Y" │ # => │ 5 │ $.bar.quox │ [A, B] │ # => │ 6 │ $.bar.quox.0 │ "A" │ # => │ 7 │ $.bar.quox.1 │ "B" │ # => ╰───┴──────────────┴───────────────────────────────────────────────╯ {"name": "/", "children": [ {"name": "/bin", "children": [ {"name": "/bin/ls", "children": []}, {"name": "/bin/sh", "children": []}]}, {"name": "/home", "children": [ {"name": "/home/stephen", "children": [ {"name": "/home/stephen/jq", "children": []}]}]}]} | recurse children | get item.name # => ╭───┬──────────────────╮ # => │ 0 │ / │ # => │ 1 │ /bin │ # => │ 2 │ /home │ # => │ 3 │ /bin/ls │ # => │ 4 │ /bin/sh │ # => │ 5 │ /home/stephen │ # => │ 6 │ /home/stephen/jq │ # => ╰───┴──────────────────╯ {"name": "/", "children": [ {"name": "/bin", "children": [ {"name": "/bin/ls", "children": []}, {"name": "/bin/sh", "children": []}]}, {"name": "/home", "children": [ {"name": "/home/stephen", "children": [ {"name": "/home/stephen/jq", "children": []}]}]}]} | recurse children --depth-first | get item.name # => ╭───┬──────────────────╮ # => │ 0 │ / │ # => │ 1 │ /bin │ # => │ 2 │ /bin/ls │ # => │ 3 │ /bin/sh │ # => │ 4 │ /home │ # => │ 5 │ /home/stephen │ # => │ 6 │ /home/stephen/jq │ # => ╰───┴──────────────────╯ 2 | recurse { ({path: square item: ($in * $in)}) } | take while { $in.item < 100 } # => ╭───┬─────────────────┬──────╮ # => │ # │ path │ item │ # => ├───┼─────────────────┼──────┤ # => │ 0 │ $. │ 2 │ # => │ 1 │ $.square │ 4 │ # => │ 2 │ $.square.square │ 16 │ # => ╰───┴─────────────────┴──────╯ ``` # User-Facing Changes No changes other than the new command. # Tests + Formatting Added tests for examples. (As we can't run them directly as tests yet.) - 🟢 `toolkit test stdlib` # After Submitting - Update relevant parts of https://www.nushell.sh/cookbook/jq_v_nushell.html - `$env.config | recurse | where ($it.item | describe -d).type not-in [list, record, table]` can partially cover the use case of `config flatten`, should we do something? --------- Co-authored-by: Bahex <17417311+Bahex@users.noreply.github.com> |