aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/ui.txt36
-rw-r--r--src/nvim/api/ui_events.in.h2
-rw-r--r--src/nvim/buffer.c38
-rw-r--r--src/nvim/ex_cmds.c249
-rw-r--r--src/nvim/ex_cmds2.c52
-rw-r--r--src/nvim/ex_getln.c2
-rw-r--r--src/nvim/testdir/Makefile1
-rw-r--r--src/nvim/testdir/test_profile.vim183
-rw-r--r--src/nvim/version.c8
-rw-r--r--test/functional/ui/inccommand_spec.lua832
-rw-r--r--test/functional/ui/tabline_spec.lua57
-rw-r--r--test/functional/ui/wildmode_spec.lua4
-rw-r--r--test/functional/viml/completion_spec.lua2
13 files changed, 1249 insertions, 217 deletions
diff --git a/runtime/doc/ui.txt b/runtime/doc/ui.txt
index 4f0006856e..3644d0784f 100644
--- a/runtime/doc/ui.txt
+++ b/runtime/doc/ui.txt
@@ -28,7 +28,7 @@ a dictionary with these (optional) keys:
`ext_popupmenu` Externalize the popupmenu. |ui-popupmenu|
`ext_tabline` Externalize the tabline. |ui-tabline|
`ext_cmdline` Externalize the cmdline. |ui-cmdline|
- `ext_wildmenu` Externalize the tabline. |ui-ext-wildmenu|
+ `ext_wildmenu` Externalize the wildmenu. |ui-ext-wildmenu|
Nvim will then send msgpack-rpc notifications, with the method name "redraw"
and a single argument, an array of screen update events.
@@ -202,21 +202,21 @@ Popupmenu Events *ui-popupmenu*
Only sent if `ext_popupmenu` option is set in |ui-options|
["popupmenu_show", items, selected, row, col]
- `items` is an array of the items to show, the
- items are themselves arrays of the form [word, kind, menu, info]
- as defined at |complete-items|, except that `word` is replaced by
- `abbr` if present. `selected` is the initially selected item, either a
- zero-based index into the array of items, or -1 if no item is
- selected. `row` and `col` is the anchor position, where the first
- character of the completed word will be.
+ Show |popupmenu-completion|. `items` is an array of completion items
+ to show; each item is an array of the form [word, kind, menu, info] as
+ defined at |complete-items|, except that `word` is replaced by `abbr`
+ if present. `selected` is the initially-selected item, a zero-based
+ index into the array of items (-1 if no item is selected). `row` and
+ `col` give the anchor position, where the first character of the
+ completed word will be.
["popupmenu_select", selected]
- An item in the currently displayed popupmenu is selected. `selected`
- is either a zero-based index into the array of items from the last
- `popupmenu_show` event, or -1 if no item is selected.
+ Select an item in the current popupmenu. `selected` is a zero-based
+ index into the array of items from the last popupmenu_show event, or
+ -1 if no item is selected.
["popupmenu_hide"]
- The popupmenu is hidden.
+ Hide the popupmenu.
==============================================================================
Tabline Events *ui-tabline*
@@ -293,16 +293,16 @@ Wildmenu Events *ui-wildmenu*
Only sent if `ext_wildmenu` option is set in |ui-options|
["wildmenu_show", items]
- Sent when wildmenu (command line completion) is activated.
- `items` is an array with the completion items.
+ Activate the wildmenu (command-line completion). `items` is an array
+ with the completion items.
["wildmenu_select", selected]
- An item in the currently displayed wildmenu is selected. `selected`
- is either a zero-based index into the array of items from the last
- wildmenu event, or -1 if no item is selected.
+ Select an item in the current wildmenu. `selected` is a zero-based
+ index into the array of items from the last wildmenu_show event, or -1
+ if no item is selected.
["wildmenu_hide"]
- The wildmenu is hidden.
+ Hide the wildmenu.
==============================================================================
vim:tw=78:ts=8:noet:ft=help:norl:
diff --git a/src/nvim/api/ui_events.in.h b/src/nvim/api/ui_events.in.h
index 579ba1441a..847b21072a 100644
--- a/src/nvim/api/ui_events.in.h
+++ b/src/nvim/api/ui_events.in.h
@@ -85,7 +85,7 @@ void cmdline_block_append(Array lines)
void cmdline_block_hide(void)
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
-void wildmenu_show(Array content)
+void wildmenu_show(Array items)
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
void wildmenu_select(Integer selected)
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index 9d42fbc1b3..f874268910 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -5278,6 +5278,44 @@ int bufhl_add_hl(buf_T *buf,
return src_id;
}
+/// Add highlighting to a buffer, bounded by two cursor positions,
+/// with an offset.
+///
+/// @param buf Buffer to add highlights to
+/// @param src_id src_id to use or 0 to use a new src_id group,
+/// or -1 for ungrouped highlight.
+/// @param hl_id Highlight group id
+/// @param pos_start Cursor position to start the hightlighting at
+/// @param pos_end Cursor position to end the highlighting at
+/// @param offset Move the whole highlighting this many columns to the right
+void bufhl_add_hl_pos_offset(buf_T *buf,
+ int src_id,
+ int hl_id,
+ lpos_T pos_start,
+ lpos_T pos_end,
+ colnr_T offset)
+{
+ colnr_T hl_start = 0;
+ colnr_T hl_end = 0;
+
+ for (linenr_T lnum = pos_start.lnum; lnum <= pos_end.lnum; lnum ++) {
+ if (pos_start.lnum < lnum && lnum < pos_end.lnum) {
+ hl_start = offset;
+ hl_end = MAXCOL;
+ } else if (lnum == pos_start.lnum && lnum < pos_end.lnum) {
+ hl_start = pos_start.col + offset + 1;
+ hl_end = MAXCOL;
+ } else if (pos_start.lnum < lnum && lnum == pos_end.lnum) {
+ hl_start = offset;
+ hl_end = pos_end.col + offset;
+ } else if (pos_start.lnum == lnum && pos_end.lnum == lnum) {
+ hl_start = pos_start.col + offset + 1;
+ hl_end = pos_end.col + offset;
+ }
+ (void)bufhl_add_hl(buf, src_id, hl_id, lnum, hl_start, hl_end);
+ }
+}
+
/// Clear bufhl highlights from a given source group and range of lines.
///
/// @param buf The buffer to remove highlights from
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 918e7a0c91..112f53247c 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -90,14 +90,20 @@ typedef struct {
SubIgnoreType do_ic; ///< ignore case flag
} subflags_T;
-/// Lines matched during :substitute.
+/// Partial result of a substitution during :substitute.
+/// Numbers refer to the buffer _after_ substitution
typedef struct {
- linenr_T lnum;
- long nmatch;
- char_u *line;
- kvec_t(colnr_T) cols; ///< columns of in-line matches
-} MatchedLine;
-typedef kvec_t(MatchedLine) MatchedLineVec;
+ lpos_T start; // start of the match
+ lpos_T end; // end of the match
+ linenr_T pre_match; // where to begin showing lines before the match
+} SubResult;
+
+// Collected results of a substitution for showing them in
+// the preview window
+typedef struct {
+ kvec_t(SubResult) subresults;
+ linenr_T lines_needed; // lines neede in the preview window
+} PreviewLines;
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "ex_cmds.c.generated.h"
@@ -3168,7 +3174,10 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout)
linenr_T old_line_count = curbuf->b_ml.ml_line_count;
char_u *sub_firstline; // allocated copy of first sub line
bool endcolumn = false; // cursor in last column when done
- MatchedLineVec matched_lines = KV_INITIAL_VALUE;
+ PreviewLines preview_lines = { KV_INITIAL_VALUE, 0 };
+ static int pre_src_id = 0; // Source id for the preview highlight
+ static int pre_hl_id = 0;
+ buf_T *orig_buf = curbuf; // save to reset highlighting
pos_T old_cursor = curwin->w_cursor;
int start_nsubs;
int save_ma = 0;
@@ -3336,7 +3345,7 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout)
linenr_T line2 = eap->line2;
for (linenr_T lnum = eap->line1;
lnum <= line2 && !got_quit && !aborting()
- && (!preview || matched_lines.size < (size_t)p_cwh
+ && (!preview || preview_lines.lines_needed <= (linenr_T)p_cwh
|| lnum <= curwin->w_botline);
lnum++) {
long nmatch = vim_regexec_multi(&regmatch, curwin, curbuf, lnum,
@@ -3401,8 +3410,6 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout)
sub_firstlnum = lnum;
copycol = 0;
matchcol = 0;
- // the current match
- MatchedLine matched_line = { 0, 0, NULL, KV_INITIAL_VALUE };
/* At first match, remember current cursor position. */
if (!got_match) {
@@ -3419,10 +3426,19 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout)
* 5. break if there isn't another match in this line
*/
for (;; ) {
- /* Advance "lnum" to the line where the match starts. The
- * match does not start in the first line when there is a line
- * break before \zs. */
+ SubResult current_match = {
+ .start = { 0, 0 },
+ .end = { 0, 0 },
+ .pre_match = 0,
+ };
+ // lnum is where the match start, but maybe not the pattern match,
+ // since we can have \n before \zs in the pattern
+
+ // Advance "lnum" to the line where the match starts. The
+ // match does not start in the first line when there is a line
+ // break before \zs.
if (regmatch.startpos[0].lnum > 0) {
+ current_match.pre_match = lnum;
lnum += regmatch.startpos[0].lnum;
sub_firstlnum += regmatch.startpos[0].lnum;
nmatch -= regmatch.startpos[0].lnum;
@@ -3430,6 +3446,10 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout)
sub_firstline = NULL;
}
+ // Now we're at the line where the pattern match starts
+ // Note: If not first match on a line, column can't be known here
+ current_match.start.lnum = sub_firstlnum;
+
if (sub_firstline == NULL) {
sub_firstline = vim_strsave(ml_get(sub_firstlnum));
}
@@ -3439,12 +3459,6 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout)
curwin->w_cursor.lnum = lnum;
do_again = FALSE;
- if (preview) {
- // Increment the in-line match count and store the column.
- matched_line.nmatch++;
- kv_push(matched_line.cols, regmatch.startpos[0].col);
- }
-
/*
* 1. Match empty string does not count, except for first
* match. This reproduces the strange vi behaviour.
@@ -3669,6 +3683,7 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout)
// go beyond the last line of the buffer.
if (nmatch > curbuf->b_ml.ml_line_count - sub_firstlnum + 1) {
nmatch = curbuf->b_ml.ml_line_count - sub_firstlnum + 1;
+ current_match.end.lnum = sub_firstlnum + nmatch;
skip_match = true;
}
@@ -3696,8 +3711,19 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout)
} \
} while (0)
+ // Save the line numbers for the preview buffer
+ // NOTE: If the pattern matches a final newline, the next line will
+ // be shown also, but should not be highlighted. Intentional for now.
if (preview && !has_second_delim) {
+ current_match.start.col = regmatch.startpos[0].col;
+ if (current_match.end.lnum == 0) {
+ current_match.end.lnum = sub_firstlnum + nmatch - 1;
+ }
+ current_match.end.col = regmatch.endpos[0].col;
+
ADJUST_SUB_FIRSTLNUM();
+ lnum += nmatch - 1;
+
goto skip;
}
@@ -3747,6 +3773,10 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout)
memmove(new_end, sub_firstline + copycol, (size_t)copy_len);
new_end += copy_len;
+ // Finally, at this point we can know where the match actually will
+ // start in the new text
+ current_match.start.col = new_end - new_start;
+
(void)vim_regsub_multi(&regmatch,
sub_firstlnum - regmatch.startpos[0].lnum,
sub, new_end, true, p_magic, true);
@@ -3799,6 +3829,8 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout)
p1 += (*mb_ptr2len)(p1) - 1;
}
}
+ current_match.end.col = STRLEN(new_start);
+ current_match.end.lnum = lnum;
}
// 4. If subflags.do_all is set, find next match.
@@ -3907,9 +3939,30 @@ skip:
* found the match. */
if (nmatch == -1)
lnum -= regmatch.startpos[0].lnum;
+
+#define PUSH_PREVIEW_LINES() \
+ do { \
+ linenr_T match_lines = current_match.end.lnum \
+ - current_match.start.lnum +1; \
+ if (preview_lines.subresults.size > 0) { \
+ linenr_T last = kv_last(preview_lines.subresults).end.lnum; \
+ if (last == current_match.start.lnum) { \
+ preview_lines.lines_needed += match_lines - 1; \
+ } \
+ } else { \
+ preview_lines.lines_needed += match_lines; \
+ } \
+ kv_push(preview_lines.subresults, current_match); \
+ } while (0)
+
+ // Push the match to preview_lines.
+ PUSH_PREVIEW_LINES();
+
break;
}
}
+ // Push the match to preview_lines.
+ PUSH_PREVIEW_LINES();
line_breakcheck();
}
@@ -3919,12 +3972,6 @@ skip:
xfree(new_start); /* for when substitute was cancelled */
xfree(sub_firstline); /* free the copy of the original line */
sub_firstline = NULL;
-
- if (preview) {
- matched_line.lnum = lnum;
- matched_line.line = vim_strsave(ml_get(lnum));
- kv_push(matched_lines, matched_line);
- }
}
line_breakcheck();
@@ -3999,25 +4046,34 @@ skip:
// Show 'inccommand' preview if there are matched lines.
buf_T *preview_buf = NULL;
+ size_t subsize = preview_lines.subresults.size;
if (preview && !aborting()) {
if (got_quit) { // Substitution is too slow, disable 'inccommand'.
set_string_option_direct((char_u *)"icm", -1, (char_u *)"", OPT_FREE,
SID_NONE);
- } else if (*p_icm != NUL && matched_lines.size != 0 && pat != NULL) {
+ } else if (*p_icm != NUL && pat != NULL) {
+ if (pre_src_id == 0) {
+ // Get a unique new src_id, saved in a static
+ pre_src_id = bufhl_add_hl(NULL, 0, -1, 0, 0, 0);
+ }
+ if (pre_hl_id == 0) {
+ pre_hl_id = syn_check_group((char_u *)S_LEN("Substitute"));
+ }
curbuf->b_changed = save_b_changed; // preserve 'modified' during preview
- preview_buf = show_sub(eap, old_cursor, pat, sub, &matched_lines);
+ preview_buf = show_sub(eap, old_cursor, &preview_lines,
+ pre_hl_id, pre_src_id);
+ if (subsize > 0) {
+ bufhl_clear_line_range(orig_buf, pre_src_id, eap->line1,
+ kv_last(preview_lines.subresults).end.lnum);
+ }
}
}
- for (MatchedLine m; kv_size(matched_lines);) {
- m = kv_pop(matched_lines);
- xfree(m.line);
- kv_destroy(m.cols);
- }
- kv_destroy(matched_lines);
+ kv_destroy(preview_lines.subresults);
return preview_buf;
#undef ADJUST_SUB_FIRSTLNUM
+#undef PUSH_PREVIEW_LINES
} // NOLINT(readability/fn_size)
/*
@@ -6017,8 +6073,8 @@ void set_context_in_sign_cmd(expand_T *xp, char_u *arg)
/// Shows the effects of the :substitute command being typed ('inccommand').
/// If inccommand=split, shows a preview window and later restores the layout.
-static buf_T *show_sub(exarg_T *eap, pos_T old_cusr, char_u *pat, char_u *sub,
- MatchedLineVec *matched_lines)
+static buf_T *show_sub(exarg_T *eap, pos_T old_cusr,
+ PreviewLines *preview_lines, int hl_id, int src_id)
FUNC_ATTR_NONNULL_ALL
{
static handle_T bufnr = 0; // special buffer, re-used on each visit
@@ -6026,8 +6082,8 @@ static buf_T *show_sub(exarg_T *eap, pos_T old_cusr, char_u *pat, char_u *sub,
win_T *save_curwin = curwin;
cmdmod_T save_cmdmod = cmdmod;
char_u *save_shm_p = vim_strsave(p_shm);
- size_t sub_size = mb_string2cells(sub);
- size_t pat_size = mb_string2cells(pat);
+ PreviewLines lines = *preview_lines;
+ buf_T *orig_buf = curbuf;
// We keep a special-purpose buffer around, but don't assume it exists.
buf_T *preview_buf = bufnr ? buflist_findnr(bufnr) : 0;
@@ -6039,22 +6095,26 @@ static buf_T *show_sub(exarg_T *eap, pos_T old_cusr, char_u *pat, char_u *sub,
bool outside_curline = (eap->line1 != old_cusr.lnum
|| eap->line2 != old_cusr.lnum);
- bool split = outside_curline && (*p_icm != 'n') && (sub_size || pat_size);
+ bool split = outside_curline && (*p_icm != 'n');
if (preview_buf == curbuf) { // Preview buffer cannot preview itself!
split = false;
preview_buf = NULL;
}
// Place cursor on nearest matching line, to undo do_sub() cursor placement.
- for (size_t i = 0; i < matched_lines->size; i++) {
- MatchedLine curmatch = matched_lines->items[i];
- if (curmatch.lnum >= old_cusr.lnum) {
- curwin->w_cursor.lnum = curmatch.lnum;
- curwin->w_cursor.col = curmatch.cols.items[0];
+ for (size_t i = 0; i < lines.subresults.size; i++) {
+ SubResult curres = lines.subresults.items[i];
+ if (curres.start.lnum >= old_cusr.lnum) {
+ curwin->w_cursor.lnum = curres.start.lnum;
+ curwin->w_cursor.col = curres.start.col;
break;
} // Else: All matches are above, do_sub() already placed cursor.
}
+ // Width of the "| lnum|..." column which displays the line numbers.
+ linenr_T highest_num_line = 0;
+ int col_width = 0;
+
if (split && win_split((int)p_cwh, WSP_BOT) != FAIL) {
buf_open_scratch(preview_buf ? bufnr : 0, "[Preview]");
buf_clear();
@@ -6069,44 +6129,77 @@ static buf_T *show_sub(exarg_T *eap, pos_T old_cusr, char_u *pat, char_u *sub,
curwin->w_p_spell = false;
curwin->w_p_fen = false;
- // Width of the "| lnum|..." column which displays the line numbers.
- linenr_T highest_num_line = kv_last(*matched_lines).lnum;
- int col_width = log10(highest_num_line) + 1 + 3;
-
- char *str = NULL;
- size_t old_line_size = 0;
- size_t line_size;
- int src_id_highlight = 0;
- int hl_id = syn_check_group((char_u *)"Substitute", 13);
-
- // Dump the lines into the preview buffer.
- for (size_t line = 0; line < matched_lines->size; line++) {
- MatchedLine mat = matched_lines->items[line];
- line_size = mb_string2cells(mat.line) + col_width + 1;
-
- // Reallocate if str not long enough
- if (line_size > old_line_size) {
- str = xrealloc(str, line_size * sizeof(char));
- old_line_size = line_size;
+ if (lines.subresults.size > 0) {
+ highest_num_line = kv_last(lines.subresults).end.lnum;
+ col_width = log10(highest_num_line) + 1 + 3;
+ }
+ }
+
+ char *str = NULL; // construct the line to show in here
+ size_t old_line_size = 0;
+ size_t line_size = 0;
+ linenr_T linenr_preview = 0; // last line added to preview buffer
+ linenr_T linenr_origbuf = 0; // last line added to original buffer
+ linenr_T next_linenr = 0; // next line to show for the match
+
+ for (size_t matchidx = 0; matchidx < lines.subresults.size; matchidx++) {
+ SubResult match = lines.subresults.items[matchidx];
+
+ if (split && preview_buf) {
+ lpos_T p_start = { 0, match.start.col }; // match starts here in preview
+ lpos_T p_end = { 0, match.end.col }; // ... and ends here
+
+ if (match.pre_match == 0) {
+ next_linenr = match.start.lnum;
+ } else {
+ next_linenr = match.pre_match;
+ }
+ // Don't add a line twice
+ if (next_linenr == linenr_origbuf) {
+ next_linenr++;
+ p_start.lnum = linenr_preview; // might be redefined below
+ p_end.lnum = linenr_preview; // might be redefined below
}
- // Put "|lnum| line" into `str` and append it to the preview buffer.
- snprintf(str, line_size, "|%*ld| %s", col_width - 3, mat.lnum, mat.line);
- ml_append(line, (char_u *)str, (colnr_T)line_size, false);
-
- // highlight the replaced part
- if (sub_size > 0) {
- for (size_t i = 0; i < mat.cols.size; i++) {
- colnr_T col_start = mat.cols.items[i] + col_width
- + i * (sub_size - pat_size) + 1;
- colnr_T col_end = col_start - 1 + sub_size;
- src_id_highlight = bufhl_add_hl(curbuf, src_id_highlight, hl_id,
- line + 1, col_start, col_end);
+ for (; next_linenr <= match.end.lnum; next_linenr++) {
+ if (next_linenr == match.start.lnum) {
+ p_start.lnum = linenr_preview + 1;
}
+ if (next_linenr == match.end.lnum) {
+ p_end.lnum = linenr_preview + 1;
+ }
+ char *line;
+ if (next_linenr == orig_buf->b_ml.ml_line_count + 1) {
+ line = "";
+ } else {
+ line = (char *)ml_get_buf(orig_buf, next_linenr, false);
+ line_size = strlen(line) + col_width + 1;
+
+ // Reallocate if line not long enough
+ if (line_size > old_line_size) {
+ str = xrealloc(str, line_size * sizeof(char));
+ old_line_size = line_size;
+ }
+ }
+ // Put "|lnum| line" into `str` and append it to the preview buffer.
+ snprintf(str, line_size, "|%*ld| %s", col_width - 3,
+ next_linenr, line);
+ if (linenr_preview == 0) {
+ ml_replace(1, (char_u *)str, true);
+ } else {
+ ml_append(linenr_preview, (char_u *)str, (colnr_T)line_size, false);
+ }
+ linenr_preview += 1;
}
+ linenr_origbuf = match.end.lnum;
+
+ bufhl_add_hl_pos_offset(preview_buf, src_id, hl_id, p_start,
+ p_end, col_width);
}
- xfree(str);
+ bufhl_add_hl_pos_offset(orig_buf, src_id, hl_id, match.start,
+ match.end, 0);
}
+ xfree(str);
redraw_later(SOME_VALID);
win_enter(save_curwin, false); // Return to original window
@@ -6156,7 +6249,11 @@ void ex_substitute(exarg_T *eap)
curwin->w_p_cul = false; // Disable 'cursorline'
curwin->w_p_cuc = false; // Disable 'cursorcolumn'
+ // Don't show search highlighting during live substitution
+ bool save_hls = p_hls;
+ p_hls = false;
buf_T *preview_buf = do_sub(eap, profile_setlimit(p_rdt));
+ p_hls = save_hls;
if (save_changedtick != curbuf->b_changedtick) {
// Undo invisibly. This also moves the cursor!
diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c
index 371f7b3bce..9b8e463aee 100644
--- a/src/nvim/ex_cmds2.c
+++ b/src/nvim/ex_cmds2.c
@@ -1039,9 +1039,14 @@ static void profile_reset(void)
uf->uf_tm_total = profile_zero();
uf->uf_tm_self = profile_zero();
uf->uf_tm_children = profile_zero();
+
+ xfree(uf->uf_tml_count);
+ xfree(uf->uf_tml_total);
+ xfree(uf->uf_tml_self);
uf->uf_tml_count = NULL;
uf->uf_tml_total = NULL;
uf->uf_tml_self = NULL;
+
uf->uf_tml_start = profile_zero();
uf->uf_tml_children = profile_zero();
uf->uf_tml_wait = profile_zero();
@@ -1068,7 +1073,7 @@ static void profile_init(scriptitem_T *si)
si->sn_pr_nest = 0;
}
-/// save time when starting to invoke another script or function.
+/// Save time when starting to invoke another script or function.
void script_prof_save(
proftime_T *tm // place to store wait time
)
@@ -1141,12 +1146,14 @@ static void script_dump_profile(FILE *fd)
if (sfd == NULL) {
fprintf(fd, "Cannot open file!\n");
} else {
- for (int i = 0; i < si->sn_prl_ga.ga_len; i++) {
+ // Keep going till the end of file, so that trailing
+ // continuation lines are listed.
+ for (int i = 0; ; i++) {
if (vim_fgets(IObuff, IOSIZE, sfd)) {
break;
}
- pp = &PRL_ITEM(si, i);
- if (pp->snp_count > 0) {
+ if (i < si->sn_prl_ga.ga_len
+ && (pp = &PRL_ITEM(si, i))->snp_count > 0) {
fprintf(fd, "%5d ", pp->snp_count);
if (profile_equal(pp->sn_prl_total, pp->sn_prl_self)) {
fprintf(fd, " ");
@@ -2871,22 +2878,6 @@ int do_source(char_u *fname, int check_other, int is_vimrc)
save_sourcing_lnum = sourcing_lnum;
sourcing_lnum = 0;
- cookie.conv.vc_type = CONV_NONE; // no conversion
-
- // Read the first line so we can check for a UTF-8 BOM.
- firstline = getsourceline(0, (void *)&cookie, 0);
- if (firstline != NULL && STRLEN(firstline) >= 3 && firstline[0] == 0xef
- && firstline[1] == 0xbb && firstline[2] == 0xbf) {
- // Found BOM; setup conversion, skip over BOM and recode the line.
- convert_setup(&cookie.conv, (char_u *)"utf-8", p_enc);
- p = string_convert(&cookie.conv, firstline + 3, NULL);
- if (p == NULL) {
- p = vim_strsave(firstline + 3);
- }
- xfree(firstline);
- firstline = p;
- }
-
// start measuring script load time if --startuptime was passed and
// time_fd was successfully opened afterwards.
proftime_T rel_time;
@@ -2959,6 +2950,22 @@ int do_source(char_u *fname, int check_other, int is_vimrc)
}
}
+ cookie.conv.vc_type = CONV_NONE; // no conversion
+
+ // Read the first line so we can check for a UTF-8 BOM.
+ firstline = getsourceline(0, (void *)&cookie, 0);
+ if (firstline != NULL && STRLEN(firstline) >= 3 && firstline[0] == 0xef
+ && firstline[1] == 0xbb && firstline[2] == 0xbf) {
+ // Found BOM; setup conversion, skip over BOM and recode the line.
+ convert_setup(&cookie.conv, (char_u *)"utf-8", p_enc);
+ p = string_convert(&cookie.conv, firstline + 3, NULL);
+ if (p == NULL) {
+ p = vim_strsave(firstline + 3);
+ }
+ xfree(firstline);
+ firstline = p;
+ }
+
// Call do_cmdline, which will call getsourceline() to get the lines.
do_cmdline(firstline, getsourceline, (void *)&cookie,
DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_REPEAT);
@@ -3068,6 +3075,8 @@ char_u *get_scriptname(scid_T id)
# if defined(EXITFREE)
void free_scriptnames(void)
{
+ profile_reset();
+
# define FREE_SCRIPTNAME(item) xfree((item)->sn_name)
GA_DEEP_CLEAR(&script_items, scriptitem_T, FREE_SCRIPTNAME);
}
@@ -3281,7 +3290,8 @@ void script_line_start(void)
if (si->sn_prof_on && sourcing_lnum >= 1) {
// Grow the array before starting the timer, so that the time spent
// here isn't counted.
- ga_grow(&si->sn_prl_ga, (int)(sourcing_lnum - si->sn_prl_ga.ga_len));
+ (void)ga_grow(&si->sn_prl_ga,
+ (int)(sourcing_lnum - si->sn_prl_ga.ga_len));
si->sn_prl_idx = sourcing_lnum - 1;
while (si->sn_prl_ga.ga_len <= si->sn_prl_idx
&& si->sn_prl_ga.ga_len < si->sn_prl_ga.ga_maxlen) {
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 3d5e1a5476..27883997e4 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -2787,7 +2787,7 @@ void ui_ext_cmdline_block_append(int indent, const char *line)
{
char *buf = xmallocz(indent + strlen(line));
memset(buf, ' ', indent);
- memcpy(buf+indent, line, strlen(line));
+ memcpy(buf + indent, line, strlen(line)); // -V575
Array item = ARRAY_DICT_INIT;
ADD(item, DICTIONARY_OBJ((Dictionary)ARRAY_DICT_INIT));
diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile
index 979021ff92..ccf999c7ee 100644
--- a/src/nvim/testdir/Makefile
+++ b/src/nvim/testdir/Makefile
@@ -62,6 +62,7 @@ NEW_TESTS ?= \
test_mksession_utf8.res \
test_nested_function.res \
test_normal.res \
+ test_profile.res \
test_quickfix.res \
test_retab.res \
test_search.res \
diff --git a/src/nvim/testdir/test_profile.vim b/src/nvim/testdir/test_profile.vim
new file mode 100644
index 0000000000..4cbd800da5
--- /dev/null
+++ b/src/nvim/testdir/test_profile.vim
@@ -0,0 +1,183 @@
+" Test Vim profiler
+if !has('profile')
+ finish
+endif
+
+func Test_profile_func()
+ let lines = [
+ \ "func! Foo1()",
+ \ "endfunc",
+ \ "func! Foo2()",
+ \ " let l:count = 100",
+ \ " while l:count > 0",
+ \ " let l:count = l:count - 1",
+ \ " endwhile",
+ \ "endfunc",
+ \ "func! Foo3()",
+ \ "endfunc",
+ \ "func! Bar()",
+ \ "endfunc",
+ \ "call Foo1()",
+ \ "call Foo1()",
+ \ "profile pause",
+ \ "call Foo1()",
+ \ "profile continue",
+ \ "call Foo2()",
+ \ "call Foo3()",
+ \ "call Bar()",
+ \ "if !v:profiling",
+ \ " delfunc Foo2",
+ \ "endif",
+ \ "delfunc Foo3",
+ \ ]
+
+ call writefile(lines, 'Xprofile_func.vim')
+ call system(v:progpath
+ \ . ' -es -u NONE -U NONE -i NONE --noplugin'
+ \ . ' -c "profile start Xprofile_func.log"'
+ \ . ' -c "profile func Foo*"'
+ \ . ' -c "so Xprofile_func.vim"'
+ \ . ' -c "qall!"')
+ call assert_equal(0, v:shell_error)
+
+ let lines = readfile('Xprofile_func.log')
+
+ " - Foo1() is called 3 times but should be reported as called twice
+ " since one call is in between "profile pause" .. "profile continue".
+ " - Foo2() should come before Foo1() since Foo1() does much more work.
+ " - Foo3() is not reported because function is deleted.
+ " - Unlike Foo3(), Foo2() should not be deleted since there is a check
+ " for v:profiling.
+ " - Bar() is not reported since it does not match "profile func Foo*".
+ call assert_equal(28, len(lines))
+
+ call assert_equal('FUNCTION Foo1()', lines[0])
+ call assert_equal('Called 2 times', lines[1])
+ call assert_match('^Total time:\s\+\d\+\.\d\+$', lines[2])
+ call assert_match('^ Self time:\s\+\d\+\.\d\+$', lines[3])
+ call assert_equal('', lines[4])
+ call assert_equal('count total (s) self (s)', lines[5])
+ call assert_equal('', lines[6])
+ call assert_equal('FUNCTION Foo2()', lines[7])
+ call assert_equal('Called 1 time', lines[8])
+ call assert_match('^Total time:\s\+\d\+\.\d\+$', lines[9])
+ call assert_match('^ Self time:\s\+\d\+\.\d\+$', lines[10])
+ call assert_equal('', lines[11])
+ call assert_equal('count total (s) self (s)', lines[12])
+ call assert_match('^\s*1\s\+.*\slet l:count = 100$', lines[13])
+ call assert_match('^\s*101\s\+.*\swhile l:count > 0$', lines[14])
+ call assert_match('^\s*100\s\+.*\s let l:count = l:count - 1$', lines[15])
+ call assert_match('^\s*100\s\+.*\sendwhile$', lines[16])
+ call assert_equal('', lines[17])
+ call assert_equal('FUNCTIONS SORTED ON TOTAL TIME', lines[18])
+ call assert_equal('count total (s) self (s) function', lines[19])
+ call assert_match('^\s*1\s\+\d\+\.\d\+\s\+Foo2()$', lines[20])
+ call assert_match('^\s*2\s\+\d\+\.\d\+\s\+Foo1()$', lines[21])
+ call assert_equal('', lines[22])
+ call assert_equal('FUNCTIONS SORTED ON SELF TIME', lines[23])
+ call assert_equal('count total (s) self (s) function', lines[24])
+ call assert_match('^\s*1\s\+\d\+\.\d\+\s\+Foo2()$', lines[25])
+ call assert_match('^\s*2\s\+\d\+\.\d\+\s\+Foo1()$', lines[26])
+ call assert_equal('', lines[27])
+
+ call delete('Xprofile_func.vim')
+ call delete('Xprofile_func.log')
+endfunc
+
+func Test_profile_file()
+ let lines = [
+ \ 'func! Foo()',
+ \ 'endfunc',
+ \ 'for i in range(10)',
+ \ ' " a comment',
+ \ ' call Foo()',
+ \ 'endfor',
+ \ 'call Foo()',
+ \ ]
+
+ call writefile(lines, 'Xprofile_file.vim')
+ call system(v:progpath
+ \ . ' -es -u NONE -U NONE -i NONE --noplugin'
+ \ . ' -c "profile start Xprofile_file.log"'
+ \ . ' -c "profile file Xprofile_file.vim"'
+ \ . ' -c "so Xprofile_file.vim"'
+ \ . ' -c "so Xprofile_file.vim"'
+ \ . ' -c "qall!"')
+ call assert_equal(0, v:shell_error)
+
+ let lines = readfile('Xprofile_file.log')
+
+ call assert_equal(14, len(lines))
+
+ call assert_match('^SCRIPT .*Xprofile_file.vim$', lines[0])
+ call assert_equal('Sourced 2 times', lines[1])
+ call assert_match('^Total time:\s\+\d\+\.\d\+$', lines[2])
+ call assert_match('^ Self time:\s\+\d\+\.\d\+$', lines[3])
+ call assert_equal('', lines[4])
+ call assert_equal('count total (s) self (s)', lines[5])
+ call assert_match(' 2 0.\d\+ func! Foo()', lines[6])
+ call assert_equal(' endfunc', lines[7])
+ " Loop iterates 10 times. Since script runs twice, body executes 20 times.
+ " First line of loop executes one more time than body to detect end of loop.
+ call assert_match('^\s*22\s\+\d\+\.\d\+\s\+for i in range(10)$', lines[8])
+ call assert_equal(' " a comment', lines[9])
+ " if self and total are equal we only get one number
+ call assert_match('^\s*20\s\+\(\d\+\.\d\+\s\+\)\=\d\+\.\d\+\s\+call Foo()$', lines[10])
+ call assert_match('^\s*20\s\+\d\+\.\d\+\s\+endfor$', lines[11])
+ " if self and total are equal we only get one number
+ call assert_match('^\s*2\s\+\(\d\+\.\d\+\s\+\)\=\d\+\.\d\+\s\+call Foo()$', lines[12])
+ call assert_equal('', lines[13])
+
+ call delete('Xprofile_file.vim')
+ call delete('Xprofile_file.log')
+endfunc
+
+func Test_profile_file_with_cont()
+ let lines = [
+ \ 'echo "hello',
+ \ ' \ world"',
+ \ 'echo "foo ',
+ \ ' \bar"',
+ \ ]
+
+ call writefile(lines, 'Xprofile_file.vim')
+ call system(v:progpath
+ \ . ' -es -u NONE -U NONE -i NONE --noplugin'
+ \ . ' -c "profile start Xprofile_file.log"'
+ \ . ' -c "profile file Xprofile_file.vim"'
+ \ . ' -c "so Xprofile_file.vim"'
+ \ . ' -c "qall!"')
+ call assert_equal(0, v:shell_error)
+
+ let lines = readfile('Xprofile_file.log')
+ call assert_equal(11, len(lines))
+
+ call assert_match('^SCRIPT .*Xprofile_file.vim$', lines[0])
+ call assert_equal('Sourced 1 time', lines[1])
+ call assert_match('^Total time:\s\+\d\+\.\d\+$', lines[2])
+ call assert_match('^ Self time:\s\+\d\+\.\d\+$', lines[3])
+ call assert_equal('', lines[4])
+ call assert_equal('count total (s) self (s)', lines[5])
+ call assert_match(' 1 0.\d\+ echo "hello', lines[6])
+ call assert_equal(' \ world"', lines[7])
+ call assert_match(' 1 0.\d\+ echo "foo ', lines[8])
+ call assert_equal(' \bar"', lines[9])
+ call assert_equal('', lines[10])
+
+ call delete('Xprofile_file.vim')
+ call delete('Xprofile_file.log')
+endfunc
+
+func Test_profile_completion()
+ call feedkeys(":profile \<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"profile continue dump file func pause start stop', @:)
+
+ call feedkeys(":profile start test_prof\<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_match('^"profile start.* test_profile\.vim', @:)
+endfunc
+
+func Test_profile_errors()
+ call assert_fails("profile func Foo", 'E750:')
+ call assert_fails("profile pause", 'E750:')
+ call assert_fails("profile continue", 'E750:')
+endfunc
diff --git a/src/nvim/version.c b/src/nvim/version.c
index d841f58b92..a31381eddf 100644
--- a/src/nvim/version.c
+++ b/src/nvim/version.c
@@ -160,7 +160,7 @@ static const int included_patches[] = {
// 947,
// 946,
// 945,
- // 944,
+ 944,
// 943,
// 942,
// 941,
@@ -908,14 +908,14 @@ static const int included_patches[] = {
// 199 NA
// 198,
// 197,
- // 196,
+ 196,
195,
- // 194,
+ 194,
// 193 NA
// 192 NA
// 191 NA
190,
- // 189,
+ 189,
188,
// 187 NA
186,
diff --git a/test/functional/ui/inccommand_spec.lua b/test/functional/ui/inccommand_spec.lua
index cc023ef10d..6646e65bad 100644
--- a/test/functional/ui/inccommand_spec.lua
+++ b/test/functional/ui/inccommand_spec.lua
@@ -21,6 +21,42 @@ local default_text = [[
two lines
]]
+local multiline_text = [[
+ 1 2 3
+ A B C
+ 4 5 6
+ X Y Z
+ 7 8 9
+]]
+
+local multimatch_text = [[
+ a bdc eae a fgl lzia r
+ x
+]]
+
+local multibyte_text = [[
+ £ ¥ ѫѫ PEPPERS
+£ ¥ ѫfѫ
+ a£ ѫ¥KOL
+£ ¥ libm
+£ ¥
+]]
+
+local long_multiline_text = [[
+ 1 2 3
+ A B C
+ 4 5 6
+ X Y Z
+ 7 8 9
+ K L M
+ a b c
+ d e f
+ q r s
+ x y z
+ £ m n
+ t œ ¥
+]]
+
local function common_setup(screen, inccommand, text)
if screen then
command("syntax on")
@@ -682,14 +718,14 @@ describe(":substitute, inccommand=split", function()
feed(":%s/tw")
screen:expect([[
Inc substitution on |
- two lines |
+ {12:tw}o lines |
|
{15:~ }|
{15:~ }|
{11:[No Name] }|
- |2| two lines |
- |4| two lines |
- |
+ |2| {12:tw}o lines |
+ |4| {12:tw}o lines |
+ {15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
@@ -704,13 +740,13 @@ describe(":substitute, inccommand=split", function()
it("shows preview when cmd modifiers are present", function()
-- one modifier
feed(':keeppatterns %s/tw/to')
- screen:expect([[too lines]], nil, nil, nil, true)
+ screen:expect([[{12:to}o lines]], nil, nil, nil, true)
feed('<Esc>')
screen:expect([[two lines]], nil, nil, nil, true)
-- multiple modifiers
feed(':keeppatterns silent %s/tw/to')
- screen:expect([[too lines]], nil, nil, nil, true)
+ screen:expect([[{12:to}o lines]], nil, nil, nil, true)
feed('<Esc>')
screen:expect([[two lines]], nil, nil, nil, true)
@@ -724,14 +760,14 @@ describe(":substitute, inccommand=split", function()
feed(":%s/tw")
screen:expect([[
Inc substitution on |
- two lines |
+ {12:tw}o lines |
|
{15:~ }|
{15:~ }|
{11:[No Name] [+] }|
- |2| two lines |
- |4| two lines |
- |
+ |2| {12:tw}o lines |
+ |4| {12:tw}o lines |
+ {15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
@@ -752,7 +788,7 @@ describe(":substitute, inccommand=split", function()
{11:[No Name] [+] }|
|2| o lines |
|4| o lines |
- |
+ {15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
@@ -764,14 +800,14 @@ describe(":substitute, inccommand=split", function()
feed("x")
screen:expect([[
Inc substitution on |
- xo lines |
+ {12:x}o lines |
|
{15:~ }|
{15:~ }|
{11:[No Name] [+] }|
|2| {12:x}o lines |
|4| {12:x}o lines |
- |
+ {15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
@@ -790,7 +826,7 @@ describe(":substitute, inccommand=split", function()
{11:[No Name] [+] }|
|2| o lines |
|4| o lines |
- |
+ {15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
@@ -805,14 +841,14 @@ describe(":substitute, inccommand=split", function()
feed(":%s/tw/XX")
screen:expect([[
Inc substitution on |
- XXo lines |
+ {12:XX}o lines |
|
{15:~ }|
{15:~ }|
{11:[No Name] [+] }|
|2| {12:XX}o lines |
|4| {12:XX}o lines |
- |
+ {15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
@@ -828,7 +864,7 @@ describe(":substitute, inccommand=split", function()
screen:sleep(1)
screen:expect([[
Inc substitution on |
- two lines |
+ {12:tw}o lines |
Inc substitution on |
two lines |
|
@@ -872,14 +908,14 @@ describe(":substitute, inccommand=split", function()
-- 'cursorline' is NOT active during preview.
screen:expect([[
Inc substitution on |
- {9:tw}o lines |
+ {12:tw}o lines |
Inc substitution on |
- {9:tw}o lines |
+ {12:tw}o lines |
|
{11:[No Name] [+] }|
- |2| {9:tw}o lines |
- |4| {9:tw}o lines |
- |
+ |2| {12:tw}o lines |
+ |4| {12:tw}o lines |
+ {15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
@@ -894,14 +930,14 @@ describe(":substitute, inccommand=split", function()
feed('M M M<esc>')
feed(':%s/M/123/g')
screen:expect([[
- 123 123 123 |
+ {12:123} {12:123} {12:123} |
Inc substitution on |
two lines |
Inc substitution on |
two lines |
{11:[No Name] [+] }|
|1| {12:123} {12:123} {12:123} |
- |
+ {15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
@@ -912,6 +948,28 @@ describe(":substitute, inccommand=split", function()
]])
end)
+ it("highlights nothing when there's no match", function()
+ feed('gg')
+ feed(':%s/Inx')
+ screen:expect([[
+ Inc substitution on |
+ two lines |
+ Inc substitution on |
+ two lines |
+ |
+ {11:[No Name] [+] }|
+ |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {10:[Preview] }|
+ :%s/Inx^ |
+ ]])
+ end)
+
it('previews correctly when previewhight is small', function()
feed_command('set cwh=3')
feed_command('set hls')
@@ -919,15 +977,15 @@ describe(":substitute, inccommand=split", function()
insert(string.rep('abc abc abc\n', 20))
feed(':%s/abc/MMM/g')
screen:expect([[
- MMM MMM MMM |
- MMM MMM MMM |
- MMM MMM MMM |
- MMM MMM MMM |
- MMM MMM MMM |
- MMM MMM MMM |
- MMM MMM MMM |
- MMM MMM MMM |
- MMM MMM MMM |
+ {12:MMM} {12:MMM} {12:MMM} |
+ {12:MMM} {12:MMM} {12:MMM} |
+ {12:MMM} {12:MMM} {12:MMM} |
+ {12:MMM} {12:MMM} {12:MMM} |
+ {12:MMM} {12:MMM} {12:MMM} |
+ {12:MMM} {12:MMM} {12:MMM} |
+ {12:MMM} {12:MMM} {12:MMM} |
+ {12:MMM} {12:MMM} {12:MMM} |
+ {12:MMM} {12:MMM} {12:MMM} |
{11:[No Name] [+] }|
| 1| {12:MMM} {12:MMM} {12:MMM} |
| 2| {12:MMM} {12:MMM} {12:MMM} |
@@ -969,9 +1027,9 @@ describe(":substitute, inccommand=split", function()
screen:expect([[
BBo lines |
Inc substitution on |
- Xo lines |
+ {12:X}o lines |
Inc substitution on |
- Xo lines |
+ {12:X}o lines |
{11:[No Name] [+] }|
|1001| {12:X}o lines |
|1003| {12:X}o lines |
@@ -1069,15 +1127,15 @@ describe(":substitute, inccommand=split", function()
feed(":1,2s/t/X")
screen:expect([[
- Inc subsXitution on |
- Xwo lines |
+ Inc subs{12:X}itution on |
+ {12:X}wo lines |
Inc substitution on |
two lines |
|
{11:[No Name] [+] }|
|1| Inc subs{12:X}itution on |
|2| {12:X}wo lines |
- |
+ {15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
@@ -1134,7 +1192,7 @@ describe("inccommand=nosplit", function()
two lines |
Inc substitution on |
two lines |
- Line *.X |
+ Line *.{12:X} |
{15:~ }|
{15:~ }|
{15:~ }|
@@ -1142,7 +1200,6 @@ describe("inccommand=nosplit", function()
:%smagic/3.*/X^ |
]])
-
feed([[<C-\><C-N>]]) -- cancel
feed(":%snomagic/3.*/X") -- start :snomagic command
screen:expect([[
@@ -1150,7 +1207,7 @@ describe("inccommand=nosplit", function()
two lines |
Inc substitution on |
two lines |
- Line *.X here |
+ Line *.{12:X} here |
{15:~ }|
{15:~ }|
{15:~ }|
@@ -1162,13 +1219,13 @@ describe("inccommand=nosplit", function()
it("shows preview when cmd modifiers are present", function()
-- one modifier
feed(':keeppatterns %s/tw/to')
- screen:expect([[too lines]], nil, nil, nil, true)
+ screen:expect([[{12:to}o lines]], nil, nil, nil, true)
feed('<Esc>')
screen:expect([[two lines]], nil, nil, nil, true)
-- multiple modifiers
feed(':keeppatterns silent %s/tw/to')
- screen:expect([[too lines]], nil, nil, nil, true)
+ screen:expect([[{12:to}o lines]], nil, nil, nil, true)
feed('<Esc>')
screen:expect([[two lines]], nil, nil, nil, true)
@@ -1178,15 +1235,38 @@ describe("inccommand=nosplit", function()
feed('<Esc>')
end)
+ it("does not show window after toggling :set inccommand", function()
+ feed(":%s/tw/OKOK")
+ feed("<Esc>")
+ command("set icm=split")
+ feed(":%s/tw/OKOK")
+ feed("<Esc>")
+ command("set icm=nosplit")
+ feed(":%s/tw/OKOK")
+ wait()
+ screen:expect([[
+ Inc substitution on |
+ {12:OKOK}o lines |
+ Inc substitution on |
+ {12:OKOK}o lines |
+ |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ :%s/tw/OKOK^ |
+ ]])
+ end)
+
it('never shows preview buffer', function()
feed_command("set hlsearch")
feed(":%s/tw")
screen:expect([[
Inc substitution on |
- {9:tw}o lines |
+ {12:tw}o lines |
Inc substitution on |
- {9:tw}o lines |
+ {12:tw}o lines |
|
{15:~ }|
{15:~ }|
@@ -1198,9 +1278,9 @@ describe("inccommand=nosplit", function()
feed("/BM")
screen:expect([[
Inc substitution on |
- BMo lines |
+ {12:BM}o lines |
Inc substitution on |
- BMo lines |
+ {12:BM}o lines |
|
{15:~ }|
{15:~ }|
@@ -1212,9 +1292,9 @@ describe("inccommand=nosplit", function()
feed("/")
screen:expect([[
Inc substitution on |
- BMo lines |
+ {12:BM}o lines |
Inc substitution on |
- BMo lines |
+ {12:BM}o lines |
|
{15:~ }|
{15:~ }|
@@ -1245,8 +1325,8 @@ describe("inccommand=nosplit", function()
feed(":1,2s/t/X")
screen:expect([[
- Inc subsXitution on |
- Xwo lines |
+ Inc subs{12:X}itution on |
+ {12:X}wo lines |
Inc substitution on |
two lines |
|
@@ -1563,7 +1643,7 @@ describe("'inccommand' split windows", function()
feed(":%s/tw")
screen:expect([[
Inc substitution on {10:|}Inc substitution on|
- two lines {10:|}two lines |
+ {12:tw}o lines {10:|}{12:tw}o lines |
{10:|} |
{15:~ }{10:|}{15:~ }|
{15:~ }{10:|}{15:~ }|
@@ -1578,13 +1658,13 @@ describe("'inccommand' split windows", function()
{15:~ }{10:|}{15:~ }|
{11:[No Name] [+] }{10:|}{15:~ }|
Inc substitution on {10:|}{15:~ }|
- two lines {10:|}{15:~ }|
+ {12:tw}o lines {10:|}{15:~ }|
{10:|}{15:~ }|
{15:~ }{10:|}{15:~ }|
{15:~ }{10:|}{15:~ }|
{10:[No Name] [+] [No Name] [+] }|
- |2| two lines |
- |
+ |2| {12:tw}o lines |
+ {15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
@@ -1602,7 +1682,7 @@ describe("'inccommand' split windows", function()
feed(":%s/tw")
screen:expect([[
Inc substitution on {10:|}Inc substitution on|
- two lines {10:|}two lines |
+ {12:tw}o lines {10:|}{12:tw}o lines |
{10:|} |
{15:~ }{10:|}{15:~ }|
{15:~ }{10:|}{15:~ }|
@@ -1617,13 +1697,13 @@ describe("'inccommand' split windows", function()
{15:~ }{10:|}{15:~ }|
{11:[No Name] [+] }{10:[No Name] [+] }|
Inc substitution on |
- two lines |
+ {12:tw}o lines |
|
{15:~ }|
{15:~ }|
{10:[No Name] [+] }|
- |2| two lines |
- |
+ |2| {12:tw}o lines |
+ {15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
@@ -1652,7 +1732,7 @@ describe("'inccommand' split windows", function()
screen:expect([[
Inc substitution on |
- two lines |
+ {12:tw}o lines |
|
{15:~ }|
{15:~ }|
@@ -1672,8 +1752,8 @@ describe("'inccommand' split windows", function()
{15:~ }|
{15:~ }|
{11:[No Name] [+] }|
- |2| two lines |
- |
+ |2| {12:tw}o lines |
+ {15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
@@ -1712,3 +1792,631 @@ describe("'inccommand' with 'gdefault'", function()
eq({mode='n', blocking=false}, nvim("get_mode"))
end)
end)
+
+describe(":substitute", function()
+ local screen = Screen.new(30,15)
+
+ before_each(function()
+ clear()
+ end)
+
+ it(", inccommand=split, highlights multiline substitutions", function()
+ common_setup(screen, "split", multiline_text)
+ feed("gg")
+
+ feed(":%s/2\\_.*X")
+ screen:expect([[
+ 1 {12:2 3} |
+ {12:A B C} |
+ {12:4 5 6} |
+ {12:X} Y Z |
+ 7 8 9 |
+ {11:[No Name] [+] }|
+ |1| 1 {12:2 3} |
+ |2|{12: A B C} |
+ |3|{12: 4 5 6} |
+ |4|{12: X} Y Z |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {10:[Preview] }|
+ :%s/2\_.*X^ |
+ ]])
+
+ feed("/MMM")
+ screen:expect([[
+ 1 {12:MMM} Y Z |
+ 7 8 9 |
+ |
+ {15:~ }|
+ {15:~ }|
+ {11:[No Name] [+] }|
+ |1| 1 {12:MMM} Y Z |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {10:[Preview] }|
+ :%s/2\_.*X/MMM^ |
+ ]])
+
+ feed("\\rK\\rLLL")
+ screen:expect([[
+ 1 {12:MMM} |
+ {12:K} |
+ {12:LLL} Y Z |
+ 7 8 9 |
+ |
+ {11:[No Name] [+] }|
+ |1| 1 {12:MMM} |
+ |2|{12: K} |
+ |3|{12: LLL} Y Z |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {10:[Preview] }|
+ :%s/2\_.*X/MMM\rK\rLLL^ |
+ ]])
+ end)
+
+ it(", inccommand=nosplit, highlights multiline substitutions", function()
+ common_setup(screen, "nosplit", multiline_text)
+ feed("gg")
+
+ feed(":%s/2\\_.*X/MMM")
+ screen:expect([[
+ 1 {12:MMM} Y Z |
+ 7 8 9 |
+ |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ :%s/2\_.*X/MMM^ |
+ ]])
+
+ feed("\\rK\\rLLL")
+ screen:expect([[
+ 1 {12:MMM} |
+ {12:K} |
+ {12:LLL} Y Z |
+ 7 8 9 |
+ |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ :%s/2\_.*X/MMM\rK\rLLL^ |
+ ]])
+ end)
+
+ it(", inccommand=split, highlights multiple matches on a line", function()
+ common_setup(screen, "split", multimatch_text)
+ command("set gdefault")
+ feed("gg")
+
+ feed(":%s/a/XLK")
+ screen:expect([[
+ {12:XLK} bdc e{12:XLK}e {12:XLK} fgl lzi{12:XLK} r|
+ x |
+ |
+ {15:~ }|
+ {15:~ }|
+ {11:[No Name] [+] }|
+ |1| {12:XLK} bdc e{12:XLK}e {12:XLK} fgl lzi{12:X}|
+ {12:LK} r |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {10:[Preview] }|
+ :%s/a/XLK^ |
+ ]])
+ end)
+
+ it(", inccommand=nosplit, highlights multiple matches on a line", function()
+ common_setup(screen, "nosplit", multimatch_text)
+ command("set gdefault")
+ feed("gg")
+
+ feed(":%s/a/XLK")
+ screen:expect([[
+ {12:XLK} bdc e{12:XLK}e {12:XLK} fgl lzi{12:XLK} r|
+ x |
+ |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ :%s/a/XLK^ |
+ ]])
+ end)
+
+ it(", inccommand=split, with \\zs", function()
+ common_setup(screen, "split", multiline_text)
+ feed("gg")
+
+ feed(":%s/[0-9]\\n\\zs[A-Z]/OKO")
+ screen:expect([[
+ 1 2 3 |
+ {12:OKO} B C |
+ 4 5 6 |
+ {12:OKO} Y Z |
+ 7 8 9 |
+ {11:[No Name] [+] }|
+ |1| 1 2 3 |
+ |2| {12:OKO} B C |
+ |3| 4 5 6 |
+ |4| {12:OKO} Y Z |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {10:[Preview] }|
+ :%s/[0-9]\n\zs[A-Z]/OKO^ |
+ ]])
+ end)
+
+ it(", inccommand=nosplit, with \\zs", function()
+ common_setup(screen, "nosplit", multiline_text)
+ feed("gg")
+
+ feed(":%s/[0-9]\\n\\zs[A-Z]/OKO")
+ screen:expect([[
+ 1 2 3 |
+ {12:OKO} B C |
+ 4 5 6 |
+ {12:OKO} Y Z |
+ 7 8 9 |
+ |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ :%s/[0-9]\n\zs[A-Z]/OKO^ |
+ ]])
+ end)
+
+ it(", inccommand=split, substitutions of different length",
+ function()
+ common_setup(screen, "split", "T T123 T2T TTT T090804\nx")
+
+ feed(":%s/T\\([0-9]\\+\\)/\\1\\1/g")
+ screen:expect([[
+ T {12:123123} {12:22}T TTT {12:090804090804} |
+ x |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {11:[No Name] [+] }|
+ |1| T {12:123123} {12:22}T TTT {12:090804090}|
+ {12:804} |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {10:[Preview] }|
+ :%s/T\([0-9]\+\)/\1\1/g^ |
+ ]])
+ end)
+
+ it(", inccommand=nosplit, substitutions of different length", function()
+ common_setup(screen, "nosplit", "T T123 T2T TTT T090804\nx")
+
+ feed(":%s/T\\([0-9]\\+\\)/\\1\\1/g")
+ screen:expect([[
+ T {12:123123} {12:22}T TTT {12:090804090804} |
+ x |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ :%s/T\([0-9]\+\)/\1\1/g^ |
+ ]])
+ end)
+
+ it(", inccommand=split, contraction of lines", function()
+ local text = [[
+ T T123 T T123 T2T TT T23423424
+ x
+ afa Q
+ adf la;lkd R
+ alx
+ ]]
+
+ common_setup(screen, "split", text)
+ feed(":%s/[QR]\\n")
+ screen:expect([[
+ afa {12:Q} |
+ adf la;lkd {12:R} |
+ alx |
+ |
+ {15:~ }|
+ {11:[No Name] [+] }|
+ |3| afa {12:Q} |
+ |4|{12: }adf la;lkd {12:R} |
+ |5|{12: }alx |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {10:[Preview] }|
+ :%s/[QR]\n^ |
+ ]])
+
+ feed("/KKK")
+ screen:expect([[
+ x |
+ afa {12:KKK}adf la;lkd {12:KKK}alx |
+ |
+ {15:~ }|
+ {15:~ }|
+ {11:[No Name] [+] }|
+ |3| afa {12:KKK}adf la;lkd {12:KKK}alx |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {10:[Preview] }|
+ :%s/[QR]\n/KKK^ |
+ ]])
+ end)
+
+ it(", inccommand=nosplit, contraction of lines", function()
+ local text = [[
+ T T123 T T123 T2T TT T23423424
+ x
+ afa Q
+ adf la;lkd R
+ alx
+ ]]
+
+ common_setup(screen, "nosplit", text)
+ feed(":%s/[QR]\\n/KKK")
+ screen:expect([[
+ T T123 T T123 T2T TT T23423424|
+ x |
+ afa {12:KKK}adf la;lkd {12:KKK}alx |
+ |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ :%s/[QR]\n/KKK^ |
+ ]])
+ end)
+
+ it(", inccommand=split, multibyte text", function()
+ common_setup(screen, "split", multibyte_text)
+ feed(":%s/£.*ѫ/X¥¥")
+ screen:expect([[
+ {12:X¥¥} |
+ a{12:X¥¥}¥KOL |
+ £ ¥ libm |
+ £ ¥ |
+ |
+ {11:[No Name] [+] }|
+ |1| {12:X¥¥} PEPPERS |
+ |2| {12:X¥¥} |
+ |3| a{12:X¥¥}¥KOL |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {10:[Preview] }|
+ :%s/£.*ѫ/X¥¥^ |
+ ]])
+
+ feed("\\ra££ ¥")
+ screen:expect([[
+ {12:a££ ¥} |
+ a{12:X¥¥} |
+ {12:a££ ¥}¥KOL |
+ £ ¥ libm |
+ £ ¥ |
+ {11:[No Name] [+] }|
+ |1| {12:X¥¥} |
+ |2|{12: a££ ¥} PEPPERS |
+ |3| {12:X¥¥} |
+ |4|{12: a££ ¥} |
+ |5| a{12:X¥¥} |
+ |6|{12: a££ ¥}¥KOL |
+ {15:~ }|
+ {10:[Preview] }|
+ :%s/£.*ѫ/X¥¥\ra££ ¥^ |
+ ]])
+ end)
+
+ it(", inccommand=nosplit, multibyte text", function()
+ common_setup(screen, "nosplit", multibyte_text)
+ feed(":%s/£.*ѫ/X¥¥")
+ screen:expect([[
+ {12:X¥¥} PEPPERS |
+ {12:X¥¥} |
+ a{12:X¥¥}¥KOL |
+ £ ¥ libm |
+ £ ¥ |
+ |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ :%s/£.*ѫ/X¥¥^ |
+ ]])
+
+ feed("\\ra££ ¥")
+ screen:expect([[
+ {12:X¥¥} |
+ {12:a££ ¥} PEPPERS |
+ {12:X¥¥} |
+ {12:a££ ¥} |
+ a{12:X¥¥} |
+ {12:a££ ¥}¥KOL |
+ £ ¥ libm |
+ £ ¥ |
+ |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ :%s/£.*ѫ/X¥¥\ra££ ¥^ |
+ ]])
+ end)
+
+ it(", inccommand=split, small cmdwinheight", function()
+ common_setup(screen, "split", long_multiline_text)
+ command("set cmdwinheight=2")
+
+ feed(":%s/[a-z]")
+ screen:expect([[
+ X Y Z |
+ 7 8 9 |
+ K L M |
+ {12:a} b c |
+ {12:d} e f |
+ {12:q} r s |
+ {12:x} y z |
+ £ {12:m} n |
+ {12:t} œ ¥ |
+ |
+ {11:[No Name] [+] }|
+ | 7| {12:a} b c |
+ | 8| {12:d} e f |
+ {10:[Preview] }|
+ :%s/[a-z]^ |
+ ]])
+
+ feed("/JLKR £")
+ screen:expect([[
+ X Y Z |
+ 7 8 9 |
+ K L M |
+ {12:JLKR £} b c |
+ {12:JLKR £} e f |
+ {12:JLKR £} r s |
+ {12:JLKR £} y z |
+ £ {12:JLKR £} n |
+ {12:JLKR £} œ ¥ |
+ |
+ {11:[No Name] [+] }|
+ | 7| {12:JLKR £} b c |
+ | 8| {12:JLKR £} e f |
+ {10:[Preview] }|
+ :%s/[a-z]/JLKR £^ |
+ ]])
+
+ feed("\\rѫ ab \\rXXXX")
+ screen:expect([[
+ 7 8 9 |
+ K L M |
+ {12:JLKR £} |
+ {12:ѫ ab } |
+ {12:XXXX} b c |
+ {12:JLKR £} |
+ {12:ѫ ab } |
+ {12:XXXX} e f |
+ {12:JLKR £} |
+ {11:[No Name] [+] }|
+ | 7| {12:JLKR £} |
+ | 8|{12: ѫ ab } |
+ {10:[Preview] }|
+ :%s/[a-z]/JLKR £\rѫ ab \rXXX|
+ X^ |
+ ]])
+ end)
+
+ it(", inccommand=split, large cmdwinheight", function()
+ common_setup(screen, "split", long_multiline_text)
+ command("set cmdwinheight=11")
+
+ feed(":%s/. .$")
+ screen:expect([[
+ t {12:œ ¥} |
+ {11:[No Name] [+] }|
+ | 1| 1 {12:2 3} |
+ | 2| A {12:B C} |
+ | 3| 4 {12:5 6} |
+ | 4| X {12:Y Z} |
+ | 5| 7 {12:8 9} |
+ | 6| K {12:L M} |
+ | 7| a {12:b c} |
+ | 8| d {12:e f} |
+ | 9| q {12:r s} |
+ |10| x {12:y z} |
+ |11| £ {12:m n} |
+ {10:[Preview] }|
+ :%s/. .$^ |
+ ]])
+
+ feed("/ YYY")
+ screen:expect([[
+ t {12: YYY} |
+ {11:[No Name] [+] }|
+ | 1| 1 {12: YYY} |
+ | 2| A {12: YYY} |
+ | 3| 4 {12: YYY} |
+ | 4| X {12: YYY} |
+ | 5| 7 {12: YYY} |
+ | 6| K {12: YYY} |
+ | 7| a {12: YYY} |
+ | 8| d {12: YYY} |
+ | 9| q {12: YYY} |
+ |10| x {12: YYY} |
+ |11| £ {12: YYY} |
+ {10:[Preview] }|
+ :%s/. .$/ YYY^ |
+ ]])
+
+ feed("\\r KKK")
+ screen:expect([[
+ a {12: YYY} |
+ {11:[No Name] [+] }|
+ | 1| 1 {12: YYY} |
+ | 2|{12: KKK} |
+ | 3| A {12: YYY} |
+ | 4|{12: KKK} |
+ | 5| 4 {12: YYY} |
+ | 6|{12: KKK} |
+ | 7| X {12: YYY} |
+ | 8|{12: KKK} |
+ | 9| 7 {12: YYY} |
+ |10|{12: KKK} |
+ |11| K {12: YYY} |
+ {10:[Preview] }|
+ :%s/. .$/ YYY\r KKK^ |
+ ]])
+ end)
+
+ it(", inccommand=split, lookaround", function()
+ common_setup(screen, "split", "something\neverything\nsomeone")
+ feed([[:%s/\(some\)\@<lt>=thing/one/]])
+ screen:expect([[
+ some{12:one} |
+ everything |
+ someone |
+ {15:~ }|
+ {15:~ }|
+ {11:[No Name] [+] }|
+ |1| some{12:one} |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {10:[Preview] }|
+ :%s/\(some\)\@<=thing/one/^ |
+ ]])
+
+ feed("<C-c>")
+ wait()
+ feed([[:%s/\(some\)\@<lt>!thing/one/]])
+ screen:expect([[
+ something |
+ every{12:one} |
+ someone |
+ {15:~ }|
+ {15:~ }|
+ {11:[No Name] [+] }|
+ |2| every{12:one} |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {10:[Preview] }|
+ :%s/\(some\)\@<!thing/one/^ |
+ ]])
+
+ feed([[<C-c>]])
+ wait()
+ feed([[:%s/some\(thing\)\@=/every/]])
+ screen:expect([[
+ {12:every}thing |
+ everything |
+ someone |
+ {15:~ }|
+ {15:~ }|
+ {11:[No Name] [+] }|
+ |1| {12:every}thing |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {10:[Preview] }|
+ :%s/some\(thing\)\@=/every/^ |
+ ]])
+
+ feed([[<C-c>]])
+ wait()
+ feed([[:%s/some\(thing\)\@!/every/]])
+ screen:expect([[
+ everything |
+ {12:every}one |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {11:[No Name] [+] }|
+ |3| {12:every}one |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {10:[Preview] }|
+ :%s/some\(thing\)\@!/every/^ |
+ ]])
+ end)
+end)
diff --git a/test/functional/ui/tabline_spec.lua b/test/functional/ui/tabline_spec.lua
index 56331a33b5..e8271de0bf 100644
--- a/test/functional/ui/tabline_spec.lua
+++ b/test/functional/ui/tabline_spec.lua
@@ -2,7 +2,7 @@ local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local clear, command, eq = helpers.clear, helpers.command, helpers.eq
-describe('ui/tabline', function()
+describe('ui/ext_tabline', function()
local screen
local event_tabs, event_curtab
@@ -21,37 +21,34 @@ describe('ui/tabline', function()
screen:detach()
end)
- describe('externalized', function()
- it('publishes UI events', function()
- command("tabedit another-tab")
+ it('publishes UI events', function()
+ command("tabedit another-tab")
- local expected_tabs = {
- {tab = { id = 1 }, name = '[No Name]'},
- {tab = { id = 2 }, name = 'another-tab'},
- }
- screen:expect([[
- ^ |
- ~ |
- ~ |
- ~ |
- |
- ]], nil, nil, function()
- eq({ id = 2 }, event_curtab)
- eq(expected_tabs, event_tabs)
- end)
-
- command("tabNext")
- screen:expect([[
- ^ |
- ~ |
- ~ |
- ~ |
- |
- ]], nil, nil, function()
- eq({ id = 1 }, event_curtab)
- eq(expected_tabs, event_tabs)
- end)
+ local expected_tabs = {
+ {tab = { id = 1 }, name = '[No Name]'},
+ {tab = { id = 2 }, name = 'another-tab'},
+ }
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ |
+ ]], nil, nil, function()
+ eq({ id = 2 }, event_curtab)
+ eq(expected_tabs, event_tabs)
+ end)
+ command("tabNext")
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ |
+ ]], nil, nil, function()
+ eq({ id = 1 }, event_curtab)
+ eq(expected_tabs, event_tabs)
end)
end)
end)
diff --git a/test/functional/ui/wildmode_spec.lua b/test/functional/ui/wildmode_spec.lua
index 6ce76568db..042969357e 100644
--- a/test/functional/ui/wildmode_spec.lua
+++ b/test/functional/ui/wildmode_spec.lua
@@ -180,7 +180,7 @@ describe('command line completion', function()
end)
end)
-describe('External wildmenu', function()
+describe('ui/ext_wildmenu', function()
local screen
local items, selected = nil, nil
@@ -263,8 +263,6 @@ describe('External wildmenu', function()
eq(0, selected)
end)
-
-
feed('a')
screen:expect([[
|
diff --git a/test/functional/viml/completion_spec.lua b/test/functional/viml/completion_spec.lua
index 0e5278345c..b70ef724b7 100644
--- a/test/functional/viml/completion_spec.lua
+++ b/test/functional/viml/completion_spec.lua
@@ -868,7 +868,7 @@ describe('completion', function()
end)
end)
-describe('ui/externalized/popupmenu', function()
+describe('ui/ext_popupmenu', function()
local screen
local items, selected, anchor
before_each(function()