diff options
author | zeertzjq <zeertzjq@outlook.com> | 2022-04-28 21:18:58 +0800 |
---|---|---|
committer | zeertzjq <zeertzjq@outlook.com> | 2022-04-29 15:51:04 +0800 |
commit | 4adf2123dd94a3d5303fe200c7e909067e1cda34 (patch) | |
tree | f6dcfba23c192f0e127fc53448556b4108d53614 | |
parent | 1d97781dc53416072387b1d71aeaf11caecd8cf0 (diff) | |
download | rneovim-4adf2123dd94a3d5303fe200c7e909067e1cda34.tar.gz rneovim-4adf2123dd94a3d5303fe200c7e909067e1cda34.tar.bz2 rneovim-4adf2123dd94a3d5303fe200c7e909067e1cda34.zip |
vim-patch:8.2.4837: modifiers not simplified when timed out
Problem: Modifiers not simplified when timed out or using feedkeys() with
'n" flag.
Solution: Adjust how mapped flag and timeout are used. (closes vim/vim#10305)
https://github.com/vim/vim/commit/68a573ce2b996602a86b14d9b258ebb8c657604f
-rw-r--r-- | src/nvim/getchar.c | 23 | ||||
-rw-r--r-- | src/nvim/testdir/test_termcodes.vim | 16 | ||||
-rw-r--r-- | test/functional/options/pastetoggle_spec.lua | 73 |
3 files changed, 87 insertions, 25 deletions
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index 5aba241d45..a26ca3f2c8 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -2025,22 +2025,21 @@ static int handle_mapping(int *keylenp, bool *timedout, int *mapdepth) if ((mp == NULL || max_mlen > mp_match_len) && keylen != KEYLEN_PART_MAP) { // When no matching mapping found or found a non-matching mapping that // matches at least what the matching mapping matched: - // Try to include the modifier into the key, when: - // - mapping is allowed, - // - keys have not been mapped, - // - and when not timed out, - if ((no_mapping == 0 || allow_keys != 0) - && (typebuf.tb_maplen == 0 - || (p_remap && typebuf.tb_noremap[typebuf.tb_off] == RM_YES)) - && !*timedout) { + // Try to include the modifier into the key when mapping is allowed. + if (no_mapping == 0 || allow_keys != 0) { if (tb_c1 == K_SPECIAL && (typebuf.tb_len < 2 - || (typebuf.tb_buf[typebuf.tb_off + 1] == KS_MODIFIER - && typebuf.tb_len < 4))) { + || (typebuf.tb_buf[typebuf.tb_off + 1] == KS_MODIFIER && typebuf.tb_len < 4))) { // Incomplete modifier sequence: cannot decide whether to simplify yet. keylen = KEYLEN_PART_KEY; - // Don't simplify if 'pastetoggle' matched partially. - } else if (keylen != KEYLEN_PART_KEY) { + } else if (keylen == KEYLEN_PART_KEY && !*timedout) { + // If 'pastetoggle' matched partially, don't simplify. + // When the last characters were not typed, don't wait for a typed character to + // complete 'pastetoggle'. + if (typebuf.tb_len == typebuf.tb_maplen) { + keylen = 0; + } + } else { // Try to include the modifier into the key. keylen = check_simplify_modifier(max_mlen + 1); if (keylen < 0) { diff --git a/src/nvim/testdir/test_termcodes.vim b/src/nvim/testdir/test_termcodes.vim index 987889f33c..f3b10a922e 100644 --- a/src/nvim/testdir/test_termcodes.vim +++ b/src/nvim/testdir/test_termcodes.vim @@ -6,5 +6,21 @@ func Test_simplify_ctrl_at() bw! endfunc +func Test_simplify_noremap() + call feedkeys("i\<*C-M>", 'nx') + call assert_equal('', getline(1)) + call assert_equal([0, 2, 1, 0, 1], getcurpos()) + bw! +endfunc + +func Test_simplify_timedout() + inoremap <C-M>a b + call feedkeys("i\<*C-M>", 'xt') + call assert_equal('', getline(1)) + call assert_equal([0, 2, 1, 0, 1], getcurpos()) + iunmap <C-M>a + bw! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/test/functional/options/pastetoggle_spec.lua b/test/functional/options/pastetoggle_spec.lua index aaf30c54f4..40c14fa187 100644 --- a/test/functional/options/pastetoggle_spec.lua +++ b/test/functional/options/pastetoggle_spec.lua @@ -7,6 +7,7 @@ local eq = helpers.eq local expect = helpers.expect local eval = helpers.eval local insert = helpers.insert +local meths = helpers.meths local sleep = helpers.sleep describe("'pastetoggle' option", function() @@ -19,19 +20,65 @@ describe("'pastetoggle' option", function() feed('j') eq(1, eval('&paste')) end) - it("multiple key 'pastetoggle' is waited for", function() - eq(0, eval('&paste')) - local pastetoggle = 'lllll' - command('set pastetoggle=' .. pastetoggle) - command('set timeoutlen=1 ttimeoutlen=10000') - feed(pastetoggle:sub(0, 2)) - -- sleep() for long enough that vgetorpeek() is gotten into, but short - -- enough that ttimeoutlen is not reached. - sleep(200) - feed(pastetoggle:sub(3, -1)) - -- Need another key so that the vgetorpeek() function returns. - feed('j') - eq(1, eval('&paste')) + describe("multiple key 'pastetoggle'", function() + before_each(function() + eq(0, eval('&paste')) + command('set timeoutlen=1 ttimeoutlen=10000') + end) + it('is waited for when chars are typed', function() + local pastetoggle = 'lllll' + command('set pastetoggle=' .. pastetoggle) + feed(pastetoggle:sub(0, 2)) + -- sleep() for long enough that vgetorpeek() is gotten into, but short + -- enough that ttimeoutlen is not reached. + sleep(200) + feed(pastetoggle:sub(3, -1)) + -- Need another key so that the vgetorpeek() function returns. + feed('j') + eq(1, eval('&paste')) + end) + + it('is not waited for when there are no typed chars after mapped chars', function() + command('set pastetoggle=abc') + command('imap d a') + meths.feedkeys('id', 't', true) + -- sleep() for long enough that vgetorpeek() is gotten into, but short + -- enough that ttimeoutlen is not reached. + sleep(200) + feed('bc') + -- Need another key so that the vgetorpeek() function returns. + feed('j') + -- 'ttimeoutlen' should NOT apply + eq(0, eval('&paste')) + end) + + it('is waited for when there are typed chars after mapped chars', function() + command('set pastetoggle=abc') + command('imap d a') + meths.feedkeys('idb', 't', true) + -- sleep() for long enough that vgetorpeek() is gotten into, but short + -- enough that ttimeoutlen is not reached. + sleep(200) + feed('c') + -- Need another key so that the vgetorpeek() function returns. + feed('j') + -- 'ttimeoutlen' should apply + eq(1, eval('&paste')) + end) + + it('is waited for when there are typed chars after noremapped chars', function() + command('set pastetoggle=abc') + command('inoremap d a') + meths.feedkeys('idb', 't', true) + -- sleep() for long enough that vgetorpeek() is gotten into, but short + -- enough that ttimeoutlen is not reached. + sleep(200) + feed('c') + -- Need another key so that the vgetorpeek() function returns. + feed('j') + -- 'ttimeoutlen' should apply + eq(1, eval('&paste')) + end) end) it('does not interfere with character-find', function() insert('foo,bar') |