diff options
author | Bram Moolenaar <Bram@vim.org> | 2016-07-07 23:04:18 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2016-07-07 23:04:18 +0200 |
commit | bc5d6dd1dd1dc3a06e4e655fc9479529db288365 (patch) | |
tree | a1a4a52ccd792948a0da290701ed3fbc14b34ed5 /src | |
parent | bf2cc5f36d5ffd5de445e6970602000c7869b65a (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.c | 47 | ||||
-rw-r--r-- | src/globals.h | 1 | ||||
-rw-r--r-- | src/message.c | 14 | ||||
-rw-r--r-- | src/proto/eval.pro | 3 | ||||
-rw-r--r-- | src/testdir/test_evalcmd.vim | 25 | ||||
-rw-r--r-- | src/version.c | 2 |
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, |