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

[Bug]: Navigation via tmux not working after tmux pane resized #118

Closed icyrainz closed 11 months ago

icyrainz commented 1 year ago

Similar Issues

Neovim Version

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

Multiplexer Integration

tmux

Multiplexer Version

tmux 3.3a

Steps to Reproduce

  1. Open terminal
  2. New tmux session
  3. Create a split
  4. Try to navigate (should work) (both direction works nvim <-> terminal)
  5. Maximize or fullscreen the terminal
  6. Navigation from nvim -> terminal no longer works. (Terminal -> nvim still works)

Expected Behavior

Navigation should work even when maximize/fullscreen terminal.

Actual Behavior

Navigation from nvim -> terminal not working in maximize/fullscreen terminal.

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

My nvim dotfiles: https://github.com/icyrainz/.dotfiles/tree/master/nvim

mrjones2014 commented 1 year ago

I can't reproduce. What terminal are you using? Do you have any config that might be swallowing the keys at the terminal emulator level?

Please post your tmux config and terminal emulator config.

qizidog commented 1 year ago

The same problem, show my config as followed,

Neovim Version

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

Multiplexer Integration

tmux

Multiplexer Version

tmux 3.3a

Steps to Reproduce

  1. Open terminal
  2. New tmux session
  3. Create a vertical split (left and right) and open nvim in the left side
  4. Try to navigate from left nvim to right tmux pane (should work and it does work) (both direction works nvim <-> terminal)
  5. Maximize or fullscreen or resize the terminal (Alacritty) with mouse
  6. Navigation from nvim -> tmux pane no longer works. (tmux pane -> nvim still works)
  7. Change terminal size to original size as just opened (with default shortcut of Rectangle crtl+option+backspace) then try navigate, it works again

What's more, if I move the left nvim to the right side of tmux pane, it works in Maximized ternimal again, it seems like there are some problem with terminal window size. Try to do more resize with terminal window may helps to reproduce this bug.

Minimal Configuration to Reproduce

I'm using LazyVim.

return {
  -- move around between tmux pane and vim window
  -- resize window in a more smart and intuitive way
  {
    "mrjones2014/smart-splits.nvim",
    -- make sure to be loaded at the first time
    lazy = false,
    opts = {
      at_edge = "stop",
    },
    config = function(_, opts)
      -- change focus window
      vim.keymap.set("n", "<C-h>", require("smart-splits").move_cursor_left, { desc = "Move to left window" })
      vim.keymap.set("n", "<C-j>", require("smart-splits").move_cursor_down, { desc = "Move to down window" })
      vim.keymap.set("n", "<C-k>", require("smart-splits").move_cursor_up, { desc = "Move to up window" })
      vim.keymap.set("n", "<C-l>", require("smart-splits").move_cursor_right, { desc = "Move to right window" })

      -- resize window
      vim.keymap.set("n", "<C-Left>", require("smart-splits").resize_left, { desc = "smart resize left" })
      vim.keymap.set("n", "<C-Down>", require("smart-splits").resize_down, { desc = "smart resize down" })
      vim.keymap.set("n", "<C-Up>", require("smart-splits").resize_up, { desc = "smart resize up" })
      vim.keymap.set("n", "<C-Right>", require("smart-splits").resize_right, { desc = "smart resize right" })
      require("smart-splits").setup(opts)
    end,
  },
}
qizidog commented 1 year ago

@mrjones2014 I have reproduced this bug in both Alacritty and iterm2, so I think terminal is not the key.

qizidog commented 1 year ago

This might help, I resize window and tmux pane with mouse in video.

https://github.com/mrjones2014/smart-splits.nvim/assets/45590672/9f81b509-e201-4f6b-a601-e3028c9c7dcd

mrjones2014 commented 1 year ago

Is there any relevant error lines in :SmartSplitsLog?

qizidog commented 1 year ago

No, just two lines logged when starting nvim.

[一  7/31 19:41:34 2023][smart-splits.nvim] Auto-detected multiplexer back-end: tmux
[一  7/31 19:41:34 2023][smart-splits.nvim] Auto-detected multiplexer back-end: tmux
mrjones2014 commented 1 year ago

Can you try the branch mrj/118/debug-logging, reproduce the issue, then repost the logs? I've added a bunch of debug logs on that branch that might help us track down the root issue.

qizidog commented 1 year ago

It seems still hard to find out what goes wrong, no log print out when navigation is invalid.

https://github.com/mrjones2014/smart-splits.nvim/assets/45590672/c40af4d3-157f-42d2-b22d-b445cb608c2b

mrjones2014 commented 1 year ago

