]> granicus.if.org Git - vim/commitdiff
patch 7.4.2008 v7.4.2008
authorBram Moolenaar <Bram@vim.org>
Sat, 9 Jul 2016 15:07:29 +0000 (17:07 +0200)
committerBram Moolenaar <Bram@vim.org>
Sat, 9 Jul 2016 15:07:29 +0000 (17:07 +0200)
Problem:    evalcmd() has a confusing name.
Solution:   Rename to execute().  Make silent optional.  Support a list of
            commands.

runtime/doc/eval.txt
src/Makefile
src/eval.c
src/ex_docmd.c
src/globals.h
src/message.c
src/proto/eval.pro
src/testdir/test_alot.vim
src/testdir/test_evalcmd.vim [deleted file]
src/testdir/test_execute_func.vim [new file with mode: 0644]

index 4b55f911d09928fff522cbb0ccfc27bcbe57ec54..7f948eee1ef5471482193c0b7ce1d4d6df539f4e 100644 (file)
@@ -1,4 +1,4 @@
-*eval.txt*     For Vim version 7.4.  Last change: 2016 Jul 06
+*eval.txt*     For Vim version 7.4.  Last change: 2016 Jul 09
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -1961,9 +1961,9 @@ 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
+execute({command})             String  execute {command} and get the output
 exepath({expr})                        String  full path of the command {expr}
 exists({expr})                 Number  |TRUE| if {expr} exists
 extend({expr1}, {expr2} [, {expr3}])
@@ -3232,15 +3232,6 @@ 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,
@@ -3271,6 +3262,31 @@ executable({expr})                                       *executable()*
                        0       does not exist
                        -1      not implemented on this system
 
+execute({command} [, {silent}])                                        *execute()*
+               Execute an Ex command or commands and return the output as a
+               string.
+               {command} can be a string or a List.  In case of a List the
+               lines are executed one by one.
+               This is equivalent to: >
+                       redir => var
+                       {command}
+                       redir END
+<
+               The optional {silent} argument can have these values:
+                       ""              no `:silent` used
+                       "silent"        `:silent` used
+                       "silent!"       `:silent!` used
+               The default is 'silent'.  Note that with "silent!", unlike
+               `:redir`, error messages are dropped.
+                                                       *E930*
+               It is not possible to use `:redir` anywhere in {command}.
+
+               To get a list of lines use |split()| on the result: >
+                       split(evalcmd('args'), "\n")
+
+<              When used recursively the output of the recursive call is not
+               included in the output of the higher level call.
+
 exepath({expr})                                                *exepath()*
                If {expr} is an executable and is either an absolute path, a
                relative path or found in $PATH, return the full path.
@@ -7046,9 +7062,9 @@ synID({lnum}, {col}, {trans})                             *synID()*
                that's where the cursor can be in Insert mode, synID() returns
                zero.
 
-               When {trans} is non-zero, transparent items are reduced to the
+               When {trans} is |TRUE|, transparent items are reduced to the
                item that they reveal.  This is useful when wanting to know
-               the effective color.  When {trans} is zero, the transparent
+               the effective color.  When {trans} is |FALSE|, the transparent
                item is returned.  This is useful when wanting to know which
                syntax item is effective (e.g. inside parens).
                Warning: This function can be very slow.  Best speed is
index 13bf77691406863ba1965dcfc5e64f9b0a7b5b20..007c7925db3d375261b185c26e4505c10f003d11 100644 (file)
@@ -2023,8 +2023,8 @@ test_arglist \
        test_cmdline \
        test_cursor_func \
        test_delete \
-       test_evalcmd \
        test_ex_undo \
+       test_execute_func \
        test_expand \
        test_expand_dllpath \
        test_expr \
index 4764f49ab80e32682e3ffe3777dcfcb262f3b822..ab808b9e2adcdb524fa6eee411d32177e6576d8c 100644 (file)
@@ -555,9 +555,9 @@ 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_execute(typval_T *argvars, typval_T *rettv);
 static void f_exepath(typval_T *argvars, typval_T *rettv);
 static void f_exists(typval_T *argvars, typval_T *rettv);
 #ifdef FEAT_FLOAT
