Too late, I did one this morning
Quick and (very) dirty, but it works…
I won’t go further since your friend’s will probably be better.
Some ideas: it could be useful to group some of the cursor movements (so that pressing the right arrow 10 times will only be recorded as 1 command), and also to have a history of the where modifications were made, rather than just cursor movements.
And the ‘cursor redo stack’ doesn’t need to be cleared each time there’s a modification
EDIT: this is per-view… but it’s easy to adapt for multiple files/views.
Here you go:
import sublime, sublimeplugin
from collections import defaultdict
class CursorHistory(sublimeplugin.TextCommand):
_undo = defaultdict(list)
_redo = defaultdict(list)
_lastSize = defaultdict(int)
isUndoing = False
# the following properties are to make it easier to migrate to sublime text X
# (per-view command instances)
@property
def undo(self): return self._undo[sublime.activeWindow().activeView().id()]
@undo.setter
def undo(self, value): self._undo[sublime.activeWindow().activeView().id()] = value
@property
def redo(self): return self._redo[sublime.activeWindow().activeView().id()]
@redo.setter
def redo(self, value): self._redo[sublime.activeWindow().activeView().id()] = value
@property
def lastSize(self): return self._lastSize[sublime.activeWindow().activeView().id()]
@lastSize.setter
def lastSize(self, value): self._lastSize[sublime.activeWindow().activeView().id()] = value
def onSelectionModified(self, view):
if self.isUndoing:
self.isUndoing = False
return
self.redo = ]
if self.lastSize == view.size():
# cursor movement
self.undo.append(tuple(view.sel()))
else:
# modification
self.lastSize = view.size()
def run(self, view, args):
if len(args) > 0 and args[0] in 'redo', 'up']:
try:
prev = self.redo.pop()
if prev:
if prev[0] == view.sel()[0]:
self.undo.append(prev)
prev = self.redo.pop()
self.undo.append(prev)
self.isUndoing = True
view.sel().clear()
view.sel().add(prev[0])
except IndexError:
pass
else:
try:
prev = self.undo.pop()
if prev:
if prev[0] == view.sel()[0]:
self.redo.append(prev)
prev = self.undo.pop()
self.redo.append(prev)
self.isUndoing = True
view.sel().clear()
view.sel().add(prev[0])
except IndexError:
pass
And add this to the keymap:
<binding key="ctrl+alt+left" command="cursorHistory undo"/>
<binding key="ctrl+alt+right" command="cursorHistory redo"/>