r5471 - in pyrepl/branch/pyrepl-rework-n: . pyrepl pyrepl/dfa test/unit
[email protected] Wed, 7 Jul 2004 13:34:18 +0200 (MEST)
| Newsgroups | gmane.comp.python.pyrepl.checkins |
|---|---|
| Message-ID | <[email protected]> |
Author: mwh Date: Wed Jul 7 13:34:17 2004 New Revision: 5471 Removed: pyrepl/branch/pyrepl-rework-n/pyrepl/.cvsignore pyrepl/branch/pyrepl-rework-n/pyrepl/copy_code.py Modified: pyrepl/branch/pyrepl-rework-n/LICENSE pyrepl/branch/pyrepl-rework-n/TODO pyrepl/branch/pyrepl-rework-n/pyrepl/commands.py pyrepl/branch/pyrepl-rework-n/pyrepl/completing_reader.py pyrepl/branch/pyrepl-rework-n/pyrepl/console.py pyrepl/branch/pyrepl-rework-n/pyrepl/dfa/commandsm.py pyrepl/branch/pyrepl-rework-n/pyrepl/dfa/unicodesm.py pyrepl/branch/pyrepl-rework-n/pyrepl/historical_reader.py pyrepl/branch/pyrepl-rework-n/pyrepl/keymap.py pyrepl/branch/pyrepl-rework-n/pyrepl/keymaps.py pyrepl/branch/pyrepl-rework-n/pyrepl/python_reader.py pyrepl/branch/pyrepl-rework-n/pyrepl/reader.py pyrepl/branch/pyrepl-rework-n/pyrepl/unix_console.py pyrepl/branch/pyrepl-rework-n/test/unit/test_commandsm.py pyrepl/branch/pyrepl-rework-n/test/unit/test_unicodesm.py Log: the result of a couple of days of failing to be productive at maths: + all the readers now use the new machinery + the old state machine code is removed + implement describe-key-briefly (this is cool!) + bits and pieces towards vi-mode + yet another new way of building the keymaps + note some problems in TODO + VILE HACK in reader.use_keymap + the odd bugfix and cleanup + improvements on how unrecognized key sequences are reported Modified: pyrepl/branch/pyrepl-rework-n/LICENSE ============================================================================== --- pyrepl/branch/pyrepl-rework-n/LICENSE (original) +++ pyrepl/branch/pyrepl-rework-n/LICENSE Wed Jul 7 13:34:17 2004 @@ -1,4 +1,4 @@ - Copyright 2000-2002 Michael Hudson [email protected] + Copyright 2000-2004 Michael Hudson [email protected] All Rights Reserved Modified: pyrepl/branch/pyrepl-rework-n/TODO ============================================================================== --- pyrepl/branch/pyrepl-rework-n/TODO (original) +++ pyrepl/branch/pyrepl-rework-n/TODO Wed Jul 7 13:34:17 2004 @@ -1,19 +1,40 @@ -In no particular order: -+ vi-mode -+ GUI toolkit friendliness (done for tk) -+ point-and-mark? -+ user customization support (maybe even try to read $INPUTRC?) -+ in general, implement more readline functions (just a matter of - typing, for the most part) -+ a more incremental way of updating the screen. -+ unicode support -+ undo support -+ port to windows - -+ reduce verbosity -+ tabs -+ look up delete in terminfo? tcsetattr(self.fd).cc[termios.VERASE] -+ mention license? +Rambling about current problems (or problems that were at one point +current): -+ find a font. maybe I can bundle andale mono? + There are scary suboptimalities in the area of keys known by + multiple names (the tab key probably being the winner for having + the most names). Also possibly but not probably relatedly, + getting vi insert mode to recognize `escape' as a distinct + keystroke and not as a precursor to, say, one of the arrow keys is + a pain. + It may turn out that my neat character-> unicode-> keystroke-> + command process may not work out as well as I had hoped. Bugrit. + +Things to hack on, in no particular order: + + + vi-mode (this has mostly reached the 'typing' point, too, though + 'knowing how vi-mode is supposed to work' would be handy) + + + GUI toolkit friendliness (done for tk) + + + point-and-mark? + + + user customization support (maybe even try to read $INPUTRC?) + + + in general, implement more readline functions (just a matter of + typing, for the most part) + + + a more incremental way of updating the screen. + + + undo support + + + port to windows + + + reduce verbosity + + + tabs + + + resurrect pygame console + + + integrate with rlcompleter, ipython Deleted: /pyrepl/branch/pyrepl-rework-n/pyrepl/.cvsignore ============================================================================== --- /pyrepl/branch/pyrepl-rework-n/pyrepl/.cvsignore Wed Jul 7 13:34:17 2004 +++ (empty file) @@ -1 +0,0 @@ -*.pyc Modified: pyrepl/branch/pyrepl-rework-n/pyrepl/commands.py ============================================================================== --- pyrepl/branch/pyrepl-rework-n/pyrepl/commands.py (original) +++ pyrepl/branch/pyrepl-rework-n/pyrepl/commands.py Wed Jul 7 13:34:17 2004 @@ -82,7 +82,7 @@ kills_digit_arg = 0 def do(self): r = self.reader - c = self.event[-1] + c = self.event[-1].raw if c == "-": if r.arg is not None: r.arg = -r.arg @@ -325,7 +325,7 @@ r = self.reader b = r.buffer if ( r.pos == 0 and len(b) == 0 # this is something of a hack - and self.event[-1] == "\004"): + and self.event[-1].raw == "\004"): r.console.finish() raise EOFError for i in range(r.get_arg()): @@ -346,9 +346,17 @@ class invalid_key(Command): def do(self): + from curses.ascii import unctrl + mu = self.reader.console.keys.maybe_untranslate pending = self.reader.console.getpending() - s = ''.join([e.raw for e in self.event]) + pending.raw - self.reader.error("`%r' not bound"%s) + l = [] + for e in self.event: + n = e.name + if len(n) == 1 and ord(n) < 32: + n = 'C-' + unctrl(ord(n))[1:].lower() + l.append(n) + s = ' '.join(l) + self.reader.error(u"`%s' not bound"%s) class invalid_command(Command): def do(self): @@ -358,18 +366,66 @@ class qIHelp(Command): def do(self): r = self.reader - r.insert((self.event + r.console.getpending().data) * r.get_arg()) + r.insert((self.event.raw + r.console.getpending().raw) * r.get_arg()) r.pop_input_trans() -from pyrepl import input - class QITrans(object): def push(self, evt): self.evt = evt def get(self): - return ('qIHelp', self.evt.raw) + from pyrepl.console import Command + return Command('qIHelp', self.evt) class quoted_insert(Command): kills_digit_arg = 0 def do(self): self.reader.push_input_trans(QITrans()) + +class vi_editing_mode(Command): + def do(self): + self.reader.use_keymap(self.reader.vi_insert_keymap) + self.reader.msg = 'entering vi-edit mode' + self.reader.dirty = 1 + +class vi_command_mode(Command): + def do(self): + self.reader.use_keymap(self.reader.vi_command_keymap) + self.reader.msg = 'entering vi-command mode' + self.reader.dirty = 1 + +class emacs_editing_mode(Command): + def do(self): + self.reader.use_keymap(self.reader.emacs_keymap) + self.reader.msg = 'entering emacs mode' + self.reader.dirty = 1 + +class DKBTrans(object): + def __init__(self, wrapped): + self.wrapped = wrapped + def push(self, evt): + self.wrapped.push(evt) + def get(self): + e = self.wrapped.get() + if e is None: + return e + from pyrepl.console import Command + return Command('dkbHelp', e) + +class describe_key_briefly(Command): + def do(self): + self.reader.push_input_trans(DKBTrans(self.reader.input_trans)) + +class dkbHelp(Command): + def do(self): + from curses.ascii import unctrl + s = [] + for k in self.event.keystrokes: + n = k.name + if len(n) == 1 and ord(n) < 32: + n = 'C-' + unctrl(ord(n))[1:].lower() + s.append(n) + + self.reader.msg = "`%s' runs the command `%s'"%(' '.join(s), + self.event.cmd) + self.reader.dirty = 1 + self.reader.pop_input_trans() Modified: pyrepl/branch/pyrepl-rework-n/pyrepl/completing_reader.py ============================================================================== --- pyrepl/branch/pyrepl-rework-n/pyrepl/completing_reader.py (original) +++ pyrepl/branch/pyrepl-rework-n/pyrepl/completing_reader.py Wed Jul 7 13:34:17 2004 @@ -163,10 +163,8 @@ * """ - def collect_keymap(self): - return super(CompletingReader, self).collect_keymap() + ( - (r'\t', 'complete'),) - + _emacs_keymap = ((r'\<tab>', 'complete'),) + def __init__(self, console): super(CompletingReader, self).__init__(console) self.cmpltn_menu = ["[ menu 1 ]", "[ menu 2 ]"] @@ -213,11 +211,13 @@ return [] def test(): + from unix_console import UnixConsole + words = ['a', 'bb', 'abc'] class TestReader(CompletingReader): def get_completions(self, stem): - return [s for l in map(lambda x:x.split(),self.history) + return [s for l in map(lambda x:x.split(), words) for s in l if s and s.startswith(stem)] - reader = TestReader() + reader = TestReader(UnixConsole()) reader.ps1 = "c**> " reader.ps2 = "c/*> " reader.ps3 = "c|*> " Modified: pyrepl/branch/pyrepl-rework-n/pyrepl/console.py ============================================================================== --- pyrepl/branch/pyrepl-rework-n/pyrepl/console.py (original) +++ pyrepl/branch/pyrepl-rework-n/pyrepl/console.py Wed Jul 7 13:34:17 2004 @@ -46,18 +46,7 @@ return "%s(%r, %r)"%(self.__class__.__name__, self.cmd, self.keystrokes) -class Event: - """An Event. `evt' is 'key' or somesuch.""" - - def __init__(self, evt, data, raw=''): - self.evt = evt - self.data = data - self.raw = raw - - def __repr__(self): - return 'Event(%r, %r)'%(self.evt, self.data) - -class Console: +class Console(object): """Attributes: screen, @@ -86,8 +75,8 @@ pass def get_event(self, block=1): - """Return an Event instance. Returns None if |block| is false - and there is no event pending, otherwise waits for the + """Return an Command instance. Returns None if |block| is + false and there is no event pending, otherwise waits for the completion of an event.""" pass Deleted: /pyrepl/branch/pyrepl-rework-n/pyrepl/copy_code.py ============================================================================== --- /pyrepl/branch/pyrepl-rework-n/pyrepl/copy_code.py Wed Jul 7 13:34:17 2004 +++ (empty file) @@ -1,73 +0,0 @@ -# Copyright 2000-2004 Michael Hudson [email protected] -# -# All Rights Reserved -# -# -# Permission to use, copy, modify, and distribute this software and -# its documentation for any purpose is hereby granted without fee, -# provided that the above copyright notice appear in all copies and -# that both that copyright notice and this permission notice appear in -# supporting documentation. -# -# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO -# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, -# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER -# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF -# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import new - -def copy_code_with_changes(codeobject, - argcount=None, - nlocals=None, - stacksize=None, - flags=None, - code=None, - consts=None, - names=None, - varnames=None, - filename=None, - name=None, - firstlineno=None, - lnotab=None): - if argcount is None: argcount = codeobject.co_argcount - if nlocals is None: nlocals = codeobject.co_nlocals - if stacksize is None: stacksize = codeobject.co_stacksize - if flags is None: flags = codeobject.co_flags - if code is None: code = codeobject.co_code - if consts is None: consts = codeobject.co_consts - if names is None: names = codeobject.co_names - if varnames is None: varnames = codeobject.co_varnames - if filename is None: filename = codeobject.co_filename - if name is None: name = codeobject.co_name - if firstlineno is None: firstlineno = codeobject.co_firstlineno - if lnotab is None: lnotab = codeobject.co_lnotab - return new.code(argcount, - nlocals, - stacksize, - flags, - code, - consts, - names, - varnames, - filename, - name, - firstlineno, - lnotab) - -code_attrs=['argcount', - 'nlocals', - 'stacksize', - 'flags', - 'code', - 'consts', - 'names', - 'varnames', - 'filename', - 'name', - 'firstlineno', - 'lnotab'] - - Modified: pyrepl/branch/pyrepl-rework-n/pyrepl/dfa/commandsm.py ============================================================================== --- pyrepl/branch/pyrepl-rework-n/pyrepl/dfa/commandsm.py (original) +++ pyrepl/branch/pyrepl-rework-n/pyrepl/dfa/commandsm.py Wed Jul 7 13:34:17 2004 @@ -30,6 +30,8 @@ self.output.append(Command(k, self.buf)) self.buf = [] self.k = self.ck + else: + self.k = k else: if (len(self.buf) > 1 or len(keystroke.raw) > 1 Modified: pyrepl/branch/pyrepl-rework-n/pyrepl/dfa/unicodesm.py ============================================================================== --- pyrepl/branch/pyrepl-rework-n/pyrepl/dfa/unicodesm.py (original) +++ pyrepl/branch/pyrepl-rework-n/pyrepl/dfa/unicodesm.py Wed Jul 7 13:34:17 2004 @@ -52,7 +52,11 @@ if not self.l: c = self.chars self.chars = '' - self.output.append(c.decode('utf-8')) + try: + self.output.append(c.decode('utf-8')) + except UnicodeError: + self.output.append(u'<invalid utf-8 data>') + def unicodesm_for_encoding(encoding): if codecs.lookup(encoding) == codecs.lookup('utf-8'): Modified: pyrepl/branch/pyrepl-rework-n/pyrepl/historical_reader.py ============================================================================== --- pyrepl/branch/pyrepl-rework-n/pyrepl/historical_reader.py (original) +++ pyrepl/branch/pyrepl-rework-n/pyrepl/historical_reader.py Wed Jul 7 13:34:17 2004 @@ -20,6 +20,8 @@ from pyrepl import reader, commands from pyrepl.reader import Reader as R +from pyrepl.dfa import commandsm + isearch_keymap = tuple( [('\\%03o'%c, 'isearch-end') for c in range(256) if chr(c) != '\\'] + \ [(c, 'isearch-add-character') @@ -135,7 +137,7 @@ def do(self): r = self.reader b = r.buffer - r.isearch_term += self.event[-1] + r.isearch_term += self.event[-1].raw r.dirty = 1 p = r.pos + len(r.isearch_term) - 1 if b[p:p+1] != [r.isearch_term[-1]]: @@ -186,18 +188,16 @@ HistoricalReader instance methods. """ - def collect_keymap(self): - return super(HistoricalReader, self).collect_keymap() + ( - (r'\C-n', 'next-history'), - (r'\C-p', 'previous-history'), - (r'\C-o', 'operate-and-get-next'), - (r'\C-r', 'reverse-history-isearch'), - (r'\C-s', 'forward-history-isearch'), - (r'\M-r', 'restore-history'), - (r'\M-.', 'yank-arg'), - (r'\<page down>', 'last-history'), - (r'\<page up>', 'first-history')) - + _emacs_keymap = ( + (r'\C-n', 'next-history'), + (r'\C-p', 'previous-history'), + (r'\C-o', 'operate-and-get-next'), + (r'\C-r', 'reverse-history-isearch'), + (r'\C-s', 'forward-history-isearch'), + (r'\M-r', 'restore-history'), + (r'\M-.', 'yank-arg'), + (r'\<page down>', 'last-history'), + (r'\<page up>', 'first-history')) def __init__(self, console): super(HistoricalReader, self).__init__(console) @@ -214,8 +214,8 @@ isearch_forwards, isearch_backwards, operate_and_get_next]: self.commands[c.__name__] = c self.commands[c.__name__.replace('_', '-')] = c - from pyrepl import input - self.isearch_trans = input.KeymapTranslator( + self.isearch_trans = commandsm.CommandSM( + None, self.console.keys, isearch_keymap, invalid_cls=isearch_end, character_cls=isearch_add_character) Modified: pyrepl/branch/pyrepl-rework-n/pyrepl/keymap.py ============================================================================== --- pyrepl/branch/pyrepl-rework-n/pyrepl/keymap.py (original) +++ pyrepl/branch/pyrepl-rework-n/pyrepl/keymap.py Wed Jul 7 13:34:17 2004 @@ -120,7 +120,7 @@ raise KeySpecError, \ "unrecognised keyname `%s' at char %d of %s"%( ret, s + 2, repr(key)) - #ret = keys.translate(ret) + #ret = keys.maybe_untranslate(ret) s = t + 1 else: raise KeySpecError, \ @@ -133,6 +133,7 @@ if len(ret) > 1: raise KeySpecError, "\\C- must be followed by a character" ret = ascii.ctrl(ret) + ret = keys.maybe_untranslate(ret) if meta: ret = ['\033', ret] else: Modified: pyrepl/branch/pyrepl-rework-n/pyrepl/keymaps.py ============================================================================== --- pyrepl/branch/pyrepl-rework-n/pyrepl/keymaps.py (original) +++ pyrepl/branch/pyrepl-rework-n/pyrepl/keymaps.py Wed Jul 7 13:34:17 2004 @@ -25,12 +25,11 @@ (r'\C-e', 'end-of-line'), (r'\C-f', 'right'), (r'\C-g', 'cancel'), - (r'\C-h', 'backspace'), - (r'\C-j', 'self-insert'), + (r'\C-hc', 'describe-key-briefly'), (r'\<return>', 'accept'), (r'\C-k', 'kill-line'), (r'\C-l', 'clear-screen'), -# (r'\C-m', 'accept'), + (r'\C-m', 'accept'), (r'\C-q', 'quoted-insert'), (r'\C-t', 'transpose-characters'), (r'\C-u', 'unix-line-discard'), @@ -59,7 +58,7 @@ (r'\M-7', 'digit-arg'), (r'\M-8', 'digit-arg'), (r'\M-9', 'digit-arg'), - (r'\M-\n', 'self-insert'), +# (r'\M-\n', 'insert-nl'), (r'\<backslash>', 'self-insert')] + \ [(c, 'self-insert') for c in map(chr, range(32, 127)) if c <> '\\'] + \ @@ -79,6 +78,8 @@ (r'\EOF', 'end'), # the entries in the terminfo database for xterms (r'\EOH', 'home'), # seem to be wrong. this is a less than ideal # workaround + (r'\M-\<return>', 'vi-editing-mode'), + (r'\C-x\C-v', 'vi-editing-mode'), ]) hist_emacs_keymap = reader_emacs_keymap + ( @@ -90,7 +91,7 @@ (r'\M-r', 'restore-history'), (r'\M-.', 'yank-arg'), (r'\<page down>', 'last-history'), - (r'\<page up>', 'first-history')) + (r'\<page up>', 'first-history'),) comp_emacs_keymap = hist_emacs_keymap + ( (r'\t', 'complete'),) @@ -98,7 +99,7 @@ python_emacs_keymap = comp_emacs_keymap + ( (r'\n', 'maybe-accept'), (r'\M-\n', 'self-insert')) - + reader_vi_insert_keymap = tuple( [(c, 'self-insert') for c in map(chr, range(32, 127)) if c <> '\\'] + \ @@ -106,17 +107,20 @@ for c in map(chr, range(128, 256)) if c.isalpha()] + \ [(r'\C-d', 'delete'), (r'\<backspace>', 'backspace'), - ('')]) + (r'\C-t', 'transpose-characters'), + ('\033', 'vi-command-mode'), + #(r'\C-\M-j', 'emacs-editing-mode'), + ]) reader_vi_command_keymap = tuple( [ - ('E', 'enter-emacs-mode'), + ('E', 'end-of-word'), ('R', 'enter-replace-mode'), ('dw', 'delete-word'), ('dd', 'delete-line'), - + (r'\M-\<return>', 'emacs-editing-mode'), ('h', 'left'), - ('i', 'enter-insert-mode'), + ('i', 'vi-editing-mode'), ('j', 'down'), ('k', 'up'), ('l', 'right'), @@ -129,12 +133,5 @@ [(c, 'digit-arg') for c in '01234567689'] + []) - -reader_keymaps = { - 'emacs' : reader_emacs_keymap, - 'vi-insert' : reader_vi_insert_keymap, - 'vi-command' : reader_vi_command_keymap - } - del c # from the listcomps Modified: pyrepl/branch/pyrepl-rework-n/pyrepl/python_reader.py ============================================================================== --- pyrepl/branch/pyrepl-rework-n/pyrepl/python_reader.py (original) +++ pyrepl/branch/pyrepl-rework-n/pyrepl/python_reader.py Wed Jul 7 13:34:17 2004 @@ -21,7 +21,7 @@ from pyrepl.completing_reader import CompletingReader from pyrepl.historical_reader import HistoricalReader from pyrepl import completing_reader, reader -from pyrepl import copy_code, commands, completer +from pyrepl import commands, completer from pyrepl import module_lister import new, sys, os, re, code, traceback import atexit, warnings @@ -30,8 +30,6 @@ except ImportError: import pickle -CommandCompiler = code.CommandCompiler - def eat_it(*args): """this function eats warnings, if you were wondering""" pass @@ -68,10 +66,12 @@ return saver class PythonicReader(CompletingReader, HistoricalReader): - def collect_keymap(self): - return super(PythonicReader, self).collect_keymap() + ( - (r'\n', 'maybe-accept'), - (r'\M-\n', 'insert-nl')) + _emacs_keymap = ( + (r'\n', 'maybe-accept'), + (r'\M-\n', 'insert-nl')) + _vi_insert_keymap = ( + (r'\n', 'maybe-accept'),) + def __init__(self, console, locals, compiler=None): @@ -82,7 +82,7 @@ st[c] = reader.SYNTAX_WORD self.locals = locals if compiler is None: - self.compiler = CommandCompiler() + self.compiler = code.CommandCompiler() else: self.compiler = compiler try: @@ -136,7 +136,7 @@ if locals is None: locals = {} self.II_init(locals) - self.compiler = CommandCompiler() + self.compiler = code.CommandCompiler() self.compile = self.compiler.compiler self.reader = PythonicReader(console, locals, self.compiler) locals['Reader'] = self.reader @@ -309,7 +309,7 @@ signal.default_int_handler) self.prepare() try: - reactor.run() + reactor.run(installSignalHandlers=0) finally: self.restore() @@ -321,7 +321,7 @@ self.cocoainteracter = CocoaInteracter.alloc().init(self, inputfilehandle, outputfilehandle) -def main(use_pygame_console=0, interactmethod="twistedinteract"): +def main(use_pygame_console=0, interactmethod="interact"): si, se, so = sys.stdin, sys.stderr, sys.stdout try: if 0 and use_pygame_console: # pygame currently borked @@ -359,7 +359,7 @@ 'for more information.' sys.path.insert(0, os.getcwd()) - module_lister._make_module_list() + #module_lister._make_module_list() if __name__ != '__main__': mainmod = new.module('__main__') Modified: pyrepl/branch/pyrepl-rework-n/pyrepl/reader.py ============================================================================== --- pyrepl/branch/pyrepl-rework-n/pyrepl/reader.py (original) +++ pyrepl/branch/pyrepl-rework-n/pyrepl/reader.py Wed Jul 7 13:34:17 2004 @@ -21,6 +21,7 @@ from pyrepl import commands from curses import ascii from pyrepl.dfa import commandsm +from pyrepl import keymaps def _make_unctrl_map(): uc_map = {} @@ -94,72 +95,6 @@ st[u'\n'] = st[u' '] = SYNTAX_WHITESPACE return st -default_keymap = tuple( - [(r'\C-a', 'beginning-of-line'), - (r'\C-b', 'left'), - (r'\C-c', 'interrupt'), - (r'\C-d', 'delete'), - (r'\C-e', 'end-of-line'), - (r'\C-f', 'right'), - (r'\C-g', 'cancel'), - (r'\C-h', 'backspace'), - (r'\C-j', 'accept'), - (r'\<return>', 'accept'), - (r'\C-k', 'kill-line'), - (r'\C-l', 'clear-screen'), - (r'\C-m', 'accept'), - (r'\C-q', 'quoted-insert'), - (r'\C-t', 'transpose-characters'), - (r'\C-u', 'unix-line-discard'), - (r'\C-v', 'quoted-insert'), - (r'\C-w', 'unix-word-rubout'), - (r'\C-x\C-u', 'upcase-region'), - (r'\C-y', 'yank'), - (r'\C-z', 'suspend'), - - (r'\M-b', 'backward-word'), - (r'\M-c', 'capitalize-word'), - (r'\M-d', 'kill-word'), - (r'\M-f', 'forward-word'), - (r'\M-l', 'downcase-word'), - (r'\M-t', 'transpose-words'), - (r'\M-u', 'upcase-word'), - (r'\M-y', 'yank-pop'), - (r'\M--', 'digit-arg'), - (r'\M-0', 'digit-arg'), - (r'\M-1', 'digit-arg'), - (r'\M-2', 'digit-arg'), - (r'\M-3', 'digit-arg'), - (r'\M-4', 'digit-arg'), - (r'\M-5', 'digit-arg'), - (r'\M-6', 'digit-arg'), - (r'\M-7', 'digit-arg'), - (r'\M-8', 'digit-arg'), - (r'\M-9', 'digit-arg'), - (r'\M-\n', 'insert-nl'), - ('\\\\', 'self-insert')] + \ - [(c, 'self-insert') - for c in map(chr, range(32, 127)) if c <> '\\'] + \ - [(c, 'self-insert') - for c in map(chr, range(128, 256)) if c.isalpha()] + \ - [(r'\<up>', 'up'), - (r'\<down>', 'down'), - (r'\<left>', 'left'), - (r'\<right>', 'right'), - (r'\<insert>', 'quoted-insert'), - (r'\<delete>', 'delete'), - (r'\<backspace>', 'backspace'), - (r'\M-\<backspace>', 'backward-kill-word'), - (r'\<end>', 'end'), - (r'\<home>', 'home'), - (r'\<f1>', 'help'), - (r'\EOF', 'end'), # the entries in the terminfo database for xterms - (r'\EOH', 'home'), # seem to be wrong. this is a less than ideal - # workaround - ]) - -del c # from the listcomps - class Reader(object): """The Reader class implements the bare bones of a command reader, handling such details as editing and cursor motion. What it does @@ -241,14 +176,31 @@ self.commands[v.__name__.replace('_', '-')] = v self.syntax_table = make_default_syntax_table() self.input_trans_stack = [] - self.keymap = self.collect_keymap() self.input_trans = commandsm.CommandSM( - None, self.console.keys, self.keymap, + None, self.console.keys, self.emacs_keymap, invalid_cls='invalid-key', character_cls='self-insert') - def collect_keymap(self): - return default_keymap + + def make_keymap_getter(km): + attr = '_%s_keymap'%km + class KeymapDescr(object): + def __get__(self, ob, cls): + mro = list(cls.__mro__) + mro.reverse() + r = () + for c in mro: + r += getattr(c, attr, ()) + return r + return KeymapDescr() + + emacs_keymap = make_keymap_getter('emacs') + vi_insert_keymap = make_keymap_getter('vi_insert') + vi_command_keymap = make_keymap_getter('vi_command') + + _emacs_keymap = keymaps.reader_emacs_keymap + _vi_insert_keymap = keymaps.reader_vi_insert_keymap + _vi_command_keymap = keymaps.reader_vi_command_keymap def calc_screen(self): """The purpose of this method is to translate changes in @@ -472,8 +424,8 @@ if isinstance(cmd.cmd, str): cmd = self.commands.get(cmd.cmd, commands.invalid_command)(self, (cmd.cmd, cmd.keystrokes)) - elif isinstance(cmd[0], type): - cmd = cmd.cmd(self, cmd) + elif isinstance(cmd.cmd, type): + cmd = cmd.cmd(self, (cmd.cmd, cmd.keystrokes)) cmd.do() @@ -506,7 +458,7 @@ if keystroke is None: # can only happen if we're not blocking return None - if keystroke.name[0] != '<': + if keystroke.name[0] != '<<': self.input_trans.push(keystroke) elif keystroke.name == '<scroll>': self.refresh() @@ -543,12 +495,64 @@ finally: self.restore() - def bind(self, spec, command): - self.keymap = self.keymap + ((spec, command),) + def use_keymap(self, keymap): + assert not self.input_trans_stack + self.keymap = keymap self.input_trans = commandsm.CommandSM( None, self.console.keys, self.keymap, invalid_cls='invalid-key', character_cls='self-insert') + from pyrepl.dfa import keystrokesm + if isinstance(self.input_trans.k['\033'], dict): + self.console.keystrokesm = keystrokesm.KeystrokeSM( + None, self.console.keys) + else: + class CursesKeys(object): + _curses_keynames = { + "delete" : "kdch1", + } + _simple_keys = { +# 'escape': '\033', + 'return': '\n', + 'space': ' ', + 'tab': '\t', + 'backslash': '\\', + } + + def translate(self, key): + if key in self._curses_keynames: + from curses import tigetstr + return tigetstr(self._curses_keynames[key]) + elif key in self._simple_keys: + return self._simple_keys[key] + def maybe_untranslate(self, key): + for k, v in self._simple_keys.items(): + if v == key: + return k + return key + def all_keys(self): + r = [] + for k in self.keynames(): + v = self.translate(k) + if v is not None: + r.append((v, k)) + # XXX ick + from fancy_termios import tcgetattr + import termios + r.append((tcgetattr(0).cc[termios.VERASE], 'backspace')) + return r + def keynames(self): + return self._curses_keynames.keys() + self._simple_keys.keys() + ['backspace'] + self.console.keystrokesm = keystrokesm.KeystrokeSM( + None, CursesKeys()) + self.console.unicodesm.parent = self.console.keystrokesm + + def bind(self, spec, command): + self.emacs_keymap += ((spec, command),) + self.input_trans = commandsm.CommandSM( + None, self.console.keys, self.emacs_keymap, + invalid_cls='invalid-key', + character_cls='self-insert') def get_buffer(self, encoding=None): if encoding is None: @@ -566,6 +570,7 @@ reader.ps2 = "/*> " reader.ps3 = "|*> " reader.ps4 = "\*> " +# print reader.input_trans.k['\n'] while reader.readline(): pass Modified: pyrepl/branch/pyrepl-rework-n/pyrepl/unix_console.py ============================================================================== --- pyrepl/branch/pyrepl-rework-n/pyrepl/unix_console.py (original) +++ pyrepl/branch/pyrepl-rework-n/pyrepl/unix_console.py Wed Jul 7 13:34:17 2004 @@ -90,11 +90,11 @@ "up" : "kcuu1", } _simple_keys = { - 'enter': '\r', # 'escape': '\033', - 'return': '\r', + 'return': '\n', 'space': ' ', 'tab': '\t', + 'backslash': '\\', } def translate(self, key): @@ -103,6 +103,11 @@ return tigetstr(self._curses_keynames[key]) elif key in self._simple_keys: return self._simple_keys[key] + def maybe_untranslate(self, key): + for k, v in self._simple_keys.items(): + if v == key: + return k + return key def all_keys(self): r = [] for k in self.keynames(): @@ -122,7 +127,7 @@ if encoding is None: encoding = sys.getdefaultencoding() - self.encoding = encoding + self._encoding = encoding if isinstance(f_in, int): self.input_fd = f_in @@ -143,7 +148,6 @@ self.keystrokesm = keystrokesm.KeystrokeSM(None, self.keys) self.unicodesm.parent = self.keystrokesm - print self.keystrokesm.k self._bel = _my_getstr("bel") self._civis = _my_getstr("civis", optional=1) @@ -205,8 +209,15 @@ self.partial_char = '' + def get_encoding(self): + return self._encoding + def change_encoding(self, encoding): - self.encoding = encoding + self.unicodesm = unicodesm.unicodesm_for_encoding(encoding) + self.unicodesm.parent = self.keystrokesm + self._encoding = encoding + + encoding = property(get_encoding, change_encoding) def refresh(self, screen, (cx, cy)): # this function is still too long (over 90 lines) Modified: pyrepl/branch/pyrepl-rework-n/test/unit/test_commandsm.py ============================================================================== --- pyrepl/branch/pyrepl-rework-n/test/unit/test_commandsm.py (original) +++ pyrepl/branch/pyrepl-rework-n/test/unit/test_commandsm.py Wed Jul 7 13:34:17 2004 @@ -9,7 +9,8 @@ assert v == r test_keymap = [('a', 'cmd'), - ('\C-a', 'bol')] + ('\C-a', 'bol'), + ('\C-x\C-x', 'swop')] def test_basic(): m = CommandSM(None, None, test_keymap, None, None) @@ -17,5 +18,8 @@ do_feed(m, [a], [Command('cmd', [a])]) a = Keystroke('\001', '') do_feed(m, [a], [Command('bol', [a])]) + a = Keystroke('\030', '') + do_feed(m, [a], [None]) + do_feed(m, [a], [Command('swop', [a, a])]) Modified: pyrepl/branch/pyrepl-rework-n/test/unit/test_unicodesm.py ============================================================================== --- pyrepl/branch/pyrepl-rework-n/test/unit/test_unicodesm.py (original) +++ pyrepl/branch/pyrepl-rework-n/test/unit/test_unicodesm.py Wed Jul 7 13:34:17 2004 @@ -1,6 +1,6 @@ def run_test_fixedwidthsm(encoding): - from pyrepl.statemachine import FixedWidthUnicodeSM + from pyrepl.dfa.unicodesm import FixedWidthUnicodeSM m = FixedWidthUnicodeSM(None, encoding) inpu = u'abc\N{latin small letter i with diaeresis}de' inp = inpu.encode(encoding) @@ -11,7 +11,7 @@ assert m.get() is None def test_utf8sm(): - from pyrepl.statemachine import UTF8UnicodeSM + from pyrepl.dfa.unicodesm import UTF8UnicodeSM m = UTF8UnicodeSM(None) inpu = u'abc\N{latin small letter i with diaeresis}de' inp = inpu.encode('utf-8')