summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2022-04-07 13:58:04 +0100
committerBram Moolenaar <Bram@vim.org>2022-04-07 13:58:04 +0100
commit6d4e725a3447af6f69305fdc9f1e1ff8d82e3863 (patch)
tree2b8acbed1a0774ac7def27ea696f7ad59e93a6d7
parentf26c16144ddb27642c09f2cf5271afd163b36306 (diff)
downloadvim-git-6d4e725a3447af6f69305fdc9f1e1ff8d82e3863.tar.gz
patch 8.2.4705: jump list marker disappearsv8.2.4705
Problem: Jump list marker disappears. Solution: Reset reg_executing later. (closes #10111, closes #10100)
-rw-r--r--src/ex_docmd.c4
-rw-r--r--src/getchar.c29
-rw-r--r--src/globals.h2
-rw-r--r--src/structs.h1
-rw-r--r--src/testdir/test_registers.vim18
-rw-r--r--src/version.c2
6 files changed, 52 insertions, 4 deletions
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index 2d5752445..90ca7ade2 100644
--- 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;
diff --git a/src/getchar.c b/src/getchar.c
index b81f64a65..29ad56e6a 100644
--- a/src/getchar.c
+++ b/src/getchar.c
@@ -1421,7 +1421,7 @@ static int old_mouse_row; // mouse_row related to old_char
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
diff --git a/src/globals.h b/src/globals.h
index f690efffc..da1ff7639 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -1123,6 +1123,8 @@ EXTERN int ex_no_reprint INIT(= FALSE); // no need to print after z or p
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.
diff --git a/src/structs.h b/src/structs.h
index a1dbfbed2..b8648a545 100644
--- 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;
diff --git a/src/testdir/test_registers.vim b/src/testdir/test_registers.vim
index 078b78dfd..51543c00c 100644
--- 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()
diff --git a/src/version.c b/src/version.c
index 1bc106337..62623614a 100644
--- 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,