Fish shell has different PATH than neovim
TL;DR: neovim triggers shell commands in a non-interactive subshell that is initialised from scratch from your fish.confg (or other shell setup script). Ensure you set the $PATH the same way for both the interactive and the non-interactive shell.
Today, I found a strange thing. I added a yaml formatter to my neovim config (I use mhartington/formatter.nvim). The formatter runs python3 -m pyaml to format the file. So I installed pip3 install pyaml to have the module.
When I ran the formatter from within neovim, I saw an error Failed to run formatter python3: /opt/homebrew/python3... no module named pyaml.
That is strange because I don’t use homebrew python3. I install python using the asdf VM.
It seems that my fish shell and my neovim have a different path
- Fish:
which python3returns/Users/tomas/.asdf/shims/python3 - neovim:
!:which python3returns/opt/homebrew/bin/python3 - and the
echo $PATH(in fish) and:!echo $PATH(in neovim) also return different value.
How could this be?
I looked through fish and neovim documentation, trying to find evidence that fish doesn’t send the $PATH variable to its subprocess or that neovim ignores it.
In the end, I found the issue by running :echo $PATH and :!echo $PATH in neovim and noticing that the value is different. The first command returns the same value as the fish shell, and the second returns a different path.
Learning: When you run :! in neovim, it creates a subshell. It’s still fish :!echo $SHELL returns /opt/homebrew/bin/fish but the initialisation is different (non-interactive).
See, I tried to be smart and efficient and guarded most of my config.fish shell setup with if status is-interactive. That means I don’t set up autocompletion and other interactive-only features when I run scripts. But one of the setup steps in this interactive-only section was to initialise asdf. When I moved the asdf setup from the interactive-only section, the :echo $PATH and :!echo $PATH commands in neovim had identical output.
This is the fix commit in my dotfiles.