You get no additional logs from :SmartSplitsLog on that branch? Hmm, that's weird. Can we see if nvim is even getting the keystrokes properly at all? Can you wrap your keymap handlers like so?

function()
  vim.notify('Move left called!')
  smartsplits.move_cursor_left()
end

Also, the navigation keymaps still work outside of Neovim when this happens, or no? Like, if you reproduce the issue, but then quit Neovim, can you navigate around the normal tmux panes fine?

qizidog commented 1 year ago

Also, the navigation keymaps still work outside of Neovim when this happens, or no? Like, if you reproduce the issue, but then quit Neovim, can you navigate around the normal tmux panes fine?

Yes, the keymaps still work after nvim quited, navigate from tmux pane to anything else always work, it's natural because this behavior is configured through tmux, not nvim.

I'll check wrapped keymap soon.

qizidog commented 1 year ago

Can we see if nvim is even getting the keystrokes properly at all? Can you wrap your keymap handlers like so?

function()
  vim.notify('Move left called!')
  smartsplits.move_cursor_left()
end

I wrapped the keymap handler and the keybinding is triggered exactly, the notification is shown but navigation failed, it happens even when I execute command lua require("smart-splits").move_cursor_right() directly.

    vim.keymap.set("n", "<C-h>", function()
      vim.notify("Move left called!")
      require("smart-splits").move_cursor_left()
    end, { desc = "Move to left window" })

    vim.keymap.set("n", "<C-j>", function()
      vim.notify("Move down called!")
      require("smart-splits").move_cursor_down()
    end, { desc = "Move to down window" })

    vim.keymap.set("n", "<C-k>", function()
      vim.notify("Move up called!")
      require("smart-splits").move_cursor_up()
    end, { desc = "Move to up window" })

    vim.keymap.set("n", "<C-l>", function()
      vim.notify("Move right called!")
      require("smart-splits").move_cursor_right()
    end, { desc = "Move to right window" })
mrjones2014 commented 1 year ago

I tried adding more logs, try again and see if you get any useful log info now please 🙏

mrjones2014 commented 1 year ago

Update the branch

qizidog commented 1 year ago

sure

qizidog commented 1 year ago

"at_edge is not set to AtEdgeBehavior.wrap and current pane is at edge, not moving cursor"

mrjones2014 commented 1 year ago

