[go: up one dir, main page]

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nushell support #463

Open
Tarnadas opened this issue Jun 1, 2021 · 40 comments · May be fixed by #801
Open

Nushell support #463

Tarnadas opened this issue Jun 1, 2021 · 40 comments · May be fixed by #801
Labels
enhancement New feature or request

Comments

@Tarnadas
Copy link
Tarnadas commented Jun 1, 2021

Now that nushell has an eval-like mechanism for setting environment variables, I’d like to open this feature request to also add support for it.

Via the load-env command, one can set multiple environment variables, see here:
nushell/nushell#3481

Is that enough to make it possible or is something missing?

@Schniz
Copy link
Owner
Schniz commented Jun 1, 2021

It's enough for basic usage. But if we want --use-on-cd we might want to add functions or whatever it is called in nushell. I really want to try nushell again so it might be a nice experiment 😃

@orta
Copy link
orta commented Jun 12, 2021

In the meanwhile - you can get the path edit via:

/home/orta> fnm env | lines | split column '"' | first | get Column2
/tmp/fnm_multishells/10174_1623514914978/bin

Then the rest of the env vars via:

fnm env | str  find-replace -a "export " '' | str find-replace -a '"' '' |  lines | split column = | rename name value | last 5
───┬──────────────────────┬────────────────────────────────────────────
 # │         name         │                   value                    
───┼──────────────────────┼────────────────────────────────────────────
 0 │ FNM_MULTISHELL_PATH  │ "/tmp/fnm_multishells/10210_1623514981704" 
 1 │ FNM_DIR              │ "/home/orta/.fnm"                          
 2 │ FNM_LOGLEVEL         │ "info"                                     
 3 │ FNM_NODE_DIST_MIRROR │ "https://nodejs.org/dist"                  
 4 │ FNM_ARCH             │ "x64"                                      
───┴──────────────────────┴────────────────────────────────────────────

So to mix it all together:

#Update paths
echo $nu.path | append (fnm env | lines | split column '"' | first | get Column2) | config set_into  path

# Add env vars
fnm env | str  find-replace -a "export " '' | str find-replace -a '"' '' |  lines | split column = | rename name value | last 5 | load-env

And at least from some current messing around it seems to work

@ghost
Copy link
ghost commented Aug 9, 2021

Nushell added pathvar command for dynamic path updates. To make work fnm in nushell, add these two commands in the startup:

#load env variables
fnm env --shell bash | lines | last 5 | str find-replace 'export ' '' | str find-replace -a '"' '' | split column = | rename name value | load-env

#add dynamic fnm path
pathvar add $nu.env.FNM_MULTISHELL_PATH

Info: Requires nushell v0.34+ (pathvar command is supported only with v0.34 and above)

@Schniz Schniz added the enhancement New feature or request label Dec 20, 2021
@fellnerse
Copy link

I had to change the path like this:
pathvar add ($nu.env.FNM_MULTISHELL_PATH + /bin)

@Southclaws
Copy link

Nushell has from json so a quick easy way to support this and other experimental shells would be to expose environment variables as a simple JSON object.

I made a super quick Go program for this: https://github.com/Southclaws/fnm-nushell

Install with go install github.com/Southclaws/fnm-nushell@latest then run a short pipeline: fnm env --shell powershell | fnm-nushell | from json | load-env in your nushell config.

@greym0uth
Copy link
greym0uth commented Apr 22, 2022

This is the code I added to my env.nu using nushell 0.61.0 that works:

#load env variables
load-env (fnm env --shell bash | lines | str replace 'export ' '' | str replace -a '"' '' | split column = | rename name value | where name != "FNM_ARCH" && name != "PATH" | reduce -f {} {|it, acc| $acc | upsert $it.name $it.value })

#add dynamic fnm path
let-env PATH = $"($env.FNM_MULTISHELL_PATH)/bin:($env.PATH)"

@dex157
Copy link
dex157 commented May 2, 2022

This is my first experience with nu, so it needs to be tested, but it seems to work:

