leap.nvim
leap.nvim copied to clipboard
double-sided labelling, highlighting ranges, or other features for leap to select
Since this conversation has there been any progress or thought on how to do the labelling for ranges rather than single position targets?
For me I think labelling both sides, while not perfect due to the problem of overlapping edges, is still quite useable in practice. I have been using treehopper for a couple of years now and don't really have that much annoyance. I have found that I tend to do selection first, ie vm<label><action>
just in case I am wrong about the labelling. (also see: https://github.com/ggandor/leap-ast.nvim/pull/5)
Another thing that could be helpful and less cluttering is to use some background highlighting over the ranges to select from, and then only show the labels at the unique end of the range. overlapping ranges could be automatically changed to different colors or shades of the same color.
There are no official fields for leap targets that defines ranges.
So we need to start from adding a new field.
I'm not sure if this is the scope of leap.nvim.
Officially, there are two below.
-
pos
: a (1,1)-indexed tuple; this is the position of the label, mandatory -
wininfo
: a value from `getwininfo(), optional
https://github.com/ggandor/leap.nvim/blob/3144cefc5ec8872c838dc6710707d23b6de5ec02/doc/leap.txt#L446-L447
For the question of scope: I think the discussion in treehopper and existence of leap-ast implies atleast a bit of interest in leap.nvim for selections or atleast being able to be a target selection engine for selections. #149 also shows that the scope of leap isn't necessarily just for moving the cursor but any kind of dynamic labelled selection.
Im fine if it isn't, that's atleast partially the point of my question.
Also related: #65, #151, https://github.com/ggandor/leap-spooky.nvim/issues/11, https://github.com/ggandor/leap-spooky.nvim/pull/12
Since https://github.com/mfussenegger/nvim-treehopper/issues/23 has there been any progress or thought on how to do the labelling for ranges rather than single position targets?
Not really, this is very low priority for me, TBH. I welcome any ideas that address this without complicating the internals of Leap, or minimally do so. E.g., highlighting ranges could be done by the extension itself, since in this case we are feeding custom targets to Leap anyway. Autocommands could do wonders too.
I think a first step could be adding endpos
, an optional field in the target list, if given, leap would render the label at both pos, endpos
. This would bring us to parity with nvim-treehopper, which works for many people, even though its not ideal due to the overlapping problem. Does this complicate the internals a lot, since its just a visual change?
Any other kind of highlighting/rendering of the ranges could probably be piloted in another extension, or just live in another extension. I'm actually interested, when I get time, in using hologram.nvim to draw lines that can overlay text without completely covering it, that could be used to visually depict ranges.
If some kind of more granular control like mentioned in #151 is implemented then more interesting/flexible selection modalities could be experimented with outside of core to see what kind of AOT labelling could be done
without complicating the internals of Leap
*internals & interface
I think a first step could be adding
endpos
This feels very ad-hoc, I'd rather have a general beacon
function exposed, as discussed in #65 and #151, then anyone can implement any beaconing logic, without us having to give a damn here in the core.
I agree a general beacon function would be better in the long run, it just sounds like something that will take a while for the implementation and bikeshedding and everything.
pos+endpos is a bit ad-hoc but its also probably the most obvious and common way of beaconing ranges. I think there is value in some common cases being handled by the engine.
:+1: to export beacon!
I would also suggest extend pos
rather than adding endpos
- {[1]: integer, [2]: integer}
+ {[1]: integer, [2]: integer} | {[1]: integer, [2]: integer, [3]: integer, [4]: integer}
In this case, third and forth elements corresponds to endrow and endcol.
What we have to do is only to document something like below
Optionally, third and forth elements corresponds to endrow and endcol of a target. These fields are preserved for extending leap (e.g, visual selection of a target).
Regarding treesitter/leap-ast, I have a new idea about the UI. Somehow we should mark positions which start multiple nodes; after selecting one of those, the corresponding endpoints remain on the screen, and the user, in an additional step, should select the preferred one. Labeling these "stacked" start positions with capital letters (and using lowercase for all others) could be a simple way of achieving this.
So if there are stacked positions then selecting that node/range would require 2 keypresses unconditionally? Or the user is able to disambiguate using capital letters if theyre not sure, but directly select using lowercase letters?
The latter, I see no reason to disallow selecting non-conflicting labels directly.
[a] [b] [C] | [c] [d] [b] [a]
You can select c
or d
just like a
or b
, but if you press capital C
, then you will see
[ ] | [c] [d]
with an empty marker or sg like that kept at the start position, for reference.
Sorry I think I wasn't clear. My point is that will the overlapping ranges (grouped under C
in your example) always require 2 keypresses?
When you say:
You can select
c'
orc''
(imagine one-letter labels) just likea
orb
What actually is the user pressing to select the range C <-> c'
or C <-> c''
?
Edited my comment above, the labeling was confusing I guess, just wanted to emphasize the pairings. (I assume double-sided labeling of course.)
What actually is the user pressing to select the range C <-> c'
c'
, or C
then c'
Okay thats actually what I assumed but thought I'd clarify. I think this a slight improvement on nvim-treehopper but no real drawbacks
BTW there was recently this plugin that automatically generates shades of the background to show nested blocks: https://github.com/HampusHauffman/block.nvim. Perhaps something like this makes sense for giving a little more visual clarity on what the ranges are? Optional probably since I know you don't like a lot of visual noise when leaping
Perhaps something like this makes sense for giving a little more visual clarity on what the ranges are?
Not (just) the visual noise, but it doesn't really help. An indented block is pretty obvious anyway, and all the other cases (nodes beginning in the same column or line) are utterly problematic or impossible to handle in this manner (in a TUI at least).
Maybe an opt-in mode could be implemented where you should accept the selection with enter
(or repeating the label). When selecting a label, all that happens is that the range will be highlighted, and if you misfired, you can just press another one.
Maybe an opt-in mode could be implemented where you should accept the selection with enter (or repeating the label). When selecting a label, all that happens is that the range will be highlighted, and if you misfired, you can just press another one.
Actually, this might be yet another valid approach to handle those stacked positions. If a
labels multiple start points, then you can cycle between the nodes by repeatedly pressing a
, and accept it with enter
. This way double-sided labeling is not even (strictly) necessary, although I agree that it would be better to have that.
So folke/flash.nvim uses inline virtual text for its double sided labelling. No trouble with overlapping but text will move around a little when you activate it
Something like this?
foo and bar
something
end
f[X][Y]oo and bar[Y]
something
end[X]
That might work when you don't have to type an input pattern (focusing heavily on a given spot), although still a bit distracting, but if it causes line wrapping(s), potentially rearranging the whole window, that's unacceptable.
Yeah its not perfect but I don't know if a perfect solution to labelling overlapping ranges really exists.
A more generalized labelled range selection (not just around the cursor, but selecting any range precisely in the way that leap can jump to any position precisely) probably needs two keypresses anyway so maybe we just have different labels on each side anyway.
https://github.com/ggandor/leap.nvim/commit/24c0f4d08b8081022e2675fbedb59e8de325f9a6, https://github.com/ggandor/leap.nvim/issues/65#issuecomment-1637749795