patch 9.1.1471: completion: inconsistent ordering with CTRL-P
Problem: completion: inconsistent ordering with CTRL-P
(zeertzjq)
Solution: reset compl_curr_match when using CTRL-P (Girish Palya)
fixes: #17425
closes: #17434
Signed-off-by: Girish Palya <girishji@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
diff --git a/src/edit.c b/src/edit.c
index 9cc55ef..97e4224 100644
--- a/src/edit.c
+++ b/src/edit.c
@@ -693,7 +693,7 @@
&& stop_arrow() == OK)
{
ins_compl_delete();
- ins_compl_insert(FALSE, FALSE);
+ ins_compl_insert(FALSE);
}
// Delete preinserted text when typing special chars
else if (IS_WHITE_NL_OR_NUL(c) && ins_compl_preinsert_effect())
diff --git a/src/insexpand.c b/src/insexpand.c
index 2d39887..94eb760 100644
--- a/src/insexpand.c
+++ b/src/insexpand.c
@@ -2378,7 +2378,7 @@
if (compl_match_array == NULL)
compl_enter_selects = FALSE;
else if (ins_compl_has_preinsert() && compl_leader.length > 0)
- ins_compl_insert(FALSE, TRUE);
+ ins_compl_insert(TRUE);
}
/*
@@ -5235,6 +5235,12 @@
compl_started = FALSE;
}
+
+ // For `^P` completion, reset `compl_curr_match` to the head to avoid
+ // mixing matches from different sources.
+ if (!compl_dir_forward())
+ while (compl_curr_match->cp_prev)
+ compl_curr_match = compl_curr_match->cp_prev;
}
cpt_sources_index = -1;
compl_started = TRUE;
@@ -5404,12 +5410,11 @@
/*
* Insert the new text being completed.
- * "in_compl_func" is TRUE when called from complete_check().
* "move_cursor" is used when 'completeopt' includes "preinsert" and when TRUE
* cursor needs to move back from the inserted text to the compl_leader.
*/
void
-ins_compl_insert(int in_compl_func, int move_cursor)
+ins_compl_insert(int move_cursor)
{
int compl_len = get_compl_len();
int preinsert = ins_compl_has_preinsert();
@@ -5442,8 +5447,6 @@
set_vim_var_dict(VV_COMPLETED_ITEM, dict);
}
#endif
- if (!in_compl_func)
- compl_curr_match = compl_shown_match;
}
/*
@@ -5638,8 +5641,7 @@
int allow_get_expansion,
int count, // repeat completion this many times; should
// be at least 1
- int insert_match, // Insert the newly selected match
- int in_compl_func) // called from complete_check()
+ int insert_match) // Insert the newly selected match
{
int num_matches = -1;
int todo = count;
@@ -5700,7 +5702,7 @@
else if (insert_match)
{
if (!compl_get_longest || compl_used_match)
- ins_compl_insert(in_compl_func, TRUE);
+ ins_compl_insert(TRUE);
else
ins_compl_insert_bytes(compl_leader.string + get_compl_len(), -1);
}
@@ -5786,7 +5788,7 @@
c = safe_vgetc(); // Eat the character
compl_shows_dir = ins_compl_key2dir(c);
(void)ins_compl_next(FALSE, ins_compl_key2count(c),
- c != K_UP && c != K_DOWN, in_compl_func);
+ c != K_UP && c != K_DOWN);
}
else
{
@@ -5809,7 +5811,7 @@
int todo = compl_pending > 0 ? compl_pending : -compl_pending;
compl_pending = 0;
- (void)ins_compl_next(FALSE, todo, TRUE, in_compl_func);
+ (void)ins_compl_next(FALSE, todo, TRUE);
}
}
@@ -6656,7 +6658,7 @@
// Find next match (and following matches).
save_w_wrow = curwin->w_wrow;
save_w_leftcol = curwin->w_leftcol;
- n = ins_compl_next(TRUE, ins_compl_key2count(c), insert_match, FALSE);
+ n = ins_compl_next(TRUE, ins_compl_key2count(c), insert_match);
// may undisplay the popup menu
ins_compl_upd_pum();
diff --git a/src/proto/insexpand.pro b/src/proto/insexpand.pro
index 8965aca..0564008 100644
--- a/src/proto/insexpand.pro
+++ b/src/proto/insexpand.pro
@@ -63,7 +63,7 @@
void f_complete_check(typval_T *argvars, typval_T *rettv);
void f_complete_info(typval_T *argvars, typval_T *rettv);
void ins_compl_delete(void);
-void ins_compl_insert(int in_compl_func, int move_cursor);
+void ins_compl_insert(int move_cursor);
void ins_compl_check_keys(int frequency, int in_compl_func);
int ins_complete(int c, int enable_pum);
void free_insexpand_stuff(void);
diff --git a/src/testdir/test_ins_complete.vim b/src/testdir/test_ins_complete.vim
index 155c5b7..df59e1e 100644
--- a/src/testdir/test_ins_complete.vim
+++ b/src/testdir/test_ins_complete.vim
@@ -4754,6 +4754,73 @@
delfunc TestComplete
endfunc
+" Verify that the order of matches from each source is consistent
+" during both ^N and ^P completions (Issue #17425).
+func Test_complete_with_multiple_function_sources()
+ func F1(findstart, base)
+ if a:findstart
+ return col('.') - 1
+ endif
+ return ['one', 'two', 'three']
+ endfunc
+
+ func F2(findstart, base)
+ if a:findstart
+ return col('.') - 1
+ endif
+ return ['four', 'five', 'six']
+ endfunc
+
+ func F3(findstart, base)
+ if a:findstart
+ return col('.') - 1
+ endif
+ return ['seven', 'eight', 'nine']
+ endfunc
+
+ new
+ setlocal complete=.,FF1,FF2,FF3
+ inoremap <buffer> <F2> <Cmd>let b:matches = complete_info(["matches"]).matches<CR>
+ call setline(1, ['xxx', 'yyy', 'zzz', ''])
+
+ call feedkeys("GS\<C-N>\<F2>\<Esc>0", 'tx!')
+ call assert_equal([
+ \ 'xxx', 'yyy', 'zzz',
+ \ 'one', 'two', 'three',
+ \ 'four', 'five', 'six',
+ \ 'seven', 'eight', 'nine',
+ \ ], b:matches->mapnew('v:val.word'))
+
+ call feedkeys("GS\<C-P>\<F2>\<Esc>0", 'tx!')
+ call assert_equal([
+ \ 'seven', 'eight', 'nine',
+ \ 'four', 'five', 'six',
+ \ 'one', 'two', 'three',
+ \ 'xxx', 'yyy', 'zzz',
+ \ ], b:matches->mapnew('v:val.word'))
+
+ %delete
+
+ call feedkeys("GS\<C-N>\<F2>\<Esc>0", 'tx!')
+ call assert_equal([
+ \ 'one', 'two', 'three',
+ \ 'four', 'five', 'six',
+ \ 'seven', 'eight', 'nine',
+ \ ], b:matches->mapnew('v:val.word'))
+
+ call feedkeys("GS\<C-P>\<F2>\<Esc>0", 'tx!')
+ call assert_equal([
+ \ 'seven', 'eight', 'nine',
+ \ 'four', 'five', 'six',
+ \ 'one', 'two', 'three',
+ \ ], b:matches->mapnew('v:val.word'))
+
+ bwipe!
+ delfunc F1
+ delfunc F2
+ delfunc F3
+endfunc
+
func Test_complete_fuzzy_omnifunc_backspace()
let g:do_complete = v:false
func Omni_test(findstart, base)
diff --git a/src/version.c b/src/version.c
index 05e85ad..52fdfc3 100644
--- a/src/version.c
+++ b/src/version.c
@@ -710,6 +710,8 @@
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1471,
+/**/
1470,
/**/
1469,