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 · 35 comments · May be fixed by #801
Open

Nushell support #463

Tarnadas opened this issue Jun 1, 2021 · 35 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 ])
}

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.