changeset 17020:1841c03a9b5e v8.1.1510

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 <Bram@vim.org> 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)
author Bram Moolenaar <Bram@vim.org>
date Sun, 09 Jun 2019 17:30:04 +0200
parents 9bd84943d7bd
children d2b0c88a5128
files runtime/doc/eval.txt runtime/doc/usr_41.txt src/evalfunc.c src/testdir/test_expand.vim src/version.c
diffstat 5 files changed, 78 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- 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|.
--- 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
--- 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
  */
--- 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 <cword>'))
+  call assert_equal('e Vim!@#', expandcmd('e <cWORD>'))
+  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 <afile>")', 'E495:')
+  call assert_fails('call expandcmd("make <afile>")', 'E495:')
+  enew
+  call assert_fails('call expandcmd("make %")', 'E499:')
+  close
+endfunc
--- 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,