Merge pull request #12611 from janlazo/vim-8.0.1531

vim-patch:8.0.{1531,1544,1589,1591,1712,1745,1747},8.1.{819},8.2.{420,539,893,894,895,899,1114,1118,1169,1170,1171,1172,1173,1177,1179,1180,1181,1187,1188,1196,1198,1211,1214,1215,1222}
This commit is contained in:
Matthieu Coudron 2020-07-19 18:41:40 +02:00 committed by GitHub
commit daa5bffd93
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 235 additions and 81 deletions

View File

@ -2019,11 +2019,12 @@ argidx() Number current index in the argument list
arglistid([{winnr} [, {tabnr}]]) Number argument list id arglistid([{winnr} [, {tabnr}]]) Number argument list id
argv({nr} [, {winid}]) String {nr} entry of the argument list argv({nr} [, {winid}]) String {nr} entry of the argument list
argv([-1, {winid}]) List the argument list argv([-1, {winid}]) List the argument list
asin({expr}) Float arc sine of {expr}
assert_beeps({cmd}) Number assert {cmd} causes a beep assert_beeps({cmd}) Number assert {cmd} causes a beep
assert_equal({exp}, {act} [, {msg}]) assert_equal({exp}, {act} [, {msg}])
Number assert {exp} is equal to {act} Number assert {exp} is equal to {act}
assert_equalfile({fname-one}, {fname-two}) assert_equalfile({fname-one}, {fname-two} [, {msg}])
Number assert file contents is equal Number assert file contents are equal
assert_exception({error} [, {msg}]) assert_exception({error} [, {msg}])
Number assert {error} is in v:exception Number assert {error} is in v:exception
assert_fails({cmd} [, {error}]) Number assert {cmd} fails assert_fails({cmd} [, {error}]) Number assert {cmd} fails
@ -2039,7 +2040,6 @@ assert_notmatch({pat}, {text} [, {msg}])
Number assert {pat} not matches {text} Number assert {pat} not matches {text}
assert_report({msg}) Number report a test failure assert_report({msg}) Number report a test failure
assert_true({actual} [, {msg}]) Number assert {actual} is true assert_true({actual} [, {msg}]) Number assert {actual} is true
asin({expr}) Float arc sine of {expr}
atan({expr}) Float arc tangent of {expr} atan({expr}) Float arc tangent of {expr}
atan2({expr}, {expr}) Float arc tangent of {expr1} / {expr2} atan2({expr}, {expr}) Float arc tangent of {expr1} / {expr2}
browse({save}, {title}, {initdir}, {default}) browse({save}, {title}, {initdir}, {default})
@ -2630,7 +2630,7 @@ assert_equal({expected}, {actual}, [, {msg}])
test.vim line 12: Expected 'foo' but got 'bar' ~ test.vim line 12: Expected 'foo' but got 'bar' ~
*assert_equalfile()* *assert_equalfile()*
assert_equalfile({fname-one}, {fname-two}) assert_equalfile({fname-one}, {fname-two} [, {msg}])
When the files {fname-one} and {fname-two} do not contain When the files {fname-one} and {fname-two} do not contain
exactly the same text an error message is added to |v:errors|. exactly the same text an error message is added to |v:errors|.
Also see |assert-return|. Also see |assert-return|.

View File

