mrjones2014 / smart-splits.nvim

🧠 Smart, seamless, directional navigation and resizing of Neovim + terminal multiplexer splits. Supports tmux, Wezterm, and Kitty. Think about splits in terms of "up/down/left/right".
MIT License
904 stars 38 forks source link

[Bug]: Moving between nvim splits stops working in poetry shells #93

Closed rikchilvers closed 1 year ago

rikchilvers commented 1 year ago

Similar Issues

Neovim Version

NVIM v0.9.0
Build type: Release
LuaJIT 2.1.0-beta3

   system vimrc file: "$VIM/sysinit.vim"
  fall-back for $VIM: "/opt/homebrew/Cellar/neovim/0.9.0/share/nvim"

Multiplexer Integration

Wezterm

Multiplexer Version

wezterm 20230408-112425-69ae8472

Steps to Reproduce

Activate a poetry shell (with pynvim installed) Open neovim Create a neovim split Try to move between splits using <C-{h|j|k|l}>

Expected Behavior

Moving between splits works using default keybindings

Actual Behavior

Moving between splits only works by calling :SmartCursorMove{Direction} directly

Minimal Configuration to Reproduce

local root = vim.fn.fnamemodify('./.repro', ':p')

-- set stdpaths to use .repro
for _, name in ipairs({ 'config', 'data', 'state', 'cache' }) do
  vim.env[('XDG_%s_HOME'):format(name:upper())] = root .. '/' .. name
end

-- bootstrap lazy
local lazypath = root .. '/plugins/lazy.nvim'
if not vim.loop.fs_stat(lazypath) then
  vim.fn.system({
    'git',
    'clone',
    '--filter=blob:none',
    '--single-branch',
    'https://github.com/folke/lazy.nvim.git',
    lazypath,
  })
end
vim.opt.runtimepath:prepend(lazypath)

-- install plugins
local plugins = {
  -- do not remove the colorscheme! it makes testing nicer
  'folke/tokyonight.nvim',
  'mrjones2014/smart-splits.nvim',
  -- add any other pugins here
}

require('lazy').setup(plugins, {
  root = root .. '/plugins',
})

require('smart-splits').setup({
  -- add any options here
})

-- recommended mappings
-- resizing splits
-- these keymaps will also accept a range,
-- for example `10<A-h>` will `resize_left` by `(10 * config.default_amount)`
vim.keymap.set('n', '<A-h>', require('smart-splits').resize_left)
vim.keymap.set('n', '<A-j>', require('smart-splits').resize_down)
vim.keymap.set('n', '<A-k>', require('smart-splits').resize_up)
vim.keymap.set('n', '<A-l>', require('smart-splits').resize_right)
-- moving between splits
vim.keymap.set('n', '<C-h>', require('smart-splits').move_cursor_left)
vim.keymap.set('n', '<C-j>', require('smart-splits').move_cursor_down)
vim.keymap.set('n', '<C-k>', require('smart-splits').move_cursor_up)
vim.keymap.set('n', '<C-l>', require('smart-splits').move_cursor_right)
-- swapping buffers between windows
vim.keymap.set('n', '<leader><leader>h', require('smart-splits').swap_buf_left)
vim.keymap.set('n', '<leader><leader>j', require('smart-splits').swap_buf_down)
vim.keymap.set('n', '<leader><leader>k', require('smart-splits').swap_buf_up)
vim.keymap.set('n', '<leader><leader>l', require('smart-splits').swap_buf_right)

-- add anything else here
vim.opt.termguicolors = true
-- do not remove the colorscheme! it makes testing nicer
vim.cmd([[colorscheme tokyonight]])

Additional Details and/or Screenshots

No response

mrjones2014 commented 1 year ago

I'm not familiar with Poetry, I almost never use Python, but I'd gladly accept a PR from anyone familiar with it

rikchilvers commented 1 year ago

Understood.

