From aa7cba995dc0ba55de8886d12f1a7f37715bea6e Mon Sep 17 00:00:00 2001 From: glepnir Date: Tue, 14 Apr 2026 14:30:16 +0800 Subject: [PATCH] fix(completion): preselect ignores completeopt flag #39030 Problem: compl_preselect_match is set even when completeopt doesn't include preselect. Solution: Check kOptCotFlagPreselect in ins_compl_add before setting compl_preselect_match. --- src/nvim/insexpand.c | 10 ++++++++-- test/functional/editor/completion_spec.lua | 6 ++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/nvim/insexpand.c b/src/nvim/insexpand.c index 83af30d6e4..17d7c9e4be 100644 --- a/src/nvim/insexpand.c +++ b/src/nvim/insexpand.c @@ -971,7 +971,8 @@ static int ins_compl_add(char *const str, int len, char *const fname, char *cons match->cp_number = flags & CP_ORIGINAL_TEXT ? 0 : -1; match->cp_str = cbuf_to_string(str, (size_t)len); match->cp_preselect = preselect; - if (preselect && compl_preselect_match == NULL) { + if (preselect && compl_preselect_match == NULL + && (get_cot_flags() & kOptCotFlagPreselect)) { compl_preselect_match = match; } @@ -3452,7 +3453,7 @@ static void set_completion(colnr_T startcol, list_T *list) compl_curr_match = compl_first_match; bool no_select = compl_no_select || compl_longest; - if ((get_cot_flags() & kOptCotFlagPreselect) && compl_preselect_match && !no_select) { + if (compl_preselect_match && !no_select) { compl_curr_match = compl_preselect_match->cp_prev; ins_complete(Ctrl_N, false); } else if (compl_no_insert || no_select) { @@ -6511,6 +6512,11 @@ static void remove_old_matches(void) shown_match_removed = true; } + // Avoid dangling pointer when preselect match is removed. + if (to_delete == compl_preselect_match) { + compl_preselect_match = NULL; + } + current = current->cp_next; if (to_delete == compl_first_match) { // node to remove is at head diff --git a/test/functional/editor/completion_spec.lua b/test/functional/editor/completion_spec.lua index d873ec67cf..acadf16c9b 100644 --- a/test/functional/editor/completion_spec.lua +++ b/test/functional/editor/completion_spec.lua @@ -328,6 +328,12 @@ describe('completion', function() {1:~ }|*2 {5:-- INSERT --} | ]]) + + -- without "preselect" in completeopt, preselect attribute is ignored + feed('S') + command('set completeopt-=preselect') + feed('=TestComplete()') + eq('aaa', api.nvim_get_current_line()) end) end) end)