aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/edit.c48
-rw-r--r--src/nvim/eval.c2
-rw-r--r--src/nvim/search.c2
-rw-r--r--src/nvim/spell.c2
-rw-r--r--src/nvim/tag.c2
-rw-r--r--src/nvim/testdir/test_popup.vim113
-rw-r--r--test/functional/legacy/076_completefunc_spec.lua68
7 files changed, 143 insertions, 94 deletions
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index 24744f1437..dcb772e23c 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -669,7 +669,7 @@ static int insert_execute(VimState *state, int key)
&& (s->c == CAR || s->c == K_KENTER || s->c == NL)))
&& stop_arrow() == OK) {
ins_compl_delete();
- ins_compl_insert();
+ ins_compl_insert(false);
}
}
}
@@ -2775,7 +2775,7 @@ static void ins_compl_files(int count, char_u **files, int thesaurus, int flags,
break;
}
line_breakcheck();
- ins_compl_check_keys(50);
+ ins_compl_check_keys(50, false);
}
fclose(fp);
}
@@ -3907,7 +3907,7 @@ static int ins_compl_get_exp(pos_T *ini)
break;
/* Fill the popup menu as soon as possible. */
if (type != -1)
- ins_compl_check_keys(0);
+ ins_compl_check_keys(0, false);
if ((l_ctrl_x_mode != 0 && !CTRL_X_MODE_LINE_OR_EVAL(l_ctrl_x_mode))
|| compl_interrupted) {
@@ -3969,8 +3969,9 @@ static void ins_compl_delete(void)
set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc());
}
-/* Insert the new text being completed. */
-static void ins_compl_insert(void)
+// Insert the new text being completed.
+// "in_compl_func" is TRUE when called from complete_check().
+static void ins_compl_insert(int in_compl_func)
{
ins_bytes(compl_shown_match->cp_str + ins_compl_len());
if (compl_shown_match->cp_flags & ORIGINAL_TEXT)
@@ -3992,7 +3993,9 @@ static void ins_compl_insert(void)
dict_add_nr_str(dict, "info", 0L,
EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_INFO]));
set_vim_var_dict(VV_COMPLETED_ITEM, dict);
- compl_curr_match = compl_shown_match;
+ if (!in_compl_func) {
+ compl_curr_match = compl_shown_match;
+ }
}
/*
@@ -4014,9 +4017,10 @@ static void ins_compl_insert(void)
static int
ins_compl_next (
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 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 num_matches = -1;
@@ -4146,7 +4150,7 @@ ins_compl_next (
compl_used_match = FALSE;
} else if (insert_match) {
if (!compl_get_longest || compl_used_match) {
- ins_compl_insert();
+ ins_compl_insert(in_compl_func);
} else {
ins_bytes(compl_leader + ins_compl_len());
}
@@ -4196,14 +4200,14 @@ ins_compl_next (
return num_matches;
}
-/*
- * Call this while finding completions, to check whether the user has hit a key
- * that should change the currently displayed completion, or exit completion
- * mode. Also, when compl_pending is not zero, show a completion as soon as
- * possible. -- webb
- * "frequency" specifies out of how many calls we actually check.
- */
-void ins_compl_check_keys(int frequency)
+// Call this while finding completions, to check whether the user has hit a key
+// that should change the currently displayed completion, or exit completion
+// mode. Also, when compl_pending is not zero, show a completion as soon as
+// possible. -- webb
+// "frequency" specifies out of how many calls we actually check.
+// "in_compl_func" is TRUE when called from complete_check(), don't set
+// compl_curr_match.
+void ins_compl_check_keys(int frequency, int in_compl_func)
{
static int count = 0;
@@ -4226,8 +4230,8 @@ void ins_compl_check_keys(int frequency)
if (vim_is_ctrl_x_key(c) && c != Ctrl_X && c != Ctrl_R) {
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);
+ (void)ins_compl_next(false, ins_compl_key2count(c),
+ c != K_UP && c != K_DOWN, in_compl_func);
} else {
/* Need to get the character to have KeyTyped set. We'll put it
* back with vungetc() below. But skip K_IGNORE. */
@@ -4246,7 +4250,7 @@ void ins_compl_check_keys(int frequency)
int todo = compl_pending > 0 ? compl_pending : -compl_pending;
compl_pending = 0;
- (void)ins_compl_next(FALSE, todo, TRUE);
+ (void)ins_compl_next(false, todo, true, in_compl_func);
}
}
@@ -4673,7 +4677,7 @@ static int ins_complete(int c, bool enable_pum)
* Find next match (and following matches).
*/
save_w_wrow = curwin->w_wrow;
- n = ins_compl_next(true, ins_compl_key2count(c), insert_match);
+ n = ins_compl_next(true, ins_compl_key2count(c), insert_match, false);
/* may undisplay the popup menu */
ins_compl_upd_pum();
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index b8173c7570..39df4cd024 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -8010,7 +8010,7 @@ static void f_complete_check(typval_T *argvars, typval_T *rettv, FunPtr fptr)
int saved = RedrawingDisabled;
RedrawingDisabled = 0;
- ins_compl_check_keys(0);
+ ins_compl_check_keys(0, true);
rettv->vval.v_number = compl_interrupted;
RedrawingDisabled = saved;
}
diff --git a/src/nvim/search.c b/src/nvim/search.c
index 5f4df3be92..1029190db4 100644
--- a/src/nvim/search.c
+++ b/src/nvim/search.c
@@ -4549,7 +4549,7 @@ exit_matched:
}
line_breakcheck();
if (action == ACTION_EXPAND)
- ins_compl_check_keys(30);
+ ins_compl_check_keys(30, false);
if (got_int || compl_interrupted)
break;
diff --git a/src/nvim/spell.c b/src/nvim/spell.c
index d9cdce8ca4..7119ac6dc1 100644
--- a/src/nvim/spell.c
+++ b/src/nvim/spell.c
@@ -13160,7 +13160,7 @@ spell_dump_compl (
// Done all bytes at this node, go up one level.
--depth;
line_breakcheck();
- ins_compl_check_keys(50);
+ ins_compl_check_keys(50, false);
} else {
// Do one more byte at this node.
n = arridx[depth] + curi[depth];
diff --git a/src/nvim/tag.c b/src/nvim/tag.c
index 81256b4f01..46fad688cc 100644
--- a/src/nvim/tag.c
+++ b/src/nvim/tag.c
@@ -1295,7 +1295,7 @@ find_tags (
for (;; ) {
line_breakcheck(); /* check for CTRL-C typed */
if ((flags & TAG_INS_COMP)) /* Double brackets for gcc */
- ins_compl_check_keys(30);
+ ins_compl_check_keys(30, false);
if (got_int || compl_interrupted) {
stop_searching = TRUE;
break;
diff --git a/src/nvim/testdir/test_popup.vim b/src/nvim/testdir/test_popup.vim
index 63be8bf609..8615e32cfd 100644
--- a/src/nvim/testdir/test_popup.vim
+++ b/src/nvim/testdir/test_popup.vim
@@ -63,3 +63,116 @@ func! Test_popup_completion_insertmode()
bwipe!
iunmap <F5>
endfunc
+
+func DummyCompleteOne(findstart, base)
+ if a:findstart
+ return 0
+ else
+ wincmd n
+ return ['onedef', 'oneDEF']
+ endif
+endfunc
+
+" Test that nothing happens if the 'completefunc' opens
+" a new window (no completion, no crash)
+func Test_completefunc_opens_new_window_one()
+ new
+ let winid = win_getid()
+ setlocal completefunc=DummyCompleteOne
+ call setline(1, 'one')
+ /^one
+ call assert_fails('call feedkeys("A\<C-X>\<C-U>\<C-N>\<Esc>", "x")', 'E839:')
+ call assert_notequal(winid, win_getid())
+ q!
+ call assert_equal(winid, win_getid())
+ call assert_equal('', getline(1))
+ q!
+endfunc
+
+" Test that nothing happens if the 'completefunc' opens
+" a new window (no completion, no crash)
+func DummyCompleteTwo(findstart, base)
+ if a:findstart
+ wincmd n
+ return 0
+ else
+ return ['twodef', 'twoDEF']
+ endif
+endfunction
+
+" Test that nothing happens if the 'completefunc' opens
+" a new window (no completion, no crash)
+func Test_completefunc_opens_new_window_two()
+ new
+ let winid = win_getid()
+ setlocal completefunc=DummyCompleteTwo
+ call setline(1, 'two')
+ /^two
+ call assert_fails('call feedkeys("A\<C-X>\<C-U>\<C-N>\<Esc>", "x")', 'E764:')
+ call assert_notequal(winid, win_getid())
+ q!
+ call assert_equal(winid, win_getid())
+ call assert_equal('two', getline(1))
+ q!
+endfunc
+
+func DummyCompleteThree(findstart, base)
+ if a:findstart
+ return 0
+ else
+ return ['threedef', 'threeDEF']
+ endif
+endfunc
+
+:"Test that 'completefunc' works when it's OK.
+func Test_completefunc_works()
+ new
+ let winid = win_getid()
+ setlocal completefunc=DummyCompleteThree
+ call setline(1, 'three')
+ /^three
+ call feedkeys("A\<C-X>\<C-U>\<C-N>\<Esc>", "x")
+ call assert_equal(winid, win_getid())
+ call assert_equal('threeDEF', getline(1))
+ q!
+endfunc
+
+func DummyCompleteFour(findstart, base)
+ if a:findstart
+ return 0
+ else
+ call complete_add('four1')
+ call complete_add('four2')
+ call complete_check()
+ call complete_add('four3')
+ call complete_add('four4')
+ call complete_check()
+ call complete_add('four5')
+ call complete_add('four6')
+ return []
+ endif
+endfunc
+
+:"Test that 'completefunc' works when it's OK.
+func Test_omnifunc_with_check()
+ new
+ setlocal omnifunc=DummyCompleteFour
+ call setline(1, 'four')
+ /^four
+ call feedkeys("A\<C-X>\<C-O>\<C-N>\<Esc>", "x")
+ call assert_equal('four2', getline(1))
+
+ call setline(1, 'four')
+ /^four
+ call feedkeys("A\<C-X>\<C-O>\<C-N>\<C-N>\<Esc>", "x")
+ call assert_equal('four3', getline(1))
+
+ call setline(1, 'four')
+ /^four
+ call feedkeys("A\<C-X>\<C-O>\<C-N>\<C-N>\<C-N>\<C-N>\<Esc>", "x")
+ call assert_equal('four5', getline(1))
+
+ q!
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/test/functional/legacy/076_completefunc_spec.lua b/test/functional/legacy/076_completefunc_spec.lua
deleted file mode 100644
index bf3f56eb84..0000000000
--- a/test/functional/legacy/076_completefunc_spec.lua
+++ /dev/null
@@ -1,68 +0,0 @@
--- Tests for completefunc/omnifunc.
-
-local helpers = require('test.functional.helpers')(after_each)
-local feed, insert, source = helpers.feed, helpers.insert, helpers.source
-local clear, expect, execute = helpers.clear, helpers.expect, helpers.execute
-
-describe('completefunc', function()
- setup(clear)
-
- it('is working', function()
- insert([=[
- +++
- one
- two
- three]=])
-
- -- Test that nothing happens if the 'completefunc' opens
- -- a new window (no completion, no crash).
- source([=[
- function! DummyCompleteOne(findstart, base)
- if a:findstart
- return 0
- else
- wincmd n
- return ['onedef', 'oneDEF']
- endif
- endfunction
- setlocal completefunc=DummyCompleteOne
- /^one
- ]=])
- feed('A<C-X><C-U><C-N><esc>')
- execute('q!')
- source([=[
- function! DummyCompleteTwo(findstart, base)
- if a:findstart
- wincmd n
- return 0
- else
- return ['twodef', 'twoDEF']
- endif
- endfunction
- setlocal completefunc=DummyCompleteTwo
- /^two
- ]=])
- feed('A<C-X><C-U><C-N><esc>')
- execute('q!')
- -- Test that 'completefunc' works when it's OK.
- source([=[
- function! DummyCompleteThree(findstart, base)
- if a:findstart
- return 0
- else
- return ['threedef', 'threeDEF']
- endif
- endfunction
- setlocal completefunc=DummyCompleteThree
- /^three
- ]=])
- feed('A<C-X><C-U><C-N><esc>')
-
- -- Assert buffer contents.
- expect([=[
- +++
-
- two
- threeDEF]=])
- end)
-end)