Skip to content

Fix quoted string handling#11

Merged
sophiajt merged 1 commit intonushell:masterfrom
sophiajt:fix_quotes
May 18, 2019
Merged

Fix quoted string handling#11
sophiajt merged 1 commit intonushell:masterfrom
sophiajt:fix_quotes

Conversation

@sophiajt
Copy link
Copy Markdown
Contributor

This fixes quoted strings as arguments, so you can now pass them to executed commands.

@sophiajt sophiajt merged commit 362ca18 into nushell:master May 18, 2019
@sophiajt sophiajt deleted the fix_quotes branch May 18, 2019 14:45
ahkrr pushed a commit to ahkrr/nushell that referenced this pull request Jun 24, 2021
* WIP

* Move alt+arrow
Hofer-Julian pushed a commit to Hofer-Julian/nushell that referenced this pull request Jan 27, 2023
Trying to fix nushell#11 with common fonts for the different operating systems
sholderbach pushed a commit that referenced this pull request Mar 7, 2023
# Description
i tried yesterday to `encode` with an invalid character set and this is
what i got
```bash
>_ {alg: "HS256", type: "JWT"} | to json -r | encode base64 --character-set invalid-character-set
Error:
  × value is not an accepted character set
   ╭─[entry #11:1:1]
 1 │ {alg: "HS256", type: "JWT"} | to json -r | encode base64 --character-set invalid-character-set
   ·                                                                          ──────────┬──────────
   ·                                                                                    ╰── invalid-character-set is not a valid character-set.
Please use `help hash base64` to see a list of valid character sets.
   ╰────
```

but `hash base64` is now a deprecated command, see `help hash base64`.

=> **this PR changes the error message to mention `help encode base64`,
where the list of valid character sets is, instead**

# User-Facing Changes
```
$nothing
```

# Tests + Formatting
- 🟢 `cargo fmt --all`
- 🟢 `cargo clippy --workspace -- -D warnings -D
clippy::unwrap_used -A clippy::needless_collect`
- 🟢 `cargo test --workspace`

# After Submitting
```
$nothing
```
sholderbach pushed a commit that referenced this pull request Sep 26, 2023
Fixes: #10476

After the change, the error message will be something like this:
```nushell
❯ not null
Error: nu::shell::type_mismatch

  × Type mismatch.
   ╭─[entry #11:1:1]
 1 │ not null
   ·     ──┬─
   ·       ╰── expected bool, found nothing
   ╰────
```
amtoine added a commit that referenced this pull request Oct 1, 2023
should close #10549 

# Description
this PR is twofold
- uses `to nuon --raw` in the error messages to make sure #10549 is
solved and makes a difference between `"1"` and `1`
- tries to introduce slightly better errors, i.e. by putting left /
right on new lines => this should hopefully help when the values become
a bit big 😋

# User-Facing Changes
the original issue:
```nushell
> assert equal {one:1 two:2} {one:"1" two:"2"}
Error:   × Assertion failed.
   ╭─[entry #3:1:1]
 1 │ assert equal {one:1 two:2} {one:"1" two:"2"}
   ·              ───────────────┬───────────────
   ·                             ╰── These are not equal.
        Left  : '{one: 1, two: 2}'
        Right : '{one: "1", two: "2"}'
   ╰────
```

