summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2016-07-07 23:04:18 +0200
committerBram Moolenaar <Bram@vim.org>2016-07-07 23:04:18 +0200
commitbc5d6dd1dd1dc3a06e4e655fc9479529db288365 (patch)
treea1a4a52ccd792948a0da290701ed3fbc14b34ed5 /src
parentbf2cc5f36d5ffd5de445e6970602000c7869b65a (diff)
patch 7.4.1999v7.4.1999
Problem: evalcmd() doesn't work recursively. Solution: Use redir_evalcmd instead of redir_vname.
Diffstat (limited to 'src')
-rw-r--r--src/eval.c47
-rw-r--r--src/globals.h1
-rw-r--r--src/message.c14
-rw-r--r--src/proto/eval.pro3
-rw-r--r--src/testdir/test_evalcmd.vim25
-rw-r--r--src/version.c2
6 files changed, 75 insertions, 17 deletions
diff --git a/src/eval.c b/src/eval.c
index 74ed263d51..445b6b91c4 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -11345,6 +11345,28 @@ f_eval(typval_T *argvars, typval_T *rettv)
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;
+
+ if (value_len == -1)
+ 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
*/
@@ -11352,6 +11374,9 @@ f_eval(typval_T *argvars, typval_T *rettv)
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;
@@ -11359,20 +11384,20 @@ f_evalcmd(typval_T *argvars, typval_T *rettv)
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 (redir_evalcmd)
+ save_ga = redir_evalcmd_ga;
+ ga_init2(&redir_evalcmd_ga, (int)sizeof(char), 500);
+ redir_evalcmd = TRUE;
- if (do_cmdline_cmd(s) == OK)
- rettv->vval.v_string = redir_ga.ga_data;
- else
- vim_free(redir_ga.ga_data);
+ ++msg_silent;
+ do_cmdline_cmd(s);
+ rettv->vval.v_string = redir_evalcmd_ga.ga_data;
+ msg_silent = save_msg_silent;
- redir_ga.ga_data = NULL;
- redir_vname = FALSE;
- redir_lval = NULL;
+ redir_evalcmd = save_redir_evalcmd;
+ if (redir_evalcmd)
+ redir_evalcmd_ga = save_ga;
}
-
}
/*
diff --git a/src/globals.h b/src/globals.h
index f14cb89a92..97711164ab 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -1106,6 +1106,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 */
#endif
#ifdef FEAT_LANGMAP
diff --git a/src/message.c b/src/message.c
index b86c886750..f793ed4143 100644
--- a/src/message.c
+++ b/src/message.c
@@ -3063,7 +3063,9 @@ redir_write(char_u *str, int maxlen)
while (cur_col < msg_col)
{
#ifdef FEAT_EVAL
- if (redir_reg)
+ 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)
var_redir_str((char_u *)" ", -1);
@@ -3078,9 +3080,11 @@ redir_write(char_u *str, int maxlen)
}
#ifdef FEAT_EVAL
- if (redir_reg)
+ if (redir_evalcmd)
+ evalcmd_redir_str(s, maxlen);
+ else if (redir_reg)
write_reg_contents(redir_reg, s, maxlen, TRUE);
- if (redir_vname)
+ else if (redir_vname)
var_redir_str(s, maxlen);
#endif
@@ -3088,7 +3092,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)
+ if (!redir_reg && !redir_vname && !redir_evalcmd)
#endif
if (redir_fd != NULL)
putc(*s, redir_fd);
@@ -3113,7 +3117,7 @@ redirecting(void)
{
return redir_fd != NULL || *p_vfile != NUL
#ifdef FEAT_EVAL
- || redir_reg || redir_vname
+ || redir_reg || redir_vname || redir_evalcmd
#endif
;
}
diff --git a/src/proto/eval.pro b/src/proto/eval.pro
index 4ff063e72c..28edd782c1 100644
--- a/src/proto/eval.pro
+++ b/src/proto/eval.pro
@@ -81,12 +81,14 @@ int dict_add_list(dict_T *d, char *key, list_T *list);
dictitem_T *dict_find(dict_T *d, char_u *key, int len);
char_u *get_dict_string(dict_T *d, char_u *key, int save);
varnumber_T get_dict_number(dict_T *d, char_u *key);
+char_u *tv2string(typval_T *tv, char_u **tofree, char_u *numbuf, int copyID);
int string2float(char_u *text, float_T *value);
char_u *get_function_name(expand_T *xp, int idx);
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 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);
@@ -150,5 +152,4 @@ void ex_oldfiles(exarg_T *eap);
void reset_v_option_vars(void);
int modify_fname(char_u *src, int *usedlen, char_u **fnamep, char_u **bufp, int *fnamelen);
char_u *do_string_sub(char_u *str, char_u *pat, char_u *sub, char_u *flags);
-char_u *tv2string(typval_T *tv, char_u **tofree, char_u *numbuf, int copyID);
/* vim: set ft=c : */
diff --git a/src/testdir/test_evalcmd.vim b/src/testdir/test_evalcmd.vim
index e7f48bcfd3..a9bda875f9 100644
--- a/src/testdir/test_evalcmd.vim
+++ b/src/testdir/test_evalcmd.vim
@@ -1,8 +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
diff --git a/src/version.c b/src/version.c
index 368d1b8be2..5794e3a2fe 100644
--- a/src/version.c
+++ b/src/version.c
@@ -759,6 +759,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1999,
+/**/
1998,
/**/
1997,