22import code
33from contextlib import contextmanager
44from functools import partial
5+ from mock import Mock
56import os
67from StringIO import StringIO
78import sys
@@ -18,6 +19,7 @@ def skip(f):
1819
1920from bpython .curtsiesfrontend import repl as curtsiesrepl
2021from bpython .curtsiesfrontend import interpreter
22+ from bpython import autocomplete
2123from bpython import config
2224from bpython import args
2325
@@ -84,6 +86,73 @@ def test_get_last_word_with_prev_line(self):
8486 self .repl .up_one_line ()
8587 self .assertEqual (self .repl .current_line ,'2 3' )
8688
89+
90+ class TestCurtsiesReplTab (unittest .TestCase ):
91+
92+ def setUp (self ):
93+ self .repl = create_repl ()
94+ self .repl .matches_iter = Mock ()
95+ def add_matches (* args , ** kwargs ):
96+ self .repl .matches_iter .matches = ['aaa' , 'aab' , 'aac' ]
97+ self .repl .complete = Mock (side_effect = add_matches ,
98+ return_value = True )
99+
100+ def test_tab_with_no_matches_triggers_completion (self ):
101+ self .repl ._current_line = ' asdf'
102+ self .repl ._cursor_offset = 5
103+ self .repl .matches_iter .matches = []
104+ self .repl .matches_iter .is_cseq .return_value = False
105+ self .repl .matches_iter .cur_line .return_value = (None , None )
106+ self .repl .on_tab ()
107+ self .repl .complete .assert_called_once_with (tab = True )
108+
109+ def test_tab_after_indentation_adds_space (self ):
110+ self .repl ._current_line = ' '
111+ self .repl ._cursor_offset = 4
112+ self .repl .on_tab ()
113+ self .assertEqual (self .repl ._current_line , ' ' )
114+ self .assertEqual (self .repl ._cursor_offset , 8 )
115+
116+ def test_tab_at_beginning_of_line_adds_space (self ):
117+ self .repl ._current_line = ''
118+ self .repl ._cursor_offset = 0
119+ self .repl .on_tab ()
120+ self .assertEqual (self .repl ._current_line , ' ' )
121+ self .assertEqual (self .repl ._cursor_offset , 4 )
122+
123+ def test_tab_with_no_matches_selects_first (self ):
124+ self .repl ._current_line = ' aa'
125+ self .repl ._cursor_offset = 3
126+ self .repl .matches_iter .matches = []
127+ self .repl .matches_iter .is_cseq .return_value = False
128+ self .repl .matches_iter .next .return_value = None
129+ self .repl .matches_iter .cur_line .return_value = (None , None )
130+ self .repl .on_tab ()
131+ self .repl .complete .assert_called_once_with (tab = True )
132+ self .repl .matches_iter .next .assert_called_once_with ()
133+ self .repl .matches_iter .cur_line .assert_called_once_with ()
134+
135+ def test_tab_with_matches_selects_next_match (self ):
136+ self .repl ._current_line = ' aa'
137+ self .repl ._cursor_offset = 3
138+ self .repl .complete ()
139+ self .repl .matches_iter .is_cseq .return_value = False
140+ self .repl .matches_iter .next .return_value = None
141+ self .repl .matches_iter .cur_line .return_value = (None , None )
142+ self .repl .on_tab ()
143+ self .repl .matches_iter .next .assert_called_once_with ()
144+ self .repl .matches_iter .cur_line .assert_called_once_with ()
145+
146+ def test_tab_completes_common_sequence (self ):
147+ self .repl ._current_line = ' a'
148+ self .repl ._cursor_offset = 2
149+ self .repl .matches_iter .matches = ['aaa' , 'aab' , 'aac' ]
150+ self .repl .matches_iter .is_cseq .return_value = True
151+ self .repl .matches_iter .substitute_cseq .return_value = (None , None )
152+ self .repl .on_tab ()
153+ self .repl .matches_iter .substitute_cseq .assert_called_once_with ()
154+
155+
87156@contextmanager # from http://stackoverflow.com/a/17981937/398212 - thanks @rkennedy
88157def captured_output ():
89158 new_out , new_err = StringIO (), StringIO ()
0 commit comments