alexghergh / nvim-tmux-navigation

Easy Neovim-Tmux navigation, completely written in Lua
MIT License
273 stars 21 forks source link

Does not work when running Vim in a Poetry shell #13

Open gegnew opened 1 year ago

gegnew commented 1 year ago

nvim-tmux-navigation doesn't work at all if the neovim session is run after poetry shell. Would appreciate help debugging, if possible.

:checkhealth outside of poetry shell:

Python 3 provider (optional) ~
- pyenv: Path: /opt/homebrew/Cellar/pyenv/2.3.18/libexec/pyenv
- pyenv: Root: /Users/g/.pyenv
- `g:python3_host_prog` is not set.  Searching for python3 in the environment.
- Executable: /Users/g/.pyenv/versions/3.10.11/bin/python3
- Python version: 3.10.11
- pynvim version: 0.4.3
- OK Latest pynvim is installed.

and inside poetry shell, the same except for a virtualenv error:

Python 3 provider (optional) ~
- pyenv: Path: /opt/homebrew/Cellar/pyenv/2.3.18/libexec/pyenv
- pyenv: Root: /Users/g/.pyenv
- `g:python3_host_prog` is not set.  Searching for python3 in the environment.
- Executable: /Users/g/.pyenv/versions/3.10.11/bin/python3
- Python version: 3.10.11
- pynvim version: 0.4.3
- OK Latest pynvim is installed.

Python virtualenv ~
- WARNING $VIRTUAL_ENV is set to: /Users/g/Desktop/zeit/ml/.venv
  And its /bin directory contains: python, python3, python3.10, pythoni, pythoni1
  But $PATH yields this pythoni executable: Traceback (most recent call last):
  File "/Users/g/Desktop/zeit/ml/.venv/bin/pythoni", line 30, in <module>
  from pyrepl.python_reader import main
  File "/Users/g/Desktop/zeit/ml/.venv/lib/python3.10/site-packages/pyrepl/python_reader.py", line 25, in <module>
  from pyrepl.completing_reader import CompletingReader
  File "/Users/g/Desktop/zeit/ml/.venv/lib/python3.10/site-packages/pyrepl/completing_reader.py", line 22, in <module>
  from pyrepl import commands, reader
  File "/Users/g/Desktop/zeit/ml/.venv/lib/python3.10/site-packages/pyrepl/commands.py", line 376, in <module>
  from pyrepl import input
  File "/Users/g/Desktop/zeit/ml/.venv/lib/python3.10/site-packages/pyrepl/input.py", line 39, in <module>
  from trace import trace
  ImportError: cannot import name 'trace' from 'trace' (/Users/g/.pyenv/versions/3.10.11/lib/python3.10/trace.py)

  And $PATH in subshells yields this pythoni executable: Traceback (most recent call last):
  File "/Users/g/Desktop/zeit/ml/.venv/bin/pythoni", line 30, in <module>
  from pyrepl.python_reader import main
  File "/Users/g/Desktop/zeit/ml/.venv/lib/python3.10/site-packages/pyrepl/python_reader.py", line 25, in <module>
  from pyrepl.completing_reader import CompletingReader
  File "/Users/g/Desktop/zeit/ml/.venv/lib/python3.10/site-packages/pyrepl/completing_reader.py", line 22, in <module>
  from pyrepl import commands, reader
  File "/Users/g/Desktop/zeit/ml/.venv/lib/python3.10/site-packages/pyrepl/commands.py", line 376, in <module>
  from pyrepl import input
  File "/Users/g/Desktop/zeit/ml/.venv/lib/python3.10/site-packages/pyrepl/input.py", line 39, in <module>
  from trace import trace
  ImportError: cannot import name 'trace' from 'trace' (/Users/g/.pyenv/versions/3.10.11/lib/python3.10/trace.py)

  And $PATH yields this pythoni1 executable:   File "/Users/g/Desktop/zeit/ml/.venv/bin/pythoni1", line 16
  print 'Python', sys.version
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  SyntaxError: Missing parentheses in call to 'print'. Did you mean print(...)?

  And $PATH in subshells yields this pythoni1 executable:   File "/Users/g/Desktop/zeit/ml/.venv/bin/pythoni1", line 16
  print 'Python', sys.version
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  SyntaxError: Missing parentheses in call to 'print'. Did you mean print(...)?

  So invoking Python may lead to unexpected results.
  - ADVICE:
    - $PATH ambiguities arise if the virtualenv is not properly activated prior to launching Nvim. Close Nvim, activate the virtualenv, check that invoking Python from the command line launches the correct one, then relaunch Nvim.
    - $PATH ambiguities in subshells typically are caused by your shell config overriding the $PATH previously set by the virtualenv. Either prevent them from doing so, or use this workaround: https://vi.stackexchange.com/a/34996
gegnew commented 1 year ago

This thread is relevant, but I didn't find a satisfactory solution: https://github.com/christoomey/vim-tmux-navigator/issues/230

gegnew commented 1 year ago

