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)
68a573ce2b
This commit is contained in:
zeertzjq 2022-04-28 21:18:58 +08:00
parent 1d97781dc5
commit 4adf2123dd
3 changed files with 87 additions and 25 deletions

View File

@ -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) {

View File

@ -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

View File

@ -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')