Added url completion for :open and :tabopen commands.
authorDaniel Carl <danielcarl@gmx.de>
Sun, 3 Mar 2013 16:22:09 +0000 (17:22 +0100)
committerDaniel Carl <danielcarl@gmx.de>
Sun, 3 Mar 2013 16:22:09 +0000 (17:22 +0100)
src/completion.c
src/url_history.c
src/url_history.h
src/util.c
src/util.h

index 5ce48ce..a2f5f5e 100644 (file)
  */
 
 #include "completion.h"
+#include "util.h"
+#include "url_history.h"
 
+typedef gboolean (*Comp_Func)(char*, const char*);
 typedef struct {
     GtkWidget* label;
     GtkWidget* event;
     char*     prefix;
 } Completion;
 
-static GList* completion_init_completion(GList* target, GList* source, const char* prefix);
+static GList* completion_init_completion(GList* target, GList* source, Comp_Func func, const char* prefix);
 static GList* completion_update(GList* completion, GList* active, gboolean back);
 static void completion_show(gboolean back);
 static void completion_set_color(Completion* completion, const VpColor* fg, const VpColor* bg, PangoFontDescription* font);
@@ -58,14 +61,26 @@ gboolean completion_complete(gboolean back)
 
     input = GET_TEXT();
     /* TODO move these decision to a more generic place */
-    if (g_str_has_prefix(input, ":set ")) {
+    if (!strncmp(input, ":set ", 5)) {
         source = g_hash_table_get_keys(core.settings);
-        source = g_list_sort(source, (GCompareFunc)g_strcmp0);
-        vp.comps.completions = completion_init_completion(vp.comps.completions, source, ":set ");
+        vp.comps.completions = completion_init_completion(
+            vp.comps.completions, source, (Comp_Func)g_str_has_prefix, ":set "
+        );
+    } else if (!strncmp(input, ":open ", 6)) {
+        source = url_history_get_all();
+        vp.comps.completions = completion_init_completion(
+            vp.comps.completions, source, (Comp_Func)util_strcasestr, ":open "
+        );
+    } else if (!strncmp(input, ":tabopen ", 9)) {
+        source = url_history_get_all();
+        vp.comps.completions = completion_init_completion(
+            vp.comps.completions, source, (Comp_Func)util_strcasestr, ":tabopen "
+        );
     } else {
         source = g_hash_table_get_keys(core.behave.commands);
-        source = g_list_sort(source, (GCompareFunc)g_strcmp0);
-        vp.comps.completions = completion_init_completion(vp.comps.completions, source, ":");
+        vp.comps.completions = completion_init_completion(
+            vp.comps.completions, source, (Comp_Func)g_str_has_prefix, ":"
+        );
     }
 
     if (!vp.comps.completions) {
@@ -92,7 +107,7 @@ void completion_clean(void)
     vp.state.mode &= ~VP_MODE_COMPLETE;
 }
 
-static GList* completion_init_completion(GList* target, GList* source, const char* prefix)
+static GList* completion_init_completion(GList* target, GList* source, Comp_Func func, const char* prefix)
 {
     const char* input = GET_TEXT();
     char* command = NULL;
@@ -110,6 +125,7 @@ static GList* completion_init_completion(GList* target, GList* source, const cha
 
     token = g_strsplit(command, " ", -1);
 
+    source = g_list_sort(source, (GCompareFunc)g_strcmp0);
     for (GList* l = source; l; l = l->next) {
         data = l->data;
         match = FALSE;
@@ -117,7 +133,7 @@ static GList* completion_init_completion(GList* target, GList* source, const cha
             match = TRUE;
         } else {
             for (int i = 0; token[i]; i++) {
-                if (g_str_has_prefix(data, token[i])) {
+                if (func(data, token[i])) {
                     match = TRUE;
                 } else {
                     match = FALSE;
index cf09af8..f0aba78 100644 (file)
@@ -83,6 +83,18 @@ void url_history_add(const char* url, const char* title)
     core.behave.url_history = g_list_prepend(core.behave.url_history, item);
 }
 
+GList* url_history_get_all(void)
+{
+    GList* out = NULL;
+    for (GList* link = core.behave.url_history; link; link = link->next) {
+        UrlHist* hi = (UrlHist*)link->data;
+        /* put only the url in the list - do not allocate new memory */
+        out = g_list_prepend(out, hi->uri);
+    }
+
+    return out;
+}
+
 static void url_history_free(UrlHist* item)
 {
     g_free(item->uri);
index 36704c0..32bd86a 100644 (file)
@@ -9,5 +9,6 @@ typedef struct {
 void url_history_init(void);
 void url_history_cleanup(void);
 void url_history_add(const char* url, const char* title);
+GList* url_history_get_all(void);
 
 #endif /* end of include guard: _URL_HISTORY_H */
index 748ea9d..9a30e14 100644 (file)
@@ -17,8 +17,9 @@
  * along with this program. If not, see http://www.gnu.org/licenses/.
  */
 
-#include "util.h"
 #include <stdio.h>
+#include "ctype.h"
+#include "util.h"
 
 char* util_get_config_dir(void)
 {
@@ -96,3 +97,25 @@ char** util_get_lines(const char* filename)
     }
     return lines;
 }
+
+char* util_strcasestr(const char* haystack, const char* needle)
+{
+    int nlen = strlen(needle);
+    int hlen = strlen(haystack) - nlen + 1;
+    int i;
+
+    for (i = 0; i < hlen; i++) {
+        int j;
+        for (j = 0; j < nlen; j++) {
+            unsigned char c1 = haystack[i + j];
+            unsigned char c2 = needle[j];
+            if (toupper(c1) != toupper(c2)) {
+                goto next;
+            }
+        }
+        return (char*)haystack + i;
+next:
+        ;
+    }
+    return NULL;
+}
index ba77d53..d69a532 100644 (file)
@@ -29,5 +29,6 @@ void util_create_dir_if_not_exists(const char* dirpath);
 void util_create_file_if_not_exists(const char* filename);
 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);
 
 #endif /* end of include guard: _UTIL_H */