Skip to content

Commit f10ca74

Browse files
committed
boxes: Support typeahead for stream name in recipient box.
Note that this does not work correctly when the search text includes whitespaces, due to lack of urwid-readline support. Test added.
1 parent e204e43 commit f10ca74

File tree

2 files changed

+69
-0
lines changed

2 files changed

+69
-0
lines changed

tests/ui_tools/test_boxes.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,53 @@ def test_generic_autocomplete_emojis(self, write_box, text,
251251
typeahead_string = write_box.generic_autocomplete(text, state)
252252
assert typeahead_string == required_typeahead
253253

254+
@pytest.mark.parametrize(['text', 'state', 'to_pin', 'matching_streams'], [
255+
('', 1, [], ['Secret stream', 'Some general stream',
256+
'Stream 1', 'Stream 2']),
257+
('', 1, [['Stream 2']], ['Stream 2', 'Secret stream',
258+
'Some general stream', 'Stream 1']),
259+
('St', 1, [], ['Stream 1', 'Stream 2', 'Secret stream',
260+
'Some general stream']),
261+
('St', 1, [['Stream 2']], ['Stream 2', 'Stream 1',
262+
'Secret stream', 'Some general stream']),
263+
], ids=[
264+
'no_search_text',
265+
'no_search_text_with_pinned_stream',
266+
'single_word_search_text',
267+
'single_word_search_text_with_pinned_stream',
268+
])
269+
def test__stream_box_autocomplete(self, mocker, write_box, text, state,
270+
to_pin, matching_streams):
271+
for stream in to_pin:
272+
write_box.view.unpinned_streams.remove(stream)
273+
write_box.view.pinned_streams = to_pin
274+
_process_typeaheads = mocker.patch(BOXES
275+
+ '.WriteBox._process_typeaheads')
276+
277+
write_box._stream_box_autocomplete(text, state)
278+
279+
_process_typeaheads.assert_called_once_with(matching_streams, state,
280+
matching_streams)
281+
282+
@pytest.mark.parametrize('text, expected_text', [
283+
('Som', 'Some general stream'),
284+
pytest.param('Some gen', 'Some general stream',
285+
marks=pytest.mark.xfail(
286+
reason="Lacking urwid-readline support")),
287+
])
288+
def test__stream_box_autocomplete_with_spaces(self, mocker, write_box,
289+
text, expected_text):
290+
write_box.stream_box_view(1000)
291+
write_box.contents[0][0][0].set_edit_text(text)
292+
write_box.contents[0][0][0].set_edit_pos(len(text))
293+
write_box.focus_position = 0
294+
write_box.contents[0][0].focus_col = 0
295+
size = (20,)
296+
297+
write_box.keypress(size, keys_for_command('AUTOCOMPLETE').pop())
298+
299+
assert write_box.contents[0][0][0].edit_text == expected_text
300+
254301
@pytest.mark.parametrize(['suggestions', 'state', 'expected_state',
255302
'expected_typeahead', 'is_truncated'], [
256303
(['zero', 'one', 'two'], 1, 1, '*one*', False),

zulipterminal/ui_tools/boxes.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,11 @@ def stream_box_view(self, stream_id: int, caption: str='', title: str='',
8888
caption="Stream: ",
8989
edit_text=caption
9090
)
91+
self.stream_write_box.enable_autocomplete(
92+
func=self._stream_box_autocomplete,
93+
key=keys_for_command('AUTOCOMPLETE').pop(),
94+
key_reverse=keys_for_command('AUTOCOMPLETE_REVERSE').pop()
95+
)
9196
self.title_write_box = ReadlineEdit(caption="Topic: ",
9297
edit_text=title)
9398

@@ -109,6 +114,23 @@ def stream_box_view(self, stream_id: int, caption: str='', title: str='',
109114
]
110115
self.contents = write_box
111116

117+
def _stream_box_autocomplete(self, text: str, state: Optional[int]
118+
) -> Optional[str]:
119+
streams_list = self.view.pinned_streams + self.view.unpinned_streams
120+
streams = [stream[0]
121+
for stream in streams_list]
122+
123+
# match_streams takes stream names and typeaheads,
124+
# but we don't have typeaheads here.
125+
# FIXME: Refactor match_stream
126+
stream_data = list(zip(streams, streams))
127+
matched_streams = match_stream(stream_data, text,
128+
self.view.pinned_streams)
129+
130+
# matched_streams[0] and matched_streams[1] contains the same data.
131+
return self._process_typeaheads(matched_streams[0], state,
132+
matched_streams[1])
133+
112134
def generic_autocomplete(self, text: str, state: Optional[int]
113135
) -> Optional[str]:
114136
autocomplete_map = OrderedDict([

0 commit comments

Comments
 (0)