Allow to change input in history lookup.
authorDaniel Carl <danielcarl@gmx.de>
Mon, 22 Jul 2013 17:38:18 +0000 (19:38 +0200)
committerDaniel Carl <danielcarl@gmx.de>
Mon, 22 Jul 2013 17:38:18 +0000 (19:38 +0200)
In previous version it does not work to lookup commands like ':r<up>' and
change the input after the history was initialized. This caused none working
lookup if the first attempt did not find any item. For example if ':foo<up>'
did not find any item and the user change the inputbox into ':o<up>' which
should match items, this retrieved also no item.

This patch fixes also none working lookup of set commands like ':set s<up>'.

src/completion.c
src/history.c
src/main.c
src/main.h

index b1ce400..fecf725 100644 (file)
@@ -53,7 +53,7 @@ gboolean completion_complete(gboolean back)
     gboolean res = false, sort = true;
 
     input = GET_TEXT();
-    type  = vb_get_input_parts(input, &prefix, &suffix);
+    type  = vb_get_input_parts(input, VB_INPUT_ALL, &prefix, &suffix);
 
     if (vb.state.mode & VB_MODE_COMPLETE) {
         if (comp.text && !strcmp(input, comp.text)) {
index 4e08ef6..9545242 100644 (file)
@@ -37,12 +37,12 @@ typedef struct {
 } History;
 
 static struct {
-    char  *prefix;
-    char  *query;
+    char  *prefix;  /* prefix that is prepended to the history item to for the complete command */
+    char  *query;   /* part of input text to match the history items */
     GList *active;
 } history;
 
-static GList *get_list(const char *input);
+static GList *get_list(VbInputType type, const char *query);
 static const char *get_file_by_type(HistoryType type);
 static GList *load(const char *file);
 static void write_to_file(GList *list, const char *file);
@@ -91,13 +91,33 @@ void history_add(HistoryType type, const char *value, const char *additional)
  */
 char *history_get(const char *input, gboolean prev)
 {
+    VbInputType type;
+    const char *prefix, *query;
     GList *new = NULL;
 
+    if (history.active) {
+        /* calculate the actual content of the inpubox from history data, if
+         * the theoretical content and the actual given input are different
+         * rewind the history to recreate it later new */
+        char *current = g_strconcat(history.prefix, (char*)history.active->data, NULL);
+        if (strcmp(input, current)) {
+            history_rewind();
+        }
+        g_free(current);
+    }
+
+    /* create the history list if the lookup is started or input was changed */
     if (!history.active) {
-        history.active = get_list(input);
-        /* start with latest added items */
-        history.active = g_list_first(history.active);
-        history.active = g_list_prepend(history.active, g_strdup(""));
+        type = vb_get_input_parts(
+            input, VB_INPUT_COMMAND|VB_INPUT_SEARCH_FORWARD|VB_INPUT_SEARCH_BACKWARD,
+            &prefix, &query
+        );
+        history.active = get_list(type, query);
+        if (!history.active) {
+            return NULL;
+        }
+        OVERWRITE_STRING(history.query, query);
+        OVERWRITE_STRING(history.prefix, prefix);
     }
 
     if (prev) {
@@ -118,6 +138,7 @@ void history_rewind(void)
         g_list_free_full(history.active, (GDestroyNotify)g_free);
 
         OVERWRITE_STRING(history.prefix, NULL);
+        OVERWRITE_STRING(history.query, NULL);
         history.active = NULL;
     }
 }
@@ -194,44 +215,38 @@ gboolean history_fill_completion(GtkListStore *store, HistoryType type, const ch
  * Retrieves the list of matching history items.
  * The list must be freed.
  */
-static GList *get_list(const char *input)
+static GList *get_list(VbInputType type, const char *query)
 {
-    VbInputType input_type;
-    HistoryType type;
-    GList *result = NULL;
-    const char *prefix, *suffix;
-
-    input_type = vb_get_input_parts(input, &prefix, &suffix);
-
-    /* get the right history type and command prefix */
-    if (input_type == VB_INPUT_COMMAND
-        || input_type == VB_INPUT_OPEN
-        || input_type == VB_INPUT_TABOPEN
-    ) {
-        type = HISTORY_COMMAND;
-        OVERWRITE_STRING(history.query, suffix);
-        OVERWRITE_STRING(history.prefix, prefix);
-    } else if (input_type == VB_INPUT_SEARCH_FORWARD
-        || input_type == VB_INPUT_SEARCH_BACKWARD
-    ) {
-        type = HISTORY_SEARCH;
-        OVERWRITE_STRING(history.query, suffix);
-        OVERWRITE_STRING(history.prefix, prefix);
-    } else {
-        return NULL;
-    }
+    GList *result = NULL, *src = NULL;
+
+    switch (type) {
+        case VB_INPUT_COMMAND:
+            src = load(get_file_by_type(HISTORY_COMMAND));
+            break;
 
-    GList *src = load(get_file_by_type(type));
+        case VB_INPUT_SEARCH_FORWARD:
+        case VB_INPUT_SEARCH_BACKWARD:
+            src = load(get_file_by_type(HISTORY_SEARCH));
+            break;
+
+        default:
+            return NULL;
+    }
 
     /* generate new history list with the matching items */
     for (GList *l = src; l; l = l->next) {
         History *item = l->data;
-        if (g_str_has_prefix(item->first, history.query)) {
+        if (g_str_has_prefix(item->first, query)) {
             result = g_list_prepend(result, g_strdup(item->first));
         }
     }
     g_list_free_full(src, (GDestroyNotify)free_history);
 
+    /* prepend the original query as own item like done in vim to have the
+     * origianl input string in input box if we step before the first real
+     * item */
+    result = g_list_prepend(result, g_strdup(query));
+
     return result;
 }
 
index b821b3a..e1cec33 100644 (file)
@@ -333,7 +333,8 @@ void vb_update_urlbar(const char *uri)
  * ...) and set the given prefix pointer to the found prefix and the given
  * suffix pointer to the suffix.
  */
-VbInputType vb_get_input_parts(const char* input, const char **prefix, const char **clean)
+VbInputType vb_get_input_parts(const char* input, unsigned int use,
+    const char **prefix, const char **clean)
 {
     static const struct {
         VbInputType type;
@@ -350,6 +351,10 @@ VbInputType vb_get_input_parts(const char* input, const char **prefix, const cha
         {VB_INPUT_SEARCH_BACKWARD, "?", 1},
     };
     for (unsigned int i = 0; i < LENGTH(types); i++) {
+        /* process only those types given with use */
+        if (!(types[i].type & use)) {
+            continue;
+        }
         if (!strncmp(input, types[i].prefix, types[i].len)) {
             *prefix = types[i].prefix;
             *clean  = input + types[i].len;
index 3bdb210..9aa74da 100644 (file)
@@ -124,12 +124,13 @@ typedef enum _vb_mode {
 
 typedef enum {
     VB_INPUT_UNKNOWN,
-    VB_INPUT_SET,
-    VB_INPUT_OPEN,
-    VB_INPUT_TABOPEN,
-    VB_INPUT_COMMAND,
-    VB_INPUT_SEARCH_FORWARD,
-    VB_INPUT_SEARCH_BACKWARD
+    VB_INPUT_SET              = 1<<0,
+    VB_INPUT_OPEN             = 1<<1,
+    VB_INPUT_TABOPEN          = 1<<2,
+    VB_INPUT_COMMAND          = 1<<3,
+    VB_INPUT_SEARCH_FORWARD   = 1<<4,
+    VB_INPUT_SEARCH_BACKWARD  = 1<<5,
+    VB_INPUT_ALL              = VB_INPUT_OPEN | VB_INPUT_TABOPEN | VB_INPUT_SET | VB_INPUT_COMMAND | VB_INPUT_SEARCH_FORWARD | VB_INPUT_SEARCH_BACKWARD,
 } VbInputType;
 
 enum {
@@ -325,7 +326,8 @@ void vb_update_statusbar(void);
 void vb_update_status_style(void);
 void vb_update_input_style(void);
 void vb_update_urlbar(const char *uri);
-VbInputType vb_get_input_parts(const char* input, const char **prefix, const char **clean);
+VbInputType vb_get_input_parts(const char* input, unsigned int use,
+    const char **prefix, const char **clean);
 gboolean vb_download(WebKitWebView *view, WebKitDownload *download, const char *path);
 void vb_quit(void);