Patch 7.4.2008
Problem: evalcmd() has a confusing name.
Solution: Rename to execute(). Make silent optional. Support a list of
commands.
Files: src/eval.c, src/ex_docmd.c, src/message.c, src/globals.h,
src/proto/eval.pro, src/Makefile, src/testdir/test_evalcmd.vim,
src/testdir/test_execute_func.vim, src/testdir/test_alot.vim,
runtime/doc/eval.txt
*** ../vim-7.4.2007/src/eval.c 2016-07-08 23:06:17.183567923 +0200
--- src/eval.c 2016-07-09 16:50:27.620916933 +0200
***************
*** 555,563 ****
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);
static void f_exists(typval_T *argvars, typval_T *rettv);
#ifdef FEAT_FLOAT
--- 555,563 ----
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_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,8572 ****
{"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},
{"exists", 1, 1, f_exists},
#ifdef FEAT_FLOAT
--- 8564,8572 ----
{"empty", 1, 1, f_empty},
{"escape", 2, 2, f_escape},
{"eval", 1, 1, f_eval},
{"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,11357 ****
EMSG(_(e_trailing));
}
! static garray_T redir_evalcmd_ga;
/*
! * Append "value[value_len]" to the evalcmd() output.
*/
void
! evalcmd_redir_str(char_u *value, int value_len)
{
int len;
--- 11345,11379 ----
EMSG(_(e_trailing));
}
! /*
! * "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 execute() output.
*/
void
! execute_redir_str(char_u *value, int value_len)
{
int len;
***************
*** 11359,11429 ****
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)
{
! mch_memmove((char *)redir_evalcmd_ga.ga_data
! + redir_evalcmd_ga.ga_len, value, len);
! redir_evalcmd_ga.ga_len += len;
}
}
/*
! * "evalcmd()" function
*/
! static void
! f_evalcmd(typval_T *argvars, typval_T *rettv)
{
char_u *s;
int save_msg_silent = msg_silent;
! int save_redir_evalcmd = redir_evalcmd;
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 (redir_evalcmd)
! save_ga = redir_evalcmd_ga;
! ga_init2(&redir_evalcmd_ga, (int)sizeof(char), 500);
! redir_evalcmd = TRUE;
++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;
!
! /* "silent reg" or "silent echo x" leaves msg_col somewhere in the
! * line. Put it back in the first column. */
! msg_col = 0;
}
- }
! /*
! * "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));
}
/*
--- 11381,11496 ----
len = (int)STRLEN(value); /* Append the entire string */
else
len = value_len; /* Append only "value_len" characters */
! if (ga_grow(&redir_execute_ga, len) == OK)
{
! mch_memmove((char *)redir_execute_ga.ga_data
! + redir_execute_ga.ga_len, value, len);
! redir_execute_ga.ga_len += len;
}
}
/*
! * 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 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_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;
! if (argvars[0].v_type == VAR_LIST)
{
! 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;
!
! if (cmd != NULL)
! do_cmdline_cmd(cmd);
! else
! {
! listitem_T *item = list->lv_first;
!
! do_cmdline(NULL, get_list_line, (void *)&item,
! DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT|DOCMD_KEYTYPED);
! --list->lv_refcount;
}
! rettv->vval.v_string = redir_execute_ga.ga_data;
! msg_silent = save_msg_silent;
! emsg_silent = save_emsg_silent;
! emsg_noredir = save_emsg_noredir;
! redir_execute = save_redir_execute;
! if (redir_execute)
! redir_execute_ga = save_ga;
! /* "silent reg" or "silent echo x" leaves msg_col somewhere in the
! * line. Put it back in the first column. */
! msg_col = 0;
}
/*
*** ../vim-7.4.2007/src/ex_docmd.c 2016-07-08 15:32:49.945197584 +0200
--- src/ex_docmd.c 2016-07-09 16:26:47.626043687 +0200
***************
*** 9456,9464 ****
char_u *arg = eap->arg;
#ifdef FEAT_EVAL
! if (redir_evalcmd)
{
! EMSG(_("E930: Cannot use :redir inside evalcmd()"));
return;
}
#endif
--- 9456,9464 ----
char_u *arg = eap->arg;
#ifdef FEAT_EVAL
! if (redir_execute)
{
! EMSG(_("E930: Cannot use :redir inside execute()"));
return;
}
#endif
*** ../vim-7.4.2007/src/message.c 2016-07-07 23:04:13.437510647 +0200
--- src/message.c 2016-07-09 16:49:34.449707787 +0200
***************
*** 566,587 ****
*/
if (emsg_silent != 0)
{
! 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);
return TRUE;
}
--- 566,590 ----
*/
if (emsg_silent != 0)
{
! if (emsg_noredir == 0)
! {
! 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);
}
return TRUE;
}
***************
*** 3063,3070 ****
while (cur_col < msg_col)
{
#ifdef FEAT_EVAL
! if (redir_evalcmd)
! evalcmd_redir_str((char_u *)" ", -1);
else if (redir_reg)
write_reg_contents(redir_reg, (char_u *)" ", -1, TRUE);
else if (redir_vname)
--- 3066,3073 ----
while (cur_col < msg_col)
{
#ifdef FEAT_EVAL
! 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,3087 ****
}
#ifdef FEAT_EVAL
! if (redir_evalcmd)
! evalcmd_redir_str(s, maxlen);
else if (redir_reg)
write_reg_contents(redir_reg, s, maxlen, TRUE);
else if (redir_vname)
--- 3083,3090 ----
}
#ifdef FEAT_EVAL
! 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,3098 ****
while (*s != NUL && (maxlen < 0 || (int)(s - str) < maxlen))
{
#ifdef FEAT_EVAL
! if (!redir_reg && !redir_vname && !redir_evalcmd)
#endif
if (redir_fd != NULL)
putc(*s, redir_fd);
--- 3095,3101 ----
while (*s != NUL && (maxlen < 0 || (int)(s - str) < maxlen))
{
#ifdef FEAT_EVAL
! if (!redir_reg && !redir_vname && !redir_execute)
#endif
if (redir_fd != NULL)
putc(*s, redir_fd);
***************
*** 3117,3123 ****
{
return redir_fd != NULL || *p_vfile != NUL
#ifdef FEAT_EVAL
! || redir_reg || redir_vname || redir_evalcmd
#endif
;
}
--- 3120,3126 ----
{
return redir_fd != NULL || *p_vfile != NUL
#ifdef FEAT_EVAL
! || redir_reg || redir_vname || redir_execute
#endif
;
}
*** ../vim-7.4.2007/src/globals.h 2016-07-07 23:04:13.441510589 +0200
--- src/globals.h 2016-07-09 16:49:12.430035327 +0200
***************
*** 971,976 ****
--- 971,977 ----
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,1112 ****
#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 */
#endif
#ifdef FEAT_LANGMAP
--- 1107,1113 ----
#ifdef FEAT_EVAL
EXTERN int redir_reg INIT(= 0); /* message redirection register */
EXTERN int redir_vname INIT(= 0); /* message redirection variable */
! EXTERN int redir_execute INIT(= 0); /* execute() redirection */
#endif
#ifdef FEAT_LANGMAP
*** ../vim-7.4.2007/src/proto/eval.pro 2016-07-07 23:04:13.445510530 +0200
--- src/proto/eval.pro 2016-07-09 16:29:53.835271030 +0200
***************
*** 88,94 ****
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 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);
--- 88,94 ----
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 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);
*** ../vim-7.4.2007/src/Makefile 2016-07-07 17:32:48.290238465 +0200
--- src/Makefile 2016-07-09 16:22:52.041553378 +0200
***************
*** 2023,2030 ****
test_cmdline \
test_cursor_func \
test_delete \
- test_evalcmd \
test_ex_undo \
test_expand \
test_expand_dllpath \
test_expr \
--- 2023,2030 ----
test_cmdline \
test_cursor_func \
test_delete \
test_ex_undo \
+ test_execute_func \
test_expand \
test_expand_dllpath \
test_expr \
*** ../vim-7.4.2007/src/testdir/test_evalcmd.vim 2016-07-07
23:04:13.445510530 +0200
--- src/testdir/test_evalcmd.vim 1970-01-01 01:00:00.000000000 +0100
***************
*** 1,33 ****
- " 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
-
--- 0 ----
*** ../vim-7.4.2007/src/testdir/test_execute_func.vim 2016-07-09
17:03:10.313581869 +0200
--- src/testdir/test_execute_func.vim 2016-07-09 16:44:29.638243199 +0200
***************
*** 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
*** ../vim-7.4.2007/src/testdir/test_alot.vim 2016-07-07 17:32:48.286238524
+0200
--- src/testdir/test_alot.vim 2016-07-09 16:22:20.722020133 +0200
***************
*** 5,11 ****
source test_autocmd.vim
source test_cursor_func.vim
source test_delete.vim
! source test_evalcmd.vim
source test_ex_undo.vim
source test_expand.vim
source test_expr.vim
--- 5,11 ----
source test_autocmd.vim
source test_cursor_func.vim
source test_delete.vim
! source test_execute_func.vim
source test_ex_undo.vim
source test_expand.vim
source test_expr.vim
*** ../vim-7.4.2007/runtime/doc/eval.txt 2016-07-07 17:32:48.286238524
+0200
--- runtime/doc/eval.txt 2016-07-09 16:59:49.684562045 +0200
***************
*** 1942,1950 ****
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}
exists({expr}) Number |TRUE| if {expr} exists
extend({expr1}, {expr2} [, {expr3}])
--- 1961,1969 ----
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
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}])
***************
*** 3219,3232 ****
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
--- 3232,3261 ----
them. Also works for |Funcref|s that refer to existing
functions.
! 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.
eventhandler() *eventhandler()*
Returns 1 when inside an event handler. That is that Vim got
--
"Marriage is when a man and woman become as one; the trouble starts
when they try to decide which one"
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.