changeset 28359:390dfc3e409b v8.2.4705

patch 8.2.4705: jump list marker disappears Commit: https://github.com/vim/vim/commit/6d4e725a3447af6f69305fdc9f1e1ff8d82e3863 Author: zeertzjq <zeertzjq@outlook.com> Date: Thu Apr 7 13:58:04 2022 +0100 patch 8.2.4705: jump list marker disappears Problem: Jump list marker disappears. Solution: Reset reg_executing later. (closes https://github.com/vim/vim/issues/10111, closes https://github.com/vim/vim/issues/10100)
author Bram Moolenaar <Bram@vim.org>
date Thu, 07 Apr 2022 15:00:05 +0200
parents 44be5f4c12d4
children af739ab30d2a
files src/ex_docmd.c src/getchar.c src/globals.h src/structs.h src/testdir/test_registers.vim src/version.c
diffstat 6 files changed, 52 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -1733,6 +1733,7 @@ do_one_cmd(
     exarg_T	ea;			// Ex command arguments
     cmdmod_T	save_cmdmod;
     int		save_reg_executing = reg_executing;
+    int		save_pending_end_reg_executing = pending_end_reg_executing;
     int		ni;			// set when Not Implemented
     char_u	*cmd;
     int		starts_with_colon = FALSE;
@@ -2630,6 +2631,7 @@ doend:
     undo_cmdmod(&cmdmod);
     cmdmod = save_cmdmod;
     reg_executing = save_reg_executing;
+    pending_end_reg_executing = save_pending_end_reg_executing;
 
     if (ea.nextcmd && *ea.nextcmd == NUL)	// not really a next command
 	ea.nextcmd = NULL;
@@ -8456,6 +8458,7 @@ save_current_state(save_state_T *sst)
     sst->save_finish_op = finish_op;
     sst->save_opcount = opcount;
     sst->save_reg_executing = reg_executing;
+    sst->save_pending_end_reg_executing = pending_end_reg_executing;
 
     msg_scroll = FALSE;		    // no msg scrolling in Normal mode
     restart_edit = 0;		    // don't go to Insert mode
@@ -8485,6 +8488,7 @@ restore_current_state(save_state_T *sst)
     finish_op = sst->save_finish_op;
     opcount = sst->save_opcount;
     reg_executing = sst->save_reg_executing;
+    pending_end_reg_executing = sst->save_pending_end_reg_executing;
     msg_didout |= sst->save_msg_didout;	// don't reset msg_didout now
     current_sctx.sc_version = sst->save_script_version;
 
--- a/src/getchar.c
+++ b/src/getchar.c
@@ -1421,7 +1421,7 @@ static int old_mouse_row;	// mouse_row r
 static int old_mouse_col;	// mouse_col related to old_char
 static int old_KeyStuffed;	// whether old_char was stuffed
 
-static int can_get_old_char()
+static int can_get_old_char(void)
 {
     // If the old character was not stuffed and characters have been added to
     // the stuff buffer, need to first get the stuffed characters instead.
@@ -2950,7 +2950,7 @@ handle_mapping(
 
 /*
  * unget one character (can only be done once!)
- * If the character was stuffed, vgetc() will get it next time it was called.
+ * If the character was stuffed, vgetc() will get it next time it is called.
  * Otherwise vgetc() will only get it when the stuff buffer is empty.
  */
     void
@@ -2964,6 +2964,27 @@ vungetc(int c)
 }
 
 /*
+ * When peeking and not getting a character, reg_executing cannot be cleared
+ * yet, so set a flag to clear it later.
+ */
+    static void
+check_end_reg_executing(int advance)
+{
+    if (reg_executing != 0 && (typebuf.tb_maplen == 0
+						|| pending_end_reg_executing))
+    {
+	if (advance)
+	{
+	    reg_executing = 0;
+	    pending_end_reg_executing = FALSE;
+	}
+	else
+	    pending_end_reg_executing = TRUE;
+    }
+
+}
+
+/*
  * Get a byte:
  * 1. from the stuffbuffer
  *	This is used for abbreviated commands like "D" -> "d$".
@@ -3026,8 +3047,7 @@ vgetorpeek(int advance)
 
     init_typebuf();
     start_stuff();
-    if (advance && typebuf.tb_maplen == 0)
-	reg_executing = 0;
+    check_end_reg_executing(advance);
     do
     {
 /*
@@ -3068,6 +3088,7 @@ vgetorpeek(int advance)
 #ifdef FEAT_CMDL_INFO
 		int	showcmd_idx;
 #endif
+		check_end_reg_executing(advance);
 		/*
 		 * ui_breakcheck() is slow, don't use it too often when
 		 * inside a mapping.  But call it each time for typed
--- a/src/globals.h
+++ b/src/globals.h
@@ -1123,6 +1123,8 @@ EXTERN int ex_no_reprint INIT(= FALSE); 
 
 EXTERN int reg_recording INIT(= 0);	// register for recording  or zero
 EXTERN int reg_executing INIT(= 0);	// register being executed or zero
+// Flag set when peeking a character and found the end of executed register
+EXTERN int pending_end_reg_executing INIT(= 0);
 
 // Set when a modifyOtherKeys sequence was seen, then simplified mappings will
 // no longer be used.
--- a/src/structs.h
+++ b/src/structs.h
@@ -4302,6 +4302,7 @@ typedef struct {
     int		save_finish_op;
     int		save_opcount;
     int		save_reg_executing;
+    int		save_pending_end_reg_executing;
     int		save_script_version;
     tasave_T	tabuf;
 } save_state_T;
--- a/src/testdir/test_registers.vim
+++ b/src/testdir/test_registers.vim
@@ -759,6 +759,24 @@ func Test_record_in_select_mode()
   bwipe!
 endfunc
 
+func Test_end_reg_executing()
+  nnoremap s <Nop>
+  let @a = 's'
+  call feedkeys("@aqaq\<Esc>", 'tx')
+  call assert_equal('', @a)
+  call assert_equal('', getline(1))
+
+  call setline(1, 'aaa')
+  nnoremap s qa
+  let @a = 'fa'
+  call feedkeys("@asq\<Esc>", 'tx')
+  call assert_equal('', @a)
+  call assert_equal('aaa', getline(1))
+
+  nunmap s
+  bwipe!
+endfunc
+
 " Make sure that y_append is correctly reset
 " and the previous register is working as expected
 func Test_register_y_append_reset()
--- a/src/version.c
+++ b/src/version.c
@@ -747,6 +747,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    4705,
+/**/
     4704,
 /**/
     4703,