Spooky is a Leap extension that allows for remote operations on Vim's native text objects: that is, it exposes atomic bundles of (virtual or actual) leaping motions and text object selections.
AFAIK, the basic idea first appeared in vim-seek, one of vim-sneak's predecessors. (The feature is coincidentally called "leaping motions" there, no kidding.)
It's not just the number of keystrokes that matter here, but the potentially
more intuitive workflow achieved through these higher abstractions, that are
nevertheless obvious extensions of Vim's grammar. As usual, the aim is to
sharpen the saw; there are no big list of new commands to learn, except for two
affixes that can be added to all existing text objects. carb[leap]
("change
around remote block [marked by leap motion]") in no time will be just as
natural as targets.vim's canb
("change around next block").
Leap is automatically invoked once the text object is specified; after e.g.
yarw
, start typing the 2-character search pattern, and select the target as
you would usually do. The difference is that instead of jumping there, the word
will be yanked.
zfarp[leap]
).paste_on_remote_yank
(yaRp[leap]
)....<C-o>yaRW[leap]...
).cimw[leap][correction]
).drr[leap]
.count
: e.g. y3rr[leap]
yanks 3 lines, just as 3yy
would do.WIP - everything is experimental at the moment.
setup
creates all the necessary mappings - you can call it without arguments,
if the defaults are okay:
require('leap-spooky').setup {
-- Additional text objects, to be merged with the default ones.
-- E.g.: {'iq', 'aq'}
extra_text_objects = nil,
-- Mappings will be generated corresponding to all native text objects,
-- like: (ir|ar|iR|aR|im|am|iM|aM){obj}.
-- Special line objects will also be added, by repeating the affixes.
-- E.g. `yrr<leap>` and `ymm<leap>` will yank a line in the current
-- window.
affixes = {
-- The cursor moves to the targeted object, and stays there.
magnetic = { window = 'm', cross_window = 'M' },
-- The operation is executed seemingly remotely (the cursor boomerangs
-- back afterwards).
remote = { window = 'r', cross_window = 'R' },
},
-- Defines text objects like `riw`, `raw`, etc., instead of
-- targets.vim-style `irw`, `arw`. (Note: prefix is forced if a custom
-- text object does not start with "a" or "i".)
prefix = false,
-- The yanked text will automatically be pasted at the cursor position
-- if the unnamed register is in use.
paste_on_remote_yank = false,
}
Note: This is absolutely not stable API, just a current snapshot for people who would like to experiment.
spooky_action
returns a one-argument function that can be used as leap
's
action
parameter. That is, you have to call it when used in a mapping.
The signature looks like: spooky_action(select_cmd, {opts})
select_cmd
: a function returning a string to be passed to :normal
(by
default, the expected action is a text object selection, like viw
)opts.on_exit
: like select_cmd
, but the command is be executed after the
operation has been finishedopts.keeppos
: if true, execute the action remotely (jump back afterwards)Example:
require('leap').leap {
target_windows = { vim.fn.win_getid() }
action = require('leap-spooky').spooky_action(
function () return "viw" end,
{ keeppos = true, on_exit = (vim.v.operator == 'y') and 'p', },
),
}
You can also check the source code for ideas, or if something is unclear.
It would be awesome to restrict the search area to the given text objects.
E.g. cr]
would only give matches inside square brackets. This could often
add a huge speed boost and reduce the visual noise a lot. We could even
highlight the active areas.
Label the text objects themselves (at least blocks, paragraphs, etc.), so that you can immediately choose one, instead of having to specify the reference point with a default 2-char Leap motion.