]> granicus.if.org Git - vim/commitdiff
patch 7.4.1996 v7.4.1996
authorBram Moolenaar <Bram@vim.org>
Thu, 7 Jul 2016 15:33:02 +0000 (17:33 +0200)
committerBram Moolenaar <Bram@vim.org>
Thu, 7 Jul 2016 15:33:02 +0000 (17:33 +0200)
Problem:    Capturing the output of a command takes a few commands.
Solution:   Add evalcmd().

runtime/doc/eval.txt
src/Makefile
src/eval.c
src/testdir/test_alot.vim
src/testdir/test_evalcmd.vim [new file with mode: 0644]
src/version.c

index 2e6e08a3606f60b6aa1236ff2a55b0afd9570f18..4b55f911d09928fff522cbb0ccfc27bcbe57ec54 100644 (file)
@@ -1961,6 +1961,7 @@ diff_hlID({lnum}, {col})  Number  diff highlighting at {lnum}/{col}
 empty({expr})                  Number  |TRUE| if {expr} is empty
 escape({string}, {chars})      String  escape {chars} in {string} with '\'
 eval({string})                 any     evaluate {string} into its value
+evalcmd({command})             String  execute {command} and get the output
 eventhandler()                 Number  |TRUE| if inside an event handler
 executable({expr})             Number  1 if executable {expr} exists
 exepath({expr})                        String  full path of the command {expr}
@@ -3231,6 +3232,15 @@ eval({string})   Evaluate {string} and return the result.  Especially useful to
                them.  Also works for |Funcref|s that refer to existing
                functions.
 
+evalcmd({command})                                     *evalcmd()*
+               Execute Ex {command} and return the output as a string.  This
+               is equivalent to: >
+                       redir => var
+                       {command}
+                       redir END
+<              To get a list of lines use: >
+                       split(evalcmd(cmd), "\n")
+
 eventhandler()                                         *eventhandler()*
                Returns 1 when inside an event handler.  That is that Vim got
                interrupted while waiting for the user to type a character,
index 6add93591357b4347038c5f09b5b6fb4ac85039b..13bf77691406863ba1965dcfc5e64f9b0a7b5b20 100644 (file)
@@ -2023,6 +2023,7 @@ test_arglist \
        test_cmdline \
        test_cursor_func \
        test_delete \
+       test_evalcmd \
        test_ex_undo \
        test_expand \
        test_expand_dllpath \
index 69238c18131f90f51aab2d2683f2e23357868ed8..74ed263d51192e969ee245b9ca664bd9968dfd7c 100644 (file)
@@ -555,6 +555,7 @@ static void f_diff_hlID(typval_T *argvars, typval_T *rettv);
 static void f_empty(typval_T *argvars, typval_T *rettv);
 static void f_escape(typval_T *argvars, typval_T *rettv);
 static void f_eval(typval_T *argvars, typval_T *rettv);
+static void f_evalcmd(typval_T *argvars, typval_T *rettv);
 static void f_eventhandler(typval_T *argvars, typval_T *rettv);
 static void f_executable(typval_T *argvars, typval_T *rettv);
 static void f_exepath(typval_T *argvars, typval_T *rettv);
@@ -1133,6 +1134,7 @@ set_internal_string_var(char_u *name, char_u *value)
 }
 
 static lval_T  *redir_lval = NULL;
+#define EVALCMD_BUSY (redir_lval == (lval_T *)&redir_lval)
 static garray_T redir_ga;      /* only valid when redir_lval is not NULL */
 static char_u  *redir_endp = NULL;
 static char_u  *redir_varname = NULL;
@@ -1250,6 +1252,12 @@ var_redir_stop(void)
 {
     typval_T   tv;
 
+    if (EVALCMD_BUSY)
+    {
+       redir_lval = NULL;
+       return;
+    }
+
     if (redir_lval != NULL)
     {
        /* If there was no error: assign the text to the variable. */
@@ -8556,6 +8564,7 @@ static struct fst
     {"empty",          1, 1, f_empty},
     {"escape",         2, 2, f_escape},
     {"eval",           1, 1, f_eval},
+    {"evalcmd",                1, 1, f_evalcmd},
     {"eventhandler",   0, 0, f_eventhandler},
     {"executable",     1, 1, f_executable},
     {"exepath",                1, 1, f_exepath},
@@ -11336,6 +11345,36 @@ f_eval(typval_T *argvars, typval_T *rettv)
        EMSG(_(e_trailing));
 }
 
+/*
+ * "evalcmd()" function
+ */
+    static void
+f_evalcmd(typval_T *argvars, typval_T *rettv)
+{
+    char_u     *s;
+
+    rettv->vval.v_string = NULL;
+    rettv->v_type = VAR_STRING;
+
+    s = get_tv_string_chk(&argvars[0]);
+    if (s != NULL)
+    {
+       redir_vname = TRUE;
+       redir_lval = (lval_T *)&redir_lval;
+       ga_init2(&redir_ga, (int)sizeof(char), 500);
+
+       if (do_cmdline_cmd(s) == OK)
+           rettv->vval.v_string = redir_ga.ga_data;
+       else
+           vim_free(redir_ga.ga_data);
+
+       redir_ga.ga_data = NULL;
+       redir_vname = FALSE;
+       redir_lval = NULL;
+    }
+
+}
+
 /*
  * "eventhandler()" function
  */
index e99e137640cf2507f5c127700a81db51d969638e..074c2dec91a8da8eb83a0016cc433c5c92bf9bed 100644 (file)
@@ -5,9 +5,10 @@ source test_assign.vim
 source test_autocmd.vim
 source test_cursor_func.vim
 source test_delete.vim
+source test_evalcmd.vim
 source test_ex_undo.vim
-source test_expr.vim
 source test_expand.vim
+source test_expr.vim
 source test_expand_dllpath.vim
 source test_feedkeys.vim
 source test_fnamemodify.vim
diff --git a/src/testdir/test_evalcmd.vim b/src/testdir/test_evalcmd.vim
new file mode 100644 (file)
index 0000000..e7f48bc
--- /dev/null
@@ -0,0 +1,8 @@
+" test evalcmd()
+
+func Test_evalcmd()
+  call assert_equal("\nnocompatible", evalcmd('set compatible?'))
+  call assert_equal("\nsomething\nnice", evalcmd('echo "something\nnice"'))
+  call assert_fails('call evalcmd("doesnotexist")', 'E492:')
+endfunc
+
index f34f7a0a79f91e65ed1104887416173aca86cdc1..b6b9e59eb2852129a8bce16fa9b3a405ed15ef48 100644 (file)
@@ -758,6 +758,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1996,
 /**/
     1995,
 /**/