a sample for all the assertions and their new messages
```nushell
> assert equal {one:1 two:2} {one:"1" two:"2"}
Error:   × Assertion failed.
   ╭─[entry #3:1:1]
 1 │ assert equal {one:1 two:2} {one:"1" two:"2"}
   ·              ───────────────┬───────────────
   ·                             ╰── These are not equal.
        Left  : '{one: 1, two: 2}'
        Right : '{one: "1", two: "2"}'
   ╰────
```
```nushell
> assert equal 1 2
Error:   × Assertion failed.
   ╭─[entry #4:1:1]
 1 │ assert equal 1 2
   ·              ─┬─
   ·               ╰── These are not equal.
        Left  : '1'
        Right : '2'
   ╰────
```
```nushell
> assert less 3 1
Error:   × Assertion failed.
   ╭─[entry #6:1:1]
 1 │ assert less 3 1
   ·             ─┬─
   ·              ╰── The condition *left < right* is not satisfied.
        Left  : '3'
        Right : '1'
   ╰────
```
```nushell
> assert less or equal 3 1
Error:   × Assertion failed.
   ╭─[entry #7:1:1]
 1 │ assert less or equal 3 1
   ·                      ─┬─
   ·                       ╰── The condition *left <= right* is not satisfied.
        Left  : '3'
        Right : '1'
   ╰────
```
```nushell
> assert greater 1 3
Error:   × Assertion failed.
   ╭─[entry #8:1:1]
 1 │ assert greater 1 3
   ·                ─┬─
   ·                 ╰── The condition *left > right* is not satisfied.
        Left  : '1'
        Right : '3'
   ╰────
```
```nushell
> assert greater or equal 1 3
Error:   × Assertion failed.
   ╭─[entry #9:1:1]
 1 │ assert greater or equal 1 3
   ·                         ─┬─
   ·                          ╰── The condition *left < right* is not satisfied.
        Left  : '1'
        Right : '3'
   ╰────
```
```nushell
> assert length [1 2 3] 2
Error:   × Assertion failed.
   ╭─[entry #10:1:1]
 1 │ assert length [1 2 3] 2
   ·               ────┬────
   ·                   ╰── This does not have the correct length:
        value    : [1, 2, 3]
        length   : 3
        expected : 2
   ╰────
```
```nushell
> assert length [1 "2" 3] 2
Error:   × Assertion failed.
   ╭─[entry #11:1:1]
 1 │ assert length [1 "2" 3] 2
   ·               ─────┬─────
   ·                    ╰── This does not have the correct length:
        value    : [1, "2", 3]
        length   : 3
        expected : 2
   ╰────
```
```nushell
> assert str contains "foo" "bar"
Error:   × Assertion failed.
   ╭─[entry #13:1:1]
 1 │ assert str contains "foo" "bar"
   ·                     ─────┬─────
   ·                          ╰── This does not contain '($right)'.
        value: "foo"
   ╰────
```

# Tests + Formatting

# After Submitting
hardfau1t pushed a commit to hardfau1t/nushell that referenced this pull request Dec 14, 2023
Fixes: nushell#10476

After the change, the error message will be something like this:
```nushell
❯ not null
Error: nu::shell::type_mismatch

  × Type mismatch.
   ╭─[entry nushell#11:1:1]
 1 │ not null
   ·     ──┬─
   ·       ╰── expected bool, found nothing
   ╰────
```
hardfau1t pushed a commit to hardfau1t/nushell that referenced this pull request Dec 14, 2023
should close nushell#10549 

# Description
this PR is twofold
- uses `to nuon --raw` in the error messages to make sure nushell#10549 is
solved and makes a difference between `"1"` and `1`
- tries to introduce slightly better errors, i.e. by putting left /
right on new lines => this should hopefully help when the values become
a bit big 😋

# User-Facing Changes
the original issue:
```nushell
> assert equal {one:1 two:2} {one:"1" two:"2"}
Error:   × Assertion failed.
   ╭─[entry nushell#3:1:1]
 1 │ assert equal {one:1 two:2} {one:"1" two:"2"}
   ·              ───────────────┬───────────────
   ·                             ╰── These are not equal.
        Left  : '{one: 1, two: 2}'
        Right : '{one: "1", two: "2"}'
   ╰────
```

