undo/redo fix, some other features, open file improvements
--HG-- branch : pmacs2
This commit is contained in:
parent
6afec24fe0
commit
5a59f28525
9
IDEAS
9
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
|
||||
|
|
|
@ -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
|
||||
|
|
42
buffer2.py
42
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"
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
line one
another line
this is the last
|
|
@ -0,0 +1,4 @@
|
|||
line one
|
||||
another line
|
||||
this is the last
|
||||
(uh oh i added a fourth line!)
|
|
@ -0,0 +1,3 @@
|
|||
line one
|
||||
another line
|
||||
this is the last
|
35
method.py
35
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))
|
||||
|
||||
|
|
11
window2.py
11
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):
|
||||
|
|
Loading…
Reference in New Issue