.\" groff -man -Tascii vimb.1
 .TH PROJECT 1 "23/03/2013" "PROJECT/VERSION" "Vimb Manual"
 .SH NAME
-PROJECT \- A modal web browser based on webkit thats inspired by vim the great editor.
+PROJECT \- Vim Browser - A modal web browser based on webkit thats inspired by
+vim the great editor.
 .SH SYNOPSIS
 .BI "PROJECT [" "OPTION" "] [" "URI" "]"
 .SH DESCRIPTION
-.B PROJECT
-is a webkit based web browser that behaves like the vimperator
+PROJECT is a webkit based web browser that behaves like the vimperator
 plugin for the firefox and usage paradigms from the great editor vim. The goal
 of PROJECT is to build a completely keyboard-driven, efficient and pleasurable
 browsing-experience.
 For example the command "hint-focus-next" is only available in hinting mode.
 To call it, it has to be bound to a key like "hmap <tab>=hint-focus-next" to
 be used.
+
 .SS Open
 .TP
 .BI "open [" URI ]
 into inputbox that begins with \fI[:/?]\fP. So the history contains real
 commands and search queries.
 .SS Misc
+.TP
+.BI run " [COMMAND LIST]"
+Run is a command, that was introduced to have the ability to run multiple
+other commands with a single call. Everything after the `run' is interpreted
+as a `|' seperated list of commands and parameters.
+":run [count]command[ param[=value]]|[count]command[ param[=value]]|..."
+
+The run command allows to use fancy keybindings that set several config
+settings with only on keypress.
+
+Example:
+
+:run set input-bg-normal=#ff0 | set input-fg-normal=#f0f | 5pagedown
+
 .TP
 .BI [ N "]search-forward, [" N "]search-backward"
 Search in current page forward or backward.
 
     {"zoomreset",           command_zoom,        {COMMAND_ZOOM_RESET}},
     {"hist-next",           command_history,     {0}},
     {"hist-prev",           command_history,     {1}},
+    {"run",                 command_run_multi,   {0}},
 };
 
 
     return result;
 }
 
+/**
+ * Runs a single command form string containing the command an possible
+ * parameters.
+ */
+gboolean command_run_string(const char *input)
+{
+    gboolean success;
+    char *command = NULL, *str, **token;
+
+    if (!input || *input == '\0') {
+        return FALSE;
+    }
+
+    str =g_strdup(input);
+    g_strstrip(str);
+
+    /* get a possible command count */
+    vb.state.count = g_ascii_strtoll(str, &command, 10);
+
+    /* split the input string into command and parameter part */
+    token = g_strsplit(command, " ", 2);
+    g_free(str);
+
+    if (!token[0]) {
+        g_strfreev(token);
+        return FALSE;
+    }
+    success = command_run(token[0], token[1] ? token[1] : NULL);
+    g_strfreev(token);
+
+    return success;
+}
+
+/**
+ * Runs multiple commands that are seperated by |.
+ */
+gboolean command_run_multi(const Arg *arg)
+{
+    gboolean result = TRUE;
+    char **commands, *input;
+    unsigned int len, i;
+
+    if (!arg->s || *(arg->s) == '\0') {
+        return FALSE;
+    }
+
+    input = g_strdup(arg->s);
+    g_strstrip(input);
+
+    /* splits the commands */
+    commands = g_strsplit(input, "|", 0);
+    g_free(input);
+
+    len = g_strv_length(commands);
+    if (!len) {
+        g_strfreev(commands);
+        return FALSE;
+    }
+
+    for (i = 0; i < len; i++) {
+        /* run the single commands */
+        result = (result && command_run_string(commands[i]));
+    }
+    g_strfreev(commands);
+
+    return result;
+}
+
 gboolean command_open(const Arg *arg)
 {
     return vb_load_uri(arg);
 
 void command_cleanup(void);
 gboolean command_exists(const char *name);
 gboolean command_run(const char *name, const char *param);
+gboolean command_run_string(const char *input);
 
+gboolean command_run_multi(const Arg *arg);
 gboolean command_open(const Arg *arg);
 gboolean command_open_home(const Arg *arg);
 gboolean command_open_closed(const Arg *arg);
 
     WebKitNetworkResponse *response);
 
 /* functions */
-static gboolean vb_process_input(const char *input);
 static void vb_run_user_script(WebKitWebFrame *frame);
 static char *vb_jsref_to_string(JSContextRef context, JSValueRef ref);
 static void vb_init_core(void);
 
         case ':':
             completion_clean();
-            vb_process_input((command + 1));
+            command_run_string((command + 1));
             history_add(HISTORY_COMMAND, command + 1);
             break;
     }
     g_free(vb.gui.inspector);
 }
 
-/**
- * Processed input from input box without trailing : or ? /, input from config
- * file and default config.
- */
-static gboolean vb_process_input(const char *input)
-{
-    gboolean success;
-    char *command = NULL, **token;
-
-    if (!input || !strlen(input)) {
-        return FALSE;
-    }
-
-    /* get a possible command count */
-    vb.state.count = g_ascii_strtoll(input, &command, 10);
-
-    /* split the input string into command and parameter part */
-    token = g_strsplit(command, " ", 2);
-
-    if (!token[0]) {
-        g_strfreev(token);
-        return FALSE;
-    }
-    success = command_run(token[0], token[1] ? token[1] : NULL);
-    g_strfreev(token);
-
-    return success;
-}
-
 #ifdef FEATURE_COOKIE
 static void vb_set_cookie(SoupCookie *cookie)
 {
 
     /* load default config */
     for (guint i = 0; default_config[i].command != NULL; i++) {
-        if (!vb_process_input(default_config[i].command)) {
+        if (!command_run_string(default_config[i].command)) {
             fprintf(stderr, "Invalid default config: %s\n", default_config[i].command);
         }
     }
             if (!g_ascii_isalpha(line[0])) {
                 continue;
             }
-            if (!vb_process_input(line)) {
+            if (!command_run_string(line)) {
                 fprintf(stderr, "Invalid config: %s\n", line);
             }
         }