aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/getchar.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/getchar.c')
-rw-r--r--src/nvim/getchar.c47
1 files changed, 43 insertions, 4 deletions
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index 741fc6d803..f249cde9a0 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -1710,6 +1710,15 @@ static int handle_mapping(int *keylenp, bool *timedout, int *mapdepth)
int keylen = *keylenp;
int i;
int local_State = get_real_state();
+ bool is_plug_map = false;
+
+ // Check if typehead starts with a <Plug> mapping.
+ // In that case we will ignore nore flag on it.
+ if (typebuf.tb_buf[typebuf.tb_off] == K_SPECIAL
+ && typebuf.tb_buf[typebuf.tb_off+1] == KS_EXTRA
+ && typebuf.tb_buf[typebuf.tb_off+2] == KE_PLUG) {
+ is_plug_map = true;
+ }
// Check for a mappable key sequence.
// Walk through one maphash[] list until we find an entry that matches.
@@ -1725,7 +1734,7 @@ static int handle_mapping(int *keylenp, bool *timedout, int *mapdepth)
tb_c1 = typebuf.tb_buf[typebuf.tb_off];
if (no_mapping == 0 && maphash_valid
&& (no_zero_mapping == 0 || tb_c1 != '0')
- && (typebuf.tb_maplen == 0
+ && (typebuf.tb_maplen == 0 || is_plug_map
|| (p_remap
&& !(typebuf.tb_noremap[typebuf.tb_off] & (RM_NONE|RM_ABBR))))
&& !(p_paste && (State & (INSERT + CMDLINE)))
@@ -1813,7 +1822,7 @@ static int handle_mapping(int *keylenp, bool *timedout, int *mapdepth)
break;
}
}
- if (n >= 0) {
+ if (!is_plug_map && n >= 0) {
continue;
}
@@ -1949,8 +1958,11 @@ static int handle_mapping(int *keylenp, bool *timedout, int *mapdepth)
// expression. Also save and restore the command line
// for "normal :".
if (mp->m_expr) {
- int save_vgetc_busy = vgetc_busy;
+ const int save_vgetc_busy = vgetc_busy;
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;
@@ -1960,6 +1972,32 @@ static int handle_mapping(int *keylenp, bool *timedout, int *mapdepth)
save_m_str = vim_strsave(mp->m_str);
}
map_str = eval_map_expr(mp, NUL);
+
+ // The mapping may do anything, but we expect it to take care of
+ // redrawing. Do put the cursor back where it was.
+ 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 {
@@ -2455,7 +2493,7 @@ static int vgetorpeek(bool advance)
/// 1. a scriptfile
/// 2. the keyboard
///
-/// As much characters as we can get (up to 'maxlen') are put in "buf" and
+/// As many characters as we can get (up to 'maxlen') are put in "buf" and
/// NUL terminated (buffer length must be 'maxlen' + 1).
/// Minimum for "maxlen" is 3!!!!
///
@@ -3490,6 +3528,7 @@ static void showmap(mapblock_T *mp, bool local)
if (p_verbose > 0) {
last_set_msg(mp->m_script_ctx);
}
+ msg_clr_eos();
ui_flush(); // show one line at a time
}