Compare commits

...

10 Commits

Author SHA1 Message Date
Brian Walshe
644dbfca43
Merge 5b410d1e49 into 738320188f 2024-12-18 11:16:42 +01:00
zeertzjq
738320188f
test(old): fix incorrect comment in test_preview.vim (#31619) 2024-12-18 10:21:52 +08:00
zeertzjq
38f554e9c4
vim-patch:a977883: runtime(doc): Fix style in fold.txt (#31617)
closes: vim/vim#16236

a977883ef3

Co-authored-by: h-east <h.east.727@gmail.com>
2024-12-18 09:12:04 +08:00
zeertzjq
f7c42433c5
vim-patch:9.1.0940: Wrong cursor shape with "gq" and 'indentexpr' executes :normal (#31616)
Problem:  Wrong cursor shape with "gq" and 'indentexpr' executes :normal
Solution: Update cursor and mouse shape after restoring old_State.
          (zeertzjq)

closes: vim/vim#16241

Solution: Update cursor and mouse shape after restoring old_State.

6c3027744e
2024-12-18 09:04:32 +08:00
zeertzjq
51c380238c
Merge pull request #31615 from zeertzjq/vim-9.1.0936
vim-patch:9.1.{0936,0941,0942}: ComplMatchIns highlight
2024-12-18 08:40:23 +08:00
zeertzjq
b7da54aa9e vim-patch:9.1.0942: a few typos were found
Problem:  a few typos were found
Solution: fix them (zeertzjq)

closes: vim/vim#16232

d32bf0a067
2024-12-18 08:15:31 +08:00
zeertzjq
2f7b385f2e vim-patch:9.1.0941: ComplMatchIns doesn't work after multibyte chars
Problem:  ComplMatchIns doesn't work after multibyte chars
          (after v9.1.0936)
Solution: Use (ptr - line) instead of wlv.col (zeertzjq).

closes: vim/vim#16233

f4ccada5c3
2024-12-18 08:15:31 +08:00
zeertzjq
c830901e8c vim-patch:9.1.0936: cannot highlight completed text
Problem:  cannot highlight completed text
Solution: (optionally) highlight auto-completed text using the
          ComplMatchIns highlight group (glepnir)

closes: vim/vim#16173

6a38aff218

Co-authored-by: glepnir <glephunter@gmail.com>
2024-12-18 08:15:31 +08:00
Brian Walshe
5b410d1e49 feat(editor): :read reads the output of an Ex command into the buffer 2024-12-16 10:17:51 +00:00
Brian Walshe
c792dbc013 feat(editor): :read reads the output of an Ex command into the buffer
Problem: :read can read from files or stdin, but not from other Ex commands

Solution: use `put=execute(cmd)` to execute cmd and send its output to the
buffer
2024-12-13 16:08:35 +00:00
17 changed files with 427 additions and 41 deletions

View File

@ -60,6 +60,7 @@ hi('PmenuMatch', { link = 'Pmenu' })
hi('PmenuMatchSel', { link = 'PmenuSel' })
hi('PmenuExtra', { link = 'Pmenu' })
hi('PmenuExtraSel', { link = 'PmenuSel' })
hi('ComplMatchIns', { link = 'Normal' })
hi('Substitute', { link = 'Search' })
hi('Whitespace', { link = 'NonText' })
hi('MsgSeparator', { link = 'StatusLine' })

View File

@ -101,7 +101,8 @@ The result of foldexpr then determines the fold level as follows:
"<1", "<2", .. a fold with this level ends at this line
">1", ">2", .. a fold with this level starts at this line
The result values "=", "s" and "a" are more expensive, please see |fold-expr-slow|.
The result values "=", "s" and "a" are more expensive, please see
|fold-expr-slow|.
It is not required to mark the start (end) of a fold with ">1" ("<1"), a fold
will also start (end) when the fold level is higher (lower) than the fold
@ -117,7 +118,7 @@ For debugging the 'debug' option can be set to "msg", the error messages will
be visible then.
If the 'foldexpr' expression starts with s: or |<SID>|, then it is replaced
with the script ID (|local-function|). Examples: >
with the script ID (|local-function|). Examples: >
set foldexpr=s:MyFoldExpr()
set foldexpr=<SID>SomeFoldExpr()
<
@ -141,7 +142,7 @@ end in that line.
It may happen that folds are not updated properly. You can use |zx| or |zX|
to force updating folds.
Minimizing Computational Cost *fold-expr-slow*
MINIMIZING COMPUTATIONAL COST *fold-expr-slow*
Due to its computational cost, this fold method can make Vim unresponsive,
especially when the fold level of all lines have to be initially computed.
@ -149,13 +150,15 @@ Afterwards, after each change, Vim restricts the computation of foldlevels
to those lines whose fold level was affected by it (and reuses the known
foldlevels of all the others).
The fold expression should therefore strive to minimize the number of dependent
lines needed for the computation of a given line: For example, try to avoid the
"=", "a" and "s" return values, because these will require the evaluation of the
fold levels on previous lines until an independent fold level is found.
The fold expression should therefore strive to minimize the number of
dependent lines needed for the computation of a given line: For example, try
to avoid the "=", "a" and "s" return values, because these will require the
evaluation of the fold levels on previous lines until an independent fold
level is found.
If this proves difficult, the next best thing could be to cache all fold levels
in a buffer-local variable (b:foldlevels) that is only updated on |b:changedtick|:
If this proves difficult, the next best thing could be to cache all fold
levels in a buffer-local variable (b:foldlevels) that is only updated on
|b:changedtick|:
>vim
func MyFoldFunc()
if b:lasttick == b:changedtick
@ -406,8 +409,8 @@ zX Undo manually opened and closed folds: re-apply 'foldlevel'.
Also forces recomputing folds, like |zx|.
*zm*
zm Fold more: Subtract |v:count1| from 'foldlevel'. If 'foldlevel' was
already zero nothing happens.
zm Fold more: Subtract |v:count1| from 'foldlevel'. If
'foldlevel' was already zero nothing happens.
'foldenable' will be set.
*zM*
@ -471,7 +474,7 @@ zk Move upwards to the end of the previous fold. A closed fold
EXECUTING COMMANDS ON FOLDS ~
:[range]foldd[oopen] {cmd} *:foldd* *:folddo* *:folddoopen*
:[range]foldd[oopen] {cmd} *:foldd* *:folddo* *:folddoopen*
Execute {cmd} on all lines that are not in a closed fold.
When [range] is given, only these lines are used.
Each time {cmd} is executed the cursor is positioned on the
@ -559,7 +562,7 @@ When there is room after the text, it is filled with the character specified
by 'fillchars'.
If the 'foldtext' expression starts with s: or |<SID>|, then it is replaced
with the script ID (|local-function|). Examples: >
with the script ID (|local-function|). Examples: >
set foldtext=s:MyFoldText()
set foldtext=<SID>SomeFoldText()
<

View File

@ -2010,15 +2010,21 @@ NOTE: These commands cannot be used with |:global| or |:vglobal|.
*:r!* *:read!*
:[range]r[ead] [++opt] !{cmd}
Execute {cmd} and insert its standard output below
the cursor or the specified line. A temporary file is
used to store the output of the command which is then
read into the buffer. 'shellredir' is used to save
the output of the command, which can be set to include
stderr or not. {cmd} is executed like with ":!{cmd}",
any '!' is replaced with the previous command |:!|.
Execute shell {cmd} and insert its standard output
below the cursor or the specified line. A temporary
file is used to store the output of the command which
is then read into the buffer. 'shellredir' is used to
save the output of the command, which can be set to
include stderr or not. {cmd} is executed like with
":!{cmd}", any '!' is replaced with the previous
command |:!|.
See |++opt| for the possible values of [++opt].
*:r:* *:read:*
:[range]r[ead] :{cmd}
Execute Ex command {cmd} and insert its output below
the cursor or the specified line.
These commands insert the contents of a file, or the output of a command,
into the buffer. They can be undone. They cannot be repeated with the "."
command. They work on a line basis, insertion starts below the line in which

View File

@ -118,8 +118,8 @@ Note that when using ":" any motion becomes charwise exclusive.
*inclusive-motion-selection-exclusive*
When 'selection' is "exclusive", |Visual| mode is active and an inclusive
motion has been used, the cursor position will be adjusted by another
character to the right, so that visual selction includes the expected text and
can be acted upon.
character to the right, so that the Visual selection includes the expected
text and can be acted upon.
*forced-motion*
FORCING A MOTION TO BE LINEWISE, CHARWISE OR BLOCKWISE

View File

@ -216,7 +216,10 @@ EDITOR
• On Windows, filename arguments on the command-line prefixed with "~\" or
"~/" are now expanded to the user's profile directory, not a relative path
to a literal "~" directory.
• |hl-ComplMatchIns| shows matched text of the currently inserted completion.
• |hl-PmenuMatch| and |hl-PmenuMatchSel| show matched text in completion popup.
• |:read:| reads the output of an Ex command into the buffer. Example:>
:read :ls
EVENTS

View File

@ -5243,6 +5243,8 @@ PmenuMatch Popup menu: Matched text in normal item. Combined with
*hl-PmenuMatchSel*
PmenuMatchSel Popup menu: Matched text in selected item. Combined with
|hl-PmenuMatch| and |hl-PmenuSel|.
*hl-ComplMatchIns*
ComplMatchIns Matched text of the currently inserted completion.
*hl-Question*
Question |hit-enter| prompt and yes/no questions.
*hl-QuickFixLine*

View File

@ -31,6 +31,7 @@
#include "nvim/highlight_defs.h"
#include "nvim/highlight_group.h"
#include "nvim/indent.h"
#include "nvim/insexpand.h"
#include "nvim/mark_defs.h"
#include "nvim/marktree_defs.h"
#include "nvim/match.h"
@ -934,6 +935,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s
colnr_T vcol_prev = -1; // "wlv.vcol" of previous character
ScreenGrid *grid = &wp->w_grid; // grid specific to the window
const bool in_curline = wp == curwin && lnum == curwin->w_cursor.lnum;
const bool has_fold = foldinfo.fi_level != 0 && foldinfo.fi_lines > 0;
const bool has_foldtext = has_fold && *wp->w_p_fdt != NUL;
@ -1117,7 +1119,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s
}
// Check if the char under the cursor should be inverted (highlighted).
if (!highlight_match && lnum == curwin->w_cursor.lnum && wp == curwin
if (!highlight_match && in_curline
&& cursor_is_block_during_visual(*p_sel == 'e')) {
noinvcur = true;
}
@ -1629,8 +1631,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s
}
// When still displaying '$' of change command, stop at cursor.
if (dollar_vcol >= 0 && wp == curwin
&& lnum == wp->w_cursor.lnum && wlv.vcol >= wp->w_virtcol) {
if (dollar_vcol >= 0 && in_curline && wlv.vcol >= wp->w_virtcol) {
draw_virt_text(wp, buf, win_col_offset, &wlv.col, wlv.row);
// don't clear anything after wlv.col
wlv_put_linebuf(wp, &wlv, wlv.col, false, bg_attr, 0);
@ -1786,6 +1787,16 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s
wlv.char_attr = hl_combine_attr(char_attr_base, char_attr_pri);
}
// Apply ComplMatchIns highlight if needed.
if (wlv.filler_todo <= 0
&& (State & MODE_INSERT) && in_curline && ins_compl_active()) {
int ins_match_attr = ins_compl_col_range_attr((int)(ptr - line));
if (ins_match_attr > 0) {
char_attr_pri = hl_combine_attr(char_attr_pri, ins_match_attr);
wlv.char_attr = hl_combine_attr(char_attr_base, char_attr_pri);
}
}
if (draw_folded && has_foldtext && wlv.n_extra == 0 && wlv.col == win_col_offset) {
const int v = (int)(ptr - line);
linenr_T lnume = lnum + foldinfo.fi_lines - 1;
@ -2446,8 +2457,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s
// With 'virtualedit' we may never reach cursor position, but we still
// need to correct the cursor column, so do that at end of line.
if (!did_wcol && wlv.filler_todo <= 0
&& wp == curwin && lnum == wp->w_cursor.lnum
&& conceal_cursor_line(wp)
&& in_curline && conceal_cursor_line(wp)
&& (wlv.vcol + wlv.skip_cells >= wp->w_virtcol || mb_schar == NUL)) {
wp->w_wcol = wlv.col - wlv.boguscols;
if (wlv.vcol + wlv.skip_cells < wp->w_virtcol) {
@ -2640,7 +2650,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s
// Update w_cline_height and w_cline_folded if the cursor line was
// updated (saves a call to plines_win() later).
if (wp == curwin && lnum == curwin->w_cursor.lnum) {
if (in_curline) {
curwin->w_cline_row = startrow;
curwin->w_cline_height = wlv.row - startrow;
curwin->w_cline_folded = has_fold;

View File

@ -12,8 +12,10 @@
#include <uv.h>
#include "auto/config.h"
#include "klib/kvec.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
#include "nvim/api/vim.h"
#include "nvim/arglist.h"
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
@ -5826,6 +5828,31 @@ static void ex_syncbind(exarg_T *eap)
}
}
void do_read_cmd(exarg_T *eap)
{
Object cmd = CSTR_AS_OBJ(eap->arg + 1);
String cmd_var_name = cstr_as_string("_ex_cmd");
StringBuilder put_cmd = KV_INITIAL_VALUE;
Error error = ERROR_INIT;
nvim_set_var(cmd_var_name, cmd, &error);
if (error.type != kErrorTypeNone) {
emsg(error.msg);
return;
}
kv_printf(put_cmd, "%dput=execute(g:%s) | ", eap->line2, cmd_var_name.data);
kv_printf(put_cmd, "execute 'norm! )`.' | ");
kv_printf(put_cmd, "execute 'd _' | ");
do_cmdline(put_cmd.items, eap->ea_getline, eap->cookie, eap->flags);
kv_destroy(put_cmd);
nvim_del_var(cmd_var_name, &error);
if (error.type != kErrorTypeNone) {
emsg(error.msg);
return;
}
}
static void ex_read(exarg_T *eap)
{
int empty = (curbuf->b_ml.ml_flags & ML_EMPTY);
@ -5835,6 +5862,11 @@ static void ex_read(exarg_T *eap)
return;
}
if (*eap->arg == ':') {
do_read_cmd(eap);
return;
}
if (u_save(eap->line2, (linenr_T)(eap->line2 + 1)) == FAIL) {
return;
}

View File

@ -173,6 +173,7 @@ static const char *highlight_init_both[] = {
"default link PmenuKind Pmenu",
"default link PmenuKindSel PmenuSel",
"default link PmenuSbar Pmenu",
"default link ComplMatchIns Normal",
"default link Substitute Search",
"default link StatusLineTerm StatusLine",
"default link StatusLineTermNC StatusLineNC",

View File

@ -256,6 +256,7 @@ static pos_T compl_startpos;
static int compl_length = 0;
static colnr_T compl_col = 0; ///< column where the text starts
///< that is being completed
static colnr_T compl_ins_end_col = 0;
static char *compl_orig_text = NULL; ///< text as it was before
///< completion started
/// Undo information to restore extmarks for original text.
@ -282,6 +283,11 @@ static size_t spell_bad_len = 0; // length of located bad word
static int compl_selected_item = -1;
// "compl_match_array" points the currently displayed list of entries in the
// popup menu. It is NULL when there is no popup menu.
static pumitem_T *compl_match_array = NULL;
static int compl_match_arraysize;
/// CTRL-X pressed in Insert mode.
void ins_ctrl_x(void)
{
@ -943,6 +949,30 @@ static bool ins_compl_equal(compl_T *match, char *str, size_t len)
return strncmp(match->cp_str, str, len) == 0;
}
/// when len is -1 mean use whole length of p otherwise part of p
static void ins_compl_insert_bytes(char *p, int len)
FUNC_ATTR_NONNULL_ALL
{
if (len == -1) {
len = (int)strlen(p);
}
assert(len >= 0);
ins_bytes_len(p, (size_t)len);
compl_ins_end_col = curwin->w_cursor.col - 1;
}
/// Checks if the column is within the currently inserted completion text
/// column range. If it is, it returns a special highlight attribute.
/// -1 mean normal item.
int ins_compl_col_range_attr(int col)
{
if (col >= compl_col && col < compl_ins_end_col) {
return syn_name2attr("ComplMatchIns");
}
return -1;
}
/// Reduce the longest common string for match "match".
static void ins_compl_longest_match(compl_T *match)
{
@ -952,7 +982,7 @@ static void ins_compl_longest_match(compl_T *match)
bool had_match = (curwin->w_cursor.col > compl_col);
ins_compl_delete(false);
ins_bytes(compl_leader + get_compl_len());
ins_compl_insert_bytes(compl_leader + get_compl_len(), -1);
ins_redraw(false);
// When the match isn't there (to avoid matching itself) remove it
@ -986,7 +1016,7 @@ static void ins_compl_longest_match(compl_T *match)
*p = NUL;
bool had_match = (curwin->w_cursor.col > compl_col);
ins_compl_delete(false);
ins_bytes(compl_leader + get_compl_len());
ins_compl_insert_bytes(compl_leader + get_compl_len(), -1);
ins_redraw(false);
// When the match isn't there (to avoid matching itself) remove it
@ -1058,11 +1088,6 @@ unsigned get_cot_flags(void)
return curbuf->b_cot_flags != 0 ? curbuf->b_cot_flags : cot_flags;
}
/// "compl_match_array" points the currently displayed list of entries in the
/// popup menu. It is NULL when there is no popup menu.
static pumitem_T *compl_match_array = NULL;
static int compl_match_arraysize;
/// Remove any popup menu.
static void ins_compl_del_pum(void)
{
@ -1678,6 +1703,7 @@ void ins_compl_clear(void)
compl_cont_status = 0;
compl_started = false;
compl_matches = 0;
compl_ins_end_col = 0;
XFREE_CLEAR(compl_pattern);
compl_patternlen = 0;
XFREE_CLEAR(compl_leader);
@ -1802,7 +1828,7 @@ static void ins_compl_new_leader(void)
{
ins_compl_del_pum();
ins_compl_delete(true);
ins_bytes(compl_leader + get_compl_len());
ins_compl_insert_bytes(compl_leader + get_compl_len(), -1);
compl_used_match = false;
if (compl_started) {
@ -2137,7 +2163,7 @@ static bool ins_compl_stop(const int c, const int prev_mode, bool retval)
const int compl_len = get_compl_len();
const int len = (int)strlen(p);
if (len > compl_len) {
ins_bytes_len(p + compl_len, (size_t)(len - compl_len));
ins_compl_insert_bytes(p + compl_len, len - compl_len);
}
}
restore_orig_extmarks();
@ -3639,7 +3665,7 @@ void ins_compl_insert(bool in_compl_func)
// Make sure we don't go over the end of the string, this can happen with
// illegal bytes.
if (compl_len < (int)strlen(compl_shown_match->cp_str)) {
ins_bytes(compl_shown_match->cp_str + compl_len);
ins_compl_insert_bytes(compl_shown_match->cp_str + compl_len, -1);
}
compl_used_match = !match_at_original_text(compl_shown_match);
@ -3888,14 +3914,15 @@ static int ins_compl_next(bool allow_get_expansion, int count, bool insert_match
// Insert the text of the new completion, or the compl_leader.
if (compl_no_insert && !started) {
ins_bytes(compl_orig_text + get_compl_len());
ins_compl_insert_bytes(compl_orig_text + get_compl_len(), -1);
compl_used_match = false;
restore_orig_extmarks();
} else if (insert_match) {
if (!compl_get_longest || compl_used_match) {
ins_compl_insert(in_compl_func);
} else {
ins_bytes(compl_leader + get_compl_len());
assert(compl_leader != NULL);
ins_compl_insert_bytes(compl_leader + get_compl_len(), -1);
}
if (!strcmp(compl_curr_match->cp_str, compl_orig_text)) {
restore_orig_extmarks();

View File

@ -35,6 +35,7 @@
#include "nvim/strings.h"
#include "nvim/textformat.h"
#include "nvim/textobject.h"
#include "nvim/ui.h"
#include "nvim/undo.h"
#include "nvim/vim_defs.h"
#include "nvim/window.h"
@ -1049,12 +1050,18 @@ void format_lines(linenr_T line_count, bool avoid_fex)
State = MODE_INSERT; // for open_line()
smd_save = p_smd;
p_smd = false;
insertchar(NUL, INSCHAR_FORMAT
+ (do_comments ? INSCHAR_DO_COM : 0)
+ (do_comments && do_comments_list ? INSCHAR_COM_LIST : 0)
+ (avoid_fex ? INSCHAR_NO_FEX : 0), second_indent);
State = old_State;
p_smd = smd_save;
// Cursor shape may have been updated (e.g. by :normal) in insertchar(),
// so it needs to be updated here.
ui_cursor_shape();
second_indent = -1;
// at end of par.: need to set indent of next par.
need_set_indent = is_end_par;

View File

@ -0,0 +1,94 @@
local t = require('test.testutil')
local n = require('test.functional.testnvim')()
local eq, write_file, clear, pcall_err = t.eq, t.write_file, n.clear, t.pcall_err
local fn = n.fn
local setline, getline, setcharpos, execute = fn.setline, fn.getline, fn.setcharpos, fn.execute
local tmp_file = 'text.txt'
local original_text = { 'First', 'Last' }
local read_text = { ' This is a line starts with a space', ' This one starts with two spaces.' }
local inserted_middle = { original_text[1], read_text[1], read_text[2], original_text[2] }
local inserted_start = { read_text[1], read_text[2], original_text[1], original_text[2] }
local function test_read(cmd, expected)
setline(1, original_text)
setcharpos('.', { 0, 0, 0 })
execute(cmd)
for i, e in ipairs(expected) do
eq(e, getline(i))
end
end
local function test_undo(cmd)
setline(1, original_text)
execute(cmd)
execute('undo')
eq(original_text, { getline(1), getline(2) })
end
describe(':read', function()
local function cleanup()
os.remove(tmp_file)
end
before_each(function()
clear()
cleanup()
write_file(tmp_file, table.concat(read_text, '\n'), true)
end)
after_each(cleanup)
it('inserts text from file', function()
test_read('read ' .. tmp_file, inserted_middle)
eq({ 0, 2, 2, 0 }, fn.getpos('.'))
end)
it('inserts text from shell', function()
test_read('read !cat ' .. tmp_file, inserted_middle)
eq({ 0, 3, 3, 0 }, fn.getpos('.'))
end)
it('inserts text from Ex command', function()
local make_lines = string.format('let lines="%s"', table.concat(read_text, '\\n'))
execute(make_lines)
test_read('read :echo lines', inserted_middle)
end)
it('inserts text from file at specific position', function()
test_read('0read ' .. tmp_file, inserted_start)
eq({ 0, 1, 2, 0 }, fn.getpos('.'))
end)
it('inserts text from shell cmd at specific position', function()
test_read('0read !cat ' .. tmp_file, inserted_start)
eq({ 0, 2, 3, 0 }, fn.getpos('.'))
end)
it('executes next command when using |', function()
local make_lines = string.format('let lines="%s"', table.concat(read_text, '\\n'))
execute(make_lines)
execute("let guard = 'fail'")
test_read("read :echo lines | let guard='pass'", inserted_middle)
eq('pass', vim.trim(execute('echo guard')))
end)
it('sets fileformat, fileencoding, bomb correctly', function()
execute('set fileformat=dos')
execute('set fileencoding=latin1')
execute('set bomb')
execute('read ++edit ' .. tmp_file)
eq('fileformat=unix', vim.trim(execute('set fileformat?')))
eq('fileencoding=utf-8', vim.trim(execute('set fileencoding?')))
eq('nobomb', vim.trim(execute('set bomb?')))
end)
it('file reads can be undone', function()
test_undo('read ' .. tmp_file)
end)
it('shell reads can be undone', function()
test_undo('read !cat ' .. tmp_file)
end)
it('command reads can be undone', function()
local make_lines = string.format('let lines="%s"', table.concat(read_text, '\\n'))
execute(make_lines)
test_undo('read :echo lines')
end)
it('errors out correctly when a non-existant file is used', function()
eq("Vim(read):E484: Can't open file asdfasdf", pcall_err(execute, ':read asdfasdf'))
end)
it('errors out correctly when an invalid command is used', function()
eq('Vim:E492: Not an editor command: asdfasdf', pcall_err(execute, ':read :asdfasdf'))
end)
end)

View File

@ -94,6 +94,46 @@ describe('ui mode_change event', function()
}
end)
-- oldtest: Test_indent_norm_with_gq()
it('is restored to Normal mode after "gq" indents using :normal #12309', function()
screen:try_resize(60, 6)
n.exec([[
func Indent()
exe "normal! \<Ignore>"
return 0
endfunc
setlocal indentexpr=Indent()
call setline(1, [repeat('a', 80), repeat('b', 80)])
]])
feed('ggVG')
screen:expect {
grid = [[
{17:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}|
{17:aaaaaaaaaaaaaaaaaaaa} |
^b{17:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb}|
{17:bbbbbbbbbbbbbbbbbbbb} |
{1:~ }|
{5:-- VISUAL LINE --} |
]],
mode = 'visual',
}
feed('gq')
screen:expect {
grid = [[
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
aaaaaaaaaaaaaaaaaaaa |
^bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
bbbbbbbbbbbbbbbbbbbb |
{1:~ }|
|
]],
mode = 'normal',
}
end)
it('works in insert mode', function()
feed('i')
screen:expect {

View File

@ -5561,6 +5561,71 @@ describe('builtin popupmenu', function()
]])
feed('<C-E><ESC>')
end)
-- oldtest: Test_pum_matchins_highlight()
it('with ComplMatchIns highlight', function()
exec([[
func Omni_test(findstart, base)
if a:findstart
return col(".")
endif
return [#{word: "foo"}, #{word: "bar"}, #{word: "你好"}]
endfunc
set omnifunc=Omni_test
hi ComplMatchIns guifg=red
]])
feed('Sαβγ <C-X><C-O>')
screen:expect([[
αβγ {8:foo}^ |
{1:~ }{s: foo }{1: }|
{1:~ }{n: bar }{1: }|
{1:~ }{n: }{1: }|
{1:~ }|*15
{2:-- }{5:match 1 of 3} |
]])
feed('<C-E><Esc>')
feed('Sαβγ <C-X><C-O><C-N>')
screen:expect([[
αβγ {8:bar}^ |
{1:~ }{n: foo }{1: }|
{1:~ }{s: bar }{1: }|
{1:~ }{n: }{1: }|
{1:~ }|*15
{2:-- }{5:match 2 of 3} |
]])
feed('<C-E><Esc>')
feed('Sαβγ <C-X><C-O><C-N><C-N>')
screen:expect([[
αβγ {8:}^ |
{1:~ }{n: foo }{1: }|
{1:~ }{n: bar }{1: }|
{1:~ }{s: }{1: }|
{1:~ }|*15
{2:-- }{5:match 3 of 3} |
]])
feed('<C-E><Esc>')
-- restore after accept
feed('Sαβγ <C-X><C-O><C-Y>')
screen:expect([[
αβγ foo^ |
{1:~ }|*18
{2:-- INSERT --} |
]])
feed('<Esc>')
-- restore after cancel completion
feed('Sαβγ <C-X><C-O><Space>')
screen:expect([[
αβγ foo ^ |
{1:~ }|*18
{2:-- INSERT --} |
]])
feed('<Esc>')
end)
end
end

View File

@ -1,5 +1,8 @@
" Test for various indent options
source shared.vim
source check.vim
func Test_preserveindent()
new
" Test for autoindent copying indent from the previous line
@ -303,4 +306,50 @@ func Test_indent_overflow_count2()
close!
endfunc
" Test that mouse shape is restored to Normal mode after using "gq" when
" 'indentexpr' executes :normal.
func Test_indent_norm_with_gq()
CheckFeature mouseshape
CheckCanRunGui
let lines =<< trim END
func Indent()
exe "normal! \<Ignore>"
return 0
endfunc
setlocal indentexpr=Indent()
END
call writefile(lines, 'Xindentexpr.vim', 'D')
let lines =<< trim END
vim9script
var mouse_shapes = []
setline(1, [repeat('a', 80), repeat('b', 80)])
feedkeys('ggVG')
timer_start(50, (_) => {
mouse_shapes += [getmouseshape()]
timer_start(50, (_) => {
feedkeys('gq')
timer_start(50, (_) => {
mouse_shapes += [getmouseshape()]
timer_start(50, (_) => {
writefile(mouse_shapes, 'Xmouseshapes')
quit!
})
})
})
})
END
call writefile(lines, 'Xmouseshape.vim', 'D')
call RunVim([], [], "-g -S Xindentexpr.vim -S Xmouseshape.vim")
call WaitForAssert({-> assert_equal(['rightup-arrow', 'arrow'],
\ readfile('Xmouseshapes'))}, 300)
call delete('Xmouseshapes')
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@ -1713,4 +1713,49 @@ func Test_pum_keep_select()
call StopVimInTerminal(buf)
endfunc
func Test_pum_matchins_highlight()
CheckScreendump
let lines =<< trim END
func Omni_test(findstart, base)
if a:findstart
return col(".")
endif
return [#{word: "foo"}, #{word: "bar"}, #{word: "你好"}]
endfunc
set omnifunc=Omni_test
hi ComplMatchIns ctermfg=red
END
call writefile(lines, 'Xscript', 'D')
let buf = RunVimInTerminal('-S Xscript', {})
call TermWait(buf)
call term_sendkeys(buf, "Sαβγ \<C-X>\<C-O>")
call VerifyScreenDump(buf, 'Test_pum_matchins_01', {})
call term_sendkeys(buf, "\<C-E>\<Esc>")
call TermWait(buf)
call term_sendkeys(buf, "Sαβγ \<C-X>\<C-O>\<C-N>")
call VerifyScreenDump(buf, 'Test_pum_matchins_02', {})
call term_sendkeys(buf, "\<C-E>\<Esc>")
call TermWait(buf)
call term_sendkeys(buf, "Sαβγ \<C-X>\<C-O>\<C-N>\<C-N>")
call VerifyScreenDump(buf, 'Test_pum_matchins_03', {})
call term_sendkeys(buf, "\<C-E>\<Esc>")
" restore after accept
call TermWait(buf)
call term_sendkeys(buf, "Sαβγ \<C-X>\<C-O>\<C-Y>")
call VerifyScreenDump(buf, 'Test_pum_matchins_04', {})
call term_sendkeys(buf, "\<C-E>\<Esc>")
" restore after cancel completion
call TermWait(buf)
call term_sendkeys(buf, "Sαβγ \<C-X>\<C-O>\<Space>")
call VerifyScreenDump(buf, 'Test_pum_matchins_05', {})
call term_sendkeys(buf, "\<C-E>\<Esc>")
call StopVimInTerminal(buf)
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@ -59,7 +59,8 @@ func Test_window_preview_terminal()
CheckFeature quickfix
" CheckFeature terminal
term " ++curwin
" term ++curwin
term
const buf_num = bufnr('$')
call assert_equal(1, winnr('$'))
exe 'pbuffer' . buf_num