changeset 23853:a9ed31ab85c3 v8.2.2468

patch 8.2.2468: not easy to get the full command name from a shortened one Commit: https://github.com/vim/vim/commit/038e09ee7645731de0296d255aabb17603276443 Author: Bram Moolenaar <Bram@vim.org> Date: Sat Feb 6 12:38:51 2021 +0100 patch 8.2.2468: not easy to get the full command name from a shortened one Problem: Not easy to get the full command name from a shortened one. Solution: Add fullcommand(). (Martin Tournoij, closes https://github.com/vim/vim/issues/7777)
author Bram Moolenaar <Bram@vim.org>
date Sat, 06 Feb 2021 12:45:04 +0100
parents cbebf5f1a5a7
children d66967ef351c
files runtime/doc/eval.txt runtime/doc/usr_41.txt src/evalfunc.c src/ex_docmd.c src/proto/evalfunc.pro src/testdir/test_cmdline.vim src/version.c
diffstat 7 files changed, 86 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -2562,6 +2562,7 @@ foldlevel({lnum})		Number	fold level at 
 foldtext()			String	line displayed for closed fold
 foldtextresult({lnum})		String	text for closed fold at {lnum}
 foreground()			Number	bring the Vim window to the foreground
+fullcommand({name})		String	get full command from {name}
 funcref({name} [, {arglist}] [, {dict}])
 				Funcref	reference to function {name}
 function({name} [, {arglist}] [, {dict}])
@@ -4902,6 +4903,21 @@ foreground()	Move the Vim window to the 
 		{only in the Win32, Athena, Motif and GTK GUI versions and the
 		Win32 console version}
 
+fullcommand({name})						*fullcommand()*
+		Get the full command name from a short abbreviated command
+		name; see |20.2| for details on command abbreviations.
+
+		{name} may start with a `:` and can include a [range], these
+		are skipped and not returned.
+		Returns an empty string if a command doesn't exist or if it's
+		ambiguous (for user-defined functions).
+
+		For example `fullcommand('s')`, `fullcommand('sub')`,
+		`fullcommand(':%substitute')` all return "substitute".
+
+		Can also be used as a |method|: >
+			GetName()->fullcommand()
+<
 						*funcref()*
 funcref({name} [, {arglist}] [, {dict}])
 		Just like |function()|, but the returned Funcref will lookup
--- a/runtime/doc/usr_41.txt
+++ b/runtime/doc/usr_41.txt
@@ -883,6 +883,7 @@ Command line:					*command-line-function
 	getcmdtype()		return the current command-line type
 	getcmdwintype()		return the current command-line window type
 	getcompletion()		list of command-line completion matches
+	fullcommand()		get full command name
 
 Quickfix and location lists:			*quickfix-functions*
 	getqflist()		list of quickfix errors
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -978,6 +978,8 @@ static funcentry_T global_functions[] =
 			ret_string,	    f_foldtextresult},
     {"foreground",	0, 0, 0,	    NULL,
 			ret_void,	    f_foreground},
+    {"fullcommand",	1, 1, FEARG_1,	    arg1_string,
+			ret_string,	    f_fullcommand},
     {"funcref",		1, 3, FEARG_1,	    NULL,
 			ret_func_any,	    f_funcref},
     {"function",	1, 3, FEARG_1,	    NULL,
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -3668,6 +3668,33 @@ cmd_exists(char_u *name)
 	return 0;	// trailing garbage
     return (ea.cmdidx == CMD_SIZE ? 0 : (full ? 2 : 1));
 }
+
+/*
+ * "fullcommand" function
+ */
+    void
+f_fullcommand(typval_T *argvars, typval_T *rettv)
+{
+    exarg_T  ea;
+    char_u   *name = argvars[0].vval.v_string;
+    char_u   *p;
+
+    while (name[0] != NUL && name[0] == ':')
+	name++;
+    name = skip_range(name, TRUE, NULL);
+
+    rettv->v_type = VAR_STRING;
+
+    ea.cmd = (*name == '2' || *name == '3') ? name + 1 : name;
+    ea.cmdidx = (cmdidx_T)0;
+    p = find_ex_command(&ea, NULL, NULL, NULL);
+    if (p == NULL || ea.cmdidx == CMD_SIZE)
+	return;
+
+    rettv->vval.v_string = vim_strsave(IS_USER_CMDIDX(ea.cmdidx)
+				    ? get_user_commands(NULL, ea.useridx)
+				    : cmdnames[ea.cmdidx].cmd_name);
+}
 #endif
 
     cmdidx_T
--- a/src/proto/evalfunc.pro
+++ b/src/proto/evalfunc.pro
@@ -23,4 +23,5 @@ void range_list_materialize(list_T *list
 float_T vim_round(float_T f);
 long do_searchpair(char_u *spat, char_u *mpat, char_u *epat, int dir, typval_T *skip, int flags, pos_T *match_pos, linenr_T lnum_stop, long time_limit);
 void f_string(typval_T *argvars, typval_T *rettv);
+void f_fullcommand(typval_T *argvars, typval_T *rettv);
 /* vim: set ft=c : */
--- a/src/testdir/test_cmdline.vim
+++ b/src/testdir/test_cmdline.vim
@@ -442,6 +442,43 @@ func Test_getcompletion()
   call assert_fails('call getcompletion("abc", [])', 'E475:')
 endfunc
 
+func Test_fullcommand()
+  let tests = {
+        \ '':           '',
+        \ ':':          '',
+        \ ':::':        '',
+        \ ':::5':       '',
+        \ 'not_a_cmd':  '',
+        \ 'Check':      '',
+        \ 'syntax':     'syntax',
+        \ ':syntax':    'syntax',
+        \ '::::syntax': 'syntax',
+        \ 'sy':         'syntax',
+        \ 'syn':        'syntax',
+        \ 'synt':       'syntax',
+        \ ':sy':        'syntax',
+        \ '::::sy':     'syntax',
+        \ 'match':      'match',
+        \ '2match':     'match',
+        \ '3match':     'match',
+        \ 'aboveleft':  'aboveleft',
+        \ 'abo':        'aboveleft',
+        \ 's':          'substitute',
+        \ '5s':         'substitute',
+        \ ':5s':        'substitute',
+        \ "'<,'>s":     'substitute',
+        \ ":'<,'>s":    'substitute',
+        \ 'CheckUni':   'CheckUnix',
+        \ 'CheckUnix':  'CheckUnix',
+  \ }
+
+  for [in, want] in items(tests)
+    call assert_equal(want, fullcommand(in))
+  endfor
+
+  call assert_equal('syntax', 'syn'->fullcommand())
+endfunc
+
 func Test_shellcmd_completion()
   let save_path = $PATH
 
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    2468,
+/**/
     2467,
 /**/
     2466,