nvm-sh / nvm

Node Version Manager - POSIX-compliant bash script to manage multiple active node.js versions
MIT License
78.9k stars 7.9k forks source link

Please add xonsh support so nvm can be run from xonsh #2748

Closed meramsey closed 2 years ago

meramsey commented 2 years ago

Operating system and version:

NAME="Pop!_OS" VERSION="21.10" ID=pop ID_LIKE="ubuntu debian" PRETTY_NAME="Pop!_OS 21.10" VERSION_ID="21.10" HOME_URL="https://pop.system76.com" SUPPORT_URL="https://support.system76.com" BUG_REPORT_URL="https://github.com/pop-os/pop/issues" PRIVACY_POLICY_URL="https://system76.com/privacy" VERSION_CODENAME=impish UBUNTU_CODENAME=impish LOGO=distributor-logo-pop-os

nvm debug output:

```sh nvm --version: v0.39.0 $SHELL: /bin/bash $SHLVL: 1 whoami: 'mike' ${HOME}: /home/mike ${NVM_DIR}: '${HOME}/.nvm' ${PATH}: ${HOME}/.sdkman/candidates/gradle/current/bin:${HOME}/.pyprojectx:${HOME}/.pyenv/plugins/pyenv-virtualenv/shims:${HOME}/.pyenv/shims:${HOME}/.pyenv/bin:${NVM_DIR}/versions/node/v12.22.1/bin:${HOME}/.pyenv/shims:${HOME}/.pyenv/bin:${HOME}/.cargo/bin:${HOME}/.poetry/bin:${HOME}/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin $PREFIX: '' ${NPM_CONFIG_PREFIX}: '' $NVM_NODEJS_ORG_MIRROR: '' $NVM_IOJS_ORG_MIRROR: '' shell version: 'GNU bash, version 5.1.8(1)-release (x86_64-pc-linux-gnu)' uname -a: 'Linux 5.15.15-76051515-generic #202201160435~1642693824~21.10~97db1bb SMP Thu Jan 20 17:35:05 U x86_64 x86_64 x86_64 GNU/Linux' checksum binary: 'sha256sum' OS version: Pop!_OS 21.10 curl: /usr/bin/curl, curl 7.74.0 (x86_64-pc-linux-gnu) libcurl/7.74.0 OpenSSL/1.1.1l zlib/1.2.11 brotli/1.0.9 libidn2/2.3.1 libpsl/0.21.0 (+libidn2/2.3.0) libssh/0.9.6/openssl/zlib nghttp2/1.43.0 librtmp/2.3 wget: /usr/bin/wget, GNU Wget 1.21 built on linux-gnu. git: /usr/bin/git, git version 2.32.0 grep: /usr/bin/grep (grep --color=auto), grep (GNU grep) 3.7 awk: /usr/bin/awk, GNU Awk 5.1.0, API: 3.0 (GNU MPFR 4.1.0, GNU MP 6.2.1) sed: /usr/bin/sed, sed (GNU sed) 4.7 cut: /usr/bin/cut, cut (GNU coreutils) 8.32 basename: /usr/bin/basename, basename (GNU coreutils) 8.32 rm: /usr/bin/rm, rm (GNU coreutils) 8.32 mkdir: /usr/bin/mkdir, mkdir (GNU coreutils) 8.32 xargs: /usr/bin/xargs, xargs (GNU findutils) 4.8.0 nvm current: v12.22.1 which node: ${NVM_DIR}/versions/node/v12.22.1/bin/node which iojs: which npm: ${NVM_DIR}/versions/node/v12.22.1/bin/npm npm config get prefix: ${NVM_DIR}/versions/node/v12.22.1 npm root -g: ${NVM_DIR}/versions/node/v12.22.1/lib/node_modules ```

nvm ls output:

```sh ❯ nvm ls -> v12.22.1 default -> 12.22.1 (-> v12.22.1) iojs -> N/A (default) unstable -> N/A (default) node -> stable (-> v12.22.1) (default) stable -> 12.22 (-> v12.22.1) (default) lts/* -> lts/gallium (-> N/A) lts/argon -> v4.9.1 (-> N/A) lts/boron -> v6.17.1 (-> N/A) lts/carbon -> v8.17.0 (-> N/A) lts/dubnium -> v10.24.1 (-> N/A) lts/erbium -> v12.22.7 (-> N/A) lts/fermium -> v14.18.1 (-> N/A) lts/gallium -> v16.13.0 (-> N/A) ~ at 16:48:34 ❯ ```

