Preserving Multi-Cursor Selections Across Commands for Scripting Use?

Hello

I am working on a Kakoune macro & custom command that transforms text across multiple selections think refactoring multiple variable names or editing multiple function definitions at once. :slightly_smiling_face: However; I’m running into a problem: once a command / script modifies the buffer; it resets / disturbs the selection set in unexpected ways. :innocent:

I am aware of %val{selections_desc} and using select to re-apply selections, but the behavior is inconsistent especially when selections span modified lines / get adjusted by command side-effects. :innocent:

Is there a best-practice method to capture, store, and accurately restore selections across multiple commands / scripts in a way that’s robust even when the buffer is modified? :thinking:

I’ve tried dumping selections to a register and restoring them, but that feels fragile when working with large buffers or overlapping edits. I’d love to hear if there’s a more canonical or Kakoune-idiomatic approach. :thinking: I checked https://discuss.kakoune.com/t/what-do-you-use-registers-for/2188/ guide related to this and found it quite informative.

If anyone has tackled a similar problem in their plugin or workflow especially involving external tools or hooks I would be grateful for tips or examples. Bonus if you’ve managed to chain this into an LSP / refactoring tool! :innocent:

Thank you !! :slightly_smiling_face:

1 Like

I think you are looking for marks, as created with Z. By default Z stores the mark in the "^ register, but you can specify a register with (for example) "aZ to save to the "a register, and "az to restore from the "a register.

As described in :doc registers marks, a mark contains the locations of selections (as with %val{selections_desc}) but the first item in the list is of the form:

<buffer name>@<timestamp>@<main sel index>

That is, it includes the %val{buffile} of the buffer where the selection was made, and the %val{timestamp} of when it was made. When you jump to the mark with z (restoring the saved selections), Kakoune switches to the named buffer, and then runs through all the edits that have occurred from the given timestamp to the current state, adjusting the positions of all the selections appropriately.

For example, if you saved selections on lines 3 and 5, and then inserted ten lines at the top of the file, when you restored the selections they’d be on lines 13 and 15.

If you need to get even fancier, you can use a range-specs option. There’s no easy way to create the range-specs values from within Kakoune (like you can easily create a mark), and there’s the extra payload associated with each range that wouldn’t be useful to you. However, because it’s an option, you’re not restricted to existing registers, and you can use the :update-option command to have Kakoune calculate the required offset changes and save them back to the option, where your plugin can read them and do more calculations.

1 Like