summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYegappan Lakshmanan <yegappan@yahoo.com>2022-01-03 11:03:48 +0000
committerBram Moolenaar <Bram@vim.org>2022-01-03 11:03:48 +0000
commite982586f8eebf2b055987218f6d3f7a084c4bf69 (patch)
tree99e63f241c4e8f329eca27a710dfbf335c965d97
parent475d9521baaeb060ebb915d678094ff28e67b5be (diff)
patch 8.2.3989: some insert completion code is not testedv8.2.3989
Problem: Some insert completion code is not tested. Solution: Add a few tests. Refactor thesaurus completion. (Yegappan Lakshmanan, closes #9460)
-rw-r--r--src/insexpand.c129
-rw-r--r--src/testdir/test_edit.vim26
-rw-r--r--src/testdir/test_ins_complete.vim100
-rw-r--r--src/version.c2
4 files changed, 210 insertions, 47 deletions
diff --git a/src/insexpand.c b/src/insexpand.c
index 926b3517fe..0d5a6e5687 100644
--- a/src/insexpand.c
+++ b/src/insexpand.c
@@ -1017,6 +1017,10 @@ ins_compl_dict_alloc(compl_T *match)
return dict;
}
+/*
+ * Trigger the CompleteChanged autocmd event. Invoked each time the Insert mode
+ * completion menu is changed.
+ */
static void
trigger_complete_changed_event(int cur)
{
@@ -1219,8 +1223,8 @@ ins_compl_show_pum(void)
#define DICT_EXACT (2) // "dict" is the exact name of a file
/*
- * Add any identifiers that match the given pattern in the list of dictionary
- * files "dict_start" to the list of completions.
+ * Add any identifiers that match the given pattern "pat" in the list of
+ * dictionary files "dict_start" to the list of completions.
*/
static void
ins_compl_dictionaries(
@@ -1346,6 +1350,66 @@ theend:
vim_free(buf);
}
+/*
+ * Add all the words in the line "*buf_arg" from the thesaurus file "fname"
+ * skipping the word at 'skip_word'. Returns OK on success.
+ */
+ static int
+thesarurs_add_words_in_line(
+ char_u *fname,
+ char_u **buf_arg,
+ int dir,
+ char_u *skip_word)
+{
+ int status = OK;
+ char_u *ptr;
+ char_u *wstart;
+
+ // Add the other matches on the line
+ ptr = *buf_arg;
+ while (!got_int)
+ {
+ // Find start of the next word. Skip white
+ // space and punctuation.
+ ptr = find_word_start(ptr);
+ if (*ptr == NUL || *ptr == NL)
+ break;
+ wstart = ptr;
+
+ // Find end of the word.
+ if (has_mbyte)
+ // Japanese words may have characters in
+ // different classes, only separate words
+ // with single-byte non-word characters.
+ while (*ptr != NUL)
+ {
+ int l = (*mb_ptr2len)(ptr);
+
+ if (l < 2 && !vim_iswordc(*ptr))
+ break;
+ ptr += l;
+ }
+ else
+ ptr = find_word_end(ptr);
+
+ // Add the word. Skip the regexp match.
+ if (wstart != skip_word)
+ {
+ status = ins_compl_add_infercase(wstart, (int)(ptr - wstart), p_ic,
+ fname, dir, FALSE);
+ if (status == FAIL)
+ break;
+ }
+ }
+
+ *buf_arg = ptr;
+ return status;
+}
+
+/*
+ * Process "count" dictionary/thesaurus "files" and add the text matching
+ * "regmatch".
+ */
static void
ins_compl_files(
int count,
@@ -1392,41 +1456,10 @@ ins_compl_files(
p_ic, files[i], *dir, FALSE);
if (thesaurus)
{
- char_u *wstart;
-
- // Add the other matches on the line
+ // For a thesaurus, add all the words in the line
ptr = buf;
- while (!got_int)
- {
- // Find start of the next word. Skip white
- // space and punctuation.
- ptr = find_word_start(ptr);
- if (*ptr == NUL || *ptr == NL)
- break;
- wstart = ptr;
-
- // Find end of the word.
- if (has_mbyte)
- // Japanese words may have characters in
- // different classes, only separate words
- // with single-byte non-word characters.
- while (*ptr != NUL)
- {
- int l = (*mb_ptr2len)(ptr);
-
- if (l < 2 && !vim_iswordc(*ptr))
- break;
- ptr += l;
- }
- else
- ptr = find_word_end(ptr);
-
- // Add the word. Skip the regexp match.
- if (wstart != regmatch->startp[0])
- add_r = ins_compl_add_infercase(wstart,
- (int)(ptr - wstart),
- p_ic, files[i], *dir, FALSE);
- }
+ add_r = thesarurs_add_words_in_line(files[i], &ptr, *dir,
+ regmatch->startp[0]);
}
if (add_r == OK)
// if dir was BACKWARD then honor it just once
@@ -1649,15 +1682,14 @@ ins_compl_bs(void)
vim_free(compl_leader);
compl_leader = vim_strnsave(line + compl_col, (p - line) - compl_col);
- if (compl_leader != NULL)
- {
- ins_compl_new_leader();
- if (compl_shown_match != NULL)
- // Make sure current match is not a hidden item.
- compl_curr_match = compl_shown_match;
- return NUL;
- }
- return K_BS;
+ if (compl_leader == NULL)
+ return K_BS;
+
+ ins_compl_new_leader();
+ if (compl_shown_match != NULL)
+ // Make sure current match is not a hidden item.
+ compl_curr_match = compl_shown_match;
+ return NUL;
}
/*
@@ -2795,6 +2827,10 @@ ins_compl_mode(void)
return (char_u *)"";
}
+/*
+ * Assign the sequence number to all the completion matches which don't have
+ * one assigned yet.
+ */
static void
ins_compl_update_sequence_numbers()
{
@@ -4853,6 +4889,9 @@ ins_complete(int c, int enable_pum)
return OK;
}
+/*
+ * Remove (if needed) and show the popup menu
+ */
static void
show_pum(int prev_w_wrow, int prev_w_leftcol)
{
diff --git a/src/testdir/test_edit.vim b/src/testdir/test_edit.vim
index c39c8a0fb1..e83d67250c 100644
--- a/src/testdir/test_edit.vim
+++ b/src/testdir/test_edit.vim
@@ -733,8 +733,13 @@ func Test_edit_CTRL_N()
call feedkeys("Ii\<c-n>\<cr>\<esc>", "tnix")
call feedkeys("ILO\<c-n>\<cr>\<esc>", 'tnix')
call assert_equal(['INFER', 'loWER', 'infer', 'LOWER', '', ''], getline(1, '$'), e)
-
- set noignorecase noinfercase complete&
+ set noignorecase noinfercase
+ %d
+ call setline(1, ['one word', 'two word'])
+ exe "normal! Goo\<C-P>\<C-X>\<C-P>"
+ call assert_equal('one word', getline(3))
+ %d
+ set complete&
bw!
endfor
endfunc
@@ -900,6 +905,23 @@ func Test_edit_CTRL_T()
bw!
endfunc
+" Test thesaurus completion with different encodings
+func Test_thesaurus_complete_with_encoding()
+ call writefile(['angry furious mad enraged'], 'Xthesaurus')
+ set thesaurus=Xthesaurus
+ for e in ['latin1', 'utf-8']
+ exe 'set encoding=' .. e
+ new
+ call setline(1, 'mad')
+ call cursor(1, 1)
+ call feedkeys("A\<c-x>\<c-t>\<cr>\<esc>", 'tnix')
+ call assert_equal(['mad', ''], getline(1, '$'))
+ bw!
+ endfor
+ set thesaurus=
+ call delete('Xthesaurus')
+endfunc
+
" Test 'thesaurusfunc'
func MyThesaurus(findstart, base)
let mythesaurus = [
diff --git a/src/testdir/test_ins_complete.vim b/src/testdir/test_ins_complete.vim
index b0b97bbc22..86ad6098c9 100644
--- a/src/testdir/test_ins_complete.vim
+++ b/src/testdir/test_ins_complete.vim
@@ -709,6 +709,21 @@ func Test_complete_func_error()
call assert_equal([], complete_info(['items']).items)
endfunc
+" Test for recursively starting completion mode using complete()
+func Test_recursive_complete_func()
+ func ListColors()
+ call complete(5, ["red", "blue"])
+ return ''
+ endfunc
+ new
+ call setline(1, ['a1', 'a2'])
+ set complete=.
+ exe "normal Goa\<C-X>\<C-L>\<C-R>=ListColors()\<CR>\<C-N>"
+ call assert_equal('a2blue', getline(3))
+ delfunc ListColors
+ bw!
+endfunc
+
" Test for completing words following a completed word in a line
func Test_complete_wrapscan()
" complete words from another buffer
@@ -932,6 +947,91 @@ func Test_issue_7021()
set completeslash=
endfunc
+" Test for 'longest' setting in 'completeopt' with latin1 and utf-8 encodings
+func Test_complete_longest_match()
+ for e in ['latin1', 'utf-8']
+ exe 'set encoding=' .. e
+ new
+ set complete=.
+ set completeopt=menu,longest
+ call setline(1, ['pfx_a1', 'pfx_a12', 'pfx_a123', 'pfx_b1'])
+ exe "normal Gopfx\<C-P>"
+ call assert_equal('pfx_', getline(5))
+ bw!
+ endfor
+
+ " Test for completing additional words with longest match set
+ new
+ call setline(1, ['abc1', 'abd2'])
+ exe "normal Goab\<C-P>\<C-X>\<C-P>"
+ call assert_equal('ab', getline(3))
+ bw!
+ set complete& completeopt&
+endfunc
+
+" Test for removing the first displayed completion match and selecting the
+" match just before that.
+func Test_complete_erase_firstmatch()
+ new
+ call setline(1, ['a12', 'a34', 'a56'])
+ set complete=.
+ exe "normal Goa\<C-P>\<BS>\<BS>3\<CR>"
+ call assert_equal('a34', getline('$'))
+ set complete&
+ bw!
+endfunc
+
+" Test for completing whole lines from unloaded buffers
+func Test_complete_wholeline_unloadedbuf()
+ call writefile(['a line1', 'a line2', 'a line3'], "Xfile1")
+ edit Xfile1
+ enew
+ set complete=u
+ exe "normal! ia\<C-X>\<C-L>\<C-P>"
+ call assert_equal('a line2', getline(1))
+ %d
+ " completing from an unlisted buffer should fail
+ bdel Xfile1
+ exe "normal! ia\<C-X>\<C-L>\<C-P>"
+ call assert_equal('a', getline(1))
+ set complete&
+ %bw!
+ call delete("Xfile1")
+endfunc
+
+" Test for completing whole lines from unlisted buffers
+func Test_complete_wholeline_unlistedbuf()
+ call writefile(['a line1', 'a line2', 'a line3'], "Xfile1")
+ edit Xfile1
+ enew
+ set complete=U
+ " completing from a unloaded buffer should fail
+ exe "normal! ia\<C-X>\<C-L>\<C-P>"
+ call assert_equal('a', getline(1))
+ %d
+ bdel Xfile1
+ exe "normal! ia\<C-X>\<C-L>\<C-P>"
+ call assert_equal('a line2', getline(1))
+ set complete&
+ %bw!
+ call delete("Xfile1")
+endfunc
+
+" Test for adding a multibyte character using CTRL-L in completion mode
+func Test_complete_mbyte_char_add()
+ new
+ set complete=.
+ call setline(1, 'abė')
+ exe "normal! oa\<C-P>\<BS>\<BS>\<C-L>\<C-L>"
+ call assert_equal('abė', getline(2))
+ " Test for a leader with multibyte character
+ %d
+ call setline(1, 'abėĕ')
+ exe "normal! oabė\<C-P>"
+ call assert_equal('abėĕ', getline(2))
+ bw!
+endfunc
+
" Test to ensure 'Scanning...' messages are not recorded in messages history
func Test_z1_complete_no_history()
new
diff --git a/src/version.c b/src/version.c
index 21e11dc048..6cff7cc5fa 100644
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 3989,
+/**/
3988,
/**/
3987,