Added ':normal' command to run normal mode commands from input box.
authorDaniel Carl <danielcarl@gmx.de>
Sun, 13 Oct 2013 19:06:04 +0000 (21:06 +0200)
committerDaniel Carl <danielcarl@gmx.de>
Sun, 13 Oct 2013 19:20:41 +0000 (21:20 +0200)
This allows to run normal mode commands from input box, for example after
setting some options like ':set scripts!|no! R'.

doc/vimb.1
src/ex.c
src/map.c
src/map.h

index a0f6b43..eefde41 100644 (file)
@@ -513,6 +513,14 @@ value.
 
 Example:
 ":eval document.cookie"
+.TP
+.BI ":no[rmal][!] [" CMDS ]
+Execute normal mode commands \fICMDS\fP. This makes it possible to execute
+normal mode commands typed on the input box. If the \fI!\fP is given, mappings
+will not be used.
+
+Example:
+":set scripts!|no! R"
 
 .SH INPUT MODE
 
index 90efb9f..7d22407 100644 (file)
--- a/src/ex.c
+++ b/src/ex.c
@@ -49,6 +49,7 @@ typedef enum {
     EX_CUNMAP,
     EX_IUNMAP,
     EX_NUNMAP,
+    EX_NORMAL,
     EX_OPEN,
 #ifdef FEATURE_QUEUE
     EX_QCLEAR,
@@ -105,6 +106,7 @@ static gboolean ex_bookmark(const ExArg *arg);
 static gboolean ex_eval(const ExArg *arg);
 static gboolean ex_map(const ExArg *arg);
 static gboolean ex_unmap(const ExArg *arg);
+static gboolean ex_normal(const ExArg *arg);
 static gboolean ex_open(const ExArg *arg);
 static gboolean ex_queue(const ExArg *arg);
 static gboolean ex_quit(const ExArg *arg);
@@ -138,6 +140,7 @@ static ExInfo commands[] = {
     {"imap",             EX_IMAP,        ex_map,        EX_FLAG_LHS|EX_FLAG_RHS},
     {"iunmap",           EX_IUNMAP,      ex_unmap,      EX_FLAG_LHS},
     {"nmap",             EX_NMAP,        ex_map,        EX_FLAG_LHS|EX_FLAG_RHS},
+    {"normal",           EX_NORMAL,      ex_normal,     EX_FLAG_BANG|EX_FLAG_LHS},
     {"nunmap",           EX_NUNMAP,      ex_unmap,      EX_FLAG_LHS},
     {"open",             EX_OPEN,        ex_open,       EX_FLAG_RHS},
     {"quit",             EX_QUIT,        ex_quit,       EX_FLAG_NONE},
@@ -730,6 +733,16 @@ static gboolean ex_unmap(const ExArg *arg)
     return true;
 }
 
+static gboolean ex_normal(const ExArg *arg)
+{
+    mode_enter('n');
+
+    /* if called with bang - don't apply mapping */
+    map_handle_string(arg->lhs->str, !arg->bang);
+
+    return true;
+}
+
 static gboolean ex_open(const ExArg *arg)
 {
     if (arg->code == EX_TABOPEN) {
index a783024..646c6fe 100644 (file)
--- a/src/map.c
+++ b/src/map.c
@@ -123,7 +123,7 @@ gboolean map_keypress(GtkWidget *widget, GdkEventKey* event, gpointer data)
     }
 
     vb.state.processed_key = true;
-    map_handle_keys(string, len);
+    map_handle_keys(string, len, true);
 
     return vb.state.processed_key;
 }
@@ -133,7 +133,7 @@ gboolean map_keypress(GtkWidget *widget, GdkEventKey* event, gpointer data)
  * chars. The key sequence do not need to be NUL terminated.
  * Keylen of 0 signalized a key timeout.
  */
-MapState map_handle_keys(const guchar *keys, int keylen)
+MapState map_handle_keys(const guchar *keys, int keylen, gboolean use_map)
 {
     int ambiguous;
     Map *match = NULL;
@@ -207,7 +207,7 @@ MapState map_handle_keys(const guchar *keys, int keylen)
         /* try to find matching maps */
         match     = NULL;
         ambiguous = 0;
-        if (!(vb.mode->flags & FLAG_NOMAP)) {
+        if (use_map && !(vb.mode->flags & FLAG_NOMAP)) {
             for (GSList *l = map.list; l != NULL; l = l->next) {
                 Map *m = (Map*)l->data;
                 /* ignore maps for other modes */
@@ -239,12 +239,12 @@ MapState map_handle_keys(const guchar *keys, int keylen)
                     match = m;
                 }
             }
-        }
 
-        /* if there are ambiguous matches return MAP_KEY and flush queue
-         * after a timeout if the user do not type more keys */
-        if (ambiguous) {
-            return MAP_AMBIGUOUS;
+            /* if there are ambiguous matches return MAP_KEY and flush queue
+             * after a timeout if the user do not type more keys */
+            if (ambiguous) {
+                return MAP_AMBIGUOUS;
+            }
         }
 
         /* replace the matched chars from queue by the cooked string that
@@ -285,6 +285,18 @@ MapState map_handle_keys(const guchar *keys, int keylen)
     return MAP_DONE;
 }
 
+/**
+ * Like map_handle_keys but use a null terminates string with untranslated
+ * keys like <C-T> that are converted here before calling map_handle_keys.
+ */
+void map_handle_string(char *str, gboolean use_map)
+{
+    int len;
+    char *keys = convert_keys(str, strlen(str), &len);
+
+    map_handle_keys((guchar*)keys, len, use_map);
+}
+
 void map_insert(char *in, char *mapped, char mode)
 {
     int inlen, mappedlen;
@@ -549,7 +561,7 @@ static char *convert_keylabel(char *in, int inlen, int *len)
 static gboolean do_timeout(gpointer data)
 {
     /* signalize the timeout to the key handler */
-    map_handle_keys((guchar*)"", 0);
+    map_handle_keys((guchar*)"", 0, true);
 
     /* call only once */
     return false;
index 3e79610..52b2c72 100644 (file)
--- a/src/map.h
+++ b/src/map.h
@@ -34,7 +34,8 @@ typedef enum {
 
 void map_cleanup(void);
 gboolean map_keypress(GtkWidget *widget, GdkEventKey* event, gpointer data);
-MapState map_handle_keys(const guchar *keys, int keylen);
+MapState map_handle_keys(const guchar *keys, int keylen, gboolean use_map);
+void map_handle_string(char *str, gboolean use_map);
 void map_insert(char *in, char *mapped, char mode);
 gboolean map_delete(char *in, char mode);