@@ -8564,9 +8564,9 @@ 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},
+    {"execute",                1, 2, f_execute},
     {"exepath",                1, 1, f_exepath},
     {"exists",         1, 1, f_exists},
 #ifdef FEAT_FLOAT
@@ -11345,13 +11345,35 @@ f_eval(typval_T *argvars, typval_T *rettv)
        EMSG(_(e_trailing));
 }
 
-static garray_T        redir_evalcmd_ga;
+/*
+ * "eventhandler()" function
+ */
+    static void
+f_eventhandler(typval_T *argvars UNUSED, typval_T *rettv)
+{
+    rettv->vval.v_number = vgetc_busy;
+}
+
+/*
+ * "executable()" function
+ */
+    static void
+f_executable(typval_T *argvars, typval_T *rettv)
+{
+    char_u *name = get_tv_string(&argvars[0]);
+
+    /* Check in $PATH and also check directly if there is a directory name. */
+    rettv->vval.v_number = mch_can_exe(name, NULL, TRUE)
+                || (gettail(name) != name && mch_can_exe(name, NULL, FALSE));
+}
+
+static garray_T        redir_execute_ga;
 
 /*
- * Append "value[value_len]" to the evalcmd() output.
+ * Append "value[value_len]" to the execute() output.
  */
     void
-evalcmd_redir_str(char_u *value, int value_len)
+execute_redir_str(char_u *value, int value_len)
 {
     int                len;
 
@@ -11359,71 +11381,116 @@ evalcmd_redir_str(char_u *value, int value_len)
        len = (int)STRLEN(value);       /* Append the entire string */
     else
        len = value_len;                /* Append only "value_len" characters */
-    if (ga_grow(&redir_evalcmd_ga, len) == OK)
+    if (ga_grow(&redir_execute_ga, len) == OK)
     {
-       mch_memmove((char *)redir_evalcmd_ga.ga_data
-                                      + redir_evalcmd_ga.ga_len, value, len);
-       redir_evalcmd_ga.ga_len += len;
+       mch_memmove((char *)redir_execute_ga.ga_data
+                                      + redir_execute_ga.ga_len, value, len);
+       redir_execute_ga.ga_len += len;
     }
 }
 
 /*
- * "evalcmd()" function
+ * Get next line from a list.
+ * Called by do_cmdline() to get the next line.
+ * Returns allocated string, or NULL for end of function.
  */
-    static void
-f_evalcmd(typval_T *argvars, typval_T *rettv)
+
+    static char_u *
+get_list_line(
+    int            c UNUSED,
+    void    *cookie,
+    int            indent UNUSED)
 {
+    listitem_T **p = (listitem_T **)cookie;
+    listitem_T *item = *p;
+    char_u     buf[NUMBUFLEN];
     char_u     *s;
+
+    if (item == NULL)
+       return NULL;
+    s = get_tv_string_buf_chk(&item->li_tv, buf);
+    *p = item->li_next;
+    return s == NULL ? NULL : vim_strsave(s);
+}
+
+/*
+ * "execute()" function
+ */
+    static void
+f_execute(typval_T *argvars, typval_T *rettv)
+{
+    char_u     *cmd = NULL;
+    list_T     *list = NULL;
     int                save_msg_silent = msg_silent;
-    int                save_redir_evalcmd = redir_evalcmd;
+    int                save_emsg_silent = emsg_silent;
+    int                save_emsg_noredir = emsg_noredir;
+    int                save_redir_execute = redir_execute;
     garray_T   save_ga;
 
     rettv->vval.v_string = NULL;
     rettv->v_type = VAR_STRING;
 
-    s = get_tv_string_chk(&argvars[0]);
-    if (s != NULL)
+    if (argvars[0].v_type == VAR_LIST)
     {
-       if (redir_evalcmd)
-           save_ga = redir_evalcmd_ga;
-       ga_init2(&redir_evalcmd_ga, (int)sizeof(char), 500);
-       redir_evalcmd = TRUE;
+       list = argvars[0].vval.v_list;
+       if (list == NULL || list->lv_first == NULL)
+           /* empty list, no commands, empty output */
+           return;
+       ++list->lv_refcount;
+    }
+    else
+    {
+       cmd = get_tv_string_chk(&argvars[0]);
+       if (cmd == NULL)
+           return;
+    }
 
+    if (redir_execute)
+       save_ga = redir_execute_ga;
+    ga_init2(&redir_execute_ga, (int)sizeof(char), 500);
+    redir_execute = TRUE;
+
+    if (argvars[1].v_type != VAR_UNKNOWN)
+    {
+       char_u  buf[NUMBUFLEN];
+       char_u  *s = get_tv_string_buf_chk(&argvars[1], buf);
+
+       if (s == NULL)
+           return;
+       if (STRNCMP(s, "silent", 6) == 0)
+           ++msg_silent;
+       if (STRCMP(s, "silent!") == 0)
+       {
+           emsg_silent = TRUE;
+           emsg_noredir = TRUE;
+       }
+    }
+    else
        ++msg_silent;
-       do_cmdline_cmd(s);
-       rettv->vval.v_string = redir_evalcmd_ga.ga_data;
-       msg_silent = save_msg_silent;
 
-       redir_evalcmd = save_redir_evalcmd;
-       if (redir_evalcmd)
-           redir_evalcmd_ga = save_ga;
+    if (cmd != NULL)
+       do_cmdline_cmd(cmd);
+    else
+    {
+       listitem_T      *item = list->lv_first;
 
-       /* "silent reg" or "silent echo x" leaves msg_col somewhere in the
-        * line.  Put it back in the first column. */
-       msg_col = 0;
+       do_cmdline(NULL, get_list_line, (void *)&item,
+                     DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT|DOCMD_KEYTYPED);
+       --list->lv_refcount;
     }
-}
 
