Allow shortcut params with spaces (#88).
authorDaniel Carl <danielcarl@gmx.de>
Mon, 9 Jun 2014 10:31:16 +0000 (12:31 +0200)
committerDaniel Carl <danielcarl@gmx.de>
Mon, 9 Jun 2014 10:31:16 +0000 (12:31 +0200)
doc/vimb.1
src/shortcut.c
tests/test-shortcut.c

index bfd35ea..83dbc8b 100644 (file)
@@ -487,12 +487,19 @@ given when the shortcut is called. The parameters given when the shortcut is
 called will be split into as many parameters like the highest used
 placeholder.
 
+To use spaces within the parameters, the parameters can be grouped by
+surrounding them with single- or double quotes like shown in example shortcut
+`map'.
+
 .RS
 Examples:
 .IP ":shortcut-add dl=https://duckduckgo.com/lite/?q=$0"
 to setup a search engine. Can be called by `:open dl my search phrase'.
 .IP ":shortcut-add gh=https://github.com/$0/$1"
 to build URIs from given parameters. Can be called `:open gh fanglingsu vimb'.
+.IP ":shortcut-add map=https://maps.google.com/maps?saddr=$0&daddr=$1"
+to search for a route, all but the last parameter must be quoted if they
+contain spaces like `:open map "city hall, London" railway station, London'
 .RE
 .TP
 .BI ":shortcut-remove " "SHORTCUT"
index 240b0b5..94990cd 100644 (file)
@@ -70,36 +70,68 @@ gboolean shortcut_set_default(const char *key)
 char *shortcut_get_uri(const char *string)
 {
     const char *tmpl, *query = NULL;
-    char *uri, **parts, ph[3] = "$0";
-    unsigned int len;
-    int max;
+    char *uri, **argv, *quoted_param, ph[3] = "$0";
+    int i, max, argc;
+    GError *error = NULL;
 
     tmpl = shortcut_lookup(string, &query);
     if (!tmpl) {
         return NULL;
     }
 
-    uri = g_strdup(tmpl);
     max = get_max_placeholder(tmpl);
+    /* if there are only $0 placeholders we don't need to split the parameters */
+    if (max == 0) {
+        quoted_param = soup_uri_encode(query, "&");
+        uri          = util_str_replace(ph, quoted_param, tmpl);
+        g_free(quoted_param);
+
+        return uri;
+    }
+
+    uri = g_strdup(tmpl);
+
     /* skip if no placeholders found */
     if (max < 0) {
         return uri;
     }
 
-    /* split the parameters */
-    parts = g_strsplit(query, " ", max + 1);
-    len   = g_strv_length(parts);
+    /* for multiple placeholders - split the parameters */
+    if (!g_shell_parse_argv(query, &argc, &argv, &error)) {
+#ifndef TESTLIB
+        vb_echo(VB_MSG_ERROR, true, error->message);
+#endif
+        g_clear_error(&error);
+
+        /* us the shortcut template uri like it is */
+        return uri;
+    }
+
+    for (i = 0; i < argc; i++) {
+        char *new, *qs, *combined;
+
+        ph[1] = i + '0';
+        /* if we reached the last placeholder put all other tokens into it */
+        if (i >= max) {
+            combined = g_strjoinv(" ", &(argv[i]));
+            qs       = soup_uri_encode(combined, "&");
+            new      = util_str_replace(ph, qs, uri);
+            g_free(combined);
+            g_free(qs);
+            g_free(uri);
+            uri = new;
+
+            /* we are done - break the loop */
+            break;
+        }
 
-    for (unsigned int n = 0; n < len; n++) {
-        char *new, *qs;
-        ph[1] = n + '0';
-        qs  = soup_uri_encode(parts[n], "&");
+        qs  = soup_uri_encode(argv[i], "&");
         new = util_str_replace(ph, qs, uri);
         g_free(qs);
         g_free(uri);
         uri = new;
     }
-    g_strfreev(parts);
+    g_strfreev(argv);
 
     return uri;
 }
index 159c9a4..6733a06 100644 (file)
@@ -28,6 +28,16 @@ static void test_shortcut_single(void)
     uri = shortcut_get_uri("_vimb1_ zero one");
     g_assert_cmpstr(uri, ==, "only-zero:zero%20one");
     g_free(uri);
+
+    /* don't fail on unmatches quotes if there are only $0 placeholders */
+    uri = shortcut_get_uri("_vimb1_ 'unmatched quote");
+    g_assert_cmpstr(uri, ==, "only-zero:'unmatched%20quote");
+    g_free(uri);
+
+    /* check if all placeholders $0 are replaces */
+    uri = shortcut_get_uri("_vimb5_ one two");
+    g_assert_cmpstr(uri, ==, "double-zero:one%20two-one%20two");
+    g_free(uri);
 }
 
 static void test_shortcut_default(void)
@@ -61,6 +71,34 @@ static void test_shortcut_fullrange(void)
     g_free(uri);
 }
 
+static void test_shortcut_shell_param(void)
+{
+    char *uri;
+
+    /* single quotes */
+    uri = shortcut_get_uri("_vimb6_ 'rail station' 'city hall'");
+    g_assert_cmpstr(uri, ==, "shell:rail%20station-city%20hall");
+    g_free(uri);
+
+    /* double quotes */
+    uri = shortcut_get_uri("_vimb6_ \"rail station\" city hall");
+    g_assert_cmpstr(uri, ==, "shell:rail%20station-city%20hall");
+    g_free(uri);
+}
+
+static void test_shortcut_shell_param_invalid(void)
+{
+    char *uri;
+    /* if parsing fails we expect the shortcut template to be returned */
+    uri = shortcut_get_uri("_vimb6_ 'rail station' 'city hall");
+    g_assert_cmpstr(uri, ==, "shell:$0-$1");
+    g_free(uri);
+
+    uri = shortcut_get_uri("_vimb6_ can't parse");
+    g_assert_cmpstr(uri, ==, "shell:$0-$1");
+    g_free(uri);
+}
+
 static void test_shortcut_remove(void)
 {
     char *uri;
@@ -81,6 +119,8 @@ int main(int argc, char *argv[])
     g_assert_true(shortcut_add("_vimb2_", "default:$0-$2"));
     g_assert_true(shortcut_add("_vimb3_", "fullrange:$0-$1-$9"));
     g_assert_true(shortcut_add("_vimb4_", "for-remove:$0"));
+    g_assert_true(shortcut_add("_vimb5_", "double-zero:$0-$0"));
+    g_assert_true(shortcut_add("_vimb6_", "shell:$0-$1"));
     g_assert_true(shortcut_set_default("_vimb2_"));
 
     g_test_init(&argc, &argv, NULL);
@@ -89,6 +129,8 @@ int main(int argc, char *argv[])
     g_test_add_func("/test-shortcut/get_uri/default", test_shortcut_default);
     g_test_add_func("/test-shortcut/get_uri/keep-unmatched", test_shortcut_keep_unmatched);
     g_test_add_func("/test-shortcut/get_uri/fullrange", test_shortcut_fullrange);
+    g_test_add_func("/test-shortcut/get_uri/shell-param", test_shortcut_shell_param);
+    g_test_add_func("/test-shortcut/get_uri/shell-param-invalid", test_shortcut_shell_param_invalid);
     g_test_add_func("/test-shortcut/remove", test_shortcut_remove);
 
     result = g_test_run();