Compare commits

...

5 Commits

Author SHA1 Message Date
glepnir
5dcb752988
Merge a9251f760a into 02bc40c194 2024-12-19 12:40:46 +09:00
zeertzjq
02bc40c194
vim-patch:9.1.0945: ComplMatchIns highlight doesn't end after inserted text (#31628)
Problem:  ComplMatchIns highlight doesn't end after inserted text.
Solution: Handle ComplMatchIns highlight more like search highlight.
          Fix off-by-one error. Handle deleting text properly.
          (zeertzjq)

closes: vim/vim#16244

f25d8f9312
2024-12-18 23:59:03 +00:00
luukvbaal
160cbd0ef4
test(cursor_spec): global highlight definitions (#31613) 2024-12-18 19:06:16 +00:00
Gregory Anders
3db3947b0e
fix(terminal): restore cursor from 'guicursor' on TermLeave (#31620)
Fixes: https://github.com/neovim/neovim/issues/31612
2024-12-18 11:41:05 -06:00
glepnir
a9251f760a fix(api): support get autocmds by id in api
Problem: Can not use id as filter condition to get autocmds.

Solution: add id which support integer or array to filter get autocmds
2024-12-16 16:55:32 +08:00
16 changed files with 396 additions and 127 deletions

View File

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

View File

@ -3589,33 +3589,35 @@ nvim_get_autocmds({opts}) *nvim_get_autocmds()*
Parameters: ~ Parameters: ~
• {opts} Dict with at least one of the following: • {opts} Dict with at least one of the following:
• group (string|integer): the autocommand group name or id to • buffer: (integer) Buffer number or list of buffer numbers
match against. for buffer local autocommands |autocmd-buflocal|. Cannot be
• event (string|array): event or events to match against used with {pattern}
• event: (string|table) event or events to match against
|autocmd-events|. |autocmd-events|.
• pattern (string|array): pattern or patterns to match against • id: (integer) Autocommand ID to match.
• group: (string|table) the autocommand group name or id to
match against.
• pattern: (string|table) pattern or patterns to match against
|autocmd-pattern|. Cannot be used with {buffer} |autocmd-pattern|. Cannot be used with {buffer}
• buffer: Buffer number or list of buffer numbers for buffer
local autocommands |autocmd-buflocal|. Cannot be used with
{pattern}
Return: ~ Return: ~
Array of autocommands matching the criteria, with each item containing Array of autocommands matching the criteria, with each item containing
the following fields: the following fields:
• id (number): the autocommand id (only when defined with the API). • buffer: (integer) the buffer number.
• group (integer): the autocommand group id. • buflocal: (boolean) true if the autocommand is buffer local.
• group_name (string): the autocommand group name. • command: (string) the autocommand command. Note: this will be empty
• desc (string): the autocommand description.
• event (string): the autocommand event.
• command (string): the autocommand command. Note: this will be empty
if a callback is set. if a callback is set.
• callback (function|string|nil): Lua function or name of a Vim script • callback: (function|string|nil): Lua function or name of a Vim
function which is executed when this autocommand is triggered. script function which is executed when this autocommand is
• once (boolean): whether the autocommand is only run once. triggered.
• pattern (string): the autocommand pattern. If the autocommand is • desc: (string) the autocommand description.
• event: (string) the autocommand event.
• id: (integer) the autocommand id (only when defined with the API).
• group: (integer) the autocommand group id.
• group_name: (string) the autocommand group name.
• once: (boolean) whether the autocommand is only run once.
• pattern: (string) the autocommand pattern. If the autocommand is
buffer local |autocmd-buffer-local|: buffer local |autocmd-buffer-local|:
• buflocal (boolean): true if the autocommand is buffer local.
• buffer (number): the buffer number.
============================================================================== ==============================================================================

View File

@ -1254,27 +1254,28 @@ function vim.api.nvim_get_all_options_info() end
--- match any combination of them. --- match any combination of them.
--- ---
--- @param opts vim.api.keyset.get_autocmds Dict with at least one of the following: --- @param opts vim.api.keyset.get_autocmds Dict with at least one of the following:
--- - group (string|integer): the autocommand group name or id to match against. --- - buffer: (integer) Buffer number or list of buffer numbers for buffer local autocommands
--- - event (string|array): event or events to match against `autocmd-events`.
--- - pattern (string|array): pattern or patterns to match against `autocmd-pattern`.
--- Cannot be used with {buffer}
--- - buffer: Buffer number or list of buffer numbers for buffer local autocommands
--- `autocmd-buflocal`. Cannot be used with {pattern} --- `autocmd-buflocal`. Cannot be used with {pattern}
--- - event: (string|table) event or events to match against `autocmd-events`.
--- - id: (integer) Autocommand ID to match.
--- - group: (string|table) the autocommand group name or id to match against.
--- - pattern: (string|table) pattern or patterns to match against `autocmd-pattern`.
--- Cannot be used with {buffer}
--- @return vim.api.keyset.get_autocmds.ret[] # Array of autocommands matching the criteria, with each item --- @return vim.api.keyset.get_autocmds.ret[] # Array of autocommands matching the criteria, with each item
--- containing the following fields: --- containing the following fields:
--- - id (number): the autocommand id (only when defined with the API). --- - buffer: (integer) the buffer number.
--- - group (integer): the autocommand group id. --- - buflocal: (boolean) true if the autocommand is buffer local.
--- - group_name (string): the autocommand group name. --- - command: (string) the autocommand command. Note: this will be empty if a callback is set.
--- - desc (string): the autocommand description. --- - callback: (function|string|nil): Lua function or name of a Vim script function
--- - event (string): the autocommand event.
--- - command (string): the autocommand command. Note: this will be empty if a callback is set.
--- - callback (function|string|nil): Lua function or name of a Vim script function
--- which is executed when this autocommand is triggered. --- which is executed when this autocommand is triggered.
--- - once (boolean): whether the autocommand is only run once. --- - desc: (string) the autocommand description.
--- - pattern (string): the autocommand pattern. --- - event: (string) the autocommand event.
--- - id: (integer) the autocommand id (only when defined with the API).
--- - group: (integer) the autocommand group id.
--- - group_name: (string) the autocommand group name.
--- - once: (boolean) whether the autocommand is only run once.
--- - pattern: (string) the autocommand pattern.
--- If the autocommand is buffer local |autocmd-buffer-local|: --- If the autocommand is buffer local |autocmd-buffer-local|:
--- - buflocal (boolean): true if the autocommand is buffer local.
--- - buffer (number): the buffer number.
function vim.api.nvim_get_autocmds(opts) end function vim.api.nvim_get_autocmds(opts) end
--- Gets information about a channel. --- Gets information about a channel.

View File

@ -116,6 +116,7 @@ error('Cannot require a meta file')
--- @field group? integer|string --- @field group? integer|string
--- @field pattern? string|string[] --- @field pattern? string|string[]
--- @field buffer? integer|integer[] --- @field buffer? integer|integer[]
--- @field id? integer
--- @class vim.api.keyset.get_commands --- @class vim.api.keyset.get_commands
--- @field builtin? boolean --- @field builtin? boolean

View File

@ -68,32 +68,31 @@ static int64_t next_autocmd_id = 1;
/// match any combination of them. /// match any combination of them.
/// ///
/// @param opts Dict with at least one of the following: /// @param opts Dict with at least one of the following:
/// - group (string|integer): the autocommand group name or id to match against. /// - buffer: (integer) Buffer number or list of buffer numbers for buffer local autocommands
/// - event (string|array): event or events to match against |autocmd-events|.
/// - pattern (string|array): pattern or patterns to match against |autocmd-pattern|.
/// Cannot be used with {buffer}
/// - buffer: Buffer number or list of buffer numbers for buffer local autocommands
/// |autocmd-buflocal|. Cannot be used with {pattern} /// |autocmd-buflocal|. Cannot be used with {pattern}
/// - event: (string|table) event or events to match against |autocmd-events|.
/// - id: (integer) Autocommand ID to match.
/// - group: (string|table) the autocommand group name or id to match against.
/// - pattern: (string|table) pattern or patterns to match against |autocmd-pattern|.
/// Cannot be used with {buffer}
/// @return Array of autocommands matching the criteria, with each item /// @return Array of autocommands matching the criteria, with each item
/// containing the following fields: /// containing the following fields:
/// - id (number): the autocommand id (only when defined with the API). /// - buffer: (integer) the buffer number.
/// - group (integer): the autocommand group id. /// - buflocal: (boolean) true if the autocommand is buffer local.
/// - group_name (string): the autocommand group name. /// - command: (string) the autocommand command. Note: this will be empty if a callback is set.
/// - desc (string): the autocommand description. /// - callback: (function|string|nil): Lua function or name of a Vim script function
/// - event (string): the autocommand event.
/// - command (string): the autocommand command. Note: this will be empty if a callback is set.
/// - callback (function|string|nil): Lua function or name of a Vim script function
/// which is executed when this autocommand is triggered. /// which is executed when this autocommand is triggered.
/// - once (boolean): whether the autocommand is only run once. /// - desc: (string) the autocommand description.
/// - pattern (string): the autocommand pattern. /// - event: (string) the autocommand event.
/// - id: (integer) the autocommand id (only when defined with the API).
/// - group: (integer) the autocommand group id.
/// - group_name: (string) the autocommand group name.
/// - once: (boolean) whether the autocommand is only run once.
/// - pattern: (string) the autocommand pattern.
/// If the autocommand is buffer local |autocmd-buffer-local|: /// If the autocommand is buffer local |autocmd-buffer-local|:
/// - buflocal (boolean): true if the autocommand is buffer local.
/// - buffer (number): the buffer number.
Array nvim_get_autocmds(Dict(get_autocmds) *opts, Arena *arena, Error *err) Array nvim_get_autocmds(Dict(get_autocmds) *opts, Arena *arena, Error *err)
FUNC_API_SINCE(9) FUNC_API_SINCE(9)
{ {
// TODO(tjdevries): Would be cool to add nvim_get_autocmds({ id = ... })
ArrayBuilder autocmd_list = KV_INITIAL_VALUE; ArrayBuilder autocmd_list = KV_INITIAL_VALUE;
kvi_init(autocmd_list); kvi_init(autocmd_list);
char *pattern_filters[AUCMD_MAX_PATTERNS]; char *pattern_filters[AUCMD_MAX_PATTERNS];
@ -127,6 +126,8 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Arena *arena, Error *err)
}); });
} }
int id = (HAS_KEY(opts, get_autocmds, id)) ? (int)opts->id : -1;
if (HAS_KEY(opts, get_autocmds, event)) { if (HAS_KEY(opts, get_autocmds, event)) {
check_event = true; check_event = true;
@ -237,6 +238,10 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Arena *arena, Error *err)
continue; continue;
} }
if (id != -1 && ac->id != id) {
continue;
}
// Skip autocmds from invalid groups if passed. // Skip autocmds from invalid groups if passed.
if (group != 0 && ap->group != group) { if (group != 0 && ap->group != group) {
continue; continue;

View File

@ -262,6 +262,7 @@ typedef struct {
Union(Integer, String) group; Union(Integer, String) group;
Union(String, ArrayOf(String)) pattern; Union(String, ArrayOf(String)) pattern;
Union(Integer, ArrayOf(Integer)) buffer; Union(Integer, ArrayOf(Integer)) buffer;
Integer id;
} Dict(get_autocmds); } Dict(get_autocmds);
typedef struct { typedef struct {

View File

@ -955,7 +955,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s
bool area_highlighting = false; // Visual or incsearch highlighting in this line bool area_highlighting = false; // Visual or incsearch highlighting in this line
int vi_attr = 0; // attributes for Visual and incsearch highlighting int vi_attr = 0; // attributes for Visual and incsearch highlighting
int area_attr = 0; // attributes desired by highlighting int area_attr = 0; // attributes desired by highlighting
int search_attr = 0; // attributes desired by 'hlsearch' int search_attr = 0; // attributes desired by 'hlsearch' or ComplMatchIns
int vcol_save_attr = 0; // saved attr for 'cursorcolumn' int vcol_save_attr = 0; // saved attr for 'cursorcolumn'
int decor_attr = 0; // attributes desired by syntax and extmarks int decor_attr = 0; // attributes desired by syntax and extmarks
bool has_syntax = false; // this buffer has syntax highl. bool has_syntax = false; // this buffer has syntax highl.
@ -969,7 +969,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s
int spell_attr = 0; // attributes desired by spelling int spell_attr = 0; // attributes desired by spelling
int word_end = 0; // last byte with same spell_attr int word_end = 0; // last byte with same spell_attr
int cur_checked_col = 0; // checked column for current line int cur_checked_col = 0; // checked column for current line
bool extra_check = 0; // has syntax or linebreak bool extra_check = false; // has extra highlighting
int multi_attr = 0; // attributes desired by multibyte int multi_attr = 0; // attributes desired by multibyte
int mb_l = 1; // multi-byte byte length int mb_l = 1; // multi-byte byte length
int mb_c = 0; // decoded multi-byte character int mb_c = 0; // decoded multi-byte character
@ -1495,6 +1495,10 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s
ptr = line + v; // "line" may have been updated ptr = line + v; // "line" may have been updated
} }
if ((State & MODE_INSERT) && in_curline && ins_compl_active()) {
area_highlighting = true;
}
win_line_start(wp, &wlv); win_line_start(wp, &wlv);
bool draw_cols = true; bool draw_cols = true;
int leftcols_width = 0; int leftcols_width = 0;
@ -1740,6 +1744,14 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s
if (*ptr == NUL) { if (*ptr == NUL) {
has_match_conc = 0; has_match_conc = 0;
} }
// Check if ComplMatchIns highlight is needed.
if ((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) {
search_attr = hl_combine_attr(search_attr, ins_match_attr);
}
}
} }
if (wlv.diff_hlf != (hlf_T)0) { if (wlv.diff_hlf != (hlf_T)0) {
@ -1787,16 +1799,6 @@ 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); 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) { if (draw_folded && has_foldtext && wlv.n_extra == 0 && wlv.col == win_col_offset) {
const int v = (int)(ptr - line); const int v = (int)(ptr - line);
linenr_T lnume = lnum + foldinfo.fi_lines - 1; linenr_T lnume = lnum + foldinfo.fi_lines - 1;

View File

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

View File

@ -958,7 +958,7 @@ static void ins_compl_insert_bytes(char *p, int len)
} }
assert(len >= 0); assert(len >= 0);
ins_bytes_len(p, (size_t)len); ins_bytes_len(p, (size_t)len);
compl_ins_end_col = curwin->w_cursor.col - 1; compl_ins_end_col = curwin->w_cursor.col;
} }
/// Checks if the column is within the currently inserted completion text /// Checks if the column is within the currently inserted completion text
@ -2147,6 +2147,8 @@ static bool ins_compl_stop(const int c, const int prev_mode, bool retval)
&& pum_visible()) { && pum_visible()) {
word = xstrdup(compl_shown_match->cp_str); word = xstrdup(compl_shown_match->cp_str);
retval = true; retval = true;
// May need to remove ComplMatchIns highlight.
redrawWinline(curwin, curwin->w_cursor.lnum);
} }
// CTRL-E means completion is Ended, go back to the typed text. // CTRL-E means completion is Ended, go back to the typed text.
@ -3648,6 +3650,7 @@ void ins_compl_delete(bool new_leader)
return; return;
} }
backspace_until_column(col); backspace_until_column(col);
compl_ins_end_col = curwin->w_cursor.col;
} }
// TODO(vim): is this sufficient for redrawing? Redrawing everything // TODO(vim): is this sufficient for redrawing? Redrawing everything

