aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin M. Keyes <justinkz@gmail.com>2020-01-18 16:12:16 -0800
committerGitHub <noreply@github.com>2020-01-18 16:12:16 -0800
commitfb8b0503baf95ccd9ab4a30220dd08ca8b16736b (patch)
tree8106670804b58724a15c64da4473b78393528601
parentfd89ad7bfb1534c42c99b36ca025ea42ccbee7e1 (diff)
parentad35cbca76222deb33357b63a61a29945ef084f7 (diff)
downloadrneovim-fb8b0503baf95ccd9ab4a30220dd08ca8b16736b.tar.gz
rneovim-fb8b0503baf95ccd9ab4a30220dd08ca8b16736b.tar.bz2
rneovim-fb8b0503baf95ccd9ab4a30220dd08ca8b16736b.zip
Merge #11707 from janlazo/vim-8.1.1434
vim-patch:8.1.{716,1139},8.2.{112,120,123}
-rw-r--r--runtime/doc/autocmd.txt2
-rw-r--r--src/nvim/edit.c20
-rw-r--r--src/nvim/eval.c11
-rw-r--r--src/nvim/indent_c.c3
-rw-r--r--src/nvim/ops.c2
-rw-r--r--src/nvim/spell.c246
-rw-r--r--src/nvim/testdir/test_cindent.vim9
-rw-r--r--src/nvim/testdir/test_ins_complete.vim66
-rw-r--r--src/nvim/testdir/test_marks.vim21
9 files changed, 112 insertions, 268 deletions
diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt
index 45bead968d..774e6a5d92 100644
--- a/runtime/doc/autocmd.txt
+++ b/runtime/doc/autocmd.txt
@@ -596,6 +596,8 @@ CompleteChanged *CompleteChanged*
CompleteDone After Insert mode completion is done. Either
when something was completed or abandoning
completion. |ins-completion|
+ |complete_info()| can be used, the info is
+ cleared after triggering CompleteDone.
The |v:completed_item| variable contains the
completed item.
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index cdb4b127da..0c183add16 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -3385,6 +3385,7 @@ static bool ins_compl_prep(int c)
{
char_u *ptr;
bool retval = false;
+ const int prev_mode = ctrl_x_mode;
/* Forget any previous 'special' messages if this is actually
* a ^X mode key - bar ^R, in which case we wait to see what it gives us.
@@ -3593,6 +3594,18 @@ static bool ins_compl_prep(int c)
auto_format(FALSE, TRUE);
+ {
+ const int new_mode = ctrl_x_mode;
+
+ // Trigger the CompleteDone event to give scripts a chance to
+ // act upon the completion. Do this before clearing the info,
+ // and restore ctrl_x_mode, so that complete_info() can be
+ // used.
+ ctrl_x_mode = prev_mode;
+ ins_apply_autocmds(EVENT_COMPLETEDONE);
+ ctrl_x_mode = new_mode;
+ }
+
ins_compl_free();
compl_started = false;
compl_matches = 0;
@@ -3617,9 +3630,6 @@ static bool ins_compl_prep(int c)
*/
if (want_cindent && in_cinkeys(KEY_COMPLETE, ' ', inindent(0)))
do_c_expr_indent();
- /* Trigger the CompleteDone event to give scripts a chance to act
- * upon the completion. */
- ins_apply_autocmds(EVENT_COMPLETEDONE);
}
} else if (ctrl_x_mode == CTRL_X_LOCAL_MSG)
/* Trigger the CompleteDone event to give scripts a chance to act
@@ -3747,6 +3757,8 @@ expand_by_function(
case VAR_DICT:
matchdict = rettv.vval.v_dict;
break;
+ case VAR_SPECIAL:
+ FALLTHROUGH;
default:
// TODO(brammool): Give error message?
tv_clear(&rettv);
@@ -5210,7 +5222,7 @@ static int ins_complete(int c, bool enable_pum)
}
}
- /* Show a message about what (completion) mode we're in. */
+ // Show a message about what (completion) mode we're in.
showmode();
if (!shortmess(SHM_COMPLETIONMENU)) {
if (edit_submode_extra != NULL) {
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 9916ee3bd3..797c61a482 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -16018,7 +16018,7 @@ static void f_setpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
const char *const name = tv_get_string_chk(argvars);
if (name != NULL) {
if (list2fpos(&argvars[1], &pos, &fnum, &curswant) == OK) {
- if (--pos.col < 0) {
+ if (pos.col != MAXCOL && --pos.col < 0) {
pos.col = 0;
}
if (name[0] == '.' && name[1] == NUL) {
@@ -19045,6 +19045,15 @@ static void f_virtcol(typval_T *argvars, typval_T *rettv, FunPtr fptr)
fp = var2fpos(&argvars[0], FALSE, &fnum);
if (fp != NULL && fp->lnum <= curbuf->b_ml.ml_line_count
&& fnum == curbuf->b_fnum) {
+ // Limit the column to a valid value, getvvcol() doesn't check.
+ if (fp->col < 0) {
+ fp->col = 0;
+ } else {
+ const size_t len = STRLEN(ml_get(fp->lnum));
+ if (fp->col > (colnr_T)len) {
+ fp->col = (colnr_T)len;
+ }
+ }
getvvcol(curwin, fp, NULL, NULL, &vcol);
++vcol;
}
diff --git a/src/nvim/indent_c.c b/src/nvim/indent_c.c
index 1ca1f3dae5..67a7e58ed7 100644
--- a/src/nvim/indent_c.c
+++ b/src/nvim/indent_c.c
@@ -461,6 +461,9 @@ cin_iscase (
if (cin_starts_with(s, "case")) {
for (s += 4; *s; ++s) {
s = cin_skipcomment(s);
+ if (*s == NUL) {
+ break;
+ }
if (*s == ':') {
if (s[1] == ':') /* skip over "::" for C++ */
++s;
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 5da81dbff6..da2b81fd0a 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -1372,7 +1372,7 @@ int op_delete(oparg_T *oap)
linenr_T lnum;
char_u *ptr;
char_u *newp, *oldp;
- struct block_def bd;
+ struct block_def bd = { 0 };
linenr_T old_lcount = curbuf->b_ml.ml_line_count;
if (curbuf->b_ml.ml_flags & ML_EMPTY) { // nothing to do
diff --git a/src/nvim/spell.c b/src/nvim/spell.c
index 5feb7efda9..c75a53a777 100644
--- a/src/nvim/spell.c
+++ b/src/nvim/spell.c
@@ -5835,10 +5835,7 @@ void spell_soundfold(slang_T *slang, char_u *inword, bool folded, char_u *res)
word = fword;
}
- if (has_mbyte)
- spell_soundfold_wsal(slang, word, res);
- else
- spell_soundfold_sal(slang, word, res);
+ spell_soundfold_wsal(slang, word, res);
}
}
@@ -5903,250 +5900,13 @@ static void spell_soundfold_sofo(slang_T *slang, char_u *inword, char_u *res)
res[ri] = NUL;
}
-static void spell_soundfold_sal(slang_T *slang, char_u *inword, char_u *res)
-{
- salitem_T *smp;
- char_u word[MAXWLEN];
- char_u *s = inword;
- char_u *t;
- char_u *pf;
- int i, j, z;
- int reslen;
- int n, k = 0;
- int z0;
- int k0;
- int n0;
- int c;
- int pri;
- int p0 = -333;
- int c0;
-
- // Remove accents, if wanted. We actually remove all non-word characters.
- // But keep white space. We need a copy, the word may be changed here.
- if (slang->sl_rem_accents) {
- t = word;
- while (*s != NUL) {
- if (ascii_iswhite(*s)) {
- *t++ = ' ';
- s = skipwhite(s);
- } else {
- if (spell_iswordp_nmw(s, curwin))
- *t++ = *s;
- ++s;
- }
- }
- *t = NUL;
- } else
- STRLCPY(word, s, MAXWLEN);
-
- smp = (salitem_T *)slang->sl_sal.ga_data;
-
- // This comes from Aspell phonet.cpp. Converted from C++ to C.
- // Changed to keep spaces.
- i = reslen = z = 0;
- while ((c = word[i]) != NUL) {
- // Start with the first rule that has the character in the word.
- n = slang->sl_sal_first[c];
- z0 = 0;
-
- if (n >= 0) {
- // check all rules for the same letter
- for (; (s = smp[n].sm_lead)[0] == c; ++n) {
- // Quickly skip entries that don't match the word. Most
- // entries are less then three chars, optimize for that.
- k = smp[n].sm_leadlen;
- if (k > 1) {
- if (word[i + 1] != s[1])
- continue;
- if (k > 2) {
- for (j = 2; j < k; ++j)
- if (word[i + j] != s[j])
- break;
- if (j < k)
- continue;
- }
- }
-
- if ((pf = smp[n].sm_oneof) != NULL) {
- // Check for match with one of the chars in "sm_oneof".
- while (*pf != NUL && *pf != word[i + k])
- ++pf;
- if (*pf == NUL)
- continue;
- ++k;
- }
- s = smp[n].sm_rules;
- pri = 5; // default priority
-
- p0 = *s;
- k0 = k;
- while (*s == '-' && k > 1) {
- k--;
- s++;
- }
- if (*s == '<')
- s++;
- if (ascii_isdigit(*s)) {
- // determine priority
- pri = *s - '0';
- s++;
- }
- if (*s == '^' && *(s + 1) == '^')
- s++;
-
- if (*s == NUL
- || (*s == '^'
- && (i == 0 || !(word[i - 1] == ' '
- || spell_iswordp(word + i - 1, curwin)))
- && (*(s + 1) != '$'
- || (!spell_iswordp(word + i + k0, curwin))))
- || (*s == '$' && i > 0
- && spell_iswordp(word + i - 1, curwin)
- && (!spell_iswordp(word + i + k0, curwin)))) {
- // search for followup rules, if:
- // followup and k > 1 and NO '-' in searchstring
- c0 = word[i + k - 1];
- n0 = slang->sl_sal_first[c0];
-
- if (slang->sl_followup && k > 1 && n0 >= 0
- && p0 != '-' && word[i + k] != NUL) {
- // test follow-up rule for "word[i + k]"
- for (; (s = smp[n0].sm_lead)[0] == c0; ++n0) {
- // Quickly skip entries that don't match the word.
- k0 = smp[n0].sm_leadlen;
- if (k0 > 1) {
- if (word[i + k] != s[1])
- continue;
- if (k0 > 2) {
- pf = word + i + k + 1;
- for (j = 2; j < k0; ++j)
- if (*pf++ != s[j])
- break;
- if (j < k0)
- continue;
- }
- }
- k0 += k - 1;
-
- if ((pf = smp[n0].sm_oneof) != NULL) {
- // Check for match with one of the chars in
- // "sm_oneof".
- while (*pf != NUL && *pf != word[i + k0])
- ++pf;
- if (*pf == NUL)
- continue;
- ++k0;
- }
-
- p0 = 5;
- s = smp[n0].sm_rules;
- while (*s == '-') {
- // "k0" gets NOT reduced because
- // "if (k0 == k)"
- s++;
- }
- if (*s == '<')
- s++;
- if (ascii_isdigit(*s)) {
- p0 = *s - '0';
- s++;
- }
-
- if (*s == NUL
- // *s == '^' cuts
- || (*s == '$'
- && !spell_iswordp(word + i + k0,
- curwin))) {
- if (k0 == k)
- // this is just a piece of the string
- continue;
-
- if (p0 < pri)
- // priority too low
- continue;
- // rule fits; stop search
- break;
- }
- }
-
- if (p0 >= pri && smp[n0].sm_lead[0] == c0)
- continue;
- }
-
- // replace string
- s = smp[n].sm_to;
- if (s == NULL)
- s = (char_u *)"";
- pf = smp[n].sm_rules;
- p0 = (vim_strchr(pf, '<') != NULL) ? 1 : 0;
- if (p0 == 1 && z == 0) {
- // rule with '<' is used
- if (reslen > 0 && *s != NUL && (res[reslen - 1] == c
- || res[reslen - 1] == *s))
- reslen--;
- z0 = 1;
- z = 1;
- k0 = 0;
- while (*s != NUL && word[i + k0] != NUL) {
- word[i + k0] = *s;
- k0++;
- s++;
- }
- if (k > k0)
- STRMOVE(word + i + k0, word + i + k);
-
- // new "actual letter"
- c = word[i];
- } else {
- // no '<' rule used
- i += k - 1;
- z = 0;
- while (*s != NUL && s[1] != NUL && reslen < MAXWLEN) {
- if (reslen == 0 || res[reslen - 1] != *s)
- res[reslen++] = *s;
- s++;
- }
- // new "actual letter"
- c = *s;
- if (strstr((char *)pf, "^^") != NULL) {
- if (c != NUL)
- res[reslen++] = c;
- STRMOVE(word, word + i + 1);
- i = 0;
- z0 = 1;
- }
- }
- break;
- }
- }
- } else if (ascii_iswhite(c)) {
- c = ' ';
- k = 1;
- }
-
- if (z0 == 0) {
- if (k && !p0 && reslen < MAXWLEN && c != NUL
- && (!slang->sl_collapse || reslen == 0
- || res[reslen - 1] != c))
- // condense only double letters
- res[reslen++] = c;
-
- i++;
- z = 0;
- k = 0;
- }
- }
-
- res[reslen] = NUL;
-}
-
// Turn "inword" into its sound-a-like equivalent in "res[MAXWLEN]".
// Multi-byte version of spell_soundfold().
static void spell_soundfold_wsal(slang_T *slang, char_u *inword, char_u *res)
{
salitem_T *smp = (salitem_T *)slang->sl_sal.ga_data;
- int word[MAXWLEN];
- int wres[MAXWLEN];
+ int word[MAXWLEN] = { 0 };
+ int wres[MAXWLEN] = { 0 };
int l;
int *ws;
int *pf;
diff --git a/src/nvim/testdir/test_cindent.vim b/src/nvim/testdir/test_cindent.vim
index d9795d9335..debc9da46d 100644
--- a/src/nvim/testdir/test_cindent.vim
+++ b/src/nvim/testdir/test_cindent.vim
@@ -118,4 +118,13 @@ b = something();
bw!
endfunc
+" this was going beyond the end of the line.
+func Test_cindent_case()
+ new
+ call setline(1, "case x: // x")
+ set cindent
+ norm! f:a:
+ bwipe!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_ins_complete.vim b/src/nvim/testdir/test_ins_complete.vim
index 52ec281d82..e6d427db05 100644
--- a/src/nvim/testdir/test_ins_complete.vim
+++ b/src/nvim/testdir/test_ins_complete.vim
@@ -98,6 +98,15 @@ func Test_ins_complete()
call delete('Xdir', 'rf')
endfunc
+func s:CompleteDone_CompleteFuncNone( findstart, base )
+ throw 'skipped: Nvim does not support v:none'
+ if a:findstart
+ return 0
+ endif
+
+ return v:none
+endfunc
+
function! s:CompleteDone_CompleteFuncDict( findstart, base )
if a:findstart
return 0
@@ -117,6 +126,10 @@ function! s:CompleteDone_CompleteFuncDict( findstart, base )
\ }
endfunction
+func s:CompleteDone_CheckCompletedItemNone()
+ let s:called_completedone = 1
+endfunc
+
function! s:CompleteDone_CheckCompletedItemDict()
call assert_equal( 'aword', v:completed_item[ 'word' ] )
call assert_equal( 'wrd', v:completed_item[ 'abbr' ] )
@@ -125,18 +138,37 @@ function! s:CompleteDone_CheckCompletedItemDict()
call assert_equal( 'W', v:completed_item[ 'kind' ] )
call assert_equal( 'test', v:completed_item[ 'user_data' ] )
+ call assert_equal('function', complete_info().mode)
+
let s:called_completedone = 1
endfunction
-function Test_CompleteDoneDict()
+func Test_CompleteDoneNone()
+ throw 'skipped: Nvim does not support v:none'
+ au CompleteDone * :call <SID>CompleteDone_CheckCompletedItemNone()
+ let oldline = join(map(range(&columns), 'nr2char(screenchar(&lines-1, v:val+1))'), '')
+
+ set completefunc=<SID>CompleteDone_CompleteFuncNone
+ execute "normal a\<C-X>\<C-U>\<C-Y>"
+ set completefunc&
+ let newline = join(map(range(&columns), 'nr2char(screenchar(&lines-1, v:val+1))'), '')
+
+ call assert_true(s:called_completedone)
+ call assert_equal(oldline, newline)
+
+ let s:called_completedone = 0
+ au! CompleteDone
+endfunc
+
+func Test_CompleteDoneDict()
au CompleteDone * :call <SID>CompleteDone_CheckCompletedItemDict()
set completefunc=<SID>CompleteDone_CompleteFuncDict
execute "normal a\<C-X>\<C-U>\<C-Y>"
set completefunc&
- call assert_equal( 'test', v:completed_item[ 'user_data' ] )
- call assert_true( s:called_completedone )
+ call assert_equal('test', v:completed_item[ 'user_data' ])
+ call assert_true(s:called_completedone)
let s:called_completedone = 0
au! CompleteDone
@@ -155,7 +187,7 @@ func Test_CompleteDone_undo()
au! CompleteDone
endfunc
-function! s:CompleteDone_CompleteFuncDictNoUserData( findstart, base )
+func s:CompleteDone_CompleteFuncDictNoUserData(findstart, base)
if a:findstart
return 0
endif
@@ -171,9 +203,9 @@ function! s:CompleteDone_CompleteFuncDictNoUserData( findstart, base )
\ }
\ ]
\ }
-endfunction
+endfunc
-function! s:CompleteDone_CheckCompletedItemDictNoUserData()
+func s:CompleteDone_CheckCompletedItemDictNoUserData()
call assert_equal( 'aword', v:completed_item[ 'word' ] )
call assert_equal( 'wrd', v:completed_item[ 'abbr' ] )
call assert_equal( 'extra text', v:completed_item[ 'menu' ] )
@@ -182,31 +214,31 @@ function! s:CompleteDone_CheckCompletedItemDictNoUserData()
call assert_equal( '', v:completed_item[ 'user_data' ] )
let s:called_completedone = 1
-endfunction
+endfunc
-function Test_CompleteDoneDictNoUserData()
+func Test_CompleteDoneDictNoUserData()
au CompleteDone * :call <SID>CompleteDone_CheckCompletedItemDictNoUserData()
set completefunc=<SID>CompleteDone_CompleteFuncDictNoUserData
execute "normal a\<C-X>\<C-U>\<C-Y>"
set completefunc&
- call assert_equal( '', v:completed_item[ 'user_data' ] )
- call assert_true( s:called_completedone )
+ call assert_equal('', v:completed_item[ 'user_data' ])
+ call assert_true(s:called_completedone)
let s:called_completedone = 0
au! CompleteDone
endfunc
-function! s:CompleteDone_CompleteFuncList( findstart, base )
+func s:CompleteDone_CompleteFuncList(findstart, base)
if a:findstart
return 0
endif
return [ 'aword' ]
-endfunction
+endfunc
-function! s:CompleteDone_CheckCompletedItemList()
+func s:CompleteDone_CheckCompletedItemList()
call assert_equal( 'aword', v:completed_item[ 'word' ] )
call assert_equal( '', v:completed_item[ 'abbr' ] )
call assert_equal( '', v:completed_item[ 'menu' ] )
@@ -215,17 +247,17 @@ function! s:CompleteDone_CheckCompletedItemList()
call assert_equal( '', v:completed_item[ 'user_data' ] )
let s:called_completedone = 1
-endfunction
+endfunc
-function Test_CompleteDoneList()
+func Test_CompleteDoneList()
au CompleteDone * :call <SID>CompleteDone_CheckCompletedItemList()
set completefunc=<SID>CompleteDone_CompleteFuncList
execute "normal a\<C-X>\<C-U>\<C-Y>"
set completefunc&
- call assert_equal( '', v:completed_item[ 'user_data' ] )
- call assert_true( s:called_completedone )
+ call assert_equal('', v:completed_item[ 'user_data' ])
+ call assert_true(s:called_completedone)
let s:called_completedone = 0
au! CompleteDone
diff --git a/src/nvim/testdir/test_marks.vim b/src/nvim/testdir/test_marks.vim
index 272553c29f..06b9dc9dab 100644
--- a/src/nvim/testdir/test_marks.vim
+++ b/src/nvim/testdir/test_marks.vim
@@ -26,11 +26,11 @@ function! Test_Incr_Marks()
endfunction
func Test_setpos()
- new one
+ new Xone
let onebuf = bufnr('%')
let onewin = win_getid()
call setline(1, ['aaa', 'bbb', 'ccc'])
- new two
+ new Xtwo
let twobuf = bufnr('%')
let twowin = win_getid()
call setline(1, ['aaa', 'bbb', 'ccc'])
@@ -63,7 +63,24 @@ func Test_setpos()
call setpos("'N", [onebuf, 1, 3, 0])
call assert_equal([onebuf, 1, 3, 0], getpos("'N"))
+ " try invalid column and check virtcol()
call win_gotoid(onewin)
+ call setpos("'a", [0, 1, 2, 0])
+ call assert_equal([0, 1, 2, 0], getpos("'a"))
+ call setpos("'a", [0, 1, -5, 0])
+ call assert_equal([0, 1, 2, 0], getpos("'a"))
+ call setpos("'a", [0, 1, 0, 0])
+ call assert_equal([0, 1, 1, 0], getpos("'a"))
+ call setpos("'a", [0, 1, 4, 0])
+ call assert_equal([0, 1, 4, 0], getpos("'a"))
+ call assert_equal(4, virtcol("'a"))
+ call setpos("'a", [0, 1, 5, 0])
+ call assert_equal([0, 1, 5, 0], getpos("'a"))
+ call assert_equal(4, virtcol("'a"))
+ call setpos("'a", [0, 1, 21341234, 0])
+ call assert_equal([0, 1, 21341234, 0], getpos("'a"))
+ call assert_equal(4, virtcol("'a"))
+
bwipe!
call win_gotoid(twowin)
bwipe!