-/*
- * "eventhandler()" function
- */
-    static void
-f_eventhandler(typval_T *argvars UNUSED, typval_T *rettv)
-{
-    rettv->vval.v_number = vgetc_busy;
-}
+    rettv->vval.v_string = redir_execute_ga.ga_data;
+    msg_silent = save_msg_silent;
+    emsg_silent = save_emsg_silent;
+    emsg_noredir = save_emsg_noredir;
 
-/*
- * "executable()" function
- */
-    static void
-f_executable(typval_T *argvars, typval_T *rettv)
-{
-    char_u *name = get_tv_string(&argvars[0]);
+    redir_execute = save_redir_execute;
+    if (redir_execute)
+       redir_execute_ga = save_ga;
 
-    /* Check in $PATH and also check directly if there is a directory name. */
-    rettv->vval.v_number = mch_can_exe(name, NULL, TRUE)
-                || (gettail(name) != name && mch_can_exe(name, NULL, FALSE));
+    /* "silent reg" or "silent echo x" leaves msg_col somewhere in the
+     * line.  Put it back in the first column. */
+    msg_col = 0;
 }
 
 /*
index b892b63072ed943af01585229a9f957648ea8ec0..f8b50ed1d1ebfef92eb80bbff28380a3e1398e3e 100644 (file)
@@ -9456,9 +9456,9 @@ ex_redir(exarg_T *eap)
     char_u     *arg = eap->arg;
 
 #ifdef FEAT_EVAL
-    if (redir_evalcmd)
+    if (redir_execute)
     {
-       EMSG(_("E930: Cannot use :redir inside evalcmd()"));
+       EMSG(_("E930: Cannot use :redir inside execute()"));
        return;
     }
 #endif
index 97711164abd8a4591a43353db309e15625d0c569..68bf36f582314e2ad52249ef8c378bbb21c363c7 100644 (file)
@@ -971,6 +971,7 @@ EXTERN cmdmod_T     cmdmod;                 /* Ex command modifiers */
 
 EXTERN int     msg_silent INIT(= 0);   /* don't print messages */
 EXTERN int     emsg_silent INIT(= 0);  /* don't print error messages */
+EXTERN int     emsg_noredir INIT(= 0); /* don't redirect error messages */
 EXTERN int     cmd_silent INIT(= FALSE); /* don't echo the command line */
 
 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) \
