leap.nvim
leap.nvim copied to clipboard
Make `;`, `,` repeat keys interoperate with native `;`, `,`
If you do Leap then native f
/t
, ;
will repeat the Leap motion rather than the native f
/t
motion.
Workaround: use different bindings for Leap repeat
If anyone can solve this (interop with native f/t), I'd be very happy to hear how (I couldn't yet).
I think this happens also with leap.nvim and flit.nvim. leap then flit -> ; still repeats the leap. Maybe related: https://github.com/ggandor/flit.nvim/issues/29#issue-1630554266
off the top of my head maybe you could use vim.on_key
to see when fFtT is hit and unmap the leap repeat mappings from there (may need vim.schedule
), and then remap it when leap is activated.
IIRC this works in vim-sneak so there could be some inspiration there
@ggandor https://github.com/nvim-treesitter/nvim-treesitter-textobjects/pull/359 provides a repeatable movements engine that interops with native ;
/,
and allows other plugins to hook into it.
In their README, they also mention https://github.com/ghostbuster91/nvim-next as being a more focused and lightweight alternative that provides out of the box ;
/,
integrations with the former and several other plugins. Would it be possible to provide a repeat api for leap that either can hook into?
Taken directly from the README for nvim-treesitter-textobjects
You can make the movements repeatable like ; and ,.
local ts_repeat_move = require "nvim-treesitter.textobjects.repeatable_move"
-- Repeat movement with ; and ,
-- ensure ; goes forward and , goes backward regardless of the last direction
vim.keymap.set({ "n", "x", "o" }, ";", ts_repeat_move.repeat_last_move_next)
vim.keymap.set({ "n", "x", "o" }, ",", ts_repeat_move.repeat_last_move_previous)
-- vim way: ; goes to the direction you were moving.
-- vim.keymap.set({ "n", "x", "o" }, ";", ts_repeat_move.repeat_last_move)
-- vim.keymap.set({ "n", "x", "o" }, ",", ts_repeat_move.repeat_last_move_opposite)
-- Optionally, make builtin f, F, t, T also repeatable with ; and ,
vim.keymap.set({ "n", "x", "o" }, "f", ts_repeat_move.builtin_f)
vim.keymap.set({ "n", "x", "o" }, "F", ts_repeat_move.builtin_F)
vim.keymap.set({ "n", "x", "o" }, "t", ts_repeat_move.builtin_t)
vim.keymap.set({ "n", "x", "o" }, "T", ts_repeat_move.builtin_T)
You can even make a custom repeat behaviour.
-- This repeats the last query with always previous direction and to the start of the range.
vim.keymap.set({ "n", "x", "o" }, "<home>", function()
ts_repeat_move.repeat_last_move({forward = false, start = true})
end)
-- This repeats the last query with always next direction and to the end of the range.
vim.keymap.set({ "n", "x", "o" }, "<end>", function()
ts_repeat_move.repeat_last_move({forward = true, start = false})
end)
Furthermore, you can make any custom movements (e.g. from another plugin) repeatable with the same keys. This doesn't need to be treesitter-related.
-- example: make gitsigns.nvim movement repeatable with ; and , keys.
local gs = require("gitsigns")
-- make sure forward function comes first
local next_hunk_repeat, prev_hunk_repeat = ts_repeat_move.make_repeatable_move_pair(gs.next_hunk, gs.prev_hunk)
-- Or, use `make_repeatable_move` or `set_last_move` functions for more control. See the code for instructions.
vim.keymap.set({ "n", "x", "o" }, "]h", next_hunk_repeat)
vim.keymap.set({ "n", "x", "o" }, "[h", prev_hunk_repeat)
Alternative way is to use a repeatable movement managing plugin such as [nvim-next]
Taken from the README for nvim-next
Repeateable movements reborn!
By default vim allows repeating default movements like f/F/t/T and others using ;
and ,
. However, the builtin mechanism is not extendable and as soon as we start using some custom movements we are left to implement the repeating on your own. Some plugins provide that options some don't. But even when they do, they do it in a way that steals ; for themselves.
While I don't use repeating movments often with default motions, I would like to use them with motions like next-treesitter-method, next-diagnostic, next-git-change, etc that comes from many different plugins.
This plugin is a repeatable movments engine that other plugins can hook into. You can think of it as of nvim-cmp but for movements.
The idea is that other plugins like for example git-signs will expose logic to perform some movement, and then we will wrap it with an adapter and plug into that engine.
@Subjective Interesting project, but it's not interoping with native ;
/,
, it actually reimplements f
/F
/t
/T
. (At the moment, dot-repeat, cancelling a change operation, and forcing v
are broken, for example. Which is fine, the readme states the plugin is in a very early state, and this is the authors first plugin, I'm just noting.)
Would it be possible to provide a repeat api for leap that either can hook into?
I'm not sure what other API we would need to provide other than the repeat
parameter in the leap
function (the "writing a custom adapter" part is yet to be finished in the readme).
I think this happens also with leap.nvim and flit.nvim. leap then flit -> ; still repeats the leap. Maybe related: ggandor/flit.nvim#29 (comment)
Interop between leap and flit is doable with some autocommand and expression mapping magic, someone just needs to do it :)
IIRC this works in vim-sneak so there could be some inspiration there
Seems like vim-sneak just remaps f
/F
after sneaking.
https://github.com/justinmk/vim-sneak/blob/29ec9167d4a609f74c130b46265aa17eb2736e6a/doc/sneak.txt#L431