vim-patch:9.1.1638: completion: not possible to delay the autcompletion

Problem:  completion: not possible to delay the autcompletion
Solution: add the 'autocompletedelay' option value (Girish Palya).

This patch introduces a new global option 'autocompletedelay'/'acl' that
specifies the delay, in milliseconds, before the autocomplete menu
appears after typing.

When set to a non-zero value, Vim waits for the specified time before
showing the completion popup, allowing users to reduce distraction from
rapid suggestion pop-ups or to fine-tune the responsiveness of
completion.

The default value is 0, which preserves the current immediate-popup
behavior.

closes: vim/vim#17960

a09b1604d4

N/A patch: vim-patch:9.1.1641: a few compiler warnings are output

Co-authored-by: Girish Palya <girishji@gmail.com>
This commit is contained in:
zeertzjq
2025-08-22 14:54:26 +08:00
parent 639f9f4cda
commit 4019d3050d
10 changed files with 200 additions and 8 deletions

View File

@@ -1117,8 +1117,8 @@ CTRL-X CTRL-Z Stop completion without changing the text.
AUTOCOMPLETION *ins-autocompletion*
Vim can display a completion menu as you type, similar to using |i_CTRL-N|,
but triggered automatically. See 'autocomplete'. The menu items are collected
from the sources listed in the 'complete' option.
but triggered automatically. See 'autocomplete' and 'autocompletedelay'.
The menu items are collected from the sources listed in the 'complete' option.
Unlike manual |i_CTRL-N| completion, this mode uses a decaying timeout to keep
Vim responsive. Sources earlier in the 'complete' list are given more time

View File

@@ -747,6 +747,13 @@ A jump table for the options with a short description can be found at |Q_op|.
When on, Vim shows a completion menu as you type, similar to using
|i_CTRL-N|, but triggered automatically. See |ins-autocompletion|.
*'autocompletedelay'* *'acl'*
'autocompletedelay' 'acl' number (default 0)
global
Delay in milliseconds before the autocomplete menu appears after
typing. If you prefer it not to open too quickly, set this value
slightly above your typing speed. See |ins-autocompletion|.
*'autoindent'* *'ai'* *'noautoindent'* *'noai'*
'autoindent' 'ai' boolean (default on)
local to buffer

View File

@@ -626,6 +626,7 @@ Short explanation of each option: *option-list*
'arabicshape' 'arshape' do shaping for Arabic characters
'autochdir' 'acd' change directory to the file in the current window
'autocomplete' 'ac' enable automatic completion in insert mode
'autocompletedelay' 'acl' delay in msec before menu appears after typing
'autoindent' 'ai' take indent for new line from previous line
'autoread' 'ar' autom. read file when changed outside of Vim
'autowrite' 'aw' automatically write file if changed

View File

@@ -120,6 +120,16 @@ vim.o.ac = vim.o.autocomplete
vim.go.autocomplete = vim.o.autocomplete
vim.go.ac = vim.go.autocomplete
--- Delay in milliseconds before the autocomplete menu appears after
--- typing. If you prefer it not to open too quickly, set this value
--- slightly above your typing speed. See `ins-autocompletion`.
---
--- @type integer
vim.o.autocompletedelay = 0
vim.o.acl = vim.o.autocompletedelay
vim.go.autocompletedelay = vim.o.autocompletedelay
vim.go.acl = vim.go.autocompletedelay
--- Copy indent from current line when starting a new line (typing <CR>
--- in Insert mode or when using the "o" or "O" command). If you do not
--- type anything on the new line except <BS> or CTRL-D and then type

View File

@@ -1,7 +1,7 @@
" These commands create the option window.
"
" Maintainer: The Vim Project <https://github.com/vim/vim>
" Last Change: 2025 Aug 07
" Last Change: 2025 Aug 16
" Former Maintainer: Bram Moolenaar <Bram@vim.org>
" If there already is an option window, jump to that one.
@@ -737,6 +737,8 @@ if has("insert_expand")
call <SID>OptionL("cpt")
call <SID>AddOption("autocomplete", gettext("automatic completion in insert mode"))
call <SID>BinOptionG("ac", &ac)
call <SID>AddOption("autocompletedelay", gettext("delay in msec before menu appears after typing"))
call append("$", " \tset acl=" . &acl)
call <SID>AddOption("completeopt", gettext("whether to use a popup menu for Insert mode completion"))
call <SID>OptionL("cot")
call <SID>AddOption("completeitemalign", gettext("popup menu item align order"))

