diff --git a/mode2.py b/mode2.py new file mode 100644 index 0000000..b00f4be --- /dev/null +++ b/mode2.py @@ -0,0 +1,231 @@ +import os +import sets, string + +import color, default, highlight, method, point + +DEBUG = False + +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): + 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.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: + act = self.window.application.methods[self.bindings[sequence]] + self.last_sequence = sequence + self.curr_tokens = [] + 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.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-]',)) + #self.add_bindings('close-paren', (')',)) + #self.add_bindings('close-brace', ('}',)) + #self.add_bindings('close-bracket', (']',)) + + # 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 + #if c == ')' or c == ']' or c == '}': + # continue + 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.tokens + else: + raise Exception, "" + regions = [] + for i in range(0, len(self.window.buffer.lines)): + l = self.window.buffer.lines[i] + regions.append([lex2.Token('line', '', i, 0, l)]) + return regions + + 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)