It looks like tmux is reporting that you are already at the edge you are attempting to move towards (e.g. you're moving right but already at the right edge) but that doesn't seem to actually be the case in reality.

My best guess as to what is happening here is that tmux is not properly updating its internal representation of the pane layout. To test this, can you try detaching from the tmux session and reattaching and see if it works after that?

From a separate terminal window, connect to the same tmux session and run tmux detach -a to detach the first client, then detach the terminal you just opened. Then reconnect to the session and see if smart-splits.nvim behaves properly.

mrjones2014 commented 1 year ago

What do you have at_edge set to in config?

qizidog commented 1 year ago

What do you have at_edge set to in config?

at_edge = "stop", I set the only option since I do not want to navigate back to the opposite side.

opts = {
  at_edge = "stop",
},
mrjones2014 commented 1 year ago

Yeah, gotcha. Can you try detaching and reattaching to the tmux session?

qizidog commented 1 year ago

"detaching and then reattaching" is checked, discribe my steps as followed, please check if I do what you want exactly

  1. make sure navigation is now invalid
  2. open the second instance of alacritty terminal
  3. tmux attach in the second terminal
  4. tmux detach -a in the second terminal
  5. <C-b> d detach from tmux in the second terminal
  6. tmux attach in the second terminal
  7. check navigation

No, smart-splits.nvim doesn't behave properly. 😢

qizidog commented 1 year ago

Perhaps the title of the issue is not accurate enough, I think it should be "[Bug]: Navigation via tmux not working after tmux pane resized", resizing terminal window is not necessary.

mrjones2014 commented 1 year ago

It stops working for all directions right? I am not sure why tmux is reporting that you are somehow at all edges simultaneously. I added a new log, can you update the branch, reproduce, then look in the logs for a line starting with

Output from `tmux list-panes -F {tmux_expr}`:
qizidog commented 1 year ago

No, not all directions, I think it can be seen from the two videos I posted earlier, there are keyboard buttons displayed in the bottom left corner of the video. Sometimes it is possible to navigate down without changing the window size, but not to the right.

I have tried debugging the codes, but I am not very familiar with neovim plugin development.

image

I will go check the new log immediately.

qizidog commented 1 year ago

In the first part, navigate down to tmux pane doesn't work(tried twice), in the second part, navigate right to tmux pane works.

[一  7/31 23:15:08 2023][smart-splits.nvim] Output from `tmux list-panes -F {tmux_expr}`: { "%17:7:_active_", "%23:7:_no_", "%22:40:_no_", "%18:40:_no_" }
[一  7/31 23:15:08 2023][smart-splits.nvim] at_edge is not set to AtEdgeBehavior.wrap and current pane is at edge, not moving cursor
[一  7/31 23:15:16 2023][smart-splits.nvim] Output from `tmux list-panes -F {tmux_expr}`: { "%17:7:_active_", "%23:7:_no_", "%22:40:_no_", "%18:40:_no_" }
[一  7/31 23:15:16 2023][smart-splits.nvim] at_edge is not set to AtEdgeBehavior.wrap and current pane is at edge, not moving cursor

[一  7/31 23:15:33 2023][smart-splits.nvim] Output from `tmux list-panes -F {tmux_expr}`: { "%17:22:_active_", "%23:82:_no_", "%22:82:_no_", "%18:165:_no_" }
[一  7/31 23:15:33 2023][smart-splits.nvim] Pane ID: %17
[一  7/31 23:15:33 2023][smart-splits.nvim] Attempting to move cursor with tmux command...
[一  7/31 23:15:33 2023][smart-splits.nvim] Command ran, did your cursor move?
[一  7/31 23:15:33 2023][smart-splits.nvim] Pane ID: %23
[一  7/31 23:15:33 2023][smart-splits.nvim] Successfully moved to new mux pane
[一  7/31 23:15:33 2023][smart-splits.nvim] Done moving cursor with mux
qizidog commented 1 year ago

Sharing the screen shot.

image
qizidog commented 1 year ago

Is it necessary to check my tmux configuration? I'm not sure whether base-index, pane-base-index, renumber-windows options will have an impact on smart-splits, especially pane-base-index.

# ======= base config =======
PREFIX='C-b'
PREFIX2='None'
set -g prefix $PREFIX
set -g prefix2 $PREFIX2
set -g mouse on
set -g base-index 1
set -g pane-base-index 1
set -g renumber-windows on
set -g mode-keys vi
set -g status-keys vi
set -g history-limit 5000
set -g default-terminal "screen-256color"
set -sa terminal-features ',screen-256color:RGB'
set -g default-command "${SHELL}"
set -g display-panes-time 10000
set -g set-clipboard on

# ======= bindkey config =======
# ...

# ======= style config =======
# border-line
set -g pane-border-style "fg=#181823"
set -g pane-active-border-style "fg=#edc4e6"
# ...

# ======= plugin config =======
# ...
qizidog commented 1 year ago

I checked the same configurantion on my remote ubuntu server, it behaves just the as on my mac, I'll check my configuration with only smart-splits loaded tomorrow.

Thanks a lot.

mrjones2014 commented 1 year ago

I don't think pane-base-index would have an effect as smart-splits.nvim is just checking pane IDs, which should still be unique from tmux which is all that matters.

I don't personally use tmux anymore (I use Wezterm's mux) so I will need to set aside some time to set up to debug this issue thoroughly. Likely won't have a ton of time to do so until next week.

I'm not 100% sure but I'm still thinking it has something to do with tmux not reporting the layout properly, or the integration not parsing it properly or something.

qizidog commented 1 year ago

I upload a Minimal Configuration to Reproduce, try reproducing please.

According to my testing, this problem seems to be caused by LazyVim.

The testing method has been recorded in init.lua, tmux config is not necessary (just for ctrl+[direction] keybindings)

mrjones2014 commented 1 year ago

In that case, we should open a related issue in the lazyvim repo if it requires lazyvim to reproduce.

mrjones2014 commented 1 year ago

Since I don't use LazyVim, could you open an issue? Since the issue form requires version information etc.

qizidog commented 1 year ago

sure

qizidog commented 1 year ago

Issue has been opened. If it's convenient, could you please help confirm if the configuration I uploaded can reproduce the bug?

I have disabled downloading the default plugin of LazyVim in the configuration. In fact, it only uses very basic lazy.nvim and smart-splits.

mrjones2014 commented 1 year ago

I will try to reproduce and comment on the issue when I have time 👍

mrjones2014 commented 11 months ago

circling back to this, it sounds like tmux is not properly reporting its layout after resizing a pane. I haven't been able to reproduce though 😕

freddiehaddad commented 11 months ago

I am experiencing the same behavior as OP, not sure if this is helpful:

I have my tmux session split into three panes (left, middle, right) with neovim in the middle. Navigating from left to right works. Navigating from right to left works from right most pane to neovim, but not from neovim to left most pane.

Running the following in the left most pane shows:

