<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><title>Python: module test.tc_ui</title>
</head><body bgcolor="#f0f0f8">
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
<tr bgcolor="#7799ee">
<td valign=bottom> <br>
<font color="#ffffff" face="helvetica, arial"> <br><big><big><strong><a href="test.html"><font color="#ffffff">test</font></a>.tc_ui</strong></big></big></font></td
><td align=right valign=bottom
><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/home/hut/ranger/test/tc_ui.py">/home/hut/ranger/test/tc_ui.py</a></font></td></pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */# coding=utf-8
# Copyright (C) 2009, 2010 Roman Zimbelmann <romanz@lavabit.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
if __name__ == '__main__': from __init__ import init; init()
from unittest import TestCase, main
from ranger.ext.tree import Tree
from ranger.container.keymap import *
import sys
class PressTestCase(TestCase):
"""Some useful methods for the actual test"""
def _mkpress(self, keybuffer, keymap):
def press(keys):
keybuffer.clear()
match = keybuffer.simulate_press(keys)
self.assertFalse(keybuffer.failure,
"parsing keys '"+keys+"' did fail!")
self.assertTrue(keybuffer.done,
"parsing keys '"+keys+"' did not complete!")
arg = CommandArgs(None, None, keybuffer)
self.assert_(match.function, "No function found! " + \
str(match.__dict__))
return match.function(arg)
return press
def assertPressFails(self, kb, keys):
kb.clear()
kb.simulate_press(keys)
self.assertTrue(kb.failure, "Keypress did not fail as expected")
kb.clear()
def assertPressIncomplete(self, kb, keys):
kb.clear()
kb.simulate_press(keys)
self.assertFalse(kb.failure, "Keypress failed, expected incomplete")
self.assertFalse(kb.done, "Keypress done which was unexpected")
kb.clear()
class Test(PressTestCase):
"""The test cases"""
def test_passive_action(self):
km = KeyMap()
directions = KeyMap()
kb = KeyBuffer(km, directions)
def n(value):
"""return n or value"""
def fnc(arg=None):
if arg is None or arg.n is None:
return value
return arg.n
return fnc
km.map('ppp', n(5))
km.map('pp<bg>', n(8))
km.map('pp<dir>', n(2))
directions.map('j', dir=Direction(down=1))
press = self._mkpress(kb, km)
self.assertEqual(5, press('ppp'))
self.assertEqual(3, press('3ppp'))
self.assertEqual(2, press('ppj'))
kb.clear()
match = kb.simulate_press('pp')
args = CommandArgs(0, 0, kb)
self.assert_(match)
self.assert_(match.function)
self.assertEqual(8, match.function(args))
def test_map_collision(self):
def add_dirs(arg):
return sum(dir.down for dir in arg.directions)
def return5(_):
return 5
directions = KeyMap()
directions.map('gg', dir=Direction(down=1))
km = KeyMap()
km.map('gh', return5)
km.map('agh', return5)
km.map('a<dir>', add_dirs)
kb = KeyBuffer(km, directions)
press = self._mkpress(kb, km)
self.assertEqual(5, press('gh'))
self.assertEqual(5, press('agh'))
# self.assertPressFails(kb, 'agh')
self.assertEqual(1, press('agg'))
def test_translate_keys(self):
def test(string, *args):
if not args:
args = (string, )
self.assertEqual(ordtuple(*args), tuple(translate_keys(string)))
def ordtuple(*args):
lst = []
for arg in args:
if isinstance(arg, str):
lst.extend(ord(c) for c in arg)
else:
lst.append(arg)
return tuple(lst)
test('k')
test('kj')
test('k<dir>', 'k', DIRKEY)
test('k<ANY>z<any>', 'k', ANYKEY, 'z', ANYKEY)
test('k<anY>z<dir>', 'k', ANYKEY, 'z', DIRKEY)
test('<cr>', "\n")
test('<tab><tab><cr>', "\t\t\n")
test('<')
test('>')
test('<C-a>', 1)
test('<C-b>', 2)
for i in range(1, 26):
test('<C-' + chr(i+ord('a')-1) + '>', i)
test('k<a')
test('k<anz>')
test('k<a<nz>')
test('k<a<nz>')
test('k<a<>nz>')
test('>nz>')
def test_alias(self):
def add_dirs(arg):
return sum(dir.down for dir in arg.directions)
def return5(_):
return 5
directions = KeyMap()
directions.map('j', dir=Direction(down=1))
directions.map('k', dir=Direction(down=-1))
directions.map('<CR>', alias='j')
directions.map('@', alias='<CR>')
base = KeyMap()
base.map('a<dir>', add_dirs)
base.map('b<dir>', add_dirs)
base.map('x<dir>x<dir>', add_dirs)
base.map('f', return5)
base.map('yy', alias='y')
base.map('!', alias='!')
other = KeyMap()
other.map('b<dir>b<dir>', alias='x<dir>x<dir>')
other.map('c<dir>', add_dirs)
other.map('g', alias='f')
km = base.merge(other, copy=True)
kb = KeyBuffer(km, directions)
press = self._mkpress(kb, km)
self.assertEqual(1, press('aj'))
self.assertEqual(2, press('bjbj'))
self.assertEqual(1, press('cj'))
self.assertEqual(1, press('c<CR>'))
self.assertEqual(5, press('f'))
self.assertEqual(5, press('g'))
self.assertEqual(press('c<CR>'), press('c@'))
self.assertEqual(press('c<CR>'), press('c@'))
self.assertEqual(press('c<CR>'), press('c@'))
for n in range(1, 50):
self.assertPressIncomplete(kb, 'y' * n)
for n in range(1, 5):
self.assertPressFails(kb, '!' * n)
def test_tree(self):
t = Tree()
t.set('abcd', "Yes")
self.assertEqual("Yes", t.traverse('abcd'))
self.assertRaises(KeyError, t.traverse, 'abcde')
self.assertRaises(KeyError, t.traverse, 'xyz')
self.assert_(isinstance(t.traverse('abc'), Tree))
t2 = Tree()
self.assertRaises(KeyError, t2.set, 'axy', "Lol", force=False)
t2.set('axx', 'ololol')
t2.set('axyy', "Lol")
self.assertEqual("Yes", t.traverse('abcd'))
self.assertRaises(KeyError, t2.traverse, 'abcd')
self.assertEqual("Lol", t2.traverse('axyy'))
self.assertEqual("ololol", t2.traverse('axx'))
t2.unset('axyy')
self.assertEqual("ololol", t2.traverse('axx'))
self.assertRaises(KeyError, t2.traverse, 'axyy')
self.assertRaises(KeyError, t2.traverse, 'axy')
t2.unset('a')
self.assertRaises(KeyError, t2.traverse, 'abcd')
self.assertRaises(KeyError, t2.traverse, 'a')
self.assert_(t2.empty())
def test_merge_trees(self):
def makeTreeA():
t = Tree()
t.set('aaaX', 1)
t.set('aaaY', 2)
t.set('aaaZ', 3)
t.set('bbbA', 11)
t.set('bbbB', 12)
t.set('bbbC', 13)
t.set('bbbD', 14)
t.set('bP', 21)
t.set('bQ', 22)
return t
def makeTreeB():
u = Tree()
u.set('aaaX', 0)
u.set('bbbC', 'Yes')
u.set('bbbD', None)
u.set('bbbE', 15)
u.set('bbbF', 16)
u.set('bQ', 22)
u.set('bR', 23)
u.set('ffff', 1337)
return u
# test 1
t = Tree('a')
u = Tree('b')
merged = t.merge(u, copy=True)
self.assertEqual('b', merged._tree)
# test 2
t = Tree('a')
u = makeTreeA()
merged = t.merge(u, copy=True)
self.assertEqual(u._tree, merged._tree)
# test 3
t = makeTreeA()
u = makeTreeB()
v = t.merge(u, copy=True)
self.assertEqual(0, v['aaaX'])
self.assertEqual(2, v['aaaY'])
self.assertEqual(3, v['aaaZ'])
self.assertEqual(11, v['bbbA'])
self.assertEqual('Yes', v['bbbC'])
self.assertEqual(None, v['bbbD'])
self.assertEqual(15, v['bbbE'])
self.assertEqual(16, v['bbbF'])
self.assertRaises(KeyError, t.__getitem__, 'bbbG')
self.assertEqual(21, v['bP'])
self.assertEqual(22, v['bQ'])
self.assertEqual(23, v['bR'])
self.assertEqual(1337, v['ffff'])
# merge shouldn't be destructive
self.assertEqual(makeTreeA()._tree, t._tree)
self.assertEqual(makeTreeB()._tree, u._tree)
v['fff'].replace('Lolz')
self.assertEqual('Lolz', v['fff'])
v['aaa'].replace('Very bad')
v.plow('qqqqqqq').replace('eww.')
self.assertEqual(makeTreeA()._tree, t._tree)
self.assertEqual(makeTreeB()._tree, u._tree)
def test_add(self):
c = KeyMap()
c.map('aa', 'b', lambda *_: 'lolz')
self.assert_(c['aa'].function(), 'lolz')
@c.map('a', 'c')
def test():
return 5
self.assert_(c['b'].function(), 'lolz')
self.assert_(c['c'].function(), 5)
self.assert_(c['a'].function(), 5)
def test_quantifier(self):
km = KeyMap()
directions = KeyMap()
kb = KeyBuffer(km, directions)
def n(value):
"""return n or value"""
def fnc(arg=None):
if arg is None or arg.n is None:
return value
return arg.n
return fnc
km.map('p', n(5))
press = self._mkpress(kb, km)
self.assertEqual(5, press('p'))
self.assertEqual(3, press('3p'))
self.assertEqual(6223, press('6223p'))
def test_direction(self):
km = KeyMap()
directions = KeyMap()
kb = KeyBuffer(km, directions)
directions.map('j', dir=Direction(down=1))
directions.map('k', dir=Direction(down=-1))
def nd(arg):
""" n * direction """
n = arg.n is None and 1 or arg.n
dir = arg.direction is None and Direction(down=1) \
or arg.direction
return n * dir.down
km.map('d<dir>', nd)
km.map('dd', func=nd)
press = self._mkpress(kb, km)
self.assertPressIncomplete(kb, 'd')
self.assertEqual( 1, press('dj'))
self.assertEqual( 3, press('3ddj'))
self.assertEqual( 15, press('3d5j'))
self.assertEqual(-15, press('3d5k'))
# supporting this kind of key combination would be too confusing:
# self.assertEqual( 15, press('3d5d'))
self.assertEqual( 3, press('3dd'))
self.assertEqual( 33, press('33dd'))
self.assertEqual( 1, press('dd'))
km.map('x<dir>', nd)
km.map('xxxx', func=nd)
self.assertEqual(1, press('xxxxj'))
self.assertEqual(1, press('xxxxjsomeinvalitchars'))
# these combinations should break:
self.assertPressFails(kb, 'xxxj')
self.assertPressFails(kb, 'xxj')
self.assertPressFails(kb, 'xxkldfjalksdjklsfsldkj')
self.assertPressFails(kb, 'xyj')
self.assertPressIncomplete(kb, 'x') # direction missing
def test_any_key(self):
km = KeyMap()
directions = KeyMap()
kb = KeyBuffer(km, directions)
directions.map('j', dir=Direction(down=1))
directions.map('k', dir=Direction(down=-1))
directions.map('g<any>', dir=Direction(down=-1))
def cat(arg):
n = arg.n is None and 1 or arg.n
return ''.join(chr(c) for c in arg.matches) * n
km.map('return<any>', cat)
km.map('cat4<any><any><any><any>', cat)
km.map('foo<dir><any>', cat)
press = self._mkpress(kb, km)
self.assertEqual('x', press('returnx'))
self.assertEqual('abcd', press('cat4abcd'))
self.assertEqual('abcdabcd', press('2cat4abcd'))
self.assertEqual('55555', press('5return5'))
self.assertEqual('x', press('foojx'))
self.assertPressFails(kb, 'fooggx') # ANYKEY forbidden in DIRECTION
km.map('<any>', lambda _: Ellipsis)
self.assertEqual('x', press('returnx'))
self.assertEqual('abcd', press('cat4abcd'))
self.assertEqual(Ellipsis, press('2cat4abcd'))
self.assertEqual(Ellipsis, press('5return5'))
self.assertEqual(Ellipsis, press('g'))
self.assertEqual(Ellipsis, press('ß'))
self.assertEqual(Ellipsis, press('ア'))
self.assertEqual(Ellipsis, press('9'))
def test_multiple_directions(self):
km = KeyMap()
directions = KeyMap()
kb = KeyBuffer(km, directions)
directions.map('j', dir=Direction(down=1))
directions.map('k', dir=Direction(down=-1))
def add_dirs(arg):
return sum(dir.down for dir in arg.directions)
km.map('x<dir>y<dir>', add_dirs)
km.map('four<dir><dir><dir><dir>', add_dirs)
press = self._mkpress(kb, km)
self.assertEqual(2, press('xjyj'))
self.assertEqual(0, press('fourjkkj'))
self.assertEqual(2, press('four2j4k2j2j'))
self.assertEqual(10, press('four1j2j3j4j'))
self.assertEqual(10, press('four1j2j3j4jafslkdfjkldj'))
def test_corruptions(self):
km = KeyMap()
directions = KeyMap()
kb = KeyBuffer(km, directions)
press = self._mkpress(kb, km)
directions.map('j', dir=Direction(down=1))
directions.map('k', dir=Direction(down=-1))
km.map('xxx', lambda _: 1)
self.assertEqual(1, press('xxx'))
# corrupt the tree
tup = tuple(translate_keys('xxx'))
x = ord('x')
km._tree[x][x][x] = "Boo"
self.assertPressFails(kb, 'xxy')
self.assertPressFails(kb, 'xzy')
self.assertPressIncomplete(kb, 'xx')
self.assertPressIncomplete(kb, 'x')
if not sys.flags.optimize:
self.assertRaises(AssertionError, kb.simulate_press, 'xxx')
kb.clear()
def test_directions_as_functions(self):
km = KeyMap()
directions = KeyMap()
kb = KeyBuffer(km, directions)
press = self._mkpress(kb, km)
def move(arg):
return arg.directi