diff options
-rw-r--r-- | src/nvim/ex_cmds.c | 4 | ||||
-rw-r--r-- | test/functional/ex_cmds/global_spec.lua | 74 |
2 files changed, 78 insertions, 0 deletions
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 17780c58e4..d616b55554 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -4082,6 +4082,7 @@ void global_exe(char_u *cmd) linenr_T old_lcount; /* b_ml.ml_line_count before the command */ buf_T *old_buf = curbuf; /* remember what buffer we started in */ linenr_T lnum; /* line number according to old situation */ + int save_mapped_ctrl_c = mapped_ctrl_c; /* * Set current position only once for a global command. @@ -4092,6 +4093,8 @@ void global_exe(char_u *cmd) /* When the command writes a message, don't overwrite the command. */ msg_didout = TRUE; + // Disable CTRL-C mapping, let it interrupt (potentially long output). + mapped_ctrl_c = 0; sub_nsubs = 0; sub_nlines = 0; @@ -4108,6 +4111,7 @@ void global_exe(char_u *cmd) os_breakcheck(); } + mapped_ctrl_c = save_mapped_ctrl_c; global_busy = 0; if (global_need_beginline) beginline(BL_WHITE | BL_FIX); diff --git a/test/functional/ex_cmds/global_spec.lua b/test/functional/ex_cmds/global_spec.lua new file mode 100644 index 0000000000..81a0ef3248 --- /dev/null +++ b/test/functional/ex_cmds/global_spec.lua @@ -0,0 +1,74 @@ +local helpers = require('test.functional.helpers')(after_each) +local Screen = require('test.functional.ui.screen') +local clear, feed, source = helpers.clear, helpers.feed, helpers.source + +if helpers.pending_win32(pending) then return end + +describe(':global', function() + before_each(function() + clear() + end) + + it('is interrupted by mapped CTRL-C', function() + if os.getenv("TRAVIS") and os.getenv("CLANG_SANITIZER") == "ASAN_UBSAN" then + -- XXX: ASAN_UBSAN is too slow to react to the CTRL-C. + pending("", function() end) + return + end + + source([[ + set nomore + set undolevels=-1 + nnoremap <C-C> <NOP> + for i in range(0, 99999) + put ='XXX' + endfor + put ='ZZZ' + 1 + .delete + ]]) + + local screen = Screen.new(52, 6) + screen:attach() + screen:set_default_attr_ids({ + [0] = {foreground = Screen.colors.White, + background = Screen.colors.Red}, + [1] = {bold = true, + foreground = Screen.colors.SeaGreen} + }) + + screen:expect([[ + ^XXX | + XXX | + XXX | + XXX | + XXX | + | + ]]) + + local function test_ctrl_c(ms) + feed(":global/^/p<CR>") + helpers.sleep(ms) + feed("<C-C>") + screen:expect([[ + XXX | + XXX | + XXX | + XXX | + {0:Interrupted} | + Interrupt: {1:Press ENTER or type command to continue}^ | + ]]) + end + + -- The test is time-sensitive. Try with different sleep values. + local ms_values = {10, 50, 100} + for i, ms in ipairs(ms_values) do + if i < #ms_values then + local status, _ = pcall(test_ctrl_c, ms) + if status then break end + else -- Call the last attempt directly. + test_ctrl_c(ms) + end + end + end) +end) |