# FNM
# load env variables
load-env (fnm env --shell bash | lines | str replace 'export ' '' | str replace -a '"' '' | split column = | rename name value | where name != "FNM_ARCH" && name != "PATH" | reduce -f {} {|it, acc| $acc | upsert $it.name $it.value })

# add dynamic fnm path
let-env PATH = ($env.PATH | prepend $"($env.FNM_MULTISHELL_PATH)/bin")

# add fnm with cd
def-env fnmcd [path: string] {
  let-env PWD = ($path | path expand)
  if (['.node-version' '.nvmrc'] | any? ($env.PWD | path join $it | path exists)) {
     fnm use --silent-if-unchanged
  }
}

alias cd = fnmcd

@tuscen
Copy link
tuscen commented May 20, 2022

Could you at least add something like fnm env --json with outputting only fnm related variables there (without modified PATH that is)? In that case we could maintain fnm integration ourselves since nushell is constantly changing. I myself don't really need on-cd functionality and am using fnm as simple nodejs sdk manager.

@jcoppis
Copy link
jcoppis commented Jul 3, 2022

This is the code I added to my env.nu using nushell 0.64.0 that works on WINDOWS:

# FNM for windows
# load env variables
load-env (fnm env --shell cmd | lines | str replace 'SET ' '' | split column = | rename name value | where name != "FNM_ARCH" && name != "PATH" | reduce -f {} {|it, acc| $acc | upsert $it.name $it.value })

# add dynamic fnm path
let-env Path = ($env.Path | prepend $env.FNM_MULTISHELL_PATH)

This was referenced Aug 17, 2022
@azzamsa
Copy link
azzamsa commented Aug 21, 2022

Nu has changed a lot. It is better now. Any plan for fnm to have built-in support for Nushell?

Current workaround inspired by #463 (comment):
Nu 0.67.0, GNU/Linux.

# FNM config

# Parse FNM env from other supported shell. It result should looks like this:
# │ FNM_VERSION_FILE_STRATEGY │ local                          │
# │ FNM_DIR                   │ /home/user/.fnm                |
# Then load these value key pair to Nushell env
load-env (fnm env --shell bash | lines | str replace 'export ' '' | str replace -a '"' '' | split column = | rename name value | where name != "FNM_ARCH" && name != "PATH" | reduce -f {} {|it, acc| $acc | upsert $it.name $it.value })

# Add dynamic FNM path
let-env PATH = ($env.PATH | append [
  $"($env.FNM_MULTISHELL_PATH)/bin"
])

@vajdagabor
Copy link
vajdagabor commented Aug 29, 2022

It seems nushell support is on the way: #801

For the meantime the solution from @azzamsa works for me, but with prepend in the PATH setting.

Nushell has very handy hook feature that can be used to pick node version on directory change. I added this to my config.nu:

let-env config = {
  …
  hooks: {
    env_change: {
      PWD: [{|before, after|
        if ([.nvmrc .node-version] | path exists | any? ($it == true)) {
          fnm use
        }
      }]
    }
  }
  …
}

@remmycat
Copy link

Now that #800 landed in 1.32.0, the setup for nu already got much nicer using the fnm env --json command 🎉

The PR mentions this script:

fnm env --json | from json | load-env
let-env PATH = ($env.PATH | prepend ($env.FNM_MULTISHELL_PATH + "/bin"))

Personally I use this:

^fnm env --json | from json | load-env
let-env PATH = ([([$env.FNM_MULTISHELL_PATH "bin"] | path join) $env.PATH] | str join (char esep))

I concatenate the paths as strings, because this is part of my env.nu where the $env.PATH is not yet parsed as a nu list unless one manually did so. (And I like to rely on path join for adding to a path)

@Fishrock123
Copy link
Fishrock123 commented Nov 26, 2022

Ok so, this is currently in my env.nu, and seems to at least not have nushell 0.71 errors

# FNM
# load env variables
fnm env --json | from json | load-env