a sample for all the assertions and their new messages
```nushell
> assert equal {one:1 two:2} {one:"1" two:"2"}
Error:   × Assertion failed.
   ╭─[entry nushell#3:1:1]
 1 │ assert equal {one:1 two:2} {one:"1" two:"2"}
   ·              ───────────────┬───────────────
   ·                             ╰── These are not equal.
        Left  : '{one: 1, two: 2}'
        Right : '{one: "1", two: "2"}'
   ╰────
```
```nushell
> assert equal 1 2
Error:   × Assertion failed.
   ╭─[entry nushell#4:1:1]
 1 │ assert equal 1 2
   ·              ─┬─
   ·               ╰── These are not equal.
        Left  : '1'
        Right : '2'
   ╰────
```
```nushell
> assert less 3 1
Error:   × Assertion failed.
   ╭─[entry nushell#6:1:1]
 1 │ assert less 3 1
   ·             ─┬─
   ·              ╰── The condition *left < right* is not satisfied.
        Left  : '3'
        Right : '1'
   ╰────
```
```nushell
> assert less or equal 3 1
Error:   × Assertion failed.
   ╭─[entry nushell#7:1:1]
 1 │ assert less or equal 3 1
   ·                      ─┬─
   ·                       ╰── The condition *left <= right* is not satisfied.
        Left  : '3'
        Right : '1'
   ╰────
```
```nushell
> assert greater 1 3
Error:   × Assertion failed.
   ╭─[entry nushell#8:1:1]
 1 │ assert greater 1 3
   ·                ─┬─
   ·                 ╰── The condition *left > right* is not satisfied.
        Left  : '1'
        Right : '3'
   ╰────
```
```nushell
> assert greater or equal 1 3
Error:   × Assertion failed.
   ╭─[entry nushell#9:1:1]
 1 │ assert greater or equal 1 3
   ·                         ─┬─
   ·                          ╰── The condition *left < right* is not satisfied.
        Left  : '1'
        Right : '3'
   ╰────
```
```nushell
> assert length [1 2 3] 2
Error:   × Assertion failed.
   ╭─[entry nushell#10:1:1]
 1 │ assert length [1 2 3] 2
   ·               ────┬────
   ·                   ╰── This does not have the correct length:
        value    : [1, 2, 3]
        length   : 3
        expected : 2
   ╰────
```
```nushell
> assert length [1 "2" 3] 2
Error:   × Assertion failed.
   ╭─[entry nushell#11:1:1]
 1 │ assert length [1 "2" 3] 2
   ·               ─────┬─────
   ·                    ╰── This does not have the correct length:
        value    : [1, "2", 3]
        length   : 3
        expected : 2
   ╰────
```
```nushell
> assert str contains "foo" "bar"
Error:   × Assertion failed.
   ╭─[entry nushell#13:1:1]
 1 │ assert str contains "foo" "bar"
   ·                     ─────┬─────
   ·                          ╰── This does not contain '($right)'.
        value: "foo"
   ╰────
```

# Tests + Formatting

# After Submitting
WindSoilder added a commit that referenced this pull request Nov 27, 2024
# Description
Fixes:  #13159

After the change, `std help` will no-longer print out "double error"
messages.

Actually I think it's tricky to make it right. To make `help <cmd>`
keeps paging feature from fallback `man` command. I have to split
`commands` into `scope-commands` and `external-commands`.

