leap.nvim icon indicating copy to clipboard operation
leap.nvim copied to clipboard

double-sided labelling, highlighting ranges, or other features for leap to select

Open IndianBoy42 opened this issue 1 year ago • 20 comments

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.

IndianBoy42 avatar Apr 07 '23 10:04 IndianBoy42

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

atusy avatar May 18 '23 15:05 atusy

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.

IndianBoy42 avatar May 18 '23 15:05 IndianBoy42

Also related: #65, #151, https://github.com/ggandor/leap-spooky.nvim/issues/11, https://github.com/ggandor/leap-spooky.nvim/pull/12

ggandor avatar May 18 '23 18:05 ggandor

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.

ggandor avatar May 18 '23 18:05 ggandor

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

IndianBoy42 avatar May 19 '23 15:05 IndianBoy42

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.

ggandor avatar May 20 '23 17:05 ggandor

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.

IndianBoy42 avatar May 22 '23 09:05 IndianBoy42

:+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).

atusy avatar May 23 '23 12:05 atusy

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.

ggandor avatar Jun 19 '23 10:06 ggandor

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?

IndianBoy42 avatar Jun 19 '23 11:06 IndianBoy42

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.

ggandor avatar Jun 19 '23 12:06 ggandor

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' or c'' (imagine one-letter labels) just like a or b

What actually is the user pressing to select the range C <-> c' or C <-> c''?

IndianBoy42 avatar Jun 19 '23 12:06 IndianBoy42

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'

ggandor avatar Jun 19 '23 12:06 ggandor

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

IndianBoy42 avatar Jun 19 '23 12:06 IndianBoy42

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.

ggandor avatar Jun 19 '23 13:06 ggandor

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.

ggandor avatar Jun 19 '23 13:06 ggandor

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

IndianBoy42 avatar Jun 21 '23 12:06 IndianBoy42

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.

ggandor avatar Jun 21 '23 14:06 ggandor

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.

IndianBoy42 avatar Jun 21 '23 14:06 IndianBoy42

https://github.com/ggandor/leap.nvim/commit/24c0f4d08b8081022e2675fbedb59e8de325f9a6, https://github.com/ggandor/leap.nvim/issues/65#issuecomment-1637749795

ggandor avatar Jul 17 '23 09:07 ggandor