undo/redo fix, some other features, open file improvements

--HG--
branch : pmacs2
This commit is contained in:
moculus 2007-07-19 16:38:17 +00:00
parent 6afec24fe0
commit 5a59f28525
8 changed files with 106 additions and 35 deletions

9
IDEAS
View File

@ -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: 2007/07/17:
It would be nice to be able to toggle various lexing rules on/off, so that for It would be nice to be able to toggle various lexing rules on/off, so that for

View File

@ -233,6 +233,41 @@ class Application(object):
slot = self.bufferlist.slots[i] slot = self.bufferlist.slots[i]
return (slot.height, slot.width) 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 # mini buffer handling
def get_mini_buffer(self): def get_mini_buffer(self):
return self.mini_buffer return self.mini_buffer
@ -702,7 +737,6 @@ def open_aes_file(path, nl, name=None):
p = getpass.getpass("Please enter the AES password: ") p = getpass.getpass("Please enter the AES password: ")
b = buffer2.AesBuffer(path, p, nl, name) b = buffer2.AesBuffer(path, p, nl, name)
return b return b
def open_plain_file(path, nl, name=None): def open_plain_file(path, nl, name=None):
b = buffer2.FileBuffer(path, nl, name) b = buffer2.FileBuffer(path, nl, name)
return b return b

View File

@ -17,6 +17,8 @@ class AddMove:
def restore(self, act=ACT_UNDO): def restore(self, act=ACT_UNDO):
assert act == ACT_UNDO or act == ACT_REDO assert act == ACT_UNDO or act == ACT_REDO
self.buffer.insert_lines(self.p, self.lines, act) 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 # used for undo/redo stacks when text will need to be removed
class DelMove: class DelMove:
@ -27,9 +29,12 @@ class DelMove:
def restore(self, act): def restore(self, act):
assert act == ACT_UNDO or act == ACT_REDO assert act == ACT_UNDO or act == ACT_REDO
self.buffer.delete(self.p1, self.p2, act) self.buffer.delete(self.p1, self.p2, act)
def getpos(self):
return self.p1
# abstract class # abstract class
class Buffer(object): class Buffer(object):
btype = 'generic'
def __init__(self, nl='\n', stack_limit=STACK_LIMIT): def __init__(self, nl='\n', stack_limit=STACK_LIMIT):
assert nl in ('\n', '\r', '\r\n'), "Invalid line ending" assert nl in ('\n', '\r', '\r\n'), "Invalid line ending"
self.lines = [""] self.lines = [""]
@ -86,12 +91,14 @@ class Buffer(object):
if len(self.undo_stack): if len(self.undo_stack):
move = self.undo_stack.pop(-1) move = self.undo_stack.pop(-1)
move.restore(ACT_UNDO) move.restore(ACT_UNDO)
return move.getpos()
else: else:
raise Exception, "Nothing to Undo!" raise Exception, "Nothing to Undo!"
def redo(self): def redo(self):
if len(self.redo_stack): if len(self.redo_stack):
move = self.redo_stack.pop(-1) move = self.redo_stack.pop(-1)
move.restore(ACT_REDO) move.restore(ACT_REDO)
return move.getpos()
else: else:
raise Exception, "Nothing to Redo!" raise Exception, "Nothing to Redo!"
@ -293,6 +300,7 @@ class Buffer(object):
# scratch is a singleton # scratch is a singleton
scratch = None scratch = None
class ScratchBuffer(Buffer): class ScratchBuffer(Buffer):
btype = 'scratch'
def __new__(cls, *args, **kwargs): def __new__(cls, *args, **kwargs):
global scratch global scratch
if scratch is None: if scratch is None:
@ -305,6 +313,7 @@ class ScratchBuffer(Buffer):
scratch = None scratch = None
class DataBuffer(Buffer): class DataBuffer(Buffer):
btype = 'data'
def __init__(self, name, data, nl='\n'): def __init__(self, name, data, nl='\n'):
Buffer.__init__(self, nl) Buffer.__init__(self, nl)
self._name = name self._name = name
@ -319,6 +328,7 @@ class DataBuffer(Buffer):
# console is another singleton # console is another singleton
console = None console = None
class ConsoleBuffer(Buffer): class ConsoleBuffer(Buffer):
btype = 'console'
def __new__(cls, *args, **kwargs): def __new__(cls, *args, **kwargs):
global console global console
if console is None: if console is None:
@ -345,6 +355,7 @@ class ConsoleBuffer(Buffer):
return True return True
class FileBuffer(Buffer): class FileBuffer(Buffer):
btype = 'file'
def __init__(self, path, nl='\n', name=None): def __init__(self, path, nl='\n', name=None):
'''fb = FileBuffer(path)''' '''fb = FileBuffer(path)'''
Buffer.__init__(self, nl) Buffer.__init__(self, nl)
@ -454,6 +465,7 @@ class FileBuffer(Buffer):
self.save() self.save()
class AesBuffer(FileBuffer): class AesBuffer(FileBuffer):
btype = 'aesfile'
def __init__(self, path, password, nl='\n', name=None): def __init__(self, path, password, nl='\n', name=None):
'''fb = FileBuffer(path)''' '''fb = FileBuffer(path)'''
FileBuffer.__init__(self, path, nl, name) FileBuffer.__init__(self, path, nl, name)
@ -462,3 +474,33 @@ class AesBuffer(FileBuffer):
return aes.decrypt_data(data, self.password) return aes.decrypt_data(data, self.password)
def write_filter(self, data): def write_filter(self, data):
return aes.encrypt_data(data, self.password) 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"

