Skip to content

Selections combinations

Nick Ballard edited this page Apr 30, 2024 · 3 revisions

This page attempts to illustrate how the combining operators work. These operators are the one listed in the infobox when you use <a-z> or <a-Z>:

a: append lists
u: union
i: intersection
<: select leftmost cursor
>: select rightmost cursor
+: select longest
-: select shortest

Let's start with simple examples involving only 2 selections on this dummy buffer content:

First line
Second line
Third line with more text

Select the first line with x, and save this selection to the ^ register with Z. Now, move to the third line and select it with x. Each scenario shows the relevant snippet of C++ code extracted from kakoune code.

a: append lists

After pressing <a-z>a, we end up with 2 selections:

[First line]
Second line
[Third line with more text]

u: union

After pressing, <a-z>u we end up with 1 new big selection encompassing the one in the register and current one:

case CombineOp::Union:
    sel.set(std::min(sel.min(), other.min()),
            std::max(sel.max(), other.max()));
    break;
[First line
Second line
Third line with more text]

i: intersection

After pressing <a-z>i, we end up with 1 new selection corresponding to the part between the one in the register and the current one:

case CombineOp::Intersect:
    sel.set(std::max(sel.min(), other.min()),
            std::min(sel.max(), other.max()));
    break;
First line[
Second line
T]hird line with more text

<: select leftmost cursor

After pressing <a-z><, we end up with the selection from the register since it is the one that appears first in the buffer.

case CombineOp::SelectLeftmostCursor:
    if (sel.cursor() > other.cursor())
        sel = other;
    break;
[First line]
Second line
Third line with more text

>: select rightmost cursor

After pressing <a-z>>, we keep the current selection since it is the one that appears last in the buffer.

case CombineOp::SelectRightmostCursor:
    if (sel.cursor() < other.cursor())
        sel = other;
    break;
First line
Second line
[Third line with more text]

+: select longest

After pressing <a-z>+, we keep the current selection since line 3 is longer than line 1.

case CombineOp::SelectLongest:
    if (char_length(buffer, sel) < char_length(buffer, other))
        sel = other;
    break;
First line
Second line
[Third line with more text]

-: select shortest

After pressing <a-z>-, we keep the selection from the register since line 1 is shorter than line 3.

case CombineOp::SelectShortest:
    if (char_length(buffer, sel) > char_length(buffer, other))
        sel = other;
    break;
[First line]
Second line
Third line with more text

What happens if more than 2 selections are involved?

Kakoune can combine selections lists only if they have the same length (except when appending lists). An error message is displayed otherwise. The combining operators are then applied pairwise. It means that the first selection from the selections list saved in the register will be paired with the first one from the current selections list, then the same operation is applied for the second selection in the lists etc…

Let's illustrate with the following buffer:

First line
Second line
Third line with more text
Last line

Select the first 2 lines, with JX and then split by new lines with <a-s> to obtain 2 selections that you save with Z:

[First line]
[Second line]
Third line with more text
Last line

Now do the same with the last 2 lines, without saving this time, to have these selections highlighted:

First line
Second line
[Third line with more text]
[Last line]

Finally, let's try to do a <a-z>+ to perform a longest combination.

The third line is longer than the first line, so it is kept, where as the second line is longer that the last line. So we end up with:

First line
[Second line]
[Third line with more text]
Last line
Clone this wiki locally