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:
parent
4d9852a76a
commit
8ce8f8e6dc
@ -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
|
// Remove quote character before and after names when doing autocomplete
|
||||||
char* unquoted = strip_arg_quotes(input);
|
char* unquoted = strip_arg_quotes(input);
|
||||||
for (int i = 0; i < ARRAY_SIZE(contact_choices); i++) {
|
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) {
|
if (result) {
|
||||||
free(unquoted);
|
free(unquoted);
|
||||||
return result;
|
return result;
|
||||||
|
@ -57,7 +57,7 @@ struct autocomplete_t
|
|||||||
gchar* search_str;
|
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
|
||||||
autocomplete_new(void)
|
autocomplete_new(void)
|
||||||
@ -245,7 +245,7 @@ autocomplete_contains(Autocomplete ac, const char* value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
gchar*
|
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;
|
gchar* found = NULL;
|
||||||
|
|
||||||
@ -266,7 +266,7 @@ autocomplete_complete(Autocomplete ac, const gchar* search_str, gboolean quote,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ac->search_str = strdup(search_str);
|
ac->search_str = strdup(search_str);
|
||||||
found = _search(ac, ac->items, quote, NEXT);
|
found = _search(ac, ac->items, quote, NEXT, substring);
|
||||||
|
|
||||||
return found;
|
return found;
|
||||||
|
|
||||||
@ -274,13 +274,13 @@ autocomplete_complete(Autocomplete ac, const gchar* search_str, gboolean quote,
|
|||||||
} else {
|
} else {
|
||||||
if (previous) {
|
if (previous) {
|
||||||
// search from here-1 to beginning
|
// 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) {
|
if (found) {
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// search from here+1 to end
|
// 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) {
|
if (found) {
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
@ -288,13 +288,13 @@ autocomplete_complete(Autocomplete ac, const gchar* search_str, gboolean quote,
|
|||||||
|
|
||||||
if (previous) {
|
if (previous) {
|
||||||
// search from end
|
// 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) {
|
if (found) {
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// search from beginning
|
// search from beginning
|
||||||
found = _search(ac, ac->items, quote, NEXT);
|
found = _search(ac, ac->items, quote, NEXT, substring);
|
||||||
if (found) {
|
if (found) {
|
||||||
return 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_func func is used -> autocomplete_param_with_func
|
||||||
// Autocomplete ac, gboolean quote are used -> autocomplete_param_with_ac
|
// Autocomplete ac, gboolean quote are used -> autocomplete_param_with_ac
|
||||||
static char*
|
static char*
|
||||||
@ -399,7 +411,7 @@ autocomplete_remove_older_than_max_reverse(Autocomplete ac, int maxsize)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gchar*
|
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_ascii = g_str_to_ascii(ac->search_str, NULL);
|
||||||
auto_gchar gchar* search_str_lower = g_ascii_strdown(search_str_ascii, -1);
|
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_ascii = g_str_to_ascii(curr->data, NULL);
|
||||||
auto_gchar gchar* curr_lower = g_ascii_strdown(curr_ascii, -1);
|
auto_gchar gchar* curr_lower = g_ascii_strdown(curr_ascii, -1);
|
||||||
|
|
||||||
// match found
|
gboolean found = FALSE;
|
||||||
if (strncmp(curr_lower, search_str_lower, strlen(search_str_lower)) == 0) {
|
|
||||||
|
|
||||||
|
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
|
// set pointer to last found
|
||||||
ac->last_found = curr;
|
ac->last_found = curr;
|
||||||
|
|
||||||
|
@ -59,6 +59,8 @@ void autocomplete_add_unsorted(Autocomplete ac, const char* item, const gboolean
|
|||||||
|
|
||||||
// find the next item prefixed with search string
|
// find the next item prefixed with search string
|
||||||
gchar* autocomplete_complete(Autocomplete ac, const gchar* search_str, gboolean quote, gboolean previous);
|
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);
|
GList* autocomplete_create_list(Autocomplete ac);
|
||||||
gint autocomplete_length(Autocomplete ac);
|
gint autocomplete_length(Autocomplete ac);
|
||||||
|
@ -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);
|
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*
|
char*
|
||||||
roster_fulljid_autocomplete(const char* const search_str, gboolean previous, void* context)
|
roster_fulljid_autocomplete(const char* const search_str, gboolean previous, void* context)
|
||||||
{
|
{
|
||||||
|
@ -64,6 +64,7 @@ GSList* roster_get_contacts(roster_ord_t order);
|
|||||||
GSList* roster_get_contacts_online(void);
|
GSList* roster_get_contacts_online(void);
|
||||||
gboolean roster_has_pending_subscriptions(void);
|
gboolean roster_has_pending_subscriptions(void);
|
||||||
char* roster_contact_autocomplete(const char* const search_str, gboolean previous, void* context);
|
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);
|
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);
|
GSList* roster_get_group(const char* const group, roster_ord_t order);
|
||||||
GList* roster_get_groups(void);
|
GList* roster_get_groups(void);
|
||||||
|
Loading…
Reference in New Issue
Block a user