1
code_examples/cr.txt Normal file
View File

@ -0,0 +1 @@
line one another line this is the last

4
code_examples/crlf.txt Normal file
View File

@ -0,0 +1,4 @@
line one
another line
this is the last
(uh oh i added a fourth line!)

3
code_examples/lf.txt Normal file
View File

@ -0,0 +1,3 @@
line one
another line
this is the last

View File

@ -173,39 +173,16 @@ class OpenFile(Method):
'''Open file in a new buffer, or go to file's open buffer''' '''Open file in a new buffer, or go to file's open buffer'''
args = [Argument('filename', datatype="path", prompt="Open File: ")] args = [Argument('filename', datatype="path", prompt="Open File: ")]
def _execute(self, w, **vargs): def _execute(self, w, **vargs):
path = vargs['filename'] b = w.application.open_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)
SwitchBuffer().execute(w, buffername=b.name()) SwitchBuffer().execute(w, buffername=b.name())
class OpenAesFile(Method): class OpenAesFile(Method):
'''Open AES encrypted file in a new buffer, or go to file's open buffer''' '''Open AES encrypted file in a new buffer, or go to file's open buffer'''
args = [Argument('filename', datatype="path", prompt="Open AES File: "), args = [Argument('filename', datatype="path", prompt="Open AES File: "),
Argument('password', prompt="Use AES Password: ")] Argument('password', prompt="Use AES Password: ")]
def _execute(self, w, **vargs): def _execute(self, w, **vargs):
path = vargs['filename'] b = w.application.open_path(vargs['filename'], 'aes', vargs['password'])
password = vargs['password'] SwitchBuffer().execute(w, buffername=b.name())
path = os.path.abspath(os.path.realpath(util.expand_tilde(path))) return
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)
class SwitchBuffer(Method): class SwitchBuffer(Method):
'''Switch to a different''' '''Switch to a different'''
args = [Argument('buffername', datatype="buffer", prompt="Switch To Buffer: ", args = [Argument('buffername', datatype="buffer", prompt="Switch To Buffer: ",
@ -736,14 +713,14 @@ class Undo(Method):
'''Undo last action''' '''Undo last action'''
def _execute(self, w, **vargs): def _execute(self, w, **vargs):
try: try:
w.buffer.undo() w.undo()
except Exception, e: except Exception, e:
w.application.set_error("%s" % (e)) w.application.set_error("%s" % (e))
class Redo(Method): class Redo(Method):
'''Redo last undone action''' '''Redo last undone action'''
def _execute(self, w, **vargs): def _execute(self, w, **vargs):
try: try:
w.buffer.redo() w.redo()
except Exception, e: except Exception, e:
w.application.set_error("%s" % (e)) w.application.set_error("%s" % (e))

View File

@ -552,13 +552,14 @@ class Window(object):
return self.buffer.lines[y][x] return self.buffer.lines[y][x]
# undo/redo # undo/redo
# XYZ
def undo(self): def undo(self):
# TODO: put something here to move the cursor to the area of the undo p = self.buffer.undo()
self.buffer.undo() if not self.point_is_visible(p):
self.goto(p)
def redo(self): def redo(self):
# TODO: put something here to move the cursor to the area of the redo p = self.buffer.redo()
self.buffer.redo() if not self.point_is_visible(p):
self.goto(p)
# highlighting tokens # highlighting tokens
def get_token(self): def get_token(self):