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
831 stars 33 forks source link

[Bug]: remapped keys are unmapped after exiting resize mode #192

Closed rwijtvliet closed 3 months ago

rwijtvliet commented 3 months ago

Similar Issues

Neovim Version

0.9.5

Multiplexer Integration

I don't use one

Multiplexer Version

No response

Steps to Reproduce

  1. Create vertical split
  2. Enter resize mode
  3. Adjust size of split
  4. Exit resize mode
  5. Observe that resize keys have new behaviour compared to before entering resize mode

Expected Behavior

Mapping is preserved

Actual Behavior

Mapping is reset to vim standard

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({
    keys = {
      -- focus window
      { '<C-h>', function() require('smart-splits').move_cursor_left() end, desc = 'Focus to left window', },
      { '<C-t>', function() require('smart-splits').move_cursor_up() end, desc = 'Focues to above window', },
      { '<C-n>', function() require('smart-splits').move_cursor_down() end, desc = 'Focus to below window', },
      { '<C-s>', function() require('smart-splits').move_cursor_right() end, desc = 'Focus to right window', },
      -- resize window
      { '<leader>wr', function() require('smart-splits').start_resize_mode() end, desc = 'Resize', },
    },
    opts = {
      ignored_filetypes = { 'nofile', 'quickfix', 'qf', 'prompt' },
      ignored_buftypes = { 'nofile' },
      resize_mode = {
        quit_key = '<Esc>', -- key to exit persistent resize mode
        resize_keys = { 'h', 'n', 't', 's' }, -- !!!!
        silent = false,
        hooks = {
          on_enter = function()
            vim.notify 'Entering window resize mode, press <esc> to exit.'
          end,
          on_leave = function()
            vim.notify 'Resize finished.'
            require('bufresize').register()
            -- Below: workaround for error. TODO: remove when https://github.com/mrjones2014/smart-splits.nvim/issues/192 solved
            vim.keymap.set('', 'h', 'h', { desc = 'Move left' }) -- for completeness
            vim.keymap.set('', 'n', "v:count == 0 ? 'gj' : 'j'", { expr = true, desc = 'move down' })
            vim.keymap.set('', 't', "v:count == 0 ? 'gk' : 'k'", { expr = true, desc = 'move up' })
            vim.keymap.set('', 's', 'l', { desc = 'move right' })
            vim.keymap.set('', 'H', 'H', { desc = 'Move cursor to top of screen' }) -- for completeness
            vim.keymap.set('', 'S', 'L', { desc = 'Move cursor to bottom of screen' })
            vim.keymap.set('n', 'T', 'K', { remap = true, desc = 'Help' })
          end,
        },
        at_edge = 'stop',
      },
    },
  },
  --   "
}

})

-- Wanted mappings for navigation (dvorak keyboard)
vim.keymap.set('', 'h', 'h', { desc = 'Move left' }) -- for completeness
vim.keymap.set('', 'n', "v:count == 0 ? 'gj' : 'j'", { expr = true, desc = 'move down'})
vim.keymap.set('', 't', "v:count == 0 ? 'gk' : 'k'", { expr = true, desc = 'move up' })
vim.keymap.set('', 's', 'l', { desc = 'move right' })
vim.keymap.set('', 'H', 'H', { desc = 'Move cursor to top of screen' }) -- for completeness
vim.keymap.set('', 'S', 'L', { desc = 'Move cursor to bottom of screen' })
vim.keymap.set('n', 'T', 'K', { remap = true, desc = 'Help' })

-- 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

See the code above, which includes a workaround in the on_leave function.

mrjones2014 commented 3 months ago

Can probably do something like this https://github.com/tjdevries/stackmap.nvim

mrjones2014 commented 3 months ago

@rwijtvliet could you test #193 and see if it works for you?

rwijtvliet commented 3 months ago

I think the issue is solved! When exiting resize mode, the keys are correct again.

There is one thing that I'm not sure about, but that's probably due to an error in my config. And that is, that the resize_keys are ignored. When I enter resize mode, I have to use hjkl, not hnts, even though I have resize_keys={'h', 'n', 't', 's'}. Do you spot an error here?

(...)

require('smart-splits').setup {
  opts = {
    ignored_filetypes = { 'nofile', 'quickfix', 'qf', 'prompt' },
    ignored_buftypes = { 'nofile' },
    resize_mode = {
      quit_key = '<Esc>',                   -- key to exit persistent resize mode
      resize_keys = { 'h', 'n', 't', 's' }, -- !!!!
      silent = false,
      hooks = {
        on_enter = function()
          vim.notify 'Entering window resize mode, press <esc> to exit.'
        end,
        on_leave = function()
          vim.notify 'Resize finished.'
          require('bufresize').register()
        end,
      },
      at_edge = 'stop',
    },
  },
}

-- Wanted mappings for navigation (dvorak keyboard)
vim.keymap.set('', 'h', 'h', { desc = 'Move left' }) -- for completeness
vim.keymap.set('', 'n', "v:count == 0 ? 'gj' : 'j'", { expr = true, desc = 'move down' })
vim.keymap.set('', 't', "v:count == 0 ? 'gk' : 'k'", { expr = true, desc = 'move up' })
vim.keymap.set('', 's', 'l', { desc = 'move right' })
vim.keymap.set('', 'H', 'H', { desc = 'Move cursor to top of screen' }) -- for completeness
vim.keymap.set('', 'S', 'L', { desc = 'Move cursor to bottom of screen' })
vim.keymap.set('n', 'T', 'K', { remap = true, desc = 'Help' })
vim.keymap.set('n', 'j', 's', {desc = 'substitute character'})
vim.keymap.set('', 'k', 't', {desc = 'Till (fwrd)'})
vim.keymap.set('n', '<A-b>', function() require('smart-splits').start_resize_mode() end, { desc = 'Resize' })

(...)

I'd like to fix this error before I give the final feedback

mrjones2014 commented 3 months ago

It looks like you copy/pasted from lazy.nvim or something, as your entire plugin config is nested under opts = {}. That would be why your config is not respected.

rwijtvliet commented 3 months ago

Yep, that was it. Works now, many thanks!

beatmax commented 1 month ago

Hi, I use nvchad which has a default mapping of the Esc key to ":noh " to clear highlights after a search. This mapping is not being restored when leaving resize mode. I verified my smart-splits is updated and it includes #193. Maybe 'esc' is special and not covered by the fix?

mrjones2014 commented 1 month ago

@beatmax should be fixed in latest commit on master. Issue was basically checking <ESC> vs. <Esc> vs. <esc>.

beatmax commented 1 month ago

Thanks @mrjones2014 . It's better now, but there's still an issue which can be reproduced like this:

Thanks.

mrjones2014 commented 1 month ago

Could you open another issue with a minimal reproducible init.lua for that? I don't use nvchad and don't have the time to support every bespoke setup.

beatmax commented 1 month ago

Sure, no problem. I expected it can be reproduced without nvchad. I'll try to confirm it and open a new ticket. Thanks! Edit: Created #216.