From 5a59f28525db2c51c346a00686881c7f71eeaa4c Mon Sep 17 00:00:00 2001 From: moculus Date: Thu, 19 Jul 2007 16:38:17 +0000 Subject: [PATCH] undo/redo fix, some other features, open file improvements --HG-- branch : pmacs2 --- IDEAS | 9 +++++++++ application.py | 36 +++++++++++++++++++++++++++++++++++- buffer2.py | 42 ++++++++++++++++++++++++++++++++++++++++++ code_examples/cr.txt | 1 + code_examples/crlf.txt | 4 ++++ code_examples/lf.txt | 3 +++ method.py | 35 ++++++----------------------------- window2.py | 11 ++++++----- 8 files changed, 106 insertions(+), 35 deletions(-) create mode 100644 code_examples/cr.txt create mode 100644 code_examples/crlf.txt create mode 100644 code_examples/lf.txt diff --git a/IDEAS b/IDEAS index 1ad79a9..8822eb8 100644 --- a/IDEAS +++ b/IDEAS @@ -1,3 +1,12 @@ +2007/07/19: + +Convert all classes to subclass object. + +2007/07/19: + +The minibuffer should be able to expand to become multi-line if the +prompt/input string becomes too long. + 2007/07/17: It would be nice to be able to toggle various lexing rules on/off, so that for diff --git a/application.py b/application.py index 6edd614..30579a4 100755 --- a/application.py +++ b/application.py @@ -233,6 +233,41 @@ class Application(object): slot = self.bufferlist.slots[i] return (slot.height, slot.width) + # files and stuff + def open_path(self, path, cipher=None, password=None): + path = os.path.abspath(os.path.realpath(util.expand_tilde(path))) + b = self.get_buffer_by_path(path) + if b is None: + name = os.path.basename(path) + if self.has_buffer_name(name): + i = 1 + auxname = '%s/%d' % (name, i) + while self.has_buffer_name(auxname): + i += 1 + auxname = '%s/%d' % (name, i) + name = auxname + + mode_name = None + if cipher is None: + if not os.path.exists(path) or os.path.isfile(path): + b = buffer2.FileBuffer(path, name=name) + elif os.path.isdir(path): + b = buffer2.DirBuffer(path, name=name) + mode_name = 'fundamental' + else: + raise Exception, "not a file or dir: %r" % path + elif cipher == 'aes': + if not password: + raise Exception, "password is required" + if not os.path.exists(path) or os.path.isfile(path): + b = buffer2.AesBuffer(path, password, name=name) + else: + raise Exception, "not a file or dir: %r" % path + b.open() + window2.Window(b, self, height=0, width=0, mode_name=mode_name) + self.add_buffer(b) + return b + # mini buffer handling def get_mini_buffer(self): return self.mini_buffer @@ -702,7 +737,6 @@ def open_aes_file(path, nl, name=None): p = getpass.getpass("Please enter the AES password: ") b = buffer2.AesBuffer(path, p, nl, name) return b - def open_plain_file(path, nl, name=None): b = buffer2.FileBuffer(path, nl, name) return b diff --git a/buffer2.py b/buffer2.py index b0b2b79..a48555b 100644 --- a/buffer2.py +++ b/buffer2.py @@ -17,6 +17,8 @@ class AddMove: def restore(self, act=ACT_UNDO): assert act == ACT_UNDO or act == ACT_REDO self.buffer.insert_lines(self.p, self.lines, act) + def getpos(self): + return self.p # used for undo/redo stacks when text will need to be removed class DelMove: @@ -27,9 +29,12 @@ class DelMove: def restore(self, act): assert act == ACT_UNDO or act == ACT_REDO self.buffer.delete(self.p1, self.p2, act) + def getpos(self): + return self.p1 # abstract class class Buffer(object): + btype = 'generic' def __init__(self, nl='\n', stack_limit=STACK_LIMIT): assert nl in ('\n', '\r', '\r\n'), "Invalid line ending" self.lines = [""] @@ -86,12 +91,14 @@ class Buffer(object): if len(self.undo_stack): move = self.undo_stack.pop(-1) move.restore(ACT_UNDO) + return move.getpos() 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() else: raise Exception, "Nothing to Redo!" @@ -293,6 +300,7 @@ class Buffer(object): # scratch is a singleton scratch = None class ScratchBuffer(Buffer): + btype = 'scratch' def __new__(cls, *args, **kwargs): global scratch if scratch is None: @@ -305,6 +313,7 @@ class ScratchBuffer(Buffer): scratch = None class DataBuffer(Buffer): + btype = 'data' def __init__(self, name, data, nl='\n'): Buffer.__init__(self, nl) self._name = name @@ -319,6 +328,7 @@ class DataBuffer(Buffer): # console is another singleton console = None class ConsoleBuffer(Buffer): + btype = 'console' def __new__(cls, *args, **kwargs): global console if console is None: @@ -345,6 +355,7 @@ class ConsoleBuffer(Buffer): return True class FileBuffer(Buffer): + btype = 'file' def __init__(self, path, nl='\n', name=None): '''fb = FileBuffer(path)''' Buffer.__init__(self, nl) @@ -454,6 +465,7 @@ class FileBuffer(Buffer): self.save() class AesBuffer(FileBuffer): + btype = 'aesfile' def __init__(self, path, password, nl='\n', name=None): '''fb = FileBuffer(path)''' FileBuffer.__init__(self, path, nl, name) @@ -462,3 +474,33 @@ class AesBuffer(FileBuffer): return aes.decrypt_data(data, self.password) def write_filter(self, data): return aes.encrypt_data(data, self.password) + +class DirBuffer(Buffer): + btype = 'dir' + def __init__(self, path, nl='\n', name=None): + Buffer.__init__(self, nl) + self.path = os.path.realpath(path) + if name is None: + self._name = os.path.basename(self.path) + else: + self._name = name + def readonly(self): + return True + def name(self): + return self._name + def path_exists(self): + return os.path.exists(self.path) + def open(self): + if not self.path_exists(): + raise Exception, "directory %r does not exists" % self.path + self.lines = [] + if self.path != '/': + self.lines.append('..') + for name in os.listdir(self.path): + self.lines.append(name) + def reload(self): + self.open() + def save(self, force=False): + raise Exception, "can't save a directory buffer" + def save_as(self, path): + raise Exception, "can't save a directory buffer" diff --git a/code_examples/cr.txt b/code_examples/cr.txt new file mode 100644 index 0000000..9976876 --- /dev/null +++ b/code_examples/cr.txt @@ -0,0 +1 @@ +line one another line this is the last \ No newline at end of file diff --git a/code_examples/crlf.txt b/code_examples/crlf.txt new file mode 100644 index 0000000..a0deb73 --- /dev/null +++ b/code_examples/crlf.txt @@ -0,0 +1,4 @@ +line one +another line +this is the last +(uh oh i added a fourth line!) \ No newline at end of file diff --git a/code_examples/lf.txt b/code_examples/lf.txt new file mode 100644 index 0000000..95e45c0 --- /dev/null +++ b/code_examples/lf.txt @@ -0,0 +1,3 @@ +line one +another line +this is the last diff --git a/method.py b/method.py index a792d04..83b8797 100644 --- a/method.py +++ b/method.py @@ -173,39 +173,16 @@ class OpenFile(Method): '''Open file in a new buffer, or go to file's open buffer''' args = [Argument('filename', datatype="path", prompt="Open File: ")] def _execute(self, w, **vargs): - path = vargs['filename'] - path = os.path.abspath(os.path.realpath(util.expand_tilde(path))) - a = w.application - b = w.application.get_buffer_by_path(path) - if b is None: - name = os.path.basename(path) - if w.application.has_buffer_name(name): - i = 1 - auxname = '%s/%d' % (name, i) - while w.application.has_buffer_name(auxname): - i += 1 - auxname = '%s/%d' % (name, i) - name = auxname - b = buffer2.FileBuffer(path, name=name) - b.open() - window2.Window(b, a, height=0, width=0) - w.application.add_buffer(b) + b = w.application.open_path(vargs['filename']) SwitchBuffer().execute(w, buffername=b.name()) class OpenAesFile(Method): '''Open AES encrypted file in a new buffer, or go to file's open buffer''' args = [Argument('filename', datatype="path", prompt="Open AES File: "), Argument('password', prompt="Use AES Password: ")] def _execute(self, w, **vargs): - path = vargs['filename'] - password = vargs['password'] - path = os.path.abspath(os.path.realpath(util.expand_tilde(path))) - a = w.application - if not w.application.has_buffer_name(path): - b = buffer2.AesBuffer(path, password) - b.open() - window2.Window(b, a, height=0, width=0) - w.application.add_buffer(b) - SwitchBuffer().execute(w, buffername=path) + b = w.application.open_path(vargs['filename'], 'aes', vargs['password']) + SwitchBuffer().execute(w, buffername=b.name()) + return class SwitchBuffer(Method): '''Switch to a different''' args = [Argument('buffername', datatype="buffer", prompt="Switch To Buffer: ", @@ -736,14 +713,14 @@ class Undo(Method): '''Undo last action''' def _execute(self, w, **vargs): try: - w.buffer.undo() + w.undo() except Exception, e: w.application.set_error("%s" % (e)) class Redo(Method): '''Redo last undone action''' def _execute(self, w, **vargs): try: - w.buffer.redo() + w.redo() except Exception, e: w.application.set_error("%s" % (e)) diff --git a/window2.py b/window2.py index e92d672..631e92b 100644 --- a/window2.py +++ b/window2.py @@ -552,13 +552,14 @@ class Window(object): return self.buffer.lines[y][x] # undo/redo - # XYZ def undo(self): - # TODO: put something here to move the cursor to the area of the undo - self.buffer.undo() + p = self.buffer.undo() + if not self.point_is_visible(p): + self.goto(p) def redo(self): - # TODO: put something here to move the cursor to the area of the redo - self.buffer.redo() + p = self.buffer.redo() + if not self.point_is_visible(p): + self.goto(p) # highlighting tokens def get_token(self):