[pyrepl-checkins] r5437 - in pyrepl/branch/pyrepl-rework-n:
pyrepl/dfa test test/unit
mwh at codespeak.net
mwh at codespeak.net
Mon Jul 5 16:08:00 MEST 2004
Author: mwh
Date: Mon Jul 5 16:08:00 2004
New Revision: 5437
Added:
pyrepl/branch/pyrepl-rework-n/pyrepl/dfa/ (props changed)
pyrepl/branch/pyrepl-rework-n/pyrepl/dfa/__init__.py (contents, props changed)
pyrepl/branch/pyrepl-rework-n/pyrepl/dfa/base.py (contents, props changed)
pyrepl/branch/pyrepl-rework-n/pyrepl/dfa/commandsm.py (contents, props changed)
pyrepl/branch/pyrepl-rework-n/pyrepl/dfa/compile.py (contents, props changed)
pyrepl/branch/pyrepl-rework-n/pyrepl/dfa/keystrokesm.py (contents, props changed)
pyrepl/branch/pyrepl-rework-n/pyrepl/dfa/statemachine.py (contents, props changed)
pyrepl/branch/pyrepl-rework-n/pyrepl/dfa/unicodesm.py (contents, props changed)
pyrepl/branch/pyrepl-rework-n/test/
pyrepl/branch/pyrepl-rework-n/test/unit/ (props changed)
pyrepl/branch/pyrepl-rework-n/test/unit/test_commandsm.py (contents, props changed)
pyrepl/branch/pyrepl-rework-n/test/unit/test_keystrokesm.py (contents, props changed)
pyrepl/branch/pyrepl-rework-n/test/unit/test_makematch.py (contents, props changed)
pyrepl/branch/pyrepl-rework-n/test/unit/test_statemachines.py (contents, props changed)
pyrepl/branch/pyrepl-rework-n/test/unit/test_unicodesm.py (contents, props changed)
Log:
add some files on the branch
Added: pyrepl/branch/pyrepl-rework-n/pyrepl/dfa/__init__.py
==============================================================================
--- (empty file)
+++ pyrepl/branch/pyrepl-rework-n/pyrepl/dfa/__init__.py Mon Jul 5 16:08:00 2004
@@ -0,0 +1 @@
+# foo
Added: pyrepl/branch/pyrepl-rework-n/pyrepl/dfa/base.py
==============================================================================
--- (empty file)
+++ pyrepl/branch/pyrepl-rework-n/pyrepl/dfa/base.py Mon Jul 5 16:08:00 2004
@@ -0,0 +1,24 @@
+
+class StateMachine(object):
+ def __init__(self, parent):
+ self.parent = parent
+ self.output = []
+
+ def push_and_go(self, evt):
+ self.push(evt)
+ if self.parent is not None:
+ while 1:
+ e = self.get()
+ if e is None:
+ return
+ self.parent.push_and_go(e)
+
+ def push(self, evt):
+ pass
+
+ def get(self):
+ if self.output:
+ return self.output.pop(0)
+ else:
+ return None
+
Added: pyrepl/branch/pyrepl-rework-n/pyrepl/dfa/commandsm.py
==============================================================================
--- (empty file)
+++ pyrepl/branch/pyrepl-rework-n/pyrepl/dfa/commandsm.py Mon Jul 5 16:08:00 2004
@@ -0,0 +1,61 @@
+from pyrepl.dfa.base import StateMachine
+from pyrepl.dfa.compile import make_match
+from pyrepl.keymap import parse_keys
+
+import unicodedata
+
+class Command(object):
+ def __init__(self, cmd, keystrokes):
+ self.cmd = cmd
+ self.keystrokes = keystrokes
+ def __eq__(self, other):
+ if isinstance(other, Command):
+ return self.cmd == other.cmd \
+ and self.keystrokes == other.keystrokes
+ else:
+ return False
+ def __repr__(self):
+ return "%s(%r, %r)"%(self.__class__.__name__,
+ self.cmd, self.keystrokes)
+
+
+
+class CommandSM(StateMachine):
+ def __init__(self, parent, keys, keymap, invalid_cls, character_cls):
+ super(CommandSM, self).__init__(parent)
+
+ self.keymap = keymap
+ self.invalid_cls = invalid_cls
+ self.character_cls = character_cls
+
+ d = []
+ for keyspec, command in keymap:
+ keyseq = tuple(parse_keys(keyspec, keys))
+ d.append((keyseq, command))
+
+ self.k = self.ck = make_match(d, ())
+ self.buf = []
+
+ def push(self, keystroke):
+ n = keystroke.name
+ self.buf.append(keystroke)
+ if n in self.k:
+ k = self.k[n]
+ if not isinstance(k, dict):
+ self.output.append(Command(k, self.buf))
+ self.buf = []
+ self.k = self.ck
+ else:
+ if (len(self.buf) > 1
+ or len(keystroke.raw) > 1
+ or unicodedata.category(keystroke.raw)[0] == 'C'):
+ self.output.append(
+ Command(self.invalid_cls, self.buf))
+ else:
+ self.k[n] = self.character_cls
+ self.output.append(
+ Command(self.character_cls, self.buf))
+ self.buf = []
+ self.k = self.ck
+
+
Added: pyrepl/branch/pyrepl-rework-n/pyrepl/dfa/compile.py
==============================================================================
--- (empty file)
+++ pyrepl/branch/pyrepl-rework-n/pyrepl/dfa/compile.py Mon Jul 5 16:08:00 2004
@@ -0,0 +1,16 @@
+def make_match(seq, empty=''):
+ """make_match([('key', 'value'), ...]) -> nested dictionaries"""
+ r = {}
+ for key, value in seq:
+ r.setdefault(key[0], {})[key[1:]] = value
+ for key, value in r.items():
+ if empty in value:
+ if len(value) <> 1:
+ raise ValueError, \
+ "key definitions for %s clash"%(value.values(),)
+ else:
+ r[key] = value[empty]
+ else:
+ r[key] = make_match(value.items(), empty)
+ return r
+
Added: pyrepl/branch/pyrepl-rework-n/pyrepl/dfa/keystrokesm.py
==============================================================================
--- (empty file)
+++ pyrepl/branch/pyrepl-rework-n/pyrepl/dfa/keystrokesm.py Mon Jul 5 16:08:00 2004
@@ -0,0 +1,71 @@
+from pyrepl.dfa.base import StateMachine
+from pyrepl.dfa.compile import make_match
+
+class Keystroke(object):
+ def __init__(self, name, raw):
+ self.name = name
+ self.raw = raw
+ def __eq__(self, other):
+ if isinstance(other, Keystroke):
+ return self.name == other.name and self.raw == other.raw
+ else:
+ return False
+ def __repr__(self):
+ return "%s(%r, %r)"%(self.__class__.__name__,
+ self.name, self.raw)
+
+class CursesKeys(object):
+ _keynames = {
+ "delete" : "kdch1",
+ "down" : "kcud1",
+ "end" : "kend",
+ "enter" : "kent",
+ "f1" : "kf1", "f2" : "kf2", "f3" : "kf3", "f4" : "kf4",
+ "f5" : "kf5", "f6" : "kf6", "f7" : "kf7", "f8" : "kf8",
+ "f9" : "kf9", "f10" : "kf10", "f11" : "kf11", "f12" : "kf12",
+ "f13" : "kf13", "f14" : "kf14", "f15" : "kf15", "f16" : "kf16",
+ "f17" : "kf17", "f18" : "kf18", "f19" : "kf19", "f20" : "kf20",
+ "home" : "khome",
+ "insert" : "kich1",
+ "left" : "kcub1",
+ "page down" : "knp",
+ "page up" : "kpp",
+ "right" : "kcuf1",
+ "up" : "kcuu1",
+ }
+ def translate(self, key):
+ from curses import tigetstr
+ return tigetstr(self._keynames[key])
+ def all_keys(self):
+ r = []
+ for k in _keynames:
+ v = self.translate(k)
+ if v is not None:
+ r.append((v, k))
+ r.append((tcgetattr(fd)[6][VERASE], 'backspace'))
+ return r
+ def keynames(self):
+ return self._keynames.keys()
+
+class KeystrokeSM(StateMachine):
+ def __init__(self, parent, keys):
+ super(KeystrokeSM, self).__init__(parent)
+ self.k = self.ck = make_match(keys.all_keys())
+ self.chars = ''
+ def push(self, evt):
+ if evt in self.k:
+ self.chars += evt
+ k = self.k[evt]
+ if isinstance(k, dict):
+ self.k = k
+ else:
+ self.output.append(Keystroke(k, self.chars))
+ self.k = self.ck
+ self.chars = ''
+ elif self.chars:
+ self.output.extend([Keystroke(c, c) for c in self.chars])
+ self.k = self.ck
+ self.chars = ''
+ self.push(evt)
+ else:
+ self.output.append(Keystroke(evt, evt))
Added: pyrepl/branch/pyrepl-rework-n/pyrepl/dfa/statemachine.py
==============================================================================
--- (empty file)
+++ pyrepl/branch/pyrepl-rework-n/pyrepl/dfa/statemachine.py Mon Jul 5 16:08:00 2004
@@ -0,0 +1,104 @@
+# --------------------------------------------------------------------
+# base class
+# --------------------------------------------------------------------
+
+class StateMachine(object):
+ def __init__(self, parent):
+ self.parent = parent
+ self.output = []
+ def push_and_go(self, evt):
+ self.push(evt)
+ e = self.get()
+ if e is not None:
+ self.parent.push_and_go(e)
+
+ def push(self, evt):
+ pass
+ def get(self):
+ if self.output:
+ return self.output.pop(0)
+ else:
+ return None
+ # anything else?
+
+# --------------------------------------------------------------------
+# character data -> unicode
+# --------------------------------------------------------------------
+
+class FixedWidthUnicodeSM(StateMachine):
+ def __init__(self, parent, encoding):
+ super(FixedWidthUnicodeSM, self).__init__(parent)
+ self.encoding = encoding
+ self.width = len(u' '.encode(encoding))
+ self.chars = ''
+ self.output = []
+ def push(self, evt):
+ self.chars += evt
+ while len(self.chars) >= self.width:
+ self.output.append(self.chars[:self.width].decode(self.encoding))
+ self.chars = self.chars[self.width:]
+
+# nicked from unicodeobject.c:
+utf8prefix_lengths = [
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 0, 0]
+
+
+class UTF8UnicodeSM(StateMachine):
+ def __init__(self, parent):
+ super(UTF8UnicodeSM, self).__init__(parent)
+ self.chars = ''
+ self.l = 0
+ def push(self, evt):
+ if self.l:
+ self.chars += evt
+ self.l -= 1
+ else:
+ self.chars = evt
+ self.l = utf8prefix_lengths[ord(evt)] - 1
+ if self.l < 0:
+ raise UnicodeError, "invalid utf-8 data"
+ if not self.l:
+ c = self.chars
+ self.chars = ''
+ self.output.append(c.decode('utf-8'))
+
+if 0: # dreaming of coroutines....
+ while 1:
+ c = getchar()
+ l = lengths[c] - 1
+ for i in range(l):
+ c += getchar()
+ yield c.decode('utf-8')
+ while 1:
+ yield None
+ l = lengths[self.c]
+ for i in range(l):
+ yield None
+ c = self.c
+ self.c = ''
+ yield c.decode('utf-8')
+
+# --------------------------------------------------------------------
+# unicode -> keystrokes
+# --------------------------------------------------------------------
+
+
+
+# --------------------------------------------------------------------
+# keystrokes -> commands
+# --------------------------------------------------------------------
Added: pyrepl/branch/pyrepl-rework-n/pyrepl/dfa/unicodesm.py
==============================================================================
--- (empty file)
+++ pyrepl/branch/pyrepl-rework-n/pyrepl/dfa/unicodesm.py Mon Jul 5 16:08:00 2004
@@ -0,0 +1,53 @@
+from pyrepl.dfa.base import StateMachine
+
+class FixedWidthUnicodeSM(StateMachine):
+ def __init__(self, parent, encoding):
+ super(FixedWidthUnicodeSM, self).__init__(parent)
+ self.encoding = encoding
+ self.width = len(u' '.encode(encoding))
+ self.chars = ''
+ self.output = []
+ def push(self, evt):
+ self.chars += evt
+ while len(self.chars) >= self.width:
+ self.output.append(self.chars[:self.width].decode(self.encoding))
+ self.chars = self.chars[self.width:]
+
+# nicked from unicodeobject.c:
+utf8prefix_lengths = [
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 0, 0]
+
+
+class UTF8UnicodeSM(StateMachine):
+ def __init__(self, parent):
+ super(UTF8UnicodeSM, self).__init__(parent)
+ self.chars = ''
+ self.l = 0
+ def push(self, evt):
+ if self.l:
+ self.chars += evt
+ self.l -= 1
+ else:
+ self.chars = evt
+ self.l = utf8prefix_lengths[ord(evt)] - 1
+ if self.l < 0:
+ raise UnicodeError, "invalid utf-8 data"
+ if not self.l:
+ c = self.chars
+ self.chars = ''
+ self.output.append(c.decode('utf-8'))
Added: pyrepl/branch/pyrepl-rework-n/test/unit/test_commandsm.py
==============================================================================
--- (empty file)
+++ pyrepl/branch/pyrepl-rework-n/test/unit/test_commandsm.py Mon Jul 5 16:08:00 2004
@@ -0,0 +1,21 @@
+from pyrepl.dfa.keystrokesm import Keystroke
+from pyrepl.dfa.commandsm import Command, CommandSM
+
+def do_feed(m, data, results):
+ for c in data:
+ m.push(c)
+ for r in results:
+ v = m.get()
+ assert v == r
+
+test_keymap = [('a', 'cmd'),
+ ('\C-a', 'bol')]
+
+def test_basic():
+ m = CommandSM(None, None, test_keymap, None, None)
+ a = Keystroke('a', 'a')
+ do_feed(m, [a], [Command('cmd', [a])])
+ a = Keystroke('\001', '')
+ do_feed(m, [a], [Command('bol', [a])])
+
+
Added: pyrepl/branch/pyrepl-rework-n/test/unit/test_keystrokesm.py
==============================================================================
--- (empty file)
+++ pyrepl/branch/pyrepl-rework-n/test/unit/test_keystrokesm.py Mon Jul 5 16:08:00 2004
@@ -0,0 +1,26 @@
+from pyrepl.dfa.keystrokesm import KeystrokeSM, Keystroke
+
+class TestKeys(object):
+ def translate(self, key):
+ return key
+ def all_keys(self):
+ return [('abc', 'a'),
+ ('abd', 'b')]
+
+def do_feed(m, data, results):
+ for c in data:
+ m.push(c)
+ for r in results:
+ v = m.get()
+ assert v == r
+
+def test_keystrokesm():
+ m = KeystrokeSM(None, TestKeys())
+ do_feed(m, 'ab', [None])
+ do_feed(m, 'c', [Keystroke('a', 'abc')])
+ do_feed(m, 'abd', [Keystroke('b', 'abd')])
+ do_feed(m, 'ab', [None])
+ do_feed(m, 'e', [Keystroke('a', 'a'),
+ Keystroke('b', 'b'),
+ Keystroke('e', 'e')])
+ do_feed(m, 'f', [Keystroke('f', 'f')])
Added: pyrepl/branch/pyrepl-rework-n/test/unit/test_makematch.py
==============================================================================
--- (empty file)
+++ pyrepl/branch/pyrepl-rework-n/test/unit/test_makematch.py Mon Jul 5 16:08:00 2004
@@ -0,0 +1,7 @@
+from pyrepl.dfa.compile import make_match
+
+def test_make_match():
+ s = [('abc', 'a'),
+ ('abd', 'b')]
+ d = make_match(s)
+ assert d == {'a': {'b': {'c': 'a', 'd': 'b'}}}
Added: pyrepl/branch/pyrepl-rework-n/test/unit/test_statemachines.py
==============================================================================
--- (empty file)
+++ pyrepl/branch/pyrepl-rework-n/test/unit/test_statemachines.py Mon Jul 5 16:08:00 2004
@@ -0,0 +1,42 @@
+from pyrepl.dfa.unicodesm import UTF8UnicodeSM
+from pyrepl.dfa.keystrokesm import KeystrokeSM, Keystroke
+from pyrepl.dfa.commandsm import CommandSM, Command
+
+class TestKeys(object):
+ def translate(self, key):
+ return key
+ def all_keys(self):
+ return [('abc', 'a'),
+ ('abd', 'b')]
+ def keynames(self):
+ return ['abc', 'abd']
+
+test_keymap = [('q', 'cmd'),
+ ('\C-a', 'bol'),
+ ('\<abc>', 'keynamed-a'),
+ ('\<abd>', 'keynamed-b'),
+ ]
+
+def test_it():
+ tk = TestKeys()
+ c = CommandSM(None, tk, test_keymap, 'invalid', 'character')
+ k = KeystrokeSM(c, tk)
+ u = UTF8UnicodeSM(k)
+
+ egrave = u'\N{latin small letter e with grave}'
+
+ for char in egrave.encode('utf-8'):
+ u.push_and_go(char)
+
+ v = c.get()
+
+ assert v == Command('character', [Keystroke(egrave, egrave)])
+
+ u.push_and_go('a')
+ u.push_and_go('b')
+ u.push_and_go('c')
+
+ v = c.get()
+ print v
+ assert v == Command('keynamed-a', [Keystroke('abc', 'a')])
+
Added: pyrepl/branch/pyrepl-rework-n/test/unit/test_unicodesm.py
==============================================================================
--- (empty file)
+++ pyrepl/branch/pyrepl-rework-n/test/unit/test_unicodesm.py Mon Jul 5 16:08:00 2004
@@ -0,0 +1,31 @@
+
+def run_test_fixedwidthsm(encoding):
+ from pyrepl.statemachine import FixedWidthUnicodeSM
+ m = FixedWidthUnicodeSM(None, encoding)
+ inpu = u'abc\N{latin small letter i with diaeresis}de'
+ inp = inpu.encode(encoding)
+ for c in inp:
+ m.push(c)
+ for u in inpu:
+ assert u == m.get()
+ assert m.get() is None
+
+def test_utf8sm():
+ from pyrepl.statemachine import UTF8UnicodeSM
+ m = UTF8UnicodeSM(None)
+ inpu = u'abc\N{latin small letter i with diaeresis}de'
+ inp = inpu.encode('utf-8')
+ for c in inp:
+ m.push(c)
+ for u in inpu:
+ assert u == m.get()
+ assert m.get() is None
+
+def test_fixedwidthsm_latin1():
+ run_test_fixedwidthsm('latin1')
+
+def test_fixedwidthsm_utf_16_le():
+ run_test_fixedwidthsm('utf-16-le')
+
+if __name__ == '__main__':
+ test_fixedwidthsm_latin1()
More information about the pyrepl-checkins
mailing list