vim-patch:8.2.4679: cannot have expandcmd() give an error message for mistakes

Problem:    Cannot have expandcmd() give an error message for mistakes.
Solution:   Add an optional argument to give errors. Fix memory leak when
            expanding files fails. (Yegappan Lakshmanan, closes vim/vim#10071)
2b74b6805b

Co-authored-by: Yegappan Lakshmanan <yegappan@yahoo.com>
This commit is contained in:
zeertzjq
2022-10-22 09:32:01 +08:00
parent 781616bee5
commit 8e868d699a
5 changed files with 48 additions and 12 deletions

View File

@@ -134,7 +134,8 @@ exists({expr}) Number |TRUE| if {expr} exists
exp({expr}) Float exponential of {expr} exp({expr}) Float exponential of {expr}
expand({expr} [, {nosuf} [, {list}]]) expand({expr} [, {nosuf} [, {list}]])
any expand special keywords in {expr} any expand special keywords in {expr}
expandcmd({expr}) String expand {expr} like with `:edit` expandcmd({string} [, {options}])
String expand {string} like with `:edit`
extend({expr1}, {expr2} [, {expr3}]) extend({expr1}, {expr2} [, {expr3}])
List/Dict insert items of {expr2} into {expr1} List/Dict insert items of {expr2} into {expr1}
feedkeys({string} [, {mode}]) Number add key sequence to typeahead buffer feedkeys({string} [, {mode}]) Number add key sequence to typeahead buffer
@@ -2044,18 +2045,27 @@ expand({string} [, {nosuf} [, {list}]]) *expand()*
Can also be used as a |method|: > Can also be used as a |method|: >
Getpattern()->expand() Getpattern()->expand()
expandcmd({string}) *expandcmd()* expandcmd({string} [, {options}]) *expandcmd()*
Expand special items in String {string} like what is done for Expand special items in String {string} like what is done for
an Ex command such as `:edit`. This expands special keywords, an Ex command such as `:edit`. This expands special keywords,
like with |expand()|, and environment variables, anywhere in like with |expand()|, and environment variables, anywhere in
{string}. "~user" and "~/path" are only expanded at the {string}. "~user" and "~/path" are only expanded at the
start. start.
The following items are supported in the {options} Dict
argument:
errmsg If set to TRUE, error messages are displayed
if an error is encountered during expansion.
By default, error messages are not displayed.
Returns the expanded string. If an error is encountered Returns the expanded string. If an error is encountered
during expansion, the unmodified {string} is returned. during expansion, the unmodified {string} is returned.
Example: > Example: >
:echo expandcmd('make %<.o') :echo expandcmd('make %<.o')
< make /path/runtime/doc/builtin.o ~ make /path/runtime/doc/builtin.o
:echo expandcmd('make %<.o', {'errmsg': v:true})
<
Can also be used as a |method|: > Can also be used as a |method|: >
GetCommand()->expandcmd() GetCommand()->expandcmd()
< <

View File

@@ -118,7 +118,7 @@ return {
exists={args=1, base=1}, exists={args=1, base=1},
exp={args=1, base=1, float_func="exp"}, exp={args=1, base=1, float_func="exp"},
expand={args={1, 3}, base=1}, expand={args={1, 3}, base=1},
expandcmd={args=1, base=1}, expandcmd={args={1, 2}, base=1},
extend={args={2, 3}, base=1}, extend={args={2, 3}, base=1},
feedkeys={args={1, 2}, base=1}, feedkeys={args={1, 2}, base=1},
file_readable={args=1, base=1, func='f_filereadable'}, -- obsolete file_readable={args=1, base=1, func='f_filereadable'}, -- obsolete

View File

@@ -2058,6 +2058,12 @@ static void f_menu_get(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
static void f_expandcmd(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) static void f_expandcmd(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{ {
char *errormsg = NULL; char *errormsg = NULL;
bool emsgoff = true;
if (argvars[1].v_type == VAR_DICT
&& tv_dict_get_bool(argvars[1].vval.v_dict, "errmsg", kBoolVarFalse)) {
emsgoff = false;
}
rettv->v_type = VAR_STRING; rettv->v_type = VAR_STRING;
char *cmdstr = xstrdup(tv_get_string(&argvars[0])); char *cmdstr = xstrdup(tv_get_string(&argvars[0]));
@@ -2071,9 +2077,17 @@ static void f_expandcmd(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
}; };
eap.argt |= EX_NOSPC; eap.argt |= EX_NOSPC;
if (emsgoff) {
emsg_off++; emsg_off++;
expand_filename(&eap, &cmdstr, &errormsg); }
if (expand_filename(&eap, &cmdstr, &errormsg) == FAIL) {
if (!emsgoff && errormsg != NULL && *errormsg != NUL) {
emsg(errormsg);
}
}
if (emsgoff) {
emsg_off--; emsg_off--;
}
rettv->vval.v_string = cmdstr; rettv->vval.v_string = cmdstr;
} }

View File

@@ -1244,7 +1244,7 @@ int gen_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, i
add_pat = expand_backtick(&ga, (char *)p, flags); add_pat = expand_backtick(&ga, (char *)p, flags);
if (add_pat == -1) { if (add_pat == -1) {
recursive = false; recursive = false;
FreeWild(ga.ga_len, ga.ga_data); ga_clear_strings(&ga);
*num_file = 0; *num_file = 0;
*file = NULL; *file = NULL;
return FAIL; return FAIL;

View File

@@ -90,14 +90,26 @@ func Test_expandcmd()
" Test for expression expansion `= " Test for expression expansion `=
let $FOO= "blue" let $FOO= "blue"
call assert_equal("blue sky", expandcmd("`=$FOO .. ' sky'`")) call assert_equal("blue sky", expandcmd("`=$FOO .. ' sky'`"))
let x = expandcmd("`=axbycz`")
call assert_equal('`=axbycz`', x)
call assert_fails('let x = expandcmd("`=axbycz`", #{errmsg: 1})', 'E121:')
let x = expandcmd("`=axbycz`", #{abc: []})
call assert_equal('`=axbycz`', x)
" Test for env variable with spaces " Test for env variable with spaces
let $FOO= "foo bar baz" let $FOO= "foo bar baz"
call assert_equal("e foo bar baz", expandcmd("e $FOO")) call assert_equal("e foo bar baz", expandcmd("e $FOO"))
if has('unix') if has('unix') && executable('bash')
" test for using the shell to expand a command argument " test for using the shell to expand a command argument.
call assert_equal('{1..4}', expandcmd('{1..4}')) " only bash supports the {..} syntax
set shell=bash
let x = expandcmd('{1..4}')
call assert_equal('{1..4}', x)
call assert_fails("let x = expandcmd('{1..4}', #{errmsg: v:true})", 'E77:')
let x = expandcmd('{1..4}', #{error: v:true})
call assert_equal('{1..4}', x)
set shell&
endif endif
unlet $FOO unlet $FOO