@@ -1106,7 +1107,7 @@ EXTERN FILE *redir_fd INIT(= NULL);       /* message redirection file */
 #ifdef FEAT_EVAL
 EXTERN int  redir_reg INIT(= 0);       /* message redirection register */
 EXTERN int  redir_vname INIT(= 0);     /* message redirection variable */
-EXTERN int  redir_evalcmd INIT(= 0);   /* evalcmd() redirection */
+EXTERN int  redir_execute INIT(= 0);   /* execute() redirection */
 #endif
 
 #ifdef FEAT_LANGMAP
index f793ed4143ad4cd670b34b5ea89a6c9337922d63..7bb154d2e9213d9e787dad6d4548f40be2bad7f4 100644 (file)
@@ -566,22 +566,25 @@ emsg(char_u *s)
         */
        if (emsg_silent != 0)
        {
-           msg_start();
-           p = get_emsg_source();
-           if (p != NULL)
+           if (emsg_noredir == 0)
            {
-               STRCAT(p, "\n");
-               redir_write(p, -1);
-               vim_free(p);
-           }
-           p = get_emsg_lnum();
-           if (p != NULL)
-           {
-               STRCAT(p, "\n");
-               redir_write(p, -1);
-               vim_free(p);
+               msg_start();
+               p = get_emsg_source();
+               if (p != NULL)
+               {
+                   STRCAT(p, "\n");
+                   redir_write(p, -1);
+                   vim_free(p);
+               }
+               p = get_emsg_lnum();
+               if (p != NULL)
+               {
+                   STRCAT(p, "\n");
+                   redir_write(p, -1);
+                   vim_free(p);
+               }
+               redir_write(s, -1);
            }
-           redir_write(s, -1);
            return TRUE;
        }
 
@@ -3063,8 +3066,8 @@ redir_write(char_u *str, int maxlen)
            while (cur_col < msg_col)
            {
 #ifdef FEAT_EVAL
-               if (redir_evalcmd)
-                   evalcmd_redir_str((char_u *)" ", -1);
+               if (redir_execute)
+                   execute_redir_str((char_u *)" ", -1);
                else if (redir_reg)
                    write_reg_contents(redir_reg, (char_u *)" ", -1, TRUE);
                else if (redir_vname)
@@ -3080,8 +3083,8 @@ redir_write(char_u *str, int maxlen)
        }
 
 #ifdef FEAT_EVAL
-       if (redir_evalcmd)
-           evalcmd_redir_str(s, maxlen);
+       if (redir_execute)
+           execute_redir_str(s, maxlen);
        else if (redir_reg)
            write_reg_contents(redir_reg, s, maxlen, TRUE);
        else if (redir_vname)
