Skip to content

Nushell support#6873

Open
jneem wants to merge 7 commits into
ocaml:masterfrom
jneem:nushell_support
Open

Nushell support#6873
jneem wants to merge 7 commits into
ocaml:masterfrom
jneem:nushell_support

Conversation

@jneem
Copy link
Copy Markdown

@jneem jneem commented Mar 27, 2026

This is a continuation of #6330, adding nushell support.

As in #6330, nushell support for opam env works via json (so the command to populate the environment is load-env (opam env | to json)).

This also adds shell config support, but doesn't yet setup any hooks.

Comment thread src/client/opamConfigCommand.ml Outdated
Comment thread src/client/opamConfigCommand.ml Outdated
Comment thread src/core/opamStd.ml Outdated
Comment on lines +1084 to +1088
let config_home =
try Env.get "XDG_CONFIG_HOME"
with Not_found -> home ".config"
in
Some (List.fold_left Filename.concat config_home ["nushell"; "autoload"; "opam.nu"])
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

the default config location seems to be a bit more complicated than that. In particular, the default $HOME/.config/... is only true on Linux, not macOS or Windows (see https://www.nushell.sh/book/configuration.html#configuration-overview)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I took a stab at improving it, but it's untested on macOS and Windows. For background, nushell uses the dirs crate as a fallback if XDG_CONFIG_HOME is unset. It's behaviour is documented here. On windows, it actually uses win32 bindings, but some random googling suggested that maybe the APPDATA env var would also work...

Comment thread src/state/opamEnv.ml Outdated
Comment thread src/state/opamEnv.ml Outdated
| SH_csh -> Some OpamScript.env_hook_csh
| SH_fish -> Some OpamScript.env_hook_fish
| SH_pwsh _ | SH_cmd -> None
| SH_pwsh _ | SH_cmd | SH_nu -> None
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Not yet done, and I've run out of time for today. I'll re-request a review when it's ready for another look.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Ok, done now.

Comment thread src/state/opamEnv.ml
Comment thread src/state/opamEnv.ml Outdated
let fname = unix_transform ~using_backslashes:true () in
Printf.sprintf "test -r '%s' && source '%s' > /dev/null 2> /dev/null; or true\n" fname fname
| SH_nu ->
Printf.sprintf "const source_path = if ('%s' | path exists) { '%s' } else { null }\nsource $source_path\n" fname fname
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

it feels like it could be shorten to

Suggested change
Printf.sprintf "const source_path = if ('%s' | path exists) { '%s' } else { null }\nsource $source_path\n" fname fname
Printf.sprintf "if ('%s' | path exists) { source '%s' }\n" fname fname

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

It feels like it, but no... for reasons I don't really understand, the source "dep.nu" in

if ("dep.nu" | path exists) { source "dep.nu" }

is evaluated unconditionally at parse time, while the "if" condition is delayed to run time. But, if you write it as

const source_path = if ("dep.nu" | path exists) { "dep.nu"}
source $source_path

then the "if" condition is promoted to parse time. It does look like I can remove the "else null" part, though.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Comment thread src/state/opamEnv.ml Outdated
Comment thread src/state/opamEnv.ml
Comment thread src/state/opamEnv.ml
@kit-ty-kate
Copy link
Copy Markdown
Member

oops i hit enter a bit too fast. Thanks a lot for your contribution, would you have some spare time to look at the issues highlighted above. I think that once they are all fixed this should probably be in a mergeable state

@jneem
Copy link
Copy Markdown
Author

jneem commented Mar 27, 2026

Thanks for the fast response! I should be able to do another iteration over the weekend.

@rjbou rjbou self-requested a review March 30, 2026 14:16
@jneem jneem requested a review from kit-ty-kate March 31, 2026 01:29
@rjbou
Copy link
Copy Markdown
Collaborator

rjbou commented Mar 31, 2026

Thanks for the (follow-up) PR. We discussed it in dev meeting: we need to take into account the fact that nushell is prone to change:

  • make sure that the added commands are part of the baseline of most of versions
  • add a minimal version check when enabled/selected
  • add a note that informs users that their specific versions could not be supported, and a hint on how to disable/fallback on another shell.
  • update (at least) tests/reftests/init-scripts.unix.test with the new nushell files

Otherwise, the current content is quite ok (quite bc it needs to be reviewed).

@jneem
Copy link
Copy Markdown
Author

jneem commented Mar 31, 2026

make sure that the added commands are part of the baseline of most of versions

Do you have any guidance for how to determine "most" here? Nushell maintains a packaging status table, but it isn't completely obvious to me where to draw the line. For example, I often use Debian's packaged version to determine the oldest version that's worth supporting, but apparently Debian doesn't package nushell...

@kit-ty-kate
Copy link
Copy Markdown
Member

kit-ty-kate commented Apr 8, 2026

That's a good question, ideally from that table, i would say "replace debian by <fairly used distribution with the oldest version of nushell>", which in this case is Fedora (0.99.1).

Sadly in this case, it probably complicates things a bit too much, because source null apparently wasn't a thing before 0.102: https://www.nushell.sh/blog/2025-02-04-nushell_0_102_0.html#source-null-use-null-toc

So if that's not possible, i'd say probably 0.104 (latest nushell version in Alpine since 3.22) is a good starting point.

@kit-ty-kate kit-ty-kate added this to the 2.6.0~alpha1 milestone Apr 13, 2026
@jneem
Copy link
Copy Markdown
Author

jneem commented Apr 21, 2026

I spent some time trying to add a minimal version check to the autoload script, with the goal of producing an actionable error when invoked with an old nu. I didn't succeed, though, because the error is raised during parse time. For example, sourcing the script

if (version | get major) == 0 and (version | get minor) < 102 {
  return
}

const s = if ("dep.nu" | path exists) { "dep.nu" }
source $s

with nu 0.99 gives the error

Error: nu::parser::type_mismatch

  × Type mismatch.
   ╭─[/home/<me>/test.nu:6:8]
 5 │ const s = if ("dep.nu" | path exists) { "dep.nu" }
 6 │ source $s
   ·        ─┬
   ·         ╰── expected string, found nothing
   ╰────

The version guard has no effect, because the error occurs before anything is run. I tried a few hacks to get the version guard to run at parse time, but without success (in 0.99, not even the get command can run at parse time -- that appears to have changed sometime between 0.99 and 0.111).

So maybe the best course of action is to hold off on this until 0.102 is old enough that we can assume everyone uses it. In the meantime, direnv and eval $(opam env) give a pretty reasonable nushell-compatible setup.

@kit-ty-kate
Copy link
Copy Markdown
Member

what about simply parsing nu --version in OpamClient.init_checks? (you just need to pass shell to it).

The check would be done only once at init time but i don't expect people to start downgrading their version of nushell, and if so i think they would probably expect something to break.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants