parent
e1ad655912
commit
638f10174a
|
@ -2,9 +2,9 @@
|
|||
import curses, curses.ascii, getpass, os, re, string, sets, sys, termios, time
|
||||
import traceback
|
||||
|
||||
import buffer2, bufferlist, color, completer, keyinput, method, minibuffer, mode, mode2
|
||||
import buffer, bufferlist, color, completer, keyinput, method, minibuffer, mode, mode2
|
||||
import util, window2
|
||||
from point2 import Point
|
||||
from point import Point
|
||||
|
||||
def run(buffers, jump_to_line=None, init_mode=None):
|
||||
# save terminal state so we can restore it when the program exits
|
||||
|
@ -113,10 +113,10 @@ class Application(object):
|
|||
|
||||
# initialize our buffers
|
||||
# note that the first buffer in buffers will be initially visible
|
||||
buffers.append(buffer2.ScratchBuffer())
|
||||
buffers.append(buffer2.ConsoleBuffer())
|
||||
buffers.append(buffer.ScratchBuffer())
|
||||
buffers.append(buffer.ConsoleBuffer())
|
||||
if self.rcerror:
|
||||
buffers.insert(0, buffer2.DataBuffer('*RcError*', self.rcerror))
|
||||
buffers.insert(0, buffer.DataBuffer('*RcError*', self.rcerror))
|
||||
|
||||
self.bufferlist = bufferlist.BufferList(height, width)
|
||||
self.active_slot = 0
|
||||
|
@ -223,11 +223,11 @@ class Application(object):
|
|||
if cipher is None:
|
||||
if not os.path.exists(path) or os.path.isfile(path):
|
||||
if binary:
|
||||
b = buffer2.Binary32Buffer(path, name=name)
|
||||
b = buffer.Binary32Buffer(path, name=name)
|
||||
else:
|
||||
b = buffer2.FileBuffer(path, name=name)
|
||||
b = buffer.FileBuffer(path, name=name)
|
||||
elif os.path.isdir(path):
|
||||
b = buffer2.DirBuffer(path, name=name)
|
||||
b = buffer.DirBuffer(path, name=name)
|
||||
mode_name = 'dir'
|
||||
else:
|
||||
raise Exception, "not a file or dir: %r" % path
|
||||
|
@ -235,7 +235,7 @@ class Application(object):
|
|||
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)
|
||||
b = buffer.AesBuffer(path, password, name=name)
|
||||
else:
|
||||
raise Exception, "not a file or dir: %r" % path
|
||||
b.open()
|
||||
|
@ -297,7 +297,7 @@ class Application(object):
|
|||
f = open(path, 'w')
|
||||
f.write(data)
|
||||
f.close()
|
||||
b = buffer2.FileBuffer(path)
|
||||
b = buffer.FileBuffer(path)
|
||||
b.open()
|
||||
window2.Window(b, self, height=0, width=0)
|
||||
self.add_buffer(b)
|
||||
|
@ -307,7 +307,7 @@ class Application(object):
|
|||
if self.has_buffer_name(name):
|
||||
b = self.bufferlist.buffer_names[name]
|
||||
self.remove_buffer(b)
|
||||
b = buffer2.DataBuffer(name, data)
|
||||
b = buffer.DataBuffer(name, data)
|
||||
if modename is not None:
|
||||
b.modename = modename
|
||||
window2.Window(b, self, height=0, width=0)
|
||||
|
@ -742,17 +742,17 @@ class Application(object):
|
|||
def open_aes_file(path, nl, name=None):
|
||||
if os.path.isfile(path) or not os.path.exists(path):
|
||||
p = getpass.getpass("Please enter the AES password: ")
|
||||
return buffer2.AesBuffer(path, p, nl, name)
|
||||
return buffer.AesBuffer(path, p, nl, name)
|
||||
else:
|
||||
raise Exception, "can't open %r; unsupported file type" % path
|
||||
def open_plain_file(path, nl, name=None, binary=False):
|
||||
if os.path.isfile(path) or not os.path.exists(path):
|
||||
if binary:
|
||||
return buffer2.Binary32Buffer(path, nl, name)
|
||||
return buffer.Binary32Buffer(path, nl, name)
|
||||
else:
|
||||
return buffer2.FileBuffer(path, nl, name)
|
||||
return buffer.FileBuffer(path, nl, name)
|
||||
elif os.path.isdir(path):
|
||||
return buffer2.DirBuffer(path, nl, name)
|
||||
return buffer.DirBuffer(path, nl, name)
|
||||
else:
|
||||
raise Exception, "can't open %r; unsupported file type" % path
|
||||
|
||||
|
@ -832,7 +832,7 @@ if __name__ == "__main__":
|
|||
try:
|
||||
b = f(path, nl, name, opts.binary)
|
||||
b.open()
|
||||
except buffer2.BinaryDataException, e:
|
||||
except buffer.BinaryDataException, e:
|
||||
b = f(path, nl, name, True)
|
||||
b.open()
|
||||
|
||||
|
|
|
@ -0,0 +1,607 @@
|
|||
import datetime, grp, md5, os, pwd, re, sets, shutil, stat, string
|
||||
import aes, dirutil, regex, highlight2
|
||||
from point import Point
|
||||
|
||||
# undo/redo stack constants
|
||||
ACT_NORM = 0
|
||||
ACT_UNDO = 1
|
||||
ACT_REDO = 2
|
||||
STACK_LIMIT = 1024
|
||||
|
||||
# used for undo/redo stacks when text will need to be added back
|
||||
class AddMove:
|
||||
def __init__(self, buffer, p, lines):
|
||||
self.buffer = buffer
|
||||
self.p = p
|
||||
self.lines = lines
|
||||
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:
|
||||
def __init__(self, buffer, p1, p2):
|
||||
self.buffer = buffer
|
||||
self.p1 = p1
|
||||
self.p2 = p2
|
||||
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 = [""]
|
||||
self.windows = []
|
||||
self.undo_stack = []
|
||||
self.redo_stack = []
|
||||
self.stack_limit = stack_limit
|
||||
self.nl = nl
|
||||
self.modified = False
|
||||
self.highlights = {}
|
||||
|
||||
# basic file operation stuff
|
||||
def _open_file_r(self, path):
|
||||
path = os.path.realpath(path)
|
||||
if not os.path.isfile(path):
|
||||
raise Exception, "Path '%s' does not exist" % (path)
|
||||
if not os.access(path, os.R_OK):
|
||||
raise Exception, "Path '%s' cannot be read" % (path)
|
||||
f = open(path, 'r')
|
||||
return f
|
||||
def _open_file_w(self, path):
|
||||
if os.path.isfile(path):
|
||||
raise Exception, "Path '%s' already exists" % (path)
|
||||
d = os.path.dirname(path)
|
||||
if not os.access(d, os.R_OK):
|
||||
raise Exception, "Dir '%s' cannot be read" % (path)
|
||||
if not os.access(d, os.W_OK):
|
||||
raise Exception, "Dir '%s' cannot be written" % (path)
|
||||
f = open(path, 'w')
|
||||
return f
|
||||
def _temp_path(self, path):
|
||||
(dirname, basename) = os.path.split(path)
|
||||
return os.path.join(dirname, ".__%s__pmacs" % (basename))
|
||||
|
||||
# undo/redo stack
|
||||
def _stack_trim(self, stack):
|
||||
if self.stack_limit:
|
||||
while len(stack) > self.stack_limit:
|
||||
stack.pop(0)
|
||||
def add_to_stack(self, move, act):
|
||||
if act == ACT_NORM:
|
||||
self.redo_stack = []
|
||||
self.undo_stack.append(move)
|
||||
self._stack_trim(self.undo_stack)
|
||||
elif act == ACT_UNDO:
|
||||
self.redo_stack.append(move)
|
||||
self._stack_trim(self.redo_stack)
|
||||
elif act == ACT_REDO:
|
||||
self.undo_stack.append(move)
|
||||
self._stack_trim(self.undo_stack)
|
||||
else:
|
||||
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()
|
||||
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!"
|
||||
|
||||
# window-buffer communication
|
||||
def add_window(self, w):
|
||||
if w not in self.windows:
|
||||
self.windows.append(w)
|
||||
modename = w.mode.name()
|
||||
if modename not in self.highlights and w.mode.lexer is not None:
|
||||
self.highlights[modename] = highlight2.Highlighter(w.mode.lexer)
|
||||
self.highlights[modename].highlight(self.lines)
|
||||
#if modename not in self.tabbing and w.mode.tabber is not None:
|
||||
# self.tabbing[modename] =
|
||||
def remove_window(self, w):
|
||||
if w in self.windows:
|
||||
self.windows.remove(w)
|
||||
modename = w.mode.name()
|
||||
found = False
|
||||
for w2 in self.windows:
|
||||
if w2.mode.name() == modename:
|
||||
found = True
|
||||
break
|
||||
if not found:
|
||||
del self.highlights[modename]
|
||||
def _region_add(self, p1, p2, lines, act):
|
||||
move = DelMove(self, p1, p2)
|
||||
self.add_to_stack(move, act)
|
||||
for w in self.windows:
|
||||
w.region_added(p1, lines)
|
||||
for name in self.highlights:
|
||||
self.highlights[name].relex_add(self.lines, p1.y, p1.x, lines)
|
||||
def _region_del(self, p1, p2, lines, act):
|
||||
move = AddMove(self, p1, lines)
|
||||
self.add_to_stack(move, act)
|
||||
for w in self.windows:
|
||||
w.region_removed(p1, p2)
|
||||
for name in self.highlights:
|
||||
self.highlights[name].relex_del(self.lines, p1.y, p1.x, p2.y, p2.x)
|
||||
|
||||
# internal validation
|
||||
def _validate_point(self, p):
|
||||
self._validate_xy(p.x, p.y)
|
||||
def _validate_xy(self, x, y):
|
||||
assert y >= 0 and y < len(self.lines), \
|
||||
"xy1: %d >= 0 and %d < %d" % (y, y, len(self.lines))
|
||||
assert x >= 0 and x <= len(self.lines[y]), \
|
||||
"xy2: %d >= 0 and %d <= %d" % (x, x, len(self.lines[y]))
|
||||
def _validate_y(self, y):
|
||||
assert y >= 0 and y < len(self.lines), \
|
||||
"y: %d >= 0 and %d < %d" % (y, y, len(self.lines))
|
||||
|
||||
# deal with the actual logical document string
|
||||
def num_chars(self):
|
||||
n = 0
|
||||
for line in self.lines[:-1]:
|
||||
n += len(line) + 1
|
||||
n += len(self.lines[-1])
|
||||
return n
|
||||
def num_lines(self):
|
||||
return len(self.lines)
|
||||
def make_string(self, nl='\n'):
|
||||
return nl.join(self.lines)
|
||||
|
||||
# methods to be overridden by subclasses
|
||||
def name(self):
|
||||
return "Generic"
|
||||
def close(self):
|
||||
pass
|
||||
def open(self):
|
||||
pass
|
||||
def changed(self):
|
||||
return self.modified
|
||||
def reload(self):
|
||||
raise Exception, "%s reload: Unimplemented" % (self.name())
|
||||
def save_as(self, path, force=False):
|
||||
# check to see if the path exists, and if we're prepared to overwrite it
|
||||
# if yes to both, get its mode so we can preserve the path's permissions
|
||||
mode = None
|
||||
if os.path.exists(path):
|
||||
if force:
|
||||
mode = os.stat(self.path)[0]
|
||||
else:
|
||||
raise Exception, "oh no! %r already exists" % path
|
||||
|
||||
# create the string that we're going to write into the file
|
||||
data = self.write_filter(self.make_string(nl=self.nl))
|
||||
|
||||
# create a safe temporary path to write to, and write out data to it
|
||||
temp_path = self._temp_path()
|
||||
f2 = self._open_file_w(temp_path)
|
||||
f2.write(data)
|
||||
f2.close()
|
||||
|
||||
# move the temporary file to the actual path; maybe change permissions
|
||||
shutil.move(temp_path, path)
|
||||
if mode:
|
||||
os.chmod(path, mode)
|
||||
|
||||
# the file has not been modified now
|
||||
self.modified = False
|
||||
def readonly(self):
|
||||
return False
|
||||
def read_filter(self, data):
|
||||
return data
|
||||
def write_filter(self, data):
|
||||
return data
|
||||
|
||||
# point retrieval
|
||||
def get_buffer_start(self):
|
||||
return Point(0, 0)
|
||||
def get_buffer_end(self):
|
||||
return Point(len(self.lines[-1]), len(self.lines) - 1)
|
||||
|
||||
# data retrieval
|
||||
def get_sublines(self, p1, p2):
|
||||
self._validate_point(p1)
|
||||
self._validate_point(p2)
|
||||
assert p1 <= p2, "p1.x (%d) > p2.x (%d)" % (p1.x, p2.x)
|
||||
lines = []
|
||||
x = p1.x
|
||||
for i in range(p1.y, p2.y):
|
||||
lines.append(self.lines[i][x:])
|
||||
x = 0
|
||||
lines.append(self.lines[p2.y][x:p2.x])
|
||||
return lines
|
||||
def get_substring(self, p1, p2):
|
||||
lines = self.get_sublines(p1, p2)
|
||||
return '\n'.join(lines)
|
||||
|
||||
# buffer set
|
||||
def set_lines(self, lines, force=False):
|
||||
if not force and self.readonly():
|
||||
raise Exception, "set_data: buffer is readonly"
|
||||
start = self.get_buffer_start()
|
||||
end = self.get_buffer_end()
|
||||
self.delete(start, end, force=force)
|
||||
self.insert_lines(start, lines, force=force)
|
||||
self.modified = True
|
||||
def set_data(self, data, force=False):
|
||||
lines = data.split('\n')
|
||||
self.set_lines(lines, force)
|
||||
|
||||
# insertion into buffer
|
||||
def insert_lines(self, p, lines, act=ACT_NORM, force=False):
|
||||
#if lines == ['(']:
|
||||
# raise Exception, "damn"
|
||||
llen = len(lines)
|
||||
assert llen > 0
|
||||
if not force:
|
||||
assert not self.readonly(), "insert_string: buffer is read-only"
|
||||
p2 = p.vadd(len(lines[-1]), llen - 1)
|
||||
if llen > 1:
|
||||
self.lines.insert(p.y + 1, [])
|
||||
self.lines[p.y + 1] = lines[-1] + self.lines[p.y][p.x:]
|
||||
self.lines[p.y] = self.lines[p.y][:p.x] + lines[0]
|
||||
for i in range(1, llen - 1):
|
||||
self.lines.insert(p.y + i, lines[i])
|
||||
else:
|
||||
self.lines[p.y] = self.lines[p.y][:p.x] + lines[-1] + self.lines[p.y][p.x:]
|
||||
self._region_add(p, p2, lines, act)
|
||||
self.modified = True
|
||||
def insert_string(self, p, s, act=ACT_NORM, force=False):
|
||||
lines = s.split("\n")
|
||||
self.insert_lines(p, lines, act, force)
|
||||
|
||||
# deletion from buffer
|
||||
def delete(self, p1, p2, act=ACT_NORM, force=False):
|
||||
"""delete characters from p1 up to p2 from the buffer"""
|
||||
if not force:
|
||||
assert not self.readonly(), "delete_string: buffer is read-only"
|
||||
self._validate_point(p1)
|
||||
self._validate_point(p2)
|
||||
if p1 == p2:
|
||||
return
|
||||
assert p1 < p2, "p1 %r > p2 %r" % (p1, p2)
|
||||
lines = self.get_sublines(p1, p2)
|
||||
line1 = self.lines[p1.y]
|
||||
line2 = self.lines[p2.y]
|
||||
self.lines[p1.y:p2.y+1] = ["%s%s" % (line1[:p1.x], line2[p2.x:])]
|
||||
self._region_del(p1, p2, lines, act)
|
||||
self.modified = True
|
||||
def delete_char(self, p, act=ACT_NORM, force=False):
|
||||
if p.x == len(self.lines[p.y]):
|
||||
p2 = Point(0, p.y + 1)
|
||||
else:
|
||||
p2 = Point(p.x + 1, p.y)
|
||||
self.delete(p, p2, act=act, force=force)
|
||||
def overwrite_char(self, p, c, act=ACT_NORM, force=False):
|
||||
self.delete_char(p, act=act, force=force)
|
||||
self.insert_string(p, c, act=act, force=force)
|
||||
|
||||
# random
|
||||
def count_leading_whitespace(self, y):
|
||||
line = self.lines[y]
|
||||
m = regex.leading_whitespace.match(line)
|
||||
if m:
|
||||
return m.end()
|
||||
else:
|
||||
# should not happen
|
||||
raise Exception, "iiiijjjj"
|
||||
|
||||
# scratch is a singleton
|
||||
scratch = None
|
||||
class ScratchBuffer(Buffer):
|
||||
btype = 'scratch'
|
||||
def __new__(cls, *args, **kwargs):
|
||||
global scratch
|
||||
if scratch is None:
|
||||
scratch = object.__new__(ScratchBuffer, *args, **kwargs)
|
||||
return scratch
|
||||
def name(self):
|
||||
return "*Scratch*"
|
||||
def close(self):
|
||||
global scratch
|
||||
scratch = None
|
||||
|
||||
class DataBuffer(Buffer):
|
||||
btype = 'data'
|
||||
def __init__(self, name, data, nl='\n'):
|
||||
Buffer.__init__(self, nl)
|
||||
self._name = name
|
||||
self.lines = data.split("\n")
|
||||
def name(self):
|
||||
return self._name
|
||||
def close(self):
|
||||
pass
|
||||
def readonly(self):
|
||||
return True
|
||||
|
||||
# console is another singleton
|
||||
console = None
|
||||
class ConsoleBuffer(Buffer):
|
||||
btype = 'console'
|
||||
def __new__(cls, *args, **kwargs):
|
||||
global console
|
||||
if console is None:
|
||||
b = object.__new__(ConsoleBuffer, *args, **kwargs)
|
||||
console = b
|
||||
return console
|
||||
def __init__(self, nl='\n'):
|
||||
Buffer.__init__(self, nl)
|
||||
self.clear()
|
||||
def clear(self):
|
||||
lines = ['Python Console\n',
|
||||
"Evaluate python expressions in the editor's context (self)\n",
|
||||
'Press Control-] to exit\n',
|
||||
'\n']
|
||||
console.set_data(''.join(lines), force=True)
|
||||
def name(self):
|
||||
return '*Console*'
|
||||
def changed(self):
|
||||
return False
|
||||
def close(self):
|
||||
global console
|
||||
console = None
|
||||
def readonly(self):
|
||||
return True
|
||||
|
||||
class BinaryDataException(Exception):
|
||||
pass
|
||||
|
||||
class FileBuffer(Buffer):
|
||||
btype = 'file'
|
||||
def __init__(self, path, nl='\n', name=None):
|
||||
'''fb = FileBuffer(path)'''
|
||||
Buffer.__init__(self, nl)
|
||||
self.path = os.path.realpath(path)
|
||||
self.checksum = None
|
||||
if name is None:
|
||||
self._name = os.path.basename(self.path)
|
||||
else:
|
||||
self._name = name
|
||||
if os.path.exists(self.path) and not os.access(self.path, os.W_OK):
|
||||
self._readonly = True
|
||||
else:
|
||||
self._readonly = False
|
||||
def readonly(self):
|
||||
return self._readonly
|
||||
|
||||
def _open_file_r(self, path=None):
|
||||
if path is None:
|
||||
path = self.path
|
||||
path = os.path.realpath(path)
|
||||
self.path = path
|
||||
if not os.path.isfile(path):
|
||||
raise Exception, "Path '%s' does not exist" % (path)
|
||||
if not os.access(path, os.R_OK):
|
||||
raise Exception, "Path '%s' cannot be read" % (path)
|
||||
f = open(path, 'r')
|
||||
return f
|
||||
def _open_file_w(self, path=None):
|
||||
if path is None:
|
||||
path = self.path
|
||||
if os.path.isfile(path):
|
||||
raise Exception, "Path '%s' already exists" % (path)
|
||||
d = os.path.dirname(path)
|
||||
if not os.access(d, os.R_OK):
|
||||
raise Exception, "Dir '%s' cannot be read" % (path)
|
||||
if not os.access(d, os.W_OK):
|
||||
raise Exception, "Dir '%s' cannot be written" % (path)
|
||||
f = open(path, 'w')
|
||||
return f
|
||||
def _temp_path(self, path=None):
|
||||
if path is None:
|
||||
path = self.path
|
||||
(dirname, basename) = os.path.split(path)
|
||||
return os.path.join(dirname, ".__%s__pmacs" % (basename))
|
||||
|
||||
# methods for dealing with the underlying resource, etc.
|
||||
def name(self):
|
||||
#return self.path
|
||||
return self._name
|
||||
def path_exists(self):
|
||||
return os.path.exists(self.path)
|
||||
def store_checksum(self, data):
|
||||
self.checksum = md5.new(data)
|
||||
def read(self):
|
||||
if self.path_exists():
|
||||
f = self._open_file_r()
|
||||
data = f.read()
|
||||
f.close()
|
||||
self.store_checksum(data)
|
||||
else:
|
||||
data = ''
|
||||
data = self.read_filter(data)
|
||||
data = data.replace("\t", " ")
|
||||
for i in range(0, min(len(data), 8)):
|
||||
if data[i] not in string.printable:
|
||||
raise BinaryDataException, "binary files are not supported"
|
||||
#FIXME: this is horrible...but maybe not as horrible as using tabs??
|
||||
return data
|
||||
def open(self):
|
||||
data = self.read()
|
||||
self.lines = data.split(self.nl)
|
||||
def reload(self):
|
||||
self.open()
|
||||
def changed_on_disk(self):
|
||||
assert self.checksum is not None
|
||||
f = open(self.path)
|
||||
data = f.read()
|
||||
f.close()
|
||||
m = md5.new(data)
|
||||
return self.checksum.digest() != m.digest()
|
||||
def save(self, force=False):
|
||||
if self.readonly():
|
||||
raise Exception, "can't save a read-only file"
|
||||
|
||||
if self.checksum is not None and force is False:
|
||||
# the file already existed and we took a checksum so make sure it's
|
||||
# still the same right now
|
||||
if not self.path_exists():
|
||||
raise Exception, "oh no! %r disappeared!" % self.path
|
||||
if self.changed_on_disk():
|
||||
raise Exception, "oh no! %r has changed on-disk!" % self.path
|
||||
|
||||
temp_path = self._temp_path()
|
||||
data = self.make_string(nl=self.nl)
|
||||
if self.windows[0].mode.savetabs:
|
||||
data = data.replace(" ", "\t")
|
||||
|
||||
data = self.write_filter(data)
|
||||
|
||||
f2 = self._open_file_w(temp_path)
|
||||
f2.write(data)
|
||||
f2.close()
|
||||
|
||||
if self.path_exists():
|
||||
mode = os.stat(self.path)[0]
|
||||
os.chmod(temp_path, mode)
|
||||
|
||||
shutil.move(temp_path, self.path)
|
||||
self.store_checksum(data)
|
||||
self.modified = False
|
||||
def save_as(self, path):
|
||||
self.path = path
|
||||
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)
|
||||
self.password = password
|
||||
def read_filter(self, data):
|
||||
return aes.decrypt_data(data, self.password)
|
||||
def write_filter(self, data):
|
||||
return aes.encrypt_data(data, self.password)
|
||||
|
||||
class Binary32Buffer(FileBuffer):
|
||||
btype = 'bin32file'
|
||||
wordsize = 4
|
||||
numwords = 4
|
||||
def __init__(self, path, nl='\n', name=None):
|
||||
'''fb = FileBuffer(path)'''
|
||||
FileBuffer.__init__(self, path, nl, name)
|
||||
def read_filter(self, data):
|
||||
lines = []
|
||||
i = 0
|
||||
while i < len(data):
|
||||
j = 0
|
||||
words = []
|
||||
while j < self.numwords * self.wordsize and i + j < len(data):
|
||||
nibbles = []
|
||||
for c in data[i + j:i + j + self.wordsize]:
|
||||
nibbles.append(string.hexdigits[ord(c) / 16])
|
||||
nibbles.append(string.hexdigits[ord(c) % 16])
|
||||
words.append(''.join(nibbles))
|
||||
j += self.wordsize
|
||||
lines.append(' '.join(words))
|
||||
i += self.numwords * self.wordsize
|
||||
return '\n'.join(lines)
|
||||
def write_filter(self, data):
|
||||
bytes = []
|
||||
lastc = None
|
||||
for c in data:
|
||||
if c not in '0123456789abcdefABCDEF':
|
||||
pass
|
||||
elif lastc is None:
|
||||
lastc = c
|
||||
else:
|
||||
bytes.append(chr(int(lastc + c, 16)))
|
||||
lastc = None
|
||||
if lastc is not None:
|
||||
bytes.append(chr(int(lastc + '0', 16)))
|
||||
return ''.join(bytes)
|
||||
|
||||
class Binary64Buffer(Binary32Buffer):
|
||||
wordsize = 8
|
||||
numwords = 2
|
||||
|
||||
class DirBuffer(Buffer):
|
||||
btype = 'dir'
|
||||
def __init__(self, path, nl='\n', name=None):
|
||||
Buffer.__init__(self, nl)
|
||||
self.path = os.path.realpath(path)
|
||||
def changed(self):
|
||||
return False
|
||||
def readonly(self):
|
||||
return True
|
||||
def name(self):
|
||||
return self.path
|
||||
def path_exists(self):
|
||||
return os.path.exists(self.path)
|
||||
|
||||
def _get_names(self):
|
||||
if not self.path_exists():
|
||||
raise Exception, "directory %r does not exists" % self.path
|
||||
names = os.listdir(self.path)
|
||||
if self.path != '/':
|
||||
names.insert(0, '..')
|
||||
names.insert(0, '.')
|
||||
return names
|
||||
def _make_path(self, name):
|
||||
return os.path.join(self.path, name)
|
||||
def _get_lines(self):
|
||||
names = self._get_names()
|
||||
|
||||
fieldlines = []
|
||||
maxlens = [0] * 5
|
||||
for name in names:
|
||||
path = self._make_path(name)
|
||||
fields = dirutil.path_fields(path, name)
|
||||
for i in range(0, 5):
|
||||
try:
|
||||
maxlens[i] = max(maxlens[i], len(fields[i]))
|
||||
except:
|
||||
raise Exception, '%d %r' % (i, fields[i])
|
||||
fieldlines.append(fields)
|
||||
|
||||
fieldlines.sort(cmp=dirutil.path_sort)
|
||||
fmt = '%%%ds %%-%ds %%-%ds %%%ds %%%ds %%s' % tuple(maxlens)
|
||||
|
||||
lines = []
|
||||
for fields in fieldlines:
|
||||
s = fmt % fields
|
||||
lines.append(s)
|
||||
return lines
|
||||
def open(self):
|
||||
self.lines = self._get_lines()
|
||||
def reload(self):
|
||||
lines = self._get_lines()
|
||||
self.set_lines(lines, force=True)
|
||||
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"
|
||||
|
||||
class PathListBuffer(DirBuffer):
|
||||
btype = 'pathlist'
|
||||
def __init__(self, name, paths, nl='\n'):
|
||||
Buffer.__init__(self, nl)
|
||||
self.paths = paths
|
||||
self.path = os.getcwd()
|
||||
self._name = name
|
||||
def path_exists(self):
|
||||
raise Exception
|
||||
def _get_names(self):
|
||||
cwd = os.getcwd()
|
||||
return [x.replace(cwd, '.', 1) for x in self.paths]
|
||||
def _make_path(self, name):
|
||||
if name.startswith('.'):
|
||||
return name.replace('.', os.getcwd(), 1)
|
||||
else:
|
||||
return name
|
||||
def name(self):
|
||||
return self._name
|
|
@ -1,6 +1,6 @@
|
|||
import datetime, grp, md5, os, pwd, re, sets, shutil, stat, string
|
||||
import aes, dirutil, regex, highlight2
|
||||
from point2 import Point
|
||||
from point import Point
|
||||
|
||||
# undo/redo stack constants
|
||||
ACT_NORM = 0
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import datetime, grp, os, pwd, re, stat
|
||||
from point2 import Point
|
||||
from point import Point
|
||||
|
||||
def resolve_token(w, y=None):
|
||||
if y is None:
|
||||
|
|
2
lex3.py
2
lex3.py
|
@ -1,6 +1,6 @@
|
|||
import curses, re
|
||||
import regex, util
|
||||
from point2 import Point
|
||||
from point import Point
|
||||
|
||||
class Token(object):
|
||||
def __init__(self, name, rule, y, x, s, color=None, parent=None, matchd={}, link=None):
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import os, commands, popen2, re, sets
|
||||
import buffer2, default, dirutil, regex, util, window2
|
||||
from point2 import Point
|
||||
import buffer, default, dirutil, regex, util, window2
|
||||
from point import Point
|
||||
|
||||
WHITESPACE = [' ', '\n']
|
||||
|
||||
|
@ -879,7 +879,7 @@ class OpenConsole(Method):
|
|||
def execute(self, w, **vargs):
|
||||
a = w.application
|
||||
if not a.has_buffer_name('*Console*'):
|
||||
a.add_buffer(buffer2.ConsoleBuffer())
|
||||
a.add_buffer(buffer.ConsoleBuffer())
|
||||
b = a.bufferlist.get_buffer_by_name('*Console*')
|
||||
if a.window().buffer is not b:
|
||||
a.switch_buffer(b)
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import buffer2
|
||||
import buffer
|
||||
|
||||
class MiniBufferError(Exception):
|
||||
pass
|
||||
|
||||
# minibuffer is a singleton
|
||||
mini = None
|
||||
class MiniBuffer(buffer2.Buffer):
|
||||
class MiniBuffer(buffer.Buffer):
|
||||
btype = 'mini'
|
||||
def __new__(cls, *args, **kwargs):
|
||||
global mini
|
||||
|
@ -14,7 +14,7 @@ class MiniBuffer(buffer2.Buffer):
|
|||
return mini
|
||||
# the callback function should take one argument (window)
|
||||
def __init__(self, func, method=None, tabber=None, modename=None):
|
||||
buffer2.Buffer.__init__(self)
|
||||
buffer.Buffer.__init__(self)
|
||||
self.callback = func
|
||||
self.method = method
|
||||
self.tabber = tabber
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import color, mode2
|
||||
|
||||
from point2 import Point
|
||||
from point import Point
|
||||
from lex3 import Grammar, PatternRule, RegionRule
|
||||
|
||||
class MetadataGrammar(Grammar):
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import code, string, StringIO, sys, traceback
|
||||
import color, completer, method, mode2
|
||||
from lex3 import Grammar, PatternRule
|
||||
from point2 import Point
|
||||
from point import Point
|
||||
|
||||
class ConsoleMini(mode2.Fundamental):
|
||||
modename = 'ConsoleMini'
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import color, mode2
|
||||
from lex3 import Grammar, PatternRule, NocasePatternRule, RegionRule, NocaseRegionRule
|
||||
from point2 import Point
|
||||
from point import Point
|
||||
|
||||
class StringGrammar(Grammar):
|
||||
rules = [
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import commands, dirutil, grp, method, mode2, os.path, pwd, re
|
||||
import buffer2, window2
|
||||
import buffer, window2
|
||||
from lex3 import Grammar, PatternRule, RegionRule, PatternGroupRule
|
||||
from point2 import Point
|
||||
from point import Point
|
||||
from method import Method, Argument
|
||||
|
||||
class PermGrammar(Grammar):
|
||||
|
@ -94,7 +94,7 @@ class DirGrep(Method):
|
|||
(status, output) = commands.getstatusoutput(cmd)
|
||||
paths = output.split('\n')
|
||||
bufname = '*%s*' % self.name.title()
|
||||
b = buffer2.PathListBuffer(bufname, paths)
|
||||
b = buffer.PathListBuffer(bufname, paths)
|
||||
b.modename = 'dir'
|
||||
b.open()
|
||||
window2.Window(b, w.application, height=0, width=0)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import commands, os.path, sets, string, sys, traceback
|
||||
import color, completer, default, mode2, method, regex, tab2
|
||||
from point2 import Point
|
||||
from point import Point
|
||||
from lex3 import Grammar, PatternRule, RegionRule, OverridePatternRule
|
||||
|
||||
class StringGrammar(Grammar):
|
||||
|
|
|
@ -2,7 +2,7 @@ import string
|
|||
import color, mode2
|
||||
from lex3 import Grammar, PatternRule, RegionRule
|
||||
from method import Method, Argument
|
||||
from point2 import Point
|
||||
from point import Point
|
||||
|
||||
class HexGrammar(Grammar):
|
||||
rules = [
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import color, mode2, tab2
|
||||
from lex3 import Grammar, PatternRule, RegionRule
|
||||
from point2 import Point
|
||||
from point import Point
|
||||
from mode.python import StringGrammar
|
||||
|
||||
class JavascriptGrammar(Grammar):
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import commands, os.path, sets, string, sys, traceback
|
||||
import color, completer, default, mode2, method, regex, tab2
|
||||
from point2 import Point
|
||||
from point import Point
|
||||
from lex3 import Grammar, PatternRule, RegionRule, OverridePatternRule
|
||||
from mode.python import StringGrammar
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import commands, os.path, sets, string, sys, traceback
|
||||
import color, completer, default, mode2, method, regex, tab2
|
||||
from point2 import Point
|
||||
from point import Point
|
||||
from lex3 import Grammar, PatternRule, RegionRule, NocasePatternRule
|
||||
|
||||
class StringGrammar(Grammar):
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import re, sets, string, sys
|
||||
import color, commands, default, method, mode2, regex, tab2
|
||||
from point2 import Point
|
||||
from point import Point
|
||||
from lex3 import Grammar, PatternRule, ContextPatternRule, RegionRule, OverridePatternRule, PatternGroupRule
|
||||
from method import Argument, Method, WrapParagraph
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import commands, os.path, sets, string, sys, traceback
|
||||
import color, completer, default, mode2, method, regex, tab2
|
||||
from point2 import Point
|
||||
from point import Point
|
||||
from lex3 import Grammar, PatternRule, RegionRule, OverridePatternRule
|
||||
|
||||
class StringGrammar(Grammar):
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import re, sets, string
|
||||
|
||||
import color, method, minibuffer, mode2, searchutil
|
||||
from point2 import Point
|
||||
from point import Point
|
||||
|
||||
class Replace(mode2.Fundamental):
|
||||
modename = 'Replace'
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import commands, os.path, sets, string, sys, traceback
|
||||
import color, completer, default, mode2, method, regex, tab2
|
||||
from point2 import Point
|
||||
from point import Point
|
||||
from lex3 import Grammar, PatternRule, RegionRule, OverridePatternRule
|
||||
import mode.lisp
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import re, sets, string
|
||||
|
||||
import color, method, minibuffer, mode2, searchutil
|
||||
from point2 import Point
|
||||
from point import Point
|
||||
|
||||
selected_color = 'magenta'
|
||||
unselected_color = 'yellow'
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import color, method, mode2
|
||||
from point2 import Point
|
||||
from point import Point
|
||||
|
||||
class Which(mode2.Fundamental):
|
||||
modename = 'Which'
|
||||
|
|
2
mode2.py
2
mode2.py
|
@ -1,7 +1,7 @@
|
|||
import os, sets, string
|
||||
import color, method
|
||||
from lex3 import Lexer
|
||||
from point2 import Point
|
||||
from point import Point
|
||||
|
||||
DEBUG = False
|
||||
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
class Point(tuple):
|
||||
'''Represents an (x,y) coordinate'''
|
||||
def __new__(cls, x, y):
|
||||
return tuple.__new__(cls, (y, x))
|
||||
def __getattr__(self, name):
|
||||
if name == "x":
|
||||
return self[1]
|
||||
elif name == 'y':
|
||||
return self[0]
|
||||
else:
|
||||
raise AttributeError
|
||||
def __repr__(self):
|
||||
return '<Point(%d, %d)>' % (self[1], self[0])
|
||||
def __str__(self):
|
||||
return '(%d,%d)' % (self[1], self[0])
|
||||
|
||||
def xy(self):
|
||||
'''Returns a tuple (x,y)'''
|
||||
return (self[1], self[0])
|
||||
def yx(self):
|
||||
'''Returns a tuple (x,y)'''
|
||||
return tuple(self)
|
||||
def add(self, xdelta, ydelta):
|
||||
'''Returns a new point, adding xdelta and ydelta'''
|
||||
return Point(self[1] + xdelta, self[0] + ydelta)
|
||||
def vadd(self, xdelta, ydelta):
|
||||
'''Returns a new point. If ydelta != 0, xdelta is absolute; otherwise, xdelta is relative'''
|
||||
assert xdelta >= 0 and ydelta >= 0, str((xdelta, ydelta))
|
||||
if ydelta != 0:
|
||||
return Point(xdelta, self[0] + ydelta)
|
||||
else:
|
||||
return Point(self[1] + xdelta, self[0])
|
||||
#def sub(self, xdelta, ydelta):
|
||||
# '''Returns a new point, subtracing xdelta and ydelta'''
|
||||
# return Point(self[1] - xdelta, self[0] - ydelta)
|
||||
#def vsub(self, xdelta, ydelta):
|
||||
# '''Returns a new point. If ydelta != 0, xdelta is absolute; otherwise, xdelta is relative'''
|
||||
# assert xdelta >= 0 and ydelta >= 0, str((xdelta, ydelta))
|
||||
# if ydelta != 0:
|
||||
# return Point(self[1], self[0] - ydelta)
|
||||
# else:
|
||||
# return Point(self[1] - xdelta, self[0])
|
|
@ -1,6 +1,6 @@
|
|||
import re
|
||||
import regex
|
||||
from point2 import Point
|
||||
from point import Point
|
||||
|
||||
bg_color = 'black'
|
||||
selected_color = 'magenta'
|
||||
|
|
2
tab2.py
2
tab2.py
|
@ -1,5 +1,5 @@
|
|||
import regex, util
|
||||
from point2 import Point
|
||||
from point import Point
|
||||
|
||||
class Marker:
|
||||
def __init__(self, name, level):
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import os.path, string
|
||||
import highlight2, regex
|
||||
from point2 import Point
|
||||
from point import Point
|
||||
|
||||
WORD_LETTERS = list(string.letters + string.digits)
|
||||
|
||||
|
|
Loading…
Reference in New Issue