How did you install nvm?

install script in readme

What steps did you perform?

tried to execute script in xonsh shell

What happened?

@ nvm debug Traceback (most recent call last): File "/home/mike/.pyenv/versions/3.9.6/bin/xonsh", line 8, in sys.exit(main()) File "/home/mike/.pyenv/versions/3.9.6/lib/python3.9/site-packages/xonsh/amalgam.py", line 21799, in main _failback_to_other_shells(args, err) File "/home/mike/.pyenv/versions/3.9.6/lib/python3.9/site-packages/xonsh/amalgam.py", line 21746, in _failback_to_other_shells raise err File "/home/mike/.pyenv/versions/3.9.6/lib/python3.9/site-packages/xonsh/amalgam.py", line 21797, in main sys.exit(main_xonsh(args)) File "/home/mike/.pyenv/versions/3.9.6/lib/python3.9/site-packages/xonsh/amalgam.py", line 21853, in main_xonsh run_script_with_cache( File "/home/mike/.pyenv/versions/3.9.6/lib/python3.9/site-packages/xonsh/amalgam.py", line 3660, in run_script_with_cache ccode = compile_code(filename, code, execer, glb, loc, mode) File "/home/mike/.pyenv/versions/3.9.6/lib/python3.9/site-packages/xonsh/amalgam.py", line 3619, in compile_code ccode = execer.compile(code, glbs=glb, locs=loc, mode=mode, filename=filename) File "/home/mike/.pyenv/versions/3.9.6/lib/python3.9/site-packages/xonsh/amalgam.py", line 14382, in compile tree = self.parse(input, ctx, mode=mode, filename=filename, transform=transform) File "/home/mike/.pyenv/versions/3.9.6/lib/python3.9/site-packages/xonsh/amalgam.py", line 14340, in parse tree, input = self._parse_ctx_free(input, mode=mode, filename=filename) File "/home/mike/.pyenv/versions/3.9.6/lib/python3.9/site-packages/xonsh/amalgam.py", line 14489, in _parse_ctx_free raise original_error from None File "/home/mike/.pyenv/versions/3.9.6/lib/python3.9/site-packages/xonsh/amalgam.py", line 14470, in _parse_ctx_free tree = self.parser.parse( File "/home/mike/.pyenv/versions/3.9.6/lib/python3.9/site-packages/xonsh/parsers/base.py", line 523, in parse tree = self.parser.parse(input=s, lexer=self.lexer, debug=debug_level) File "/home/mike/.pyenv/versions/3.9.6/lib/python3.9/site-packages/xonsh/ply/ply/yacc.py", line 335, in parse return self.parseopt_notrack(input, lexer, debug, tracking, tokenfunc) File "/home/mike/.pyenv/versions/3.9.6/lib/python3.9/site-packages/xonsh/ply/ply/yacc.py", line 1203, in parseopt_notrack tok = call_errorfunc(self.errorfunc, errtoken, self) File "/home/mike/.pyenv/versions/3.9.6/lib/python3.9/site-packages/xonsh/ply/ply/yacc.py", line 194, in call_errorfunc r = errorfunc(token) File "/home/mike/.pyenv/versions/3.9.6/lib/python3.9/site-packages/xonsh/parsers/base.py", line 3459, in p_error self._parse_error(msg, self.currloc(lineno=p.lineno, column=p.lexpos)) File "/home/mike/.pyenv/versions/3.9.6/lib/python3.9/site-packages/xonsh/parsers/base.py", line 650, in _parse_error raise_parse_error(msg, loc, self.xonsh_code, self.lines) File "/home/mike/.pyenv/versions/3.9.6/lib/python3.9/site-packages/xonsh/parsers/base.py", line 238, in raise_parse_error raise err SyntaxError: /home/mike/.nvm/nvm.sh:16:0: ('code: nvm_is_zsh',) nvm_is_zsh() { ^ ~ [✖ ERROR] at 16:43:04

@

What did you expect to happen?

expected it to be callable from xonsh shell like it would be for zsh fish bash etc.

Is there anything in any of your profile files that modifies the PATH?

Yes but its there so xonsh know where it is. lines to add it to my .xonshrc

$NVM_DIR = f'{$HOME}/.nvm'
aliases['nvm'] = f'{$NVM_DIR}/nvm.sh'

tried also sourcing it with zsh/bash thing xonsh offers but it fails that too :(

$NVM_DIR = f'{$HOME}/.nvm'
source-zsh $(f'{$NVM_DIR}/nvm.sh')
aliases['nvm'] = f'{$NVM_DIR}/nvm.sh'

More about xonsh https://xon.sh/

Seems to be that it requires zsh and even if sourced from another shell it doesn't seem to like that check https://github.com/nvm-sh/nvm/blob/master/nvm.sh#L16-L18

On zsh get a value Screenshot from 2022-02-18 17-39-03

In bash no value Screenshot from 2022-02-18 17-38-08

It looks like the reason for this may be due to using getting that version from the variable ${ZSH_VERSION-} which has {} and the -

https://xon.sh/bash_to_xsh.html

What i don't know is why that is even needed though cause echoing out both ${ZSH_VERSION-} and ${ZSH_VERSION} in zsh gets you the same value. So it seems weird that not having that value would break things. Screenshot from 2022-02-18 17-45-40

I could be missing something but maybe an exclusion could be based so having that fail isn't instant failure for what should otherwise work.

It looks like other projects ive seen do redundant checks vs just for zsh sdkman

# Determine shell
zsh_shell=false
bash_shell=false

if [[ -n "$ZSH_VERSION" ]]; then
    zsh_shell=true
elif [[ -n "$BASH_VERSION" ]]; then
    bash_shell=true
fi

Some other references https://www.av8n.com/computer/shell-dialect-detect

My xonsh env in case that's helpful:

``` @ env BASH_COMPLETIONS=/usr/share/bash-completion/bash_completion XONSH_VERSION=0.11.0 SHELL=/bin/bash SESSION_MANAGER=local/pop-os:@/tmp/.ICE-unix/4515,unix/pop-os:/tmp/.ICE-unix/4515 PYENV_HOOK_PATH=/home/mike/.pyenv/pyenv.d:/usr/local/etc/pyenv.d:/etc/pyenv.d:/usr/lib/pyenv/hooks:/home/mike/.pyenv/plugins/pyenv-virtualenv/etc/pyenv.d:/home/mike/.pyenv/plugins/pyenv-which-ext/etc/pyenv.d QT_ACCESSIBILITY=1 COLORTERM=truecolor XDG_CONFIG_DIRS=/etc/xdg/xdg-pop:/etc/xdg SSH_AGENT_LAUNCHER=gnome-keyring NVM_INC=/home/mike/.nvm/versions/node/v12.22.1/include/node XDG_MENU_PREFIX=gnome- GNOME_DESKTOP_SESSION_ID=this-is-deprecated GTK_IM_MODULE=ibus MANDATORY_PATH=/usr/share/gconf/pop.mandatory.path GNOME_SHELL_SESSION_MODE=pop SSH_AUTH_SOCK=/run/user/1000/keyring/ssh XMODIFIERS=@im=ibus DESKTOP_SESSION=pop PYENV_VERSION=3.9.6 GTK_MODULES=gail:atk-bridge:appmenu-gtk-module PWD=/home/mike LOGNAME=mike XDG_SESSION_DESKTOP=pop XDG_SESSION_TYPE=x11 GPG_AGENT_INFO=/run/user/1000/gnupg/S.gpg-agent:0:1 SYSTEMD_EXEC_PID=202650 XAUTHORITY=/run/user/1000/gdm/Xauthority WINDOWPATH=2 HOME=/home/mike USERNAME=mike LANG=en_US.UTF-8 XDG_CURRENT_DESKTOP=pop:GNOME VTE_VERSION=6402 G_ENABLE_DIAGNOSTIC=0 GNOME_TERMINAL_SCREEN=/org/gnome/Terminal/screen/3bf18db INVOCATION_ID= MANAGERPID=2923 PYENV_DIR=/home/mike NVM_DIR=/home/mike/.nvm XDG_SESSION_CLASS=user TERM=xterm-256color DEFAULTS_PATH=/usr/share/gconf/pop.default.path LIBVIRT_DEFAULT_URI=qemu:///system USER=mike GNOME_TERMINAL_SERVICE=:1.1732 DISPLAY=:1 SHLVL=3 NVM_CD_FLAGS= QT_IM_MODULE=ibus XDG_RUNTIME_DIR=/run/user/1000 PYENV_ROOT=/home/mike/.pyenv JOURNAL_STREAM=8:1097994 XDG_DATA_DIRS=/usr/share/pop:/home/mike/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/local/share/:/usr/share/ PATH=/home/mike/.pyenv/plugins/pyenv-virtualenv/shims:/home/mike/.pyenv/shims:/home/mike/.local/bin:/home/mike/.poetry/bin:/home/mike/.pyenv/bin:/home/mike/.config/composer/vendor/bin:/home/mike/.cargo/bin:/home/mike/.pyprojectx:/home/mike/.pyenv/versions/3.9.6/bin:/home/mike/.pyenv/libexec:/home/mike/.pyenv/plugins/python-build/bin:/home/mike/.pyenv/plugins/pyenv-virtualenv/bin:/home/mike/.pyenv/plugins/pyenv-update/bin:/home/mike/.pyenv/plugins/pyenv-installer/bin:/home/mike/.pyenv/plugins/pyenv-doctor/bin:/home/mike/.nvm/versions/node/v12.22.1/bin:/home/mike/.pyenv/shims:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin GDMSESSION=pop DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus NVM_BIN=/home/mike/.nvm/versions/node/v12.22.1/bin XONSH_LOGIN=1 XONSH_INTERACTIVE=1 XONSH_CONFIG_DIR=/home/mike/.config/xonsh XONSHRC=/etc/xonshrc:/home/mike/.config/xonsh/rc.xsh:/home/mike/.xonshrc XONSHRC_DIR=/etc/xonsh/rc.d:/home/mike/.config/xonsh/rc.d THREAD_SUBPROCS=1 XONSH_DATA_DIR=/home/mike/.local/share/xonsh MANPATH=/home/mike/.local/share/man PYENV=/home/mike/.pyenv/libexec/pyenv VIRTUALENV_HOME=/home/mike/.pyenv/versions user_bins=['/home/mike/.pyprojectx', '/home/mike/.cargo/bin', '/home/mike/.config/composer/vendor/bin', '/home/mike/.pyenv/bin', '/home/mike/.poetry/bin', '/home/mike/bin', '/home/mike/local/bin', '/home/mike/.local/bin'] XSH_AVOX_VENV_NAME=.venv XSH_AVOX_EXCLUDED_PATHS={'~/.virtualenvs', 'xsh-src'} XONTRIB_PROMPT_STARSHIP_LEFT_CONFIG=~/.config/starship_xonsh_left.toml STARSHIP_SHELL=sh STARSHIP_SESSION_KEY= PROMPT={starship_left} XONSH_COLOR_STYLE=solarized-dark _=/usr/bin/env PYENV_SHELL=python3.9 PYENV_VIRTUALENV_INIT=1 fzf_history_binding=c-r fzf_ssh_binding=c-s fzf_file_binding=c-t fzf_dir_binding=c-g fzf_find_command=fd fzf_find_dirs_command=fd -t d XONSH_HISTORY_BACKEND=sqlite HISTCONTROL=erasedups,ignoredups MULTILINE_PROMPT= LS_COLORS=bd=48;5;60;1;38;5;166:ca=38;5;60;48;5;166:cd=48;5;60;1;38;5;166:di=1;38;5;36:do=1;38;5;168:ex=1;38;5;100:ln=1;38;5;36:mh=0:or=48;5;60;1;38;5;166:ow=38;5;32;48;5;100:pi=48;5;60;38;5;166:rs=0:sg=38;5;60;48;5;166:so=1;38;5;168:st=38;5;102;48;5;32:su=38;5;102;48;5;166:tw=38;5;60;48;5;100 AUTO_CD=1 XONSH_STORE_STDOUT=1 XONSH_HISTORY_MATCH_ANYWHERE=1 DOTGLOB=1 MANPAGER=less -X LESS=--ignore-case --quit-if-one-screen --quit-on-intr FRXQ XONTRIB_ONEPATH_ACTIONS={'': 'cd', '': '', 'text/': 'vim', 'image/': 'xdg-open'} XONSH_SHOW_TRACEBACK=1 XONSH_TRACEBACK_LOGFILE= XONSH_READABLE_TRACEBACK=True READABLE_TRACE_STYLES={'backtrace': '\x1b[33m{0}', 'error': '\x1b[31m\x1b[1m{0}', 'line': '\x1b[31m\x1b[1m{0}', 'module': '{0}', 'context': '\x1b[1m\x1b[32m{0}', 'call': '\x1b[31m--> \x1b[33m\x1b[1m{0}'} READABLE_TRACE_REVERSE=False READABLE_TRACE_ALIGN=False READABLE_TRACE_STRIP_PATH_ENV=False READABLE_TRACE_ENVVAR_ONLY=False READABLE_TRACE_ON_TTY=False READABLE_TRACE_CONSERVATIVE=False XONSH_HISTORY_FILE=/home/mike/.local/share/xonsh/xonsh-history.sqlite SHELL_TYPE=prompt_toolkit OLDPWD=/home/mike XONSH_APPEND_NEWLINE=1 XONSH_CAPTURE_ALWAYS= ```
ljharb commented 2 years ago

What is xonsh? Is it POSIX-compliant? That (and zsh) is all that nvm supports.

ljharb commented 2 years ago

(also, nvm very much does NOT work for fish, since fish is not posix-compliant)

meramsey commented 2 years ago

More about Xonsh https://xon.sh/ https://github.com/xonsh/xonsh https://xon.sh/contents.html#comparison

Not sure if its considered POSIX-compliant but asking to find out.

ljharb commented 2 years ago

It very much doesn't look it - and the syntax error in your OP means it doesn't support normal POSIX functions.

Put another way, if it were POSIX-compliant, it would already work - if it doesn't, it's a bug (or a flaw) in that shell, and there's unlikely to be anything nvm can do to handle it.

meramsey commented 2 years ago

Makes sense. Figured I'd ask cause not seen any of the other stuff have this issue but I totally get it from your point of view.

It looks like i can get it to work with the other bash compatible thing I use in xonsh which is one way to achieve my needs Screenshot from 2022-02-18 19-13-26

I just can't yet bookmark the whole monster command alias where it works with just the nvm like in other shells, but that is something I can figure out or ask for help elsewhere with. Thanks for the super fast response and taking the time to look.

Have a wonderful day and keep up the amazing work your doing!

ljharb commented 2 years ago

Glad you got it to work!

If it does turn out that there's something small I can do to improve compatibility with xonsh, I'm happy to do it, but "rewriting every funciton" isn't viable :-)

meramsey commented 2 years ago

Thanks. I totally understand and would not want you to go through rewriting all those functions. Which is why when I saw that many I was like yeah that's out of my league lol.

If you can put in the README.md something about how to use in xonsh shell that would be swell. Thanks to the genius @anki-code https://github.com/anki-code/xontrib-sh/issues/6

Simply adding this one line of code to a user's ~/.xonshrc file

aliases['nvm'] = """bash -c @(f'[ -s "{$HOME}/.nvm/nvm.sh" ] && . "{$HOME}/.nvm/nvm.sh" && nvm {" ".join($args)}')"""

Works perfectly like it does in every other shell now so I don't have to switch to zsh or bash anymore for nvm related things. Screenshot from 2022-02-19 09-32-54

Is equivalent to doing this in your bashc

export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  # This loads nvm bash_completion
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm

Not super important but would be nice. Potentially you could auto add or suggest it to users to add if you detect there is an ~/.xonshrc

Looks like detection is here? https://github.com/nvm-sh/nvm/blob/master/install.sh#L256-L300

Suggestion output is here? https://github.com/nvm-sh/nvm/blob/master/install.sh#L411-L460

Also I see that you have scripts for auto activating nvm use I'm going to try to see if I can make something like that for xonsh and if I get it working will probably submit a PR.

Once again thanks for being so awesome and friendly.

CharString commented 8 months ago

Alternatively you can use rtx to manage your versions. It supports reading .nvmrc, .node-version and files specific to other languages/tools it supports.