# add dynamic fnm path
let-env PATH = ($env.PATH | split row (char esep) | prepend ([$env.FNM_MULTISHELL_PATH "bin"] | path join))

# add fnm with cd
def-env fnmcd [path: string] {
  let-env PWD = ($path | path expand)
  if (['.node-version' '.nvmrc'] | any ($env.PWD | path join $it | path exists)) {
     fnm use --silent-if-unchanged
  }
}

alias cd = fnmcd

@lirc571
Copy link
lirc571 commented Dec 5, 2022

Ok so, this is currently in my env.nu, and seems to at least not have nushell 0.71 errors

# FNM
# load env variables
fnm env --json | from json | load-env

# add dynamic fnm path
let-env PATH = ($env.PATH | split row (char esep) | prepend ([$env.FNM_MULTISHELL_PATH "bin"] | path join))

# add fnm with cd
def-env fnmcd [path: string] {
  let-env PWD = ($path | path expand)
  if (['.node-version' '.nvmrc'] | any ($env.PWD | path join $it | path exists)) {
     fnm use --silent-if-unchanged
  }
}

alias cd = fnmcd

Updated the snippet to work under 0.72:

# FNM
# load env variables
fnm env --json | from json | load-env

# add dynamic fnm path
let-env PATH = ($env.PATH | split row (char esep) | prepend ([$env.FNM_MULTISHELL_PATH "bin"] | path join))

# add fnm with cd
def-env fnmcd [path?: string] {
  if ($path == null) {
    cd
  } else {
    cd ($path | path expand)
  }
  if (['.node-version' '.nvmrc'] | any ($env.PWD | path join $it | path exists)) {
     fnm use --silent-if-unchanged
  }
}

alias cd = fnmcd

@ManneWas
Copy link

Ok so, this is currently in my env.nu, and seems to at least not have nushell 0.71 errors

# FNM
# load env variables
fnm env --json | from json | load-env

# add dynamic fnm path
let-env PATH = ($env.PATH | split row (char esep) | prepend ([$env.FNM_MULTISHELL_PATH "bin"] | path join))

# add fnm with cd
def-env fnmcd [path: string] {
  let-env PWD = ($path | path expand)
  if (['.node-version' '.nvmrc'] | any ($env.PWD | path join $it | path exists)) {
     fnm use --silent-if-unchanged
  }
}

alias cd = fnmcd

Updated the snippet to work under 0.72:

# FNM
# load env variables
fnm env --json | from json | load-env

# add dynamic fnm path
let-env PATH = ($env.PATH | split row (char esep) | prepend ([$env.FNM_MULTISHELL_PATH "bin"] | path join))

# add fnm with cd
def-env fnmcd [path?: string] {
  if ($path == null) {
    cd
  } else {
    cd ($path | path expand)
  }
  if (['.node-version' '.nvmrc'] | any ($env.PWD | path join $it | path exists)) {
     fnm use --silent-if-unchanged
  }
}

alias cd = fnmcd

Thank you for this, saved me a ton of time. Had to make these small changes for it to work for me on windows, but I can't say if it's correct or not confidently.

# FNM
# load env variables
fnm env --json | from json | load-env

# add dynamic fnm path
let-env Path = ($env.Path | split row (char esep) | prepend ([$env.FNM_MULTISHELL_PATH] | path join))

# add fnm with cd
def-env fnmcd [path?: string] {
  if ($path == null) {
    cd
  } else {
    cd ($path | path expand)
  }
  if (['.node-version' '.nvmrc'] | any ($env.PWD | path join $it | path exists)) {
     fnm use --silent-if-unchanged
  }
}

alias cd = fnmcd

@lirc571
Copy link
lirc571 commented Dec 27, 2022

Update for nushell v0.73:

It seems that $it has been removed for any, so any ($env.PWD | path join $it | path exists) needs to be changed to any {|it| $env.PWD | path join $it | path exists}.

We might be using too many unstable features of nushell in the script 😂

