lots of clean-up and documentation

--HG--
branch : pmacs2
This commit is contained in:
Erik Osheim 2009-07-23 16:26:59 -04:00
parent cdbc5c0c79
commit f2b4dd3712
6 changed files with 100 additions and 82 deletions

View File

@ -5,31 +5,40 @@ try:
except: except:
has_aes = False has_aes = False
class CrypterInitError(Exception):
pass
class Crypter(object): class Crypter(object):
ALIGNMENT = 16 '''Wraps AES functionality provided by pycrypto'''
def __init__(self, password, salt='aes.py'): def __init__(self, password, salt='aes.py', alignment=16):
'''Initializes a crypter object'''
if not has_aes: if not has_aes:
raise Exception("pycrypto not installed") raise CrypterInitError("pycrypto not installed")
self.password = password self.password = password
self.salt = salt self.salt = salt
self.hash = Crypto.Hash.SHA256.new(password + salt) self.hash = Crypto.Hash.SHA256.new(password + salt)
self.cipher = Crypto.Cipher.AES.new(self.hash.digest()) self.cipher = Crypto.Cipher.AES.new(self.hash.digest())
self.alignment = alignment
def pad(self, s): def pad(self, s):
xtra = len(s) % self.ALIGNMENT '''Add NULL padding to create aligned data'''
xtra = len(s) % self.alignment
if xtra: if xtra:
return s + '\x00' * (self.ALIGNMENT - xtra) return s + '\x00' * (self.alignment - xtra)
else: else:
return s return s
def unpad(self, s): def unpad(self, s):
'''Remove NULL padding to restore original data'''
l = len(s) l = len(s)
while l > 0 and s[l - 1] == '\x00': while l > 0 and s[l - 1] == '\x00':
l -= 1 l -= 1
return s[:l] return s[:l]
def encrypt(self, data): def encrypt(self, data):
'''Creates encrypted data string from original input'''
return self.cipher.encrypt(self.pad(data)) return self.cipher.encrypt(self.pad(data))
def decrypt(self, data): def decrypt(self, data):
'''Creates original data string from encrypted input'''
return self.unpad(self.cipher.decrypt(self.pad(data))) return self.unpad(self.cipher.decrypt(self.pad(data)))

View File

@ -1127,6 +1127,8 @@ if __name__ == "__main__":
help='open arguments in MODE') help='open arguments in MODE')
parser.add_option('-x', '--exec', action='callback', callback=exec_cb, parser.add_option('-x', '--exec', action='callback', callback=exec_cb,
type='string', metavar='CMD', help='run CMD after launching') type='string', metavar='CMD', help='run CMD after launching')
parser.add_option('-T', '--term', dest='term', metavar='TYPE',
help='force pmacs to use TERM=TYPE')
(opts, args) = parser.parse_args(argv) (opts, args) = parser.parse_args(argv)
@ -1134,6 +1136,10 @@ if __name__ == "__main__":
if opts.debug: if opts.debug:
mode.DEBUG = True mode.DEBUG = True
# override $TERM if we need to
if opts.term:
os.putenv('TERM', opts.term)
# if -b but no -m, then use -m hex # if -b but no -m, then use -m hex
if opts.binary and not opts.mode: if opts.binary and not opts.mode:
opts.mode = 'hex' opts.mode = 'hex'

View File

