-*autocmd.txt* For Vim version 9.1. Last change: 2025 Apr 04
+*autocmd.txt* For Vim version 9.1. Last change: 2025 Apr 21
VIM REFERENCE MANUAL by Bram Moolenaar
|CmdlineChanged| after a change was made to the command-line text
|CmdlineEnter| after the cursor moves to the command line
|CmdlineLeave| before the cursor leaves the command line
+|CmdlineLeavePre| before preparing to leave the command line
|InsertEnter| starting Insert mode
|InsertChange| when typing <Insert> while in Insert or Replace mode
<afile> is set to a single character,
indicating the type of command-line.
|cmdwin-char|
+ *CmdlineLeavePre*
+CmdlineLeavePre Just before leaving the command line, and
+ before |CmdlineLeave|. Useful for capturing
+ completion info with |cmdcomplete_info()|, as
+ this information is cleared before
+ |CmdlineLeave| is triggered. Triggered for
+ non-interactive use of ":" in a mapping, but
+ not when using |<Cmd>|. Also triggered when
+ abandoning the command line by typing CTRL-C
+ or <Esc>. <afile> is set to a single
+ character indicating the command-line type.
+ See |cmdwin-char| for details.
*CmdwinEnter*
CmdwinEnter After entering the command-line window.
Useful for setting options specifically for
-*builtin.txt* For Vim version 9.1. Last change: 2025 Apr 18
+*builtin.txt* For Vim version 9.1. Last change: 2025 Apr 21
VIM REFERENCE MANUAL by Bram Moolenaar
chdir({dir}) String change current working directory
cindent({lnum}) Number C indent for line {lnum}
clearmatches([{win}]) none clear all matches
+cmdcomplete_info() Dict get current cmdline completion
+ information
col({expr} [, {winid}]) Number column byte index of cursor or mark
complete({startcol}, {matches}) none set Insert mode completion
complete_add({expr}) Number add completion match
Return type: |Number|
+cmdcomplete_info([{what}]) *cmdcomplete_info()*
+ Returns a |Dictionary| with information about cmdline
+ completion. See |cmdline-completion|.
+ The items are:
+ cmdline_orig The original command-line string before
+ completion began.
+ pum_visible |TRUE| if popup menu is visible.
+ See |pumvisible()|.
+ matches List of all completion candidates. Each item
+ is a string.
+ selected Selected item index. First index is zero.
+ Index is -1 if no item is selected (showing
+ typed text only, or the last completion after
+ no item is selected when using the <Up> or
+ <Down> keys)
+
+ Returns an empty |Dictionary| if no completion was attempted,
+ if there was only one candidate and it was fully completed, or
+ if an error occurred.
+
+ Return type: dict<any>
+
+
col({expr} [, {winid}]) *col()*
The result is a Number, which is the byte index of the column
position given with {expr}.
CmdlineChanged autocmd.txt /*CmdlineChanged*
CmdlineEnter autocmd.txt /*CmdlineEnter*
CmdlineLeave autocmd.txt /*CmdlineLeave*
+CmdlineLeavePre autocmd.txt /*CmdlineLeavePre*
CmdwinEnter autocmd.txt /*CmdwinEnter*
CmdwinLeave autocmd.txt /*CmdwinLeave*
ColorScheme autocmd.txt /*ColorScheme*
closure eval.txt /*closure*
cmdarg-variable eval.txt /*cmdarg-variable*
cmdbang-variable eval.txt /*cmdbang-variable*
+cmdcomplete_info() builtin.txt /*cmdcomplete_info()*
cmdline-arguments vi_diff.txt /*cmdline-arguments*
cmdline-changed version5.txt /*cmdline-changed*
cmdline-completion cmdline.txt /*cmdline-completion*
-*usr_41.txt* For Vim version 9.1. Last change: 2025 Mar 30
+*usr_41.txt* For Vim version 9.1. Last change: 2025 Apr 21
VIM USER MANUAL - by Bram Moolenaar
getcmdwintype() return the current command-line window type
getcompletion() list of command-line completion matches
fullcommand() get full command name
+ cmdcomplete_info() get current completion information
Quickfix and location lists: *quickfix-functions*
getqflist() list of quickfix errors
-*version9.txt* For Vim version 9.1. Last change: 2025 Apr 18
+*version9.txt* For Vim version 9.1. Last change: 2025 Apr 21
VIM REFERENCE MANUAL by Bram Moolenaar
|base64_encode()| encode a blob into a base64 string
|blob2str()| convert a blob into a List of strings
|bindtextdomain()| set message lookup translation base path
+|cmdcomplete_info()| get current cmdline completion info
|diff()| diff two Lists of strings
|filecopy()| copy a file {from} to {to}
|foreach()| apply function to List items
Autocommands: ~
+|CmdlineLeavePre| before preparing to leave the command line
|CursorMovedC| after the cursor was moved in the command-line
|KeyInputPre| before processing any key event in any mode
|SessionWritePost| after writing the session file |:mksession|
KEYVALUE_ENTRY(EVENT_CMDLINECHANGED, "CmdlineChanged"),
KEYVALUE_ENTRY(EVENT_CMDLINEENTER, "CmdlineEnter"),
KEYVALUE_ENTRY(EVENT_CMDLINELEAVE, "CmdlineLeave"),
+ KEYVALUE_ENTRY(EVENT_CMDLINELEAVEPRE, "CmdlineLeavePre"),
KEYVALUE_ENTRY(EVENT_CMDUNDEFINED, "CmdUndefined"),
KEYVALUE_ENTRY(EVENT_CMDWINENTER, "CmdwinEnter"),
KEYVALUE_ENTRY(EVENT_CMDWINLEAVE, "CmdwinLeave"),
|| event == EVENT_SYNTAX
|| event == EVENT_CMDLINECHANGED
|| event == EVENT_CMDLINEENTER
+ || event == EVENT_CMDLINELEAVEPRE
|| event == EVENT_CMDLINELEAVE
|| event == EVENT_CURSORMOVEDC
|| event == EVENT_CMDWINENTER
// First column in cmdline of the matched item for completion.
static int compl_startcol;
static int compl_selected;
+// cmdline before expansion
+static char_u *cmdline_orig = NULL;
#define SHOW_MATCH(m) (showtail ? showmatches_gettail(matches[m]) : matches[m])
pum_undisplay();
VIM_CLEAR(compl_match_array);
+ compl_match_arraysize = 0;
p_lz = FALSE; // avoid the popup menu hanging around
update_screen(0);
p_lz = save_p_lz;
xp->xp_backslash = XP_BS_NONE;
xp->xp_prefix = XP_PREFIX_NONE;
xp->xp_numfiles = -1;
+ VIM_CLEAR(cmdline_orig);
}
/*
int attr;
int showtail;
+ // Save cmdline before expansion
+ if (ccline->cmdbuff != NULL)
+ cmdline_orig = vim_strnsave(ccline->cmdbuff, ccline->cmdlen);
+
if (xp->xp_numfiles == -1)
{
set_expand_context(xp);
vim_free(pat);
ExpandCleanup(&xpc);
}
+
+/*
+ * "cmdcomplete_info()" function
+ */
+ void
+f_cmdcomplete_info(typval_T *argvars UNUSED, typval_T *rettv)
+{
+ cmdline_info_T *ccline = get_cmdline_info();
+ dict_T *retdict;
+ list_T *li;
+ int idx;
+ int ret = OK;
+
+ if (rettv_dict_alloc(rettv) == FAIL || ccline == NULL
+ || ccline->xpc == NULL || ccline->xpc->xp_files == NULL)
+ return;
+ retdict = rettv->vval.v_dict;
+ ret = dict_add_string(retdict, "cmdline_orig", cmdline_orig);
+ if (ret == OK)
+ ret = dict_add_number(retdict, "pum_visible", pum_visible());
+ if (ret == OK)
+ ret = dict_add_number(retdict, "selected", ccline->xpc->xp_selected);
+ if (ret == OK)
+ {
+ li = list_alloc();
+ if (li == NULL)
+ return;
+ ret = dict_add_list(retdict, "matches", li);
+ for (idx = 0; ret == OK && idx < ccline->xpc->xp_numfiles; idx++)
+ list_append_string(li, ccline->xpc->xp_files[idx], -1);
+ }
+}
#endif // FEAT_EVAL
ret_number, f_cindent},
{"clearmatches", 0, 1, FEARG_1, arg1_number,
ret_void, f_clearmatches},
+ {"cmdcomplete_info",0, 0, 0, NULL,
+ ret_dict_any, f_cmdcomplete_info},
{"col", 1, 2, FEARG_1, arg2_string_or_list_number,
ret_number, f_col},
{"complete", 2, 2, FEARG_2, arg2_number_list,
}
}
+ // Trigger CmdlineLeavePre autocommand
+ if (ccline.cmdfirstc != NUL && (c == '\n' || c == '\r' || c == K_KENTER
+ || c == ESC || c == Ctrl_C))
+ trigger_cmd_autocmd(cmdline_type, EVENT_CMDLINELEAVEPRE);
+
// The wildmenu is cleared if the pressed key is not used for
// navigating the wild menu (i.e. the key is not 'wildchar' or
// 'wildcharm' or Ctrl-N or Ctrl-P or Ctrl-A or Ctrl-L).
int wildmenu_process_key(cmdline_info_T *cclp, int key, expand_T *xp);
void wildmenu_cleanup(cmdline_info_T *cclp);
void f_getcompletion(typval_T *argvars, typval_T *rettv);
+void f_cmdcomplete_info(typval_T *argvars UNUSED, typval_T *rettv);
/* vim: set ft=c : */
bwipe Xbar
endfunc
+func Test_Cmdline_Trigger()
+ autocmd CmdlineLeavePre : let g:log = "CmdlineLeavePre"
+ new
+ let g:log = ''
+ nnoremap <F1> <Cmd>echo "hello"<CR>
+ call feedkeys("\<F1>", 'x')
+ call assert_equal('', g:log)
+ nunmap <F1>
+ let g:log = ''
+ nnoremap <F1> :echo "hello"<CR>
+ call feedkeys("\<F1>", 'x')
+ call assert_equal('CmdlineLeavePre', g:log)
+ nunmap <F1>
+ let g:log = ''
+ split
+ call assert_equal('', g:log)
+ call feedkeys(":echo hello", "tx")
+ call assert_equal('CmdlineLeavePre', g:log)
+ let g:log = ''
+ close
+ call assert_equal('', g:log)
+ call feedkeys(":echo hello", "tx")
+ call assert_equal('CmdlineLeavePre', g:log)
+ let g:log = ''
+ tabnew
+ call assert_equal('', g:log)
+ call feedkeys(":echo hello", "tx")
+ call assert_equal('CmdlineLeavePre', g:log)
+ let g:log = ''
+ split
+ call assert_equal('', g:log)
+ call feedkeys(":echo hello", "tx")
+ call assert_equal('CmdlineLeavePre', g:log)
+ let g:log = ''
+ tabclose
+ call assert_equal('', g:log)
+ call feedkeys(":echo hello", "tx")
+ call assert_equal('CmdlineLeavePre', g:log)
+ bw!
+endfunc
+
func Test_Cmdline()
au! CmdlineChanged : let g:text = getcmdline()
let g:text = 0
au! CmdlineEnter : let g:entered = expand('<afile>')
au! CmdlineLeave : let g:left = expand('<afile>')
+ au! CmdlineLeavePre : let g:leftpre = expand('<afile>')
let g:entered = 0
let g:left = 0
+ let g:leftpre = 0
call feedkeys(":echo 'hello'\<CR>", 'xt')
call assert_equal(':', g:entered)
call assert_equal(':', g:left)
+ call assert_equal(':', g:leftpre)
au! CmdlineEnter
au! CmdlineLeave
+ au! CmdlineLeavePre
let save_shellslash = &shellslash
set noshellslash
au! CmdlineEnter / let g:entered = expand('<afile>')
au! CmdlineLeave / let g:left = expand('<afile>')
+ au! CmdlineLeavePre / let g:leftpre = expand('<afile>')
let g:entered = 0
let g:left = 0
+ let g:leftpre = 0
new
call setline(1, 'hello')
call feedkeys("/hello\<CR>", 'xt')
call assert_equal('/', g:entered)
call assert_equal('/', g:left)
+ call assert_equal('/', g:leftpre)
bwipe!
au! CmdlineEnter
au! CmdlineLeave
+ au! CmdlineLeavePre
let &shellslash = save_shellslash
+ let g:left = "cancelled"
+ let g:leftpre = "cancelled"
+ au! CmdlineLeave : let g:left = "triggered"
+ au! CmdlineLeavePre : let g:leftpre = "triggered"
+ call feedkeys(":echo 'hello'\<esc>", 'xt')
+ call assert_equal('triggered', g:left)
+ call assert_equal('triggered', g:leftpre)
+ let g:left = "cancelled"
+ let g:leftpre = "cancelled"
+ au! CmdlineLeave : let g:left = "triggered"
+ call feedkeys(":echo 'hello'\<c-c>", 'xt')
+ call assert_equal('triggered', g:left)
+ call assert_equal('triggered', g:leftpre)
+ au! CmdlineLeave
+ au! CmdlineLeavePre
+
au! CursorMovedC : let g:pos += [getcmdpos()]
let g:pos = []
call feedkeys(":foo bar baz\<C-W>\<C-W>\<C-W>\<Esc>", 'xt')
let &shellslash = save_shellslash
endfunc
+" Testg cmdcomplete_info() with CmdlineLeavePre autocmd
+func Test_cmdcomplete_info()
+ augroup test_CmdlineLeavePre
+ autocmd!
+ autocmd CmdlineLeavePre * let g:cmdcomplete_info = string(cmdcomplete_info())
+ augroup END
+ new
+ call assert_equal({}, cmdcomplete_info())
+ call feedkeys(":h echom\<cr>", "tx") " No expansion
+ call assert_equal('{}', g:cmdcomplete_info)
+ call feedkeys(":h echoms\<tab>\<cr>", "tx")
+ call assert_equal('{''cmdline_orig'': '''', ''pum_visible'': 0, ''matches'': [], ''selected'': 0}', g:cmdcomplete_info)
+ call feedkeys(":h echom\<tab>\<cr>", "tx")
+ call assert_equal(
+ \ '{''cmdline_orig'': ''h echom'', ''pum_visible'': 0, ''matches'': ['':echom'', '':echomsg''], ''selected'': 0}',
+ \ g:cmdcomplete_info)
+ call feedkeys(":h echom\<tab>\<tab>\<cr>", "tx")
+ call assert_equal(
+ \ '{''cmdline_orig'': ''h echom'', ''pum_visible'': 0, ''matches'': ['':echom'', '':echomsg''], ''selected'': 1}',
+ \ g:cmdcomplete_info)
+ call feedkeys(":h echom\<tab>\<tab>\<tab>\<cr>", "tx")
+ call assert_equal(
+ \ '{''cmdline_orig'': ''h echom'', ''pum_visible'': 0, ''matches'': ['':echom'', '':echomsg''], ''selected'': -1}',
+ \ g:cmdcomplete_info)
+
+ set wildoptions=pum
+ call feedkeys(":h echoms\<tab>\<cr>", "tx")
+ call assert_equal('{''cmdline_orig'': '''', ''pum_visible'': 0, ''matches'': [], ''selected'': 0}', g:cmdcomplete_info)
+ call feedkeys(":h echom\<tab>\<cr>", "tx")
+ call assert_equal(
+ \ '{''cmdline_orig'': ''h echom'', ''pum_visible'': 1, ''matches'': ['':echom'', '':echomsg''], ''selected'': 0}',
+ \ g:cmdcomplete_info)
+ call feedkeys(":h echom\<tab>\<tab>\<cr>", "tx")
+ call assert_equal(
+ \ '{''cmdline_orig'': ''h echom'', ''pum_visible'': 1, ''matches'': ['':echom'', '':echomsg''], ''selected'': 1}',
+ \ g:cmdcomplete_info)
+ call feedkeys(":h echom\<tab>\<tab>\<tab>\<cr>", "tx")
+ call assert_equal(
+ \ '{''cmdline_orig'': ''h echom'', ''pum_visible'': 1, ''matches'': ['':echom'', '':echomsg''], ''selected'': -1}',
+ \ g:cmdcomplete_info)
+ bw!
+ set wildoptions&
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 1329,
/**/
1328,
/**/
EVENT_BUFWRITEPRE, // before writing a buffer
EVENT_CMDLINECHANGED, // command line was modified
EVENT_CMDLINEENTER, // after entering the command line
+ EVENT_CMDLINELEAVEPRE, // just before leaving the command line
EVENT_CMDLINELEAVE, // before leaving the command line
EVENT_CMDUNDEFINED, // command undefined
EVENT_CMDWINENTER, // after entering the cmdline window