❯ tmux -S /tmp/tmux-1000/default list-panes -F '#{pane_id}:#{pane_left}:#{?pane_active,_active_,_no_}'
%5:0:_active_
%1:119:_no_
%2:310:_no_

Running the following from within neovim:

:!tmux -S /tmp/tmux-1000/default list-panes -F "\#{pane_id}:\#{pane_left}:\#{?pane_active,_active_,_no_}"
%5:0:_no_
%1:119:_active_
%2:310:_no_

FWIW: I had to escape the hash characters inside neovim \#.

Running the following in the right most pane shows:

❯ tmux -S /tmp/tmux-1000/default list-panes -F '#{pane_id}:#{pane_right}:#{?pane_active,_active_,_no_}'
%5:117:_no_
%1:308:_no_
%2:458:_active_

I also have at_edge set to stop in my config. Commenting that line out and using the default (I believe it's wrap) works as expected.

It seems like the correct information is there to handle pane navigation. Maybe something in the logic specific to edge detection? Will continue looking.

#{pane_at_left} exists as well as right, top, and bottom. Wondering if it would be easier to use that? It will return 1 or 0 to indicate if true or false.

For example, from right-most pane:

❯ tmux -S /tmp/tmux-1000/default list-panes -F '#{pane_id}:#{pane_left}:#{pane_at_left}:#{?pane_active,_active_,_no_}'
%2:0:1:_no_
%6:153:0:_no_
%7:306:0:_active_

Theoretically, all you have to do is check if the active pane is at the left, right, top, or bottom based on the direction of the move.

I'll try to write some code to validate and submit a PR if it works.

freddiehaddad commented 11 months ago

@qizidog can you test my PR and see if it resolves your issue? It fixes the behavior for me.

qizidog commented 11 months ago

@freddiehaddad Hey! I test it just now. Unfortunally, it still doesn't work. I put the log as followed (removed dates and time info),

[smart-splits.nvim] Output from `tmux list-panes -F {tmux_expr}`: { "%3:63:_active_", "%4:166:_no_" }
[smart-splits.nvim] at_edge is not set to AtEdgeBehavior.wrap and current pane is at edge, not moving cursor
[smart-splits.nvim] Output from `tmux list-panes -F {tmux_expr}`: { "%3:36:_active_", "%4:166:_no_" }
[smart-splits.nvim] at_edge is not set to AtEdgeBehavior.wrap and current pane is at edge, not moving cursor

# =============after resizing terminal app (resizing panes)===============

[smart-splits.nvim] Output from `tmux list-panes -F {tmux_expr}`: { "%3:38:_active_", "%4:99:_no_" }
[smart-splits.nvim] Pane ID: %3
[smart-splits.nvim] Attempting to move cursor with tmux command...
[smart-splits.nvim] Command ran, did your cursor move?
[smart-splits.nvim] Pane ID: %4
[smart-splits.nvim] Successfully moved to new mux pane
[smart-splits.nvim] Done moving cursor with mux

Test on just two panes, with nvim on the left and tmux-pane on the right.

freddiehaddad commented 11 months ago

It doesn't look like you have my changes based on the output.

Try setting the repository source to freddiehaddad/smart-splits.nvim in your spec.

Also, your plugin manager may not be clever enough to recognize the new git source URL and possibly changing branches. A clean install might be necessary or manually fixing it.

qizidog commented 11 months ago
❱❱❱ ls -a
.        ..       .repro   conf.lua
❱❱❱ ls .repro/plugins/
LazyVim           catppuccin        lazy.nvim         smart-splits.nvim tokyonight.nvim
❱❱❱ cd .repro/plugins/smart-splits.nvim
❱❱❱ git branch
❱❱❱ git status
On branch mrj/118/debug-logging
Your branch is up to date with 'origin/mrj/118/debug-logging'.

nothing to commit, working tree clean

I'm using LazyVim and I open nvim with nvim -u conf.lua conf.lua (link). It supposes to be a clean env.

If necessary, let me know and I will checkout to you branch and test again 😃

freddiehaddad commented 11 months ago

The branch you're on is origin/mrj/118/debug-logging which doesn't have my changes. I think the origin should be origin/master for my PR source repo. That's where the changes are.

qizidog commented 11 months ago

@mrjones2014 mrjones2014 linked a pull request 3 hours ago that will close this issue https://github.com/mrjones2014/smart-splits.nvim/pull/130

@freddiehaddad Sorry, I mistakenly thought that your branch had already been merged into origin/mrj/118/debug-logging.

I test your branch, and it indeed works! Awesome job 😆 !

mrjones2014 commented 11 months ago

Thanks both! I love the collaboration here. I'll merge the PR and tag a new release later today!

mrjones2014 commented 11 months ago

Tagged in v1.2.3