View File

@@ -2206,6 +2206,13 @@ static void ins_compl_new_leader(void)
ins_compl_insert_bytes(compl_leader.data + get_compl_len(), -1);
compl_used_match = false;
if (p_acl > 0) {
pum_undisplay(true);
redraw_later(curwin, UPD_VALID);
update_screen(); // Show char (deletion) immediately
ui_flush();
}
if (compl_started) {
ins_compl_set_original_text(compl_leader.data, compl_leader.size);
if (is_cpt_func_refresh_always()) {
@@ -4811,10 +4818,10 @@ static int ins_compl_get_exp(pos_T *ini)
found_new_match = FAIL;
}
int i = -1; // total of matches, unknown
int match_count = -1; // total of matches, unknown
if (found_new_match == FAIL
|| (ctrl_x_mode_not_default() && !ctrl_x_mode_line_or_eval())) {
i = ins_compl_make_cyclic();
match_count = ins_compl_make_cyclic();
}
if (cfc_has_mode() && compl_get_longest && compl_num_bests > 0) {
@@ -4838,7 +4845,7 @@ static int ins_compl_get_exp(pos_T *ini)
sort_compl_match_list(cp_compare_nearest);
}
return i;
return match_count;
}
/// Update "compl_shown_match" to the actually shown match, it may differ when
@@ -5288,7 +5295,7 @@ static int ins_compl_next(bool allow_get_expansion, int count, bool insert_match
/// collecting, and halve the timeout.
static void check_elapsed_time(void)
{
if (cpt_sources_array == NULL) {
if (cpt_sources_array == NULL || cpt_sources_index < 0) {
return;
}
@@ -6026,6 +6033,11 @@ int ins_complete(int c, bool enable_pum)
return FAIL;
}
// Timestamp when match collection starts
uint64_t compl_start_tv = 0;
if (compl_autocomplete && p_acl > 0) {
compl_start_tv = os_hrtime();
}
compl_curr_win = curwin;
compl_curr_buf = curwin->w_buffer;
compl_shown_match = compl_curr_match;
@@ -6050,7 +6062,8 @@ int ins_complete(int c, bool enable_pum)
}
// we found no match if the list has only the "compl_orig_text"-entry
if (is_first_match(compl_first_match->cp_next)) {
bool no_matches_found = is_first_match(compl_first_match->cp_next);
if (no_matches_found) {
// remove N_ADDS flag, so next ^X<> won't try to go to ADDING mode,
// because we couldn't expand anything at first place, but if we used
// ^P, ^N, ^X^I or ^X^D we might want to add-expand a single-char-word
@@ -6074,6 +6087,22 @@ int ins_complete(int c, bool enable_pum)
ins_compl_show_statusmsg();
}
// Wait for the autocompletion delay to expire
if (compl_autocomplete && p_acl > 0 && !no_matches_found
&& (os_hrtime() - compl_start_tv) / 1000000 < (uint64_t)p_acl) {
setcursor();
ui_flush();
do {
if (char_avail()) {
ins_compl_restart();
compl_interrupted = true;
break;
} else {
os_delay(2L, true);
}
} while ((os_hrtime() - compl_start_tv) / 1000000 < (uint64_t)p_acl);
}
// Show the popup menu, unless we got interrupted.
if (enable_pum && !compl_interrupted) {
show_pum(save_w_wrow, save_w_leftcol);

View File

@@ -301,6 +301,7 @@ EXTERN unsigned cia_flags; ///< order flags of 'completeitemalign'
EXTERN char *p_cot; ///< 'completeopt'
EXTERN unsigned cot_flags; ///< flags from 'completeopt'
EXTERN int p_ac; ///< 'autocomplete'
EXTERN OptInt p_acl; ///< 'autocompletedelay'
#ifdef BACKSLASH_IN_FILENAME
EXTERN char *p_csl; ///< 'completeslash'
#endif

View File

@@ -241,6 +241,20 @@ local options = {
type = 'boolean',
varname = 'p_ac',
},
{
abbreviation = 'acl',
defaults = 0,
desc = [=[
Delay in milliseconds before the autocomplete menu appears after
typing. If you prefer it not to open too quickly, set this value
slightly above your typing speed. See |ins-autocompletion|.
]=],
full_name = 'autocompletedelay',
scope = { 'global' },
short_desc = N_('delay in msec before menu appears after typing'),
type = 'number',
varname = 'p_acl',
},
{
abbreviation = 'ai',
defaults = true,

View File

@@ -1409,4 +1409,98 @@ describe('completion', function()
{5:-- INSERT --} 4,6 All |
]])
end)
-- oldtest: Test_autocompletedelay()
it("'autocompletedelay' option", function()
source([[
call setline(1, ['foo', 'foobar', 'foobarbaz'])
set autocomplete
]])
screen:try_resize(60, 10)
feed('Gof')
screen:expect([[
foo |
foobar |
foobarbaz |
f^ |
{4:foobarbaz }{1: }|
{4:foobar }{1: }|
{4:foo }{1: }|
{1:~ }|*2
{5:-- INSERT --} |
]])
feed('<Esc>')
command('set autocompletedelay=500')
feed('Sf')
screen:expect([[
foo |
foobar |
foobarbaz |
f^ |
{1:~ }|*5
{5:-- INSERT --} |
]])
feed('o')
screen:expect([[
foo |
foobar |
foobarbaz |
fo^ |
{1:~ }|*5
{5:-- INSERT --} |
]])
vim.uv.sleep(500)
screen:expect([[
foo |
foobar |
foobarbaz |
fo^ |
{4:foobarbaz }{1: }|
{4:foobar }{1: }|
{4:foo }{1: }|
{1:~ }|*2
{5:-- INSERT --} |
]])
feed('<BS>')
screen:expect([[
foo |
foobar |
foobarbaz |
f^ |
{1:~ }|*5
{5:-- INSERT --} |
]])
vim.uv.sleep(500)
screen:expect([[
foo |
foobar |
foobarbaz |
f^ |
{4:foobarbaz }{1: }|
{4:foobar }{1: }|
{4:foo }{1: }|
{1:~ }|*2
{5:-- INSERT --} |
]])
-- During delay wait, user can open menu using CTRL_N completion
feed('<Esc>')
command('set completeopt=menuone,preinsert')
feed('Sf<C-N>')
screen:expect([[
foo |
foobar |
foobarbaz |
f^oo |
{12:foo }{1: }|
{4:foobar }{1: }|
{4:foobarbaz }{1: }|
{1:~ }|*2
{5:-- Keyword completion (^N^P) }{6:match 1 of 3} |
]])
feed('<esc>')
end)
end)

