diff options
-rw-r--r-- | src/nvim/ex_getln.c | 17 | ||||
-rw-r--r-- | test/functional/ui/cmdline_highlight_spec.lua | 42 |
2 files changed, 43 insertions, 16 deletions
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index e10a485f76..c23d6089a3 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -166,6 +166,12 @@ static int hisnum[HIST_COUNT] = {0, 0, 0, 0, 0}; /* identifying (unique) number of newest history entry */ static int hislen = 0; /* actual length of history tables */ +/// Flag for command_line_handle_key to ignore <C-c> +/// +/// Used if it was received while processing highlight function in order for +/// user interrupting highlight function to not interrupt command-line. +static bool getln_interrupted_highlight = false; + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "ex_getln.c.generated.h" @@ -1026,8 +1032,11 @@ static int command_line_handle_key(CommandLineState *s) case ESC: // get here if p_wc != ESC or when ESC typed twice case Ctrl_C: // In exmode it doesn't make sense to return. Except when - // ":normal" runs out of characters. - if (exmode_active && (ex_normal_busy == 0 || typebuf.tb_len > 0)) { + // ":normal" runs out of characters. Also when highlight callback is active + // <C-c> should interrupt only it. + if ((exmode_active && (ex_normal_busy == 0 || typebuf.tb_len > 0)) + || (getln_interrupted_highlight && s->c == Ctrl_C)) { + getln_interrupted_highlight = false; return command_line_not_changed(s); } @@ -2278,6 +2287,7 @@ static bool color_cmdline(void) // // Also using try_start() because error messages may overwrite typed // command-line which is not expected. + getln_interrupted_highlight = false; try_start(); err_errmsg = N_("E5407: Callback has thrown an exception: %s"); const int saved_msg_col = msg_col; @@ -2285,6 +2295,9 @@ static bool color_cmdline(void) const bool cbcall_ret = callback_call(&color_cb, 1, &arg, &tv); msg_silent--; msg_col = saved_msg_col; + if (got_int) { + getln_interrupted_highlight = true; + } if (try_end(&err) || !cbcall_ret) { goto color_cmdline_error; } diff --git a/test/functional/ui/cmdline_highlight_spec.lua b/test/functional/ui/cmdline_highlight_spec.lua index dbabf65b68..671490e668 100644 --- a/test/functional/ui/cmdline_highlight_spec.lua +++ b/test/functional/ui/cmdline_highlight_spec.lua @@ -10,6 +10,13 @@ local source = helpers.source local screen +-- Bug in input() handling: {REDRAW} will erase the whole prompt up until +-- user types something. It exists in Vim as well, so using `h<BS>` as +-- a workaround. +local function redraw_input() + feed('{REDRAW}h<BS>') +end + before_each(function() clear() screen = Screen.new(40, 8) @@ -214,10 +221,7 @@ describe('Command-line coloring', function() {EOB:~ }| :echo {RBP1:(}{RBP2:(}42{RBP2:)}^ | ]]) - -- Bug in input() handling: {REDRAW} will erase the whole prompt up until - -- user types something. It exists in Vim as well, so using `h<BS>` as - -- a workaround. - feed('{REDRAW}h<BS>') + redraw_input() screen:expect([[ | {EOB:~ }| @@ -364,24 +368,33 @@ describe('Command-line coloring', function() : | {ERR:E5407: Callback has thrown an exception:}| {ERR: Keyboard interrupt} | - ^ | + :echo 42^ | ]]) - if true then return pending('<C-c> should only cancel callback, not input()') end - feed('{REDRAW}') - screen:snapshot_util() - feed('<CR>') - eq('echo 42', meths.get_var('out')) + redraw_input() screen:expect([[ - ^ | + | {EOB:~ }| {EOB:~ }| {EOB:~ }| {EOB:~ }| {EOB:~ }| {EOB:~ }| - Type :quit<Enter> to exit Nvim | + :echo 42^ | ]]) - start_prompt('echo 42<CR>') + feed('\n') + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + ^:echo 42 | + ]]) + feed('\n') + eq('echo 42', meths.get_var('out')) + feed('<C-c>') screen:expect([[ ^ | {EOB:~ }| @@ -390,7 +403,7 @@ describe('Command-line coloring', function() {EOB:~ }| {EOB:~ }| {EOB:~ }| - 42 | + Type :quit<Enter> to exit Nvim | ]]) end) it('works fine with NUL, NL, CR', function() @@ -420,3 +433,4 @@ describe('Ex commands coloring support', function() end) -- TODO Specifically test for coloring in cmdline and expr modes +-- TODO Check using highlighted input() from inside highlighted input() |