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]: floating neovim windows should not be resized #122

Closed alesandar closed 1 year ago

alesandar commented 1 year ago

Similar Issues

Neovim Version

NVIM v0.10.0-dev-539+g72a6643b13 Build type: RelWithDebInfo LuaJIT 2.1.0-beta3

Multiplexer Integration

tmux

Multiplexer Version

tmux 3.3a

Steps to Reproduce

0) Open Neovim and enter command-line mode by pressing : 1) Open a floating window or manually create one by issuing the following one-liner:

:lua vim.api.nvim_open_win(0, true, { relative = 'editor', width = 10, height = 10, col = 0, row = 0, border = 'solid' })

2) Press any of your resize key-mapings (Alt-{h,j,k,l}) or call one of the resize functions manually:

:lua require('smart-splits').resize_right(10)

Expected Behavior

Floating windows should be ignored by resize.

I can not think of anything else that could be done, since many plugins (e.g. telescope.nvim) use multiple floating windows.

Actual Behavior

Floating windows are resized.

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)

local plugins = { 'mrjones2014/smart-splits.nvim' }

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

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)

Additional Details and/or Screenshots

Here's an if-statement that can be used to check if the current window is floating.

if vim.api.nvim_win_get_config(0).relative ~= '' then --[[ do nothing ]] end
alesandar commented 1 year ago

Noticed another weird behavior when navigating between splits. Calling move_cursor_* (when a floating window is focused) does not move the cursor in the right direction.

Open Neovim, create a new split, focus the previous one, create a floating window and try to navigate in any direction.

:botright vsplit
:wincmd h
:lua vim.api.nvim_open_win(0, true, { relative = 'editor', width = 10, height = 10, col = 0, row = 0, border = 'solid' })
:lua lua require('smart-splits').move_cursor_right()
mrjones2014 commented 1 year ago

Hm yeah, I think the behavior would be weird with floating windows.

I would probably say that moving between multiple floating windows is not supported, as wincmd h/j/k/l will probably have inconsistent behavior in groups of floating windows, which this plugin relies on.

I think resizing floating windows would just be unsupported too

alesandar commented 1 year ago

@mrjones2014, I have tested the changes from https://github.com/mrjones2014/smart-splits.nvim/pull/123.

It appears that move/resize capabilities are completely disabled if a floating window is focused. That behavior might be considered disruptive by some users, since one should always close the floating window first (before switching between splits).

alesandar commented 1 year ago

Would you mind if I try to implement a different solution before merging #123? I was working on a few other improvements, so I have become familiar with most of the source code.

alesandar commented 1 year ago

Here is my current solution: https://github.com/mrjones2014/smart-splits.nvim/commit/ecea65d8f029978d92e29f5fa83f6774f31249aa.

Basically, if the current window is floating, the cursor will be moved back to the most recently accessed window. That fallback works quite well, because WinLeave auto-commands of other plugins will get triggered. For example, telescope.nvim and oil.nvim will automatically close their corresponding floating windows when they lose focus. Alternatively, if the previous window is also floating - the method will be aborted, just as you initially did.

mrjones2014 commented 1 year ago

I like your solution. Can you submit a PR? I will test + approve yours, and close mine.

alesandar commented 1 year ago

Thank you, I have just submitted the PR.