parent
e1ad655912
commit
638f10174a
|
@ -2,9 +2,9 @@
|
||||||
import curses, curses.ascii, getpass, os, re, string, sets, sys, termios, time
|
import curses, curses.ascii, getpass, os, re, string, sets, sys, termios, time
|
||||||
import traceback
|
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
|
import util, window2
|
||||||
from point2 import Point
|
from point import Point
|
||||||
|
|
||||||
def run(buffers, jump_to_line=None, init_mode=None):
|
def run(buffers, jump_to_line=None, init_mode=None):
|
||||||
# save terminal state so we can restore it when the program exits
|
# save terminal state so we can restore it when the program exits
|
||||||
|
@ -113,10 +113,10 @@ class Application(object):
|
||||||
|
|
||||||
# initialize our buffers
|
# initialize our buffers
|
||||||
# note that the first buffer in buffers will be initially visible
|
# note that the first buffer in buffers will be initially visible
|
||||||
buffers.append(buffer2.ScratchBuffer())
|
buffers.append(buffer.ScratchBuffer())
|
||||||
buffers.append(buffer2.ConsoleBuffer())
|
buffers.append(buffer.ConsoleBuffer())
|
||||||
if self.rcerror:
|
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.bufferlist = bufferlist.BufferList(height, width)
|
||||||
self.active_slot = 0
|
self.active_slot = 0
|
||||||
|
@ -223,11 +223,11 @@ class Application(object):
|
||||||
if cipher is None:
|
if cipher is None:
|
||||||
if not os.path.exists(path) or os.path.isfile(path):
|
if not os.path.exists(path) or os.path.isfile(path):
|
||||||
if binary:
|
if binary:
|
||||||
b = buffer2.Binary32Buffer(path, name=name)
|
b = buffer.Binary32Buffer(path, name=name)
|
||||||
else:
|
else:
|
||||||
b = buffer2.FileBuffer(path, name=name)
|
b = buffer.FileBuffer(path, name=name)
|
||||||
elif os.path.isdir(path):
|
elif os.path.isdir(path):
|
||||||
b = buffer2.DirBuffer(path, name=name)
|
b = buffer.DirBuffer(path, name=name)
|
||||||
mode_name = 'dir'
|
mode_name = 'dir'
|
||||||
else:
|
else:
|
||||||
raise Exception, "not a file or dir: %r" % path
|
raise Exception, "not a file or dir: %r" % path
|
||||||
|
@ -235,7 +235,7 @@ class Application(object):
|
||||||
if not password:
|
if not password:
|
||||||
raise Exception, "password is required"
|
raise Exception, "password is required"
|
||||||
if not os.path.exists(path) or os.path.isfile(path):
|
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:
|
else:
|
||||||
raise Exception, "not a file or dir: %r" % path
|
raise Exception, "not a file or dir: %r" % path
|
||||||
b.open()
|
b.open()
|
||||||
|
@ -297,7 +297,7 @@ class Application(object):
|
||||||
f = open(path, 'w')
|
f = open(path, 'w')
|
||||||
f.write(data)
|
f.write(data)
|
||||||
f.close()
|
f.close()
|
||||||
b = buffer2.FileBuffer(path)
|
b = buffer.FileBuffer(path)
|
||||||
b.open()
|
b.open()
|
||||||
window2.Window(b, self, height=0, width=0)
|
window2.Window(b, self, height=0, width=0)
|
||||||
self.add_buffer(b)
|
self.add_buffer(b)
|
||||||
|
@ -307,7 +307,7 @@ class Application(object):
|
||||||
if self.has_buffer_name(name):
|
if self.has_buffer_name(name):
|
||||||
b = self.bufferlist.buffer_names[name]
|
b = self.bufferlist.buffer_names[name]
|
||||||
self.remove_buffer(b)
|
self.remove_buffer(b)
|
||||||
b = buffer2.DataBuffer(name, data)
|
b = buffer.DataBuffer(name, data)
|
||||||
if modename is not None:
|
if modename is not None:
|
||||||
b.modename = modename
|
b.modename = modename
|
||||||
window2.Window(b, self, height=0, width=0)
|
window2.Window(b, self, height=0, width=0)
|
||||||
|
@ -742,17 +742,17 @@ class Application(object):
|
||||||
def open_aes_file(path, nl, name=None):
|
def open_aes_file(path, nl, name=None):
|
||||||
if os.path.isfile(path) or not os.path.exists(path):
|
if os.path.isfile(path) or not os.path.exists(path):
|
||||||
p = getpass.getpass("Please enter the AES password: ")
|
p = getpass.getpass("Please enter the AES password: ")
|
||||||
return buffer2.AesBuffer(path, p, nl, name)
|
return buffer.AesBuffer(path, p, nl, name)
|
||||||
else:
|
else:
|
||||||
raise Exception, "can't open %r; unsupported file type" % path
|
raise Exception, "can't open %r; unsupported file type" % path
|
||||||
def open_plain_file(path, nl, name=None, binary=False):
|
def open_plain_file(path, nl, name=None, binary=False):
|
||||||
if os.path.isfile(path) or not os.path.exists(path):
|
if os.path.isfile(path) or not os.path.exists(path):
|
||||||
if binary:
|
if binary:
|
||||||
return buffer2.Binary32Buffer(path, nl, name)
|
return buffer.Binary32Buffer(path, nl, name)
|
||||||
else:
|
else:
|
||||||
return buffer2.FileBuffer(path, nl, name)
|
return buffer.FileBuffer(path, nl, name)
|
||||||
elif os.path.isdir(path):
|
elif os.path.isdir(path):
|
||||||
return buffer2.DirBuffer(path, nl, name)
|
return buffer.DirBuffer(path, nl, name)
|
||||||
else:
|
else:
|
||||||
raise Exception, "can't open %r; unsupported file type" % path
|
raise Exception, "can't open %r; unsupported file type" % path
|
||||||
|
|
||||||
|
@ -832,7 +832,7 @@ if __name__ == "__main__":
|
||||||
try:
|
try:
|
||||||
b = f(path, nl, name, opts.binary)
|
b = f(path, nl, name, opts.binary)
|
||||||
b.open()
|
b.open()
|
||||||
except buffer2.BinaryDataException, e:
|
except buffer.BinaryDataException, e:
|
||||||
b = f(path, nl, name, True)
|
b = f(path, nl, name, True)
|
||||||
b.open()
|
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 datetime, grp, md5, os, pwd, re, sets, shutil, stat, string
|
||||||
import aes, dirutil, regex, highlight2
|
import aes, dirutil, regex, highlight2
|
||||||
from point2 import Point
|
from point import Point
|
||||||
|
|
||||||
# undo/redo stack constants
|
# undo/redo stack constants
|
||||||
ACT_NORM = 0
|
ACT_NORM = 0
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import datetime, grp, os, pwd, re, stat
|
import datetime, grp, os, pwd, re, stat
|
||||||
from point2 import Point
|
from point import Point
|
||||||
|
|
||||||
def resolve_token(w, y=None):
|
def resolve_token(w, y=None):
|
||||||
if y is None:
|
if y is None:
|
||||||
|
|
2
lex3.py
2
lex3.py
|
@ -1,6 +1,6 @@
|
||||||
import curses, re
|
import curses, re
|
||||||
import regex, util
|
import regex, util
|
||||||
from point2 import Point
|
from point import Point
|
||||||
|
|
||||||
class Token(object):
|
class Token(object):
|
||||||
def __init__(self, name, rule, y, x, s, color=None, parent=None, matchd={}, link=None):
|
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 os, commands, popen2, re, sets
|
||||||
import buffer2, default, dirutil, regex, util, window2
|
import buffer, default, dirutil, regex, util, window2
|
||||||
from point2 import Point
|
from point import Point
|
||||||
|
|
||||||
WHITESPACE = [' ', '\n']
|
WHITESPACE = [' ', '\n']
|
||||||
|
|
||||||
|
@ -879,7 +879,7 @@ class OpenConsole(Method):
|
||||||
def execute(self, w, **vargs):
|
def execute(self, w, **vargs):
|
||||||
a = w.application
|
a = w.application
|
||||||
if not a.has_buffer_name('*Console*'):
|
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*')
|
b = a.bufferlist.get_buffer_by_name('*Console*')
|
||||||
if a.window().buffer is not b:
|
if a.window().buffer is not b:
|
||||||
a.switch_buffer(b)
|
a.switch_buffer(b)
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import buffer2
|
import buffer
|
||||||
|
|
||||||
class MiniBufferError(Exception):
|
class MiniBufferError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# minibuffer is a singleton
|
# minibuffer is a singleton
|
||||||
mini = None
|
mini = None
|
||||||
class MiniBuffer(buffer2.Buffer):
|
class MiniBuffer(buffer.Buffer):
|
||||||
btype = 'mini'
|
btype = 'mini'
|
||||||
def __new__(cls, *args, **kwargs):
|
def __new__(cls, *args, **kwargs):
|
||||||
global mini
|
global mini
|
||||||
|
@ -14,7 +14,7 @@ class MiniBuffer(buffer2.Buffer):
|
||||||
return mini
|
return mini
|
||||||
# the callback function should take one argument (window)
|
# the callback function should take one argument (window)
|
||||||
def __init__(self, func, method=None, tabber=None, modename=None):
|
def __init__(self, func, method=None, tabber=None, modename=None):
|
||||||
buffer2.Buffer.__init__(self)
|
buffer.Buffer.__init__(self)
|
||||||
self.callback = func
|
self.callback = func
|
||||||
self.method = method
|
self.method = method
|
||||||
self.tabber = tabber
|
self.tabber = tabber
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import color, mode2
|
import color, mode2
|
||||||
|
|
||||||
from point2 import Point
|
from point import Point
|
||||||
from lex3 import Grammar, PatternRule, RegionRule
|
from lex3 import Grammar, PatternRule, RegionRule
|
||||||
|
|
||||||
class MetadataGrammar(Grammar):
|
class MetadataGrammar(Grammar):
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import code, string, StringIO, sys, traceback
|
import code, string, StringIO, sys, traceback
|
||||||
import color, completer, method, mode2
|
import color, completer, method, mode2
|
||||||
from lex3 import Grammar, PatternRule
|
from lex3 import Grammar, PatternRule
|
||||||
from point2 import Point
|
from point import Point
|
||||||
|
|
||||||
class ConsoleMini(mode2.Fundamental):
|
class ConsoleMini(mode2.Fundamental):
|
||||||
modename = 'ConsoleMini'
|
modename = 'ConsoleMini'
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import color, mode2
|
import color, mode2
|
||||||
from lex3 import Grammar, PatternRule, NocasePatternRule, RegionRule, NocaseRegionRule
|
from lex3 import Grammar, PatternRule, NocasePatternRule, RegionRule, NocaseRegionRule
|
||||||
from point2 import Point
|
from point import Point
|
||||||
|
|
||||||
class StringGrammar(Grammar):
|
class StringGrammar(Grammar):
|
||||||
rules = [
|
rules = [
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import commands, dirutil, grp, method, mode2, os.path, pwd, re
|
import commands, dirutil, grp, method, mode2, os.path, pwd, re
|
||||||
import buffer2, window2
|
import buffer, window2
|
||||||
from lex3 import Grammar, PatternRule, RegionRule, PatternGroupRule
|
from lex3 import Grammar, PatternRule, RegionRule, PatternGroupRule
|
||||||
from point2 import Point
|
from point import Point
|
||||||
from method import Method, Argument
|
from method import Method, Argument
|
||||||
|
|
||||||
class PermGrammar(Grammar):
|
class PermGrammar(Grammar):
|
||||||
|
@ -94,7 +94,7 @@ class DirGrep(Method):
|
||||||
(status, output) = commands.getstatusoutput(cmd)
|
(status, output) = commands.getstatusoutput(cmd)
|
||||||
paths = output.split('\n')
|
paths = output.split('\n')
|
||||||
bufname = '*%s*' % self.name.title()
|
bufname = '*%s*' % self.name.title()
|
||||||
b = buffer2.PathListBuffer(bufname, paths)
|
b = buffer.PathListBuffer(bufname, paths)
|
||||||
b.modename = 'dir'
|
b.modename = 'dir'
|
||||||
b.open()
|
b.open()
|
||||||
window2.Window(b, w.application, height=0, width=0)
|
window2.Window(b, w.application, height=0, width=0)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import commands, os.path, sets, string, sys, traceback
|
import commands, os.path, sets, string, sys, traceback
|
||||||
import color, completer, default, mode2, method, regex, tab2
|
import color, completer, default, mode2, method, regex, tab2
|
||||||
from point2 import Point
|
from point import Point
|
||||||
from lex3 import Grammar, PatternRule, RegionRule, OverridePatternRule
|
from lex3 import Grammar, PatternRule, RegionRule, OverridePatternRule
|
||||||
|
|
||||||
class StringGrammar(Grammar):
|
class StringGrammar(Grammar):
|
||||||
|
|
|
@ -2,7 +2,7 @@ import string
|
||||||
import color, mode2
|
import color, mode2
|
||||||
from lex3 import Grammar, PatternRule, RegionRule
|
from lex3 import Grammar, PatternRule, RegionRule
|
||||||
from method import Method, Argument
|
from method import Method, Argument
|
||||||
from point2 import Point
|
from point import Point
|
||||||
|
|
||||||
class HexGrammar(Grammar):
|
class HexGrammar(Grammar):
|
||||||
rules = [
|
rules = [
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import color, mode2, tab2
|
import color, mode2, tab2
|
||||||
from lex3 import Grammar, PatternRule, RegionRule
|
from lex3 import Grammar, PatternRule, RegionRule
|
||||||
from point2 import Point
|
from point import Point
|
||||||
from mode.python import StringGrammar
|
from mode.python import StringGrammar
|
||||||
|
|
||||||
class JavascriptGrammar(Grammar):
|
class JavascriptGrammar(Grammar):
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import commands, os.path, sets, string, sys, traceback
|
import commands, os.path, sets, string, sys, traceback
|
||||||
import color, completer, default, mode2, method, regex, tab2
|
import color, completer, default, mode2, method, regex, tab2
|
||||||
from point2 import Point
|
from point import Point
|
||||||
from lex3 import Grammar, PatternRule, RegionRule, OverridePatternRule
|
from lex3 import Grammar, PatternRule, RegionRule, OverridePatternRule
|
||||||
from mode.python import StringGrammar
|
from mode.python import StringGrammar
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import commands, os.path, sets, string, sys, traceback
|
import commands, os.path, sets, string, sys, traceback
|
||||||
import color, completer, default, mode2, method, regex, tab2
|
import color, completer, default, mode2, method, regex, tab2
|
||||||
from point2 import Point
|
from point import Point
|
||||||
from lex3 import Grammar, PatternRule, RegionRule, NocasePatternRule
|
from lex3 import Grammar, PatternRule, RegionRule, NocasePatternRule
|
||||||
|
|
||||||
class StringGrammar(Grammar):
|
class StringGrammar(Grammar):
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import re, sets, string, sys
|
import re, sets, string, sys
|
||||||
import color, commands, default, method, mode2, regex, tab2
|
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 lex3 import Grammar, PatternRule, ContextPatternRule, RegionRule, OverridePatternRule, PatternGroupRule
|
||||||
from method import Argument, Method, WrapParagraph
|
from method import Argument, Method, WrapParagraph
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import commands, os.path, sets, string, sys, traceback
|
import commands, os.path, sets, string, sys, traceback
|
||||||
import color, completer, default, mode2, method, regex, tab2
|
import color, completer, default, mode2, method, regex, tab2
|
||||||
from point2 import Point
|
from point import Point
|
||||||
from lex3 import Grammar, PatternRule, RegionRule, OverridePatternRule
|
from lex3 import Grammar, PatternRule, RegionRule, OverridePatternRule
|
||||||
|
|
||||||
class StringGrammar(Grammar):
|
class StringGrammar(Grammar):
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import re, sets, string
|
import re, sets, string
|
||||||
|
|
||||||
import color, method, minibuffer, mode2, searchutil
|
import color, method, minibuffer, mode2, searchutil
|
||||||
from point2 import Point
|
from point import Point
|
||||||
|
|
||||||
class Replace(mode2.Fundamental):
|
class Replace(mode2.Fundamental):
|
||||||
modename = 'Replace'
|
modename = 'Replace'
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import commands, os.path, sets, string, sys, traceback
|
import commands, os.path, sets, string, sys, traceback
|
||||||
import color, completer, default, mode2, method, regex, tab2
|
import color, completer, default, mode2, method, regex, tab2
|
||||||
from point2 import Point
|
from point import Point
|
||||||
from lex3 import Grammar, PatternRule, RegionRule, OverridePatternRule
|
from lex3 import Grammar, PatternRule, RegionRule, OverridePatternRule
|
||||||
import mode.lisp
|
import mode.lisp
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import re, sets, string
|
import re, sets, string
|
||||||
|
|
||||||
import color, method, minibuffer, mode2, searchutil
|
import color, method, minibuffer, mode2, searchutil
|
||||||
from point2 import Point
|
from point import Point
|
||||||
|
|
||||||
selected_color = 'magenta'
|
selected_color = 'magenta'
|
||||||
unselected_color = 'yellow'
|
unselected_color = 'yellow'
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import color, method, mode2
|
import color, method, mode2
|
||||||
from point2 import Point
|
from point import Point
|
||||||
|
|
||||||
class Which(mode2.Fundamental):
|
class Which(mode2.Fundamental):
|
||||||
modename = 'Which'
|
modename = 'Which'
|
||||||
|
|
2
mode2.py
2
mode2.py
|
@ -1,7 +1,7 @@
|
||||||
import os, sets, string
|
import os, sets, string
|
||||||
import color, method
|
import color, method
|
||||||
from lex3 import Lexer
|
from lex3 import Lexer
|
||||||
from point2 import Point
|
from point import Point
|
||||||
|
|
||||||
DEBUG = False
|
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 re
|
||||||
import regex
|
import regex
|
||||||
from point2 import Point
|
from point import Point
|
||||||
|
|
||||||
bg_color = 'black'
|
bg_color = 'black'
|
||||||
selected_color = 'magenta'
|
selected_color = 'magenta'
|
||||||
|
|
2
tab2.py
2
tab2.py
|
@ -1,5 +1,5 @@
|
||||||
import regex, util
|
import regex, util
|
||||||
from point2 import Point
|
from point import Point
|
||||||
|
|
||||||
class Marker:
|
class Marker:
|
||||||
def __init__(self, name, level):
|
def __init__(self, name, level):
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import os.path, string
|
import os.path, string
|
||||||
import highlight2, regex
|
import highlight2, regex
|
||||||
from point2 import Point
|
from point import Point
|
||||||
|
|
||||||
WORD_LETTERS = list(string.letters + string.digits)
|
WORD_LETTERS = list(string.letters + string.digits)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue