aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/api/vim.c4
-rw-r--r--src/nvim/eval.c37
-rw-r--r--src/nvim/ex_docmd.c2
-rw-r--r--src/nvim/lua/vim.lua7
-rw-r--r--src/nvim/misc1.c2
-rw-r--r--src/nvim/quickfix.c28
-rw-r--r--src/nvim/search.c16
-rw-r--r--src/nvim/spellfile.c17
-rw-r--r--src/nvim/testdir/test_gf.vim25
-rw-r--r--src/nvim/testdir/test_gn.vim3
-rw-r--r--src/nvim/testdir/test_let.vim13
-rw-r--r--src/nvim/testdir/test_spell.vim9
-rw-r--r--src/nvim/testdir/test_vimscript.vim2
-rw-r--r--test/functional/terminal/scrollback_spec.lua2
-rw-r--r--test/functional/terminal/tui_spec.lua45
-rw-r--r--test/functional/ui/messages_spec.lua14
-rw-r--r--test/functional/ui/screen.lua9
17 files changed, 166 insertions, 69 deletions
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index 0e64658f36..e587df5384 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -1251,7 +1251,7 @@ Boolean nvim_paste(String data, Boolean crlf, Integer phase, Error *err)
draining = true;
goto theend;
}
- if (!(State & CMDLINE) && !(State & INSERT) && (phase == -1 || phase == 1)) {
+ if (!(State & (CMDLINE | INSERT)) && (phase == -1 || phase == 1)) {
ResetRedobuff();
AppendCharToRedobuff('a'); // Dot-repeat.
}
@@ -1269,7 +1269,7 @@ Boolean nvim_paste(String data, Boolean crlf, Integer phase, Error *err)
}
}
}
- if (!(State & CMDLINE) && !(State & INSERT) && (phase == -1 || phase == 3)) {
+ if (!(State & (CMDLINE | INSERT)) && (phase == -1 || phase == 3)) {
AppendCharToRedobuff(ESC); // Dot-repeat.
}
theend:
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index fd83bc846b..e08e129656 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -21742,22 +21742,31 @@ void ex_function(exarg_T *eap)
}
// Check for ":let v =<< [trim] EOF"
+ // and ":let [a, b] =<< [trim] EOF"
arg = skipwhite(skiptowhite(p));
- arg = skipwhite(skiptowhite(arg));
- if (arg[0] == '=' && arg[1] == '<' && arg[2] =='<'
- && ((p[0] == 'l' && p[1] == 'e'
- && (!ASCII_ISALNUM(p[2])
- || (p[2] == 't' && !ASCII_ISALNUM(p[3])))))) {
- p = skipwhite(arg + 3);
- if (STRNCMP(p, "trim", 4) == 0) {
- // Ignore leading white space.
- p = skipwhite(p + 4);
- heredoc_trimmed = vim_strnsave(theline,
- (int)(skipwhite(theline) - theline));
+ if (*arg == '[') {
+ arg = vim_strchr(arg, ']');
+ }
+ if (arg != NULL) {
+ arg = skipwhite(skiptowhite(arg));
+ if (arg[0] == '='
+ && arg[1] == '<'
+ && arg[2] =='<'
+ && (p[0] == 'l'
+ && p[1] == 'e'
+ && (!ASCII_ISALNUM(p[2])
+ || (p[2] == 't' && !ASCII_ISALNUM(p[3]))))) {
+ p = skipwhite(arg + 3);
+ if (STRNCMP(p, "trim", 4) == 0) {
+ // Ignore leading white space.
+ p = skipwhite(p + 4);
+ heredoc_trimmed =
+ vim_strnsave(theline, (int)(skipwhite(theline) - theline));
+ }
+ skip_until = vim_strnsave(p, (int)(skiptowhite(p) - p));
+ do_concat = false;
+ is_heredoc = true;
}
- skip_until = vim_strnsave(p, (int)(skiptowhite(p) - p));
- do_concat = false;
- is_heredoc = true;
}
}
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index d3e2120721..7d02623d67 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -10156,7 +10156,7 @@ static void ex_folddo(exarg_T *eap)
bool is_loclist_cmd(int cmdidx)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
- if (cmdidx < 0 || cmdidx > CMD_SIZE) {
+ if (cmdidx < 0 || cmdidx >= CMD_SIZE) {
return false;
}
return cmdnames[cmdidx].cmd_name[0] == 'l';
diff --git a/src/nvim/lua/vim.lua b/src/nvim/lua/vim.lua
index adb90084db..1ebdde99d5 100644
--- a/src/nvim/lua/vim.lua
+++ b/src/nvim/lua/vim.lua
@@ -206,8 +206,11 @@ paste = (function()
local line1 = lines[1]:gsub('<', '<lt>'):gsub('[\r\n\012\027]', ' ') -- Scrub.
vim.api.nvim_input(line1)
vim.api.nvim_set_option('paste', false)
- elseif mode ~= 'c' then -- Else: discard remaining cmdline-mode chunks.
- if phase < 2 and mode ~= 'i' and mode ~= 'R' and mode ~= 't' then
+ elseif mode ~= 'c' then
+ if phase < 2 and mode:find('^[vV\22sS\19]') then
+ vim.api.nvim_command([[exe "normal! \<Del>"]])
+ vim.api.nvim_put(lines, 'c', false, true)
+ elseif phase < 2 and not mode:find('^[iRt]') then
vim.api.nvim_put(lines, 'c', true, true)
-- XXX: Normal-mode: workaround bad cursor-placement after first chunk.
vim.api.nvim_command('normal! a')
diff --git a/src/nvim/misc1.c b/src/nvim/misc1.c
index 1db8a1fa11..c1de7ab9a4 100644
--- a/src/nvim/misc1.c
+++ b/src/nvim/misc1.c
@@ -792,6 +792,8 @@ int prompt_for_number(int *mouse_used)
cmdline_row = msg_row - 1;
}
need_wait_return = false;
+ msg_didany = false;
+ msg_didout = false;
} else {
cmdline_row = save_cmdline_row;
}
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c
index cf5194d16f..da315252b5 100644
--- a/src/nvim/quickfix.c
+++ b/src/nvim/quickfix.c
@@ -1890,6 +1890,7 @@ static qf_info_T *qf_alloc_stack(qfltype_T qfltype)
/// Return the location list stack for window 'wp'.
/// If not present, allocate a location list stack
static qf_info_T *ll_get_or_alloc_list(win_T *wp)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET
{
if (IS_LL_WINDOW(wp))
/* For a location list window, use the referenced location list */
@@ -1931,17 +1932,14 @@ static qf_info_T * qf_cmd_get_stack(exarg_T *eap, int print_emsg)
/// Get the quickfix/location list stack to use for the specified Ex command.
/// For a location list command, returns the stack for the current window.
/// If the location list is not present, then allocates a new one.
-/// Returns NULL if the allocation fails. For a location list command, sets
-/// 'pwinp' to curwin.
-static qf_info_T * qf_cmd_get_or_alloc_stack(exarg_T *eap, win_T **pwinp)
+/// For a location list command, sets 'pwinp' to curwin.
+static qf_info_T *qf_cmd_get_or_alloc_stack(const exarg_T *eap, win_T **pwinp)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET
{
qf_info_T *qi = &ql_info;
if (is_loclist_cmd(eap->cmdidx)) {
qi = ll_get_or_alloc_list(curwin);
- if (qi == NULL) {
- return NULL;
- }
*pwinp = curwin;
}
@@ -4968,7 +4966,6 @@ void ex_vimgrep(exarg_T *eap)
char_u *s;
char_u *p;
int fi;
- qf_info_T *qi;
qf_list_T *qfl;
win_T *wp = NULL;
buf_T *buf;
@@ -4994,10 +4991,7 @@ void ex_vimgrep(exarg_T *eap)
}
}
- qi = qf_cmd_get_or_alloc_stack(eap, &wp);
- if (qi == NULL) {
- return;
- }
+ qf_info_T *qi = qf_cmd_get_or_alloc_stack(eap, &wp);
if (eap->addr_count > 0)
tomatch = eap->line2;
@@ -6304,7 +6298,6 @@ static int cbuffer_process_args(exarg_T *eap,
void ex_cbuffer(exarg_T *eap)
{
buf_T *buf = NULL;
- qf_info_T *qi;
char_u *au_name = NULL;
win_T *wp = NULL;
char_u *qf_title;
@@ -6320,10 +6313,7 @@ void ex_cbuffer(exarg_T *eap)
}
// Must come after autocommands.
- qi = qf_cmd_get_or_alloc_stack(eap, &wp);
- if (qi == NULL) {
- return;
- }
+ qf_info_T *qi = qf_cmd_get_or_alloc_stack(eap, &wp);
if (cbuffer_process_args(eap, &buf, &line1, &line2) == FAIL) {
return;
@@ -6392,7 +6382,6 @@ static char_u * cexpr_get_auname(cmdidx_T cmdidx)
/// ":lexpr {expr}", ":lgetexpr {expr}", ":laddexpr {expr}" command.
void ex_cexpr(exarg_T *eap)
{
- qf_info_T *qi;
char_u *au_name = NULL;
win_T *wp = NULL;
@@ -6404,10 +6393,7 @@ void ex_cexpr(exarg_T *eap)
}
}
- qi = qf_cmd_get_or_alloc_stack(eap, &wp);
- if (qi == NULL) {
- return;
- }
+ qf_info_T *qi = qf_cmd_get_or_alloc_stack(eap, &wp);
/* Evaluate the expression. When the result is a string or a list we can
* use it to fill the errorlist. */
diff --git a/src/nvim/search.c b/src/nvim/search.c
index c4c8633ed9..d396e7551b 100644
--- a/src/nvim/search.c
+++ b/src/nvim/search.c
@@ -4037,9 +4037,6 @@ current_search(
bool old_p_ws = p_ws;
pos_T save_VIsual = VIsual;
- /* wrapping should not occur */
- p_ws = false;
-
/* Correct cursor when 'selection' is exclusive */
if (VIsual_active && *p_sel == 'e' && lt(VIsual, curwin->w_cursor))
dec_cursor();
@@ -4063,8 +4060,7 @@ current_search(
int zero_width = is_zero_width(spats[last_idx].pat, true, &curwin->w_cursor,
FORWARD);
if (zero_width == -1) {
- p_ws = old_p_ws;
- return FAIL; /* pattern not found */
+ return FAIL; // pattern not found
}
/*
@@ -4081,11 +4077,18 @@ current_search(
}
end_pos = pos;
+ // wrapping should not occur in the first round
+ if (i == 0) {
+ p_ws = false;
+ }
+
result = searchit(curwin, curbuf, &pos, &end_pos,
(dir ? FORWARD : BACKWARD),
spats[last_idx].pat, i ? count : 1,
SEARCH_KEEP | flags, RE_SEARCH, NULL);
+ p_ws = old_p_ws;
+
// First search may fail, but then start searching from the
// beginning of the file (cursor might be on the search match)
// except when Visual mode is active, so that extending the visual
@@ -4094,7 +4097,6 @@ current_search(
curwin->w_cursor = orig_pos;
if (VIsual_active)
VIsual = save_VIsual;
- p_ws = old_p_ws;
return FAIL;
} else if (i == 0 && !result) {
if (forward) { // try again from start of buffer
@@ -4110,8 +4112,6 @@ current_search(
pos_T start_pos = pos;
- p_ws = old_p_ws;
-
if (!VIsual_active) {
VIsual = start_pos;
}
diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c
index eeec5be120..4fac001bc5 100644
--- a/src/nvim/spellfile.c
+++ b/src/nvim/spellfile.c
@@ -265,6 +265,8 @@
// follow; never used in prefix tree
#define BY_SPECIAL BY_FLAGS2 // highest special byte value
+#define ZERO_FLAG 65009 // used when flag is zero: "0"
+
// Flags used in .spl file for soundsalike flags.
#define SAL_F0LLOWUP 1
#define SAL_COLLAPSE 2
@@ -2783,6 +2785,7 @@ static unsigned affitem2flag(int flagtype, char_u *item, char_u *fname, int lnum
}
// Get one affix name from "*pp" and advance the pointer.
+// Returns ZERO_FLAG for "0".
// Returns zero for an error, still advances the pointer then.
static unsigned get_affitem(int flagtype, char_u **pp)
{
@@ -2794,6 +2797,9 @@ static unsigned get_affitem(int flagtype, char_u **pp)
return 0;
}
res = getdigits_int(pp, true, 0);
+ if (res == 0) {
+ res = ZERO_FLAG;
+ }
} else {
res = mb_ptr2char_adv((const char_u **)pp);
if (flagtype == AFT_LONG || (flagtype == AFT_CAPLONG
@@ -2915,10 +2921,15 @@ static bool flag_in_afflist(int flagtype, char_u *afflist, unsigned flag)
int digits = getdigits_int(&p, true, 0);
assert(digits >= 0);
n = (unsigned int)digits;
- if (n == flag)
+ if (n == 0) {
+ n = ZERO_FLAG;
+ }
+ if (n == flag) {
return true;
- if (*p != NUL) // skip over comma
- ++p;
+ }
+ if (*p != NUL) { // skip over comma
+ p++;
+ }
}
break;
}
diff --git a/src/nvim/testdir/test_gf.vim b/src/nvim/testdir/test_gf.vim
index accd21e9a3..d301874891 100644
--- a/src/nvim/testdir/test_gf.vim
+++ b/src/nvim/testdir/test_gf.vim
@@ -99,3 +99,28 @@ func Test_gf()
call delete('Xtest1')
call delete('Xtestgf')
endfunc
+
+func Test_gf_visual()
+ call writefile([], "Xtest_gf_visual")
+ new
+ call setline(1, 'XXXtest_gf_visualXXX')
+ set hidden
+
+ " Visually select Xtest_gf_visual and use gf to go to that file
+ norm! ttvtXgf
+ call assert_equal('Xtest_gf_visual', bufname('%'))
+
+ bwipe!
+ call delete('Xtest_gf_visual')
+ set hidden&
+endfunc
+
+func Test_gf_error()
+ new
+ call assert_fails('normal gf', 'E446:')
+ call assert_fails('normal gF', 'E446:')
+ call setline(1, '/doesnotexist')
+ call assert_fails('normal gf', 'E447:')
+ call assert_fails('normal gF', 'E447:')
+ bwipe!
+endfunc
diff --git a/src/nvim/testdir/test_gn.vim b/src/nvim/testdir/test_gn.vim
index 834397126f..d41675be0c 100644
--- a/src/nvim/testdir/test_gn.vim
+++ b/src/nvim/testdir/test_gn.vim
@@ -136,8 +136,9 @@ func Test_gn_command()
call assert_equal(['ABCDEFGHi'], getline(1,'$'))
call setline('.', ['abcdefghi'])
let @/ = 'b'
+ " this gn wraps around the end of the file
exe "norm! 0fhvhhgngU"
- call assert_equal(['abcdefghi'], getline(1,'$'))
+ call assert_equal(['aBCDEFGHi'], getline(1,'$'))
sil! %d _
call setline('.', ['abcdefghi'])
let @/ = 'f'
diff --git a/src/nvim/testdir/test_let.vim b/src/nvim/testdir/test_let.vim
index 1fce3d6937..3c0fefbd25 100644
--- a/src/nvim/testdir/test_let.vim
+++ b/src/nvim/testdir/test_let.vim
@@ -141,6 +141,11 @@ func Test_let_varg_fail()
call s:set_varg8([0])
endfunction
+func Test_let_utf8_environment()
+ let $a = 'ĀĒĪŌŪあいうえお'
+ call assert_equal('ĀĒĪŌŪあいうえお', $a)
+endfunc
+
func Test_let_heredoc_fails()
call assert_fails('let v =<< marker', 'E991:')
@@ -284,4 +289,12 @@ E
END
endif
call assert_equal([], check)
+
+ " unpack assignment
+ let [a, b, c] =<< END
+ x
+ \y
+ z
+END
+ call assert_equal([' x', ' \y', ' z'], [a, b, c])
endfunc
diff --git a/src/nvim/testdir/test_spell.vim b/src/nvim/testdir/test_spell.vim
index e49b5542fa..9dce87774b 100644
--- a/src/nvim/testdir/test_spell.vim
+++ b/src/nvim/testdir/test_spell.vim
@@ -283,9 +283,9 @@ func Test_zz_affix()
\ ])
call LoadAffAndDic(g:test_data_aff7, g:test_data_dic7)
- call RunGoodBad("meea1 meea\xE9 bar prebar barmeat prebarmeat leadprebar lead tail leadtail leadmiddletail",
+ call RunGoodBad("meea1 meezero meea\xE9 bar prebar barmeat prebarmeat leadprebar lead tail leadtail leadmiddletail",
\ "bad: mee meea2 prabar probarmaat middle leadmiddle middletail taillead leadprobar",
- \ ["bar", "barmeat", "lead", "meea1", "meea\xE9", "prebar", "prebarmeat", "tail"],
+ \ ["bar", "barmeat", "lead", "meea1", "meea\xE9", "meezero", "prebar", "prebarmeat", "tail"],
\ [
\ ["bad", ["bar", "lead", "tail"]],
\ ["mee", ["meea1", "meea\xE9", "bar"]],
@@ -713,6 +713,9 @@ let g:test_data_aff7 = [
\"SFX 61003 Y 1",
\"SFX 61003 0 meat .",
\"",
+ \"SFX 0 Y 1",
+ \"SFX 0 0 zero .",
+ \"",
\"SFX 391 Y 1",
\"SFX 391 0 a1 .",
\"",
@@ -724,7 +727,7 @@ let g:test_data_aff7 = [
\ ]
let g:test_data_dic7 = [
\"1234",
- \"mee/391,111,9999",
+ \"mee/0,391,111,9999",
\"bar/17,61003,123",
\"lead/2",
\"tail/123",
diff --git a/src/nvim/testdir/test_vimscript.vim b/src/nvim/testdir/test_vimscript.vim
index 3fcba4134e..d2f13ff072 100644
--- a/src/nvim/testdir/test_vimscript.vim
+++ b/src/nvim/testdir/test_vimscript.vim
@@ -1284,7 +1284,7 @@ func s:DoNothing()
endfunc
func Test_script_local_func()
- set nocp viminfo+=nviminfo
+ set nocp nomore viminfo+=nviminfo
new
nnoremap <buffer> _x :call <SID>DoNothing()<bar>call <SID>DoLast()<bar>delfunc <SID>DoNothing<bar>delfunc <SID>DoLast<cr>
diff --git a/test/functional/terminal/scrollback_spec.lua b/test/functional/terminal/scrollback_spec.lua
index 060f065bfc..1df8df6f6e 100644
--- a/test/functional/terminal/scrollback_spec.lua
+++ b/test/functional/terminal/scrollback_spec.lua
@@ -449,7 +449,7 @@ describe("'scrollback' option", function()
38: line |
39: line |
40: line |
- {IGNORE}|
+ {MATCH:.*}|
{3:-- TERMINAL --} |
]]}
end
diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua
index 831d3939df..676d6ef76d 100644
--- a/test/functional/terminal/tui_spec.lua
+++ b/test/functional/terminal/tui_spec.lua
@@ -302,6 +302,49 @@ describe('TUI', function()
expect_child_buf_lines({''})
end)
+ it('paste: select-mode', function()
+ feed_data('ithis is line 1\nthis is line 2\nline 3 is here\n\027')
+ wait_for_mode('n')
+ screen:expect{grid=[[
+ this is line 1 |
+ this is line 2 |
+ line 3 is here |
+ {1: } |
+ {5:[No Name] [+] }|
+ |
+ {3:-- TERMINAL --} |
+ ]]}
+ -- Select-mode. Use <C-n> to move down.
+ feed_data('gg04lgh\14\14')
+ wait_for_mode('s')
+ feed_data('\027[200~')
+ feed_data('just paste it™')
+ feed_data('\027[201~')
+ screen:expect{grid=[[
+ thisjust paste it™{1:3} is here |
+ |
+ {4:~ }|
+ {4:~ }|
+ {5:[No Name] [+] }|
+ |
+ {3:-- TERMINAL --} |
+ ]]}
+ -- Undo.
+ feed_data('u')
+ expect_child_buf_lines{
+ 'this is line 1',
+ 'this is line 2',
+ 'line 3 is here',
+ '',
+ }
+ -- Redo.
+ feed_data('\18') -- <C-r>
+ expect_child_buf_lines{
+ 'thisjust paste it™3 is here',
+ '',
+ }
+ end)
+
it('paste: terminal mode', function()
feed_data(':set statusline=^^^^^^^\n')
feed_data(':terminal '..nvim_dir..'/tty-test\n')
@@ -535,7 +578,7 @@ describe('TUI', function()
|
{4:~ }|
{5: }|
- {8:paste: Error executing lua: vim.lua:211: Vim:E21: }|
+ {MATCH:paste: Error executing lua: vim.lua:%d+: Vim:E21: }|
{8:Cannot make changes, 'modifiable' is off} |
{10:Press ENTER or type command to continue}{1: } |
{3:-- TERMINAL --} |
diff --git a/test/functional/ui/messages_spec.lua b/test/functional/ui/messages_spec.lua
index d16559bab2..8ad3aff21f 100644
--- a/test/functional/ui/messages_spec.lua
+++ b/test/functional/ui/messages_spec.lua
@@ -122,7 +122,7 @@ describe('ui/ext_messages', function()
feed('G$x')
screen:expect{grid=[[
line 1 |
- {IGNORE}|
+ {MATCH:.*}|
{1:~ }|
{1:~ }|
{1:~ }|
@@ -966,7 +966,7 @@ describe('ui/ext_messages', function()
{1:~ }|
{1:~ }|
{1:~ }|
- {IGNORE}|
+ {MATCH:.*}|
{1:~ }|
{1:~ }Nvim is open source and freely distributable{1: }|
{1:~ }https://neovim.io/#chat{1: }|
@@ -976,8 +976,8 @@ describe('ui/ext_messages', function()
{1:~ }type :q{5:<Enter>} to exit {1: }|
{1:~ }type :help{5:<Enter>} for help {1: }|
{1:~ }|
- {IGNORE}|
- {IGNORE}|
+ {MATCH:.*}|
+ {MATCH:.*}|
{1:~ }|
{1:~ }|
{1:~ }|
@@ -1022,7 +1022,7 @@ describe('ui/ext_messages', function()
|
|
|
- {IGNORE}|
+ {MATCH:.*}|
|
Nvim is open source and freely distributable |
https://neovim.io/#chat |
@@ -1032,8 +1032,8 @@ describe('ui/ext_messages', function()
type :q{5:<Enter>} to exit |
type :help{5:<Enter>} for help |
|
- {IGNORE}|
- {IGNORE}|
+ {MATCH:.*}|
+ {MATCH:.*}|
|
|
|
diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua
index 41e022791e..d3f78bf77b 100644
--- a/test/functional/ui/screen.lua
+++ b/test/functional/ui/screen.lua
@@ -269,7 +269,7 @@ local ext_keys = {
-- grid: Expected screen state (string). Each line represents a screen
-- row. Last character of each row (typically "|") is stripped.
-- Common indentation is stripped.
--- Lines containing only "{IGNORE}|" are skipped.
+-- "{MATCH:x}|" lines are matched against Lua pattern `x`.
-- attr_ids: Expected text attributes. Screen rows are transformed according
-- to this table, as follows: each substring S composed of
-- characters having the same attributes will be substituted by
@@ -390,9 +390,10 @@ function Screen:expect(expected, attr_ids, ...)
err_msg = "Expected screen height " .. #expected_rows
.. ' differs from actual height ' .. #actual_rows .. '.'
end
- for i = 1, #expected_rows do
- msg_expected_rows[i] = expected_rows[i]
- if expected_rows[i] ~= actual_rows[i] and expected_rows[i] ~= "{IGNORE}|" then
+ for i, row in ipairs(expected_rows) do
+ msg_expected_rows[i] = row
+ local m = (row ~= actual_rows[i] and row:match('{MATCH:(.*)}') or nil)
+ if row ~= actual_rows[i] and (not m or not actual_rows[i]:match(m)) then
msg_expected_rows[i] = '*' .. msg_expected_rows[i]
if i <= #actual_rows then
actual_rows[i] = '*' .. actual_rows[i]