mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
Merge #5658 'Apply :lmap in macros'
This commit is contained in:
commit
2aa308c685
@ -411,7 +411,8 @@ state for Insert mode is also used when typing a character as an argument to
|
|||||||
command like "f" or "t".
|
command like "f" or "t".
|
||||||
Language mappings will never be applied to already mapped characters. They
|
Language mappings will never be applied to already mapped characters. They
|
||||||
are only used for typed characters. This assumes that the language mapping
|
are only used for typed characters. This assumes that the language mapping
|
||||||
was already done when typing the mapping.
|
was already done when typing the mapping. Correspondingly, language mappings
|
||||||
|
are applied when recording macros, rather than when applying them.
|
||||||
|
|
||||||
|
|
||||||
1.4 LISTING MAPPINGS *map-listing*
|
1.4 LISTING MAPPINGS *map-listing*
|
||||||
|
@ -834,7 +834,7 @@ keyboards and encodings.
|
|||||||
The actual mappings are in the lines below "loadkeymap". In the example "a"
|
The actual mappings are in the lines below "loadkeymap". In the example "a"
|
||||||
is mapped to "A" and "b" to "B". Thus the first item is mapped to the second
|
is mapped to "A" and "b" to "B". Thus the first item is mapped to the second
|
||||||
item. This is done for each line, until the end of the file.
|
item. This is done for each line, until the end of the file.
|
||||||
These items are exactly the same as what can be used in a |:lnoremap| command,
|
These items are exactly the same as what can be used in a |:lmap| command,
|
||||||
using "<buffer>" to make the mappings local to the buffer.
|
using "<buffer>" to make the mappings local to the buffer.
|
||||||
You can check the result with this command: >
|
You can check the result with this command: >
|
||||||
:lmap
|
:lmap
|
||||||
@ -849,8 +849,9 @@ Since Vim doesn't know if the next character after a quote is really an "a",
|
|||||||
it will wait for the next character. To be able to insert a single quote,
|
it will wait for the next character. To be able to insert a single quote,
|
||||||
also add this line: >
|
also add this line: >
|
||||||
'' '
|
'' '
|
||||||
Since the mapping is defined with |:lnoremap| the resulting quote will not be
|
Since the mapping is defined with |:lmap| the resulting quote will not be
|
||||||
used for the start of another character.
|
used for the start of another character defined in the 'keymap'.
|
||||||
|
It can be used in a standard |:imap| mapping.
|
||||||
The "accents" keymap uses this. *keymap-accents*
|
The "accents" keymap uses this. *keymap-accents*
|
||||||
|
|
||||||
The first column can also be in |<>| form:
|
The first column can also be in |<>| form:
|
||||||
|
@ -312,6 +312,12 @@ Highlight groups:
|
|||||||
VimL (Vim script) compatibility:
|
VimL (Vim script) compatibility:
|
||||||
`count` does not alias to |v:count|
|
`count` does not alias to |v:count|
|
||||||
|
|
||||||
|
|:lmap|s are applied to macro recordings, in Vim if a macro is recorded while
|
||||||
|
using |:lmap|ped keys then the behaviour during record and replay differs.
|
||||||
|
'keymap' is implemented via |:lmap| instead of |:lnoremap| in order to allow
|
||||||
|
using macros and 'keymap' at the same time.
|
||||||
|
This means that you can use |:imap| on the results of keys from 'keymap'.
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
5. Missing legacy features *nvim-features-missing*
|
5. Missing legacy features *nvim-features-missing*
|
||||||
|
|
||||||
|
@ -1833,12 +1833,12 @@ void ex_loadkeymap(exarg_T *eap)
|
|||||||
xfree(line);
|
xfree(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
// setup ":lnoremap" to map the keys
|
// setup ":lmap" to map the keys
|
||||||
for (int i = 0; i < curbuf->b_kmap_ga.ga_len; ++i) {
|
for (int i = 0; i < curbuf->b_kmap_ga.ga_len; i++) {
|
||||||
vim_snprintf((char *)buf, sizeof(buf), "<buffer> %s %s",
|
vim_snprintf((char *)buf, sizeof(buf), "<buffer> %s %s",
|
||||||
((kmap_T *)curbuf->b_kmap_ga.ga_data)[i].from,
|
((kmap_T *)curbuf->b_kmap_ga.ga_data)[i].from,
|
||||||
((kmap_T *)curbuf->b_kmap_ga.ga_data)[i].to);
|
((kmap_T *)curbuf->b_kmap_ga.ga_data)[i].to);
|
||||||
(void)do_map(2, buf, LANGMAP, FALSE);
|
(void)do_map(0, buf, LANGMAP, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
p_cpo = save_cpo;
|
p_cpo = save_cpo;
|
||||||
|
@ -1852,8 +1852,11 @@ static int vgetorpeek(int advance)
|
|||||||
keylen = KEYLEN_PART_MAP;
|
keylen = KEYLEN_PART_MAP;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (keylen > mp_match_len) {
|
} else if (keylen > mp_match_len
|
||||||
/* found a longer match */
|
|| (keylen == mp_match_len
|
||||||
|
&& (mp_match->m_mode & LANGMAP) == 0
|
||||||
|
&& (mp->m_mode & LANGMAP) != 0)) {
|
||||||
|
// found a longer match
|
||||||
mp_match = mp;
|
mp_match = mp;
|
||||||
mp_match_len = keylen;
|
mp_match_len = keylen;
|
||||||
}
|
}
|
||||||
@ -1947,8 +1950,9 @@ static int vgetorpeek(int advance)
|
|||||||
char_u *save_m_keys;
|
char_u *save_m_keys;
|
||||||
char_u *save_m_str;
|
char_u *save_m_str;
|
||||||
|
|
||||||
// write chars to script file(s)
|
// Write chars to script file(s)
|
||||||
if (keylen > typebuf.tb_maplen) {
|
// Note: :lmap mappings are written *after* being applied. #5658
|
||||||
|
if (keylen > typebuf.tb_maplen && (mp->m_mode & LANGMAP) == 0) {
|
||||||
gotchars(typebuf.tb_buf + typebuf.tb_off + typebuf.tb_maplen,
|
gotchars(typebuf.tb_buf + typebuf.tb_off + typebuf.tb_maplen,
|
||||||
(size_t)(keylen - typebuf.tb_maplen));
|
(size_t)(keylen - typebuf.tb_maplen));
|
||||||
}
|
}
|
||||||
@ -2023,6 +2027,12 @@ static int vgetorpeek(int advance)
|
|||||||
else {
|
else {
|
||||||
int noremap;
|
int noremap;
|
||||||
|
|
||||||
|
// If this is a LANGMAP mapping, then we didn't record the keys
|
||||||
|
// at the start of the function and have to record them now.
|
||||||
|
if (keylen > typebuf.tb_maplen && (mp->m_mode & LANGMAP) != 0) {
|
||||||
|
gotchars(s, STRLEN(s));
|
||||||
|
}
|
||||||
|
|
||||||
if (save_m_noremap != REMAP_YES)
|
if (save_m_noremap != REMAP_YES)
|
||||||
noremap = save_m_noremap;
|
noremap = save_m_noremap;
|
||||||
else if (
|
else if (
|
||||||
|
30
test/functional/normal/macro_spec.lua
Normal file
30
test/functional/normal/macro_spec.lua
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
local helpers = require('test.functional.helpers')(after_each)
|
||||||
|
|
||||||
|
local eq = helpers.eq
|
||||||
|
local eval = helpers.eval
|
||||||
|
local feed = helpers.feed
|
||||||
|
local clear = helpers.clear
|
||||||
|
local expect = helpers.expect
|
||||||
|
local command = helpers.command
|
||||||
|
|
||||||
|
describe('macros', function()
|
||||||
|
before_each(clear)
|
||||||
|
it('can be recorded and replayed', function()
|
||||||
|
feed('qiahello<esc>q')
|
||||||
|
expect('hello')
|
||||||
|
eq(eval('@i'), 'ahello')
|
||||||
|
feed('@i')
|
||||||
|
expect('hellohello')
|
||||||
|
eq(eval('@i'), 'ahello')
|
||||||
|
end)
|
||||||
|
it('applies maps', function()
|
||||||
|
command('imap x l')
|
||||||
|
command('nmap l a')
|
||||||
|
feed('qilxxx<esc>q')
|
||||||
|
expect('lll')
|
||||||
|
eq(eval('@i'), 'lxxx')
|
||||||
|
feed('@i')
|
||||||
|
expect('llllll')
|
||||||
|
eq(eval('@i'), 'lxxx')
|
||||||
|
end)
|
||||||
|
end)
|
233
test/functional/options/keymap_spec.lua
Normal file
233
test/functional/options/keymap_spec.lua
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
local helpers = require('test.functional.helpers')(after_each)
|
||||||
|
local clear, feed, eq = helpers.clear, helpers.feed, helpers.eq
|
||||||
|
local expect, command, eval = helpers.expect, helpers.command, helpers.eval
|
||||||
|
local insert, call = helpers.insert, helpers.call
|
||||||
|
local funcs, dedent = helpers.funcs, helpers.dedent
|
||||||
|
|
||||||
|
-- First test it's implemented using the :lmap and :lnoremap commands, then
|
||||||
|
-- check those mappings behave as expected.
|
||||||
|
describe("'keymap' / :lmap", function()
|
||||||
|
clear()
|
||||||
|
before_each(function()
|
||||||
|
clear()
|
||||||
|
insert("lllaaa")
|
||||||
|
command('set iminsert=1')
|
||||||
|
command('set imsearch=1')
|
||||||
|
command('lmap l a')
|
||||||
|
feed('gg0')
|
||||||
|
end)
|
||||||
|
|
||||||
|
describe("'keymap' as :lmap", function()
|
||||||
|
-- Shows that 'keymap' sets language mappings that allows remapping.
|
||||||
|
-- This equivalence allows us to only test :lmap commands and assert they
|
||||||
|
-- behave the same as 'keymap' settings.
|
||||||
|
-- It does rely on the absence of special code that implements 'keymap'
|
||||||
|
-- and :lmap differently but shows mappings from the 'keymap' after
|
||||||
|
-- typing :lmap.
|
||||||
|
-- At the moment this is the case.
|
||||||
|
it("'keymap' mappings are shown with :lmap", function()
|
||||||
|
command('lmapclear')
|
||||||
|
command('lmapclear <buffer>')
|
||||||
|
command('set keymap=dvorak')
|
||||||
|
command('set nomore')
|
||||||
|
local bindings = funcs.nvim_command_output('lmap')
|
||||||
|
eq(dedent([[
|
||||||
|
|
||||||
|
l " @_
|
||||||
|
l ' @-
|
||||||
|
l + @}
|
||||||
|
l , @w
|
||||||
|
l - @[
|
||||||
|
l . @v
|
||||||
|
l / @z
|
||||||
|
l : @S
|
||||||
|
l ; @s
|
||||||
|
l < @W
|
||||||
|
l = @]
|
||||||
|
l > @V
|
||||||
|
l ? @Z
|
||||||
|
l A @A
|
||||||
|
l B @X
|
||||||
|
l C @J
|
||||||
|
l D @E
|
||||||
|
l E @>
|
||||||
|
l F @U
|
||||||
|
l G @I
|
||||||
|
l H @D
|
||||||
|
l I @C
|
||||||
|
l J @H
|
||||||
|
l K @T
|
||||||
|
l L @N
|
||||||
|
l M @M
|
||||||
|
l N @B
|
||||||
|
l O @R
|
||||||
|
l P @L
|
||||||
|
l Q @"
|
||||||
|
l R @P
|
||||||
|
l S @O
|
||||||
|
l T @Y
|
||||||
|
l U @G
|
||||||
|
l V @K
|
||||||
|
l W @<
|
||||||
|
l X @Q
|
||||||
|
l Y @F
|
||||||
|
l Z @:
|
||||||
|
l [ @/
|
||||||
|
l \ @\
|
||||||
|
l ] @=
|
||||||
|
l _ @{
|
||||||
|
l a @a
|
||||||
|
l b @x
|
||||||
|
l c @j
|
||||||
|
l d @e
|
||||||
|
l e @.
|
||||||
|
l f @u
|
||||||
|
l g @i
|
||||||
|
l h @d
|
||||||
|
l i @c
|
||||||
|
l j @h
|
||||||
|
l k @t
|
||||||
|
l l @n
|
||||||
|
l m @m
|
||||||
|
l n @b
|
||||||
|
l o @r
|
||||||
|
l p @l
|
||||||
|
l q @'
|
||||||
|
l r @p
|
||||||
|
l s @o
|
||||||
|
l t @y
|
||||||
|
l u @g
|
||||||
|
l v @k
|
||||||
|
l w @,
|
||||||
|
l x @q
|
||||||
|
l y @f
|
||||||
|
l z @;
|
||||||
|
l { @?
|
||||||
|
l | @|
|
||||||
|
l } @+]]), bindings)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
describe("'iminsert' option", function()
|
||||||
|
it("Uses :lmap in insert mode when ON", function()
|
||||||
|
feed('il<esc>')
|
||||||
|
expect('alllaaa')
|
||||||
|
end)
|
||||||
|
it("Ignores :lmap in insert mode when OFF", function()
|
||||||
|
command('set iminsert=0')
|
||||||
|
feed('il<esc>')
|
||||||
|
expect('llllaaa')
|
||||||
|
end)
|
||||||
|
it("Can be toggled with <C-^> in insert mode", function()
|
||||||
|
feed('i<C-^>l<C-^>l<esc>')
|
||||||
|
expect('lalllaaa')
|
||||||
|
eq(eval('&iminsert'), 1)
|
||||||
|
feed('i<C-^><esc>')
|
||||||
|
eq(eval('&iminsert'), 0)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
describe("'imsearch' option", function()
|
||||||
|
it("Uses :lmap at search prompt when ON", function()
|
||||||
|
feed('/lll<cr>3x')
|
||||||
|
expect('lll')
|
||||||
|
end)
|
||||||
|
it("Ignores :lmap at search prompt when OFF", function()
|
||||||
|
command('set imsearch=0')
|
||||||
|
feed('gg/lll<cr>3x')
|
||||||
|
expect('aaa')
|
||||||
|
end)
|
||||||
|
it("Can be toggled with C-^", function()
|
||||||
|
eq(eval('&imsearch'), 1)
|
||||||
|
feed('/<C-^>lll<cr>3x')
|
||||||
|
expect('aaa')
|
||||||
|
eq(eval('&imsearch'), 0)
|
||||||
|
feed('u0/<C-^>lll<cr>3x')
|
||||||
|
expect('lll')
|
||||||
|
eq(eval('&imsearch'), 1)
|
||||||
|
end)
|
||||||
|
it("can follow 'iminsert'", function()
|
||||||
|
command('set imsearch=-1')
|
||||||
|
feed('/lll<cr>3x')
|
||||||
|
expect('lll')
|
||||||
|
eq(eval('&imsearch'), -1)
|
||||||
|
eq(eval('&iminsert'), 1)
|
||||||
|
feed('u/<C-^>lll<cr>3x')
|
||||||
|
expect('aaa')
|
||||||
|
eq(eval('&imsearch'), -1)
|
||||||
|
eq(eval('&iminsert'), 0)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
it(":lmap not applied to macros", function()
|
||||||
|
command("call setreg('a', 'il')")
|
||||||
|
feed('@a')
|
||||||
|
expect('llllaaa')
|
||||||
|
eq(call('getreg', 'a'), 'il')
|
||||||
|
end)
|
||||||
|
it(":lmap applied to macro recording", function()
|
||||||
|
feed('qail<esc>q@a')
|
||||||
|
expect('aalllaaa')
|
||||||
|
eq(call('getreg', 'a'), 'ia')
|
||||||
|
end)
|
||||||
|
it(":lmap not applied to mappings", function()
|
||||||
|
command('imap t l')
|
||||||
|
feed('it<esc>')
|
||||||
|
expect('llllaaa')
|
||||||
|
end)
|
||||||
|
it("mappings applied to keys created with :lmap", function()
|
||||||
|
command('imap a x')
|
||||||
|
feed('il<esc>')
|
||||||
|
expect('xlllaaa')
|
||||||
|
end)
|
||||||
|
it("mappings not applied to keys gotten with :lnoremap", function()
|
||||||
|
command('lmapclear')
|
||||||
|
command('lnoremap l a')
|
||||||
|
command('imap a x')
|
||||||
|
feed('il<esc>')
|
||||||
|
expect('alllaaa')
|
||||||
|
end)
|
||||||
|
-- This is a problem introduced when introducting :lmap and macro
|
||||||
|
-- compatibility. There are no plans to fix this as the complexity involved
|
||||||
|
-- seems too great.
|
||||||
|
pending('mappings not applied to macro replay of :lnoremap', function()
|
||||||
|
command('lmapclear')
|
||||||
|
command('lnoremap l a')
|
||||||
|
command('imap a x')
|
||||||
|
feed('qail<esc>q')
|
||||||
|
expect('alllaaa')
|
||||||
|
feed('@a')
|
||||||
|
expect('aalllaaa')
|
||||||
|
end)
|
||||||
|
it("is applied when using f/F t/T", function()
|
||||||
|
feed('flx')
|
||||||
|
expect('lllaa')
|
||||||
|
feed('0ia<esc>4lFlx')
|
||||||
|
expect('lllaa')
|
||||||
|
feed('tllx')
|
||||||
|
expect('llla')
|
||||||
|
feed('0ia<esc>4lTlhx')
|
||||||
|
expect('llla')
|
||||||
|
end)
|
||||||
|
it('takes priority over :imap mappings', function()
|
||||||
|
command('imap l x')
|
||||||
|
feed('il<esc>')
|
||||||
|
expect('alllaaa')
|
||||||
|
command('lmapclear')
|
||||||
|
command('lmap l a')
|
||||||
|
feed('il')
|
||||||
|
expect('aalllaaa')
|
||||||
|
end)
|
||||||
|
it('does not cause recursive mappings', function()
|
||||||
|
command('lmap a l')
|
||||||
|
feed('qaila<esc>q')
|
||||||
|
expect('allllaaa')
|
||||||
|
feed('u@a')
|
||||||
|
expect('allllaaa')
|
||||||
|
end)
|
||||||
|
it('can handle multicharacter mappings', function()
|
||||||
|
command("lmap 'a x")
|
||||||
|
command("lmap '' '")
|
||||||
|
feed("qai'a''a<esc>q")
|
||||||
|
expect("x'alllaaa")
|
||||||
|
feed('u@a')
|
||||||
|
expect("x'alllaaa")
|
||||||
|
end)
|
||||||
|
end)
|
Loading…
Reference in New Issue
Block a user