neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

commit 6ebcb4a4d6ce8c3b1f405c144a0e398c9e6bf068
parent 8fe4e120a2de558fddbb91ba5438d78f3dbd926a
Author: zeertzjq <zeertzjq@outlook.com>
Date:   Sun,  6 Jul 2025 08:29:46 +0800

vim-patch:9.1.1505: not possible to return completion type for :ex command

Problem:  not possible to return command-line completion type for :ex
          command
Solution: make getcmdcompltype() accept an optional and return the
          command-line completion for that arg (Shougo Matsushita).

closes: vim/vim#17606

https://github.com/vim/vim/commit/5d2354fc07b642f8835bef27e6dd46ee705726b5

Co-authored-by: Shougo Matsushita <Shougo.Matsu@gmail.com>

Diffstat:
Mruntime/doc/usr_41.txt | 3+--
Mruntime/doc/vimfn.txt | 12++++++++----
Mruntime/lua/vim/_meta/vimfn.lua | 10++++++----
Msrc/nvim/eval.lua | 13++++++++-----
Msrc/nvim/ex_getln.c | 51++++++++++++++++++++++++++++++++++-----------------
Mtest/old/testdir/test_cmdline.vim | 10++++++++++
6 files changed, 67 insertions(+), 32 deletions(-)

diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt @@ -908,8 +908,7 @@ 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 current command line - completion + getcmdcompltype() get the type of the 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 diff --git a/runtime/doc/vimfn.txt b/runtime/doc/vimfn.txt @@ -3342,15 +3342,19 @@ getcmdcomplpat() *getcmdcomplpat()* Return: ~ (`string`) -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_=|. +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_=|. + 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?`) + Return: ~ (`string`) diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua @@ -2994,16 +2994,18 @@ function vim.fn.getcharstr(expr, opts) end --- @return string function vim.fn.getcmdcomplpat() end ---- 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_=|. +--- 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_=|. +--- --- 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 --- @return string -function vim.fn.getcmdcompltype() end +function vim.fn.getcmdcompltype(pat) end --- Return the current command-line input. Only works when the --- command line is being edited, thus requires use of diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua @@ -3751,19 +3751,22 @@ M.funcs = { signature = 'getcmdcomplpat()', }, getcmdcompltype = { + args = { 0, 1 }, + base = 1, desc = [=[ - 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_=|. + 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_=|. + 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. ]=], name = 'getcmdcompltype', - params = {}, + params = { { 'pat', 'string' } }, returns = 'string', - signature = 'getcmdcompltype()', + signature = 'getcmdcompltype([{pat}])', }, getcmdline = { desc = [=[ diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c @@ -4198,22 +4198,13 @@ static char *get_cmdline_completion_pattern(void) } /// Get the current command-line completion type. -static char *get_cmdline_completion(void) +static char *get_cmdline_completion(expand_T *xpc) { - if (cmdline_star > 0) { - return NULL; - } - - CmdlineInfo *p = get_ccline_ptr(); - if (p == NULL || p->xpc == NULL) { - return NULL; - } - - int xp_context = p->xpc->xp_context; + int xp_context = xpc->xp_context; if (xp_context == EXPAND_NOTHING) { - set_expand_context(p->xpc); - xp_context = p->xpc->xp_context; - p->xpc->xp_context = EXPAND_NOTHING; + set_expand_context(xpc); + xp_context = xpc->xp_context; + xpc->xp_context = EXPAND_NOTHING; } if (xp_context == EXPAND_UNSUCCESSFUL) { return NULL; @@ -4225,9 +4216,9 @@ static char *get_cmdline_completion(void) } if (xp_context == EXPAND_USER_LIST || xp_context == EXPAND_USER_DEFINED) { - size_t buflen = strlen(cmd_compl) + strlen(p->xpc->xp_arg) + 2; + size_t buflen = strlen(cmd_compl) + strlen(xpc->xp_arg) + 2; char *buffer = xmalloc(buflen); - snprintf(buffer, buflen, "%s,%s", cmd_compl, p->xpc->xp_arg); + snprintf(buffer, buflen, "%s,%s", cmd_compl, xpc->xp_arg); return buffer; } @@ -4244,8 +4235,34 @@ 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 = get_cmdline_completion(); + + 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); + } } /// "getcmdline()" function diff --git a/test/old/testdir/test_cmdline.vim b/test/old/testdir/test_cmdline.vim @@ -4601,4 +4601,14 @@ 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