Skip to content

Conversation

@jokeyrhyme
Copy link
Contributor

  • addresses the unexpected behaviour discussed here: `mise activate nu` emits invalid code #6876
  • previously, work was done to have mise reverse the changes it made to the environment variables: fix(activate): reset PATH when activate is called multiple times #6829
  • however, for nushell, this resulted in the raw operations CSV text becoming part of the activation script, which is not valid nushell syntax
  • this PR wraps the raw operations CSV text in quotes to make it a string literal, and then passes it through | parse env | update-env just as with other places in the nushell script that make use of the raw operations CSV text
  • in order for that work, the parse env and update-env functions were re-ordered to always be above the deactivation statements

@theutz
Copy link

theutz commented Nov 17, 2025

Thank you for doing this! My love for both Nushell and Mise has made me yearn to learn Rust so I can help out, but I haven't had a chance yet. :D

@@ -0,0 +1,38 @@
#! /usr/bin/env sh
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would you mind adding nushell to either the coverage github action tests or mise.toml so they actually get run in CI? these tests otherwise won't do any good

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure thing!

Copy link
Contributor Author

@jokeyrhyme jokeyrhyme Nov 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

huh, any special reason why the Windows end-to-end tests were automated via GitHub Actions, but not the rest of the end-to-end tests?

edit: ignore me, i found them in the "nightly" Action, although they don't seem to log any output to stdout which is intriguing ...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mise run e2e --list works on my machine and outputs the full list to stdout

i'm not sure mise run e2e (what is already in "nightly") or even mise run e2e --all actually does anything at the moment ...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jdx well, i've explicitly added the nushell end-to-end tests in "nightly", but i think a follow-up PR is needed to fix the rest of the end-to-end tests, unless you're okay with only the nushell ones running? 🤷

@jokeyrhyme jokeyrhyme force-pushed the fix-nushell-generate-valid-deactivate-statements-for-nushell-0-108-0 branch 2 times, most recently from 9100a4a to bc83799 Compare November 18, 2025 00:42
@jdx
Copy link
Owner

jdx commented Nov 18, 2025

that biome test failure is unrelated. I am going to try to fix it tomorrow

@jokeyrhyme
Copy link
Contributor Author

jokeyrhyme commented Nov 18, 2025

oh, hang on, all of the end-to-end tests, including the nushell ones, are spread out across the "coverage" Actions, so explicitly adding the nushell tests to the "nightly" Action wasn't necessary

(but i do need to ensure that nu is available in the "coverage" Actions)

@jokeyrhyme jokeyrhyme force-pushed the fix-nushell-generate-valid-deactivate-statements-for-nushell-0-108-0 branch from dd1a5f9 to fa24ac2 Compare November 18, 2025 04:23
@jokeyrhyme
Copy link
Contributor Author

yay, for fa24ac2 :

E2E shell/test_nushell
  removed 'e2e_nushell_init.Beo2r5iJkQ'
  shell/test_nushell: 0s
E2E shell/test_nushell_deactivation
  mise WARN  Failed to deserialize __MISE_DIFF: Invalid input length: 1
  removed 'e2e_nushell_init.DP4HhGPMjm'
  shell/test_nushell_deactivation: 0s

@jdx jdx merged commit 9ff02f6 into jdx:main Nov 18, 2025
26 checks passed
jdx pushed a commit that referenced this pull request Nov 18, 2025
### 📦 Registry

