aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/insexpand.c11
-rw-r--r--src/nvim/popupmenu.h1
-rw-r--r--test/old/testdir/test_ins_complete.vim20
3 files changed, 29 insertions, 3 deletions
diff --git a/src/nvim/insexpand.c b/src/nvim/insexpand.c
index 711e2292b1..139637b8a1 100644
--- a/src/nvim/insexpand.c
+++ b/src/nvim/insexpand.c
@@ -1144,11 +1144,13 @@ static void trigger_complete_changed_event(int cur)
}
/// pumitem qsort compare func
-static int ins_compl_fuzzy_sort(const void *a, const void *b)
+static int ins_compl_fuzzy_cmp(const void *a, const void *b)
{
const int sa = (*(pumitem_T *)a).pum_score;
const int sb = (*(pumitem_T *)b).pum_score;
- return sa == sb ? 0 : sa < sb ? 1 : -1;
+ const int ia = (*(pumitem_T *)a).pum_idx;
+ const int ib = (*(pumitem_T *)b).pum_idx;
+ return sa == sb ? (ia == ib ? 0 : (ia < ib ? -1 : 1)) : (sa < sb ? 1 : -1);
}
/// Build a popup menu to show the completion matches.
@@ -1284,9 +1286,12 @@ static int ins_compl_build_pum(void)
} while (comp != NULL && !is_first_match(comp));
if (compl_fuzzy_match && compl_leader != NULL && lead_len > 0) {
+ for (i = 0; i < compl_match_arraysize; i++) {
+ compl_match_array[i].pum_idx = i;
+ }
// sort by the largest score of fuzzy match
qsort(compl_match_array, (size_t)compl_match_arraysize, sizeof(pumitem_T),
- ins_compl_fuzzy_sort);
+ ins_compl_fuzzy_cmp);
}
if (!shown_match_ok) { // no displayed match at all
diff --git a/src/nvim/popupmenu.h b/src/nvim/popupmenu.h
index 9e3f8f5a7f..bcf2a14290 100644
--- a/src/nvim/popupmenu.h
+++ b/src/nvim/popupmenu.h
@@ -15,6 +15,7 @@ typedef struct {
char *pum_extra; ///< extra menu text (may be truncated)
char *pum_info; ///< extra info
int pum_score; ///< fuzzy match score
+ int pum_idx; ///< index of item before sorting by score
} pumitem_T;
EXTERN ScreenGrid pum_grid INIT( = SCREEN_GRID_INIT);
diff --git a/test/old/testdir/test_ins_complete.vim b/test/old/testdir/test_ins_complete.vim
index fd77da67f8..ac08da9743 100644
--- a/test/old/testdir/test_ins_complete.vim
+++ b/test/old/testdir/test_ins_complete.vim
@@ -2639,4 +2639,24 @@ func Test_complete_fuzzy_match()
unlet g:word
endfunc
+" Check that tie breaking is stable for completeopt+=fuzzy (which should
+" behave the same on different platforms).
+func Test_complete_fuzzy_match_tie()
+ new
+ set completeopt+=fuzzy,noselect
+ call setline(1, ['aaabbccc', 'aaabbCCC', 'aaabbcccc', 'aaabbCCCC', ''])
+
+ call feedkeys("Gcc\<C-X>\<C-N>ab\<C-N>\<C-Y>", 'tx')
+ call assert_equal('aaabbccc', getline('.'))
+ call feedkeys("Gcc\<C-X>\<C-N>ab\<C-N>\<C-N>\<C-Y>", 'tx')
+ call assert_equal('aaabbCCC', getline('.'))
+ call feedkeys("Gcc\<C-X>\<C-N>ab\<C-N>\<C-N>\<C-N>\<C-Y>", 'tx')
+ call assert_equal('aaabbcccc', getline('.'))
+ call feedkeys("Gcc\<C-X>\<C-N>ab\<C-N>\<C-N>\<C-N>\<C-N>\<C-Y>", 'tx')
+ call assert_equal('aaabbCCCC', getline('.'))
+
+ bwipe!
+ set completeopt&
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab nofoldenable