@ -5552,19 +5552,18 @@ void prepare_assert_error(garray_T *gap)
} }
} }
// Append "str" to "gap", escaping unprintable characters. // Append "p[clen]" to "gap", escaping unprintable characters.
// Changes NL to \n, CR to \r, etc. // Changes NL to \n, CR to \r, etc.
static void ga_concat_esc(garray_T *gap, char_u *str) static void ga_concat_esc(garray_T *gap, const char_u *p, int clen)
FUNC_ATTR_NONNULL_ALL
{ {
char_u *p;
char_u buf[NUMBUFLEN]; char_u buf[NUMBUFLEN];
if (str == NULL) { if (clen > 1) {
ga_concat(gap, (char_u *)"NULL"); memmove(buf, p, clen);
return; buf[clen] = NUL;
} ga_concat(gap, buf);
} else {
for (p = str; *p != NUL; p++) {
switch (*p) { switch (*p) {
case BS: ga_concat(gap, (char_u *)"\\b"); break; case BS: ga_concat(gap, (char_u *)"\\b"); break;
case ESC: ga_concat(gap, (char_u *)"\\e"); break; case ESC: ga_concat(gap, (char_u *)"\\e"); break;
@ -5585,6 +5584,41 @@ static void ga_concat_esc(garray_T *gap, char_u *str)
} }
} }
// Append "str" to "gap", escaping unprintable characters.
// Changes NL to \n, CR to \r, etc.
static void ga_concat_shorten_esc(garray_T *gap, const char_u *str)
FUNC_ATTR_NONNULL_ARG(1)
{
char_u buf[NUMBUFLEN];
if (str == NULL) {
ga_concat(gap, (char_u *)"NULL");
return;
}
for (const char_u *p = str; *p != NUL; p++) {
int same_len = 1;
const char_u *s = p;
const int c = mb_ptr2char_adv(&s);
const int clen = s - p;
while (*s != NUL && c == utf_ptr2char(s)) {
same_len++;
s += clen;
}
if (same_len > 20) {
ga_concat(gap, (char_u *)"\\[");
ga_concat_esc(gap, p, clen);
ga_concat(gap, (char_u *)" occurs ");
vim_snprintf((char *)buf, NUMBUFLEN, "%d", same_len);
ga_concat(gap, buf);
ga_concat(gap, (char_u *)" times]");
p = s - 1;
} else {
ga_concat_esc(gap, p, clen);
}
}
}
// Fill "gap" with information about an assert error. // Fill "gap" with information about an assert error.
void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv, void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv,
char_u *exp_str, typval_T *exp_tv, char_u *exp_str, typval_T *exp_tv,
@ -5609,10 +5643,10 @@ void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv,
if (exp_str == NULL) { if (exp_str == NULL) {
tofree = (char_u *)encode_tv2string(exp_tv, NULL); tofree = (char_u *)encode_tv2string(exp_tv, NULL);
ga_concat_esc(gap, tofree); ga_concat_shorten_esc(gap, tofree);
xfree(tofree); xfree(tofree);
} else { } else {
ga_concat_esc(gap, exp_str); ga_concat_shorten_esc(gap, exp_str);
} }
if (atype != ASSERT_NOTEQUAL) { if (atype != ASSERT_NOTEQUAL) {
@ -5624,7 +5658,7 @@ void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv,
ga_concat(gap, (char_u *)" but got "); ga_concat(gap, (char_u *)" but got ");
} }
tofree = (char_u *)encode_tv2string(got_tv, NULL); tofree = (char_u *)encode_tv2string(got_tv, NULL);
ga_concat_esc(gap, tofree); ga_concat_shorten_esc(gap, tofree);
xfree(tofree); xfree(tofree);
} }
} }
@ -5674,6 +5708,9 @@ int assert_equalfile(typval_T *argvars)
IObuff[0] = NUL; IObuff[0] = NUL;
FILE *const fd1 = os_fopen(fname1, READBIN); FILE *const fd1 = os_fopen(fname1, READBIN);
char line1[200];
char line2[200];
ptrdiff_t lineidx = 0;
if (fd1 == NULL) { if (fd1 == NULL) {
snprintf((char *)IObuff, IOSIZE, (char *)e_notread, fname1); snprintf((char *)IObuff, IOSIZE, (char *)e_notread, fname1);
} else { } else {
@ -5682,6 +5719,7 @@ int assert_equalfile(typval_T *argvars)
fclose(fd1); fclose(fd1);
snprintf((char *)IObuff, IOSIZE, (char *)e_notread, fname2); snprintf((char *)IObuff, IOSIZE, (char *)e_notread, fname2);
} else { } else {
int64_t linecount = 1;
for (int64_t count = 0; ; count++) { for (int64_t count = 0; ; count++) {
const int c1 = fgetc(fd1); const int c1 = fgetc(fd1);
const int c2 = fgetc(fd2); const int c2 = fgetc(fd2);
@ -5693,19 +5731,50 @@ int assert_equalfile(typval_T *argvars)
} else if (c2 == EOF) { } else if (c2 == EOF) {
STRCPY(IObuff, "second file is shorter"); STRCPY(IObuff, "second file is shorter");
break; break;
} else if (c1 != c2) { } else {
line1[lineidx] = c1;
line2[lineidx] = c2;
lineidx++;
if (c1 != c2) {
snprintf((char *)IObuff, IOSIZE, snprintf((char *)IObuff, IOSIZE,
"difference at byte %" PRId64, count); "difference at byte %" PRId64 ", line %" PRId64,
count, linecount);
break; break;
} }
} }
if (c1 == NL) {
linecount++;
lineidx = 0;
} else if (lineidx + 2 == (ptrdiff_t)sizeof(line1)) {
memmove(line1, line1 + 100, lineidx - 100);
memmove(line2, line2 + 100, lineidx - 100);
lineidx -= 100;
}
}
fclose(fd1); fclose(fd1);
fclose(fd2); fclose(fd2);
} }
} }
if (IObuff[0] != NUL) { if (IObuff[0] != NUL) {
prepare_assert_error(&ga); prepare_assert_error(&ga);
if (argvars[2].v_type != VAR_UNKNOWN) {
char *const tofree = encode_tv2echo(&argvars[2], NULL);
ga_concat(&ga, (char_u *)tofree);
xfree(tofree);
ga_concat(&ga, (char_u *)": ");
}
ga_concat(&ga, IObuff); ga_concat(&ga, IObuff);
if (lineidx > 0) {
line1[lineidx] = NUL;
line2[lineidx] = NUL;
ga_concat(&ga, (char_u *)" after \"");
ga_concat(&ga, (char_u *)line1);
if (STRCMP(line1, line2) != 0) {
ga_concat(&ga, (char_u *)"\" vs \"");
ga_concat(&ga, (char_u *)line2);
}
ga_concat(&ga, (char_u *)"\"");
}
assert_error(&ga); assert_error(&ga);
ga_clear(&ga); ga_clear(&ga);
return 1; return 1;

View File

@ -28,7 +28,7 @@ return {
asin={args=1, func="float_op_wrapper", data="&asin"}, -- WJMc asin={args=1, func="float_op_wrapper", data="&asin"}, -- WJMc
assert_beeps={args={1, 2}}, assert_beeps={args={1, 2}},
assert_equal={args={2, 3}}, assert_equal={args={2, 3}},
assert_equalfile={args=2}, assert_equalfile={args={2, 3}},
assert_exception={args={1, 2}}, assert_exception={args={1, 2}},
assert_fails={args={1, 3}}, assert_fails={args={1, 3}},
assert_false={args={1, 2}}, assert_false={args={1, 2}},

View File

@ -415,7 +415,7 @@ static void f_assert_equal(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_number = assert_equal_common(argvars, ASSERT_EQUAL); rettv->vval.v_number = assert_equal_common(argvars, ASSERT_EQUAL);
} }
// "assert_equalfile(fname-one, fname-two)" function // "assert_equalfile(fname-one, fname-two[, msg])" function
static void f_assert_equalfile(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_assert_equalfile(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{ {
rettv->vval.v_number = assert_equalfile(argvars); rettv->vval.v_number = assert_equalfile(argvars);

View File

@ -799,10 +799,14 @@ bool tv_list_equal(list_T *const l1, list_T *const l2, const bool ic,
if (l1 == l2) { if (l1 == l2) {
return true; return true;
} }
if (l1 == NULL || l2 == NULL) { if (tv_list_len(l1) != tv_list_len(l2)) {
return false; return false;
} }
if (tv_list_len(l1) != tv_list_len(l2)) { if (tv_list_len(l1) == 0) {
// empty and NULL list are considered equal
return true;
}
if (l1 == NULL || l2 == NULL) {
return false; return false;
} }

View File

@ -1029,6 +1029,15 @@ void fast_breakcheck(void)
} }
} }
// Like line_breakcheck() but check 100 times less often.
void veryfast_breakcheck(void)
{
if (++breakcheck_count >= BREAKCHECK_SKIP * 100) {
breakcheck_count = 0;
os_breakcheck();
}
}
/// os_call_shell() wrapper. Handles 'verbose', :profile, and v:shell_error. /// os_call_shell() wrapper. Handles 'verbose', :profile, and v:shell_error.
/// Invalidates cached tags. /// Invalidates cached tags.
/// ///

View File

@ -3080,10 +3080,12 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
if (ve_flags == VE_ALL if (ve_flags == VE_ALL
&& (curwin->w_cursor.coladd > 0 && (curwin->w_cursor.coladd > 0
|| endcol2 == curwin->w_cursor.col)) { || endcol2 == curwin->w_cursor.col)) {
if (dir == FORWARD && c == NUL) if (dir == FORWARD && c == NUL) {
++col; col++;
if (dir != FORWARD && c != NUL) }
++curwin->w_cursor.col; if (dir != FORWARD && c != NUL && curwin->w_cursor.coladd > 0) {
curwin->w_cursor.col++;
}
if (c == TAB) { if (c == TAB) {
if (dir == BACKWARD && curwin->w_cursor.col) if (dir == BACKWARD && curwin->w_cursor.col)
curwin->w_cursor.col--; curwin->w_cursor.col--;

View File

@ -1134,7 +1134,6 @@ static int read_sal_section(FILE *fd, slang_T *slang)
salitem_T *smp; salitem_T *smp;
int ccnt; int ccnt;
char_u *p; char_u *p;
int c = NUL;
slang->sl_sofo = false; slang->sl_sofo = false;
@ -1158,7 +1157,9 @@ static int read_sal_section(FILE *fd, slang_T *slang)
ga_grow(gap, cnt + 1); ga_grow(gap, cnt + 1);
// <sal> : <salfromlen> <salfrom> <saltolen> <salto> // <sal> : <salfromlen> <salfrom> <saltolen> <salto>
for (; gap->ga_len < cnt; ++gap->ga_len) { for (; gap->ga_len < cnt; gap->ga_len++) {
int c = NUL;
smp = &((salitem_T *)gap->ga_data)[gap->ga_len]; smp = &((salitem_T *)gap->ga_data)[gap->ga_len];
ccnt = getc(fd); // <salfromlen> ccnt = getc(fd); // <salfromlen>
if (ccnt < 0) if (ccnt < 0)
@ -1810,7 +1811,8 @@ spell_reload_one (
#define CONDIT_SUF 4 // add a suffix for matching flags #define CONDIT_SUF 4 // add a suffix for matching flags
#define CONDIT_AFF 8 // word already has an affix #define CONDIT_AFF 8 // word already has an affix
// Tunable parameters for when the tree is compressed. See 'mkspellmem'. // Tunable parameters for when the tree is compressed. Filled from the
// 'mkspellmem' option.
static long compress_start = 30000; // memory / SBLOCKSIZE static long compress_start = 30000; // memory / SBLOCKSIZE
static long compress_inc = 100; // memory / SBLOCKSIZE static long compress_inc = 100; // memory / SBLOCKSIZE
static long compress_added = 500000; // word count static long compress_added = 500000; // word count
@ -3015,6 +3017,7 @@ static int spell_read_dic(spellinfo_T *spin, char_u *fname, afffile_T *affile)
char_u message[MAXLINELEN + MAXWLEN]; char_u message[MAXLINELEN + MAXWLEN];
int flags; int flags;
int duplicate = 0; int duplicate = 0;
Timestamp last_msg_time = 0;
// Open the file. // Open the file.
fd = os_fopen((char *)fname, "r"); fd = os_fopen((char *)fname, "r");
@ -3090,19 +3093,23 @@ static int spell_read_dic(spellinfo_T *spin, char_u *fname, afffile_T *affile)
continue; continue;
} }
// This takes time, print a message every 10000 words. // This takes time, print a message every 10000 words, but not more
// often than once per second.
if (spin->si_verbose && spin->si_msg_count > 10000) { if (spin->si_verbose && spin->si_msg_count > 10000) {
spin->si_msg_count = 0; spin->si_msg_count = 0;
if (os_time() > last_msg_time) {
last_msg_time = os_time();
vim_snprintf((char *)message, sizeof(message), vim_snprintf((char *)message, sizeof(message),
_("line %6d, word %6ld - %s"), _("line %6d, word %6ld - %s"),
lnum, spin->si_foldwcount + spin->si_keepwcount, w); lnum, spin->si_foldwcount + spin->si_keepwcount, w);
msg_start(); msg_start();
msg_puts_long_attr(message, 0); msg_puts_long_attr(message, 0);
msg_clr_eos(); msg_clr_eos();
msg_didout = FALSE; msg_didout = false;
msg_col = 0; msg_col = 0;
ui_flush(); ui_flush();
} }
}
// Store the word in the hashtable to be able to find duplicates. // Store the word in the hashtable to be able to find duplicates.
dw = getroom_save(spin, w); dw = getroom_save(spin, w);
@ -3914,10 +3921,11 @@ static int tree_add_word(spellinfo_T *spin, char_u *word, wordnode_T *root, int
++spin->si_msg_count; ++spin->si_msg_count;
if (spin->si_compress_cnt > 1) { if (spin->si_compress_cnt > 1) {
if (--spin->si_compress_cnt == 1) if (--spin->si_compress_cnt == 1) {
// Did enough words to lower the block count limit. // Did enough words to lower the block count limit.
spin->si_blocks_cnt += compress_inc; spin->si_blocks_cnt += compress_inc;
} }
}
// When we have allocated lots of memory we need to compress the word tree // When we have allocated lots of memory we need to compress the word tree
// to free up some room. But compression is slow, and we might actually // to free up some room. But compression is slow, and we might actually
@ -3955,9 +3963,10 @@ static int tree_add_word(spellinfo_T *spin, char_u *word, wordnode_T *root, int
// compression useful, or one of them is small, which means // compression useful, or one of them is small, which means
// compression goes fast. But when filling the soundfold word tree // compression goes fast. But when filling the soundfold word tree
// there is no keep-case tree. // there is no keep-case tree.
wordtree_compress(spin, spin->si_foldroot); wordtree_compress(spin, spin->si_foldroot, "case-folded");
if (affixID >= 0) if (affixID >= 0) {
wordtree_compress(spin, spin->si_keeproot); wordtree_compress(spin, spin->si_keeproot, "keep-case");
}
} }
return OK; return OK;
@ -3990,6 +3999,7 @@ static wordnode_T *get_wordnode(spellinfo_T *spin)
// siblings. // siblings.
// Returns the number of nodes actually freed. // Returns the number of nodes actually freed.
static int deref_wordnode(spellinfo_T *spin, wordnode_T *node) static int deref_wordnode(spellinfo_T *spin, wordnode_T *node)
FUNC_ATTR_NONNULL_ALL
{ {
wordnode_T *np; wordnode_T *np;
int cnt = 0; int cnt = 0;
@ -4009,6 +4019,7 @@ static int deref_wordnode(spellinfo_T *spin, wordnode_T *node)
// Free a wordnode_T for re-use later. // Free a wordnode_T for re-use later.
// Only the "wn_child" field becomes invalid. // Only the "wn_child" field becomes invalid.
static void free_wordnode(spellinfo_T *spin, wordnode_T *n) static void free_wordnode(spellinfo_T *spin, wordnode_T *n)
FUNC_ATTR_NONNULL_ALL
{ {
n->wn_child = spin->si_first_free; n->wn_child = spin->si_first_free;
spin->si_first_free = n; spin->si_first_free = n;
@ -4016,18 +4027,19 @@ static void free_wordnode(spellinfo_T *spin, wordnode_T *n)
} }
// Compress a tree: find tails that are identical and can be shared. // Compress a tree: find tails that are identical and can be shared.
static void wordtree_compress(spellinfo_T *spin, wordnode_T *root) static void wordtree_compress(spellinfo_T *spin, wordnode_T *root,
const char *name)
FUNC_ATTR_NONNULL_ALL
{ {
hashtab_T ht; hashtab_T ht;
int n; long tot = 0;
int tot = 0; long perc;
int perc;
// Skip the root itself, it's not actually used. The first sibling is the // Skip the root itself, it's not actually used. The first sibling is the
// start of the tree. // start of the tree.
if (root->wn_sibling != NULL) { if (root->wn_sibling != NULL) {
hash_init(&ht); hash_init(&ht);
n = node_compress(spin, root->wn_sibling, &ht, &tot); const long n = node_compress(spin, root->wn_sibling, &ht, &tot);
#ifndef SPELL_PRINTTREE #ifndef SPELL_PRINTTREE
if (spin->si_verbose || p_verbose > 2) if (spin->si_verbose || p_verbose > 2)
@ -4040,8 +4052,8 @@ static void wordtree_compress(spellinfo_T *spin, wordnode_T *root)
else else
perc = (tot - n) * 100 / tot; perc = (tot - n) * 100 / tot;
vim_snprintf((char *)IObuff, IOSIZE, vim_snprintf((char *)IObuff, IOSIZE,
_("Compressed %d of %d nodes; %d (%d%%) remaining"), _("Compressed %s of %ld nodes; %ld (%ld%%) remaining"),
n, tot, tot - n, perc); name, tot, tot - n, perc);
spell_message(spin, IObuff); spell_message(spin, IObuff);
} }
#ifdef SPELL_PRINTTREE #ifdef SPELL_PRINTTREE
@ -4053,23 +4065,23 @@ static void wordtree_compress(spellinfo_T *spin, wordnode_T *root)
// Compress a node, its siblings and its children, depth first. // Compress a node, its siblings and its children, depth first.
// Returns the number of compressed nodes. // Returns the number of compressed nodes.
static int static long node_compress(
node_compress (
spellinfo_T *spin, spellinfo_T *spin,
wordnode_T *node, wordnode_T *node,
hashtab_T *ht, hashtab_T *ht,
int *tot // total count of nodes before compressing, long *tot // total count of nodes before compressing,
// incremented while going through the tree // incremented while going through the tree
) )
FUNC_ATTR_NONNULL_ALL
{ {
wordnode_T *np; wordnode_T *np;
wordnode_T *tp; wordnode_T *tp;
wordnode_T *child; wordnode_T *child;
hash_T hash; hash_T hash;
hashitem_T *hi; hashitem_T *hi;
int len = 0; long len = 0;
unsigned nr, n; unsigned nr, n;
int compressed = 0; long compressed = 0;
// Go through the list of siblings. Compress each child and then try // Go through the list of siblings. Compress each child and then try
// finding an identical child to replace it. // finding an identical child to replace it.
@ -4142,7 +4154,7 @@ node_compress (
node->wn_u1.hashkey[5] = NUL; node->wn_u1.hashkey[5] = NUL;
// Check for CTRL-C pressed now and then. // Check for CTRL-C pressed now and then.
fast_breakcheck(); veryfast_breakcheck();
return compressed; return compressed;
} }
@ -4749,7 +4761,7 @@ static void spell_make_sugfile(spellinfo_T *spin, char_u *wfname)
// Compress the soundfold trie. // Compress the soundfold trie.
spell_message(spin, (char_u *)_(msg_compressing)); spell_message(spin, (char_u *)_(msg_compressing));
wordtree_compress(spin, spin->si_foldroot); wordtree_compress(spin, spin->si_foldroot, "case-folded");
// Write the .sug file. // Write the .sug file.
// Make the file name by changing ".spl" to ".sug". // Make the file name by changing ".spl" to ".sug".
@ -5219,9 +5231,9 @@ mkspell (
if (!error && !got_int) { if (!error && !got_int) {
// Combine tails in the tree. // Combine tails in the tree.
spell_message(&spin, (char_u *)_(msg_compressing)); spell_message(&spin, (char_u *)_(msg_compressing));
wordtree_compress(&spin, spin.si_foldroot); wordtree_compress(&spin, spin.si_foldroot, "case-folded");
wordtree_compress(&spin, spin.si_keeproot); wordtree_compress(&spin, spin.si_keeproot, "keep-case");
wordtree_compress(&spin, spin.si_prefroot); wordtree_compress(&spin, spin.si_prefroot, "prefixes");
} }
if (!error && !got_int) { if (!error && !got_int) {
@ -5273,7 +5285,8 @@ theend:
// Display a message for spell file processing when 'verbose' is set or using // Display a message for spell file processing when 'verbose' is set or using
// ":mkspell". "str" can be IObuff. // ":mkspell". "str" can be IObuff.
static void spell_message(spellinfo_T *spin, char_u *str) static void spell_message(const spellinfo_T *spin, char_u *str)
FUNC_ATTR_NONNULL_ALL
{ {
if (spin->si_verbose || p_verbose > 2) { if (spin->si_verbose || p_verbose > 2) {
if (!spin->si_verbose) if (!spin->si_verbose)

View File

@ -275,7 +275,7 @@ func GetVimCommand(...)
" If using valgrind, make sure every run uses a different log file. " If using valgrind, make sure every run uses a different log file.
if cmd =~ 'valgrind.*--log-file=' if cmd =~ 'valgrind.*--log-file='
let cmd = substitute(cmd, '--log-file=\(^\s*\)', '--log-file=\1.' . g:valgrind_cnt, '') let cmd = substitute(cmd, '--log-file=\(\S*\)', '--log-file=\1.' . g:valgrind_cnt, '')
let g:valgrind_cnt += 1 let g:valgrind_cnt += 1
endif endif

View File

@ -28,7 +28,18 @@ func Test_assert_equalfile()
call writefile(['1234X89'], 'Xone') call writefile(['1234X89'], 'Xone')
call writefile(['1234Y89'], 'Xtwo') call writefile(['1234Y89'], 'Xtwo')
call assert_equal(1, assert_equalfile('Xone', 'Xtwo')) call assert_equal(1, assert_equalfile('Xone', 'Xtwo'))
call assert_match("difference at byte 4", v:errors[0]) call assert_match('difference at byte 4, line 1 after "1234X" vs "1234Y"', v:errors[0])
call remove(v:errors, 0)
call writefile([repeat('x', 234) .. 'X'], 'Xone')
call writefile([repeat('x', 234) .. 'Y'], 'Xtwo')
call assert_equal(1, assert_equalfile('Xone', 'Xtwo'))
let xes = repeat('x', 134)
call assert_match('difference at byte 234, line 1 after "' .. xes .. 'X" vs "' .. xes .. 'Y"', v:errors[0])
call remove(v:errors, 0)
call assert_equal(1, assert_equalfile('Xone', 'Xtwo', 'a message'))
call assert_match("a message: difference at byte 234, line 1 after", v:errors[0])
call remove(v:errors, 0) call remove(v:errors, 0)
call delete('Xone') call delete('Xone')

View File

@ -800,3 +800,25 @@ func Test_diff_closeoff()
diffoff! diffoff!
enew! enew!
endfunc endfunc
func Test_diff_and_scroll()
" this was causing an ml_get error
set ls=2
for i in range(winheight(0) * 2)
call setline(i, i < winheight(0) - 10 ? i : i + 10)
endfor
vnew
for i in range(winheight(0)*2 + 10)
call setline(i, i < winheight(0) - 10 ? 0 : i)
endfor
diffthis
wincmd p
diffthis
execute 'normal ' . winheight(0) . "\<C-d>"
bwipe!
bwipe!
set ls&
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@ -167,4 +167,22 @@ func Test_set_register()
enew! enew!
endfunc endfunc
func Test_ve_blockpaste()
new
set ve=all
0put =['QWERTZ','ASDFGH']
call cursor(1,1)
exe ":norm! \<C-V>3ljdP"
call assert_equal(1, col('.'))
call assert_equal(getline(1, 2), ['QWERTZ', 'ASDFGH'])
call cursor(1,1)
exe ":norm! \<C-V>3ljd"
call cursor(1,1)
norm! $3lP
call assert_equal(5, col('.'))
call assert_equal(getline(1, 2), ['TZ QWER', 'GH ASDF'])
set ve&vim
bwipe!
endfunc
" vim: shiftwidth=2 sts=2 expandtab " vim: shiftwidth=2 sts=2 expandtab

View File

@ -47,10 +47,8 @@ describe('NULL', function()
-- Subjectable behaviour -- Subjectable behaviour
-- FIXME Should return 1 null_expr_test('is equal to empty list', 'L == []', 0, 1)
null_expr_test('is equal to empty list', 'L == []', 0, 0) null_expr_test('is equal to empty list (reverse order)', '[] == L', 0, 1)
-- FIXME Should return 1
null_expr_test('is equal to empty list (reverse order)', '[] == L', 0, 0)
-- Correct behaviour -- Correct behaviour
null_expr_test('can be indexed with error message for empty list', 'L[0]', null_expr_test('can be indexed with error message for empty list', 'L[0]',

View File

@ -38,6 +38,9 @@ describe('assert function:', function()
call assert_equal(4, n) call assert_equal(4, n)
let l = [1, 2, 3] let l = [1, 2, 3]
call assert_equal([1, 2, 3], l) call assert_equal([1, 2, 3], l)
call assert_equal(v:_null_list, v:_null_list)
call assert_equal(v:_null_list, [])
call assert_equal([], v:_null_list)
fu Func() fu Func()
endfu endfu
let F1 = function('Func') let F1 = function('Func')
@ -92,6 +95,11 @@ describe('assert function:', function()
call('assert_equal', 'foo', 'bar', 'testing') call('assert_equal', 'foo', 'bar', 'testing')
expected_errors({"testing: Expected 'foo' but got 'bar'"}) expected_errors({"testing: Expected 'foo' but got 'bar'"})
end) end)
it('should shorten a long message', function()
call ('assert_equal', 'XxxxxxxxxxxxxxxxxxxxxxX', 'XyyyyyyyyyyyyyyyyyyyyyyyyyX')
expected_errors({"Expected 'X\\[x occurs 21 times]X' but got 'X\\[y occurs 25 times]X'"})
end)
end) end)
-- assert_notequal({expected}, {actual}[, {msg}]) -- assert_notequal({expected}, {actual}[, {msg}])

View File

@ -1234,13 +1234,13 @@ describe('typval.c', function()
local l = list() local l = list()
local l2 = list() local l2 = list()
-- NULL lists are not equal to empty lists -- NULL lists are equal to empty lists
eq(false, lib.tv_list_equal(l, nil, true, false)) eq(true, lib.tv_list_equal(l, nil, true, false))
eq(false, lib.tv_list_equal(nil, l, false, false)) eq(true, lib.tv_list_equal(nil, l, false, false))
eq(false, lib.tv_list_equal(nil, l, false, true)) eq(true, lib.tv_list_equal(nil, l, false, true))
eq(false, lib.tv_list_equal(l, nil, true, true)) eq(true, lib.tv_list_equal(l, nil, true, true))
-- Yet NULL lists are equal themselves -- NULL lists are equal themselves
eq(true, lib.tv_list_equal(nil, nil, true, false)) eq(true, lib.tv_list_equal(nil, nil, true, false))
eq(true, lib.tv_list_equal(nil, nil, false, false)) eq(true, lib.tv_list_equal(nil, nil, false, false))
eq(true, lib.tv_list_equal(nil, nil, false, true)) eq(true, lib.tv_list_equal(nil, nil, false, true))
@ -2648,13 +2648,13 @@ describe('typval.c', function()
local l2 = lua2typvalt(empty_list) local l2 = lua2typvalt(empty_list)
local nl = lua2typvalt(null_list) local nl = lua2typvalt(null_list)
-- NULL lists are not equal to empty lists -- NULL lists are equal to empty lists
eq(false, lib.tv_equal(l, nl, true, false)) eq(true, lib.tv_equal(l, nl, true, false))
eq(false, lib.tv_equal(nl, l, false, false)) eq(true, lib.tv_equal(nl, l, false, false))
eq(false, lib.tv_equal(nl, l, false, true)) eq(true, lib.tv_equal(nl, l, false, true))
eq(false, lib.tv_equal(l, nl, true, true)) eq(true, lib.tv_equal(l, nl, true, true))
-- Yet NULL lists are equal themselves -- NULL lists are equal themselves
eq(true, lib.tv_equal(nl, nl, true, false)) eq(true, lib.tv_equal(nl, nl, true, false))
eq(true, lib.tv_equal(nl, nl, false, false)) eq(true, lib.tv_equal(nl, nl, false, false))
eq(true, lib.tv_equal(nl, nl, false, true)) eq(true, lib.tv_equal(nl, nl, false, true))