diff src/getchar.c @ 30102:539fb427124d v9.0.0387

patch 9.0.0387: repeat <ScriptCmd> mapping doesn't use right script context Commit: https://github.com/vim/vim/commit/ddf7dba96e05a41c7a228b153146237e0a21b146 Author: Bram Moolenaar <Bram@vim.org> Date: Mon Sep 5 16:53:21 2022 +0100 patch 9.0.0387: repeat <ScriptCmd> mapping doesn't use right script context Problem: repeating a <ScriptCmd> mapping does not use the right script context. Solution: When using a mapping put <SID>{sid}; in the redo buffer. (closes #11049)
author Bram Moolenaar <Bram@vim.org>
date Mon, 05 Sep 2022 18:00:05 +0200
parents 5b4f3129cadc
children cabceac53ade
line wrap: on
line diff
--- a/src/getchar.c
+++ b/src/getchar.c
@@ -85,6 +85,7 @@ static int	last_recorded_len = 0;	// num
 
 #ifdef FEAT_EVAL
 mapblock_T	*last_used_map = NULL;
+int		last_used_sid = -1;
 #endif
 
 static int	read_readbuf(buffheader_T *buf, int advance);
@@ -837,6 +838,22 @@ start_redo(long count, int old_redo)
 
     c = read_redo(FALSE, old_redo);
 
+#ifdef FEAT_EVAL
+    if (c == K_SID)
+    {
+	// Copy the <SID>{sid}; sequence
+	add_char_buff(&readbuf2, c);
+	for (;;)
+	{
+	    c = read_redo(FALSE, old_redo);
+	    add_char_buff(&readbuf2, c);
+	    if (!isdigit(c))
+		break;
+	}
+	c = read_redo(FALSE, old_redo);
+    }
+#endif
+
     // copy the buffer name, if present
     if (c == '"')
     {
@@ -876,7 +893,7 @@ start_redo(long count, int old_redo)
 	add_num_buff(&readbuf2, count);
     }
 
-    // copy from the redo buffer into the stuff buffer
+    // copy the rest from the redo buffer into the stuff buffer
     add_char_buff(&readbuf2, c);
     copy_redo(old_redo);
     return OK;
@@ -1796,7 +1813,21 @@ vgetc(void)
 		if (c == K_CSI)
 		    c = CSI;
 #endif
+#ifdef FEAT_EVAL
+		if (c == K_SID)
+		{
+		    int	    j;
+
+		    // Handle <SID>{sid};  Do up to 20 digits for safety.
+		    last_used_sid = 0;
+		    for (j = 0; j < 20 && isdigit(c = vgetorpeek(TRUE)); ++j)
+			last_used_sid = last_used_sid * 10 + (c - '0');
+		    last_used_map = NULL;
+		    continue;
+		}
+#endif
 	    }
+
 	    // a keypad or special function key was not mapped, use it like
 	    // its ASCII equivalent
 	    switch (c)
@@ -2922,6 +2953,10 @@ handle_mapping(
 	{
 	    int noremap;
 
+#ifdef FEAT_EVAL
+	    last_used_map = mp;
+	    last_used_sid = -1;
+#endif
 	    if (save_m_noremap != REMAP_YES)
 		noremap = save_m_noremap;
 	    else if (
@@ -2940,7 +2975,6 @@ handle_mapping(
 #ifdef FEAT_EVAL
 	    if (save_m_expr)
 		vim_free(map_str);
-	    last_used_map = mp;
 #endif
 	}
 #ifdef FEAT_EVAL
@@ -3896,6 +3930,29 @@ getcmdkeycmd(
     return (char_u *)line_ga.ga_data;
 }
 
+#if defined(FEAT_EVAL) || defined(PROTO)
+/*
+ * If there was a mapping put info about it in the redo buffer, so that "."
+ * will use the same script context.  We only need the SID.
+ */
+    void
+may_add_last_used_map_to_redobuff(void)
+{
+    char_u buf[3 + 20];
+
+    if (last_used_map == NULL || last_used_map->m_script_ctx.sc_sid < 0)
+	return;
+
+    // <K_SID>{nr};
+    buf[0] = K_SPECIAL;
+    buf[1] = KS_EXTRA;
+    buf[2] = KE_SID;
+    vim_snprintf((char *)buf + 3, 20, "%d;",
+					   last_used_map->m_script_ctx.sc_sid);
+    add_buff(&redobuff, buf, -1L);
+}
+#endif
+
     int
 do_cmdkey_command(int key UNUSED, int flags)
 {
@@ -3903,10 +3960,18 @@ do_cmdkey_command(int key UNUSED, int fl
 #ifdef FEAT_EVAL
     sctx_T  save_current_sctx = {-1, 0, 0, 0};
 
-    if (key == K_SCRIPT_COMMAND && last_used_map != NULL)
+    if (key == K_SCRIPT_COMMAND
+		  && (last_used_map != NULL || SCRIPT_ID_VALID(last_used_sid)))
     {
 	save_current_sctx = current_sctx;
-	current_sctx = last_used_map->m_script_ctx;
+	if (last_used_map != NULL)
+	    current_sctx = last_used_map->m_script_ctx;
+	else
+	{
+	    current_sctx.sc_sid = last_used_sid;
+	    current_sctx.sc_lnum = 0;
+	    current_sctx.sc_version = SCRIPT_ITEM(last_used_sid)->sn_version;
+	}
     }
 #endif
 
@@ -3925,6 +3990,9 @@ do_cmdkey_command(int key UNUSED, int fl
 reset_last_used_map(mapblock_T *mp)
 {
     if (last_used_map == mp)
+    {
 	last_used_map = NULL;
+	last_used_sid = -1;
+    }
 }
 #endif