View File

@ -641,9 +641,6 @@ bool terminal_enter(void)
curwin->w_p_so = 0; curwin->w_p_so = 0;
curwin->w_p_siso = 0; curwin->w_p_siso = 0;
// Save the existing cursor entry since it may be modified by the application
cursorentry_T save_cursorentry = shape_table[SHAPE_IDX_TERM];
// Update the cursor shape table and flush changes to the UI // Update the cursor shape table and flush changes to the UI
s->term->pending.cursor = true; s->term->pending.cursor = true;
refresh_cursor(s->term); refresh_cursor(s->term);
@ -674,8 +671,8 @@ bool terminal_enter(void)
RedrawingDisabled = s->save_rd; RedrawingDisabled = s->save_rd;
apply_autocmds(EVENT_TERMLEAVE, NULL, NULL, false, curbuf); apply_autocmds(EVENT_TERMLEAVE, NULL, NULL, false, curbuf);
shape_table[SHAPE_IDX_TERM] = save_cursorentry; // Restore the terminal cursor to what is set in 'guicursor'
ui_mode_info_set(); (void)parse_shape_opt(SHAPE_CURSOR);
if (save_curwin == curwin->handle) { // Else: window was closed. if (save_curwin == curwin->handle) { // Else: window was closed.
curwin->w_p_cul = save_w_p_cul; curwin->w_p_cul = save_w_p_cul;

View File

@ -899,6 +899,89 @@ describe('autocmd api', function()
eq([[:echo "Buffer"]], normalized_aus[1].command) eq([[:echo "Buffer"]], normalized_aus[1].command)
end) end)
end) end)
describe('id', function()
it('gets events by ID', function()
local id = api.nvim_create_autocmd('BufEnter', {
command = 'echo "hello"',
})
eq({
{
buflocal = false,
command = 'echo "hello"',
event = 'BufEnter',
id = id,
once = false,
pattern = '*',
},
}, api.nvim_get_autocmds({ id = id }))
end)
it('gets events by ID by other filters', function()
local group_name = 'NVIM_GET_AUTOCMDS_ID'
local group = api.nvim_create_augroup(group_name, { clear = true })
local id = api.nvim_create_autocmd('BufEnter', {
command = 'set number',
group = group,
})
api.nvim_create_autocmd('WinEnter', {
group = group,
command = 'set cot&',
})
eq({
{
buflocal = false,
command = 'set number',
event = 'BufEnter',
group = group,
group_name = group_name,
id = id,
once = false,
pattern = '*',
},
}, api.nvim_get_autocmds({ id = id, group = group }))
end)
it('gets events by ID and a specific event', function()
local id = api.nvim_create_autocmd('InsertEnter', { command = 'set number' })
api.nvim_create_autocmd('InsertEnter', { command = 'set wrap' })
eq({
{
buflocal = false,
command = 'set number',
event = 'InsertEnter',
id = id,
once = false,
pattern = '*',
},
}, api.nvim_get_autocmds({ id = id, event = 'InsertEnter' }))
end)
it('gets events by ID and a specific pattern', function()
local id = api.nvim_create_autocmd('InsertEnter', {
pattern = '*.c',
command = 'set number',
})
api.nvim_create_autocmd('InsertEnter', {
pattern = '*.c',
command = 'set wrap',
})
eq({
{
buflocal = false,
command = 'set number',
event = 'InsertEnter',
id = id,
once = false,
pattern = '*.c',
},
}, api.nvim_get_autocmds({ id = id, pattern = '*.c' }))
end)
it('empty result when id does not found', function()
eq({}, api.nvim_get_autocmds({ id = 255 }))
end)
end)
end) end)
describe('nvim_exec_autocmds', function() describe('nvim_exec_autocmds', function()

View File

@ -15,9 +15,20 @@ local skip = t.skip
describe(':terminal cursor', function() describe(':terminal cursor', function()
local screen local screen
local terminal_mode_idx ---@type number
before_each(function() before_each(function()
clear() clear()
screen = tt.setup_screen() screen = tt.setup_screen()
if terminal_mode_idx == nil then
for i, v in ipairs(screen._mode_info) do
if v.name == 'terminal' then
terminal_mode_idx = i
end
end
assert(terminal_mode_idx)
end
end) end)
it('moves the screen cursor when focused', function() it('moves the screen cursor when focused', function()
@ -143,13 +154,6 @@ describe(':terminal cursor', function()
it('can be modified by application #3681', function() it('can be modified by application #3681', function()
skip(is_os('win'), '#31587') skip(is_os('win'), '#31587')
local idx ---@type number
for i, v in ipairs(screen._mode_info) do
if v.name == 'terminal' then
idx = i
end
end
assert(idx)
local states = { local states = {
[1] = { blink = true, shape = 'block' }, [1] = { blink = true, shape = 'block' },
@ -171,13 +175,13 @@ describe(':terminal cursor', function()
]], ]],
condition = function() condition = function()
if v.blink then if v.blink then
eq(500, screen._mode_info[idx].blinkon) eq(500, screen._mode_info[terminal_mode_idx].blinkon)
eq(500, screen._mode_info[idx].blinkoff) eq(500, screen._mode_info[terminal_mode_idx].blinkoff)
else else
eq(0, screen._mode_info[idx].blinkon) eq(0, screen._mode_info[terminal_mode_idx].blinkon)
eq(0, screen._mode_info[idx].blinkoff) eq(0, screen._mode_info[terminal_mode_idx].blinkoff)
end end
eq(v.shape, screen._mode_info[idx].cursor_shape) eq(v.shape, screen._mode_info[terminal_mode_idx].cursor_shape)
end, end,
}) })
end end
@ -191,20 +195,13 @@ describe(':terminal cursor', function()
]]) ]])
-- Cursor returns to default on TermLeave -- Cursor returns to default on TermLeave
eq(500, screen._mode_info[idx].blinkon) eq(500, screen._mode_info[terminal_mode_idx].blinkon)
eq(500, screen._mode_info[idx].blinkoff) eq(500, screen._mode_info[terminal_mode_idx].blinkoff)
eq('block', screen._mode_info[idx].cursor_shape) eq('block', screen._mode_info[terminal_mode_idx].cursor_shape)
end) end)
it('can be modified per terminal', function() it('can be modified per terminal', function()
skip(is_os('win'), '#31587') skip(is_os('win'), '#31587')
local idx ---@type number
for i, v in ipairs(screen._mode_info) do
if v.name == 'terminal' then
idx = i
end
end
assert(idx)
-- Set cursor to vertical bar with blink -- Set cursor to vertical bar with blink
tt.feed_csi('5 q') tt.feed_csi('5 q')
@ -216,9 +213,9 @@ describe(':terminal cursor', function()
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]], ]],
condition = function() condition = function()
eq(500, screen._mode_info[idx].blinkon) eq(500, screen._mode_info[terminal_mode_idx].blinkon)
eq(500, screen._mode_info[idx].blinkoff) eq(500, screen._mode_info[terminal_mode_idx].blinkoff)
eq('vertical', screen._mode_info[idx].cursor_shape) eq('vertical', screen._mode_info[terminal_mode_idx].cursor_shape)
end, end,
}) })
@ -231,9 +228,9 @@ describe(':terminal cursor', function()
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]], ]],
condition = function() condition = function()
eq(500, screen._mode_info[idx].blinkon) eq(500, screen._mode_info[terminal_mode_idx].blinkon)
eq(500, screen._mode_info[idx].blinkoff) eq(500, screen._mode_info[terminal_mode_idx].blinkoff)
eq('vertical', screen._mode_info[idx].cursor_shape) eq('vertical', screen._mode_info[terminal_mode_idx].cursor_shape)
end, end,
}) })
@ -256,9 +253,9 @@ describe(':terminal cursor', function()
]], ]],
condition = function() condition = function()
-- New terminal, cursor resets to defaults -- New terminal, cursor resets to defaults
eq(500, screen._mode_info[idx].blinkon) eq(500, screen._mode_info[terminal_mode_idx].blinkon)
eq(500, screen._mode_info[idx].blinkoff) eq(500, screen._mode_info[terminal_mode_idx].blinkoff)
eq('block', screen._mode_info[idx].cursor_shape) eq('block', screen._mode_info[terminal_mode_idx].cursor_shape)
end, end,
}) })
@ -275,9 +272,9 @@ describe(':terminal cursor', function()
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]], ]],
condition = function() condition = function()
eq(0, screen._mode_info[idx].blinkon) eq(0, screen._mode_info[terminal_mode_idx].blinkon)
eq(0, screen._mode_info[idx].blinkoff) eq(0, screen._mode_info[terminal_mode_idx].blinkoff)
eq('horizontal', screen._mode_info[idx].cursor_shape) eq('horizontal', screen._mode_info[terminal_mode_idx].cursor_shape)
end, end,
}) })
@ -294,9 +291,9 @@ describe(':terminal cursor', function()
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]], ]],
condition = function() condition = function()
eq(500, screen._mode_info[idx].blinkon) eq(500, screen._mode_info[terminal_mode_idx].blinkon)
eq(500, screen._mode_info[idx].blinkoff) eq(500, screen._mode_info[terminal_mode_idx].blinkoff)
eq('vertical', screen._mode_info[idx].cursor_shape) eq('vertical', screen._mode_info[terminal_mode_idx].cursor_shape)
end, end,
}) })
end) end)
@ -326,6 +323,32 @@ describe(':terminal cursor', function()
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]) ]])
end) end)
it('preserves guicursor value on TermLeave #31612', function()
eq(3, screen._mode_info[terminal_mode_idx].hl_id)
-- Change 'guicursor' while terminal mode is active
command('set guicursor+=t:Error')
local error_hl_id = call('hlID', 'Error')
screen:expect({
condition = function()
eq(error_hl_id, screen._mode_info[terminal_mode_idx].hl_id)
end,
})
-- Exit terminal mode
feed([[<C-\><C-N>]])
screen:expect([[
tty ready |
^ |
|*5
]])
eq(error_hl_id, screen._mode_info[terminal_mode_idx].hl_id)
end)
end) end)
describe('buffer cursor position is correct in terminal without number column', function() describe('buffer cursor position is correct in terminal without number column', function()
@ -350,12 +373,6 @@ describe('buffer cursor position is correct in terminal without number column',
}, { }, {
cols = 70, cols = 70,
}) })
screen:set_default_attr_ids({
[1] = { foreground = 253, background = 11 },
[2] = { reverse = true },
[3] = { bold = true },
[4] = { background = 11 },
})
-- Also check for real cursor position, as it is used for stuff like input methods -- Also check for real cursor position, as it is used for stuff like input methods
screen._handle_busy_start = function() end screen._handle_busy_start = function() end
screen._handle_busy_stop = function() end screen._handle_busy_stop = function() end
@ -667,13 +684,6 @@ describe('buffer cursor position is correct in terminal with number column', fun
}, { }, {
cols = 70, cols = 70,
}) })
screen:set_default_attr_ids({
[1] = { foreground = 253, background = 11 },
[2] = { reverse = true },
[3] = { bold = true },
[4] = { background = 11 },
[7] = { foreground = 130 },
})
-- Also check for real cursor position, as it is used for stuff like input methods -- Also check for real cursor position, as it is used for stuff like input methods
screen._handle_busy_start = function() end screen._handle_busy_start = function() end
screen._handle_busy_stop = function() end screen._handle_busy_stop = function() end

