diff options
-rw-r--r-- | src/nvim/getchar.c | 14 | ||||
-rw-r--r-- | src/nvim/normal.c | 41 | ||||
-rw-r--r-- | test/old/testdir/test_registers.vim | 26 |
3 files changed, 57 insertions, 24 deletions
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index 5c1366c5b2..2e584e7cff 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -1147,6 +1147,13 @@ static void gotchars(const uint8_t *chars, size_t len) maptick++; } +/// Record a <Nop> key. +void gotchars_nop(void) +{ + uint8_t nop_buf[3] = { K_SPECIAL, KS_EXTRA, KE_NOP }; + gotchars(nop_buf, 3); +} + /// 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. @@ -2745,14 +2752,9 @@ static int vgetorpeek(bool advance) } if (timedout && c == ESC) { - uint8_t nop_buf[3]; - // When recording there will be no timeout. Add a <Nop> after the ESC // to avoid that it forms a key code with following characters. - nop_buf[0] = K_SPECIAL; - nop_buf[1] = KS_EXTRA; - nop_buf[2] = KE_NOP; - gotchars(nop_buf, 3); + gotchars_nop(); } vgetc_busy--; diff --git a/src/nvim/normal.c b/src/nvim/normal.c index b82a6b928d..1e9bc78fe3 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -807,25 +807,32 @@ static void normal_get_additional_char(NormalState *s) } } - // When getting a text character and the next character is a - // multi-byte character, it could be a composing character. - // However, don't wait for it to arrive. Also, do enable mapping, - // because if it's put back with vungetc() it's too late to apply - // mapping. - no_mapping--; - while (lang && (s->c = vpeekc()) > 0 - && (s->c >= 0x100 || MB_BYTE2LEN(vpeekc()) > 1)) { - s->c = plain_vgetc(); - if (!utf_iscomposing(s->c)) { - vungetc(s->c); // it wasn't, put it back - break; - } else if (s->ca.ncharC1 == 0) { - s->ca.ncharC1 = s->c; - } else { - s->ca.ncharC2 = s->c; + if (lang) { + // When getting a text character and the next character is a + // multi-byte character, it could be a composing character. + // However, don't wait for it to arrive. Also, do enable mapping, + // because if it's put back with vungetc() it's too late to apply + // mapping. + no_mapping--; + while (lang && (s->c = vpeekc()) > 0 + && (s->c >= 0x100 || MB_BYTE2LEN(vpeekc()) > 1)) { + s->c = plain_vgetc(); + if (!utf_iscomposing(s->c)) { + vungetc(s->c); // it wasn't, put it back + break; + } else if (s->ca.ncharC1 == 0) { + s->ca.ncharC1 = s->c; + } else { + s->ca.ncharC2 = s->c; + } } + no_mapping++; + // Vim may be in a different mode when the user types the next key, + // but when replaying a recording the next key is already in the + // typeahead buffer, so record a <Nop> before that to prevent the + // vpeekc() above from applying wrong mappings when replaying. + gotchars_nop(); } - no_mapping++; } no_mapping--; allow_keys--; diff --git a/test/old/testdir/test_registers.vim b/test/old/testdir/test_registers.vim index 70dac535b4..01f9507916 100644 --- a/test/old/testdir/test_registers.vim +++ b/test/old/testdir/test_registers.vim @@ -758,8 +758,9 @@ func Test_record_in_select_mode() bwipe! endfunc -" mapping that ends macro recording should be removed from recorded macro +" A mapping that ends recording should be removed from the recorded register. func Test_end_record_using_mapping() + new call setline(1, 'aaa') nnoremap s q call feedkeys('safas', 'tx') @@ -779,7 +780,10 @@ func Test_end_record_using_mapping() bwipe! endfunc +" Starting a new recording should work immediately after replaying a recording +" that ends with a <Nop> mapping or a character search. func Test_end_reg_executing() + new nnoremap s <Nop> let @a = 's' call feedkeys("@aqaq\<Esc>", 'tx') @@ -797,5 +801,25 @@ func Test_end_reg_executing() bwipe! endfunc +" An operator-pending mode mapping shouldn't be applied to keys typed in +" Insert mode immediately after a character search when replaying. +func Test_replay_charsearch_omap() + CheckFeature timers + + new + call setline(1, 'foo[blah]') + onoremap , k + call timer_start(10, {-> feedkeys(",bar\<Esc>q", 't')}) + call feedkeys('qrct[', 'xt!') + call assert_equal(',bar[blah]', getline(1)) + undo + call assert_equal('foo[blah]', getline(1)) + call feedkeys('@r', 'xt!') + call assert_equal(',bar[blah]', getline(1)) + + ounmap , + bwipe! +endfunc + " vim: shiftwidth=2 sts=2 expandtab |