Sublime Forum

How to save / Restore cursors position, without shifting when replacing text

#1

There are many plugins(AutoSelect, MarkAndMove, MultipleSelectionScroller, PowerCursors, TabsExtra) that save cursors and selections, but in all of them, when replacing text, the position cursor shifts to end of line or disappears.

I found a plugin , but still, if the text is deleted or added, the recovery cursors are shifted.
[add_cursors.py]
Is it possible to save and restore the cursors positions at the same place.

If I understand correctly, to this plugin should add an offset of the text by the same number of letters that will change.
Or somehow store and restore each cursor relative to each line.
My knowledge is too little to figure it out

skuroda

import sublime
import sublime_plugin
 
 
class CursorCommand(sublime_plugin.TextCommand):
    saved_cursors_map = {}
    def run(self, edit, action="add"):
        view = self.view
        cursors = view.sel()
        view_id = view.id()
        if view_id not in self.saved_cursors_map:
            self.saved_cursors_map[view_id] = set()
        if action == "add":
            for cursor in cursors:
                self.saved_cursors_map[view_id].add(cursor.begin())
        elif action == "show" and len(self.saved_cursors_map[view_id]) > 0:
            for cursor in cursors:
                self.saved_cursors_map[view_id].add(cursor.begin())
                
            cursors.clear()
            
            for cursor in self.saved_cursors_map[view_id]:
                cursors.add(cursor)
            self.saved_cursors_map[view_id].clear()
        elif action == "clear":
            self.saved_cursors_map[view_id].clear()
        elif action == "remove":
            for cursor in cursors:
                try:
                    self.saved_cursors_map[view_id].remove(cursor.begin())
                except KeyError:
                    pass

        self.highlight_regions()

    def highlight_regions(self):
        view_id = self.view.id()
        regions = [sublime.Region(x, x) for x in self.saved_cursors_map[view_id]]
        self.view.add_regions("saved_cursor_region", regions,
                              "keyword", "", sublime.DRAW_EMPTY)

class EventListener(sublime_plugin.EventListener):
    def on_modified(self, view):
        view.run_command("cursor", {"action": "noop"})

{ “keys”: [“f12”], “command”: “cursor”, “args”: {“action”: “add”}},
{ “keys”: [“f11”], “command”: “cursor”, “args”: {“action”: “show”}},
{ “keys”: [“f10”], “command”: “cursor”, “args”: {“action”: “clear”}},
{ “keys”: [“f9”], “command”: “cursor”, “args”: {“action”: “remove”}}

0 Likes

#2

Cursor positions are just a point, which is an offset into the buffer to a specific character. For example, if the first selection is at 3, then the cursor is at the third character.

When using a region with add_regions(), you’re telling it to save the locations of a specific region of text, and indeed edits to the text maintain that region.

That is, if you type some text prior to start of the region, the whole region will shift to the right once per character because it needs to keep marking out the region of text, which is moving.

Similarly when you delete text prior to the region it moves to the left, and if you delete text from inside the region it will shrink (it will also grow if you add text inside).

It’s a bit unclear what you’re asking here (i.e. is this mechanism not working as I described it here?).

If your intention is to mark position 20 and always have it be position 20 no matter what happens in the text (for example) then don’t use a region; just remember the number 20. The cursor will stop lining up with the text as it appeared prior if edits happen in such a case.

0 Likes

#3

this is what i want yep.
I just want to save the position of the cursors in the lines and then restore them to the same values

I haven’t found a similar plugin here, and I don’t have enough knowledge to write it myself…

0 Likes