aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/api/buffer.c14
-rw-r--r--src/nvim/buffer.c2
-rw-r--r--src/nvim/change.c4
-rw-r--r--src/nvim/decoration.c57
-rw-r--r--src/nvim/decoration.h17
-rw-r--r--src/nvim/edit.c2
-rw-r--r--src/nvim/eval/userfunc.c11
-rw-r--r--src/nvim/ex_cmds.c11
-rw-r--r--src/nvim/ex_cmds.lua6
-rw-r--r--src/nvim/ex_docmd.c1
-rw-r--r--src/nvim/ex_eval.c9
-rw-r--r--src/nvim/extmark.c1
-rw-r--r--src/nvim/fileio.c8
-rw-r--r--src/nvim/normal.c4
-rw-r--r--src/nvim/os/time.c1
-rw-r--r--src/nvim/screen.c17
-rw-r--r--src/nvim/search.c9
-rw-r--r--src/nvim/syntax.c18
-rw-r--r--src/nvim/tag.c4
-rw-r--r--src/nvim/testdir/test_autocmd.vim14
-rw-r--r--src/nvim/testdir/test_backspace_opt.vim20
-rw-r--r--src/nvim/testdir/test_expr.vim9
-rw-r--r--src/nvim/testdir/test_filetype.vim2
-rw-r--r--src/nvim/testdir/test_functions.vim16
-rw-r--r--src/nvim/testdir/test_syntax.vim45
25 files changed, 198 insertions, 104 deletions
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c
index c55dc39605..e79a7a2de2 100644
--- a/src/nvim/api/buffer.c
+++ b/src/nvim/api/buffer.c
@@ -1437,6 +1437,10 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id,
/// default
/// - "combine": combine with background text color
/// - "blend": blend with background text color.
+/// - hl_eol : when true, for a multiline highlight covering the
+/// EOL of a line, continue the highlight for the rest
+/// of the screen line (just like for diff and
+/// cursorline highlight).
///
/// - ephemeral : for use with |nvim_set_decoration_provider|
/// callbacks. The mark will only be used for the current
@@ -1581,6 +1585,11 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
if (ERROR_SET(err)) {
goto error;
}
+ } else if (strequal("hl_eol", k.data)) {
+ decor.hl_eol = api_object_to_bool(*v, "hl_eol", false, err);
+ if (ERROR_SET(err)) {
+ goto error;
+ }
} else if (strequal("hl_mode", k.data)) {
if (v->type != kObjectTypeString) {
api_set_error(err, kErrorTypeValidation,
@@ -1669,7 +1678,8 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
if (ephemeral) {
d = &decor;
} else if (kv_size(decor.virt_text)
- || decor.priority != DECOR_PRIORITY_BASE) {
+ || decor.priority != DECOR_PRIORITY_BASE
+ || decor.hl_eol) {
// TODO(bfredl): this is a bit sketchy. eventually we should
// have predefined decorations for both marks/ephemerals
d = xcalloc(1, sizeof(*d));
@@ -1680,7 +1690,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
// TODO(bfredl): synergize these two branches even more
if (ephemeral && decor_state.buf == buf) {
- decor_add_ephemeral((int)line, (int)col, line2, col2, &decor, 0);
+ decor_add_ephemeral((int)line, (int)col, line2, col2, &decor);
} else {
if (ephemeral) {
api_set_error(err, kErrorTypeException, "not yet implemented");
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index c98f2786c2..ce4163fccf 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -1844,7 +1844,7 @@ buf_T *buflist_new(char_u *ffname_arg, char_u *sfname_arg, linenr_T lnum,
EMSG(_("W14: Warning: List of file names overflow"));
if (emsg_silent == 0) {
ui_flush();
- os_delay(3000L, true); // make sure it is noticed
+ os_delay(3001L, true); // make sure it is noticed
}
top_file_num = 1;
}
diff --git a/src/nvim/change.c b/src/nvim/change.c
index 38bd591eca..74e27ca880 100644
--- a/src/nvim/change.c
+++ b/src/nvim/change.c
@@ -68,7 +68,7 @@ void change_warning(int col)
(void)msg_end();
if (msg_silent == 0 && !silent_mode && ui_active()) {
ui_flush();
- os_delay(1000L, true); // give the user time to think about it
+ os_delay(1002L, true); // give the user time to think about it
}
curbuf->b_did_warn = true;
redraw_cmdline = false; // don't redraw and erase the message
@@ -109,7 +109,7 @@ void changed(void)
// and don't let the emsg() set msg_scroll.
if (need_wait_return && emsg_silent == 0) {
ui_flush();
- os_delay(2000L, true);
+ os_delay(2002L, true);
wait_return(true);
msg_scroll = save_msg_scroll;
} else {
diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c
index 52a48ae6fb..e39d2328f5 100644
--- a/src/nvim/decoration.c
+++ b/src/nvim/decoration.c
@@ -144,9 +144,9 @@ bool decor_redraw_reset(buf_T *buf, DecorState *state)
state->row = -1;
state->buf = buf;
for (size_t i = 0; i < kv_size(state->active); i++) {
- HlRange item = kv_A(state->active, i);
+ DecorRange item = kv_A(state->active, i);
if (item.virt_text_owned) {
- clear_virttext(&item.virt_text);
+ clear_virttext(&item.decor.virt_text);
}
}
kv_size(state->active) = 0;
@@ -190,14 +190,14 @@ bool decor_redraw_start(buf_T *buf, int top_row, DecorState *state)
if (mark.id&MARKTREE_END_FLAG) {
decor_add(state, altpos.row, altpos.col, mark.row, mark.col,
- decor, false, 0);
+ decor, false);
} else {
if (altpos.row == -1) {
altpos.row = mark.row;
altpos.col = mark.col;
}
decor_add(state, mark.row, mark.col, altpos.row, altpos.col,
- decor, false, 0);
+ decor, false);
}
next_mark:
@@ -222,22 +222,19 @@ bool decor_redraw_line(buf_T *buf, int row, DecorState *state)
}
static void decor_add(DecorState *state, int start_row, int start_col,
- int end_row, int end_col, Decoration *decor, bool owned,
- DecorPriority priority)
+ int end_row, int end_col, Decoration *decor, bool owned)
{
int attr_id = decor->hl_id > 0 ? syn_id2attr(decor->hl_id) : 0;
- HlRange range = { start_row, start_col, end_row, end_col,
- attr_id, MAX(priority, decor->priority),
- decor->virt_text,
- decor->virt_text_pos, decor->virt_text_hide, decor->hl_mode,
+ DecorRange range = { start_row, start_col, end_row, end_col,
+ *decor, attr_id,
kv_size(decor->virt_text) && owned, -1 };
kv_pushp(state->active);
size_t index;
for (index = kv_size(state->active)-1; index > 0; index--) {
- HlRange item = kv_A(state->active, index-1);
- if (item.priority <= range.priority) {
+ DecorRange item = kv_A(state->active, index-1);
+ if (item.decor.priority <= range.decor.priority) {
break;
}
kv_A(state->active, index) = kv_A(state->active, index-1);
@@ -291,7 +288,7 @@ int decor_redraw_col(buf_T *buf, int col, int virt_col, bool hidden,
}
decor_add(state, mark.row, mark.col, endpos.row, endpos.col,
- decor, false, 0);
+ decor, false);
next_mark:
marktree_itr_next(buf->b_marktree, state->itr);
@@ -300,11 +297,11 @@ next_mark:
int attr = 0;
size_t j = 0;
for (size_t i = 0; i < kv_size(state->active); i++) {
- HlRange item = kv_A(state->active, i);
+ DecorRange item = kv_A(state->active, i);
bool active = false, keep = true;
if (item.end_row < state->row
|| (item.end_row == state->row && item.end_col <= col)) {
- if (!(item.start_row >= state->row && kv_size(item.virt_text))) {
+ if (!(item.start_row >= state->row && kv_size(item.decor.virt_text))) {
keep = false;
}
} else {
@@ -324,13 +321,13 @@ next_mark:
attr = hl_combine_attr(attr, item.attr_id);
}
if ((item.start_row == state->row && item.start_col <= col)
- && kv_size(item.virt_text) && item.virt_col == -1) {
- item.virt_col = (item.virt_text_hide && hidden) ? -2 : virt_col;
+ && kv_size(item.decor.virt_text) && item.virt_col == -1) {
+ item.virt_col = (item.decor.virt_text_hide && hidden) ? -2 : virt_col;
}
if (keep) {
kv_A(state->active, j++) = item;
} else if (item.virt_text_owned) {
- clear_virttext(&item.virt_text);
+ clear_virttext(&item.decor.virt_text);
}
}
kv_size(state->active) = j;
@@ -343,28 +340,34 @@ void decor_redraw_end(DecorState *state)
state->buf = NULL;
}
-VirtText decor_redraw_virt_text(buf_T *buf, DecorState *state)
+VirtText decor_redraw_eol(buf_T *buf, DecorState *state, int *eol_attr)
{
decor_redraw_col(buf, MAXCOL, MAXCOL, false, state);
+ VirtText text = VIRTTEXT_EMPTY;
for (size_t i = 0; i < kv_size(state->active); i++) {
- HlRange item = kv_A(state->active, i);
- if (item.start_row == state->row && kv_size(item.virt_text)
- && item.virt_text_pos == kVTEndOfLine) {
- return item.virt_text;
+ DecorRange item = kv_A(state->active, i);
+ if (!kv_size(text)
+ && item.start_row == state->row && kv_size(item.decor.virt_text)
+ && item.decor.virt_text_pos == kVTEndOfLine) {
+ text = item.decor.virt_text;
+ }
+
+ if (item.decor.hl_eol && item.start_row <= state->row) {
+ *eol_attr = hl_combine_attr(*eol_attr, item.attr_id);
}
}
- return VIRTTEXT_EMPTY;
+
+ return text;
}
void decor_add_ephemeral(int start_row, int start_col, int end_row, int end_col,
- Decoration *decor, DecorPriority priority)
+ Decoration *decor)
{
if (end_row == -1) {
end_row = start_row;
end_col = start_col;
}
- decor_add(&decor_state, start_row, start_col, end_row, end_col, decor, true,
- priority);
+ decor_add(&decor_state, start_row, start_col, end_row, end_col, decor, true);
}
diff --git a/src/nvim/decoration.h b/src/nvim/decoration.h
index c5424a1642..08d69060f0 100644
--- a/src/nvim/decoration.h
+++ b/src/nvim/decoration.h
@@ -37,33 +37,28 @@ struct Decoration
VirtTextPos virt_text_pos;
bool virt_text_hide;
HlMode hl_mode;
+ bool hl_eol;
// TODO(bfredl): style, signs, etc
DecorPriority priority;
bool shared; // shared decoration, don't free
};
#define DECORATION_INIT { 0, KV_INITIAL_VALUE, kVTEndOfLine, false, \
- kHlModeUnknown, DECOR_PRIORITY_BASE, false }
+ kHlModeUnknown, false, DECOR_PRIORITY_BASE, false }
typedef struct {
int start_row;
int start_col;
int end_row;
int end_col;
- int attr_id;
- // TODO(bfredl): embed decoration instead, perhaps using an arena
- // for ephemerals?
- DecorPriority priority;
- VirtText virt_text;
- VirtTextPos virt_text_pos;
- bool virt_text_hide;
- HlMode hl_mode;
+ Decoration decor;
+ int attr_id; // cached lookup of decor.hl_id
bool virt_text_owned;
int virt_col;
-} HlRange;
+} DecorRange;
typedef struct {
MarkTreeIter itr[1];
- kvec_t(HlRange) active;
+ kvec_t(DecorRange) active;
buf_T *buf;
int top_row;
int row;
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index ea13052f25..f2fddc89fe 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -2058,7 +2058,7 @@ static bool check_compl_option(bool dict_opt)
vim_beep(BO_COMPL);
setcursor();
ui_flush();
- os_delay(2000L, false);
+ os_delay(2004L, false);
}
return false;
}
diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c
index 689d05e079..00260bc3f7 100644
--- a/src/nvim/eval/userfunc.c
+++ b/src/nvim/eval/userfunc.c
@@ -833,6 +833,8 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars,
bool islambda = false;
char_u numbuf[NUMBUFLEN];
char_u *name;
+ typval_T *tv_to_free[MAX_FUNC_ARGS];
+ int tv_to_free_len = 0;
proftime_T wait_start;
proftime_T call_start;
int started_profiling = false;
@@ -985,6 +987,11 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars,
v->di_tv = isdefault ? def_rettv : argvars[i];
v->di_tv.v_lock = VAR_FIXED;
+ if (isdefault) {
+ // Need to free this later, no matter where it's stored.
+ tv_to_free[tv_to_free_len++] = &v->di_tv;
+ }
+
if (addlocal) {
// Named arguments can be accessed without the "a:" prefix in lambda
// expressions. Add to the l: dict.
@@ -1209,7 +1216,9 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars,
did_emsg |= save_did_emsg;
depth--;
-
+ for (int i = 0; i < tv_to_free_len; i++) {
+ tv_clear(tv_to_free[i]);
+ }
cleanup_function_call(fc);
if (--fp->uf_calls <= 0 && fp->uf_refcount <= 0) {
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index b191e8cf67..3e330b88a2 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -968,12 +968,6 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest)
mark_adjust_nofold(last_line - num_lines + 1, last_line,
-(last_line - dest - extra), 0L, kExtmarkNOOP);
- // extmarks are handled separately
- extmark_move_region(curbuf, line1-1, 0, start_byte,
- line2-line1+1, 0, extent_byte,
- dest+line_off, 0, dest_byte+byte_off,
- kExtmarkUndo);
-
changed_lines(last_line - num_lines + 1, 0, last_line + 1, -extra, false);
// send update regarding the new lines that were added
@@ -995,6 +989,11 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest)
smsg(_("%" PRId64 " lines moved"), (int64_t)num_lines);
}
+ extmark_move_region(curbuf, line1-1, 0, start_byte,
+ line2-line1+1, 0, extent_byte,
+ dest+line_off, 0, dest_byte+byte_off,
+ kExtmarkUndo);
+
/*
* Leave the cursor on the last of the moved lines.
*/
diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua
index 2965ea7496..d99383303b 100644
--- a/src/nvim/ex_cmds.lua
+++ b/src/nvim/ex_cmds.lua
@@ -928,6 +928,12 @@ module.cmds = {
func='ex_edit',
},
{
+ command='eval',
+ flags=bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN),
+ addr_type='ADDR_NONE',
+ func='ex_eval',
+ },
+ {
command='ex',
flags=bit.bor(BANG, FILE1, CMDARG, ARGOPT, TRLBAR),
addr_type='ADDR_NONE',
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index d1eddfc74f..ae5c334592 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -1857,6 +1857,7 @@ static char_u * do_one_cmd(char_u **cmdlinep,
case CMD_echoerr:
case CMD_echomsg:
case CMD_echon:
+ case CMD_eval:
case CMD_execute:
case CMD_filter:
case CMD_help:
diff --git a/src/nvim/ex_eval.c b/src/nvim/ex_eval.c
index 0917c6dd02..5ca88002f1 100644
--- a/src/nvim/ex_eval.c
+++ b/src/nvim/ex_eval.c
@@ -788,6 +788,15 @@ void report_discard_pending(int pending, void *value)
}
}
+// ":eval".
+void ex_eval(exarg_T *eap)
+{
+ typval_T tv;
+
+ if (eval0(eap->arg, &tv, &eap->nextcmd, !eap->skip) == OK) {
+ tv_clear(&tv);
+ }
+}
/*
* ":if".
diff --git a/src/nvim/extmark.c b/src/nvim/extmark.c
index cacbeddb32..2906a2196b 100644
--- a/src/nvim/extmark.c
+++ b/src/nvim/extmark.c
@@ -702,6 +702,7 @@ void extmark_move_region(
int new_row, colnr_T new_col, bcount_t new_byte,
ExtmarkOp undo)
{
+ curbuf->deleted_bytes2 = 0;
// TODO(bfredl): this is not synced to the buffer state inside the callback.
// But unless we make the undo implementation smarter, this is not ensured
// anyway.
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index 65bd809436..792ef81665 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -4947,11 +4947,11 @@ int buf_check_timestamp(buf_T *buf)
(void)msg_end();
if (emsg_silent == 0) {
ui_flush();
- /* give the user some time to think about it */
- os_delay(1000L, true);
+ // give the user some time to think about it
+ os_delay(1004L, true);
- /* don't redraw and erase the message */
- redraw_cmdline = FALSE;
+ // don't redraw and erase the message
+ redraw_cmdline = false;
}
}
already_warned = TRUE;
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index f016ef6813..c948881eca 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -630,9 +630,9 @@ static void normal_redraw_mode_message(NormalState *s)
ui_cursor_shape(); // show different cursor shape
ui_flush();
if (msg_scroll || emsg_on_display) {
- os_delay(1000L, true); // wait at least one second
+ os_delay(1003L, true); // wait at least one second
}
- os_delay(3000L, false); // wait up to three seconds
+ os_delay(3003L, false); // wait up to three seconds
State = save_State;
msg_scroll = false;
diff --git a/src/nvim/os/time.c b/src/nvim/os/time.c
index e7e0dc4013..9ea74716aa 100644
--- a/src/nvim/os/time.c
+++ b/src/nvim/os/time.c
@@ -62,6 +62,7 @@ uint64_t os_now(void)
/// @param ignoreinput If true, only SIGINT (CTRL-C) can interrupt.
void os_delay(uint64_t ms, bool ignoreinput)
{
+ DLOG("%" PRIu64 " ms", ms);
if (ignoreinput) {
if (ms > INT_MAX) {
ms = INT_MAX;
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index 9fb2eb2772..6be3b6fb60 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -3951,7 +3951,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
.hl_id = hl_err }));
do_virttext = true;
} else if (has_decor) {
- virt_text = decor_redraw_virt_text(wp->w_buffer, &decor_state);
+ virt_text = decor_redraw_eol(wp->w_buffer, &decor_state, &line_attr);
if (kv_size(virt_text)) {
do_virttext = true;
}
@@ -4381,11 +4381,12 @@ void draw_virt_text(buf_T *buf, int *end_col, int max_col)
{
DecorState *state = &decor_state;
for (size_t i = 0; i < kv_size(state->active); i++) {
- HlRange *item = &kv_A(state->active, i);
- if (item->start_row == state->row && kv_size(item->virt_text)
- && item->virt_text_pos == kVTOverlay
+ DecorRange *item = &kv_A(state->active, i);
+ if (item->start_row == state->row && kv_size(item->decor.virt_text)
+ && item->decor.virt_text_pos == kVTOverlay
&& item->virt_col >= 0) {
- VirtText vt = item->virt_text;
+ VirtText vt = item->decor.virt_text;
+ HlMode hl_mode = item->decor.hl_mode;
LineState s = LINE_STATE("");
int virt_attr = 0;
int col = item->virt_col;
@@ -4405,9 +4406,9 @@ void draw_virt_text(buf_T *buf, int *end_col, int max_col)
}
int attr;
bool through = false;
- if (item->hl_mode == kHlModeCombine) {
+ if (hl_mode == kHlModeCombine) {
attr = hl_combine_attr(linebuf_attr[col], virt_attr);
- } else if (item->hl_mode == kHlModeBlend) {
+ } else if (hl_mode == kHlModeBlend) {
through = (*s.p == ' ');
attr = hl_blend_attrs(linebuf_attr[col], virt_attr, &through);
} else {
@@ -6226,7 +6227,7 @@ void check_for_delay(int check_msg_scroll)
&& !did_wait_return
&& emsg_silent == 0) {
ui_flush();
- os_delay(1000L, true);
+ os_delay(1006L, true);
emsg_on_display = false;
if (check_msg_scroll) {
msg_scroll = false;
diff --git a/src/nvim/search.c b/src/nvim/search.c
index c4479a077e..abe05bbd12 100644
--- a/src/nvim/search.c
+++ b/src/nvim/search.c
@@ -2373,10 +2373,11 @@ showmatch(
* brief pause, unless 'm' is present in 'cpo' and a character is
* available.
*/
- if (vim_strchr(p_cpo, CPO_SHOWMATCH) != NULL)
- os_delay(p_mat * 100L, true);
- else if (!char_avail())
- os_delay(p_mat * 100L, false);
+ if (vim_strchr(p_cpo, CPO_SHOWMATCH) != NULL) {
+ os_delay(p_mat * 100L + 8, true);
+ } else if (!char_avail()) {
+ os_delay(p_mat * 100L + 9, false);
+ }
curwin->w_cursor = save_cursor; // restore cursor position
*so = save_so;
*siso = save_siso;
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index 825aef1465..77a751e5ad 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -5306,13 +5306,17 @@ get_id_list(
xfree(name);
break;
}
- if (name[1] == 'A')
- id = SYNID_ALLBUT;
- else if (name[1] == 'T')
- id = SYNID_TOP;
- else
- id = SYNID_CONTAINED;
- id += current_syn_inc_tag;
+ if (name[1] == 'A') {
+ id = SYNID_ALLBUT + current_syn_inc_tag;
+ } else if (name[1] == 'T') {
+ if (curwin->w_s->b_syn_topgrp >= SYNID_CLUSTER) {
+ id = curwin->w_s->b_syn_topgrp;
+ } else {
+ id = SYNID_TOP + current_syn_inc_tag;
+ }
+ } else {
+ id = SYNID_CONTAINED + current_syn_inc_tag;
+ }
} else if (name[1] == '@') {
if (skip) {
id = -1;
diff --git a/src/nvim/tag.c b/src/nvim/tag.c
index 588821f260..a6310344e9 100644
--- a/src/nvim/tag.c
+++ b/src/nvim/tag.c
@@ -625,7 +625,7 @@ do_tag(
}
if (ic && !msg_scrolled && msg_silent == 0) {
ui_flush();
- os_delay(1000L, true);
+ os_delay(1007L, true);
}
}
@@ -2853,7 +2853,7 @@ static int jumpto_tag(
MSG(_("E435: Couldn't find tag, just guessing!"));
if (!msg_scrolled && msg_silent == 0) {
ui_flush();
- os_delay(1000L, true);
+ os_delay(1010L, true);
}
}
retval = OK;
diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim
index 5e99edf233..5611560b1b 100644
--- a/src/nvim/testdir/test_autocmd.vim
+++ b/src/nvim/testdir/test_autocmd.vim
@@ -276,28 +276,28 @@ func Test_augroup_warning()
augroup TheWarning
au VimEnter * echo 'entering'
augroup END
- call assert_true(match(execute('au VimEnter'), "TheWarning.*VimEnter") >= 0)
+ call assert_match("TheWarning.*VimEnter", execute('au VimEnter'))
redir => res
augroup! TheWarning
redir END
- call assert_true(match(res, "W19:") >= 0)
- call assert_true(match(execute('au VimEnter'), "-Deleted-.*VimEnter") >= 0)
+ call assert_match("W19:", res)
+ call assert_match("-Deleted-.*VimEnter", execute('au VimEnter'))
" check "Another" does not take the pace of the deleted entry
augroup Another
augroup END
- call assert_true(match(execute('au VimEnter'), "-Deleted-.*VimEnter") >= 0)
+ call assert_match("-Deleted-.*VimEnter", execute('au VimEnter'))
augroup! Another
" no warning for postpone aucmd delete
augroup StartOK
au VimEnter * call RemoveGroup()
augroup END
- call assert_true(match(execute('au VimEnter'), "StartOK.*VimEnter") >= 0)
+ call assert_match("StartOK.*VimEnter", execute('au VimEnter'))
redir => res
doautocmd VimEnter
redir END
- call assert_true(match(res, "W19:") < 0)
+ call assert_notmatch("W19:", res)
au! VimEnter
endfunc
@@ -325,7 +325,7 @@ func Test_augroup_deleted()
au VimEnter * echo
augroup end
augroup! x
- call assert_true(match(execute('au VimEnter'), "-Deleted-.*VimEnter") >= 0)
+ call assert_match("-Deleted-.*VimEnter", execute('au VimEnter'))
au! VimEnter
endfunc
diff --git a/src/nvim/testdir/test_backspace_opt.vim b/src/nvim/testdir/test_backspace_opt.vim
index d680b442db..11459991ea 100644
--- a/src/nvim/testdir/test_backspace_opt.vim
+++ b/src/nvim/testdir/test_backspace_opt.vim
@@ -1,15 +1,5 @@
" Tests for 'backspace' settings
-func Exec(expr)
- let str=''
- try
- exec a:expr
- catch /.*/
- let str=v:exception
- endtry
- return str
-endfunc
-
func Test_backspace_option()
set backspace=
call assert_equal('', &backspace)
@@ -41,10 +31,10 @@ func Test_backspace_option()
set backspace-=eol
call assert_equal('', &backspace)
" Check the error
- call assert_equal(0, match(Exec('set backspace=ABC'), '.*E474'))
- call assert_equal(0, match(Exec('set backspace+=def'), '.*E474'))
+ call assert_fails('set backspace=ABC', 'E474:')
+ call assert_fails('set backspace+=def', 'E474:')
" NOTE: Vim doesn't check following error...
- "call assert_equal(0, match(Exec('set backspace-=ghi'), '.*E474'))
+ "call assert_fails('set backspace-=ghi', 'E474:')
" Check backwards compatibility with version 5.4 and earlier
set backspace=0
@@ -55,8 +45,8 @@ func Test_backspace_option()
call assert_equal('2', &backspace)
set backspace=3
call assert_equal('3', &backspace)
- call assert_false(match(Exec('set backspace=4'), '.*E474'))
- call assert_false(match(Exec('set backspace=10'), '.*E474'))
+ call assert_fails('set backspace=4', 'E474:')
+ call assert_fails('set backspace=10', 'E474:')
" Cleared when 'compatible' is set
" set compatible
diff --git a/src/nvim/testdir/test_expr.vim b/src/nvim/testdir/test_expr.vim
index 09d79979ce..0b41a1127a 100644
--- a/src/nvim/testdir/test_expr.vim
+++ b/src/nvim/testdir/test_expr.vim
@@ -501,3 +501,12 @@ func Test_empty_concatenate()
call assert_equal('b', 'a'[4:0] . 'b')
call assert_equal('b', 'b' . 'a'[4:0])
endfunc
+
+func Test_eval_after_if()
+ let s:val = ''
+ func SetVal(x)
+ let s:val ..= a:x
+ endfunc
+ if 0 | eval SetVal('a') | endif | call SetVal('b')
+ call assert_equal('b', s:val)
+endfunc
diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim
index 1a98dc6451..bd2e673570 100644
--- a/src/nvim/testdir/test_filetype.vim
+++ b/src/nvim/testdir/test_filetype.vim
@@ -275,6 +275,8 @@ let s:filename_checks = {
\ 'lss': ['file.lss'],
\ 'lua': ['file.lua', 'file.rockspec', 'file.nse'],
\ 'lynx': ['lynx.cfg'],
+ \ 'm3build': ['m3makefile', 'm3overrides'],
+ \ 'm3quake': ['file.quake', 'cm3.cfg'],
\ 'm4': ['file.at'],
\ 'mail': ['snd.123', '.letter', '.letter.123', '.followup', '.article', '.article.123', 'pico.123', 'mutt-xx-xxx', 'muttng-xx-xxx', 'ae123.txt', 'file.eml'],
\ 'mailaliases': ['/etc/mail/aliases', '/etc/aliases'],
diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim
index 555f549743..93f567b3a0 100644
--- a/src/nvim/testdir/test_functions.vim
+++ b/src/nvim/testdir/test_functions.vim
@@ -1071,10 +1071,10 @@ func Test_inputlist()
endfunc
func Test_balloon_show()
- if has('balloon_eval')
- " This won't do anything but must not crash either.
- call balloon_show('hi!')
- endif
+ CheckFeature balloon_eval
+
+ " This won't do anything but must not crash either.
+ call balloon_show('hi!')
endfunc
func Test_shellescape()
@@ -1448,4 +1448,12 @@ func Test_nr2char()
call assert_equal("\x80\xfc\b\xfd\x80\xfeX\x80\xfeX\x80\xfeX\x80\xfeX\x80\xfeX", eval('"\<M-' .. nr2char(0x40000000) .. '>"'))
endfunc
+func HasDefault(msg = 'msg')
+ return a:msg
+endfunc
+
+func Test_default_arg_value()
+ call assert_equal('msg', HasDefault())
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_syntax.vim b/src/nvim/testdir/test_syntax.vim
index 66cb0bbe22..875e23894f 100644
--- a/src/nvim/testdir/test_syntax.vim
+++ b/src/nvim/testdir/test_syntax.vim
@@ -24,6 +24,32 @@ func GetSyntaxItem(pat)
return c
endfunc
+func AssertHighlightGroups(lnum, startcol, expected, trans = 1, msg = "")
+ " Assert that the characters starting at a given (line, col)
+ " sequentially match the expected highlight groups.
+ " If groups are provided as a string, each character is assumed to be a
+ " group and spaces represent no group, useful for visually describing tests.
+ let l:expectedGroups = type(a:expected) == v:t_string
+ "\ ? a:expected->split('\zs')->map({_, v -> trim(v)})
+ \ ? map(split(a:expected, '\zs'), {_, v -> trim(v)})
+ \ : a:expected
+ let l:errors = 0
+ " let l:msg = (a:msg->empty() ? "" : a:msg .. ": ")
+ let l:msg = (empty(a:msg) ? "" : a:msg .. ": ")
+ \ .. "Wrong highlight group at " .. a:lnum .. ","
+
+ " for l:i in range(a:startcol, a:startcol + l:expectedGroups->len() - 1)
+ " let l:errors += synID(a:lnum, l:i, a:trans)
+ " \ ->synIDattr("name")
+ " \ ->assert_equal(l:expectedGroups[l:i - 1],
+ for l:i in range(a:startcol, a:startcol + len(l:expectedGroups) - 1)
+ let l:errors +=
+ \ assert_equal(synIDattr(synID(a:lnum, l:i, a:trans), "name"),
+ \ l:expectedGroups[l:i - 1],
+ \ l:msg .. l:i)
+ endfor
+endfunc
+
func Test_syn_iskeyword()
new
call setline(1, [
@@ -707,3 +733,22 @@ func Test_syntax_foldlevel()
quit!
endfunc
+
+func Test_syn_include_contains_TOP()
+ let l:case = "TOP in included syntax means its group list name"
+ new
+ syntax include @INCLUDED syntax/c.vim
+ syntax region FencedCodeBlockC start=/```c/ end=/```/ contains=@INCLUDED
+
+ call setline(1, ['```c', '#if 0', 'int', '#else', 'int', '#endif', '```' ])
+ let l:expected = ["cCppOutIf2"]
+ eval AssertHighlightGroups(3, 1, l:expected, 1)
+ " cCppOutElse has contains=TOP
+ let l:expected = ["cType"]
+ eval AssertHighlightGroups(5, 1, l:expected, 1, l:case)
+ syntax clear
+ bw!
+endfunc
+
+
+" vim: shiftwidth=2 sts=2 expandtab