diff options
-rw-r--r-- | src/nvim/ex_docmd.c | 5 | ||||
-rw-r--r-- | src/nvim/terminal.c | 1 | ||||
-rw-r--r-- | src/nvim/tui/input.c | 15 | ||||
-rw-r--r-- | test/functional/ui/inccommand_spec.lua | 102 | ||||
-rw-r--r-- | test/functional/ui/searchhl_spec.lua | 11 |
5 files changed, 110 insertions, 24 deletions
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 7c857cde82..8aa670fc74 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -603,6 +603,11 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline, cmd_getline, cmd_cookie); recursive--; + // Ignore trailing '|'-separated commands in preview-mode ('inccommand'). + if (State & CMDPREVIEW) { + next_cmdline = NULL; + } + if (cmd_cookie == (void *)&cmd_loop_cookie) /* Use "current_line" from "cmd_loop_cookie", it may have been * incremented when defining a function. */ diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c index 5a05847197..d006477c80 100644 --- a/src/nvim/terminal.c +++ b/src/nvim/terminal.c @@ -1106,6 +1106,7 @@ static void refresh_timer_cb(TimeWatcher *watcher, void *data) { refresh_pending = false; if (exiting // Cannot redraw (requires event loop) during teardown/exit. + || (State & CMDPREVIEW) // WM_LIST (^D) is not redrawn, unlike the normal wildmenu. So we must // skip redraws to keep it visible. || wild_menu_showing == WM_LIST) { diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c index b04a6ce4f9..0362820687 100644 --- a/src/nvim/tui/input.c +++ b/src/nvim/tui/input.c @@ -170,11 +170,21 @@ static void forward_mouse_event(TermInput *input, TermKeyKey *key) char buf[64]; size_t len = 0; int button, row, col; + static int last_pressed_button = 0; TermKeyMouseEvent ev; termkey_interpret_mouse(input->tk, key, &ev, &button, &row, &col); - if (ev != TERMKEY_MOUSE_PRESS && ev != TERMKEY_MOUSE_DRAG - && ev != TERMKEY_MOUSE_RELEASE) { + if ((ev == TERMKEY_MOUSE_RELEASE || ev == TERMKEY_MOUSE_DRAG) + && button == 0) { + // Some terminals (like urxvt) don't report which button was released. + // libtermkey reports button 0 in this case. + // For drag and release, we can reasonably infer the button to be the last + // pressed one. + button = last_pressed_button; + } + + if (button == 0 || (ev != TERMKEY_MOUSE_PRESS && ev != TERMKEY_MOUSE_DRAG + && ev != TERMKEY_MOUSE_RELEASE)) { return; } @@ -210,6 +220,7 @@ static void forward_mouse_event(TermInput *input, TermKeyKey *key) "ScrollWheelDown"); } else { len += (size_t)snprintf(buf + len, sizeof(buf) - len, "Mouse"); + last_pressed_button = button; } break; case TERMKEY_MOUSE_DRAG: diff --git a/test/functional/ui/inccommand_spec.lua b/test/functional/ui/inccommand_spec.lua index 27e4066d9f..ee1a3240a2 100644 --- a/test/functional/ui/inccommand_spec.lua +++ b/test/functional/ui/inccommand_spec.lua @@ -16,6 +16,8 @@ local retry = helpers.retry local source = helpers.source local wait = helpers.wait local nvim = helpers.nvim +local iswin = helpers.iswin +local sleep = helpers.sleep local default_text = [[ Inc substitution on @@ -1354,6 +1356,23 @@ describe("inccommand=nosplit", function() :echo 'foo'^ | ]]) end) + + it("does not execute trailing bar-separated commands #7494", function() + feed(':%s/two/three/g|q!') + screen:expect([[ + Inc substitution on | + {12:three} lines | + Inc substitution on | + {12:three} lines | + | + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + :%s/two/three/g|q!^ | + ]]) + eq(eval('v:null'), eval('v:exiting')) + end) end) describe(":substitute, 'inccommand' with a failing expression", function() @@ -1833,7 +1852,7 @@ describe(":substitute", function() clear() end) - it(", inccommand=split, highlights multiline substitutions", function() + it("inccommand=split, highlights multiline substitutions", function() common_setup(screen, "split", multiline_text) feed("gg") @@ -1895,7 +1914,7 @@ describe(":substitute", function() ]]) end) - it(", inccommand=nosplit, highlights multiline substitutions", function() + it("inccommand=nosplit, highlights multiline substitutions", function() common_setup(screen, "nosplit", multiline_text) feed("gg") @@ -1938,7 +1957,7 @@ describe(":substitute", function() ]]) end) - it(", inccommand=split, highlights multiple matches on a line", function() + it("inccommand=split, highlights multiple matches on a line", function() common_setup(screen, "split", multimatch_text) command("set gdefault") feed("gg") @@ -1963,7 +1982,7 @@ describe(":substitute", function() ]]) end) - it(", inccommand=nosplit, highlights multiple matches on a line", function() + it("inccommand=nosplit, highlights multiple matches on a line", function() common_setup(screen, "nosplit", multimatch_text) command("set gdefault") feed("gg") @@ -1988,7 +2007,7 @@ describe(":substitute", function() ]]) end) - it(", inccommand=split, with \\zs", function() + it("inccommand=split, with \\zs", function() common_setup(screen, "split", multiline_text) feed("gg") @@ -2012,7 +2031,7 @@ describe(":substitute", function() ]]) end) - it(", inccommand=nosplit, with \\zs", function() + it("inccommand=nosplit, with \\zs", function() common_setup(screen, "nosplit", multiline_text) feed("gg") @@ -2036,7 +2055,7 @@ describe(":substitute", function() ]]) end) - it(", inccommand=split, substitutions of different length", + it("inccommand=split, substitutions of different length", function() common_setup(screen, "split", "T T123 T2T TTT T090804\nx") @@ -2060,7 +2079,7 @@ describe(":substitute", function() ]]) end) - it(", inccommand=nosplit, substitutions of different length", function() + 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") @@ -2083,7 +2102,7 @@ describe(":substitute", function() ]]) end) - it(", inccommand=split, contraction of lines", function() + it("inccommand=split, contraction of lines", function() local text = [[ T T123 T T123 T2T TT T23423424 x @@ -2132,7 +2151,7 @@ describe(":substitute", function() ]]) end) - it(", inccommand=nosplit, contraction of lines", function() + it("inccommand=nosplit, contraction of lines", function() local text = [[ T T123 T T123 T2T TT T23423424 x @@ -2162,7 +2181,7 @@ describe(":substitute", function() ]]) end) - it(", inccommand=split, multibyte text", function() + it("inccommand=split, multibyte text", function() common_setup(screen, "split", multibyte_text) feed(":%s/£.*ѫ/X¥¥") screen:expect([[ @@ -2203,7 +2222,7 @@ describe(":substitute", function() ]]) end) - it(", inccommand=nosplit, multibyte text", function() + it("inccommand=nosplit, multibyte text", function() common_setup(screen, "nosplit", multibyte_text) feed(":%s/£.*ѫ/X¥¥") screen:expect([[ @@ -2244,7 +2263,7 @@ describe(":substitute", function() ]]) end) - it(", inccommand=split, small cmdwinheight", function() + it("inccommand=split, small cmdwinheight", function() common_setup(screen, "split", long_multiline_text) command("set cmdwinheight=2") @@ -2306,7 +2325,7 @@ describe(":substitute", function() ]]) end) - it(", inccommand=split, large cmdwinheight", function() + it("inccommand=split, large cmdwinheight", function() common_setup(screen, "split", long_multiline_text) command("set cmdwinheight=11") @@ -2368,7 +2387,7 @@ describe(":substitute", function() ]]) end) - it(", inccommand=split, lookaround", function() + it("inccommand=split, lookaround", function() common_setup(screen, "split", "something\neverything\nsomeone") feed([[:%s/\(some\)\@<lt>=thing/one/]]) screen:expect([[ @@ -2452,4 +2471,57 @@ describe(":substitute", function() :%s/some\(thing\)\@!/every/^ | ]]) end) + + it('with inccommand during :terminal activity', function() + command("set cmdwinheight=3") + if iswin() then + feed([[:terminal for /L \%I in (1,1,5000) do @(echo xxx & echo xxx & echo xxx)<cr>]]) + else + feed([[:terminal for i in $(seq 1 5000); do printf 'xxx\nxxx\nxxx\n'; done<cr>]]) + end + command('file term') + command('new') + common_setup(screen, 'split', 'foo bar baz\nbar baz fox\nbar foo baz') + command('wincmd =') + + -- Allow some terminal output. + screen:expect([[ + bar baz fox | + bar foo ba^z | + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {11:[No Name] [+] }| + xxx | + xxx | + xxx | + xxx | + xxx | + xxx | + {10:term }| + | + ]]) + + feed('gg') + feed(':%s/foo/ZZZ') + sleep(50) -- Allow some terminal activity. + screen:expect([[ + {12:ZZZ} bar baz | + bar baz fox | + bar {12:ZZZ} baz | + {15:~ }| + {15:~ }| + {15:~ }| + {11:[No Name] [+] }| + xxx | + xxx | + {10:term }| + |1| {12:ZZZ} bar baz | + |3| bar {12:ZZZ} baz | + {15:~ }| + {10:[Preview] }| + :%s/foo/ZZZ^ | + ]]) + end) end) diff --git a/test/functional/ui/searchhl_spec.lua b/test/functional/ui/searchhl_spec.lua index f241a9fc44..168080a092 100644 --- a/test/functional/ui/searchhl_spec.lua +++ b/test/functional/ui/searchhl_spec.lua @@ -5,6 +5,7 @@ local feed_command = helpers.feed_command local eq = helpers.eq local eval = helpers.eval local iswin = helpers.iswin +local sleep = helpers.sleep describe('search highlighting', function() local screen @@ -92,18 +93,13 @@ describe('search highlighting', function() ]]) end) - it('#x is preserved during :terminal activity', function() - -- Because this test verifies a _lack_ of activity after screen:sleep(), we - -- must wait the full timeout. So make it reasonable. - screen.timeout = 1000 - + it('is preserved during :terminal activity', function() if iswin() then feed([[:terminal for /L \%I in (1,1,5000) do @(echo xxx & echo xxx & echo xxx)<cr>]]) else - feed([[:terminal for i in $(seq 1 5000); do printf 'xxx\nxxx\nxxx\n'; sleep 0.1; done<cr>]]) + feed([[:terminal for i in $(seq 1 5000); do printf 'xxx\nxxx\nxxx\n'; done<cr>]]) end - feed([[<C-\><C-N>gg]]) feed(':file term<CR>') feed(':vnew<CR>') insert([[ @@ -112,6 +108,7 @@ describe('search highlighting', function() bar foo baz ]]) feed('/foo') + sleep(50) -- Allow some terminal activity. screen:expect([[ {3:foo} bar baz {3:│}xxx | bar baz {2:foo} {3:│}xxx | |