If we don't split it, simply call `let commands = (try { commands
$target_item --find $find })` in `help main` will cause us to lost
paging feature, which is not we want.

A comment from original issue:

> If there are no objections, I'd like to remove the man page fallback
code from std help for the moment. While it's probably fixable, it's
also platform specific and requires testing on all platforms. It also
seems like a low-value add here.

Actually I think it's a beautiful feature of `std help`, so I want to
keep it here.

# User-Facing Changes
### Before
```nushell
> help commands asdfadsf
Help pages from external command asdfadsf:
No manual entry for asdfadsf
Error:   × std::help::command_not_found
   ╭─[entry #11:1:15]
 1 │ help commands asdfadsf
   ·               ────┬───
   ·                   ╰── command not found
   ╰────
```

### After
```nushell
> help commands asdfasdf
Help pages from external command asdfasdf:
No manual entry for asdfasdf
```

# Tests + Formatting
Actually it's a little hard to add test because it required user input
(especially for fallback `man` command)
WindSoilder pushed a commit that referenced this pull request Jan 15, 2025
…14765)

# Description
This PR removes the required positional argument from `run-external` and
`exec` in favor of the rest arguments, meaning lists of external
commands can be spread directly into `run-external` and `exec`. This
does have the drawback of making calling `run-external` and `exec` with
no arguments a run-time error rather than a parse error, but I don't
imagine that is an issue.

Before (for both `run-external` and `exec`):
```nushell
run-external
# => Error: nu::parser::missing_positional
# => 
# =>   × Missing required positional argument.
# =>    ╭─[entry #9:1:13]
# =>  1 │ run-external
# =>    ╰────
# =>   help: Usage: run-external <command> ...(args) . Use `--help` for more
# =>         information.

let command = ["cat" "hello.txt"]
run-external ...$command
# => Error: nu::parser::missing_positional
# => 
# =>   × Missing required positional argument.
# =>    ╭─[entry #11:1:14]
# =>  1 │ run-external ...$command
# =>    ·              ▲
# =>    ·              ╰── missing command
# =>    ╰────
# =>   help: Usage: run-external <command> ...(args) . Use `--help` for more
# =>         information.
run-external ($command | first) ...($command | skip 1)
# => hello world!
```

After (for both `run-external` and `exec`):
```nushell
run-external
# => Error: nu:🐚:missing_parameter
# => 
# =>   × Missing parameter: no command given.
# =>    ╭─[entry #2:1:1]
# =>  1 │ run-external
# =>    · ──────┬─────
# =>    ·       ╰── missing parameter: no command given
# =>    ╰────
# => 

let command = ["cat" "hello.txt"]
run-external ...$command
# => hello world!
```



# User-Facing Changes
Lists can now be spread directly into `run-external` and `exec`:

```nushell
let command = [cat hello.txt]
run-external ...$command
# => hello world!
``` 

# Tests + Formatting
- 🟢 `toolkit fmt`
- 🟢 `toolkit clippy`
- 🟢 `toolkit test`
- 🟢 `toolkit test stdlib`

# After Submitting
N/A
sholderbach pushed a commit that referenced this pull request Apr 10, 2025
Issue #12289, can be closed when this is merged

# Description
Currently, the ``into datetime`` command's signature indicates that it
supports input as record, but it was actually not supported.

This PR implements this feature.

# User-Facing Changes

``into datetime``'s signature changed (see comments)

**Happy paths**

Note: I'm in +02:00 timezone.

```nushell
> date now | into record | into datetime
Fri, 4 Apr 2025 18:32:34 +0200 (now)

> {year: 2025, month: 12, day: 6, second: 59} | into datetime | into record
╭─────────────┬────────╮
│ year        │ 2025   │
│ month       │ 12     │
│ day         │ 6      │
│ hour        │ 0      │
│ minute      │ 0      │
│ second      │ 59     │
│ millisecond │ 0      │
│ microsecond │ 0      │
│ nanosecond  │ 0      │
│ timezone    │ +02:00 │
╰─────────────┴────────╯

> {day: 6, second: 59, timezone: '-06:00'} | into datetime | into record
╭─────────────┬────────╮
│ year        │ 2025   │
│ month       │ 4      │
│ day         │ 6      │
│ hour        │ 0      │
│ minute      │ 0      │
│ second      │ 59     │
│ millisecond │ 0      │
│ microsecond │ 0      │
│ nanosecond  │ 0      │
│ timezone    │ -06:00 │
╰─────────────┴────────╯
```

**Edge cases**

```nushell
{} | into datetime
Fri, 4 Apr 2025 18:35:19 +0200 (now)
```

**Error paths**

- A key has a wrong type
  ```nushell
  > {month: 12, year: '2023'} | into datetime
  Error: nu::shell::only_supports_this_input_type

    × Input type not supported.
    ╭─[entry #8:1:19]
  1 │ {month: 12, year: '2023'} | into datetime
    ·                   ───┬──    ──────┬──────
· │ ╰── only int input data is supported
    ·                      ╰── input type: string
    ╰────
  ```
  ```nushell
  > {month: 12, year: 2023, timezone: 100} | into datetime
  Error: nu:🐚:only_supports_this_input_type

    × Input type not supported.
    ╭─[entry #10:1:35]
  1 │ {month: 12, year: 2023, timezone: 100} | into datetime
    ·                                   ─┬─    ──────┬──────
· │ ╰── only string input data is supported
    ·                                    ╰── input type: int
    ╰────
  ```
- Key has the right type but value invalid (e.g. month=13, or day=0)
  ```nushell
  > {month: 13, year: 2023} | into datetime
  Error: nu:🐚:incorrect_value

    × Incorrect value.
    ╭─[entry #9:1:1]
  1 │ {month: 13, year: 2023} | into datetime
    · ───────────┬───────────   ──────┬──────
· │ ╰── one of more values are incorrect and do not represent valid date
    ·            ╰── encountered here
    ╰────
  ```
  ```nushell
  > {hour: 1, minute: 1, second: 70} | into datetime
  Error: nu:🐚:incorrect_value
  
    × Incorrect value.
     ╭─[entry #3:1:1]
   1 │ {hour: 1, minute: 1, second: 70} | into datetime
     · ────────────────┬───────────────   ──────┬──────
· │ ╰── one of more values are incorrect and do not represent valid time
     ·                 ╰── encountered here
     ╰────
  ```
- Timezone has right type but is invalid
  ```nushell
  > {month: 12, year: 2023, timezone: "+100:00"} | into datetime
  Error: nu:🐚:incorrect_value

    × Incorrect value.
    ╭─[entry #11:1:35]
  1 │ {month: 12, year: 2023, timezone: "+100:00"} | into datetime
    ·                                   ────┬────    ──────┬──────
· │ ╰── encountered here
    ·                                       ╰── invalid timezone
    ╰────
  ```
- Record contains an invalid key
  ```nushell
  > {month: 12, year: 2023, unknown: 1} | into datetime
  Error: nu:🐚:unsupported_input

    × Unsupported input
    ╭─[entry #12:1:1]
  1 │ {month: 12, year: 2023, unknown: 1} | into datetime
    · ─────────────────┬─────────────────   ──────┬──────
· │ ╰── Column 'unknown' is not valid for a structured datetime. Allowed
columns are: year, month, day, hour, minute, second, millisecond,
microsecond, nanosecond, timezone
    ·                  ╰── value originates from here
    ╰────
  ```
- If several issues are present, the user can get the error msg for only
one, though
  ```nushell
  > {month: 20, year: '2023'} | into datetime
  Error: nu:🐚:only_supports_this_input_type

    × Input type not supported.
    ╭─[entry #7:1:19]
  1 │ {month: 20, year: '2023'} | into datetime
    ·                   ───┬──    ──────┬──────
· │ ╰── only int input data is supported
    ·                      ╰── input type: string
    ╰
  ```


# Tests + Formatting
Tests added
Fmt + clippy OK

# After Submitting
Maybe indicate that in the release notes
I added an example in the command, so the documentation will be
automatically updated.
ysthakur pushed a commit that referenced this pull request Jul 4, 2025
<!--
if this PR closes one or more issues, you can automatically link the PR
with
them by using one of the [*linking
keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword),
e.g.
- this PR should close #xxxx
- fixes #xxxx

you can also mention related issues, PRs or discussions!
-->

# Description
<!--
Thank you for improving Nushell. Please, check our [contributing
guide](../CONTRIBUTING.md) and talk to the core team before making major
changes.

Description of your pull request goes here. **Provide examples and/or
screenshots** if your changes affect the user experience.
-->

Rel: #14429, #16079

Finishes up a TODO in the assignment type checking. 

- For regular assignment operations (only applies to `mut`), type
checking is now done using `type_compatible` (which is what `let` uses)
- This allows some mutable assignments to work which weren't allowed
before

Before:
```nushell
let x: glob = "" 
# => ok, no error
mut x: glob = ""; $x = ""
# => Error: nu::parser::operator_incompatible_types
# => 
# =>   × Types 'glob' and 'string' are not compatible for the '=' operator.
# =>    ╭─[entry #6:1:19]
# =>  1 │ mut x: glob = ""; $x = ""
# =>    ·                   ─┬ ┬ ─┬
# =>    ·                    │ │  ╰── string
# =>    ·                    │ ╰── does not operate between 'glob' and 'string'
# =>    ·                    ╰── glob
# =>    ╰────

let x: number = 1
# ok, no error
mut x: number = 1; $x = 2
# => Error: nu::parser::operator_incompatible_types
# => 
# =>   × Types 'number' and 'int' are not compatible for the '=' operator.
# =>    ╭─[source:1:20]
# =>  1 │ mut x: number = 1; $x = 2
# =>    ·                    ─┬ ┬ ┬
# =>    ·                     │ │ ╰── int
# =>    ·                     │ ╰── does not operate between 'number' and 'int'
# =>    ·                     ╰── number
# =>    ╰────
```

After:
```nushell
let x: glob = ""
# ok, no error (same as before)
mut x: glob = ""; $x = ""
# ok, no error

let x: number = 1
# ok, no error (same as before)
mut x: number = 1; $x = 2
# ok, no error
```

- Properly type check compound operations. First checks if the operation
(eg. `+` for `+=`) type checks successfully, and then checks if the
assignment type checks successfully (also using `type_compatible`)
- This fixes some issues where the "long version" of a compound
assignment operator would error, but the compound assignment operator
itself would not

Before:
```nushell
mut x = 1; $x = $x / 2
# => Error: nu::parser::operator_incompatible_types
# => 
# =>   × Types 'int' and 'float' are not compatible for the '=' operator.
# =>    ╭─[entry #15:1:12]
# =>  1 │ mut x = 1; $x = $x / 2
# =>    ·            ─┬ ┬ ───┬──
# =>    ·             │ │    ╰── float
# =>    ·             │ ╰── does not operate between 'int' and 'float'
# =>    ·             ╰── int
# =>    ╰────

mut x = 1; $x /= 2
# uh oh, no error...

mut x = (date now); $x = $x - 2019-05-10
# => Error: nu::parser::operator_incompatible_types
# => 
# =>   × Types 'datetime' and 'duration' are not compatible for the '=' operator.
# =>    ╭─[entry #1:1:21]
# =>  1 │ mut x = (date now); $x = $x - 2019-05-10
# =>    ·                     ─┬ ┬ ───────┬───────
# =>    ·                      │ │        ╰── duration
# =>    ·                      │ ╰── does not operate between 'datetime' and 'duration'
# =>    ·                      ╰── datetime
# =>    ╰────

mut x = (date now); $x -= 2019-05-10
# uh oh, no error... (the result of this is a duration, not a datetime)
```

After:
```nushell
mut x = 1; $x = $x / 2
# => Error: nu::parser::operator_incompatible_types
# => 
# =>   × Types 'int' and 'float' are not compatible for the '=' operator.
# =>    ╭─[entry #5:1:12]
# =>  1 │ mut x = 1; $x = $x / 2
# =>    ·            ─┬ ┬ ───┬──
# =>    ·             │ │    ╰── float
# =>    ·             │ ╰── does not operate between 'int' and 'float'
# =>    ·             ╰── int
# =>    ╰────

mut x = (date now); $x -= 2019-05-10
# => Error: nu::parser::operator_incompatible_types
# => 
# =>   × Types 'datetime' and 'datetime' are not compatible for the '-=' operator.
# =>    ╭─[entry #11:1:21]
# =>  1 │ mut x = (date now); $x -= 2019-05-10
# =>    ·                     ─┬ ─┬ ─────┬────
# =>    ·                      │  │      ╰── datetime
# =>    ·                      │  ╰── does not operate between 'datetime' and 'datetime'
# =>    ·                      ╰── datetime
# =>    ╰────
# =>   help: The result type of this operation is not compatible with the type of the variable.
```

This is technically a breaking change if you relied on the old behavior
(for example, there was a test that broke after this change because it
relied on `/=` improperly type checking)

# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->
* Mutable assignment operations now use the same type checking rules as
normal assignments
* For example, `$x = 123` now uses the same type checking rules as `let
x = 123` or `mut x = 123`
* Compound assignment operations now type check using the same rules as
the operation they use
* Assignment errors will also now highlight the invalid assignment
operator in red


# Tests + Formatting
<!--
Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use toolkit.nu; toolkit test stdlib"` to run the
tests for the standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->
Adds some tests for the examples given above

# After Submitting
<!-- If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
-->
N/A
fdncred pushed a commit that referenced this pull request Dec 18, 2025
## User-facing Changes

* New arguments! (`error make "hello"`)
* New parts for `error_struct`! (`error make {inner: [] labels: []
...}`)
* Pipeline inputs for chained errors! (`try {error make foo} catch
{error make bar}`)
* Pipeline inputs for normal errors! (`"help" | error make`)
* External errors! (`error make {src: {path: $nu.cofig-path} ...}`)
* Backwards compatibility!

### Arguments and Inputs

The main changes are in how the arguments are passed. Everything is
still backwards compatible with the old `error make` commands, there's
just a nice extra layer we get from the pipeline and a few new args
(that were already added in #17037). There are some new ways to
(hopefully intentionally) cause an error, such as using a naked `error
make`, pipelines from records and simple string input!

#### Inputs

Because `error make` will just make an error anyway, it can technically
take any input to make an error, but only properly formatted record
input will create a chain. the `x | f $in` pattern can be used for
string input, if that is more comfortable.

#### With no arguments

This is a completely new way to do this, with no arguments the `error
make` invocation is highlighted, along with a simple `originates from
here` message. This makes normal errors very easy to create without any
special message setup.

```
> error make
Error: nu::shell::error

  × originates from here
   ╭─[entry #4:1:1]
 1 │ error make
   · ──────────
   ╰────
```

#### Create a single argument

* With pipeline input: `{msg: foo} | error make`
* With an argument: `error make {msg: foo}`
* With a string argument: `error make foo`
```
Error: nu:🐚:error

  × foo
   ╭─[entry #2:1:12]
 1 │ error make {msg: foo}
   ·            ──────────
   ╰────
```
#### Chaining errors together

These will automatically create a chain of errors, placing the pipeline
as an `inner` to the argument. This can very easily be used to get a bit
more detail in a try loop using the naked `error make`:

```
Error: nu:🐚:error

  × originates from here
   ╭─[source:1:31]
 1 │ try {error make "foo"} catch {error make}
   ·                               ──────────
   ╰────

Error: nu:🐚:error

  × foo
   ╭─[source:1:6]
 1 │ try {error make "foo"} catch {error make}
   ·      ──────────
   ╰────
```

Or with more complex errors:

* With both, combining the errors: `{msg: foo} | error make bar`
* With the raw error from try: `try {error make foo} catch {error make
bar}`

Both are equivalent to:
* `error make {msg: bar inner: [{msg: foo}]}`

```
Error: nu:🐚:error

  × bar
   ╭─[entry #1:1:29]
 1 │ try {error make foo} catch {error make bar}
   ·                             ──────────
   ╰────

Error: nu:🐚:error

  × foo
   ╭─[entry #1:1:6]
 1 │ try {error make foo} catch {error make bar}
   ·      ──────────
   ╰────
```

### Labels

As is noticeable in the examples above, simple errors no longer use an
extra line for the label. If no label is present, `error make` will
place a bar under the span of itself or the argument to `error make`.
Labels have also gotten a bit of a rewrite, but they're pretty much the
same as those in #17037, except for `label`, which is now only a single
label (not `oneof<list, label>`).
#### Simple Labels

`label.text` and `labels.*.text` is no longer required for a span to
show up, an empty text will simply underline. This example can either
use `label: $record` or be written as `labels: [$record]`:

```
> def f [x] {
  error make {msg: here label: {span: (metadata $x).span}}
}
f abcd
Error: nu::shell::error

  × here
   ╭─[entry #7:4:3]
 3 │ }
 4 │ f abcd
   ·   ────
   ╰────
```

#### Multiple labels
Any number of labels can be added in the `labels` column, allowing for
more detailed error messages, especially for functions:

```
> def f [x y z] {
  error make {msg: here labels: [
    {text: "there" span: (metadata $x).span}
    {text: "everywhere" span: (metadata $y).span}
    {text: "somewhere" span: (metadata $z).span}
  ]
  }
}
f abcd [x y z] {d: a}

Error: nu:🐚:error

  × here
   ╭─[entry #11:9:3]
 8 │ }
 9 │ f abcd [x y z] {d: a}
   ·   ──┬─ ───┬─── ───┬──
   ·     │     │       ╰── somewhere
   ·     │     ╰── everywhere
   ·     ╰── there
   ╰────
```

#### External sources

There is a `ShellError::OutsideSpannedLabeledError` that can be used to
refer to external sources, not just the internal nushell spanns. This
has been expanded to allow the multi-label stuff to work using the new
`src` column:

```
> "foo\nbar\nbaz" | save -f /tmp/foo.bar
error make {
  msg: 'error here'
  src: {path: /tmp/foo.bar}
  labels: [
    {text: "this" span: {start: 4 end: 7}}
  ]
}
Error: nu:🐚:outside

  × error here
   ╭─[/tmp/foo.bar:2:1]
 1 │ foo
 2 │ bar
   · ─┬─
   ·  ╰── this
 3 │ baz
   ╰────
```

### Errors That Can't be Caught

These will not work since `try` will never get parsed:

- `try {1 + ""} catch {error make badmath}`
- (TODO: Add more examples)

## Internal Changes

Most of the parsing from an error record to an actual error is now moved
into `nu-protocol`, using `FromValue` to turn it into a useful internal
type.

### `nu-protocol::LabeledError`

This struct has a few changes, the main one being the type of
`LabeledError.inner`. It is now a `ShellError`, not another
`LabeledError`. It should be trivial to do a `.into()` for things that
already use `LabeledError.with_inner(x)`.

### `nu-protocol::ShellError::into_value`

I renamed the old `into_value` to `into_full_value` to better say what
it is, since it doesn't just do the `IntoValue::into_value` method, it
also requires some context to create the `Value`. Now `ShellError` has
an `IntoValue` implementation matching other types.

### `nu-protocol::ShellError::{OutsideSource, OutsideSourceNoUrl}`

Miette's derived types don't have a nice way to maybe include a url, so
there are now two types! These allow using multiple labels on outside
sources. They are used internally for the new `{src: {}}` part of the
`error_struct`, and they look a lot more like the `LabeledError`, but
without the need for a separate type and all the fun `impl`s that would
require for the `Diagnostic::source_code` method.

### Misc

* Spelling fix: `into_chainned` => `into_chained`

## Current bugs:
- [x] `OutsideSpannedLabeledError`  
The inner most error of `try {']' from nuon} catch {error make}` will
reference `span: {start: 0, end: 1}`, which in `']' from nuon` will
point to the `]` character, but when it does this in `error make` as an
input it will point to the very first character (probably the `n` in
`nu`).

## Release notes summary - What our users need to know

### New `error make` functionality!
* New arguments! (`error make "hello"`)
* New parts for `error_struct`! (`error make {inner: [] labels: []
...}`)
* Pipeline inputs for chained errors! (`try {error make foo} catch
{error make bar}`)
* Pipeline inputs for normal errors! (`"help" | error make`)
* External errors! (`error make {src: {path: $nu.cofig-path} ...}`)
* Backwards compatibility!


## Tasks after submitting
<!-- Remove any tasks which aren't relevant for your PR, or add your own
-->
- [ ] Update the
[documentation](https://github.com/nushell/nushell.github.io)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant