Commit Graph

17 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:

![image](https://github.com/user-attachments/assets/d5e6f202-db52-42e4-a2ba-fb7c4f1d530a)


![image](https://github.com/user-attachments/assets/b080da2a-7aff-48a9-a523-55c638fdcce3)

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>
2025-06-23 16:29:58 -05:00
fda181d566 Adjust std-rfc/clip deprecation window (#15981)
Follow-up to #15877. That PR was created before 0.105, but merged after
it was released. This PR adjusts the deprecation window from
0.105.0-0.107.0 to 0.106.0-0.108.0
2025-06-16 21:40:37 +02:00
ebcb26f9d5 Promote clip from std-rfc to std (#15877)
# Description
Promotes the clip module from `std-rfc` to `std`. Whether we want to
promote other modules as well (probably?) is up for discussion but I
thought I would get the ball rolling with this one.

# User-Facing Changes
* The `clip` module has been promoted from `std-rfc` to `std`. Using the
`std-rfc` version of clip modules will give a deprecation warning
instructing you to switch to the `std` version.

# Tests + Formatting
N/A

# After Submitting
N/A
2025-06-13 07:26:48 +08:00
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>
2025-06-03 11:21:12 -04:00
88d421dcb6 std-rfc/kv: optimize kv get by only selecting one row from the stor db (#15792)
Optimize std-rfc/kv, kv get to only read one row from the sqlite db.
2025-05-22 21:14:31 -04:00
5483519c7d fix kv set examples (#15769)
As talked in #15588, I have updated the examples of `kv set` so that it
correctly shows how to use the command with closures.
2025-05-17 23:31:46 -04:00
5fecf59f54 Revert "Fix kv set with a closure argument" (#15648)
Reverts nushell/nushell#15588 (see comments there)
2025-04-26 23:00:00 -04:00
6193679dfc Fix kv set with a closure argument (#15588)
<!--
if this PR closes one or more issues, you can automatically link the PR
with
them by using one of the [*linking
keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword),
e.g.
- this PR should close #xxxx
- fixes #xxxx

you can also mention related issues, PRs or discussions!
-->
Fixes #15528 
# Description
Fixed `kv set` passing the pipeline input to the closure instead of the
value stored in that key.

# User-Facing Changes
Now `kv set` will pass the value in that key to the closure.

# Tests + Formatting


# After Submitting
2025-04-22 22:30:38 +08:00
49d86855ce Fixes clip copy stripping control characters when de-ansifying (#15428)
Fixes #15414 by changing the method used to de-ansi-fy the input. Control characters will now be kept when using `clip copy`, but ANSI escape codes will be removed (when not using `--ansi (-a)`)
2025-03-28 19:15:17 -04:00
44b7cfd696 refactor: tree-sitter-nu friendly alternative expressions (#15301)
# Description

Choose more tree-sitter-nu-friendly (if not better) expressions in nu
scripts.
The changes made in this PR all come from known issues of
`tree-sitter-nu`.

1. nested single/double quotes:
https://github.com/nushell/tree-sitter-nu/issues/125
2. module path of `use` command:
https://github.com/nushell/tree-sitter-nu/issues/165
3. where predicates of boolean column:
https://github.com/nushell/tree-sitter-nu/issues/177
4. `error make` keyword:
https://github.com/nushell/tree-sitter-nu/issues/179

Those issues are either hard to fix or "not planned" for syntactical
precision considerations ATM.

# User-Facing Changes

Should be none

# Tests + Formatting

# After Submitting
2025-03-12 08:48:19 -05:00
453e294883 Refactor kv commands: replace inline params in SQL queries (#15108)
# Description

Update some comments and fix potential security issue:

SQL Injection in DELETE statements: The code constructs SQL queries by
interpolating the $key variable directly into the string. If a key
contains malicious input could lead to SQL injection. Need to use
parameterized queries or escaping.
2025-02-13 23:23:59 -05:00
f7d5162582 docs(std-rfc): use actual examples rather than doc comments (#15097)
# Description
Update examples with attributes.

# User-Facing Changes
`std-rfc` commands now have examples.

# Tests + Formatting
N/A

# After Submitting
N/A
2025-02-11 16:33:27 -06:00
18e3a5d40b Fix match blocks in std-rfc/kv implementation (#15089)
Fixes failure surfaced by merging
https://github.com/nushell/nushell/pull/15032
2025-02-11 11:16:57 +01:00
a7830ac1fd Update README.md
Fix link
2025-02-10 09:06:09 -05:00
00713c9339 Update README.md
Fix Drawing-Board link/description
2025-02-10 09:05:05 -05:00
720813339f Add std-rfc README (#15066)
Copied the old README from `nu_scripts/stdlib-candidate/std-rfc` over to `nu-std/std-rfc` and
updated it with the latest info.
2025-02-09 11:21:56 -05:00
5b4dd775d4 Move std-rfc into Nushell (#15042)
Move `std-rfc` into Nushell.  `use std-rfc/<submodule>` now works "out-of-the-box"
2025-02-09 09:03:37 -05:00