View File

@@ -5573,4 +5573,38 @@ func Test_omni_start_invalid_col()
set omnifunc& complete&
endfunc
func Test_autocompletedelay()
CheckScreendump
let lines =<< trim [SCRIPT]
call setline(1, ['foo', 'foobar', 'foobarbaz'])
set autocomplete
[SCRIPT]
call writefile(lines, 'XTest_autocomplete_delay', 'D')
let buf = RunVimInTerminal('-S XTest_autocomplete_delay', {'rows': 10})
call term_sendkeys(buf, "Gof")
call VerifyScreenDump(buf, 'Test_autocompletedelay_1', {})
call term_sendkeys(buf, "\<Esc>:set autocompletedelay=500\<CR>")
call term_sendkeys(buf, "Sf")
call VerifyScreenDump(buf, 'Test_autocompletedelay_2', {})
call term_sendkeys(buf, "o")
call VerifyScreenDump(buf, 'Test_autocompletedelay_3', {})
sleep 500m
call VerifyScreenDump(buf, 'Test_autocompletedelay_4', {})
call term_sendkeys(buf, "\<BS>")
call VerifyScreenDump(buf, 'Test_autocompletedelay_5', {})
sleep 500m
call VerifyScreenDump(buf, 'Test_autocompletedelay_6', {})
" During delay wait, user can open menu using CTRL_N completion
call term_sendkeys(buf, "\<Esc>:set completeopt=menuone,preinsert\<CR>")
call term_sendkeys(buf, "Sf\<C-N>")
call VerifyScreenDump(buf, 'Test_autocompletedelay_7', {})
call term_sendkeys(buf, "\<esc>")
call StopVimInTerminal(buf)
endfunc
" vim: shiftwidth=2 sts=2 expandtab nofoldenable