@Southclaws
Copy link

That's why I simply wrote it in Go instead 😂

@Fishrock123
Copy link

Full fnm script for nu 0.73

# FNM
# load env variables
fnm env --json | from json | load-env

# add dynamic fnm path
let-env PATH = ($env.PATH | split row (char esep) | prepend ([$env.FNM_MULTISHELL_PATH "bin"] | path join))

# add fnm with cd
def-env fnmcd [path?: string] {
  if ($path == null) {
    cd
  } else {
    cd ($path | path expand)
  }
  if (['.node-version' '.nvmrc'] | any {|it| $env.PWD | path join $it | path exists}) {
     fnm use --silent-if-unchanged
  }
}

alias cd = fnmcd

@sr-mothership
Copy link

On mac I'm getting

 65 │ # load env variables
 66 │ fnm env --json | from json | load-env
    · ─┬─
    ·  ╰── did you mean 'fnmcd'?
 67 │
    ╰────
  help: No such file or directory (os error 2)

How can I solve this? :D

@lirc572
Copy link
lirc572 commented Mar 11, 2023

@sr-mothership You need to have fnm in your PATH first. Add something like let-env PATH = ($env.PATH | split row (char esep) | prepend '/home/ubuntu/.cargo/bin') (change the path to the directory of your fnm binary) before the snippet given above.

@sr-mothership
Copy link

@sr-mothership You need to have fnm in your PATH first. Add something like let-env PATH = ($env.PATH | split row (char esep) | prepend '/home/ubuntu/.cargo/bin') (change the path to the directory of your fnm binary) before the snippet given above.

That is so weird, since I already have let-env PATH = ($env.PATH |split row ":"| prepend $"($env.HOME)/.cargo/bin") in my config.nu 🤔

@lirc572
Copy link
lirc572 commented Mar 13, 2023

@sr-mothership It should be in env.nu instead. Both the let-env command and the snippet above.

@sr-mothership
Copy link

@sr-mothership It should be in env.nu instead. Both the let-env command and the snippet above.

Damn that solved it, haha. Thanks 🙂

@JadoJodo
Copy link
JadoJodo commented Apr 4, 2023

In Nushell 0.77, there is a breaking change related to the use of alias. If you try to use the snippet above, it will break on aliasing cd to the snippet. You can simply rename alias to old-alias, for the time being.

@VuiMuich
Copy link

It seems nushell support is on the way: #801

For the meantime the solution from @azzamsa works for me, but with prepend in the PATH setting.

Nushell has very handy hook feature that can be used to pick node version on directory change. I added this to my config.nu:

let-env config = {
  …
  hooks: {
    env_change: {
      PWD: [{|before, after|
        if ([.nvmrc .node-version] | path exists | any? ($it == true)) {
          fnm use
        }
      }]
    }
  }
  …
}

For nu 0.79.1 I had to change the hook a little bit:

    env_change: {
      PWD: [{|before, after|
        if ([.nvmrc .node-version] | path exists | any {|it| ($it == true)}) {
          fnm use
        }
      }]
    }

@flying-sheep
Copy link
flying-sheep commented Jun 22, 2023

So to summarize:

  1. add to env.nu:

    if not (which fnm | is-empty) {
      ^fnm env --json | from json | load-env
      let-env PATH = ($env.PATH | prepend [
        $"($env.FNM_MULTISHELL_PATH)/bin"
      ])
    }
  2. add to config.nu:

    let-env config = {
      []
      hooks: {
        []
        env_change: {
          PWD: [{ |before, after|
            if ('FNM_DIR' in $env) and ([.nvmrc .node-version] | path exists | any { |it| $it }) {
              fnm use
            }
          }]
        }
        []
      }
      []
    }

If you have fnm on every machine, you can leave out the not (which fnm | is-empty) and 'FNM_DIR' in $env checks.

@hustcer
Copy link
hustcer commented Aug 9, 2023

For fnm 1.3.5 and nu 0.83:

