mirror of
https://github.com/neovim/neovim.git
synced 2026-08-26 09:01:57 +00:00
vim-patch:9.2.1004: a completion function cannot tell why it was called (#41500)
Problem: A function used through 'omnifunc' or 'complete' is called the
same way whether 'autocomplete' started the completion or a
key asked for one, so it cannot answer differently.
Solution: Report which of the two it is in complete_info() as "auto". It
is returned only when asked for in {what}, so what
complete_info() says by itself does not change
(Hirohito Higashi).
closes: vim/vim#21143
1f56c351de
Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
This commit is contained in:
@@ -1316,6 +1316,12 @@ complete_info([{what}]) *complete_info()*
|
||||
Returns a |Dictionary| with information about Insert mode
|
||||
completion. See |ins-completion|.
|
||||
The items are:
|
||||
auto |TRUE| when Vim started this completion by
|
||||
itself, which is what 'autocomplete' does,
|
||||
and |FALSE| when a key asked for it, such as
|
||||
|i_CTRL-X_CTRL-O|. A |complete-functions|
|
||||
function can read this to tell the two apart.
|
||||
Returned only when asked for in {what}.
|
||||
completed Return a dictionary containing the entries of
|
||||
the currently selected index item.
|
||||
items List of all completion candidates. Each item
|
||||
|
||||
6
runtime/lua/vim/_meta/vimfn.gen.lua
generated
6
runtime/lua/vim/_meta/vimfn.gen.lua
generated
@@ -1135,6 +1135,12 @@ function vim.fn.complete_check() end
|
||||
--- Returns a |Dictionary| with information about Insert mode
|
||||
--- completion. See |ins-completion|.
|
||||
--- The items are:
|
||||
--- auto |TRUE| when Vim started this completion by
|
||||
--- itself, which is what 'autocomplete' does,
|
||||
--- and |FALSE| when a key asked for it, such as
|
||||
--- |i_CTRL-X_CTRL-O|. A |complete-functions|
|
||||
--- function can read this to tell the two apart.
|
||||
--- Returned only when asked for in {what}.
|
||||
--- completed Return a dictionary containing the entries of
|
||||
--- the currently selected index item.
|
||||
--- items List of all completion candidates. Each item
|
||||
|
||||
@@ -1489,6 +1489,12 @@ M.funcs = {
|
||||
Returns a |Dictionary| with information about Insert mode
|
||||
completion. See |ins-completion|.
|
||||
The items are:
|
||||
auto |TRUE| when Vim started this completion by
|
||||
itself, which is what 'autocomplete' does,
|
||||
and |FALSE| when a key asked for it, such as
|
||||
|i_CTRL-X_CTRL-O|. A |complete-functions|
|
||||
function can read this to tell the two apart.
|
||||
Returned only when asked for in {what}.
|
||||
completed Return a dictionary containing the entries of
|
||||
the currently selected index item.
|
||||
items List of all completion candidates. Each item
|
||||
|
||||
@@ -134,6 +134,7 @@ static kvec_t(char) replace_stack = KV_INITIAL_VALUE;
|
||||
update_screen(); /* Show char deletion immediately */ \
|
||||
ui_flush(); \
|
||||
ins_compl_enable_autocomplete(); \
|
||||
ins_compl_arm_autostart(); \
|
||||
if (!ins_compl_arm_autocomplete_delay()) { \
|
||||
insert_do_complete(s); \
|
||||
break; \
|
||||
@@ -522,6 +523,7 @@ static int insert_check(VimState *state)
|
||||
s->c = char_before_cursor();
|
||||
if (vim_isprintc(s->c)) {
|
||||
ins_compl_enable_autocomplete();
|
||||
ins_compl_arm_autostart();
|
||||
ins_compl_init_get_longest();
|
||||
// Defer until the delay expires (K_COMPLETE_DELAY), or
|
||||
// trigger now when no delay is in effect.
|
||||
@@ -563,6 +565,7 @@ static int insert_execute(VimState *state, int key)
|
||||
if (key != K_EVENT && key != K_COMPLETE_DELAY) {
|
||||
// Don't want delayed autocompletion from the previous key either.
|
||||
ins_compl_clear_autocomplete_delay();
|
||||
ins_compl_disarm_autostart();
|
||||
}
|
||||
|
||||
// Special handling of keys while the popup menu is visible or wanted
|
||||
@@ -1001,6 +1004,7 @@ static int insert_handle_key(InsertState *s)
|
||||
// The completion may have been cleared while waiting, so re-enable
|
||||
// autocomplete to match a zero delay.
|
||||
ins_compl_enable_autocomplete();
|
||||
ins_compl_arm_autostart();
|
||||
insert_do_complete(s);
|
||||
break;
|
||||
|
||||
|
||||
@@ -329,6 +329,8 @@ static buf_T *compl_curr_buf = NULL; ///< buf where completion is active
|
||||
// longer fixed timeout is used (COMPL_FUNC_TIMEOUT_MS or
|
||||
// COMPL_FUNC_TIMEOUT_NON_KW_MS). - girish
|
||||
static bool compl_autocomplete = false; ///< whether autocompletion is active
|
||||
static bool compl_autostarted = false; ///< Vim started this completion
|
||||
static bool compl_autostart_pending = false; ///< the trigger armed one
|
||||
static bool compl_autocomplete_pending = false;
|
||||
static uint64_t compl_autocomplete_start_tv; ///< when the delay was armed
|
||||
static uint64_t compl_timeout_ms = COMPL_INITIAL_TIMEOUT_MS;
|
||||
@@ -2287,6 +2289,7 @@ void ins_compl_clear(void)
|
||||
cpt_sources_clear();
|
||||
compl_autocomplete = false;
|
||||
compl_from_nonkeyword = false;
|
||||
compl_autostarted = false;
|
||||
compl_num_bests = 0;
|
||||
// clear v:completed_item
|
||||
set_vim_var_dict(VV_COMPLETED_ITEM, tv_dict_alloc_lock(VAR_FIXED));
|
||||
@@ -2586,6 +2589,7 @@ static void ins_compl_restart(void)
|
||||
cpt_sources_clear();
|
||||
compl_autocomplete = false;
|
||||
compl_from_nonkeyword = false;
|
||||
compl_autostarted = false;
|
||||
compl_num_bests = 0;
|
||||
}
|
||||
|
||||
@@ -2892,6 +2896,7 @@ static bool ins_compl_stop(const int c, const int prev_mode, bool retval)
|
||||
}
|
||||
compl_autocomplete = false;
|
||||
compl_from_nonkeyword = false;
|
||||
compl_autostarted = false;
|
||||
compl_num_bests = 0;
|
||||
compl_ins_end_col = 0;
|
||||
|
||||
@@ -3696,11 +3701,12 @@ static void get_complete_info(list_T *what_list, dict_T *retdict)
|
||||
#define CI_WHAT_COMPLETED 0x10
|
||||
#define CI_WHAT_MATCHES 0x20
|
||||
#define CI_WHAT_PREINSERTED_TEXT 0x40
|
||||
#define CI_WHAT_AUTO 0x80
|
||||
#define CI_WHAT_ALL 0xff
|
||||
int what_flag;
|
||||
|
||||
if (what_list == NULL) {
|
||||
what_flag = CI_WHAT_ALL & ~(CI_WHAT_MATCHES|CI_WHAT_COMPLETED);
|
||||
what_flag = CI_WHAT_ALL & ~(CI_WHAT_MATCHES|CI_WHAT_COMPLETED|CI_WHAT_AUTO);
|
||||
} else {
|
||||
what_flag = 0;
|
||||
for (listitem_T *item = tv_list_first(what_list)
|
||||
@@ -3722,6 +3728,8 @@ static void get_complete_info(list_T *what_list, dict_T *retdict)
|
||||
what_flag |= CI_WHAT_PREINSERTED_TEXT;
|
||||
} else if (strcmp(what, "matches") == 0) {
|
||||
what_flag |= CI_WHAT_MATCHES;
|
||||
} else if (strcmp(what, "auto") == 0) {
|
||||
what_flag |= CI_WHAT_AUTO;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3736,6 +3744,10 @@ static void get_complete_info(list_T *what_list, dict_T *retdict)
|
||||
ret = tv_dict_add_nr(retdict, S_LEN("pum_visible"), pum_visible());
|
||||
}
|
||||
|
||||
if (ret == OK && (what_flag & CI_WHAT_AUTO)) {
|
||||
ret = tv_dict_add_nr(retdict, S_LEN("auto"), compl_autostarted);
|
||||
}
|
||||
|
||||
if (ret == OK && (what_flag & CI_WHAT_PREINSERTED_TEXT)) {
|
||||
char *line = get_cursor_line_ptr();
|
||||
int len = compl_ins_end_col - curwin->w_cursor.col;
|
||||
@@ -6317,6 +6329,9 @@ int ins_complete(int c, bool enable_pum)
|
||||
int insert_match = ins_compl_use_match(c);
|
||||
|
||||
if (!compl_started) {
|
||||
// Only what the automatic trigger armed counts as started by Vim.
|
||||
compl_autostarted = compl_autostart_pending;
|
||||
compl_autostart_pending = false;
|
||||
if (ins_compl_start() == FAIL) {
|
||||
return FAIL;
|
||||
}
|
||||
@@ -6401,6 +6416,19 @@ void ins_compl_enable_autocomplete(void)
|
||||
compl_get_longest = false;
|
||||
}
|
||||
|
||||
/// Remember that Vim is about to start a completion by itself, rather than
|
||||
/// because a key was typed to ask for one.
|
||||
void ins_compl_arm_autostart(void)
|
||||
{
|
||||
compl_autostart_pending = true;
|
||||
}
|
||||
|
||||
/// Forget what the automatic trigger armed, another key was typed since.
|
||||
void ins_compl_disarm_autostart(void)
|
||||
{
|
||||
compl_autostart_pending = false;
|
||||
}
|
||||
|
||||
/// Arm the 'autocompletedelay' timer when the delay is in effect.
|
||||
/// Return true when the popup should be deferred, false to trigger it now.
|
||||
bool ins_compl_arm_autocomplete_delay(void)
|
||||
|
||||
@@ -6851,6 +6851,45 @@ func Test_complete_info_hlgroup()
|
||||
bwipe!
|
||||
endfunc
|
||||
|
||||
" Test that complete_info() tells a completion Vim started by itself from one
|
||||
" that a key asked for.
|
||||
func Test_complete_info_auto()
|
||||
call Ntest_override("char_avail", 1)
|
||||
new
|
||||
func! AutoOmni(findstart, base)
|
||||
if a:findstart
|
||||
call add(g:auto, complete_info(['auto']).auto)
|
||||
return col('.') - 1
|
||||
endif
|
||||
return ['alpha', 'alphabet']
|
||||
endfunc
|
||||
setlocal omnifunc=AutoOmni
|
||||
setlocal complete=o
|
||||
setlocal completeopt=menuone
|
||||
call setline(1, ' al')
|
||||
|
||||
" 'autocomplete' starts it, nothing was asked for.
|
||||
setlocal autocomplete
|
||||
let g:auto = []
|
||||
call feedkeys("A\<Esc>", 'tx')
|
||||
call assert_equal([1], g:auto)
|
||||
|
||||
" The second call is the one CTRL-X CTRL-O asked for.
|
||||
let g:auto = []
|
||||
call feedkeys("A\<C-X>\<C-O>\<Esc>", 'tx')
|
||||
call assert_equal([1, 0], g:auto)
|
||||
|
||||
setlocal noautocomplete
|
||||
let g:auto = []
|
||||
call feedkeys("A\<C-X>\<C-O>\<Esc>", 'tx')
|
||||
call assert_equal([0], g:auto)
|
||||
|
||||
call Ntest_override("ALL", 0)
|
||||
unlet g:auto
|
||||
delfunc AutoOmni
|
||||
bwipe!
|
||||
endfunc
|
||||
|
||||
func Test_complete_fuzzy_resort()
|
||||
new
|
||||
set completeopt=menu,menuone,noselect,fuzzy
|
||||
|
||||
Reference in New Issue
Block a user