mirror of
https://github.com/neovim/neovim.git
synced 2025-09-06 03:18:16 +00:00
fix(ui): proper event ordering for nested cmdline_block events (#35344)
Problem: Wrong event order for nested cmdline in a conditional cmdline_block. Solution: Emit all but the first cmdline_block event immediately after getting the next command, before executing it.
This commit is contained in:
@@ -403,8 +403,7 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
|
|||||||
bool msg_didout_before_start = false;
|
bool msg_didout_before_start = false;
|
||||||
int count = 0; // line number count
|
int count = 0; // line number count
|
||||||
bool did_inc = false; // incremented RedrawingDisabled
|
bool did_inc = false; // incremented RedrawingDisabled
|
||||||
int block_indent = -1; // indent for ext_cmdline block event
|
bool did_block = false; // emitted cmdline_block event
|
||||||
char *block_line = NULL; // block_line for ext_cmdline block event
|
|
||||||
int retval = OK;
|
int retval = OK;
|
||||||
cstack_T cstack = { // conditional stack
|
cstack_T cstack = { // conditional stack
|
||||||
.cs_idx = -1,
|
.cs_idx = -1,
|
||||||
@@ -573,18 +572,18 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
|
|||||||
// 2. If no line given, get an allocated line with fgetline().
|
// 2. If no line given, get an allocated line with fgetline().
|
||||||
if (next_cmdline == NULL) {
|
if (next_cmdline == NULL) {
|
||||||
int indent = cstack.cs_idx < 0 ? 0 : (cstack.cs_idx + 1) * 2;
|
int indent = cstack.cs_idx < 0 ? 0 : (cstack.cs_idx + 1) * 2;
|
||||||
if (count >= 1 && getline_equal(fgetline, cookie, getexline)) {
|
|
||||||
|
if (count == 1 && getline_equal(fgetline, cookie, getexline)) {
|
||||||
if (ui_has(kUICmdline)) {
|
if (ui_has(kUICmdline)) {
|
||||||
char *line = block_line == last_cmdline ? "" : last_cmdline;
|
// Emit cmdline_block event for loop/conditional block.
|
||||||
ui_ext_cmdline_block_append((size_t)MAX(0, block_indent), line);
|
ui_ext_cmdline_block_append(0, last_cmdline);
|
||||||
block_line = last_cmdline;
|
did_block = true;
|
||||||
block_indent = indent;
|
}
|
||||||
} else if (count == 1) {
|
|
||||||
// Need to set msg_didout for the first line after an ":if",
|
// Need to set msg_didout for the first line after an ":if",
|
||||||
// otherwise the ":if" will be overwritten.
|
// otherwise the ":if" will be overwritten.
|
||||||
msg_didout = true;
|
msg_didout = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (fgetline == NULL || (next_cmdline = fgetline(':', cookie, indent, true)) == NULL) {
|
if (fgetline == NULL || (next_cmdline = fgetline(':', cookie, indent, true)) == NULL) {
|
||||||
// Don't call wait_return() for aborted command line. The NULL
|
// Don't call wait_return() for aborted command line. The NULL
|
||||||
// returned for the end of a sourced file or executed function
|
// returned for the end of a sourced file or executed function
|
||||||
@@ -597,6 +596,12 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
|
|||||||
}
|
}
|
||||||
used_getline = true;
|
used_getline = true;
|
||||||
|
|
||||||
|
// Emit all but the first cmdline_block event immediately; waiting until after
|
||||||
|
// command execution would mess up event ordering with nested command lines.
|
||||||
|
if (ui_has(kUICmdline) && count > 0 && getline_equal(fgetline, cookie, getexline)) {
|
||||||
|
ui_ext_cmdline_block_append((size_t)indent, next_cmdline);
|
||||||
|
}
|
||||||
|
|
||||||
// Keep the first typed line. Clear it when more lines are typed.
|
// Keep the first typed line. Clear it when more lines are typed.
|
||||||
if (flags & DOCMD_KEEPLINE) {
|
if (flags & DOCMD_KEEPLINE) {
|
||||||
xfree(repeat_cmdline);
|
xfree(repeat_cmdline);
|
||||||
@@ -941,7 +946,7 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (block_indent >= 0) {
|
if (did_block) {
|
||||||
ui_ext_cmdline_block_leave();
|
ui_ext_cmdline_block_leave();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -673,6 +673,36 @@ local function test_cmdline(linegrid)
|
|||||||
cmdline = { { content = { { '' } }, firstc = ':', indent = 2, pos = 0 } },
|
cmdline = { { content = { { '' } }, firstc = ':', indent = 2, pos = 0 } },
|
||||||
cmdline_block = { { { 'if 1' } }, { { ' let x = 1' } }, { { ' ' } } },
|
cmdline_block = { { { 'if 1' } }, { { ' let x = 1' } }, { { ' ' } } },
|
||||||
})
|
})
|
||||||
|
feed('call input("foo:")<CR>')
|
||||||
|
screen:expect({
|
||||||
|
grid = [[
|
||||||
|
^ |
|
||||||
|
{1:~ }|*3
|
||||||
|
|
|
||||||
|
]],
|
||||||
|
cmdline = { { content = { { '' } }, pos = 0, prompt = 'foo:' } },
|
||||||
|
cmdline_block = {
|
||||||
|
{ { 'if 1' } },
|
||||||
|
{ { ' let x = 1' } },
|
||||||
|
{ { ' ' } },
|
||||||
|
{ { ' call input("foo:")' } },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
feed('bar<CR>')
|
||||||
|
screen:expect({
|
||||||
|
grid = [[
|
||||||
|
^ |
|
||||||
|
{1:~ }|*3
|
||||||
|
|
|
||||||
|
]],
|
||||||
|
cmdline = { { content = { { '' } }, firstc = ':', indent = 2, pos = 0 } },
|
||||||
|
cmdline_block = {
|
||||||
|
{ { 'if 1' } },
|
||||||
|
{ { ' let x = 1' } },
|
||||||
|
{ { ' ' } },
|
||||||
|
{ { ' call input("foo:")' } },
|
||||||
|
},
|
||||||
|
})
|
||||||
feed('endif')
|
feed('endif')
|
||||||
screen:expect({
|
screen:expect({
|
||||||
grid = [[
|
grid = [[
|
||||||
@@ -681,7 +711,12 @@ local function test_cmdline(linegrid)
|
|||||||
|
|
|
|
||||||
]],
|
]],
|
||||||
cmdline = { { content = { { 'endif' } }, firstc = ':', indent = 2, pos = 5 } },
|
cmdline = { { content = { { 'endif' } }, firstc = ':', indent = 2, pos = 5 } },
|
||||||
cmdline_block = { { { 'if 1' } }, { { ' let x = 1' } }, { { ' ' } } },
|
cmdline_block = {
|
||||||
|
{ { 'if 1' } },
|
||||||
|
{ { ' let x = 1' } },
|
||||||
|
{ { ' ' } },
|
||||||
|
{ { ' call input("foo:")' } },
|
||||||
|
},
|
||||||
})
|
})
|
||||||
feed('<CR>')
|
feed('<CR>')
|
||||||
screen:expect([[
|
screen:expect([[
|
||||||
|
Reference in New Issue
Block a user