1
0
mirror of https://github.com/profanity-im/profanity.git synced 2024-12-04 14:46:46 -05:00

Implement substring autocompletion for /msg

People with huge contact lists most likely happen to have contacts starting with popular names more often.
They can use /msg Arthur to find the correct person.

But if they have 50 Arthurs it will take a while. Using the surname might be faster. So a substring search of /msg Clarke<tab> will be faster.

Fix https://github.com/profanity-im/profanity/issues/1984
This commit is contained in:
Michael Vetter 2024-06-20 16:24:25 +02:00
parent 4d9852a76a
commit 8ce8f8e6dc
5 changed files with 43 additions and 11 deletions

View File

@ -2084,7 +2084,7 @@ _cmd_ac_complete_params(ProfWin* window, const char* const input, gboolean previ
// Remove quote character before and after names when doing autocomplete
char* unquoted = strip_arg_quotes(input);
for (int i = 0; i < ARRAY_SIZE(contact_choices); i++) {
result = autocomplete_param_with_func(unquoted, contact_choices[i], roster_contact_autocomplete, previous, NULL);
result = autocomplete_param_with_func(unquoted, contact_choices[i], roster_contact_autocomplete_substring, previous, NULL);
if (result) {
free(unquoted);
return result;

View File

@ -57,7 +57,7 @@ struct autocomplete_t
gchar* search_str;
};
static gchar* _search(Autocomplete ac, GList* curr, gboolean quote, search_direction direction);
static gchar* _search(Autocomplete ac, GList* curr, gboolean quote, search_direction direction, gboolean substring);
Autocomplete
autocomplete_new(void)
@ -245,7 +245,7 @@ autocomplete_contains(Autocomplete ac, const char* value)
}
gchar*
autocomplete_complete(Autocomplete ac, const gchar* search_str, gboolean quote, gboolean previous)
_autocomplete_complete_internal(Autocomplete ac, const gchar* search_str, gboolean quote, gboolean previous, gboolean substring)
{
gchar* found = NULL;
@ -266,7 +266,7 @@ autocomplete_complete(Autocomplete ac, const gchar* search_str, gboolean quote,
}
ac->search_str = strdup(search_str);
found = _search(ac, ac->items, quote, NEXT);
found = _search(ac, ac->items, quote, NEXT, substring);
return found;
@ -274,13 +274,13 @@ autocomplete_complete(Autocomplete ac, const gchar* search_str, gboolean quote,
} else {
if (previous) {
// search from here-1 to beginning
found = _search(ac, g_list_previous(ac->last_found), quote, PREVIOUS);
found = _search(ac, g_list_previous(ac->last_found), quote, PREVIOUS, substring);
if (found) {
return found;
}
} else {
// search from here+1 to end
found = _search(ac, g_list_next(ac->last_found), quote, NEXT);
found = _search(ac, g_list_next(ac->last_found), quote, NEXT, substring);
if (found) {
return found;
}
@ -288,13 +288,13 @@ autocomplete_complete(Autocomplete ac, const gchar* search_str, gboolean quote,
if (previous) {
// search from end
found = _search(ac, g_list_last(ac->items), quote, PREVIOUS);
found = _search(ac, g_list_last(ac->items), quote, PREVIOUS, substring);
if (found) {
return found;
}
} else {
// search from beginning
found = _search(ac, ac->items, quote, NEXT);
found = _search(ac, ac->items, quote, NEXT, substring);
if (found) {
return found;
}
@ -307,6 +307,18 @@ autocomplete_complete(Autocomplete ac, const gchar* search_str, gboolean quote,
}
}
gchar*
autocomplete_complete(Autocomplete ac, const gchar* search_str, gboolean quote, gboolean previous)
{
return _autocomplete_complete_internal(ac, search_str, quote, previous, FALSE);
}
gchar*
autocomplete_complete_substring(Autocomplete ac, const gchar* search_str, gboolean quote, gboolean previous)
{
return _autocomplete_complete_internal(ac, search_str, quote, previous, TRUE);
}
// autocomplete_func func is used -> autocomplete_param_with_func
// Autocomplete ac, gboolean quote are used -> autocomplete_param_with_ac
static char*
@ -399,7 +411,7 @@ autocomplete_remove_older_than_max_reverse(Autocomplete ac, int maxsize)
}
static gchar*
_search(Autocomplete ac, GList* curr, gboolean quote, search_direction direction)
_search(Autocomplete ac, GList* curr, gboolean quote, search_direction direction, gboolean substring)
{
auto_gchar gchar* search_str_ascii = g_str_to_ascii(ac->search_str, NULL);
auto_gchar gchar* search_str_lower = g_ascii_strdown(search_str_ascii, -1);
@ -408,9 +420,18 @@ _search(Autocomplete ac, GList* curr, gboolean quote, search_direction direction
auto_gchar gchar* curr_ascii = g_str_to_ascii(curr->data, NULL);
auto_gchar gchar* curr_lower = g_ascii_strdown(curr_ascii, -1);
// match found
if (strncmp(curr_lower, search_str_lower, strlen(search_str_lower)) == 0) {
gboolean found = FALSE;
if (!substring && (strncmp(curr_lower, search_str_lower, strlen(search_str_lower)) == 0)) {
// if we want to start from beginning (prefix)
found = TRUE;
} else if (substring && (strstr(curr_lower, search_str_lower) != 0)) {
// if we only are looking for a substring
found = TRUE;
}
// match found
if (found) {
// set pointer to last found
ac->last_found = curr;

View File

@ -59,6 +59,8 @@ void autocomplete_add_unsorted(Autocomplete ac, const char* item, const gboolean
// find the next item prefixed with search string
gchar* autocomplete_complete(Autocomplete ac, const gchar* search_str, gboolean quote, gboolean previous);
// find the next item containing search string
gchar* autocomplete_complete_substring(Autocomplete ac, const gchar* search_str, gboolean quote, gboolean previous);
GList* autocomplete_create_list(Autocomplete ac);
gint autocomplete_length(Autocomplete ac);

View File

@ -517,6 +517,14 @@ roster_contact_autocomplete(const char* const search_str, gboolean previous, voi
return autocomplete_complete(roster->name_ac, search_str, TRUE, previous);
}
char*
roster_contact_autocomplete_substring(const char* const search_str, gboolean previous, void* context)
{
assert(roster != NULL);
return autocomplete_complete_substring(roster->name_ac, search_str, TRUE, previous);
}
char*
roster_fulljid_autocomplete(const char* const search_str, gboolean previous, void* context)
{

View File

@ -64,6 +64,7 @@ GSList* roster_get_contacts(roster_ord_t order);
GSList* roster_get_contacts_online(void);
gboolean roster_has_pending_subscriptions(void);
char* roster_contact_autocomplete(const char* const search_str, gboolean previous, void* context);
char* roster_contact_autocomplete_substring(const char* const search_str, gboolean previous, void* context);
char* roster_fulljid_autocomplete(const char* const search_str, gboolean previous, void* context);
GSList* roster_get_group(const char* const group, roster_ord_t order);
GList* roster_get_groups(void);