# env.nu
if not (which fnm | is-empty) {
  ^fnm env --json | from json | load-env
  # Checking `Path` for Windows
  let path = if 'Path' in $env { $env.Path } else { $env.PATH }
  let node_path = if (sys).host.name == 'Windows' {
    $"($env.FNM_MULTISHELL_PATH)"
  } else {
    $"($env.FNM_MULTISHELL_PATH)/bin"
  }
  $env.PATH = ($path | prepend [ $node_path ])
}

# config.nu
$env.config = {
   hooks: {
    env_change: {
      PWD: [{ |before, after|
        if ('FNM_DIR' in $env) and ([.nvmrc .node-version] | path exists | any { |it| $it }) {
          fnm use
        }
      }]
    }
  }
}

@marcelarie
Copy link
marcelarie commented Sep 7, 2023

For fnm 1.3.5 and nu 0.83:

@hustcer your solution works for me, but I always get this warning:

warning: The current Node.js path is not on your PATH environment variable.
You should setup your shell profile to evaluate `fnm env`, see https://github.com/Schniz/fnm#shell-setup on how to do this
Check out our documentation for more information: https://fnm.vercel.app```

@hustcer
Copy link
hustcer commented Sep 8, 2023

@marcelarie It works for me, However, You can give this PR a try: https://github.com/nushell/nu_scripts/pull/593/files

@Borber
Copy link
Borber commented Sep 26, 2023

use this: above v0.85 nushell
anywhere: fnm.nu

load-env (fnm env --shell bash | lines | str replace 'export ' '' | str replace -a '"' '' | split column = | rename name value | where name != "FNM_ARCH" and name != "PATH" | reduce -f {} {|it, acc| $acc | upsert $it.name $it.value })

# Add dynamic FNM path
$env.Path = ($env.Path | append [
  $env.FNM_MULTISHELL_PATH
])

then source it in $nu.config-path

source  /path/to/fnm.nu

@jqhr
Copy link
jqhr commented Oct 28, 2023

use this: above v0.85 nushell anywhere: fnm.nu

load-env (fnm env --shell bash | lines | str replace 'export ' '' | str replace -a '"' '' | split column = | rename name value | where name != "FNM_ARCH" and name != "PATH" | reduce -f {} {|it, acc| $acc | upsert $it.name $it.value })

# Add dynamic FNM path
$env.Path = ($env.Path | append [
  $env.FNM_MULTISHELL_PATH
])

then source it in $nu.config-path

source  /path/to/fnm.nu

Work for me.

But how to config for fnm use on cd?

@marcelarie
Copy link
marcelarie commented Oct 30, 2023

For me, this works like a charm:

$env.config = {
   hooks: {
    env_change: {
      PWD: [{ |before, after|
        let is_node_dir = [.nvmrc .node-version] | path exists | any { |it| $it }
        if ('FNM_DIR' in $env) and $is_node_dir {
          fnm use # Personally I prefer to use fnm --log-level=quiet use 
        }
      }]
    }
  }
}

if not (which fnm | is-empty) {
  ^fnm env --json | from json | load-env
  # Checking `Path` for Windows
  let path = if 'Path' in $env { $env.Path } else { $env.PATH }
  let node_path = if (sys).host.name == 'Windows' {
    $"($env.FNM_MULTISHELL_PATH)"
  } else {
    $"($env.FNM_MULTISHELL_PATH)/bin"
  }
  $env.PATH = ($path | prepend [ $node_path ])
}

@connorjs
Copy link
connorjs commented Nov 13, 2023

A slight tweak to the if not block from @marcelarie that I needed to change for my set up (on Windows).

if not (which fnm | is-empty) {
  ^fnm env --json | from json | load-env

  let node_path = if (sys).host.name == 'Windows' {
    $"($env.FNM_MULTISHELL_PATH)"
  } else {
    $"($env.FNM_MULTISHELL_PATH)/bin"
  }

  # Checking `Path` for Windows
  if 'Path' in $env {
    $env.Path = ($env.Path | split row (char esp) | prepend $node_path)
  } else {
    $env.PATH = ($env.PATH | split row (char esp) | prepend $node_path)
  }
}

