diff options
-rw-r--r-- | src/nvim/insexpand.c | 11 | ||||
-rw-r--r-- | src/nvim/popupmenu.h | 1 | ||||
-rw-r--r-- | test/old/testdir/test_ins_complete.vim | 20 |
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 |