Implemented prefix aware history searching (#7).
authorDaniel Carl <danielcarl@gmx.de>
Sun, 24 Feb 2013 19:24:05 +0000 (20:24 +0100)
committerDaniel Carl <danielcarl@gmx.de>
Sun, 24 Feb 2013 19:24:05 +0000 (20:24 +0100)
If ':set' is already typed in the inputbox, the history will only step over
those items that matches this prefix. Now vimp behave a little bit more like
the great vim editor.

doc/vimp.1.txt
src/command.c
src/history.c
src/history.h
src/main.h

index c4f1187..0454140 100644 (file)
@@ -287,6 +287,8 @@ Reset the zoomlevel to the default value.
 Prints the previous or next cammand from history into inputbox. If \fIPREFIX\fP
 is given, this will be used as prefix for the inserted command, else the
 default ':' will be used.
+If there is already text in the input box this will be used to get previous
+history items.
 .SS Misc
 .TP
 .BI [ N "]search-forward, [" N "]search-backward"
index 02398a6..3a96bdb 100644 (file)
@@ -25,6 +25,7 @@
 #include "hints.h"
 #include "util.h"
 #include "searchengine.h"
+#include "history.h"
 
 static CommandInfo cmd_list[] = {
     /* command              function             arg                                                                                 mode */
@@ -529,23 +530,17 @@ gboolean command_zoom(const Arg* arg)
 
 gboolean command_history(const Arg* arg)
 {
-    const int len   = g_list_length(core.behave.history);
-    char* message   = NULL;
+    char* msg = NULL;
     const int count = vp.state.count ? vp.state.count : 1;
+    const gint step = count * (arg->i == VP_SEARCH_BACKWARD ? -1 : 1);
+    const char* entry = history_get(step);
 
-    if (!len) {
+    if (!entry) {
         return FALSE;
     }
-    if (arg->i == VP_SEARCH_BACKWARD) {
-        core.behave.history_pointer = (len + core.behave.history_pointer - count) % len;
-    } else {
-        core.behave.history_pointer = (len + core.behave.history_pointer + count) % len;
-    }
-
-    const char* command = (char*)g_list_nth_data(core.behave.history, core.behave.history_pointer);
-    message = g_strconcat(arg->s, command, NULL);
-    command_write_input(message);
-    g_free(message);
+    msg = g_strconcat(arg->s, entry, NULL);
+    command_write_input(msg);
+    g_free(msg);
 
     return TRUE;
 }
index 817005f..0b0c087 100644 (file)
@@ -36,7 +36,43 @@ void history_append(const char* line)
     core.behave.history = g_list_append(core.behave.history, g_strdup(line));
 }
 
+const char* history_get(const int step)
+{
+    const char* command;
+    GList* history = NULL;
+
+    /* get the search prefix only on start of history search */
+    if (!vp.state.history_prefix) {
+        const char* text = GET_TEXT();
+        /* TODO at the moment we skip only the first char of input box but
+         * maybe we'll have history items that have a longer or no prefix */
+        OVERWRITE_STRING(vp.state.history_prefix, (text + 1));
+    }
+
+    for (GList* l = core.behave.history; l; l = l->next) {
+        char* entry = (char*)l->data;
+        if (g_str_has_prefix(entry, vp.state.history_prefix)) {
+            history = g_list_prepend(history, entry);
+        }
+    }
+
+    const int len = g_list_length(history);
+    if (!len) {
+        return NULL;
+    }
+
+    history = g_list_reverse(history);
+
+    /* if reached end/beginnen start at the opposit site of list again */
+    vp.state.history_pointer = (len + vp.state.history_pointer + step) % len;
+
+    command = (char*)g_list_nth_data(history, vp.state.history_pointer);
+
+    return command;
+}
+
 void history_rewind(void)
 {
-    core.behave.history_pointer = 0;
+    vp.state.history_pointer = 0;
+    OVERWRITE_STRING(vp.state.history_prefix, NULL);
 }
index 476a46c..d6c3ccf 100644 (file)
@@ -22,6 +22,7 @@
 
 void history_cleanup(void);
 void history_append(const char* line);
+const char* history_get(const int step);
 void history_rewind(void);
 
 #endif /* end of include guard: _HISTORY_H */
index 7c80029..a794b12 100644 (file)
@@ -228,6 +228,8 @@ typedef struct {
     SearchDirection search_dir;
     char*           search_query;
     GList*          downloads;
+    int             history_pointer;
+    char*           history_prefix;
 } State;
 
 /* behaviour */
@@ -237,7 +239,6 @@ typedef struct {
     GString*    modkeys;
     GSList*     searchengines;
     GList*      history;
-    int         history_pointer;
 } Behaviour;
 
 typedef struct {