Here is a workaround involving checking for a poetry environment. It's a little weird because the tty does not show up with poetry in it at all, but rather as a long filepath like: S<+ /opt/homebrew/Cellar/python@3.11/3.11.3/Frameworks/Python.framework/Versions/3.11/Resources/Python.app/Contents/MacOS/Python

# add a check for the poetry env
is_poetry="ps -o state= -o comm= -t '#{pane_tty}' | grep -iqE 'Frameworks\/Python.framework'"

# all other lines in tmux config remain the same, but change the "bind-key" lines to:
bind -n C-h run "($is_vim && tmux send-keys C-h) || ($is_poetry && tmux send-keys C-h) || tmux select-pane -L"
bind -n C-j run "($is_vim && tmux send-keys C-j)  || ($is_poetry && tmux send-keys C-j) || tmux select-pane -D"
bind -n C-k run "($is_vim && tmux send-keys C-k) || ($is_poetry && tmux send-keys C-k)  || tmux select-pane -U"
bind -n C-l run  "($is_vim && tmux send-keys C-l) || ($is_poetry && tmux send-keys C-l) || tmux select-pane -R"
bind-key -n 'C-\\' if-shell "$is_vim" 'send-keys C-\\\\'  'select-pane -l'
gegnew commented 1 year ago

This should work for pipenv and other environments, but you'll need to check the process status with ps to see what your env looks like.

1) get the tty of the tmux pane containing the env with <tmux leader>:display-message '#{pane_tty}' 2) then check the process status:ps -o state= -o comm= -t /dev/`

Edit: nevermind, still broken

alexghergh commented 1 year ago

Hey,

Thanks for reporting the issue! I am aware that some of the functionality of the plugin is broken inside python* shells/environments. It's always Python that's broken, am I right..

My long term idea was to completely change how the plugin detects vim/neovim and tmux, since we cannot always determine them reliably with the current solution.

However, due to life issues, I am currently unable to look into it. I will be able to do so in about 1 to 2 months.

I cannot provide a workaround solution for now, since I don't use any of the tools, however I will keep the thread open, and perhaps someone else would be able to find a fix.

In the meantime, please keep posting if you do find new information that could be helpful for a future fix.

Regards

pacjac commented 8 months ago

The workaround works for me, thanks @gegnew! Would love to see a fix still.

gegnew commented 7 months ago

The problem I have is that, although I can detect the Poetry environment, it cannot detect vim in a pane if it's in the Poetry environment. The is_poetry ps command returns true, but the is_vim poetry command returns false, because the output of ps in the pane with the Poetry env is /opt/homebrew/Cellar/python@3.11/3.11.3/Frameworks/Python.framework/Versions/3.11/Resources/Python.app/Contents/MacOS.

If anyone has any ideas, I'm all 👂

akail commented 7 months ago

So, I've been coming back to this issue on and off for a while now and found how to get things working right with pipenv at least and also know why is_vim does not work for any future references. Hope it helps.

For is_vim, the ps command looks at the current pane's tty. When poetry shell or pipenv shell are called, it starts a new tty under the pipenv process. See below where you see pts/10 has been started.

akail      30255    2760  0 Dec02 pts/4    00:00:00       -zsh
akail     237624   30255  6 10:54 pts/4    00:00:00         /usr/bin/python /usr/bin/pipenv shell
akail     237626  237624  1 10:54 pts/10   00:00:00           /bin/zsh -i

I found the same experience with poetry shell

akail      30255    2760  0 Dec02 pts/4    00:00:01       -zsh
akail     238893   30255  8 11:05 pts/4    00:00:00         /usr/bin/python /usr/bin/poetry shell
akail     238899  238893  1 11:05 pts/10   00:00:00           /bin/zsh -i

I've been trying to find a way to extract all the children but it gets cumbersome pretty quickly.

Pipenv offers a flag on the shell to command --fancy which changes the behavior and keeps everything under the same tty.

  --fancy             Run in shell in fancy mode. Make sure the shell have no
                      path manipulating scripts. Run $pipenv shell for issues
                      with compatibility mode.

When running in this mode, it does not start a new process in a new tty and only seems to modify the environment variables.

prurph commented 6 months ago

Just wanted to chime in here with another workaround. I've found trying to modify the $is_vim logic to be unsatisfactory, and instead I just use poetry run nvim instead of doing poetry shell and then nvim. The former seems to make LSP references, diagnostics, built-in nvim terminal, etc. "just work". I had also tried launching nvim then using a plugin to choose the virtual env; this also worked but required extra steps to exclude diagnostics from showing on imported modules.

I also tried this workaround but found it to be a bit slow because it needs multiple shell commands to first see if we're inside poetry, then to get its child processes to see if we're inside vim as well. I'm not an expert and I'm working on personal projects so perhaps there are problems with this approach I'm not aware of in larger or professional settings, but afaict poetry run nvim is perfect.

haakenlid commented 6 months ago

One workaround is to activate the poetry virtual env in the current shell instead of of using poetry shell to spawn a subshell.

In bash you can run this command: source $(poetry env info --path)/bin/activate

https://python-poetry.org/docs/basic-usage#activating-the-virtual-environment