# encoding: utf-8
from bpython.curtsiesfrontend.manual_readline import \
left_arrow, right_arrow, beginning_of_line, forward_word, back_word, \
end_of_line, delete, last_word_pos, backspace, delete_from_cursor_back, \
delete_from_cursor_forward, delete_rest_of_word, delete_word_to_cursor, \
transpose_character_before_cursor, UnconfiguredEdits, \
delete_word_from_cursor_back
from bpython.test import unittest
class TestManualReadline(unittest.TestCase):
def setUp(self):
self._line = "this is my test string"
def tearDown(self):
pass
def test_left_arrow_at_zero(self):
pos = 0
expected = (pos, self._line)
result = left_arrow(pos, self._line)
self.assertEqual(expected, result)
def test_left_arrow_at_non_zero(self):
for i in range(1, len(self._line)):
expected = (i-1, self._line)
result = left_arrow(i, self._line)
self.assertEqual(expected, result)
def test_right_arrow_at_end(self):
pos = len(self._line)
expected = (pos, self._line)
result = right_arrow(pos, self._line)
self.assertEqual(expected, result)
def test_right_arrow_at_non_end(self):
for i in range(len(self._line) - 1):
expected = (i + 1, self._line)
result = right_arrow(i, self._line)
self.assertEqual(expected, result)
def test_beginning_of_line(self):
expected = (0, self._line)
for i in range(len(self._line)):
result = beginning_of_line(i, self._line)
self.assertEqual(expected, result)
def test_end_of_line(self):
expected = (len(self._line), self._line)
for i in range(len(self._line)):
result = end_of_line(i, self._line)
self.assertEqual(expected, result)
def test_forward_word(self):
line = "going from here to_here"
start_pos = 11
next_word_pos = 15
expected = (next_word_pos, line)
result = forward_word(start_pos, line)
self.assertEqual(expected, result)
start_pos = 15
next_word_pos = 23
expected = (next_word_pos, line)
result = forward_word(start_pos, line)
self.assertEqual(expected, result)
def test_forward_word_tabs(self):
line = "going from here to_here"
start_pos = 11
next_word_pos = 15
expected = (next_word_pos, line)
result = forward_word(start_pos, line)
self.assertEqual(expected, result)
start_pos = 15
next_word_pos = 28
expected = (next_word_pos, line)
result = forward_word(start_pos, line)
self.assertEqual(expected, result)
def test_forward_word_end(self):
line = "going from here to_here"
start_pos = 16
next_word_pos = 23
expected = (next_word_pos, line)
result = forward_word(start_pos, line)
self.assertEqual(expected, result)
start_pos = 22
next_word_pos = 23
expected = (next_word_pos, line)
result = forward_word(start_pos, line)
self.assertEqual(expected, result)
start_pos = 23
next_word_pos = 23
expected = (next_word_pos, line)
result = forward_word(start_pos, line)
self.assertEqual(expected, result)
def test_forward_word_empty(self):
line = ""
start_pos = 0
next_word_pos = 0
expected = (next_word_pos, line)
result = forward_word(start_pos, line)
self.assertEqual(expected, result)
def test_back_word(self):
line = "going to here from_here"
start_pos = 14
prev_word_pos = 9
self.assertEqual(line[start_pos], 'f')
self.assertEqual(line[prev_word_pos], 'h')
expected = (prev_word_pos, line)
result = back_word(start_pos, line)
self.assertEqual(expected, result)
def test_last_word_pos(self):
line = "a word"
expected = 2
result = last_word_pos(line)
self.assertEqual(expected, result)
def test_last_word_pos_single_word(self):
line = "word"
expected = 0
result = last_word_pos(line)
self.assertEqual(expected, result)
def test_delete(self):
line = "deletion line"
pos = 3
expected = (3, "deltion line")
result = delete(pos, line)
self.assertEqual(expected, result)
def test_delete_from_cursor_back(self):
line = "everything before this will be deleted"
expected = (0, "this will be deleted")
result = delete_from_cursor_back(line.find("this"), line)
self.assertEqual(expected, result)
def test_delete_from_cursor_forward(self):
line = "everything after this will be deleted"
pos = line.find("this")
expected = (pos, "everything after ")
result = delete_from_cursor_forward(line.find("this"), line)[:-1]
self.assertEqual(expected, result)
self.assertEqual(delete_from_cursor_forward(0, ''), (0, '', ''))
def test_delete_rest_of_word(self):
self.try_stages_kill([
'z|s;df asdf d s;a;a',
'z|;df asdf d s;a;a',
'z| asdf d s;a;a',
'z| d s;a;a',
'z| s;a;a',
'z|;a;a',
'z|;a',
'z|',
'z|'],
delete_rest_of_word)
def test_delete_word_to_cursor(self):
self.try_stages_kill([
' a;d sdf ;a;s;d; fjksald|a',
' a;d sdf ;a;s;d; |a',
' a;d sdf |a',
' a;d |a',
' |a',
'|a',
'|a'],
delete_word_to_cursor)
def test_yank_prev_killed_text(self):
pass
def test_yank_prev_prev_killed_text(self):
pass
def try_stages(self, strings, func):
if not all('|' in s for s in strings):
raise ValueError("Need to use '|' to specify cursor")
stages = [(s.index('|'), s.replace('|', '')) for s in strings]
for (initial_pos, initial), (final_pos, final) in zip(stages[:-1],
stages[1:]):
self.assertEqual(func(initial_pos, initial), (final_pos, final))
def try_stages_kill(self, strings, func):
if not all('|' in s for s in strings):
raise ValueError("Need to use '|' to specify cursor")
stages = [(s.index('|'), s.replace('|', '')) for s in strings]
for (initial_pos, initial), (final_pos, final) in zip(stages[:-1],
stages[1:]):
self.assertEqual(func(initial_pos, initial)[:-1],
(final_pos, final))
def test_transpose_character_before_cursor(self):
self.try_stages(["as|df asdf",
"ads|f asdf",
"adfs| asdf",
"adf s|asdf",
"adf as|sdf"], transpose_character_before_cursor)
def test_transpose_empty_line(self):
self.assertEqual(transpose_character_before_cursor(0, ''),
(0, ''))
def test_transpose_first_character(self):
self.assertEqual(transpose_character_before_cursor(0, 'a'),
(0, 'a'))
self.assertEqual(transpose_character_before_cursor(0, 'as'),
(0, 'as'))
def test_transpose_end_of_line(self):
self.assertEqual(transpose_character_before_cursor(1, 'a'),
(1, 'a'))
self.assertEqual(transpose_character_before_cursor(2, 'as'),
(2, 'sa'))
def test_transpose_word_before_cursor(self):
pass
def test_backspace(self):
self.assertEqual(backspace(2, 'as'), (1, 'a'))
self.assertEqual(backspace(3, 'as '), (2, 'as'))
def test_delete_word_from_cursor_back(self):
self.try_stages_kill([
"asd;fljk asd;lfjas;dlkfj asdlk jasdf;ljk|",
"asd;fljk asd;lfjas;dlkfj asdlk jasdf;|",
"asd;fljk asd;lfjas;dlkfj asdlk |",
"asd;fljk asd;lfjas;dlkfj |",
"asd;fljk asd;lfjas;|",
"asd;fljk asd;|",
"asd;fljk |",
"asd;|",
"|",
"|"],
delete_word_from_cursor_back)
self.try_stages_kill([
" (( asdf |",
" (( |",
"|"],
delete_word_from_cursor_back)
class TestEdits(unittest.TestCase):
def setUp(self):
self.edits = UnconfiguredEdits()
def test_seq(self):
def f(cursor_offset, line):
return ('hi', 2)
self.edits.add('a', f)
self.assertIn('a', self.edits)
self.assertEqual(self.edits['a'], f)
self.assertEqual(self.edits.call('a', cursor_offset=3, line='hello'),
('hi', 2))
with self.assertRaises(KeyError):
self.edits['b']
with self.assertRaises(KeyError):
self.edits.call('b')
def test_functions_with_bad_signatures(self):
def f(something):
return (1, 2)
with self.assertRaises(TypeError):
self.edits.add('a', f)
def g(cursor_offset, line, something, something_else):
return (1, 2)
with self.assertRaises(TypeError):
self.edits.add('a', g)
def test_functions_with_bad_return_values(self):
def f(cursor_offset, line):
return ('hi',)
with self.assertRaises(ValueError):
self.edits.add('a', f)
def g(cursor_offset, line):
return ('hi', 1, 2, 3)
with self.assertRaises(ValueError):
self.edits.add('b', g)
def test_config(self):
def f(cursor_offset, line):
return ('hi', 2)
def g(cursor_offset, line):
return ('hey', 3)
self.edits.add_config_attr('att', f)
self.assertNotIn('att', self.edits)
class config(object):
att = 'c'
key_dispatch = {'c': 'c'}
configured_edits = self.edits.mapping_with_config(config, key_dispatch)
self.assertTrue(configured_edits.__contains__, 'c')
self.assertNotIn('c', self.edits)
with self.assertRaises(NotImplementedError):
configured_edits.add_config_attr('att2', g)
with self.assertRaises(NotImplementedError):
configured_edits.add('d', g)
self.assertEqual(configured_edits.call('c', cursor_offset=5,
line='asfd'),
('hi', 2))
if __name__ == '__main__':
unittest.main()