On further thought, this feels like an issue for how Neovim interacts with Python when in a virtualenv (possibly just for how I've got things set up). I'll have a poke around and see if I can find a fix.

mrjones2014 commented 1 year ago

Things that might come to mind:

rikchilvers commented 1 year ago

Thanks for the tips. The CLI is still in my $PATH. How can I check the pane:get_foreground_process_name()?

mrjones2014 commented 1 year ago

In your wezterm config, in the keymaps recommended in the README.md of this plugin, there is a function called is_vim -- in there, add the line:

print(string.format('foreground process name: %s', pane:get_foreground_process_name()))

then start Wezterm via the CLI from a different terminal (i.e. open a different terminal and run the wezterm command) which will let you see Wezterm's log output.

rikchilvers commented 1 year ago

Thanks.

Does pane:get_foreground_process_name() in Wezterm's Lua still report nvim when in a Poetry shell? This is used by the is_vim function in the recommended mappings.

No. The foreground process changes to Poetry's python.

lua: foreground process name: /Users/rik/Library/Application Support/pypoetry/venv/bin/python
mrjones2014 commented 1 year ago

From the pane with Neovim running in it? Wonder if poetry is not updating process information or something

rikchilvers commented 1 year ago

I'll close this since the problem isn't smart-splits'. Thanks for the help!

For anyone else that runs into this, you can edit is_vim to something similar to:

local function is_vim(pane)
  local process_name = basename(pane:get_foreground_process_name())
  return process_name == 'nvim' or process_name == 'vim' or string.find(process_name, "pypoetry/venv/bin/python")
end
mrjones2014 commented 1 year ago

Won't that mess with your keymaps if you're in a poetry shell without Neovim open?

We could solve this another way with user vars: https://wezfurlong.org/wezterm/recipes/passing-data.html#user-vars

In your shell, you would add these aliases:

# This function emits an OSC 1337 sequence to set a user var
# associated with the current terminal pane.
# It requires the `base64` utility to be available in the path.
# This function is included in the wezterm shell integration script, but
# is reproduced here for clarity
__wezterm_set_user_var() {
  if hash base64 2>/dev/null ; then
    printf "\033]1337;SetUserVar=%s=%s\007" "$1" `echo -n "$2" | base64`
  fi
}

function _run_prog() {
    # set PROG to the program being run
    __wezterm_set_user_var "PROG" "$1"

    # arrange to clear it when it is done
    trap '__wezterm_set_user_var PROG ""' EXIT

    # and now run the corresponding command, taking care to avoid looping
    # with the alias definition
    command "$@"
}

alias nvim="_run_prog nvim"

Then you could update the is_vim function to basically just check:

pane:get_user_vars().PROG == 'nvim'

If this works for you, I can add this setup to the README.md as an alternative setup.

rikchilvers commented 1 year ago

Good point.

I've had a play with your suggestion but couldn't get it to work with fish shell, which I'm using. Any idea on how to set a user var in fish in the way that wezterm needs?

mrjones2014 commented 1 year ago

I'm a Fish shell user as well. I'll play around with it tomorrow.

mrjones2014 commented 1 year ago

Hmm, actually I couldn't get this working either.

@wez any ideas? Here's the shell integration code converted to Fish shell syntax. But In Wezterm, pane:get_user_vars().PROG still returns nil

# This function emits an OSC 1337 sequence to set a user var
# associated with the current terminal pane.
# It requires the `base64` utility to be available in the path.
# This function is included in the wezterm shell integration script, but
# is reproduced here for clarity
function __wezterm_set_user_var
    if hash base64 2>/dev/null
        printf "\033]1337;SetUserVar=%s=%s\007" "$1" `echo -n "$2" | base64`
    end
end

function _run_prog
    # set PROG to the program being run
    __wezterm_set_user_var PROG "$1"

    # arrange to clear it when it is done
    trap '__wezterm_set_user_var PROG ""' EXIT

    # and now run the corresponding command, taking care to avoid looping
    # with the alias definition
    command "$argv"
end

alias nvim="_run_prog nvim"
wez commented 1 year ago

If poetry isn't correctly managing the foreground process / or otherwise managing unix job control correctly, then the foreground process name will be incorrect.

https://wezfurlong.org/wezterm/config/lua/window-events/user-var-changed.html may be helpful to debug user vars being set.