From 2e5eb32fd2ac8ea2bfced83ece21acbdc41170b0 Mon Sep 17 00:00:00 2001 From: moculus Date: Wed, 20 Aug 2008 01:10:47 +0000 Subject: [PATCH] undo id--awesome --HG-- branch : pmacs2 --- BUGS | 7 ++----- application.py | 3 +-- buffer.py | 36 +++++++++++++++++------------------- method/__init__.py | 2 +- 4 files changed, 21 insertions(+), 27 deletions(-) diff --git a/BUGS b/BUGS index 72565ef..1a67d01 100644 --- a/BUGS +++ b/BUGS @@ -2,7 +2,6 @@ 2008/06/25: * when the "first" point is on a wrapping line bad things happen. - * try implementing an "undo ID" in the application. * the "last visible" calculation doesn't handle long lines correctly. this affects page-up/page-down/etc. @@ -21,7 +20,5 @@ first-visible/cursor syncing with drawn window may be buggy. 2007/09/14: -known deficiencies: - 1. a single action (global search and replace) may produce N actions that - need to be individually "undone". This is annoying. - 3. opening files larger than 5-10k lines can be very slow + known deficiencies: + 3. opening files larger than 5-10k lines can be very slow diff --git a/application.py b/application.py index 9a43113..9a89a31 100755 --- a/application.py +++ b/application.py @@ -28,7 +28,6 @@ def run_app(stdscr, buffers, jump_to_line=None, init_mode=None): a.run() MAX_ERROR_DISPLAY = 128 - KILL_RING_LIMIT = 128 WORD_LETTERS = list(string.letters + string.digits) ERROR_TIMEOUT = -1 @@ -42,7 +41,7 @@ class Application(object): # initialize some basic stuff # a highlighted_range contains three things: (window, start_p, end_p) - #self.state = defaultdict(lambda: {}) + #self.state = defaultdict(lambda: {}) self.state = {} self.config = {} self.highlighted_ranges = [] diff --git a/buffer.py b/buffer.py index cd0f06c..e7435a6 100644 --- a/buffer.py +++ b/buffer.py @@ -12,25 +12,13 @@ STACK_LIMIT = 1024 class ReadOnlyError(Exception): pass -# used for multiple text additions/deletions -class GroupMove(object): - def __init__(self, buffer, p, moves): - self.buffer = buffer - self.lines = lines - self.moves = moves - def restore(self, act=ACT_UNDO): - assert act == ACT_UNDO or act == ACT_REDO - for move in self.moves: - move.restore(act) - def getpos(self): - return self.moves[-1].getpos() - # used for undo/redo stacks when text will need to be added back class AddMove(object): def __init__(self, buffer, p, lines): self.buffer = buffer self.p = p self.lines = lines + self.undo_id = buffer.undo_id def restore(self, act=ACT_UNDO): assert act == ACT_UNDO or act == ACT_REDO self.buffer.insert_lines(self.p, self.lines, act) @@ -43,6 +31,7 @@ class DelMove(object): self.buffer = buffer self.p1 = p1 self.p2 = p2 + self.undo_id = buffer.undo_id def restore(self, act): assert act == ACT_UNDO or act == ACT_REDO self.buffer.delete(self.p1, self.p2, act) @@ -58,6 +47,7 @@ class Buffer(object): def __init__(self, stack_limit=STACK_LIMIT): self.lines = [""] self.windows = [] + self.undo_id = 1 self.undo_stack = [] self.redo_stack = [] self.stack_limit = stack_limit @@ -126,16 +116,24 @@ class Buffer(object): raise Exception, "Invalid act: %d" % (act) def undo(self): if len(self.undo_stack): - move = self.undo_stack.pop(-1) - move.restore(ACT_UNDO) - return move.getpos() + undo_id = self.undo_stack[-1].undo_id + pos = None + while self.undo_stack and self.undo_stack[-1].undo_id == undo_id: + move = self.undo_stack.pop(-1) + move.restore(ACT_UNDO) + pos = move.getpos() + return pos else: raise Exception, "Nothing to Undo!" def redo(self): if len(self.redo_stack): - move = self.redo_stack.pop(-1) - move.restore(ACT_REDO) - return move.getpos() + undo_id = self.redo_stack[-1].undo_id + pos = None + while self.redo_stack and self.redo_stack[-1].undo_id == undo_id: + move = self.redo_stack.pop(-1) + move.restore(ACT_REDO) + pos = move.getpos() + return pos else: raise Exception, "Nothing to Redo!" diff --git a/method/__init__.py b/method/__init__.py index 38d6334..970af4e 100644 --- a/method/__init__.py +++ b/method/__init__.py @@ -108,7 +108,7 @@ class Method(object): arg.ask_for_value(self, w, **vargs) return self._execute(w, **vargs) - + w.buffer.undo_id += 1 def _execute(self, w, **vargs): raise Exception, "Unimplemented Method: %s %r" % (self.name, vargs)