Select *until* next search match, with incremental search

kak forum question

I have a newbie question/frustration. Let’s say I’m at the beginning of a URL like https://github.com/kale/kakoune/ and I want to change everything until kakoune. In Vim, I could do c/kak<enter>. A nice feature of this is that the search is incremental: after typing c/ka, I can immediately see whether that got me to where I wanted, and if not, I just type another letter.

Does Kakoune have a way of doing this?

I tried three approaches:

  1. ?kak<enter> selects everything including “kak”. I’ve tried following that up with <a-?><enter> or <a-N>, in the hope that it will unselect, similarly to how H unselects after L. That didn’t work either.

  2. ?ale/<enter> works, but loses the benefit of incremental search. I have to get it right the first time or start over.

  3. ?(?=kak)<enter> doesn’t work, since it selects the first k. Is this a bug? Even if it did work, it’s sub-optimal. It’s awkward to type and, perhaps more importantly, the incremental search doesn’t work until I type the ). So, again, I have to get it right the first time.

It’s probably too late to match Vim’s clever behavior (it designed for optimal incremental search: forward search as described above selects until the match, while backwards search selects including the match), as that’s a breaking change. Perhaps asking for <a-N> to work as in item 1. above is a reasonable request? Or is there a better way that I missed?

Thanks!

Welcome ilyagr, I don’t get why option 2 would not work for you, You can still modify your regex on the fly, or am I missing something?, Otoh, I would do ,?kak<ret>B, does it work for your use case? I also think there could be more sensible ways to use ? And a-?, I think it would be neat for them to work with a-., but now that I think of it, there are many ways you can work it around and improve your kak skills, you could create a personal mapping or plugin to anchor a point and then look the word you want and do the operation you need, or define a mapping inside the prompt mode, to append a regex range modifier like kak{1,} and being able to increase/decrease it, what do you think? I think I could hack something together tomorrow but that’s also part of the fun of learning, and also, more often than not, switching your mindset and learning more concepts will lead you to more practical solutions or building your own.

I think a little plugin that stores the start position without it being a selection that gives you visual feedback between next positions and the anchor would be similar to what you want and what I also wanted some time ago… Then you could decide to act on that range with any motion.

Under the hood it could use Z to save the initial selection and u to perform an union and just add some visual feedback. btw selection operations are quite powerful.

Thanks for your thoughts!

I don’t get why option 2 would not work for you, You can still modify your regex on the fly, or am I missing something?

That’s true, though it takes many keypresses.

Otoh, I would do ,?kak<ret>B , does it work for your use case?

?kak<ret>B is a very good point. This obviously doesn’t work in complete generality, but should work more often than not.

I still wish I could use a-N or a-? with the same effect.

you could create a personal mapping or plugin to anchor a point and then look the word you want and do the operation you need, or define a mapping inside the prompt mode, to append a regex range modifier like kak{1,} and being able to increase/decrease it, what do you think?

This may be doable, but it’s more work than I’m willing to spend on this.

I think a little plugin that stores the start position without it being a selection that gives you visual feedback between next positions and the anchor would be similar to what you want and what I also wanted some time ago… Then you could decide to act on that range with any motion.

Under the hood it could use Z to save the initial selection and u to perform an union and just add some visual feedback. btw selection operations are quite powerful.

I’m not sure I follow exactly. I hope this won’t mess up a user’s saved selection if they used Z themselves.

In kakoune I find myself using regex less than I would in vim, since you can combine primtives in ways I find faster and more intuitive. For instance, in your example depending on where the cursor is I’d either <a-i><a-w> or <a-e> to select the whole url. Then I’d just press B, notice that doesn’t take me back far enough and press B or H. Alternatively there’s <a-F>/.

Comparing keypress counts kakoune is less presses but more modifiers, which is often the case when comparing the two. The preference is mostly personal.

Kakoune could have a search untill regex primitive. There’s include/exclude variants of object selection <a-a>[] vs <a-i><a-[><a-]> but no equivalent for searching. Possibly because sall alt+shift+key combos for n and / are already taken up.

That was a short example. I actually want to use this kind of thing to select several paragraphs between my cursor and the text I’m looking at.

IMO there’s two (kinda) seperate issues here.
For precise selections you can’t easily “select to a regex” and for larger selections you can’t repeat ?.

The first could probably be easily added to kakoune or just worked around, at least IMO. The second is more complicated.

The reason you can’t repeat ? is that commands in kakoune are relatively stateless. This has a negative affect on command “cleverness” and user friendliness but makes them more predictable and consistent. The n family of commands don’t know what kind of search was last used, they just know the contents of the search register. This is why n always goes forwards in kakoune but in Vim it depends on if you did / or ?. Similarly only the initial ? can have the extend behaviour.

You can track that information manually and re-do the search but it’s never going to be as nice as if this was properly supported. Simple example here:

declare-option str last_search
map global normal / ': set window last_search / <ret><ret>/'
map global normal ? ': set window last_search ? <ret><ret>?'
# <ret> on empty search buffer uses last entry
map global normal n ': exec %opt{last_search}<ret><ret>'
map global normal <a-n> '<c-o>'

I took the challlenge and implemented select until on top of the prompt kakoune construct. It is a tad more fiddly than I initially thought because the -on-change argument executes in the prompt mode rather than in normal mode.

define-command -hidden select-until-aux -params 0..1 %{
    try %{
        set-register t %val{text}
        execute-keys -save-regs '/' "%arg{1}z%arg{1}?.*?(?=<c-r>t)<ret>"
    }
}

define-command select-until %{
    execute-keys -save-regs '' Z
    prompt -on-change 'select-until-aux <a-semicolon>' until: select-until-aux
}
4 Likes

wow, nice one!

That’s neat, I wasn’t aware you could <a-semicolon> in a prompt. Unfourtunatly there’s also the difficulty of getting the n family of commands to work with custom search commands.

1 Like

I found an interesting approach for my original goal of searching until a pattern. I can use the split command, S. It works even if something like B isn’t enough.

After ?complicated_pattern<ret>, one can press S<ret> to split on the same pattern, which leaves the part until the pattern selected. Done!

If you selected several instances of your pattern (e.g. ?pattern<ret>NN), you would need to do the slightly more complicated, but more robust, S<up>\z<ret>. Adding \z to the end of the pattern makes sure that only the tail end of the selection gets deselected.

3 Likes