Allow multiple placeholder in shortcuts.
authorDaniel Carl <danielcarl@gmx.de>
Sun, 28 Apr 2013 12:35:27 +0000 (14:35 +0200)
committerDaniel Carl <danielcarl@gmx.de>
Sun, 28 Apr 2013 12:53:15 +0000 (14:53 +0200)
The single previous %s placeholder for url shortcuts is now removed by
placeholders $0-$9 that make vimb browser more usable and the shortcut system
more flexible.

The $0 placeholder will be removed by all query parameter. So the previous
search engine feature can be build up with this new shortcut feature. For
example use 'dl=https://duckduckgo.com/lite/?q=$0' to define a shortcut for
the great duckduckgo search engine.

doc/vimb.1.txt
src/config.h
src/setting.c
src/shortcut.c
src/util.c
src/util.h

index 2ceffd6..511d53c 100644 (file)
@@ -251,26 +251,32 @@ Yank the current url to the primary and secondary clipboard.
 .B yank-selection
 Yank the selected text into the primary and secondary clipboard.
 .SS Shortcuts
-Shortcuts allows to open URL build up from a named tamplate with additional
-parameters. If a sortcut named 'dd' is defined, you can use it with `:open dd
+Shortcuts allows to open URL build up from a named template with additional
+parameters. If a shortcut named 'dd' is defined, you can use it with `:open dd
 list of parameters' to open the generated URL.
 
-Shortcuts are a good to use searchengines where the URL is nearly the same but
-a single parameter is user diefined.
+Shortcuts are a good to use with search engines where the URL is nearly the
+same but a single parameter is user defined.
 .TP
 .BI "shortcut-add " "SHORTCUT" "=" "URI"
-Adds a shortcut with the \fISHORTCUT\fP and search \fIURI\fP. The uri must
-not contain more than one '%s' placeholder.
+Adds a shortcut with the \fISHORTCUT\fP and search \fIURI\fP. The \fIURI\fP
+can contain multiple placeholders $0-$9 that will be filled by the parameters
+given when the shortcut is called. The $0 placeholder will be filled with all
+given parameters (this is useful for search engines), all other placeholders $1
+to $9 will be replaced by the numbered argument.
 
-Example: shortcut-add dl=https://duckduckgo.com/lite/?q=%s
+Example 1: shortcut-add dl=https://duckduckgo.com/lite/?q=$0 to setup a
+search engine. Can be called by `:open dl my search phrase'.
+
+Example 2: shortcut-add gh=https://github.com/$1/$2 to build urls from given
+parameters. Can be called `:open gh fanglingsu vimb'.
 .TP
 .BI "shortcut-remove " "SHORTCUT"
 Remove the search engine to the given \fISHORTCUT\fP.
 .TP
 .BI "shortcut-default " "SHORTCUT"
-Set the search engine for given \fISHORTCUT\fP as the default search engine.
-It doesn't metter if the \fISHORTCUT\fP is already in use or not to be able to
-set the default search engine.
+Set the shortcut for given \fISHORTCUT\fP as the default. It doesn't matter if
+the \fISHORTCUT\fP is already in use or not to be able to set it.
 .SS Configuration
 .TP
 .BI "set " VAR = VALUE
index 838ffff..2c5ec29 100644 (file)
@@ -92,8 +92,8 @@ const char *default_config[] = {
     "cmap <up>=hist-prev",
     "cmap <down>=hist-next",
     "imap <ctrl-t>=editor",
-    "shortcut-add dl=https://duckduckgo.com/lite/?q=%s",
-    "shortcut-add dd=https://duckduckgo.com/?q=%s",
+    "shortcut-add dl=https://duckduckgo.com/lite/?q=$0",
+    "shortcut-add dd=https://duckduckgo.com/?q=$0",
     "shortcut-default dl",
     "set images=on",
     "set cursivfont=serif",
index 671470d..bc3be88 100644 (file)
@@ -702,9 +702,6 @@ static gboolean editor_command(const Setting *s, const SettingType type)
         return true;
     }
 
-    if (!util_valid_format_string(s->arg.s, 's', 1)) {
-        return false;
-    }
     OVERWRITE_STRING(vb.config.editor_command, s->arg.s);
 
     return true;
