0
0
mirror of https://github.com/vim/vim.git synced 2025-09-25 03:54:15 -04:00

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 #10071)
This commit is contained in:
Yegappan Lakshmanan
2022-04-03 21:30:32 +01:00
committed by Bram Moolenaar
parent 1061195057
commit 2b74b6805b
6 changed files with 50 additions and 13 deletions

View File

@@ -161,7 +161,8 @@ exists_compiled({expr}) Number |TRUE| if {expr} exists at compile time
exp({expr}) Float exponential of {expr}
expand({expr} [, {nosuf} [, {list}]])
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}])
List/Dict insert items of {expr2} into {expr1}
extendnew({expr1}, {expr2} [, {expr3}])
@@ -2293,18 +2294,27 @@ expand({string} [, {nosuf} [, {list}]]) *expand()*
Can also be used as a |method|: >
Getpattern()->expand()
expandcmd({string}) *expandcmd()*
expandcmd({string} [, {options}]) *expandcmd()*
Expand special items in String {string} like what is done for
an Ex command such as `:edit`. This expands special keywords,
like with |expand()|, and environment variables, anywhere in
{string}. "~user" and "~/path" are only expanded at the
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
during expansion, the unmodified {string} is returned.
Example: >
: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|: >
GetCommand()->expandcmd()
<

View File

@@ -1761,7 +1761,7 @@ static funcentry_T global_functions[] =
ret_float, FLOAT_FUNC(f_exp)},
{"expand", 1, 3, FEARG_1, arg3_string_bool_bool,
ret_any, f_expand},
{"expandcmd", 1, 1, FEARG_1, arg1_string,
{"expandcmd", 1, 2, FEARG_1, arg2_string_dict,
ret_string, f_expandcmd},
{"extend", 2, 3, FEARG_1, arg23_extend,
ret_extend, f_extend},
@@ -4152,10 +4152,18 @@ f_expandcmd(typval_T *argvars, typval_T *rettv)
exarg_T eap;
char_u *cmdstr;
char *errormsg = NULL;
int emsgoff = TRUE;
if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL)
if (in_vim9script()
&& (check_for_string_arg(argvars, 0) == FAIL
|| check_for_opt_dict_arg(argvars, 1) == FAIL))
return;
if (argvars[1].v_type == VAR_DICT
&& dict_get_bool(argvars[1].vval.v_dict, (char_u *)"errmsg",
VVAL_FALSE))
emsgoff = FALSE;
rettv->v_type = VAR_STRING;
cmdstr = vim_strsave(tv_get_string(&argvars[0]));
@@ -4167,9 +4175,13 @@ f_expandcmd(typval_T *argvars, typval_T *rettv)
eap.nextcmd = NULL;
eap.cmdidx = CMD_USER;
++emsg_off;
expand_filename(&eap, &cmdstr, &errormsg);
--emsg_off;
if (emsgoff)
++emsg_off;
if (expand_filename(&eap, &cmdstr, &errormsg) == FAIL)
if (!emsgoff && errormsg != NULL && *errormsg != NUL)
emsg(errormsg);
if (emsgoff)
--emsg_off;
rettv->vval.v_string = cmdstr;
}

View File

@@ -3999,7 +3999,7 @@ gen_expand_wildcards(
// When returning FAIL the array must be freed here.
if (retval == FAIL)
ga_clear(&ga);
ga_clear_strings(&ga);
*num_file = ga.ga_len;
*file = (ga.ga_data != NULL) ? (char_u **)ga.ga_data

View File

@@ -90,14 +90,26 @@ func Test_expandcmd()
" Test for expression expansion `=
let $FOO= "blue"
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
let $FOO= "foo bar baz"
call assert_equal("e foo bar baz", expandcmd("e $FOO"))
if has('unix')
" test for using the shell to expand a command argument
call assert_equal('{1..4}', expandcmd('{1..4}'))
if has('unix') && executable('bash')
" test for using the shell to expand a command argument.
" 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
unlet $FOO

View File

@@ -1020,6 +1020,7 @@ def Test_expandcmd()
expandcmd('')->assert_equal('')
v9.CheckDefAndScriptFailure(['expandcmd([1])'], ['E1013: Argument 1: type mismatch, expected string but got list<number>', 'E1174: String required for argument 1'])
v9.CheckDefAndScriptFailure(['expandcmd("abc", [])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<unknown>', 'E1206: Dictionary required for argument 2'])
enddef
def Test_extend_arg_types()

View File

@@ -750,6 +750,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
4679,
/**/
4678,
/**/