View File

@ -94,7 +94,7 @@ describe('ui mode_change event', function()
} }
end) end)
-- oldtest: Test_indent_norm_with_gq() -- oldtest: Test_mouse_shape_indent_norm_with_gq()
it('is restored to Normal mode after "gq" indents using :normal #12309', function() it('is restored to Normal mode after "gq" indents using :normal #12309', function()
screen:try_resize(60, 6) screen:try_resize(60, 6)
n.exec([[ n.exec([[

View File

@ -1162,6 +1162,8 @@ describe('builtin popupmenu', function()
[6] = { foreground = Screen.colors.White, background = Screen.colors.Red }, [6] = { foreground = Screen.colors.White, background = Screen.colors.Red },
[7] = { background = Screen.colors.Yellow }, -- Search [7] = { background = Screen.colors.Yellow }, -- Search
[8] = { foreground = Screen.colors.Red }, [8] = { foreground = Screen.colors.Red },
[9] = { foreground = Screen.colors.Yellow, background = Screen.colors.Green },
[10] = { foreground = Screen.colors.White, background = Screen.colors.Green },
ks = { foreground = Screen.colors.Red, background = Screen.colors.Grey }, ks = { foreground = Screen.colors.Red, background = Screen.colors.Grey },
kn = { foreground = Screen.colors.Red, background = Screen.colors.Plum1 }, kn = { foreground = Screen.colors.Red, background = Screen.colors.Plum1 },
xs = { foreground = Screen.colors.Black, background = Screen.colors.Grey }, xs = { foreground = Screen.colors.Black, background = Screen.colors.Grey },
@ -5625,6 +5627,114 @@ describe('builtin popupmenu', function()
{2:-- INSERT --} | {2:-- INSERT --} |
]]) ]])
feed('<Esc>') feed('<Esc>')
-- text after the inserted text shouldn't be highlighted
feed('0ea <C-X><C-O>')
screen:expect([[
αβγ {8:foo}^ foo |
{1:~ }{s: foo }{1: }|
{1:~ }{n: bar }{1: }|
{1:~ }{n: }{1: }|
{1:~ }|*15
{2:-- }{5:match 1 of 3} |
]])
feed('<C-P>')
screen:expect([[
αβγ ^ foo |
{1:~ }{n: foo }{1: }|
{1:~ }{n: bar }{1: }|
{1:~ }{n: }{1: }|
{1:~ }|*15
{2:-- }{8:Back at original} |
]])
feed('<C-P>')
screen:expect([[
αβγ {8:}^ foo |
{1:~ }{n: foo }{1: }|
{1:~ }{n: bar }{1: }|
{1:~ }{s: }{1: }|
{1:~ }|*15
{2:-- }{5:match 3 of 3} |
]])
feed('<C-Y>')
screen:expect([[
αβγ ^ foo |
{1:~ }|*18
{2:-- INSERT --} |
]])
feed('<Esc>')
end)
-- oldtest: Test_pum_matchins_highlight_combine()
it('with ComplMatchIns, Normal and CursorLine highlights', 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 Normal guibg=blue
hi CursorLine guibg=green guifg=white
set cursorline
call setline(1, 'aaa bbb')
]])
-- when ComplMatchIns is not set, CursorLine applies normally
feed('0ea <C-X><C-O>')
screen:expect([[
{10:aaa foo^ bbb }|
{1:~ }{s: foo }{1: }|
{1:~ }{n: bar }{1: }|
{1:~ }{n: }{1: }|
{1:~ }|*15
{2:-- }{5:match 1 of 3} |
]])
feed('<C-E>')
screen:expect([[
{10:aaa ^ bbb }|
{1:~ }|*18
{2:-- INSERT --} |
]])
feed('<BS><Esc>')
-- when ComplMatchIns is set, it is applied over CursorLine
command('hi ComplMatchIns guifg=Yellow')
feed('0ea <C-X><C-O>')
screen:expect([[
{10:aaa }{9:foo}{10:^ bbb }|
{1:~ }{s: foo }{1: }|
{1:~ }{n: bar }{1: }|
{1:~ }{n: }{1: }|
{1:~ }|*15
{2:-- }{5:match 1 of 3} |
]])
feed('<C-P>')
screen:expect([[
{10:aaa ^ bbb }|
{1:~ }{n: foo }{1: }|
{1:~ }{n: bar }{1: }|
{1:~ }{n: }{1: }|
{1:~ }|*15
{2:-- }{8:Back at original} |
]])
feed('<C-P>')
screen:expect([[
{10:aaa }{9:}{10:^ bbb }|
{1:~ }{n: foo }{1: }|
{1:~ }{n: bar }{1: }|
{1:~ }{s: }{1: }|
{1:~ }|*15
{2:-- }{5:match 3 of 3} |
]])
feed('<C-E>')
screen:expect([[
{10:aaa ^ bbb }|
{1:~ }|*18
{2:-- INSERT --} |
]])
feed('<Esc>')
end) end)
end end
end end

