Now we distinct between history completion and bookmark completion.
1. Bookmark completion is triggered by ':open !<tab>' to complete all
bookmarks or by ':open !tag1 tag2' to complete only those bookmarks that
have tags with the prefixes tag1 and tag2.
2. History completion is changed to split the search query at the space char
and to search for all given words in the history. Only those history items
are completed, that match all given words or tags.
3. Search completion works now also tag based like the url and bookmark
completions.
#include "main.h"
#include "bookmark.h"
+#include "util.h"
extern VbCore vb;
} Bookmark;
static GList *load(const char *file);
-static gboolean contains_all_tags(char **src, unsigned int s, char **query, unsigned int q);
static void free_bookmark(Bookmark *bm);
/**
src = load(vb.files[FILES_BOOKMARK]);
if (!tags || *tags == '\0') {
+ /* without any tags return all bookmarked items */
for (GList *l = src; l; l = l->next) {
Bookmark *bm = (Bookmark*)l->data;
- if (!bm->tags) {
- res = g_list_prepend(res, g_strdup(bm->uri));
- }
+ res = g_list_prepend(res, g_strdup(bm->uri));
}
} else {
parts = g_strsplit(tags, " ", 0);
for (GList *l = src; l; l = l->next) {
Bookmark *bm = (Bookmark*)l->data;
if (bm->tags
- && contains_all_tags(bm->tags, g_strv_length(bm->tags), parts, len)
+ && util_array_contains_all_tags(bm->tags, g_strv_length(bm->tags), parts, len)
) {
res = g_list_prepend(res, g_strdup(bm->uri));
}
return list;
}
-/**
- * Checks if the given source array of pointer contains all those entries
- * given as array of search strings.
- */
-static gboolean contains_all_tags(char **src, unsigned int s, char **query, unsigned int q)
-{
- unsigned int i, n;
-
- if (!s || !q) {
- return true;
- }
-
- /* iterate over all query parts */
- for (i = 0; i < q; i++) {
- gboolean found = false;
- for (n = 0; n < s; n++) {
- if (!strcmp(query[i], src[n])) {
- found = true;
- break;
- }
- }
- if (!found) {
- return false;
- }
- }
-
- return true;
-}
-
static void free_bookmark(Bookmark *bm)
{
g_free(bm->uri);
}
}
-GList *command_get_all(void)
+GList *command_get_by_prefix(const char *prefix)
{
+ GList *res = NULL;
/* according to vim we return only the long commands here */
- return g_hash_table_get_keys(commands);
+ 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)
#define _COMMAND_H
void command_init(void);
-GList *command_get_all(void);
+GList *command_get_by_prefix(const char *prefix);
void command_cleanup(void);
gboolean command_exists(const char *name);
gboolean command_run(const char *name, const char *param);
#include "command.h"
#include "setting.h"
+#define TAG_INDICATOR '!'
+
extern VbCore vb;
-typedef gboolean (*Comp_Func)(char*, const char*);
typedef struct {
GtkWidget *label;
GtkWidget *event;
char *prefix;
} comps;
-static GList *filter_list(GList *target, GList *source, Comp_Func func, const char *input);
static GList *init_completion(GList *target, GList *source, const char *prefix);
static GList *update(GList *completion, GList *active, gboolean back);
static void show(gboolean back);
{
VbInputType type;
const char *input, *prefix, *suffix;
- GList *source = NULL, *tmp = NULL;
+ GList *source = NULL;
input = GET_TEXT();
type = vb_get_input_parts(input, &prefix, &suffix);
gtk_box_pack_start(GTK_BOX(vb.gui.box), vb.gui.compbox, false, false, 0);
if (type == VB_INPUT_SET) {
- source = g_list_sort(setting_get_all(), (GCompareFunc)g_strcmp0);
- comps.completions = init_completion(
- comps.completions,
- filter_list(tmp, source, (Comp_Func)g_str_has_prefix, suffix),
- prefix
- );
+ source = g_list_sort(setting_get_by_prefix(suffix), (GCompareFunc)g_strcmp0);
+ comps.completions = init_completion(comps.completions, source, prefix);
g_list_free(source);
} else if (type == VB_INPUT_OPEN || type == VB_INPUT_TABOPEN) {
- source = history_get_all(HISTORY_URL);
- tmp = filter_list(tmp, source, (Comp_Func)util_strcasestr, suffix);
- /* prepend the bookmark items */
- tmp = g_list_concat(bookmark_get_by_tags(suffix), tmp);
- comps.completions = init_completion(comps.completions, tmp, prefix);
-
- history_list_free(&source);
+ /* if search string begins with TAG_INDICATOR lookup the bookmarks */
+ if (suffix && *suffix == TAG_INDICATOR) {
+ source = bookmark_get_by_tags(suffix + 1);
+ comps.completions = init_completion(comps.completions, source, prefix);
+ } else {
+ source = history_get_by_tags(HISTORY_URL, suffix);
+ comps.completions = init_completion(comps.completions, source, prefix);
+ }
+ 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 */
comps.count = g_ascii_strtoll(suffix, &command, 10);
- source = g_list_sort(command_get_all(), (GCompareFunc)g_strcmp0);
- comps.completions = init_completion(
- comps.completions,
- filter_list(tmp, source, (Comp_Func)g_str_has_prefix, command),
- prefix
- );
+ source = g_list_sort(command_get_by_prefix(suffix), (GCompareFunc)g_strcmp0);
+ comps.completions = init_completion(comps.completions, source, prefix);
g_list_free(source);
} else if (type == VB_INPUT_SEARCH_FORWARD || type == VB_INPUT_SEARCH_BACKWARD) {
- source = g_list_sort(history_get_all(HISTORY_SEARCH), (GCompareFunc)g_strcmp0);
- comps.completions = init_completion(
- comps.completions,
- filter_list(tmp, source, (Comp_Func)g_str_has_prefix, suffix),
- prefix
- );
- g_list_free(source);
+ source = g_list_sort(history_get_by_tags(HISTORY_SEARCH, suffix), (GCompareFunc)g_strcmp0);
+ comps.completions = init_completion(comps.completions, source, prefix);
+ g_list_free_full(source, (GDestroyNotify)g_free);
}
if (!comps.completions) {
vb.state.mode &= ~VB_MODE_COMPLETE;
}
-static GList *filter_list(GList *target, GList *source, Comp_Func func, const char *input)
-{
- for (GList *l = source; l; l = l->next) {
- char *data = l->data;
- if (func(data, input)) {
- target = g_list_prepend(target, data);
- }
- }
-
- target = g_list_reverse(target);
-
- return target;
-}
-
static GList *init_completion(GList *target, GList *source, const char *prefix)
{
OVERWRITE_STRING(comps.prefix, prefix);
#include "main.h"
#include "history.h"
+#include "util.h"
extern VbCore vb;
}
/**
- * Retrieves all history entries for given history type.
+ * Retrieves the list of matching history items to given tag string.
+ * Returned list must be freed.
*/
-GList *history_get_all(HistoryType type)
+GList *history_get_by_tags(HistoryType type, const char *tags)
{
- return load(get_file_by_type(type));
+ GList *res = NULL, *src = NULL;
+ char **parts;
+ unsigned int len;
+
+ 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) {
+ res = g_list_prepend(res, g_strdup((char*)l->data));
+ }
+ } else {
+ parts = g_strsplit(tags, " ", 0);
+ len = g_strv_length(parts);
+
+ for (GList *l = src; l; l = l->next) {
+ char *value = (char*)l->data;
+ if (util_string_contains_all_tags(value, parts, len)) {
+ res = g_list_prepend(res, g_strdup(value));
+ }
+ }
+ g_strfreev(parts);
+ }
+ g_list_free_full(src, (GDestroyNotify)g_free);
+
+ return res;
}
/**
}
}
-void history_list_free(GList **list)
-{
- if (*list) {
- g_list_free_full(*list, (GDestroyNotify)g_free);
- *list = NULL;
- }
-}
-
/**
* Retrieves the list of matching history items.
* The list must be freed.
fclose(f);
}
- history_list_free(&list);
+ g_list_free_full(list, (GDestroyNotify)g_free);
}
void history_cleanup(void);
void history_add(HistoryType type, const char *value);
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);
-void history_list_free(GList **list);
#endif /* end of include guard: _HISTORY_H */
}
}
-GList* setting_get_all(void)
+/**
+ * Retrieves the settings names as list for given prefix.
+ */
+GList* setting_get_by_prefix(const char *prefix)
{
- return g_hash_table_get_keys(settings);
+ 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)
};
void setting_init(void);
-GList* setting_get_all(void);
+GList* setting_get_by_prefix(const char *prefix);
void setting_cleanup(void);
gboolean setting_run(char* name, const char* param);
return NULL;
}
+
+/**
+ * Checks if the given source array of pointer are prefixes to all those
+ * entries given as array of search strings.
+ */
+gboolean util_array_contains_all_tags(char **src, unsigned int s, char **query, unsigned int q)
+{
+ unsigned int i, n;
+
+ if (!s || !q) {
+ return true;
+ }
+
+ /* iterate over all query parts */
+ for (i = 0; i < q; i++) {
+ gboolean found = false;
+ for (n = 0; n < s; n++) {
+ if (g_str_has_prefix(src[n], query[i])) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/**
+ * Checks if the given array of tags are all found in source string.
+ */
+gboolean util_string_contains_all_tags(char *src, char **query, unsigned int q)
+{
+ unsigned int i;
+ if (!q) {
+ return true;
+ }
+
+ /* iterate over all query parts */
+ for (i = 0; i < q; i++) {
+ if (!util_strcasestr(src, query[i])) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
/**
* Replaces appearances of search in string by given replace.
* Returne a new allocated string of search was found.
#include "main.h"
+typedef gboolean (*Util_Comp_Func)(const char*, const char*);
+
char* util_get_config_dir(void);
char* util_get_cache_dir(void);
const char* util_get_home_dir(void);
char* util_get_file_contents(const char* filename, gsize* length);
char** util_get_lines(const char* filename);
char* util_strcasestr(const char* haystack, const char* needle);
+gboolean util_array_contains_all_tags(char **src, unsigned int s, char **query, unsigned int q);
+gboolean util_string_contains_all_tags(char *src, char **query, unsigned int q);
char *util_str_replace(const char* search, const char* replace, const char* string);
gboolean util_create_tmp_file(const char *content, char **file);