@@ -3092,7 +3095,7 @@ redir_write(char_u *str, int maxlen)
        while (*s != NUL && (maxlen < 0 || (int)(s - str) < maxlen))
        {
 #ifdef FEAT_EVAL
-           if (!redir_reg && !redir_vname && !redir_evalcmd)
+           if (!redir_reg && !redir_vname && !redir_execute)
 #endif
                if (redir_fd != NULL)
                    putc(*s, redir_fd);
@@ -3117,7 +3120,7 @@ redirecting(void)
 {
     return redir_fd != NULL || *p_vfile != NUL
 #ifdef FEAT_EVAL
-                         || redir_reg || redir_vname || redir_evalcmd
+                         || redir_reg || redir_vname || redir_execute
 #endif
                                       ;
 }
index 28edd782c13a63d9bb5083166d0286b63397c372..e81669b05eb62d0286eb3a7be07461736cd91927 100644 (file)
@@ -88,7 +88,7 @@ char_u *get_expr_name(expand_T *xp, int idx);
 int call_func(char_u *funcname, int len, typval_T *rettv, int argcount_in, typval_T *argvars_in, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, partial_T *partial, dict_T *selfdict_in);
 buf_T *buflist_find_by_name(char_u *name, int curtab_only);
 int func_call(char_u *name, typval_T *args, partial_T *partial, dict_T *selfdict, typval_T *rettv);
-void evalcmd_redir_str(char_u *value, int value_len);
+void execute_redir_str(char_u *value, int value_len);
 void dict_extend(dict_T *d1, dict_T *d2, char_u *action);
 void mzscheme_call_vim(char_u *name, typval_T *args, typval_T *rettv);
 float_T vim_round(float_T f);
index 074c2dec91a8da8eb83a0016cc433c5c92bf9bed..3074a5c0bd562119c99468fac12f69a3c0bb9c0a 100644 (file)
@@ -5,7 +5,7 @@ source test_assign.vim
 source test_autocmd.vim
 source test_cursor_func.vim
 source test_delete.vim
-source test_evalcmd.vim
+source test_execute_func.vim
 source test_ex_undo.vim
 source test_expand.vim
 source test_expr.vim
diff --git a/src/testdir/test_evalcmd.vim b/src/testdir/test_evalcmd.vim
deleted file mode 100644 (file)
index a9bda87..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-" test evalcmd()
-
-func NestedEval()
-  let nested = evalcmd('echo "nested\nlines"')
-  echo 'got: "' . nested . '"'
-endfunc
-
-func NestedRedir()
-  redir => var
-  echo 'broken'
-  redir END
-endfunc
-
-func Test_evalcmd()
-  call assert_equal("\nnocompatible", evalcmd('set compatible?'))
-  call assert_equal("\nsomething\nnice", evalcmd('echo "something\nnice"'))
-  call assert_equal("noendofline", evalcmd('echon "noendofline"'))
-  call assert_equal("", evalcmd(123))
-
-  call assert_equal("\ngot: \"\nnested\nlines\"", evalcmd('call NestedEval()'))
-  redir => redired
-  echo 'this'
-  let evaled = evalcmd('echo "that"')
-  echo 'theend'
-  redir END
-  call assert_equal("\nthis\ntheend", redired)
-  call assert_equal("\nthat", evaled)
-
-  call assert_fails('call evalcmd("doesnotexist")', 'E492:')
-  call assert_fails('call evalcmd(3.4)', 'E806:')
-  call assert_fails('call evalcmd("call NestedRedir()")', 'E930:')
-endfunc
-
diff --git a/src/testdir/test_execute_func.vim b/src/testdir/test_execute_func.vim
new file mode 100644 (file)
index 0000000..dd07e4a
--- /dev/null
@@ -0,0 +1,51 @@
+" test execute()
+
+func NestedEval()
+  let nested = execute('echo "nested\nlines"')
+  echo 'got: "' . nested . '"'
+endfunc
+
+func NestedRedir()
+  redir => var
+  echo 'broken'
+  redir END
+endfunc
+
+func Test_execute_string()
+  call assert_equal("\nnocompatible", execute('set compatible?'))
+  call assert_equal("\nsomething\nnice", execute('echo "something\nnice"'))
+  call assert_equal("noendofline", execute('echon "noendofline"'))
+  call assert_equal("", execute(123))
+
+  call assert_equal("\ngot: \"\nnested\nlines\"", execute('call NestedEval()'))
+  redir => redired
+  echo 'this'
+  let evaled = execute('echo "that"')
+  echo 'theend'
+  redir END
+  call assert_equal("\nthis\ntheend", redired)
+  call assert_equal("\nthat", evaled)
+
+  call assert_fails('call execute("doesnotexist")', 'E492:')
+  call assert_fails('call execute(3.4)', 'E806:')
+  call assert_fails('call execute("call NestedRedir()")', 'E930:')
+
+  call assert_equal("\nsomething", execute('echo "something"', ''))
+  call assert_equal("\nsomething", execute('echo "something"', 'silent'))
+  call assert_equal("\nsomething", execute('echo "something"', 'silent!'))
+  call assert_equal("", execute('burp', 'silent!'))
+  call assert_fails('call execute("echo \"x\"", 3.4)', 'E806:')
+
+  call assert_equal("", execute(test_null_string()))
+endfunc
+
+func Test_execute_list()
+  call assert_equal("\nsomething\nnice", execute(['echo "something"', 'echo "nice"']))
+  let l = ['for n in range(0, 3)',
+       \  'echo n',
+       \  'endfor']
+  call assert_equal("\n0\n1\n2\n3", execute(l))
+
+  call assert_equal("", execute([]))
+  call assert_equal("", execute(test_null_list()))
+endfunc