Of course, I only tried the Windows side. (And we could probably combine the two if-else blocks together.)

Edit: I added the split row bit from the path configuration nushell docs

azzamsa added a commit to azzamsa/dotfiles that referenced this issue Jan 9, 2024
Welcome to the club!

However, after several hours of setup. Nushell is not ready for daily usage.

- [nushell: atuin should not always trigger on ⬆️ · Issue #1025 · atuinsh/atuin](atuinsh/atuin#1025)
- [`column_not_found` in Nushell · sxyazi/yazi · Discussion #501](sxyazi/yazi#501)
- [Generated .zoxide.nu has incorrect syntax · Issue #661 · ajeetdsouza/zoxide](ajeetdsouza/zoxide#661)
- [Nushell support · Issue #463 · Schniz/fnm](Schniz/fnm#463)
- Syntax highlighting still requires manual setup.
  - https://github.com/nushell/tree-sitter-nu/blob/main/installation/neovim.md#manual-installation
- nufmt is still very much in beta.
azzamsa added a commit to azzamsa/dotfiles that referenced this issue Jan 18, 2024
Welcome to the club!

However, after several hours of setup. Nushell is not ready for daily usage.

- [nushell: atuin should not always trigger on ⬆️ · Issue #1025 · atuinsh/atuin](atuinsh/atuin#1025)
- [`column_not_found` in Nushell · sxyazi/yazi · Discussion #501](sxyazi/yazi#501)
- [Generated .zoxide.nu has incorrect syntax · Issue #661 · ajeetdsouza/zoxide](ajeetdsouza/zoxide#661)
- [Nushell support · Issue #463 · Schniz/fnm](Schniz/fnm#463)
- Syntax highlighting still requires manual setup.
  - https://github.com/nushell/tree-sitter-nu/blob/main/installation/neovim.md#manual-installation
- nufmt is still very much in beta.
@FrancescElies
Copy link

This could be simplified a bit further, no need for windows patch check in the end.

# File: config.nu
use std "path add"
if not (which fnm | is-empty) {
  ^fnm env --json | from json | load-env
  let node_path = match $nu.os-info.name {
    "windows" => $"($env.FNM_MULTISHELL_PATH)",
    _ => $"($env.FNM_MULTISHELL_PATH)/bin",
  }
  path add $node_path
}

@gclarkjr5
Copy link

Another tweak to what @marcelarie provided. It seems that the solution was somehow conflicting with my existing config as the banner returned after having been set to False and all of my other custom hooks were no longer taking affect. So I went with this.

export-env {
  $env.config = ($env.config | upsert hooks {
      env_change: {
          PWD: ($env.config.hooks.env_change.PWD ++
            [{
              condition: {|before, after| [.nvmrc .node-version] | path exists | any { |it| $it }}
	      code: {|before, after|
                if ('FNM_DIR' in $env) {
	          fnm use # Personally I prefer to use fnm --log-level=quiet use 
		}
	      }
	  }]
        )
      }
  })
}


if not (which fnm | is-empty) {
  ^fnm env --json | from json | load-env
  # Checking `Path` for Windows
  let path = if 'Path' in $env { $env.Path } else { $env.PATH }
  let node_path = if (sys).host.name == 'Windows' {
    $"($env.FNM_MULTISHELL_PATH)"
  } else {
    $"($env.FNM_MULTISHELL_PATH)/bin"
  }
  $env.PATH = ($path | prepend [ $node_path ])
}

@AbhinavRobinson
Copy link

@gclarkjr5 improvement - sys is deprecated.
(sys).host.name can be updated to (sys host).name

@kuchta
Copy link
kuchta commented Jun 18, 2024
if not (which fnm | is-empty) {
  ^fnm env --resolve-engines --corepack-enabled --json | from json | load-env
  let node_path = match $nu.os-info.name {
    "windows" => $"($env.FNM_MULTISHELL_PATH)",
    _ => $"($env.FNM_MULTISHELL_PATH)/bin",
  }
  $env.PATH = ($env.PATH | prepend [ $node_path ])
}

$env.config = ($env.config | merge {
	hooks: {
		env_change: {
			PWD: [{
				if ([.nvmrc .node-version] | path exists | any { |it| $it }) {
					fnm use
				} else {
					fnm --log-level=quiet use default
				}
			}]
		}
	}
})

fdncred pushed a commit to nushell/nushell that referenced this issue Jun 28, 2024
# Description
The standard library's `path add` function has some surprising side
effects that I attempt to address in this PR:

1. Paths added, if they are symbolic links, should not be resolved to
their targets. Currently, resolution happens.

   Imagine the following:

   ```nu
# Some time earlier, perhaps even not by the user, a symlink is created
   mkdir real-dir
   ln -s real-dir link-dir

   # Then, step to now, with link-dir that we want in our PATHS variable
   use std
   path add link-dir
   ```

In the current implementation of `path add`, it is _not_ `link-dir` that
will be added, as has been stated in the command. It is instead
`real-dir`. This is surprising. Users have the agency to do this
resolution if they wish with `path expand` (sans a `--no-symlink` flag):
for example, `path add (link-dir | path expand)`

In particular, when I was trying to set up
[fnm](https://github.com/Schniz/fnm), a Node.js version manager, I was
bitten by this fact when `fnm` told me that an expected path had not
been added to the PATHS variable. It was looking for the non-resolved
link. The user in [this
comment](Schniz/fnm#463 (comment))
was likely affected by this too.

Shells, such as nushell, can handle path symlinks just fine. Binary
lookup is unaffected. Let resolution be opt-in.

Lastly, there is some convention already in place for **not** resolving
path symlinks in the [default $env.ENV_CONVERSIONS
table](https://github.com/nushell/nushell/blob/57452337ff4e228102433e99b4c6000700a9b3b2/crates/nu-utils/src/sample_config/default_env.nu#L65).
   
2. All existing paths in the path variable should be left untouched.
Currently, they are `path expand`-ed (including symbolic link
resolution).

   Path add should mean just that: prepend/append this path.

Instead, it currently means that, _plus mutate all other paths in the
variable_.

Again, users have the agency to do this with something like `$env.PATH =
$env.PATH | split row (char esep) | path expand`.

3. Minorly, I update documentation on running tests in
`crates/nu-std/CONTRIBUTING.md`. The offered command to run the standard
library test suite was no longer functional. Thanks to @weirdan in [this
Discord
conversation](https://discord.com/channels/601130461678272522/614593951969574961/1256029201119576147)
for the context.

# User-Facing Changes

(Written from the perspective of release notes)

- The standard library's `path add` function no longer resolves symlinks
in either the newly added paths, nor the other paths already in the
variable.

# Tests + Formatting

A test for the changes working correctly has been added to
`crates/nu-std/tests/test_std.nu` under the test named
`path_add_expand`.

You can quickly verify this new test and the existing `path add` test
with the following command:

```nu
cargo run -- -c 'use crates/nu-std/testing.nu; NU_LOG_LEVEL=INFO testing run-tests --path crates/nu-std --test path_add'
```

All commands suggested in the issue template have been run and complete
without error.

# After Submitting
I'll add a release note to [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged.
@SetsuikiHyoryu
Copy link
SetsuikiHyoryu commented Sep 24, 2024

In nushell 0.98.0, I followed the tutorial in $nu.env-path:

# To add entries to PATH (on Windows you might use Path), you can use the following pattern:
# $env.PATH = ($env.PATH | split row (char esep) | prepend '/some/path')
# An alternate way to add entries to $env.PATH is to use the custom command `path add`
# which is built into the nushell stdlib:
# use std "path add"
# $env.PATH = ($env.PATH | split row (char esep))
# path add /some/path
# path add ($env.CARGO_HOME | path join "bin")
# path add ($env.HOME | path join ".local" "bin")
# $env.PATH = ($env.PATH | uniq)

I successfully accessed Node by adding the following three lines:

fnm env --json | from json | load-env
$env.PATH = ($env.PATH | split row (char esep) | prepend $env.FNM_MULTISHELL_PATH)
$env.PATH = ($env.PATH | uniq)

Here, both --json and from json | load-env were things I learned from the issue comments, but I could also deduce them from the documentation upon reviewing it.

What confuses me, however, is that the FNM_MULTISHELL_PATH for Node seems to be something I can only learn from the comments in src/config.rs, which means that I can't correctly infer the configuration method just by looking at the documentation (meaning without asking or checking the source code).

I’m not sure if I missed something in the documentation, and if not, I hope the authors can optimize it.

@constneo
Copy link

NuShell v0.98.0

Windows11

# ~/fnm.nu
use std "path add"

$env.FNM_DIR = "D:/fnm"
$env.FNM_BIN = "D:/fnm/bin"
path add $env.FNM_BIN


$env.FNM_MULTISHELL_PATH = "D:/fnm/nodejs"
path add $env.FNM_MULTISHELL_PATH

Add source ~/fnm.nu at config.nu.

fnm install 20.17.0
fnm install 22.9.0

fnm use v20.17.0
node -v
v20.17.0

fnm use v22.9.0
node -v
v22.9.0

It's working.

However, there is a slight error in the fnm environment variable FNM_MULTISHELL_PATH.

fnm env --json | from json

╭───────────────────────────┬──────────────────────────────────────────────────────────────────╮
│ FNM_MULTISHELL_PATH       │ C:\Users\[demo]\AppData\Local\fnm_multishells\1832_1727301725051 │
│ FNM_RESOLVE_ENGINES       │ false                                                            │
│ FNM_LOGLEVEL              │ info                                                             │
│ FNM_VERSION_FILE_STRATEGY │ local                                                            │
│ FNM_COREPACK_ENABLED      │ false                                                            │
│ FNM_DIR                   │ D:/fnm                                                           │
│ FNM_ARCH                  │ x64                                                              │
╰───────────────────────────┴──────────────────────────────────────────────────────────────────╯

[demo]: your username

If you want environment variables to display correctly, you need to change the code.

// config.rs
- multishell_path: Option<std::path::PathBuf>,
+ pub multishell_path: Option<std::path::PathBuf>,

//env.rs
- let _multishell_path = make_symlink(config)?;
+ let mut multishell_path = make_symlink(config)?;

+ if config.multishell_path.is_some() {
+     multishell_path = config.multishell_path.clone().unwrap();
+ };
cargo build

alias fnm2 = `path/to/fnm/target/debug/fnm.exe`

fnm2 env --json | from json

╭───────────────────────────┬───────────────────────────────────╮
│ FNM_MULTISHELL_PATH       │ D:/fnm/nodejs                     │
│ FNM_DIR                   │ D:/fnm                            │
│ FNM_LOGLEVEL              │ info                              │
│ FNM_RESOLVE_ENGINES       │ false                             │
│ FNM_VERSION_FILE_STRATEGY │ local                             │
│ FNM_ARCH                  │ x64                               │
│ FNM_COREPACK_ENABLED      │ false                             │
╰───────────────────────────┴───────────────────────────────────╯

Enjoy it.

@tymokvo
Copy link
tymokvo commented Oct 4, 2024

Using @constneo 's example, I was able to get a minimal working setup using nushell on Windows 10 via Windows Terminal by adding:

path/to/config.nu:

fnm env --json | from json | load-env

use std "path add"

$env.FNM_BIN = $"($env.FNM_DIR)/bin"
path add $env.FNM_BIN

$env.FNM_MULTISHELL_PATH = $"($env.FNM_DIR)/nodejs"
path add $env.FNM_MULTISHELL_PATH

This works with the fnm that was installed from winget.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.