Merge pull request #17185 from zeertzjq/vim-8.2.3993

vim-patch:8.2.{3993,4002}: when recording a change in Select mode char appears twice
This commit is contained in:
bfredl 2022-01-27 13:45:34 +01:00 committed by GitHub
commit d95bb85024
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 111 additions and 19 deletions

View File

@ -284,9 +284,19 @@ static void add_buff(buffheader_T *const buf, const char *const s, ptrdiff_t sle
} }
} }
/* /// Delete "slen" bytes from the end of "buf".
* Add number "n" to buffer "buf". /// Only works when it was just added.
*/ static void delete_buff_tail(buffheader_T *buf, int slen)
{
int len = (int)STRLEN(buf->bh_curr->b_str);
if (len >= slen) {
buf->bh_curr->b_str[len - slen] = NUL;
buf->bh_space += (size_t)slen;
}
}
/// Add number "n" to buffer "buf".
static void add_num_buff(buffheader_T *buf, long n) static void add_num_buff(buffheader_T *buf, long n)
{ {
char number[32]; char number[32];
@ -967,31 +977,31 @@ int ins_typebuf(char_u *str, int noremap, int offset, bool nottyped, bool silent
return OK; return OK;
} }
/* /// Put character "c" back into the typeahead buffer.
* Put character "c" back into the typeahead buffer. /// Can be used for a character obtained by vgetc() that needs to be put back.
* Can be used for a character obtained by vgetc() that needs to be put back. /// Uses cmd_silent, KeyTyped and KeyNoremap to restore the flags belonging to
* Uses cmd_silent, KeyTyped and KeyNoremap to restore the flags belonging to /// the char.
* the char. /// @return the length of what was inserted
*/ int ins_char_typebuf(int c, int modifier)
void ins_char_typebuf(int c, int modifier)
{ {
char_u buf[MB_MAXBYTES + 4]; char_u buf[MB_MAXBYTES * 3 + 4];
int idx = 0; int len = 0;
if (modifier != 0) { if (modifier != 0) {
buf[0] = K_SPECIAL; buf[0] = K_SPECIAL;
buf[1] = KS_MODIFIER; buf[1] = KS_MODIFIER;
buf[2] = (char_u)modifier; buf[2] = (char_u)modifier;
buf[3] = NUL; buf[3] = NUL;
idx = 3; len = 3;
} }
if (IS_SPECIAL(c)) { if (IS_SPECIAL(c)) {
buf[idx] = K_SPECIAL; buf[len] = K_SPECIAL;
buf[idx + 1] = (char_u)K_SECOND(c); buf[len + 1] = (char_u)K_SECOND(c);
buf[idx + 2] = (char_u)K_THIRD(c); buf[len + 2] = (char_u)K_THIRD(c);
buf[idx + 3] = NUL; buf[len + 3] = NUL;
} else { } else {
char_u *p = buf + idx; char_u *p = buf + len;
int char_len = utf_char2bytes(c, p); int char_len = utf_char2bytes(c, p);
len += char_len;
// If the character contains K_SPECIAL bytes they need escaping. // If the character contains K_SPECIAL bytes they need escaping.
for (int i = char_len; --i >= 0; p++) { for (int i = char_len; --i >= 0; p++) {
if ((uint8_t)(*p) == K_SPECIAL) { if ((uint8_t)(*p) == K_SPECIAL) {
@ -999,11 +1009,13 @@ void ins_char_typebuf(int c, int modifier)
*p++ = K_SPECIAL; *p++ = K_SPECIAL;
*p++ = KS_SPECIAL; *p++ = KS_SPECIAL;
*p = KE_FILLER; *p = KE_FILLER;
len += 2;
} }
} }
*p = NUL; *p = NUL;
} }
(void)ins_typebuf(buf, KeyNoremap, 0, !KeyTyped, cmd_silent); (void)ins_typebuf(buf, KeyNoremap, 0, !KeyTyped, cmd_silent);
return len;
} }
/// Return TRUE if the typeahead buffer was changed (while waiting for a /// Return TRUE if the typeahead buffer was changed (while waiting for a
@ -1163,6 +1175,18 @@ static void gotchars(const char_u *chars, size_t len)
maptick++; maptick++;
} }
/// Undo the last gotchars() for "len" bytes. To be used when putting a typed
/// character back into the typeahead buffer, thus gotchars() will be called
/// again.
/// Only affects recorded characters.
void ungetchars(int len)
{
if (reg_recording != 0) {
delete_buff_tail(&recordbuff, len);
last_recorded_len -= (size_t)len;
}
}
/* /*
* Sync undo. Called when typed characters are obtained from the typeahead * Sync undo. Called when typed characters are obtained from the typeahead
* buffer, or when a menu is used. * buffer, or when a menu is used.

View File

@ -1011,7 +1011,12 @@ static int normal_execute(VimState *state, int key)
// restart automatically. // restart automatically.
// Insert the typed character in the typeahead buffer, so that it can // Insert the typed character in the typeahead buffer, so that it can
// be mapped in Insert mode. Required for ":lmap" to work. // be mapped in Insert mode. Required for ":lmap" to work.
ins_char_typebuf(s->c, mod_mask); int len = ins_char_typebuf(s->c, mod_mask);
// When recording the character will be recorded again, remove the
// previously recording.
ungetchars(len);
if (restart_edit != 0) { if (restart_edit != 0) {
s->c = 'd'; s->c = 'd';
} else { } else {

View File

@ -121,6 +121,17 @@ func Test_recording_esc_sequence()
endif endif
endfunc endfunc
func Test_recording_with_select_mode()
new
call feedkeys("qacc12345\<Esc>gH98765\<Esc>q", "tx")
call assert_equal("98765", getline(1))
call assert_equal("cc12345\<Esc>gH98765\<Esc>", @a)
call setline(1, 'asdf')
normal! @a
call assert_equal("98765", getline(1))
bwipe!
endfunc
" Test for executing the last used register (@) " Test for executing the last used register (@)
func Test_last_used_exec_reg() func Test_last_used_exec_reg()
" Test for the @: command " Test for the @: command

View File

@ -1,5 +1,6 @@
" Tests for Unicode manipulations " Tests for Unicode manipulations
source check.vim
source view_util.vim source view_util.vim
" Visual block Insert adjusts for multi-byte char " Visual block Insert adjusts for multi-byte char
@ -148,4 +149,55 @@ func Test_print_overlong()
bwipe! bwipe!
endfunc endfunc
func Test_recording_with_select_mode_utf8()
call Run_test_recording_with_select_mode_utf8()
endfunc
func Run_test_recording_with_select_mode_utf8()
new
" No escaping
call feedkeys("qacc12345\<Esc>gH哦\<Esc>q", "tx")
call assert_equal("哦", getline(1))
call assert_equal("cc12345\<Esc>gH哦\<Esc>", @a)
call setline(1, 'asdf')
normal! @a
call assert_equal("哦", getline(1))
" 固 is 0xE5 0x9B 0xBA where 0x9B is CSI
call feedkeys("qacc12345\<Esc>gH固\<Esc>q", "tx")
call assert_equal("固", getline(1))
call assert_equal("cc12345\<Esc>gH固\<Esc>", @a)
call setline(1, 'asdf')
normal! @a
call assert_equal("固", getline(1))
" 四 is 0xE5 0x9B 0x9B where 0x9B is CSI
call feedkeys("qacc12345\<Esc>gH四\<Esc>q", "tx")
call assert_equal("四", getline(1))
call assert_equal("cc12345\<Esc>gH四\<Esc>", @a)
call setline(1, 'asdf')
normal! @a
call assert_equal("四", getline(1))
" 倒 is 0xE5 0x80 0x92 where 0x80 is K_SPECIAL
call feedkeys("qacc12345\<Esc>gH倒\<Esc>q", "tx")
call assert_equal("倒", getline(1))
call assert_equal("cc12345\<Esc>gH倒\<Esc>", @a)
call setline(1, 'asdf')
normal! @a
call assert_equal("倒", getline(1))
bwipe!
endfunc
" This must be done as one of the last tests, because it starts the GUI, which
" cannot be undone.
func Test_zz_recording_with_select_mode_utf8_gui()
CheckCanRunGui
gui -f
call Run_test_recording_with_select_mode_utf8()
endfunc
" vim: shiftwidth=2 sts=2 expandtab " vim: shiftwidth=2 sts=2 expandtab