View File

@ -308,7 +308,7 @@ endfunc
" Test that mouse shape is restored to Normal mode after using "gq" when " Test that mouse shape is restored to Normal mode after using "gq" when
" 'indentexpr' executes :normal. " 'indentexpr' executes :normal.
func Test_indent_norm_with_gq() func Test_mouse_shape_indent_norm_with_gq()
CheckFeature mouseshape CheckFeature mouseshape
CheckCanRunGui CheckCanRunGui

View File

@ -1747,13 +1747,67 @@ func Test_pum_matchins_highlight()
call TermWait(buf) call TermWait(buf)
call term_sendkeys(buf, "Sαβγ \<C-X>\<C-O>\<C-Y>") call term_sendkeys(buf, "Sαβγ \<C-X>\<C-O>\<C-Y>")
call VerifyScreenDump(buf, 'Test_pum_matchins_04', {}) call VerifyScreenDump(buf, 'Test_pum_matchins_04', {})
call term_sendkeys(buf, "\<C-E>\<Esc>") call term_sendkeys(buf, "\<Esc>")
" restore after cancel completion " restore after cancel completion
call TermWait(buf) call TermWait(buf)
call term_sendkeys(buf, "Sαβγ \<C-X>\<C-O>\<Space>") call term_sendkeys(buf, "Sαβγ \<C-X>\<C-O>\<Space>")
call VerifyScreenDump(buf, 'Test_pum_matchins_05', {}) call VerifyScreenDump(buf, 'Test_pum_matchins_05', {})
call term_sendkeys(buf, "\<C-E>\<Esc>") call term_sendkeys(buf, "\<Esc>")
" text after the inserted text shouldn't be highlighted
call TermWait(buf)
call term_sendkeys(buf, "0ea \<C-X>\<C-O>")
call VerifyScreenDump(buf, 'Test_pum_matchins_07', {})
call term_sendkeys(buf, "\<C-P>")
call VerifyScreenDump(buf, 'Test_pum_matchins_08', {})
call term_sendkeys(buf, "\<C-P>")
call VerifyScreenDump(buf, 'Test_pum_matchins_09', {})
call term_sendkeys(buf, "\<C-Y>")
call VerifyScreenDump(buf, 'Test_pum_matchins_10', {})
call term_sendkeys(buf, "\<Esc>")
call StopVimInTerminal(buf)
endfunc
func Test_pum_matchins_highlight_combine()
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 Normal ctermbg=blue
hi CursorLine cterm=underline ctermbg=green
set cursorline
call setline(1, 'aaa bbb')
END
call writefile(lines, 'Xscript', 'D')
let buf = RunVimInTerminal('-S Xscript', {})
" when ComplMatchIns is not set, CursorLine applies normally
call term_sendkeys(buf, "0ea \<C-X>\<C-O>")
call VerifyScreenDump(buf, 'Test_pum_matchins_combine_01', {})
call term_sendkeys(buf, "\<C-E>")
call VerifyScreenDump(buf, 'Test_pum_matchins_combine_02', {})
call term_sendkeys(buf, "\<BS>\<Esc>")
" when ComplMatchIns is set, it is applied over CursorLine
call TermWait(buf)
call term_sendkeys(buf, ":hi ComplMatchIns ctermbg=red ctermfg=yellow\<CR>")
call TermWait(buf)
call term_sendkeys(buf, "0ea \<C-X>\<C-O>")
call VerifyScreenDump(buf, 'Test_pum_matchins_combine_03', {})
call term_sendkeys(buf, "\<C-P>")
call VerifyScreenDump(buf, 'Test_pum_matchins_combine_04', {})
call term_sendkeys(buf, "\<C-P>")
call VerifyScreenDump(buf, 'Test_pum_matchins_combine_05', {})
call term_sendkeys(buf, "\<C-E>")
call VerifyScreenDump(buf, 'Test_pum_matchins_combine_06', {})
call term_sendkeys(buf, "\<Esc>")
call StopVimInTerminal(buf) call StopVimInTerminal(buf)
endfunc endfunc