- add tbls by @artemklevtsov in
[#6987](#6987)

### 🐛 Bug Fixes

- **(nushell)** add missing `| parse env | update-env` for deactivation
operations by @jokeyrhyme in
[#6994](#6994)
- **(pwsh)** wrap the executable path with double quotes by @leosuncin
in [#6993](#6993)
- in `activate bash` output, wrap mise executable path in single-quotes
by @cspotcode in [#7002](#7002)

### 📚 Documentation

- simplify apt instructions by @scop in
[#6986](#6986)
- update idiomatic version files enablement info by @scop in
[#6985](#6985)

### 🧪 Testing

- **(aqua)** remove biome test due to version incompatibility by @jdx in
[#7000](#7000)

### 📦️ Dependency Updates

- lock file maintenance by @renovate[bot] in
[#6997](#6997)

### New Contributors

- @jokeyrhyme made their first contribution in
[#6994](#6994)
- @cspotcode made their first contribution in
[#7002](#7002)
- @artemklevtsov made their first contribution in
[#6987](#6987)
- @leosuncin made their first contribution in
[#6993](#6993)

## 📦 Aqua Registry Updates

#### New Packages (1)

-
[`houseabsolute/omegasort`](https://github.com/houseabsolute/omegasort)

#### Updated Packages (5)

- [`apache/maven`](https://github.com/apache/maven)
- [`chaqchase/lla`](https://github.com/chaqchase/lla)
- [`leoafarias/fvm`](https://github.com/leoafarias/fvm)
- [`rustic-rs/rustic`](https://github.com/rustic-rs/rustic)
- [`sigstore/rekor`](https://github.com/sigstore/rekor)
@jokeyrhyme jokeyrhyme deleted the fix-nushell-generate-valid-deactivate-statements-for-nushell-0-108-0 branch November 18, 2025 08:17
@theutz
Copy link

theutz commented Nov 18, 2025

I just downloaded this and tried to use it, but it's giving a "Parse mismatch during operation" error, pointing to the definition for parse vars, and then saying "expected not a pipeline". So, it's actually more broken than before, and the old workaround doesn't seem to fix it.

@jokeyrhyme
Copy link
Contributor Author

@theutz eek! i'm not getting anything like that on this machine, but it might be worth reverting this PR out of caution ...

which version of nushell do you have?

what is the full output of ^mise activate nu for you?

@theutz
Copy link

theutz commented Nov 18, 2025

I'm using 0.108.0.

Error Message
Error: nu::parser::parse_mismatch

× Parse mismatch during operation.
╭─[/Users/michael/.local/share/nushell/vendor/autoload/mise.nu:1:1]
1 │ ╭─▶ def "parse vars" [] {
2 │ │ $in | from csv --noheaders --no-infer | rename 'op' 'name' 'value'
3 │ │ }
4 │ │
5 │ │ def --env "update-env" [] {
6 │ │ for $var in $in {
7 │ │ if $var.op == "set" {
8 │ │ if ($var.name | str upcase) == 'PATH' {
9 │ │ $env.PATH = ($var.value | split row (char esep))
10 │ │ } else {
11 │ │ load-env {($var.name): $var.value}
12 │ │ }
13 │ │ } else if $var.op == "hide" and $var.name in $env {
14 │ │ hide-env $var.name
15 │ │ }
16 │ │ }
17 │ │ }
18 │ │ "set,PATH,/opt/homebrew/sbin:/opt/homebrew/bin:/Users/michael/.local/bin:/Users/michael/bin:/usr/local/bin:/Users/michael/.config/composer/vendor/bin:/Users/michael/.config/carapace/bin:/usr/bin:/bin:/usr/sbin:/sbin
19 │ │ hide,MISE_SHELL,
20 │ │ hide,__MISE_DIFF,
21 │ │ hide,__MISE_DIFF,
22 │ │ " | parse vars | update-env
23 │ │ export-env {
24 │ │
25 │ │ $env.MISE_SHELL = "nu"
26 │ │ let mise_hook = {
27 │ │ condition: { "MISE_SHELL" in $env }
28 │ │ code: { mise_hook }
29 │ │ }
30 │ │ add-hook hooks.pre_prompt $mise_hook
31 │ │ add-hook hooks.env_change.PWD $mise_hook
32 │ │ }
33 │ │
34 │ │ def --env add-hook [field: cell-path new_hook: any] {
35 │ │ let field = $field | split cell-path | update optional true | into cell-path
36 │ │ let old_config = $env.config? | default {}
37 │ │ let old_hooks = $old_config | get $field | default []
38 │ │ $env.config = ($old_config | upsert $field ($old_hooks ++ [$new_hook]))
39 │ │ }
40 │ │
41 │ │ export def --env --wrapped main [command?: string, --help, ...rest: string] {
42 │ │ let commands = ["deactivate", "shell", "sh"]
43 │ │
44 │ │ if ($command == null) {
45 │ │ ^"/Users/michael/.local/bin/mise"
46 │ │ } else if ($command == "activate") {
47 │ │ $env.MISE_SHELL = "nu"
48 │ │ } else if ($command in $commands) {
49 │ │ ^"/Users/michael/.local/bin/mise" $command ...$rest
50 │ │ | parse vars
51 │ │ | update-env
52 │ │ } else {
53 │ │ ^"/Users/michael/.local/bin/mise" $command ...$rest
54 │ │ }
55 │ │ }
56 │ │
57 │ │ def --env mise_hook [] {
58 │ │ ^"/Users/michael/.local/bin/mise" hook-env -s nu
59 │ │ | parse vars
60 │ │ | update-env
61 │ │ }
62 │ ├─▶
· ╰──── expected not a pipeline
╰────

Output from ^mise activate nu

def "parse vars" [] {
$in | from csv --noheaders --no-infer | rename 'op' 'name' 'value'
}

def --env "update-env" [] {
for $var in $in {
if $var.op == "set" {
if ($var.name | str upcase) == 'PATH' {
$env.PATH = ($var.value | split row (char esep))
} else {
load-env {($var.name): $var.value}
}
} else if $var.op == "hide" and $var.name in $env {
hide-env $var.name
}
}
}
"set,PATH,/opt/homebrew/sbin:/opt/homebrew/bin:/Users/michael/.local/bin:/Users/michael/bin:/usr/local/bin:/Users/michael/.config/composer/vendor/bin:/Users/michael/.config/carapace/bin:/usr/bin:/bin:/usr/sbin:/sbin
hide,MISE_SHELL,
hide,__MISE_DIFF,
hide,__MISE_DIFF,
" | parse vars | update-env
export-env {

$env.MISE_SHELL = "nu"
let mise_hook = {
condition: { "MISE_SHELL" in $env }
code: { mise_hook }
}
add-hook hooks.pre_prompt $mise_hook
add-hook hooks.env_change.PWD $mise_hook
}

def --env add-hook [field: cell-path new_hook: any] {
let field = $field | split cell-path | update optional true | into cell-path
let old_config = $env.config? | default {}
let old_hooks = $old_config | get $field | default []
$env.config = ($old_config | upsert $field ($old_hooks ++ [$new_hook]))
}

export def --env --wrapped main [command?: string, --help, ...rest: string] {
let commands = ["deactivate", "shell", "sh"]

if ($command == null) {
^"/Users/michael/.local/bin/mise"
} else if ($command == "activate") {
$env.MISE_SHELL = "nu"
} else if ($command in $commands) {
^"/Users/michael/.local/bin/mise" $command ...$rest
| parse vars
| update-env
} else {
^"/Users/michael/.local/bin/mise" $command ...$rest
}
}

def --env mise_hook [] {
^"/Users/michael/.local/bin/mise" hook-env -s nu
| parse vars
| update-env
}

@jokeyrhyme
Copy link
Contributor Author

very mysterious

I'm not having any of that on my machine

and nushell in the coverage tests does source this and doesn't complain, so what is different here ... ?

@kdar
Copy link

kdar commented Nov 18, 2025

I'm also having this same issue with the latest nushell and mise on Windows.

nushell:

╭─────────┬─────────╮
│ channel │ release │
│ current │ true    │
│ latest  │ 0.108.0 │
╰─────────┴─────────╯

mise:

2025.11.6 windows-x64 (2025-11-18)

@jokeyrhyme
Copy link
Contributor Author

wait, Windows? @theutz are you also on Windows?
I wonder if this is a line ending thing ...
i personally tested this change during development on macOS and Linux, but not Windows ...

@theutz
Copy link

theutz commented Nov 19, 2025

I'm not using Windows, no. I'm on macOS Tahoe.

@theutz
Copy link

theutz commented Nov 19, 2025

Yeah, I don't know where those errors would be coming from. I've gone over the nushell code, and it doesn't make any sense. I'm not an expert in nu, but nothing seems too out of place to me.

I guess the only thing that might not make sense to me is the presence of these lines in the activate output:

"set,PATH,/opt/homebrew/sbin:/opt/homebrew/bin:/Users/michael/.local/bin:/Users/michael/bin:/usr/local/bin:/Users/michael/.config/composer/vendor/bin:/Users/michael/.config/carapace/bin:/usr/bin:/bin:/usr/sbin:/sbin
hide,MISE_SHELL,
hide,__MISE_DIFF,
hide,__MISE_DIFF,
" | parse vars | update-env

If we're treating the output of this command as a module, should that code be beneath the export-env line?

@jokeyrhyme
Copy link
Contributor Author

i find nushell can occasionally be wildly confused about the origin coordinates of an error

there was only one export-env { ... } in the original output of mise active nu before this PR, and this PR doesn't change what does and doesn't happen there

it'd be interesting to selectively delete/change parts of your output from mise active nu to try to narrow down exactly which part is making it explode when it gets sourced

@theutz
Copy link

theutz commented Nov 19, 2025

Good idea! So, I tried commenting everything out, and the culprit seems to be fact that line. If the script is used instead of sourced, I think it might not be proper semantics to write a pipeline in the top-level of the module like that. I think it has to go in the export-env. And, indeed, when I manually move it there, it works.

@jokeyrhyme
Copy link
Contributor Author

oh! i use source instead of use, even though the mise documentation says to use: https://mise.jdx.dev/installing-mise.html#nushell

that's the difference! if i replace source ~/.cache/init/mise.nu with use ~/.cache/init/mise.nu then i can reproduce the error

i think because the atuin documentation says source ( https://docs.atuin.sh/guide/installation/#installing-the-shell-plugin ) i guess maybe copied that approach for mise in my own settings

okay, excellent, i can reproduce locally and hence test locally and hence raise a PR to fix this confidently :)

@jokeyrhyme
Copy link
Contributor Author

here we go: #7013

@theutz
Copy link

theutz commented Nov 19, 2025

Thank you, sir!

jdx pushed a commit that referenced this pull request Nov 19, 2025
- the previous PR ( #6994 ) made the
incorrect assumption that the output of `mise activate nu` will be
`source`d from a nushell configuration, but our documentation
specifically says it should be `use`d instead (
https://mise.jdx.dev/installing-mise.html#nushell )
- this PR changes our nushell end-to-end tests accordingly, and moves
the generated lines relating to the CSV text down into the `export-env {
... }` block to fix the parser errors
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.

4 participants