Merge #11707 from janlazo/vim-8.1.1434

vim-patch:8.1.{716,1139},8.2.{112,120,123}
This commit is contained in:
Justin M. Keyes 2020-01-18 16:12:16 -08:00 committed by GitHub
commit fb8b0503ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 112 additions and 268 deletions

View File

@ -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.

View File

@ -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) {

View File

@ -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;
}

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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!