# HG changeset patch # User Bram Moolenaar # Date 1560094204 -7200 # Node ID 1841c03a9b5e5352b5c6ddc3b1e4ac8d34ffe582 # Parent 9bd84943d7bd9628393bdc552bf5a9e2af3647e1 patch 8.1.1510: a plugin cannot easily expand a command like done internally commit https://github.com/vim/vim/commit/80dad48c5095d30873a42ec82628bdb213125d8e Author: Bram Moolenaar Date: Sun Jun 9 17:22:31 2019 +0200 patch 8.1.1510: a plugin cannot easily expand a command like done internally Problem: A plugin cannot easily expand a command like done internally. Solution: Add the expandcmd() function. (Yegappan Lakshmanan, closes https://github.com/vim/vim/issues/4514) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -2326,6 +2326,7 @@ extend({expr1}, {expr2} [, {expr3}]) exp({expr}) Float exponential of {expr} expand({expr} [, {nosuf} [, {list}]]) any expand special keywords in {expr} +expandcmd({expr}) String expand {expr} like with `:edit` feedkeys({string} [, {mode}]) Number add key sequence to typeahead buffer filereadable({file}) Number |TRUE| if {file} is a readable file filewritable({file}) Number |TRUE| if {file} is a writable file @@ -4218,6 +4219,14 @@ expand({expr} [, {nosuf} [, {list}]]) See |glob()| for finding existing files. See |system()| for getting the raw output of an external command. +expandcmd({expr}) *expandcmd()* + Expand special items in {expr} like what is done for an Ex + command such as `:edit`. This expands special keywords, like + with |expand()|, and environment variables, anywhere in + {expr}. Returns the expanded string. + Example: > + :echo expandcmd('make %<.o') +< extend({expr1}, {expr2} [, {expr3}]) *extend()* {expr1} and {expr2} must be both |Lists| or both |Dictionaries|. diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt --- a/runtime/doc/usr_41.txt +++ b/runtime/doc/usr_41.txt @@ -1,4 +1,4 @@ -*usr_41.txt* For Vim version 8.1. Last change: 2019 May 29 +*usr_41.txt* For Vim version 8.1. Last change: 2019 Jun 09 VIM USER MANUAL - by Bram Moolenaar @@ -609,6 +609,7 @@ String manipulation: *string-functio strcharpart() get part of a string using char index strgetchar() get character from a string using char index expand() expand special keywords + expandcmd() expand a command like done for `:edit` iconv() convert text from one encoding to another byteidx() byte index of a character in a string byteidxcomp() like byteidx() but count composing characters diff --git a/src/evalfunc.c b/src/evalfunc.c --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -149,6 +149,7 @@ static void f_exists(typval_T *argvars, static void f_exp(typval_T *argvars, typval_T *rettv); #endif static void f_expand(typval_T *argvars, typval_T *rettv); +static void f_expandcmd(typval_T *argvars, typval_T *rettv); static void f_extend(typval_T *argvars, typval_T *rettv); static void f_feedkeys(typval_T *argvars, typval_T *rettv); static void f_filereadable(typval_T *argvars, typval_T *rettv); @@ -646,6 +647,7 @@ static struct fst {"exp", 1, 1, f_exp}, #endif {"expand", 1, 3, f_expand}, + {"expandcmd", 1, 1, f_expandcmd}, {"extend", 2, 3, f_extend}, {"feedkeys", 1, 2, f_feedkeys}, {"file_readable", 1, 1, f_filereadable}, /* obsolete */ @@ -3791,6 +3793,35 @@ f_expand(typval_T *argvars, typval_T *re } /* + * "expandcmd()" function + * Expand all the special characters in a command string. + */ + static void +f_expandcmd(typval_T *argvars, typval_T *rettv) +{ + exarg_T eap; + char_u *cmdstr; + char *errormsg = NULL; + + rettv->v_type = VAR_STRING; + cmdstr = vim_strsave(tv_get_string(&argvars[0])); + + memset(&eap, 0, sizeof(eap)); + eap.cmd = cmdstr; + eap.arg = cmdstr; + eap.argt |= NOSPC; + eap.usefilter = FALSE; + eap.nextcmd = NULL; + eap.cmdidx = CMD_USER; + + expand_filename(&eap, &cmdstr, &errormsg); + if (errormsg != NULL && *errormsg != NUL) + emsg(errormsg); + + rettv->vval.v_string = cmdstr; +} + +/* * "extend(list, list [, idx])" function * "extend(dict, dict [, action])" function */ diff --git a/src/testdir/test_expand.vim b/src/testdir/test_expand.vim --- a/src/testdir/test_expand.vim +++ b/src/testdir/test_expand.vim @@ -47,3 +47,37 @@ func Test_expand_tilde_filename() call assert_match('\~', expand('%:p')) bwipe! endfunc + +func Test_expandcmd() + let $FOO = 'Test' + call assert_equal('e x/Test/y', expandcmd('e x/$FOO/y')) + unlet $FOO + + new + edit Xfile1 + call assert_equal('e Xfile1', expandcmd('e %')) + edit Xfile2 + edit Xfile1 + call assert_equal('e Xfile2', expandcmd('e #')) + edit Xfile2 + edit Xfile3 + edit Xfile4 + let bnum = bufnr('Xfile2') + call assert_equal('e Xfile2', expandcmd('e #' . bnum)) + call setline('.', 'Vim!@#') + call assert_equal('e Vim', expandcmd('e ')) + call assert_equal('e Vim!@#', expandcmd('e ')) + enew! + edit Xfile.java + call assert_equal('e Xfile.py', expandcmd('e %:r.py')) + call assert_equal('make abc.java', expandcmd('make abc.%:e')) + call assert_equal('make Xabc.java', expandcmd('make %:s?file?abc?')) + edit a1a2a3.rb + call assert_equal('make b1b2b3.rb a1a2a3 Xfile.o', expandcmd('make %:gs?a?b? %< #<.o')) + + call assert_fails('call expandcmd("make ")', 'E495:') + call assert_fails('call expandcmd("make ")', 'E495:') + enew + call assert_fails('call expandcmd("make %")', 'E499:') + close +endfunc diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -778,6 +778,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1510, +/**/ 1509, /**/ 1508,