commit 9c04eb02adde4f7daae2c4986ed58037358ce4ad
parent 6ebcb4a4d6ce8c3b1f405c144a0e398c9e6bf068
Author: zeertzjq <zeertzjq@outlook.com>
Date: Sun, 6 Jul 2025 08:41:41 +0800
vim-patch:9.1.1509: patch 9.1.1505 was not good
Problem: Patch 9.1.1505 was not good
Solution: Revert "patch 9.1.1505: not possible to return completion type
for :ex command" and instead add the getcompletiontype()
function (Hirohito Higashi).
related: vim/vim#17606
closes: vim/vim#17662
https://github.com/vim/vim/commit/96b3ef23896ce70b2fdf3425ba2c013ce2840db6
Cherry-pick Test_multibyte_expression() from Vim, as it passes.
Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
Co-authored-by: Shougo Matsushita <Shougo.Matsu@gmail.com>
Diffstat:
8 files changed, 121 insertions(+), 59 deletions(-)
diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt
@@ -269,6 +269,7 @@ UI
VIMSCRIPT
• |cmdcomplete_info()| gets current cmdline completion info.
+• |getcompletiontype()| gets command-line completion type for any string.
• |prompt_getinput()| gets current user-input in prompt-buffer.
==============================================================================
diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt
@@ -908,7 +908,8 @@ Buffers, windows and the argument list:
Command line: *command-line-functions*
getcmdcomplpat() get completion pattern of the current command
line
- getcmdcompltype() get the type of the command line completion
+ getcmdcompltype() get the type of the current command line
+ completion
getcmdline() get the current command line input
getcmdprompt() get the current command line prompt
getcmdpos() get position of the cursor in the command line
@@ -919,6 +920,8 @@ Command line: *command-line-functions*
getcmdtype() return the current command-line type
getcmdwintype() return the current command-line window type
getcompletion() list of command-line completion matches
+ getcompletiontype() get the type of the command-line completion
+ for specified string
fullcommand() get full command name
cmdcomplete_info() get command-line completion information
diff --git a/runtime/doc/vimfn.txt b/runtime/doc/vimfn.txt
@@ -3342,18 +3342,17 @@ getcmdcomplpat() *getcmdcomplpat()*
Return: ~
(`string`)
-getcmdcompltype([{pat}]) *getcmdcompltype()*
- Return the type of command-line completion using {pat}.
- If {pat} is omited, only works when the command line is being
- edited, thus requires use of |c_CTRL-\_e| or |c_CTRL-R_=|.
-
+getcmdcompltype() *getcmdcompltype()*
+ Return the type of the current command-line completion.
+ Only works when the command line is being edited, thus
+ requires use of |c_CTRL-\_e| or |c_CTRL-R_=|.
See |:command-completion| for the return string.
Also see |getcmdtype()|, |setcmdpos()|, |getcmdline()|,
|getcmdprompt()|, |getcmdcomplpat()| and |setcmdline()|.
Returns an empty string when completion is not defined.
- Parameters: ~
- • {pat} (`string?`)
+ To get the type of the command-line completion for the
+ specified string, use |getcompletiontype()|.
Return: ~
(`string`)
@@ -3514,6 +3513,19 @@ getcompletion({pat}, {type} [, {filtered}]) *getcompletion()*
Return: ~
(`string[]`)
+getcompletiontype({pat}) *getcompletiontype()*
+ Return the type of the command-line completion using {pat}.
+ When no corresponding completion type is found, an empty
+ string is returned.
+ To get the current command-line completion type, use
+ |getcmdcompltype()|.
+
+ Parameters: ~
+ • {pat} (`string`)
+
+ Return: ~
+ (`string`)
+
getcurpos([{winid}]) *getcurpos()*
Get the position of the cursor. This is like getpos('.'), but
includes an extra "curswant" item in the list:
diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua
@@ -2994,18 +2994,19 @@ function vim.fn.getcharstr(expr, opts) end
--- @return string
function vim.fn.getcmdcomplpat() end
---- Return the type of command-line completion using {pat}.
---- If {pat} is omited, only works when the command line is being
---- edited, thus requires use of |c_CTRL-\_e| or |c_CTRL-R_=|.
----
+--- Return the type of the current command-line completion.
+--- Only works when the command line is being edited, thus
+--- requires use of |c_CTRL-\_e| or |c_CTRL-R_=|.
--- See |:command-completion| for the return string.
--- Also see |getcmdtype()|, |setcmdpos()|, |getcmdline()|,
--- |getcmdprompt()|, |getcmdcomplpat()| and |setcmdline()|.
--- Returns an empty string when completion is not defined.
---
---- @param pat? string
+--- To get the type of the command-line completion for the
+--- specified string, use |getcompletiontype()|.
+---
--- @return string
-function vim.fn.getcmdcompltype(pat) end
+function vim.fn.getcmdcompltype() end
--- Return the current command-line input. Only works when the
--- command line is being edited, thus requires use of
@@ -3154,6 +3155,16 @@ function vim.fn.getcmdwintype() end
--- @return string[]
function vim.fn.getcompletion(pat, type, filtered) end
+--- Return the type of the command-line completion using {pat}.
+--- When no corresponding completion type is found, an empty
+--- string is returned.
+--- To get the current command-line completion type, use
+--- |getcmdcompltype()|.
+---
+--- @param pat string
+--- @return string
+function vim.fn.getcompletiontype(pat) end
+
--- Get the position of the cursor. This is like getpos('.'), but
--- includes an extra "curswant" item in the list:
--- [0, lnum, col, off, curswant] ~
diff --git a/src/nvim/cmdexpand.c b/src/nvim/cmdexpand.c
@@ -3838,6 +3838,30 @@ theend:
ExpandCleanup(&xpc);
}
+/// "getcompletiontype()" function
+void f_getcompletiontype(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
+{
+ rettv->v_type = VAR_STRING;
+ rettv->vval.v_string = NULL;
+
+ if (tv_check_for_string_arg(argvars, 0) == FAIL) {
+ return;
+ }
+
+ const char *pat = tv_get_string(&argvars[0]);
+ expand_T xpc;
+ ExpandInit(&xpc);
+
+ int cmdline_len = (int)strlen(pat);
+ set_cmd_context(&xpc, (char *)pat, cmdline_len, cmdline_len, false);
+ xpc.xp_pattern_len = strlen(xpc.xp_pattern);
+ xpc.xp_col = cmdline_len;
+
+ rettv->vval.v_string = get_cmdline_completion(&xpc);
+
+ ExpandCleanup(&xpc);
+}
+
/// "cmdcomplete_info()" function
void f_cmdcomplete_info(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua
@@ -3751,22 +3751,22 @@ M.funcs = {
signature = 'getcmdcomplpat()',
},
getcmdcompltype = {
- args = { 0, 1 },
- base = 1,
desc = [=[
- Return the type of command-line completion using {pat}.
- If {pat} is omited, only works when the command line is being
- edited, thus requires use of |c_CTRL-\_e| or |c_CTRL-R_=|.
-
+ Return the type of the current command-line completion.
+ Only works when the command line is being edited, thus
+ requires use of |c_CTRL-\_e| or |c_CTRL-R_=|.
See |:command-completion| for the return string.
Also see |getcmdtype()|, |setcmdpos()|, |getcmdline()|,
|getcmdprompt()|, |getcmdcomplpat()| and |setcmdline()|.
Returns an empty string when completion is not defined.
+
+ To get the type of the command-line completion for the
+ specified string, use |getcompletiontype()|.
]=],
name = 'getcmdcompltype',
- params = { { 'pat', 'string' } },
+ params = {},
returns = 'string',
- signature = 'getcmdcompltype([{pat}])',
+ signature = 'getcmdcompltype()',
},
getcmdline = {
desc = [=[
@@ -3943,6 +3943,21 @@ M.funcs = {
returns = 'string[]',
signature = 'getcompletion({pat}, {type} [, {filtered}])',
},
+ getcompletiontype = {
+ args = 1,
+ base = 1,
+ desc = [=[
+ Return the type of the command-line completion using {pat}.
+ When no corresponding completion type is found, an empty
+ string is returned.
+ To get the current command-line completion type, use
+ |getcmdcompltype()|.
+ ]=],
+ name = 'getcompletiontype',
+ params = { { 'pat', 'string' } },
+ returns = 'string',
+ signature = 'getcompletiontype({pat})',
+ },
getcurpos = {
args = { 0, 1 },
base = 1,
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
@@ -4197,8 +4197,8 @@ static char *get_cmdline_completion_pattern(void)
return xstrdup(compl_pat);
}
-/// Get the current command-line completion type.
-static char *get_cmdline_completion(expand_T *xpc)
+/// Get the command-line completion type.
+char *get_cmdline_completion(expand_T *xpc)
{
int xp_context = xpc->xp_context;
if (xp_context == EXPAND_NOTHING) {
@@ -4235,34 +4235,15 @@ void f_getcmdcomplpat(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
/// "getcmdcompltype()" function
void f_getcmdcompltype(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
- if (tv_check_for_opt_string_arg(argvars, 0) == FAIL) {
- return;
- }
-
rettv->v_type = VAR_STRING;
+ rettv->vval.v_string = NULL;
- if (argvars[0].v_type != VAR_UNKNOWN) {
- char *pat = (char *)tv_get_string(&argvars[0]);
- expand_T xpc;
- ExpandInit(&xpc);
-
- int cmdline_len = (int)strlen(pat);
- set_cmd_context(&xpc, pat, cmdline_len, cmdline_len, false);
- xpc.xp_pattern_len = strlen(xpc.xp_pattern);
- xpc.xp_col = cmdline_len;
-
- rettv->v_type = VAR_STRING;
- rettv->vval.v_string = get_cmdline_completion(&xpc);
-
- ExpandCleanup(&xpc);
- } else {
- CmdlineInfo *p = get_ccline_ptr();
- if (cmdline_star > 0 || p == NULL || p->xpc == NULL) {
- return;
- }
-
- rettv->vval.v_string = get_cmdline_completion(p->xpc);
+ CmdlineInfo *p = get_ccline_ptr();
+ if (cmdline_star > 0 || p == NULL || p->xpc == NULL) {
+ return;
}
+
+ rettv->vval.v_string = get_cmdline_completion(p->xpc);
}
/// "getcmdline()" function
diff --git a/test/old/testdir/test_cmdline.vim b/test/old/testdir/test_cmdline.vim
@@ -737,6 +737,31 @@ func Test_getcompletion()
call assert_fails('call getcompletion("abc", [])', 'E1174:')
endfunc
+func Test_getcompletiontype()
+ call assert_fails('call getcompletiontype()', 'E119:')
+ call assert_fails('call getcompletiontype({})', 'E1174:')
+ call assert_equal(getcompletiontype(''), 'command')
+ call assert_equal(getcompletiontype('dummy '), '')
+ call assert_equal(getcompletiontype('cd '), 'dir_in_path')
+ call assert_equal(getcompletiontype('let v:n'), 'var')
+ call assert_equal(getcompletiontype('call tag'), 'function')
+ call assert_equal(getcompletiontype('help '), 'help')
+endfunc
+
+func Test_multibyte_expression()
+ " Get a dialog in the GUI
+ CheckNotGui
+
+ " This was using uninitialized memory.
+ let lines =<< trim END
+ set verbose=6
+ norm @=ٷ
+ qall!
+ END
+ call writefile(lines, 'XmultiScript', 'D')
+ call RunVim('', '', '-u NONE -n -e -s -S XmultiScript')
+endfunc
+
" Test for getcompletion() with "fuzzy" in 'wildoptions'
func Test_getcompletion_wildoptions()
let save_wildoptions = &wildoptions
@@ -4601,14 +4626,4 @@ func Test_range_complete()
set wildcharm=0
endfunc
-func Test_getcmdcompltype_with_pat()
- call assert_fails('call getcmdcompltype({})', 'E1174:')
- call assert_equal(getcmdcompltype(''), 'command')
- call assert_equal(getcmdcompltype('dummy '), '')
- call assert_equal(getcmdcompltype('cd '), 'dir_in_path')
- call assert_equal(getcmdcompltype('let v:n'), 'var')
- call assert_equal(getcmdcompltype('call tag'), 'function')
- call assert_equal(getcmdcompltype('help '), 'help')
-endfunc
-
" vim: shiftwidth=2 sts=2 expandtab