neovim

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

commit 525c02a89f96a3371b7d5ca711f6971fbbc11585
parent 9bfd0162dc11478febbdfd0fd9c9c880a0f454ae
Author: zeertzjq <zeertzjq@outlook.com>
Date:   Mon,  2 Jun 2025 14:41:02 +0800

vim-patch:9.1.1424: PMenu selection broken with multi-line selection and limits

Problem:  PMenu selection broken with multi-line selection and limits
          (Maxim Kim)
Solution: update completion match index when limiting the completion
          sources (Girish Palya)

fixes: vim/vim#17394
closes: vim/vim#17401

https://github.com/vim/vim/commit/6c40df09e07dced75010be2d7a8e4831f6b9f796

Co-authored-by: Girish Palya <girishji@gmail.com>

Diffstat:
Msrc/nvim/insexpand.c | 13++++++++++---
Mtest/old/testdir/test_ins_complete.vim | 28+++++++++++++++++++++++++++-
2 files changed, 37 insertions(+), 4 deletions(-)

diff --git a/src/nvim/insexpand.c b/src/nvim/insexpand.c @@ -1369,8 +1369,12 @@ static void trigger_complete_changed_event(int cur) /// becomes inconsistent with compl_first_match (list) after former is sorted by /// fuzzy score. The two structures end up in different orders. /// Ideally, compl_first_match list should have been sorted instead. -static void trim_compl_match_array(void) +/// +/// Returns recalculated index of shown match. +static int trim_compl_match_array(int shown_match_idx) { + int remove_count = 0; + // Count current matches per source. int *match_counts = xcalloc((size_t)cpt_sources_count, sizeof(int)); for (int i = 0; i < compl_match_arraysize; i++) { @@ -1402,6 +1406,8 @@ static void trim_compl_match_array(void) if (limit <= 0 || match_counts[src_idx] < limit) { trimmed[trimmed_idx++] = compl_match_array[i]; match_counts[src_idx]++; + } else if (i < shown_match_idx) { + remove_count++; } } else { trimmed[trimmed_idx++] = compl_match_array[i]; @@ -1413,6 +1419,7 @@ static void trim_compl_match_array(void) theend: xfree(match_counts); + return shown_match_idx - remove_count; } /// pumitem qsort compare func @@ -1607,8 +1614,8 @@ static int ins_compl_build_pum(void) shown_match_ok = true; } - if (is_forward && fuzzy_sort && cpt_sources_array != NULL) { - trim_compl_match_array(); // Truncate by max_matches in 'cpt' + if (fuzzy_sort && cpt_sources_array != NULL) { + cur = trim_compl_match_array(cur); // Truncate by max_matches in 'cpt' } if (!shown_match_ok) { // no displayed match at all cur = -1; diff --git a/test/old/testdir/test_ins_complete.vim b/test/old/testdir/test_ins_complete.vim @@ -4319,7 +4319,33 @@ func Test_complete_match_count() call assert_equal('abac', getline(4)) bw! - set completeopt& complete& + " Items with '\n' that cause menu to shift, with no leader (issue #17394) + func! ComplFunc(findstart, base) + if a:findstart == 1 + return col('.') - 1 + endif + return ["one\ntwo\nthree", "four five six", "hello\nworld\nhere"] + endfunc + set completeopt=menuone,popup,noselect,fuzzy infercase + set complete=.^1,FComplFunc^5 + new + call setline(1, ["foo", "bar", "baz"]) + execute "normal Go\<c-n>\<c-n>\<c-n>" + call assert_equal(['one', 'two', 'three'], getline(4, 6)) + %d + call setline(1, ["foo", "bar", "baz"]) + execute "normal Go\<c-n>\<c-n>\<c-n>\<c-p>" + call assert_equal('foo', getline(4)) + execute "normal S\<c-n>\<c-n>\<c-n>\<c-n>\<c-n>\<c-n>\<c-n>" + call assert_equal('foo', getline(4)) + set complete=.^1,FComplFunc^2 + execute "normal S\<c-n>\<c-n>\<c-n>\<c-n>\<c-n>\<c-n>" + call assert_equal('foo', getline(4)) + execute "normal S\<c-n>\<c-p>\<c-p>\<c-p>\<c-n>\<c-n>" + call assert_equal('four five six', getline(4)) + bw! + + set completeopt& complete& infercase& delfunc PrintMenuWords delfunc ComplFunc delfunc CompleteItemsSelect