aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuuk van Baal <luukvbaal@gmail.com>2025-03-13 13:47:48 +0100
committerChristian Clason <ch.clason+github@icloud.com>2025-03-15 12:09:22 +0100
commita70ad5cdb6de024f2efd1885107cb89c135515e3 (patch)
treec2061886b8a488244f500e1114b3dc4762ec3ebd
parent98c1355e2f2236bcbad7f8f513d3c11237040293 (diff)
downloadrneovim-a70ad5cdb6de024f2efd1885107cb89c135515e3.tar.gz
rneovim-a70ad5cdb6de024f2efd1885107cb89c135515e3.tar.bz2
rneovim-a70ad5cdb6de024f2efd1885107cb89c135515e3.zip
fix(cmdline): ext_cmdline block events for conditionals
Problem: No block events emitted with ext_cmdline for :if, :while, :try etc. Solution: Emit cmdline block events; store the indent level of the previous cmdline and whether a block event was emitted.
-rw-r--r--src/nvim/ex_docmd.c27
-rw-r--r--test/functional/ui/cmdline_spec.lua53
2 files changed, 70 insertions, 10 deletions
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 3b78092daf..af93db9956 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -406,6 +406,7 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
bool msg_didout_before_start = false;
int count = 0; // line number count
bool did_inc = false; // incremented RedrawingDisabled
+ int block_indent = -1; // indent for ext_cmdline block event
int retval = OK;
cstack_T cstack = { // conditional stack
.cs_idx = -1,
@@ -573,16 +574,18 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
// 2. If no line given, get an allocated line with fgetline().
if (next_cmdline == NULL) {
- // Need to set msg_didout for the first line after an ":if",
- // otherwise the ":if" will be overwritten.
- if (count == 1 && getline_equal(fgetline, cookie, getexline)) {
- msg_didout = true;
- }
- if (fgetline == NULL
- || (next_cmdline = fgetline(':', cookie,
- cstack.cs_idx <
- 0 ? 0 : (cstack.cs_idx + 1) * 2,
- true)) == NULL) {
+ int indent = cstack.cs_idx < 0 ? 0 : (cstack.cs_idx + 1) * 2;
+ if (count >= 1 && getline_equal(fgetline, cookie, getexline)) {
+ if (ui_has(kUICmdline)) {
+ ui_ext_cmdline_block_append((size_t)MAX(0, block_indent), last_cmdline);
+ block_indent = indent;
+ } else if (count == 1) {
+ // Need to set msg_didout for the first line after an ":if",
+ // otherwise the ":if" will be overwritten.
+ msg_didout = true;
+ }
+ }
+ if (fgetline == NULL || (next_cmdline = fgetline(':', cookie, indent, true)) == NULL) {
// Don't call wait_return() for aborted command line. The NULL
// returned for the end of a sourced file or executed function
// doesn't do this.
@@ -939,6 +942,10 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
}
}
+ if (block_indent >= 0) {
+ ui_ext_cmdline_block_leave();
+ }
+
did_endif = false; // in case do_cmdline used recursively
do_cmdline_end();
diff --git a/test/functional/ui/cmdline_spec.lua b/test/functional/ui/cmdline_spec.lua
index ce7c9596bb..cb9d978a0f 100644
--- a/test/functional/ui/cmdline_spec.lua
+++ b/test/functional/ui/cmdline_spec.lua
@@ -865,6 +865,59 @@ local function test_cmdline(linegrid)
},
})
end)
+
+ it('works with conditionals', function()
+ local s1 = [[
+ ^ |
+ {1:~ }|*3
+ |
+ ]]
+ screen:expect(s1)
+ feed(':if 1<CR>')
+ screen:expect({
+ grid = s1,
+ cmdline = {
+ {
+ content = { { '' } },
+ firstc = ':',
+ indent = 2,
+ pos = 0,
+ },
+ },
+ cmdline_block = { { { 'if 1' } } },
+ })
+ feed(':let x = 1<CR>')
+ screen:expect({
+ grid = s1,
+ cmdline = {
+ {
+ content = { { '' } },
+ firstc = ':',
+ indent = 2,
+ pos = 0,
+ },
+ },
+ cmdline_block = { { { 'if 1' } }, { { ' :let x = 1' } } },
+ })
+ feed(':endif')
+ screen:expect({
+ grid = s1,
+ cmdline = {
+ {
+ content = { { ':endif' } },
+ firstc = ':',
+ indent = 2,
+ pos = 6,
+ },
+ },
+ cmdline_block = { { { 'if 1' } }, { { ' :let x = 1' } } },
+ })
+ feed('<CR>')
+ screen:expect({
+ grid = s1,
+ cmdline = { { abort = false } },
+ })
+ end)
end
-- the representation of cmdline and cmdline_block contents changed with ext_linegrid