Skip to content

Commit 7a9cb8f

Browse files
committed
boxes: Use user_ids in autocomplete for ambiguous user mentions.
Prior to this commit, user mentions through autocomplete used only names in the typeahead. This commit appends `user_id`s to all the multiple instances of the same name to use the **Name|User_id** format of user mentions. This is done by using collections.Counter to check the count of each user name in the users list. The user_id is appended to names that have a count greater than 1. The appended user_id would serve as a distinction between users having the same name. Tests added and updated. Fixes #151.
1 parent 01d63b1 commit 7a9cb8f

File tree

2 files changed

+88
-15
lines changed

2 files changed

+88
-15
lines changed

tests/ui_tools/test_boxes.py

Lines changed: 75 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -221,19 +221,19 @@ def test_generic_autocomplete_set_footer(
221221
("@Human", 0, "@**Human Myself**"),
222222
("@Human", 1, "@**Human 1**"),
223223
("@Human", 2, "@**Human 2**"),
224-
("@Human", 3, "@**Human Duplicate**"),
225-
("@Human", 4, "@**Human Duplicate**"),
226-
("@Human", -1, "@**Human Duplicate**"),
227-
("@Human", -2, "@**Human Duplicate**"),
224+
("@Human", 3, "@**Human Duplicate|13**"),
225+
("@Human", 4, "@**Human Duplicate|14**"),
226+
("@Human", -1, "@**Human Duplicate|14**"),
227+
("@Human", -2, "@**Human Duplicate|13**"),
228228
("@Human", -3, "@**Human 2**"),
229229
("@Human", -4, "@**Human 1**"),
230230
("@Human", -5, "@**Human Myself**"),
231231
("@Human", -6, None),
232232
("@_Human", 0, "@_**Human Myself**"),
233233
("@_Human", 1, "@_**Human 1**"),
234234
("@_Human", 2, "@_**Human 2**"),
235-
("@_Human", 3, "@_**Human Duplicate**"),
236-
("@_Human", 4, "@_**Human Duplicate**"),
235+
("@_Human", 3, "@_**Human Duplicate|13**"),
236+
("@_Human", 4, "@_**Human Duplicate|14**"),
237237
("@H", 1, "@**Human 1**"),
238238
("@Hu", 1, "@**Human 1**"),
239239
("@Hum", 1, "@**Human 1**"),
@@ -260,8 +260,8 @@ def test_generic_autocomplete_set_footer(
260260
("@", 0, "@**Human Myself**"),
261261
("@", 1, "@**Human 1**"),
262262
("@", 2, "@**Human 2**"),
263-
("@", 3, "@**Human Duplicate**"),
264-
("@", 4, "@**Human Duplicate**"),
263+
("@", 3, "@**Human Duplicate|13**"),
264+
("@", 4, "@**Human Duplicate|14**"),
265265
("@", 5, "@*Group 1*"),
266266
("@", 6, "@*Group 2*"),
267267
("@", 7, "@*Group 3*"),
@@ -272,8 +272,8 @@ def test_generic_autocomplete_set_footer(
272272
("@**", 0, "@**Human Myself**"),
273273
("@**", 1, "@**Human 1**"),
274274
("@**", 2, "@**Human 2**"),
275-
("@", 3, "@**Human Duplicate**"),
276-
("@", 4, "@**Human Duplicate**"),
275+
("@", 3, "@**Human Duplicate|13**"),
276+
("@", 4, "@**Human Duplicate|14**"),
277277
("@**", 5, None), # Reached last match
278278
("@**", 6, None), # Beyond end
279279
# Expected sequence of autocompletes from '@*' (only groups)
@@ -287,11 +287,11 @@ def test_generic_autocomplete_set_footer(
287287
("@_", 0, "@_**Human Myself**"), # NOTE: No silent group mention
288288
("@_", 1, "@_**Human 1**"),
289289
("@_", 2, "@_**Human 2**"),
290-
("@_", 3, "@_**Human Duplicate**"),
291-
("@_", 4, "@_**Human Duplicate**"),
290+
("@_", 3, "@_**Human Duplicate|13**"),
291+
("@_", 4, "@_**Human Duplicate|14**"),
292292
("@_", 5, None), # Reached last match
293293
("@_", 6, None), # Beyond end
294-
("@_", -1, "@_**Human Duplicate**"),
294+
("@_", -1, "@_**Human Duplicate|14**"),
295295
# Complex autocomplete prefixes.
296296
("(@H", 0, "(@**Human Myself**"),
297297
("(@H", 1, "(@**Human 1**"),
@@ -340,6 +340,68 @@ def test_generic_autocomplete_mentions_subscribers(
340340
typeahead_string = write_box.generic_autocomplete(text, state)
341341
assert typeahead_string == required_typeahead
342342

343+
@pytest.mark.parametrize(
344+
"text",
345+
[
346+
prefix + "Human"[: index + 1]
347+
for index in range(len("Human"))
348+
for prefix in ["@", "@**"]
349+
]
350+
+ ["@**"],
351+
)
352+
def test_generic_autocomplete_user_mentions(self, write_box, text, mocker, state=1):
353+
_process_typeaheads = mocker.patch(BOXES + ".WriteBox._process_typeaheads")
354+
355+
matching_users = [
356+
"Human Myself",
357+
"Human 1",
358+
"Human 2",
359+
"Human Duplicate",
360+
"Human Duplicate",
361+
]
362+
distinct_matching_users = [
363+
"@**Human Myself**",
364+
"@**Human 1**",
365+
"@**Human 2**",
366+
"@**Human Duplicate|13**",
367+
"@**Human Duplicate|14**",
368+
]
369+
370+
write_box.generic_autocomplete(text, state)
371+
372+
_process_typeaheads.assert_called_once_with(
373+
distinct_matching_users, state, matching_users
374+
)
375+
376+
@pytest.mark.parametrize(
377+
"text", ["@_" + "Human"[:index] for index in range(len("Human") + 1)]
378+
)
379+
def test_generic_autocomplete_silent_user_mentions(
380+
self, write_box, text, mocker, state=1
381+
):
382+
_process_typeaheads = mocker.patch(BOXES + ".WriteBox._process_typeaheads")
383+
384+
matching_users = [
385+
"Human Myself",
386+
"Human 1",
387+
"Human 2",
388+
"Human Duplicate",
389+
"Human Duplicate",
390+
]
391+
distinct_matching_users = [
392+
"@_**Human Myself**",
393+
"@_**Human 1**",
394+
"@_**Human 2**",
395+
"@_**Human Duplicate|13**",
396+
"@_**Human Duplicate|14**",
397+
]
398+
399+
write_box.generic_autocomplete(text, state)
400+
401+
_process_typeaheads.assert_called_once_with(
402+
distinct_matching_users, state, matching_users
403+
)
404+
343405
@pytest.mark.parametrize(
344406
"text, state, required_typeahead, to_pin",
345407
[

zulipterminal/ui_tools/boxes.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import re
22
import typing
33
import unicodedata
4-
from collections import OrderedDict, defaultdict
4+
from collections import Counter, OrderedDict, defaultdict
55
from datetime import date, datetime, timedelta
66
from sys import platform
77
from time import sleep, time
@@ -457,12 +457,23 @@ def autocomplete_users(
457457
)
458458

459459
user_names = [user["full_name"] for user in sorted_matching_users]
460+
461+
user_names_counter = Counter(user_names)
462+
463+
# Append user_id's to users with the same names.
464+
user_names_with_distinct_duplicates = [
465+
f"{user['full_name']}|{user['user_id']}"
466+
if user_names_counter[user["full_name"]] > 1
467+
else user["full_name"]
468+
for user in sorted_matching_users
469+
]
470+
460471
extra_prefix = "{}{}".format(
461472
"*" if prefix_string[-1] != "*" else "",
462473
"*" if prefix_string[-2:] != "**" else "",
463474
)
464475
user_typeahead = format_string(
465-
user_names, prefix_string + extra_prefix + "{}**"
476+
user_names_with_distinct_duplicates, prefix_string + extra_prefix + "{}**"
466477
)
467478

468479
return user_typeahead, user_names

0 commit comments

Comments
 (0)