From: Daniel Carl Date: Sun, 14 Jul 2013 22:26:27 +0000 (+0200) Subject: Avoid glist to transfer completion data to the completion.c. X-Git-Url: https://git.owens.tech/assets/me.webp/assets/me.webp/git?a=commitdiff_plain;h=3b9924a47cf86bfed3de2aca1e9439aa3092540c;p=vimb.git Avoid glist to transfer completion data to the completion.c. The completion asked the required components to spit out the list of completion items to make a GtkListStore model and fill it with the data and to free the list. Now we let the component like history, bookmark or setting fill in the completion items self, which avoids unneeded list preparation and memory allocation. --- diff --git a/src/bookmark.c b/src/bookmark.c index 2de9ea7..9983827 100644 --- a/src/bookmark.c +++ b/src/bookmark.c @@ -20,6 +20,7 @@ #include "main.h" #include "bookmark.h" #include "util.h" +#include "completion.h" extern VbCore vb; @@ -103,26 +104,26 @@ gboolean bookmark_remove(const char *uri) return removed; } -/** - * Retrieves all bookmark uri matching the given space separated tags string. - * Don't forget to free the returned list. - */ -GList *bookmark_get_by_tags(const char *tags) +gboolean bookmark_fill_completion(GtkListStore *store, const char *input) { - GList *res = NULL, *src = NULL; + gboolean found = false; char **parts; unsigned int len; + GtkTreeIter iter; + GList *src = NULL; Bookmark *bm; src = load(vb.files[FILES_BOOKMARK]); - if (!tags || *tags == '\0') { + if (!input || *input == '\0') { /* without any tags return all bookmarked items */ for (GList *l = src; l; l = l->next) { bm = (Bookmark*)l->data; - res = g_list_prepend(res, g_strdup(bm->uri)); + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, COMPLETION_STORE_FIRST, bm->uri, -1); + found = true; } } else { - parts = g_strsplit(tags, " ", 0); + parts = g_strsplit(input, " ", 0); len = g_strv_length(parts); for (GList *l = src; l; l = l->next) { @@ -130,7 +131,9 @@ GList *bookmark_get_by_tags(const char *tags) if (bm->tags && util_array_contains_all_tags(bm->tags, g_strv_length(bm->tags), parts, len) ) { - res = g_list_prepend(res, g_strdup(bm->uri)); + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, COMPLETION_STORE_FIRST, bm->uri, -1); + found = true; } } g_strfreev(parts); @@ -138,7 +141,7 @@ GList *bookmark_get_by_tags(const char *tags) g_list_free_full(src, (GDestroyNotify)free_bookmark); - return res; + return found; } static GList *load(const char *file) diff --git a/src/bookmark.h b/src/bookmark.h index 5570f6e..1a2e1d1 100644 --- a/src/bookmark.h +++ b/src/bookmark.h @@ -22,6 +22,6 @@ gboolean bookmark_add(const char *uri, const char *title, const char *tags); gboolean bookmark_remove(const char *uri); -GList *bookmark_get_by_tags(const char *tags); +gboolean bookmark_fill_completion(GtkListStore *store, const char *input); #endif /* end of include guard: _BOOKMARK_H */ diff --git a/src/command.c b/src/command.c index 58ef5dc..9d761da 100644 --- a/src/command.c +++ b/src/command.c @@ -144,29 +144,6 @@ void command_init(void) } } -GList *command_get_by_prefix(const char *prefix) -{ - GList *res = NULL; - /* according to vim we return only the long commands here */ - GList *src = g_hash_table_get_keys(commands); - - if (!prefix || prefix == '\0') { - for (GList *l = src; l; l = l->next) { - res = g_list_prepend(res, l->data); - } - } else { - for (GList *l = src; l; l = l->next) { - char *value = (char*)l->data; - if (g_str_has_prefix(value, prefix)) { - res = g_list_prepend(res, value); - } - } - } - g_list_free(src); - - return res; -} - void command_cleanup(void) { if (commands) { @@ -278,6 +255,34 @@ gboolean command_run_multi(const Arg *arg) return result; } +gboolean command_fill_completion(GtkListStore *store, const char *input) +{ + gboolean found = false; + GtkTreeIter iter; + /* according to vim we return only the long commands here */ + GList *src = g_hash_table_get_keys(commands); + + if (!input || input == '\0') { + for (GList *l = src; l; l = l->next) { + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, COMPLETION_STORE_FIRST, l->data, -1); + found = true; + } + } else { + for (GList *l = src; l; l = l->next) { + char *value = (char*)l->data; + if (g_str_has_prefix(value, input)) { + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, COMPLETION_STORE_FIRST, l->data, -1); + found = true; + } + } + } + g_list_free(src); + + return found; +} + gboolean command_open(const Arg *arg) { vb_set_mode(VB_MODE_NORMAL, false); diff --git a/src/command.h b/src/command.h index dcdd25f..32c8f0b 100644 --- a/src/command.h +++ b/src/command.h @@ -47,11 +47,11 @@ enum { typedef gboolean (*Command)(const Arg *arg); void command_init(void); -GList *command_get_by_prefix(const char *prefix); void command_cleanup(void); gboolean command_parse_from_string(const char *input, Command *func, Arg *arg, guint *count); gboolean command_run_string(const char *input); gboolean command_run_multi(const Arg *arg); +gboolean command_fill_completion(GtkListStore *store, const char *input); gboolean command_open(const Arg *arg); gboolean command_open_home(const Arg *arg); diff --git a/src/completion.c b/src/completion.c index db518da..a24effa 100644 --- a/src/completion.c +++ b/src/completion.c @@ -26,7 +26,6 @@ #include "setting.h" #define TAG_INDICATOR '!' -#define COMP_ITEM 0 extern VbCore vb; @@ -39,7 +38,6 @@ static struct { char *text; /* text of the current active tree item */ } comp; -static GtkTreeModel *get_tree_model(GList *source); static void init_completion(GtkTreeModel *model); static void show(gboolean back); static void move_cursor(gboolean back); @@ -50,8 +48,8 @@ gboolean completion_complete(gboolean back) { VbInputType type; const char *input, *prefix, *suffix; - GList *source = NULL; - GtkTreeModel *model = NULL; + GtkListStore *store = NULL; + gboolean res = false; input = GET_TEXT(); type = vb_get_input_parts(input, &prefix, &suffix); @@ -73,49 +71,35 @@ gboolean completion_complete(gboolean back) return false; } + /* create the list store model */ + store = gtk_list_store_new(1, G_TYPE_STRING); if (type == VB_INPUT_SET) { - source = g_list_sort(setting_get_by_prefix(suffix), (GCompareFunc)g_strcmp0); - if (!g_list_first(source)) { - return false; - } - model = get_tree_model(source); - g_list_free(source); + res = setting_fill_completion(store, suffix); } else if (type == VB_INPUT_OPEN || type == VB_INPUT_TABOPEN) { /* if search string begins with TAG_INDICATOR lookup the bookmarks */ if (suffix && *suffix == TAG_INDICATOR) { - source = g_list_sort(bookmark_get_by_tags(suffix + 1), (GCompareFunc)g_strcmp0); + res = bookmark_fill_completion(store, suffix + 1); } else { - source = history_get_by_tags(HISTORY_URL, suffix); - } - if (!g_list_first(source)) { - return false; + res = history_fill_completion(store, HISTORY_URL, suffix); } - model = get_tree_model(source); - g_list_free_full(source, (GDestroyNotify)g_free); } else if (type == VB_INPUT_COMMAND) { char *command = NULL; /* remove counts before command and save it to print it later in inputbox */ comp.count = g_ascii_strtoll(suffix, &command, 10); - source = g_list_sort(command_get_by_prefix(command), (GCompareFunc)g_strcmp0); - if (!g_list_first(source)) { - return false; - } - model = get_tree_model(source); - g_list_free(source); + res = command_fill_completion(store, command); } else if (type == VB_INPUT_SEARCH_FORWARD || type == VB_INPUT_SEARCH_BACKWARD) { - source = g_list_sort(history_get_by_tags(HISTORY_SEARCH, suffix), (GCompareFunc)g_strcmp0); - if (!g_list_first(source)) { - return false; - } - model = get_tree_model(source); - g_list_free_full(source, (GDestroyNotify)g_free); + res = history_fill_completion(store, HISTORY_SEARCH, suffix); + } + + if (!res) { + return false; } vb_set_mode(VB_MODE_COMMAND | VB_MODE_COMPLETE, false); OVERWRITE_STRING(comp.prefix, prefix); - init_completion(model); + init_completion(GTK_TREE_MODEL(store)); show(back); return true; @@ -135,18 +119,6 @@ void completion_clean(void) vb.state.mode &= ~VB_MODE_COMPLETE; } -static GtkTreeModel *get_tree_model(GList *source) -{ - GtkTreeIter iter; - GtkListStore *store = gtk_list_store_new(1, G_TYPE_STRING); - - for (GList *l = source; l; l = l->next) { - gtk_list_store_append(store, &iter); - gtk_list_store_set(store, &iter, COMP_ITEM, l->data, -1); - } - return GTK_TREE_MODEL(store); -} - static void init_completion(GtkTreeModel *model) { GtkCellRenderer *renderer; @@ -188,7 +160,7 @@ static void init_completion(GtkTreeModel *model) ); gtk_tree_view_insert_column_with_attributes( GTK_TREE_VIEW(comp.tree), -1, "", renderer, - "text", COMP_ITEM, + "text", COMPLETION_STORE_FIRST, NULL ); @@ -259,7 +231,7 @@ static gboolean tree_selection_func(GtkTreeSelection *selection, /* if not selected means the item is going to be selected which we are * interested in */ if (!selected && gtk_tree_model_get_iter(model, &iter, path)) { - gtk_tree_model_get(model, &iter, COMP_ITEM, &value, -1); + gtk_tree_model_get(model, &iter, COMPLETION_STORE_FIRST, &value, -1); /* save the content of the selected item so wen can access it easy */ if (comp.text) { g_free(comp.text); diff --git a/src/completion.h b/src/completion.h index 2337a73..7074d99 100644 --- a/src/completion.h +++ b/src/completion.h @@ -22,6 +22,11 @@ #include "main.h" +enum { + COMPLETION_STORE_FIRST, + COMPLETION_STORE_SECOND +}; + void completion_clean(void); gboolean completion_complete(gboolean back); diff --git a/src/history.c b/src/history.c index d71ff6e..9e8a32e 100644 --- a/src/history.c +++ b/src/history.c @@ -20,6 +20,7 @@ #include "main.h" #include "history.h" #include "util.h" +#include "completion.h" extern VbCore vb; @@ -84,48 +85,6 @@ void history_add(HistoryType type, const char *value, const char *additional) } } -/** - * Retrieves the list of matching history items to given tag string. - * Returned list must be freed. - */ -GList *history_get_by_tags(HistoryType type, const char *tags) -{ - GList *res = NULL, *src = NULL; - char **parts; - unsigned int len; - History *item; - - src = load(get_file_by_type(type)); - if (!tags || *tags == '\0') { - /* without any tags return all items */ - for (GList *l = src; l; l = l->next) { - item = l->data; - res = g_list_prepend(res, g_strdup(item->first)); - } - } else if (HISTORY_URL == type) { - parts = g_strsplit(tags, " ", 0); - len = g_strv_length(parts); - - for (GList *l = src; l; l = l->next) { - item = l->data; - if (util_string_contains_all_tags(item->first, parts, len)) { - res = g_list_prepend(res, g_strdup(item->first)); - } - } - g_strfreev(parts); - } else { - for (GList *l = src; l; l = l->next) { - item = l->data; - if (g_str_has_prefix(item->first, tags)) { - res = g_list_prepend(res, g_strdup(item->first)); - } - } - } - g_list_free_full(src, (GDestroyNotify)g_free); - - return res; -} - /** * Retrieves the item from history to be shown in input box. * The result must be freed by the caller. @@ -163,6 +122,52 @@ void history_rewind(void) } } +gboolean history_fill_completion(GtkListStore *store, HistoryType type, const char *input) +{ + char **parts; + unsigned int len; + gboolean found = false; + GList *src = NULL; + GtkTreeIter iter; + History *item; + + src = load(get_file_by_type(type)); + if (!input || *input == '\0') { + /* without any tags return all items */ + for (GList *l = src; l; l = l->next) { + item = l->data; + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, COMPLETION_STORE_FIRST, item->first, -1); + found = true; + } + } else if (HISTORY_URL == type) { + parts = g_strsplit(input, " ", 0); + len = g_strv_length(parts); + + for (GList *l = src; l; l = l->next) { + item = l->data; + if (util_string_contains_all_tags(item->first, parts, len)) { + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, COMPLETION_STORE_FIRST, item->first, -1); + found = true; + } + } + g_strfreev(parts); + } else { + for (GList *l = src; l; l = l->next) { + item = l->data; + if (g_str_has_prefix(item->first, input)) { + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, COMPLETION_STORE_FIRST, item->first, -1); + found = true; + } + } + } + g_list_free_full(src, (GDestroyNotify)g_free); + + return found; +} + /** * Retrieves the list of matching history items. * The list must be freed. diff --git a/src/history.h b/src/history.h index 4b46399..e1219dd 100644 --- a/src/history.h +++ b/src/history.h @@ -34,5 +34,6 @@ GList *history_get_all(HistoryType type); GList *history_get_by_tags(HistoryType type, const char *tags); char *history_get(const char *input, gboolean prev); void history_rewind(void); +gboolean history_fill_completion(GtkListStore *store, HistoryType type, const char *input); #endif /* end of include guard: _HISTORY_H */ diff --git a/src/setting.c b/src/setting.c index fa147fb..b575b7f 100644 --- a/src/setting.c +++ b/src/setting.c @@ -19,6 +19,7 @@ #include "setting.h" #include "util.h" +#include "completion.h" static GHashTable *settings; @@ -118,31 +119,6 @@ void setting_init(void) } } -/** - * Retrieves the settings names as list for given prefix. - */ -GList* setting_get_by_prefix(const char *prefix) -{ - GList *res = NULL; - GList *src = g_hash_table_get_keys(settings); - - if (!prefix || prefix == '\0') { - for (GList *l = src; l; l = l->next) { - res = g_list_prepend(res, l->data); - } - } else { - for (GList *l = src; l; l = l->next) { - char *value = (char*)l->data; - if (g_str_has_prefix(value, prefix)) { - res = g_list_prepend(res, value); - } - } - } - g_list_free(src); - - return res; -} - void setting_cleanup(void) { if (settings) { @@ -221,6 +197,34 @@ gboolean setting_run(char *name, const char *param) return result; } +gboolean setting_fill_completion(GtkListStore *store, const char *input) +{ + gboolean found = false; + GtkTreeIter iter; + GList *src = g_hash_table_get_keys(settings); + + if (!input || input == '\0') { + for (GList *l = src; l; l = l->next) { + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, COMPLETION_STORE_FIRST, l->data, -1); + found = true; + } + } else { + for (GList *l = src; l; l = l->next) { + char *value = (char*)l->data; + if (g_str_has_prefix(value, input)) { + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, COMPLETION_STORE_FIRST, l->data, -1); + found = true; + } + } + } + /* TODO sort the store model */ + g_list_free(src); + + return found; +} + /** * Converts string representing also given data type into and Arg. */ diff --git a/src/setting.h b/src/setting.h index 8aa4a36..c509079 100644 --- a/src/setting.h +++ b/src/setting.h @@ -40,8 +40,8 @@ struct _Setting { }; void setting_init(void); -GList* setting_get_by_prefix(const char *prefix); void setting_cleanup(void); gboolean setting_run(char* name, const char* param); +gboolean setting_fill_completion(GtkListStore *store, const char *input); #endif /* end of include guard: _SETTING_H */