index 6df33c2..7d53b1a 100644 (file)
@@ -26,6 +26,7 @@ extern VbCore vb;
 static GHashTable *shortcuts = NULL;
 static char *default_key = NULL;
 
+static int get_max_placeholder(const char *str);
 static const char *shortcut_lookup(const char *string, const char **query);
 
 
@@ -43,16 +44,7 @@ void shortcut_cleanup(void)
 
 gboolean shortcut_add(const char *key, const char *uri)
 {
-    char *sc_key, *sc_uri;
-    /* validate if the uri contains only one %s sequence */
-    if (!util_valid_format_string(uri, 's', 1)) {
-        return false;
-    }
-
-    sc_key = g_strdup(key);
-    sc_uri = g_strdup(uri);
-
-    g_hash_table_insert(shortcuts, sc_key, sc_uri);
+    g_hash_table_insert(shortcuts, g_strdup(key), g_strdup(uri));
 
     return true;
 }
@@ -78,17 +70,62 @@ gboolean shortcut_set_default(const char *key)
 char *shortcut_get_uri(const char *string)
 {
     const char *tmpl, *query = NULL;
-    if ((tmpl = shortcut_lookup(string, &query))) {
-        char *qs, *uri;
 
-        qs  = soup_uri_encode(query, "&");
-        uri = g_strdup_printf(tmpl, qs);
-        g_free(qs);
+    tmpl = shortcut_lookup(string, &query);
+    if (!tmpl) {
+        return NULL;
+    }
 
+    char *qs, *uri, **parts, ph[3] = "$0";
+    unsigned int len;
+
+    /* replace $0 with all parameters */
+    qs = soup_uri_encode(query, "&");
+    uri = util_str_replace(ph, qs, tmpl);
+    g_free(qs);
+
+    int max = get_max_placeholder(tmpl);
+    /* skip if no placeholders found */
+    if (max < 0) {
         return uri;
     }
 
-    return NULL;
+    /* split the parameters */
+    parts = g_strsplit(query, " ", max + 1);
+    len   = g_strv_length(parts);
+
+    for (unsigned int n = 0; n < len; n++) {
+        char *new;
+        ph[1] = n + '1';
+        qs  = soup_uri_encode(parts[n], "&");
+        new = util_str_replace(ph, qs, uri);
+        g_free(qs);
+        g_free(uri);
+        uri = new;
+    }
+    g_strfreev(parts);
+
+    return uri;
+}
+
+/**
+ * Retrieves th highest placesholder number used in given string.
+ * If no placeholder is found -1 is returned.
+ */
+static int get_max_placeholder(const char *str)
+{
+    int n, res;
+
+    for (n = 0, res = -1; *str; str++) {
+        if (*str == '$') {
+            n = *(++str) - '0';
+            if (0 <= n && n <= 9 && n > res) {
+                res = n;
+            }
+        }
+    }
+
+    return res;
 }
 
 /**
index ba5af22..7ff7b76 100644 (file)
@@ -121,22 +121,20 @@ next:
 }
 
 /**
- * Checks if given printf style format string is valid. That means that it
- * contains only one defined placeholder given as char.
+ * Replaces appearances of search in string by given replace.
+ * Returne a new allocated string of search was found.
  */
-gboolean util_valid_format_string(const char *format, char type, unsigned int count)
+char *util_str_replace(const char* search, const char* replace, const char* string)
 {
-    unsigned int c;
-    for (c = 0; *format; format++) {
-        if (*format == '%') {
-            format++;
-            if (*format == type) {
-                c++;
-            }
-        }
+    if (!string) {
+        return NULL;
     }
 
-    return c == count;
+    char **buf = g_strsplit(string, search, -1);
+    char *ret  = g_strjoinv(replace, buf);
+    g_strfreev(buf);
+
+    return ret;
 }
 
 /**
index 8255b30..804832e 100644 (file)
@@ -30,7 +30,7 @@ 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);
-gboolean util_valid_format_string(const char *format, char type, unsigned int count);
+char *util_str_replace(const char* search, const char* replace, const char* string);
 gboolean util_create_tmp_file(const char *content, char **file);
 
 #endif /* end of include guard: _UTIL_H */