From 9c04eb02adde4f7daae2c4986ed58037358ce4ad Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 6 Jul 2025 08:41:41 +0800 Subject: [PATCH] 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 Co-authored-by: Shougo Matsushita --- runtime/doc/news.txt | 1 + runtime/doc/usr_41.txt | 5 ++++- runtime/doc/vimfn.txt | 26 ++++++++++++++++------- runtime/lua/vim/_meta/vimfn.lua | 23 ++++++++++++++------ src/nvim/cmdexpand.c | 24 +++++++++++++++++++++ src/nvim/eval.lua | 31 ++++++++++++++++++++------- src/nvim/ex_getln.c | 35 +++++++------------------------ test/old/testdir/test_cmdline.vim | 35 ++++++++++++++++++++++--------- 8 files changed, 121 insertions(+), 59 deletions(-) diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index df62f5a5d3..76cc711c63 100644 --- 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 index ede9dd83bf..45d996effb 100644 --- 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 index c15ada1b5b..e549042687 100644 --- 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 index 9f82fe41ff..d690eaa34a 100644 --- 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 index a1d7ae7e2c..4132e56142 100644 --- 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 index 0407a7bdbe..80f73ac209 100644 --- 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 index 570c2086c5..8ad5739bb3 100644 --- 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) { + rettv->v_type = VAR_STRING; + rettv->vval.v_string = NULL; + + CmdlineInfo *p = get_ccline_ptr(); + if (cmdline_star > 0 || p == NULL || p->xpc == NULL) { return; } - rettv->v_type = VAR_STRING; - - 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); - } + 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 index e80ede04c4..9b13bc948e 100644 --- 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