aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2022-02-17 07:18:10 +0800
committerzeertzjq <zeertzjq@outlook.com>2022-02-17 08:45:14 +0800
commit2ffe66a5a4e1297ee24fd3ab8cc4dda45b1381bd (patch)
treeed6ce83164b6c3dfe3c5a49d9627e4792ab85f35
parentc90cf8c77b96cda0fd40dbf4aa2c1762cd09dab3 (diff)
downloadrneovim-2ffe66a5a4e1297ee24fd3ab8cc4dda45b1381bd.tar.gz
rneovim-2ffe66a5a4e1297ee24fd3ab8cc4dda45b1381bd.tar.bz2
rneovim-2ffe66a5a4e1297ee24fd3ab8cc4dda45b1381bd.zip
vim-patch:8.2.4338: an error from an expression mapping messes up the display
Problem: An error from an expression mapping messes up the display. Solution: When the expression results in an empty string return K_IGNORE. In cmdline mode redraw the command line. (closes vim/vim#9726) https://github.com/vim/vim/commit/74a0a5b26d0180f3ea89e9495dff6a26f0df23cb
-rw-r--r--src/nvim/getchar.c21
-rw-r--r--src/nvim/testdir/test_mapping.vim32
2 files changed, 53 insertions, 0 deletions
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index ac5d587c1e..43a4f31478 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -1953,6 +1953,7 @@ static int handle_mapping(int *keylenp, bool *timedout, int *mapdepth)
const bool save_may_garbage_collect = may_garbage_collect;
const int save_cursor_row = ui_current_row();
const int save_cursor_col = ui_current_col();
+ const int prev_did_emsg = did_emsg;
vgetc_busy = 0;
may_garbage_collect = false;
@@ -1968,6 +1969,26 @@ static int handle_mapping(int *keylenp, bool *timedout, int *mapdepth)
ui_cursor_goto(save_cursor_row, save_cursor_col);
ui_flush();
+ // If an error was displayed and the expression returns an empty
+ // string, generate a <Nop> to allow for a redraw.
+ if (prev_did_emsg != did_emsg && (map_str == NULL || *map_str == NUL)) {
+ char_u buf[4];
+ xfree(map_str);
+ buf[0] = K_SPECIAL;
+ buf[1] = KS_EXTRA;
+ buf[2] = KE_IGNORE;
+ buf[3] = NUL;
+ map_str = vim_strsave(buf);
+ if (State & CMDLINE) {
+ // redraw the command below the error
+ msg_didout = true;
+ if (msg_row < cmdline_row) {
+ msg_row = cmdline_row;
+ }
+ redrawcmd();
+ }
+ }
+
vgetc_busy = save_vgetc_busy;
may_garbage_collect = save_may_garbage_collect;
} else {
diff --git a/src/nvim/testdir/test_mapping.vim b/src/nvim/testdir/test_mapping.vim
index 749c75106e..105f70e6bb 100644
--- a/src/nvim/testdir/test_mapping.vim
+++ b/src/nvim/testdir/test_mapping.vim
@@ -483,6 +483,38 @@ func Test_expr_map_restore_cursor()
call delete('XtestExprMap')
endfunc
+func Test_expr_map_error()
+ CheckScreendump
+
+ let lines =<< trim END
+ func Func()
+ throw 'test'
+ return ''
+ endfunc
+
+ nnoremap <expr> <F2> Func()
+ cnoremap <expr> <F2> Func()
+
+ call test_override('ui_delay', 10)
+ END
+ call writefile(lines, 'XtestExprMap')
+ let buf = RunVimInTerminal('-S XtestExprMap', #{rows: 10})
+ call TermWait(buf)
+ call term_sendkeys(buf, "\<F2>")
+ call TermWait(buf)
+ call term_sendkeys(buf, "\<CR>")
+ call VerifyScreenDump(buf, 'Test_map_expr_2', {})
+
+ call term_sendkeys(buf, ":abc\<F2>")
+ call VerifyScreenDump(buf, 'Test_map_expr_3', {})
+ call term_sendkeys(buf, "\<Esc>0")
+ call VerifyScreenDump(buf, 'Test_map_expr_4', {})
+
+ " clean up
+ call StopVimInTerminal(buf)
+ call delete('XtestExprMap')
+endfunc
+
" Test for mapping errors
func Test_map_error()
call assert_fails('unmap', 'E474:')