@ -5,31 +5,30 @@ class CacheDict(dict):
constraints on its size. Once that size is reached, the key that was constraints on its size. Once that size is reached, the key that was
inserted or accessed the least recently is removed every time a new key inserted or accessed the least recently is removed every time a new key
is added.""" is added."""
def __init__(self, max_size=1000000): def __init__(self, max_size=10000):
'''CacheDict(max_size=1000000): build a cache''' '''build a cache'''
# once max_size is reached, the oldest cache entry will be # once max_size is reached, the oldest cache entry will be pushed out to
# pushed out to make room for each new one # make room for each new one.
self.max_size = max_size self.max_size = max_size
dict.__init__(self) dict.__init__(self)
# _times_dict will map keys to timestamps # _times_dict will map keys to timestamps.
self._times_dict = {} self._times_dict = {}
# _times_list will store (timestamp, key) pairs in sorted # _times_list will store (timestamp, key) pairs, sorted oldest first.
# order (oldest first)
self._times_list = [] self._times_list = []
def timestamp(self, key): def _timestamp_index(self, key):
'''find the timestamp for key''' '''find the index in the list of timestamps for the given key'''
assert key in self assert key in self
# construct a (timestamp, key) item
item = (self._times_dict[key], key) item = (self._times_dict[key], key)
# look for the item in the (sorted) list # look for the item in the (sorted) list
i = bisect.bisect_left(self._times_list, item) i = bisect.bisect_left(self._times_list, item)
# make sure the index we are returning really is valid # make sure the index we are returning really is valid
if item != self._times_list[i]: if item != self._times_list[i]:
raise LookupError raise LookupError("key %r was not found" % key)
return i return i
def __getitem__(self, key): def __getitem__(self, key):
'''implements d[key]'''
# find the value in the dict # find the value in the dict
value = dict.__getitem__(self, key) value = dict.__getitem__(self, key)
# do this to update the timestamp on this key # do this to update the timestamp on this key
@ -37,9 +36,10 @@ class CacheDict(dict):
return value return value
def __setitem__(self, key, value): def __setitem__(self, key, value):
'''implements d[key] = value'''
# delete any old instance of the key to make way for the new # delete any old instance of the key to make way for the new
if key in self: if key in self:
del self._times_list[self.timestamp(key)] del self._times_list[self._timestamp_index(key)]
# remove old keys until we have enough space to add this one # remove old keys until we have enough space to add this one
while len(self._times_list) >= self.max_size: while len(self._times_list) >= self.max_size:
key = self._times_list[0][1] key = self._times_list[0][1]
@ -53,8 +53,9 @@ class CacheDict(dict):
bisect.insort_left(self._times_list, (t, key)) bisect.insort_left(self._times_list, (t, key))
def __delitem__(self, key): def __delitem__(self, key):
# we need to make sure we delete this key out of all three of '''implements del d[key]'''
# our data structures # we need to make sure we delete this key out of all three of our data
del self._times_list[self.timestamp(key)] # structures
del self._times_list[self._timestamp_index(key)]
del self._times_dict[key] del self._times_dict[key]
dict.__delitem__(self, key) dict.__delitem__(self, key)

View File

