From 1dcd3d70d4d846a1e6c315d3e419fb7488c0fbba Mon Sep 17 00:00:00 2001 From: Daniel Carl Date: Mon, 9 Jun 2014 12:31:16 +0200 Subject: [PATCH] Allow shortcut params with spaces (#88). --- doc/vimb.1 | 7 ++++++ src/shortcut.c | 56 +++++++++++++++++++++++++++++++++---------- tests/test-shortcut.c | 42 ++++++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+), 12 deletions(-) diff --git a/doc/vimb.1 b/doc/vimb.1 index bfd35ea..83dbc8b 100644 --- a/doc/vimb.1 +++ b/doc/vimb.1 @@ -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" diff --git a/src/shortcut.c b/src/shortcut.c index 240b0b5..94990cd 100644 --- a/src/shortcut.c +++ b/src/shortcut.c @@ -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; } diff --git a/tests/test-shortcut.c b/tests/test-shortcut.c index 159c9a4..6733a06 100644 --- a/tests/test-shortcut.c +++ b/tests/test-shortcut.c @@ -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(); -- 2.20.1