pmacs3/mode.py

233 lines
9.4 KiB
Python
Raw Normal View History

2007-03-06 10:05:38 -05:00
import os
import sets, string
import color, default, highlight, method, point
DEBUG = False
#DEBUG = True
class Handler:
def __init__(self):
self.prefixes = sets.Set(["C-x", "C-c", "C-u"])
self.last_sequence = ''
self.curr_tokens = []
self.bindings = {}
# handle adding and removing actions
def add_action(self, action):
if action.name in self.window.application.methods:
return
assert action.name not in self.window.application.methods, \
"Action %r already found" % action.name
self.window.application.methods[action.name] = action
def del_action(self, name):
#del self.window.application.methods[name]
for binding in self.bindings.keys():
if self.bindings[binding] == name:
del self.bindings[binding]
def add_binding(self, name, sequence):
#assert name in self.actions, "No action called %r found" % name
assert name in self.window.application.methods, \
"No action called %r found" % name
self.bindings[sequence] = name
def add_bindings(self, name, sequences):
for sequence in sequences:
self.add_binding(name, sequence)
def del_binding(self, sequence):
del self.bindings[sequence]
def add_action_and_bindings(self, action, sequences):
self.add_action(action)
for sequence in sequences:
self.add_binding(action.name, sequence)
def handle_token(self, t):
'''self.handle_token(token): returns None, or the action to
take. raises an exception on unknown input'''
self.curr_tokens.append(t)
sequence = " ".join(self.curr_tokens)
if sequence in self.bindings:
name = self.bindings[sequence]
#act = self.actions[name]
act = self.window.application.methods[name]
self.curr_tokens = []
self.last_sequence = sequence
return act
elif t in self.prefixes:
for binding in self.bindings:
if binding.startswith(sequence):
return None
self.curr_tokens = []
self.last_sequence = sequence
raise Exception, "no action defined for %r" % (sequence)
class Fundamental(Handler):
'''This is the default mode'''
def __init__(self, w):
self.window = w
Handler.__init__(self)
#self.actions = {}
self.bindings = {}
self.add_bindings('start-of-line', ('C-a', 'HOME',))
self.add_bindings('end-of-line', ('C-e', 'END',))
self.add_bindings('backward', ('C-b', 'L_ARROW',))
self.add_bindings('forward', ('C-f', 'R_ARROW',))
self.add_bindings('center-view', ('C-l',))
self.add_bindings('next-line', ('C-n', 'D_ARROW',))
self.add_bindings('previous-line', ('C-p', 'U_ARROW',))
self.add_bindings('next-section', ('M-n', 'M-D_ARROW',))
self.add_bindings('previous-section', ('M-p', 'M-U_ARROW',))
self.add_bindings('page-down', ('C-v', 'PG_DN',))
self.add_bindings('page-up', ('M-v', 'PG_UP',))
self.add_bindings('goto-beginning', ('M-<',))
self.add_bindings('goto-end', ('M->',))
self.add_bindings('delete-left', ('DELETE', 'BACKSPACE',))
self.add_bindings('delete-left-word', ('M-DELETE', 'M-BACKSPACE',))
self.add_bindings('delete-right', ('C-d',))
self.add_bindings('delete-right-word', ('M-d',))
self.add_bindings('kill-region', ('C-w',))
self.add_bindings('copy-region', ('M-w',))
self.add_bindings('kill', ('C-k',))
self.add_bindings('copy', ('M-k',))
self.add_bindings('yank', ('C-y',))
self.add_bindings('pop-kill', ('M-y',))
self.add_bindings('right-word', ('M-f',))
self.add_bindings('left-word', ('M-b',))
self.add_bindings('set-mark', ('C-@',))
self.add_bindings('switch-buffer', ('C-x b',))
self.add_bindings('switch-mark', ('C-x C-x',))
self.add_bindings('undo', ('C-/', 'C-x u',))
self.add_bindings('redo', ('M-/', 'M-_', 'C-x r',))
self.add_bindings('goto-line', ('M-g',))
self.add_bindings('forward-chars', ('C-x M-c',))
self.add_bindings('forward-lines', ('C-x M-n',))
self.add_bindings('search', ('C-s',))
self.add_bindings('reverse-search', ('C-r',))
self.add_bindings('toggle-margins', ('M-m',))
self.add_bindings('replace', ('M-%',))
self.add_bindings('open-file', ('C-x C-f',))
self.add_bindings('kill-buffer', ('C-x k',))
self.add_bindings('list-buffers', ('C-x C-b',))
self.add_bindings('meta-x', ('M-x',))
self.add_bindings('wrap-line', ('M-q',))
self.add_bindings('transpose-words', ('M-t',))
self.add_bindings('save-buffer', ('C-x C-s',))
self.add_bindings('save-buffer-as', ('C-x C-w',))
self.add_bindings('relex-buffer', ('M-r',))
self.add_bindings('exit', ('C-x C-c',))
self.add_bindings('exit2', ('C-c C-c',))
self.add_bindings('split-window', ('C-x s',))
self.add_bindings('unsplit-window', ('C-u s',))
self.add_bindings('toggle-window', ('C-x o',))
self.add_bindings('delete-left-whitespace', ('C-c DELETE', 'C-c BACKSPACE',))
self.add_bindings('delete-right-whitespace', ('C-c d',))
self.add_bindings('insert-space', ('SPACE',))
self.add_bindings('insert-tab', ('TAB',))
self.add_bindings('insert-newline', ('RETURN',))
self.add_bindings('comment-region', ('C-c #',))
self.add_bindings('uncomment-region', ('C-u C-c #',))
self.add_bindings('justify-right', ('C-c f',))
self.add_bindings('justify-left', ('C-c b',))
self.add_bindings('indent-block', ('C-c >',))
self.add_bindings('unindent-block', ('C-c <',))
self.add_bindings('code-complete', ('M-c',))
self.add_bindings('shell-cmd', ('C-c !',))
self.add_bindings('open-aes-file', ('C-c a',))
self.add_bindings('open-console', ('M-e',))
self.add_bindings('show-bindings-buffer', ('C-c M-h','C-c M-?',))
self.add_bindings('which-command', ('M-?',))
self.add_bindings('cmd-help-buffer', ('M-h',))
self.add_bindings('set-mode', ('C-x m',))
self.add_bindings('cancel', ('C-]',))
2007-06-17 08:38:46 -04:00
self.add_bindings('close-paren', (')',))
self.add_bindings('close-brace', ('}',))
self.add_bindings('close-bracket', (']',))
2007-03-06 10:05:38 -05:00
# create all the insert actions for the character ranges we like
for c in string.letters + string.digits + string.punctuation:
## closing tags are handled differently
2007-06-17 08:38:46 -04:00
if c == ')' or c == ']' or c == '}':
continue
2007-03-06 10:05:38 -05:00
self.add_binding('insert-string-%s' % c, c)
# initialize some stuff
self.tag_matching = False
self.grammar = None
self.lexer = None
self.tabber = None
# initialize the default colors, highlighter, etc.
self.default_color = color.pairs('default', 'default')
self.colors = {}
self.highlighter = highlight.Highlighter(self)
# get mode name
def name(self):
return "Fundamental"
# handle input tokens
def handle_token(self, t):
'''self.handle_token(token): handles input "token"'''
self.window.active_point = None
if DEBUG:
# debug mode is crash prone
act = Handler.handle_token(self, t)
if act is None:
return
else:
self.window.application.clear_error()
act.execute(self.window)
self.window.application.last_action = act.name
else:
# regular mode is hard to get stack traces from
try:
act = Handler.handle_token(self, t)
if act is None:
return
else:
self.window.application.clear_error()
act.execute(self.window)
self.window.application.last_action = act.name
except Exception, e:
if DEBUG:
raise
else:
err = "%s in mode '%s'" % (e, self.name())
self.window.application.set_error(err)
def invalidate(self):
if self.tabber is not None:
self.tabber.invalidate()
if self.lexer is not None:
self.highlighter.invalidate_regions()
def get_regions(self):
if self.lexer is not None:
return self.highlighter.get_regions()
else:
return [[] for l in self.window.get_physical_lines()]
def visible_regions(self):
i = self.window.visible_offset()
regions = self.get_regions()
return regions[i:i+self.window.height]
def region_added(self, p, xdiff, ydiff, s):
if self.lexer is not None:
if self.tabber is not None and s != ' ' and s != ' ':
self.tabber.invalidate()
self.highlighter.region_added(p, xdiff, ydiff, s)
def region_removed(self, p1, p2, s):
if self.lexer is not None:
if self.tabber is not None:
self.tabber.invalidate()
self.highlighter.region_removed(p1, p2, s)
def get_indentation_level(self, y):
if self.tabber is None:
return None
else:
return self.tabber.get_indentation_level(y)