Closed CWSpear closed 2 years ago
(Sorry, I edited this post quite a bit from the original cuz it was poorly laid out, sorry if this version doesn't match what you might have gotten in an email.)
hehe, no worries, it's a holiday here and I forgot to bring a charger home π
While
fnm
is much faster, the latter is not really needed, it'd still be nice to have this sort of capability so that one does not need to seeUsing latest-dubnium
every since time they switch directories when it's the same.nvmrc
(which would happen a lot if it had the parent search).
We can add a --silent-if-unchanged
flag so it won't add noise to the terminal. I wonder if there's anything smarter we can do. Maybe this can just be the default for use
, and making a debug log for Doesn't need to change anything
. I just don't want people to think that fnm doesn't work when it actually does work π¦
What do you think?
nvm
has aversion
subcommand that will return the exact (installed) version that matches given input, i.e.:
We can implement this. Shouldn't be that hard, because it is mostly reusing stuff we already have πOne step before actually symlinking π
The only open question regarding this feature, is something that relates to every feature β should we show what you'll use
, or what you'll install
?
If you have 10.0.0 installed, but there is 10.2.0 upstream, what should we show?
nvm_find_nvmrc
*
Currently we only look on the current directory. Didn't know that nvm does that. Do you think we should change the current behavior? I don't see the big benefit right now, but I might be wrong!
I'm all for more options, so if you wanna make this or that more optional, that's good.
In terms of what I think are reasonable expectations: I think it's pretty important that it would revert to default
when it doesn't find an .nvmrc
(or .node-version
or whatever the other one is). I am a contractor working on multiple projects and have clients that make a big deal about using specific lts releases, but I want to use latest work I'm just messing around with stuff.
This would mean that if I'm anywhere in a project with .nvmrc
at its root, it should be on that same version (i.e. the closest ancestor's .nvmrc
). I'm not in a place to test, but I'm 99.9% sure if you nvm use
in a subdirectory that does not have .nvmrc
in it, it will search in parent directories for one.
As for, "should it install/should it compare to the latest upstream version," again, I wouldn't mind options, but I think it's reasonable to just use the latest installed version (i.e. nvm use
). Which does offer to install latest if no alias matches (which nvm
does not, but I like that fnm
does).
This is the current script I use:
fnm-nvmrc() {
nvmrc_path=$(find-up .nvmrc | tr -d '[:space:]')
if [ -n "$nvmrc_path" ]; then
nvm_version=`cat $nvmrc_path/.nvmrc`
fnm use $nvm_version
else
echo "Reverting to fnm default version"
fnm use default
fi
}
find-up() {
path=$(pwd)
while [[ "$path" != "" && ! -e "$path/$1" ]]; do
path=${path%/*}
done
echo "$path"
}
It'd be nice to have a "compare current version with version in .nvmrc
to see if they are a match (i.e. if I'm on v10.6.1
that is aliased to lts/dubnium
and that's what's in .nvmrc
, it's a match), then it won't call fnm use
. Since fnm
is so fast, maybe it's fine if it just compares afterwards to see if it changed and (optionally?) not output if it didn't change, like you suggested. Not a bad compromise, as long as fnm use
remains super fast!! :)
Just leaving this here in case someone finds it useful.
I modified the --use-on-cd output and the recommendations above to only revert when necessary, so changing dirs is still super fast.
find-up() {
path=$(pwd)
while [[ "$path" != "" && ! -e "$path/$1" ]]; do
path=${path%/*}
done
echo "$path"
}
FNM_USING_LOCAL_VERSION=0
autoload -U add-zsh-hook
_fnm_autoload_hook() {
nvmrc_path=$(find-up .nvmrc | tr -d '[:space:]')
if [ -n "$nvmrc_path" ]; then
FNM_USING_LOCAL_VERSION=1
nvm_version=$(cat $nvmrc_path/.nvmrc)
fnm use $nvm_version
elif [ $FNM_USING_LOCAL_VERSION -eq 1 ]; then
FNM_USING_LOCAL_VERSION=0
fnm use default
fi
}
add-zsh-hook chpwd _fnm_autoload_hook &&
_fnm_autoload_hook
A little update,
since fnm don't need to have the version in arg if there is .nvmrc or .node-version, so no need for the find-up function:
FNM_USING_LOCAL_VERSION=0
autoload -U add-zsh-hook
_fnm_autoload_hook() {
if [[ -f .nvmrc && -r .nvmrc || -f .node-version && -r .node-version ]]; then
FNM_USING_LOCAL_VERSION=1
fnm use --install-if-missing
elif [ $FNM_USING_LOCAL_VERSION -eq 1 ]; then
FNM_USING_LOCAL_VERSION=0
fnm use default
fi
}
add-zsh-hook chpwd _fnm_autoload_hook &&
_fnm_autoload_hook
We can add a
--silent-if-unchanged
flag so it won't add noise to the terminal. I wonder if there's anything smarter we can do. Maybe this can just be the default foruse
, and making a debug log forDoesn't need to change anything
. I just don't want people to think that fnm doesn't work when it actually does work π¦
@Schniz
I'm all in for --silent-if-unchanged
flag π
OK, I've just figured out that I can just modify it and use fnm use --log-level=quiet
instead of fnm use
Here's the fish shell version if anyone needs it.
It supports
.nvmrc
or .node-version
file # ~/.config/fish/conf.d/node.fish
function find_up
set path (pwd)
while true
if test -e "$path/$argv[1]"
echo "$path/$argv[1]"
return
end
if test -e "$path/$argv[2]"
echo "$path/$argv[2]"
return
end
if test $path = "/"
return
end
set path (dirname $path)
end
end
function fnm_use
set current (string replace "v" "" (fnm current))
set target (string replace "v" "" $argv[1])
if test $current != $target
fnm use $argv[1]
end
end
function _fnm_autoload_hook --on-variable PWD --description 'Change Node version on directory change'
status --is-command-substitution; and return
set found (find_up .nvmrc .node-version)
if test -n "$found"
fnm_use (cat $found)
else
fnm_use system
end
end
fnm env | source
# VSCode open integrated terminal does not trigger PWD hook
if test "$TERM_PROGRAM" = "vscode"
_fnm_autoload_hook
end
woah, these scripts are crazy π
Maybe it's time to revisit it and add do a recursive (upwards) search for the dotfiles? π This can be configured behind a "feature toggle" and if it will make sense we can make it the default in future release.
Hope I have time soon to make it work π
My version of this script for Bash and .nvmrc
It doesn't check current version or version in file, it only cares whether the path to current .nvmrc
has changed.
__fnm_nvm_path="init"
__fnm_update_version() {
local path=$PWD
while [[ "$path" != "" && ! -e "$path/.nvmrc" ]]; do
path=${path%/*}
done
if [[ "$path" != "$__fnm_nvm_path" ]]; then
if [[ -z "$path" ]]; then
fnm use --log-level quiet default
else
fnm use --log-level quiet $(<"$path/.nvmrc")
fi
__fnm_nvm_path="$path"
fi
}
PROMPT_COMMAND="__fnm_update_version"
Thanks @gutenye for the fish shell version. I had to make one small change due to this error:
test: Missing argument at index 2
~/.config/fish/conf.d/node.fish (line 40):
if test $TERM_PROGRAM = "vscode"
^
from sourcing file ~/.config/fish/conf.d/node.fish
called on line 294 of file /usr/share/fish/config.fish
from sourcing file /usr/share/fish/config.fish
called during startup
(Type 'help test' for related documentation)
I wrapped the $TERM_PROGRAM
argument in double quotes, like so:
if test "$TERM_PROGRAM" = "vscode"
Seems to be working great now. I'm using fish, version 3.1.2
.
Hi, I'm using this script as my automatic switch, and I've just found out that it doesn't work with tags (e.g. lts-latest
, default
).
.nvmrc file
lts-latest
eval "$(fnm env)"
FNM_USING_LOCAL_VERSION=0
autoload -U add-zsh-hook
_fnm_autoload_hook () {
if [[ -f .nvmrc && -r .nvmrc || -f .node-version && -r .node-version ]]; then
FNM_USING_LOCAL_VERSION=1
fnm use --install-if-missing
elif [ $FNM_USING_LOCAL_VERSION -eq 1 ]; then
FNM_USING_LOCAL_VERSION=0
fnm use default --install-if-missing
fi
}
add-zsh-hook chpwd _fnm_autoload_hook \
&& _fnm_autoload_hook
I've uninstalled version default
and lts-latest
and when I'm opening the project on my terminal, then I get
error: Requested version lts-latest is not currently installed
@Schniz, do you have any idea how to tackle this? Maybe I'm doing something wrong? Please let me know.
Hi, I'm using this script as my automatic switch, and I've just found out that it doesn't work with tags (e.g.
lts-latest
,default
)..nvmrc file
lts-latest
eval "$(fnm env)" FNM_USING_LOCAL_VERSION=0 autoload -U add-zsh-hook _fnm_autoload_hook () { if [[ -f .nvmrc && -r .nvmrc || -f .node-version && -r .node-version ]]; then FNM_USING_LOCAL_VERSION=1 fnm use --install-if-missing elif [ $FNM_USING_LOCAL_VERSION -eq 1 ]; then FNM_USING_LOCAL_VERSION=0 fnm use default --install-if-missing fi } add-zsh-hook chpwd _fnm_autoload_hook \ && _fnm_autoload_hook
I've uninstalled version
default
andlts-latest
and when I'm opening the project on my terminal, then I geterror: Requested version lts-latest is not currently installed
looks like a bug. Will take a look when I have some more time soon π
this is how it can be reproduced:
$ fnm uninstall 'lts/*'
$ echo 'lts/*' > .node-version
$ fnm use --install-if-missing
looks like a bug. Will take a look when I have some more time soon π
Hi @Schniz! Any news on this bug? Should I make a separate issue with it?
opened π
here is my custom zsh function:
autoload -U add-zsh-hook
load-nvmrc() {
DEFAULT_NODE_VERSION=`$FNM_DIR/aliases/default/bin/node -v`
if [[ (-f .nvmrc && -r .nvmrc) || (-f .node-version && -r .node-version) ]]; then
fnm use --install-if-missing --silent-if-unchanged
elif [[ `node -v` != $DEFAULT_NODE_VERSION ]]; then
echo Reverting to node from "`node -v`" to "$DEFAULT_NODE_VERSION"
fnm use $DEFAULT_NODE_VERSION
fi
}
add-zsh-hook chpwd load-nvmrc
(Sorry, I edited this post quite a bit from the original cuz it was poorly laid out, sorry if this version doesn't match what you might have gotten in an email.)
The
nvm
docs have scripts that you can add to your .zshrc, etc, similar to the script used withfnm env --use-on-cd
, but with better support in searching ancestors for.nvmrc
and not switching unless the version is actually from the version.While
fnm
is much faster, the latter is not really needed, it'd still be nice to have this sort of capability so that one does not need to seeUsing latest-dubnium
every since time they switch directories when it's the same.nvmrc
(which would happen a lot if it had the parent search).The
fnm env --use-on-cd
one also doesn't support switching back todefault
.nvm
has a couple of things to help out with accomplishing this:nvm version
nvm
has aversion
subcommand that will return the exact (installed) version that matches given input, i.e.:This does not do a lookup, but it based on aliases, so if
v.10.16.0
is the latest lts/dubnium you have,nvm version lts/dubnium
will return that.nvm_find_nvmrc
*This one isn't as big of a deal, because there are lots of other simple scripts out there to do this thing, but it provides a helper function to find the nearest
.nvmrc
by first looking inpwd
and then checking each ancestor directory.*I think
nvm_find_nvmrc
must be a zsh-specific thing because it's not used in the bash version in thenvm
docs. It just uses a fairly standard implementation of "find-up":