mirror of
https://git.jabber.space/devs/cproof.git
synced 2026-07-19 13:46:21 +00:00
Allow previous autocompletion with shift tab
This commit is contained in:
@@ -40,14 +40,16 @@
|
||||
#include "common.h"
|
||||
#include "tools/autocomplete.h"
|
||||
#include "tools/parser.h"
|
||||
#include "ui/ui.h"
|
||||
|
||||
struct autocomplete_t {
|
||||
GSList *items;
|
||||
GSList *last_found;
|
||||
GList *items;
|
||||
GList *last_found;
|
||||
gchar *search_str;
|
||||
};
|
||||
|
||||
static gchar* _search_from(Autocomplete ac, GSList *curr, gboolean quote);
|
||||
static gchar* _search_next(Autocomplete ac, GList *curr, gboolean quote);
|
||||
static gchar* _search_prev(Autocomplete ac, GList *curr, gboolean quote);
|
||||
|
||||
Autocomplete
|
||||
autocomplete_new(void)
|
||||
@@ -64,7 +66,7 @@ void
|
||||
autocomplete_clear(Autocomplete ac)
|
||||
{
|
||||
if (ac) {
|
||||
g_slist_free_full(ac->items, free);
|
||||
g_list_free_full(ac->items, free);
|
||||
ac->items = NULL;
|
||||
|
||||
autocomplete_reset(ac);
|
||||
@@ -95,7 +97,7 @@ autocomplete_length(Autocomplete ac)
|
||||
} else if (!ac->items) {
|
||||
return 0;
|
||||
} else {
|
||||
return g_slist_length(ac->items);
|
||||
return g_list_length(ac->items);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,7 +106,7 @@ autocomplete_add(Autocomplete ac, const char *item)
|
||||
{
|
||||
if (ac) {
|
||||
char *item_cpy;
|
||||
GSList *curr = g_slist_find_custom(ac->items, item, (GCompareFunc)strcmp);
|
||||
GList *curr = g_list_find_custom(ac->items, item, (GCompareFunc)strcmp);
|
||||
|
||||
// if item already exists
|
||||
if (curr) {
|
||||
@@ -112,7 +114,7 @@ autocomplete_add(Autocomplete ac, const char *item)
|
||||
}
|
||||
|
||||
item_cpy = strdup(item);
|
||||
ac->items = g_slist_insert_sorted(ac->items, item_cpy, (GCompareFunc)strcmp);
|
||||
ac->items = g_list_insert_sorted(ac->items, item_cpy, (GCompareFunc)strcmp);
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -131,7 +133,7 @@ void
|
||||
autocomplete_remove(Autocomplete ac, const char *const item)
|
||||
{
|
||||
if (ac) {
|
||||
GSList *curr = g_slist_find_custom(ac->items, item, (GCompareFunc)strcmp);
|
||||
GList *curr = g_list_find_custom(ac->items, item, (GCompareFunc)strcmp);
|
||||
|
||||
if (!curr) {
|
||||
return;
|
||||
@@ -143,7 +145,7 @@ autocomplete_remove(Autocomplete ac, const char *const item)
|
||||
}
|
||||
|
||||
free(curr->data);
|
||||
ac->items = g_slist_delete_link(ac->items, curr);
|
||||
ac->items = g_list_delete_link(ac->items, curr);
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -158,15 +160,15 @@ autocomplete_remove_all(Autocomplete ac, char **items)
|
||||
}
|
||||
}
|
||||
|
||||
GSList*
|
||||
GList*
|
||||
autocomplete_create_list(Autocomplete ac)
|
||||
{
|
||||
GSList *copy = NULL;
|
||||
GSList *curr = ac->items;
|
||||
GList *copy = NULL;
|
||||
GList *curr = ac->items;
|
||||
|
||||
while(curr) {
|
||||
copy = g_slist_append(copy, strdup(curr->data));
|
||||
curr = g_slist_next(curr);
|
||||
copy = g_list_append(copy, strdup(curr->data));
|
||||
curr = g_list_next(curr);
|
||||
}
|
||||
|
||||
return copy;
|
||||
@@ -175,20 +177,20 @@ autocomplete_create_list(Autocomplete ac)
|
||||
gboolean
|
||||
autocomplete_contains(Autocomplete ac, const char *value)
|
||||
{
|
||||
GSList *curr = ac->items;
|
||||
GList *curr = ac->items;
|
||||
|
||||
while(curr) {
|
||||
if (strcmp(curr->data, value) == 0) {
|
||||
return TRUE;
|
||||
}
|
||||
curr = g_slist_next(curr);
|
||||
curr = g_list_next(curr);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gchar*
|
||||
autocomplete_complete(Autocomplete ac, const gchar *search_str, gboolean quote)
|
||||
autocomplete_complete(Autocomplete ac, const gchar *search_str, gboolean quote, gboolean previous)
|
||||
{
|
||||
gchar *found = NULL;
|
||||
|
||||
@@ -209,22 +211,38 @@ autocomplete_complete(Autocomplete ac, const gchar *search_str, gboolean quote)
|
||||
}
|
||||
|
||||
ac->search_str = strdup(search_str);
|
||||
found = _search_from(ac, ac->items, quote);
|
||||
found = _search_next(ac, ac->items, quote);
|
||||
|
||||
return found;
|
||||
|
||||
// subsequent search attempt
|
||||
} else {
|
||||
// search from here+1 to end
|
||||
found = _search_from(ac, g_slist_next(ac->last_found), quote);
|
||||
if (found) {
|
||||
return found;
|
||||
if (previous) {
|
||||
// search from here-1 to beginning
|
||||
found = _search_prev(ac, g_list_previous(ac->last_found), quote);
|
||||
if (found) {
|
||||
return found;
|
||||
}
|
||||
} else {
|
||||
// search from here+1 to end
|
||||
found = _search_next(ac, g_list_next(ac->last_found), quote);
|
||||
if (found) {
|
||||
return found;
|
||||
}
|
||||
}
|
||||
|
||||
// search from beginning
|
||||
found = _search_from(ac, ac->items, quote);
|
||||
if (found) {
|
||||
return found;
|
||||
if (previous) {
|
||||
// search from end
|
||||
found = _search_prev(ac, g_list_last(ac->items), quote);
|
||||
if (found) {
|
||||
return found;
|
||||
}
|
||||
} else {
|
||||
// search from beginning
|
||||
found = _search_next(ac, ac->items, quote);
|
||||
if (found) {
|
||||
return found;
|
||||
}
|
||||
}
|
||||
|
||||
// we found nothing, reset search
|
||||
@@ -235,7 +253,7 @@ autocomplete_complete(Autocomplete ac, const gchar *search_str, gboolean quote)
|
||||
}
|
||||
|
||||
char*
|
||||
autocomplete_param_with_func(const char *const input, char *command, autocomplete_func func)
|
||||
autocomplete_param_with_func(const char *const input, char *command, autocomplete_func func, gboolean previous)
|
||||
{
|
||||
GString *auto_msg = NULL;
|
||||
char *result = NULL;
|
||||
@@ -252,7 +270,7 @@ autocomplete_param_with_func(const char *const input, char *command, autocomplet
|
||||
}
|
||||
prefix[inp_len - len] = '\0';
|
||||
|
||||
char *found = func(prefix);
|
||||
char *found = func(prefix, previous);
|
||||
if (found) {
|
||||
auto_msg = g_string_new(command_cpy);
|
||||
g_string_append(auto_msg, found);
|
||||
@@ -266,7 +284,7 @@ autocomplete_param_with_func(const char *const input, char *command, autocomplet
|
||||
}
|
||||
|
||||
char*
|
||||
autocomplete_param_with_ac(const char *const input, char *command, Autocomplete ac, gboolean quote)
|
||||
autocomplete_param_with_ac(const char *const input, char *command, Autocomplete ac, gboolean quote, gboolean previous)
|
||||
{
|
||||
GString *auto_msg = NULL;
|
||||
char *result = NULL;
|
||||
@@ -282,7 +300,7 @@ autocomplete_param_with_ac(const char *const input, char *command, Autocomplete
|
||||
}
|
||||
prefix[inp_len - len] = '\0';
|
||||
|
||||
char *found = autocomplete_complete(ac, prefix, quote);
|
||||
char *found = autocomplete_complete(ac, prefix, quote, previous);
|
||||
if (found) {
|
||||
auto_msg = g_string_new(command_cpy);
|
||||
g_string_append(auto_msg, found);
|
||||
@@ -297,7 +315,7 @@ autocomplete_param_with_ac(const char *const input, char *command, Autocomplete
|
||||
}
|
||||
|
||||
char*
|
||||
autocomplete_param_no_with_func(const char *const input, char *command, int arg_number, autocomplete_func func)
|
||||
autocomplete_param_no_with_func(const char *const input, char *command, int arg_number, autocomplete_func func, gboolean previous)
|
||||
{
|
||||
if (strncmp(input, command, strlen(command)) == 0) {
|
||||
GString *result_str = NULL;
|
||||
@@ -312,7 +330,7 @@ autocomplete_param_no_with_func(const char *const input, char *command, int arg_
|
||||
|
||||
// autocomplete param
|
||||
if (comp_str) {
|
||||
char *found = func(comp_str);
|
||||
char *found = func(comp_str, previous);
|
||||
if (found) {
|
||||
result_str = g_string_new("");
|
||||
g_string_append(result_str, start_str);
|
||||
@@ -329,7 +347,7 @@ autocomplete_param_no_with_func(const char *const input, char *command, int arg_
|
||||
}
|
||||
|
||||
static gchar*
|
||||
_search_from(Autocomplete ac, GSList *curr, gboolean quote)
|
||||
_search_next(Autocomplete ac, GList *curr, gboolean quote)
|
||||
{
|
||||
gchar *search_str_ascii = g_str_to_ascii(ac->search_str, NULL);
|
||||
gchar *search_str_lower = g_ascii_strdown(search_str_ascii, -1);
|
||||
@@ -368,7 +386,54 @@ _search_from(Autocomplete ac, GSList *curr, gboolean quote)
|
||||
}
|
||||
|
||||
g_free(curr_lower);
|
||||
curr = g_slist_next(curr);
|
||||
curr = g_list_next(curr);
|
||||
}
|
||||
|
||||
g_free(search_str_lower);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gchar*
|
||||
_search_prev(Autocomplete ac, GList *curr, gboolean quote)
|
||||
{
|
||||
gchar *search_str_ascii = g_str_to_ascii(ac->search_str, NULL);
|
||||
gchar *search_str_lower = g_ascii_strdown(search_str_ascii, -1);
|
||||
g_free(search_str_ascii);
|
||||
|
||||
while(curr) {
|
||||
gchar *curr_ascii = g_str_to_ascii(curr->data, NULL);
|
||||
gchar *curr_lower = g_ascii_strdown(curr_ascii, -1);
|
||||
g_free(curr_ascii);
|
||||
|
||||
// match found
|
||||
if (strncmp(curr_lower, search_str_lower, strlen(search_str_lower)) == 0) {
|
||||
|
||||
// set pointer to last found
|
||||
ac->last_found = curr;
|
||||
|
||||
// if contains space, quote before returning
|
||||
if (quote && g_strrstr(curr->data, " ")) {
|
||||
GString *quoted = g_string_new("\"");
|
||||
g_string_append(quoted, curr->data);
|
||||
g_string_append(quoted, "\"");
|
||||
|
||||
gchar *result = quoted->str;
|
||||
g_string_free(quoted, FALSE);
|
||||
|
||||
g_free(search_str_lower);
|
||||
g_free(curr_lower);
|
||||
return result;
|
||||
|
||||
// otherwise just return the string
|
||||
} else {
|
||||
g_free(search_str_lower);
|
||||
g_free(curr_lower);
|
||||
return strdup(curr->data);
|
||||
}
|
||||
}
|
||||
|
||||
g_free(curr_lower);
|
||||
curr = g_list_previous(curr);
|
||||
}
|
||||
|
||||
g_free(search_str_lower);
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
typedef char* (*autocomplete_func)(const char *const);
|
||||
typedef char* (*autocomplete_func)(const char *const, gboolean);
|
||||
typedef struct autocomplete_t *Autocomplete;
|
||||
|
||||
// allocate new autocompleter with no items
|
||||
@@ -55,19 +55,19 @@ void autocomplete_remove(Autocomplete ac, const char *const item);
|
||||
void autocomplete_remove_all(Autocomplete ac, char **items);
|
||||
|
||||
// find the next item prefixed with search string
|
||||
gchar* autocomplete_complete(Autocomplete ac, const gchar *search_str, gboolean quote);
|
||||
gchar* autocomplete_complete(Autocomplete ac, const gchar *search_str, gboolean quote, gboolean previous);
|
||||
|
||||
GSList* autocomplete_create_list(Autocomplete ac);
|
||||
GList* autocomplete_create_list(Autocomplete ac);
|
||||
gint autocomplete_length(Autocomplete ac);
|
||||
|
||||
char* autocomplete_param_with_func(const char *const input, char *command,
|
||||
autocomplete_func func);
|
||||
autocomplete_func func, gboolean previous);
|
||||
|
||||
char* autocomplete_param_with_ac(const char *const input, char *command,
|
||||
Autocomplete ac, gboolean quote);
|
||||
Autocomplete ac, gboolean quote, gboolean previous);
|
||||
|
||||
char* autocomplete_param_no_with_func(const char *const input, char *command,
|
||||
int arg_number, autocomplete_func func);
|
||||
int arg_number, autocomplete_func func, gboolean previous);
|
||||
|
||||
void autocomplete_reset(Autocomplete ac);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user