@ -13,7 +13,7 @@ attributes = {
'standout': curses.A_STANDOUT, 'standout': curses.A_STANDOUT,
} }
inited = False inited = False
default_color = True default_color = True
ascii_map = { ascii_map = {
@ -23,11 +23,14 @@ rev_ascii_map = {
'bold': '*', 'bold': '*',
} }
# add a particular color
def add_color(name, value, abbrev): def add_color(name, value, abbrev):
colors[name] = value colors[name] = value
ascii_map[abbrev] = name ascii_map[abbrev] = name
rev_ascii_map[name] = abbrev rev_ascii_map[name] = abbrev
# assign every RGB triple (0-5) to one of six basic colors (red, yellow, green,
# cyan, blue, magenta) based on some semi-arbitrary rules i came up with.
def iter256(): def iter256():
for r in range(0, 6): for r in range(0, 6):
for g in range(0, 6): for g in range(0, 6):
@ -50,26 +53,25 @@ def iter256():
yield (name, r, g, b) yield (name, r, g, b)
raise StopIteration raise StopIteration
# if we can support 256 colors, create all of the color names and map them to
# the correct RGB value.
def color256(name, fallback, abbrev, r, g, b): def color256(name, fallback, abbrev, r, g, b):
name2 = '%s%d%d%d' % (name, r, g, b) name2 = '%s%d%d%d' % (name, r, g, b)
abbrev2 = '%s%d%d%d' % (abbrev, r, g, b) abbrev2 = '%s%d%d%d' % (abbrev, r, g, b)
if curses.COLORS == 256: if curses.COLORS == 256:
value = 16 + r * 36 + g * 6 + b value = 16 + r * 36 + g * 6 + b
if curses.can_change_color(): if curses.can_change_color():
try: curses.init_color(value, r * 200, g * 200, b* 200)
curses.init_color(value, r * 200, g * 200, b* 200)
except:
raise Exception("arghh: %d, %d, %d, %d", value, r * 200, g * 200, b * 200)
else: else:
value = fallback value = fallback
add_color(name2, value, abbrev2) add_color(name2, value, abbrev2)
# PUBLIC METHODS
def init(): def init():
global _pairs, inited global _pairs, inited
if inited: if inited: return
return inited = True
# create the basic 8 colors of curses
add_color('cyan', curses.COLOR_CYAN, 'c') add_color('cyan', curses.COLOR_CYAN, 'c')
add_color('blue', curses.COLOR_BLUE, 'b') add_color('blue', curses.COLOR_BLUE, 'b')
add_color('green', curses.COLOR_GREEN, 'g') add_color('green', curses.COLOR_GREEN, 'g')
@ -79,33 +81,31 @@ def init():
add_color('black', curses.COLOR_BLACK, 'B') add_color('black', curses.COLOR_BLACK, 'B')
add_color('white', curses.COLOR_WHITE, 'w') add_color('white', curses.COLOR_WHITE, 'w')
# initialize the "default" color if possible
if default_color: if default_color:
colors['default'] = -1 colors['default'] = -1
ascii_map['d'] = 'default' ascii_map['d'] = 'default'
rev_ascii_map['default'] = 'd' rev_ascii_map['default'] = 'd'
inited = True # add in hex aliases to 256 colors; used by color-data buffers
for i in range(0, 256): for i in range(0, 256):
name = 'f%02x' % i name = 'f%02x' % i
abbrev = 'f%02x' % i abbrev = 'f%02x' % i
add_color(name, i, abbrev) add_color(name, i, abbrev)
# GREY # create the 24 flavors of grey in 256 colors
for i in range(0, 24): for i in range(0, 24):
name2 = 'grey%d' % i name2 = 'grey%d' % i
abbrev2 = 'G%d' % i abbrev2 = 'G%d' % i
if curses.COLORS == 256: if curses.COLORS == 256:
value = 232 + i value = 232 + i
if curses.can_change_color(): if curses.can_change_color():
try: curses.init_color(value, i * 41, i * 41, i * 41)
curses.init_color(value, i * 41, i * 41, i * 41)
except:
raise Exception("arghh: %d, %d, %d, %d", value, i * 41, i * 41, i * 41)
else: else:
value = curses.COLOR_WHITE value = curses.COLOR_WHITE
add_color(name2, value, abbrev2) add_color(name2, value, abbrev2)
# create 256 colors
for name, r, g, b in iter256(): for name, r, g, b in iter256():
color256(name, colors[name], rev_ascii_map[name], r, g, b) color256(name, colors[name], rev_ascii_map[name], r, g, b)
@ -117,9 +117,6 @@ def build(fg, bg, *attr):
v = v | x v = v | x
return v return v
return build_attr(cattr, *attr)
# PRIVATE METHODS
def pairs(fg, bg): def pairs(fg, bg):
if not curses.has_colors(): if not curses.has_colors():
return curses.color_pair(0) return curses.color_pair(0)

View File

@ -17,30 +17,32 @@ class LilyGrammar(Grammar):
RegionRule(r'comment', r'%\{', CommentGrammar, r'%\}'), RegionRule(r'comment', r'%\{', CommentGrammar, r'%\}'),
RegionRule(r'string', r'#?"', StringGrammar2, r'"'), RegionRule(r'string', r'#?"', StringGrammar2, r'"'),
PatternRule(r'boolean', r'#?#[tf]'), PatternRule(r'boolean', r'#?#[tf]'),
PatternMatchRule(r'x', r'(\\new)( +)([a-zA-Z_]+)', r'directive', r'spaces', r'lily_class'), PatternMatchRule(r'x', r'(\\new)( +)([a-zA-Z_]+)', r'lily.directive',
PatternMatchRule(r'x', r'(\\set|\\override)( +)([a-zA-Z_]+)', r'directive', r'spaces', r'lily_var'), r'spaces', r'lily.class'),
PatternRule(r'tie', r'~'), PatternMatchRule(r'x', r'(\\set|\\override)( +)([a-zA-Z_]+)',
PatternRule(r'augmentation', r'\.+'), r'lily.directive', r'spaces', r'lily.var'),
PatternRule(r'directive', r'\\[a-zA-Z_][a-zA-Z_0-9]*'), PatternRule(r'lily.tie', r'~'),
PatternRule(r'lily.augmentation', r'\.+'),
PatternRule(r'lily.directive', r'\\[a-zA-Z_][a-zA-Z_0-9]*'),
PatternRule(r'delimiter', r'(?:[={}]|<<|>>)'), PatternRule(r'delimiter', r'(?:[={}]|<<|>>)'),
RegionRule(r'text', r'^"', StringGrammar2, r'"'), RegionRule(r'lily.text', r'^"', StringGrammar2, r'"'),
RegionRule(r'markup', r'(?<=\\markup) *{', MarkupGrammar, '}'), RegionRule(r'lily.markup', r'(?<=\\markup) *{', MarkupGrammar, '}'),
PatternRule(r'huh', r'\\!'), PatternRule(r'lily.huh', r'\\!'),
PatternRule(r'spaces', ' +'), PatternRule(r'spaces', ' +'),
PatternRule(r'eol', '\n'), PatternRule(r'eol', '\n'),
PatternRule(r'chord', r'[<>]'), PatternRule(r'lily.chord', r'[<>]'),
PatternRule(r'beam', r'[\[\]]'), PatternRule(r'lily.beam', r'[\[\]]'),
PatternRule(r'slur', r'[()]'), PatternRule(r'lily.slur', r'[()]'),
PatternRule(r'pslur', r'\\[()]'), PatternRule(r'lily.pslur', r'\\[()]'),
PatternRule(r'articulation', r'[-_+][-.>^+_]'), PatternRule(r'lily.articulation', r'[-_+][-.>^+_]'),
PatternRule(r'fingering', r'[-_+][0-9]+'), PatternRule(r'lily.fingering', r'[-_+][0-9]+'),
PatternRule(r'time', r'[0-9]+/[0-9]+'), PatternRule(r'lily.time', r'[0-9]+/[0-9]+'),
PatternRule(r'note', r"[a-g][sf]?[,']*[0-9]*(?![a-z-])"), PatternRule(r'lily.note', r"[a-g][sf]?[,']*[0-9]*(?![a-z-])"),
PatternRule(r'rest', r"r[0-9]*(?![a-z-])"), PatternRule(r'lily.rest', r"r[0-9]*(?![a-z-])"),
PatternRule(r'srest', r"s[0-9]*(?![a-z-])"), PatternRule(r'lily.srest', r"s[0-9]*(?![a-z-])"),
PatternRule(r'measure', r'(?:[0-9]+\.)?[0-9]+\\(?:mm|cm|in)'), PatternRule(r'lily.measure', r'(?:[0-9]+\.)?[0-9]+\\(?:mm|cm|in)'),
RegionRule(r'scheme', r'#\(', SchemeGrammar, '\)'), RegionRule(r'lily.scheme', r'#\(', SchemeGrammar, '\)'),
PatternRule(r'bareword', r'[a-zA-Z][a-zA-Z_0-9-]*[a-zA-Z0-9]'), PatternRule(r'lily.bareword', r'[a-zA-Z][a-zA-Z_0-9-]*[a-zA-Z0-9]'),
] ]
class LilyTabber(tab.StackTabber): class LilyTabber(tab.StackTabber):
@ -57,25 +59,25 @@ class Lily(mode.Fundamental):
grammar = LilyGrammar grammar = LilyGrammar
commentc = '%' commentc = '%'
colors = { colors = {
'boolean': ('magenta', 'default', 'bold'), 'lily.boolean': ('magenta', 'default', 'bold'),
'lily_class': ('magenta', 'default', 'bold'), 'lily.class': ('magenta', 'default', 'bold'),
'lily_var': ('cyan', 'default', 'bold'), 'lily.var': ('cyan', 'default', 'bold'),
'directive': ('blue', 'default', 'bold'), 'lily.directive': ('blue', 'default', 'bold'),
'markup.start': ('cyan', 'default'), 'lily.markup.start': ('cyan', 'default'),
'markup.data': ('cyan', 'default'), 'lily.markup.data': ('cyan', 'default'),
'markup.end': ('cyan', 'default'), 'lily.markup.end': ('cyan', 'default'),
'time': ('yellow', 'default'), 'lily.time': ('yellow', 'default'),
'note': ('yellow', 'default', 'bold'), 'lily.note': ('yellow', 'default', 'bold'),
'rest': ('yellow', 'default'), 'lily.rest': ('yellow', 'default'),
'srest': ('yellow', 'default'), 'lily.srest': ('yellow', 'default'),
'scheme.start': ('magenta', 'default'), 'lily.scheme.start': ('magenta', 'default'),
'scheme.end': ('magenta', 'default'), 'lily.scheme.end': ('magenta', 'default'),
'measure': ('green', 'default'), 'lily.measure': ('green', 'default'),
'beam': ('red', 'default'), 'lily.beam': ('red', 'default'),
'slur': ('red', 'default'), 'lily.slur': ('red', 'default'),
'plur': ('red', 'default'), 'lily.plur': ('red', 'default'),
'tie': ('red', 'default'), 'lily.tie': ('red', 'default'),
'huh': ('red', 'default'), 'lily.huh': ('red', 'default'),
} }
opentokens = ('delimiter',) opentokens = ('delimiter',)
opentags = {'<<': '>>', '{': '}'} opentags = {'<<': '>>', '{': '}'}

View File

@ -3,6 +3,8 @@ import pwd
import re import re
import regex import regex
# character buffers use sequences like [r:d]foo[d:d] to indicate that foo
# should be fg=red,bg=default. as such, we have to escape \, [ and ].
cbuf_re = re.compile(r'[\[\]\\]') cbuf_re = re.compile(r'[\[\]\\]')
def cbuf_escape(s): def cbuf_escape(s):
'''escape characters which have special meaning in color buffers''' '''escape characters which have special meaning in color buffers'''
@ -68,6 +70,7 @@ def count_leading_whitespace(s):
assert m, "count leading whitespace failed somehow" assert m, "count leading whitespace failed somehow"
return m.end() - m.start() return m.end() - m.start()
# TODO: move these somewhere more sensible. they aren't really utilities.
def get_margin_limit(w, def_limit=80): def get_margin_limit(w, def_limit=80):
lname = '%s.margin' % w.mode.name.lower() lname = '%s.margin' % w.mode.name.lower()
if lname in w.application.config: if lname in w.application.config: