aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2022-04-28 21:18:58 +0800
committerzeertzjq <zeertzjq@outlook.com>2022-04-29 15:51:04 +0800
commit4adf2123dd94a3d5303fe200c7e909067e1cda34 (patch)
treef6dcfba23c192f0e127fc53448556b4108d53614
parent1d97781dc53416072387b1d71aeaf11caecd8cf0 (diff)
downloadrneovim-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.c23
-rw-r--r--src/nvim/testdir/test_termcodes.vim16
-rw-r--r--test/functional/options/pastetoggle_spec.lua73
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')