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
895 stars 37 forks source link

fix: Detect and handle nested Vim instances in Tmux #168

Closed pwnalone closed 5 months ago

pwnalone commented 5 months ago

Bug Description

Split navigation stops working after opening/exiting Neovim from within a Neovim terminal window when using the Tmux integrations.

Minimal Config

Neovim

local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
  -- stylua: ignore
  vim.fn.system({ "git", "clone", "--filter=blob:none", "https://github.com/folke/lazy.nvim.git", "--branch=stable", lazypath })
end
vim.opt.rtp:prepend(lazypath)

require("lazy").setup({
  {
    "mrjones2014/smart-splits.nvim",
    event = "VeryLazy",
    config = function()
      local map = function(mode, lhs, rhs, opts)
        local base = { noremap = true, silent = true }
        vim.keymap.set(mode, lhs, rhs, vim.tbl_extend("force", base, opts or {}))
      end

      local ss = require("smart-splits")

      ss.setup()

      map({ "n", "i", "t" }, "<M-h>", ss.move_cursor_left)
      map({ "n", "i", "t" }, "<M-j>", ss.move_cursor_down)
      map({ "n", "i", "t" }, "<M-k>", ss.move_cursor_up)
      map({ "n", "i", "t" }, "<M-l>", ss.move_cursor_right)
    end,
  },
})

Tmux

set -g prefix C-a

bind -n 'M-h' if -F "#{@pane-is-vim}" 'send M-h' 'selectp -L'
bind -n 'M-j' if -F "#{@pane-is-vim}" 'send M-j' 'selectp -D'
bind -n 'M-k' if -F "#{@pane-is-vim}" 'send M-k' 'selectp -U'
bind -n 'M-l' if -F "#{@pane-is-vim}" 'send M-l' 'selectp -R'
bind -n 'M-;' if -F "#{@pane-is-vim}" 'send M-;' 'lastp'

bind -T copy-mode-vi 'M-h' selectp -L
bind -T copy-mode-vi 'M-j' selectp -D
bind -T copy-mode-vi 'M-k' selectp -U
bind -T copy-mode-vi 'M-l' selectp -R
bind -T copy-mode-vi 'M-;' lastp

bind '\' splitw -v -c '#{pane_current_path}'
bind '|' splitw -h -c '#{pane_current_path}'
unbind '"'
unbind '%'

Steps To Reproduce

  1. Open Tmux.
  2. Open Neovim.
  3. Open a Neovim terminal window.
  4. Open Neovim from within the Neovim terminal window.
  5. Exit the nested Neovim editor.
  6. Exit the terminal window.
  7. Attempt to navigate between Neovim splits.

Fix Description

This PR fixes the issue by checking if the @pane-is-vim Tmux option is already set to 1 on initialization. If it is, then we set a flag to prevent unsetting the option on exit.

pwnalone commented 5 months ago

No problem! I only ran into this issue because I use Neovim as my man-pager (e.g. export MANPAGER='nvim +Man!') and I sometimes open up man-docs in Neovim terminals. In other words, running nested Neovim instances isn't something I would normally want to do. :)