vim-patch:8.2.4932: not easy to filter the output of maplist()

Problem:    Not easy to filter the output of maplist().
Solution:   Add mode_bits to the dictionary. (Ernie Rael, closes vim/vim#10356)

d8f5f76621

Co-authored-by: Ernie Rael <errael@raelity.com>
This commit is contained in:
zeertzjq
2023-11-09 20:42:55 +08:00
parent f748a73a35
commit 04d299c170
7 changed files with 120 additions and 26 deletions

View File

@@ -4186,6 +4186,11 @@ maparg({name} [, {mode} [, {abbr} [, {dict}]]]) *maparg()*
"nowait" Do not wait for other, longer mappings. "nowait" Do not wait for other, longer mappings.
(|:map-<nowait>|). (|:map-<nowait>|).
"abbr" True if this is an |abbreviation|. "abbr" True if this is an |abbreviation|.
"mode_bits" Nvim's internal binary representation of "mode".
|mapset()| ignores this; only "mode" is used.
See |maplist()| for usage examples. The values
are from src/nvim/vim.h and may change in the
future.
The dictionary can be used to restore a mapping with The dictionary can be used to restore a mapping with
|mapset()|. |mapset()|.
@@ -4239,6 +4244,26 @@ maplist([{abbr}]) *maplist()*
echo maplist()->filter({_, m -> echo maplist()->filter({_, m ->
\ match(get(m, 'rhs', ''), 'MultiMatch') >= 0 \ match(get(m, 'rhs', ''), 'MultiMatch') >= 0
\ }) \ })
< It can be tricky to find mappings for particular |:map-modes|.
|mapping-dict|'s "mode_bits" can simplify this. For example,
the mode_bits for Normal, Insert or Command-line modes are
0x19. To find all the mappings available in those modes you
can do: >vim
let saved_maps = []
for m in maplist()
if and(m.mode_bits, 0x19) != 0
eval saved_maps->add(m)
endif
endfor
echo saved_maps->mapnew({_, m -> m.lhs})
< The values of the mode_bits are defined in Nvim's
src/nvim/vim.h file and they can be discovered at runtime
using |:map-commands| and "maplist()". Example: >vim
omap xyzzy <Nop>
let op_bit = maplist()->filter(
\ {_, m -> m.lhs == 'xyzzy'})[0].mode_bits
ounmap xyzzy
echo printf("Operator-pending mode bit: 0x%x", op_bit)
mapnew({expr1}, {expr2}) *mapnew()* mapnew({expr1}, {expr2}) *mapnew()*
Like |map()| but instead of replacing items in {expr1} a new Like |map()| but instead of replacing items in {expr1} a new

View File

@@ -5047,6 +5047,11 @@ function vim.fn.map(expr1, expr2) end
--- "nowait" Do not wait for other, longer mappings. --- "nowait" Do not wait for other, longer mappings.
--- (|:map-<nowait>|). --- (|:map-<nowait>|).
--- "abbr" True if this is an |abbreviation|. --- "abbr" True if this is an |abbreviation|.
--- "mode_bits" Nvim's internal binary representation of "mode".
--- |mapset()| ignores this; only "mode" is used.
--- See |maplist()| for usage examples. The values
--- are from src/nvim/vim.h and may change in the
--- future.
--- ---
--- The dictionary can be used to restore a mapping with --- The dictionary can be used to restore a mapping with
--- |mapset()|. --- |mapset()|.
@@ -5111,6 +5116,26 @@ function vim.fn.mapcheck(name, mode, abbr) end
--- echo maplist()->filter({_, m -> --- echo maplist()->filter({_, m ->
--- \ match(get(m, 'rhs', ''), 'MultiMatch') >= 0 --- \ match(get(m, 'rhs', ''), 'MultiMatch') >= 0
--- \ }) --- \ })
--- <It can be tricky to find mappings for particular |:map-modes|.
--- |mapping-dict|'s "mode_bits" can simplify this. For example,
--- the mode_bits for Normal, Insert or Command-line modes are
--- 0x19. To find all the mappings available in those modes you
--- can do: >vim
--- let saved_maps = []
--- for m in maplist()
--- if and(m.mode_bits, 0x19) != 0
--- eval saved_maps->add(m)
--- endif
--- endfor
--- echo saved_maps->mapnew({_, m -> m.lhs})
--- <The values of the mode_bits are defined in Nvim's
--- src/nvim/vim.h file and they can be discovered at runtime
--- using |:map-commands| and "maplist()". Example: >vim
--- omap xyzzy <Nop>
--- let op_bit = maplist()->filter(
--- \ {_, m -> m.lhs == 'xyzzy'})[0].mode_bits
--- ounmap xyzzy
--- echo printf("Operator-pending mode bit: 0x%x", op_bit)
--- ---
--- @return any --- @return any
function vim.fn.maplist() end function vim.fn.maplist() end

View File

@@ -6195,6 +6195,11 @@ M.funcs = {
"nowait" Do not wait for other, longer mappings. "nowait" Do not wait for other, longer mappings.
(|:map-<nowait>|). (|:map-<nowait>|).
"abbr" True if this is an |abbreviation|. "abbr" True if this is an |abbreviation|.
"mode_bits" Nvim's internal binary representation of "mode".
|mapset()| ignores this; only "mode" is used.
See |maplist()| for usage examples. The values
are from src/nvim/vim.h and may change in the
future.
The dictionary can be used to restore a mapping with The dictionary can be used to restore a mapping with
|mapset()|. |mapset()|.
@@ -6269,6 +6274,26 @@ M.funcs = {
echo maplist()->filter({_, m -> echo maplist()->filter({_, m ->
\ match(get(m, 'rhs', ''), 'MultiMatch') >= 0 \ match(get(m, 'rhs', ''), 'MultiMatch') >= 0
\ }) \ })
<It can be tricky to find mappings for particular |:map-modes|.
|mapping-dict|'s "mode_bits" can simplify this. For example,
the mode_bits for Normal, Insert or Command-line modes are
0x19. To find all the mappings available in those modes you
can do: >vim
let saved_maps = []
for m in maplist()
if and(m.mode_bits, 0x19) != 0
eval saved_maps->add(m)
endif
endfor
echo saved_maps->mapnew({_, m -> m.lhs})
<The values of the mode_bits are defined in Nvim's
src/nvim/vim.h file and they can be discovered at runtime
using |:map-commands| and "maplist()". Example: >vim
omap xyzzy <Nop>
let op_bit = maplist()->filter(
\ {_, m -> m.lhs == 'xyzzy'})[0].mode_bits
ounmap xyzzy
echo printf("Operator-pending mode bit: 0x%x", op_bit)
]], ]],
name = 'maplist', name = 'maplist',
params = {}, params = {},

View File

@@ -2125,6 +2125,7 @@ static Dictionary mapblock_fill_dict(const mapblock_T *const mp, const char *lhs
} }
PUT(dict, "mode", CSTR_AS_OBJ(mapmode)); PUT(dict, "mode", CSTR_AS_OBJ(mapmode));
PUT(dict, "abbr", INTEGER_OBJ(abbr ? 1 : 0)); PUT(dict, "abbr", INTEGER_OBJ(abbr ? 1 : 0));
PUT(dict, "mode_bits", INTEGER_OBJ(mp->m_mode));
return dict; return dict;
} }

View File

@@ -19,6 +19,20 @@ local sleep = helpers.sleep
local sid_api_client = -9 local sid_api_client = -9
local sid_lua = -8 local sid_lua = -8
local mode_bits_map = {
['n'] = 0x01,
['x'] = 0x02,
['o'] = 0x04,
['c'] = 0x08,
['i'] = 0x10,
['l'] = 0x20,
['s'] = 0x40,
['t'] = 0x80,
[' '] = 0x47,
['v'] = 0x42,
['!'] = 0x18,
}
describe('nvim_get_keymap', function() describe('nvim_get_keymap', function()
before_each(clear) before_each(clear)
@@ -36,6 +50,7 @@ describe('nvim_get_keymap', function()
buffer=0, buffer=0,
nowait=0, nowait=0,
mode='n', mode='n',
mode_bits=0x01,
abbr=0, abbr=0,
noremap=1, noremap=1,
lnum=0, lnum=0,
@@ -83,6 +98,7 @@ describe('nvim_get_keymap', function()
-- The table will be the same except for the mode -- The table will be the same except for the mode
local insert_table = shallowcopy(foo_bar_map_table) local insert_table = shallowcopy(foo_bar_map_table)
insert_table['mode'] = 'i' insert_table['mode'] = 'i'
insert_table['mode_bits'] = 0x10
eq({insert_table}, meths.get_keymap('i')) eq({insert_table}, meths.get_keymap('i'))
end) end)
@@ -272,6 +288,7 @@ describe('nvim_get_keymap', function()
ret.lhs = lhs ret.lhs = lhs
ret.rhs = rhs ret.rhs = rhs
ret.mode = mode ret.mode = mode
ret.mode_bits = mode_bits_map[mode]
return ret return ret
end end
@@ -327,6 +344,7 @@ describe('nvim_get_keymap', function()
lhsraw='| |', lhsraw='| |',
rhs='| |', rhs='| |',
mode='n', mode='n',
mode_bits=0x01,
abbr=0, abbr=0,
script=0, script=0,
silent=0, silent=0,
@@ -375,6 +393,7 @@ describe('nvim_get_keymap', function()
buffer=0, buffer=0,
nowait=0, nowait=0,
mode='n', mode='n',
mode_bits=0x01,
abbr=0, abbr=0,
noremap=0, noremap=0,
lnum=0, lnum=0,
@@ -395,6 +414,7 @@ describe('nvim_get_keymap', function()
buffer=0, buffer=0,
nowait=0, nowait=0,
mode='n', mode='n',
mode_bits=0x01,
abbr=0, abbr=0,
noremap=0, noremap=0,
lnum=0, lnum=0,
@@ -430,7 +450,9 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
end end
local to_return = {} local to_return = {}
to_return.mode = normalize_mapmode(mode, true) local expected_mode = normalize_mapmode(mode, true)
to_return.mode = expected_mode
to_return.mode_bits = mode_bits_map[expected_mode]
to_return.abbr = mode:sub(-1) == 'a' and 1 or 0 to_return.abbr = mode:sub(-1) == 'a' and 1 or 0
to_return.noremap = not opts.noremap and 0 or 1 to_return.noremap = not opts.noremap and 0 or 1
to_return.lhs = lhs to_return.lhs = lhs
@@ -499,7 +521,12 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
get_mapargs('', 'lhs')) get_mapargs('', 'lhs'))
end) end)
it('throws errors when given too-long mode shortnames', function() it('error on invalid mode shortname', function()
eq('Invalid mode shortname: " "', pcall_err(meths.set_keymap, ' ', 'lhs', 'rhs', {}))
eq('Invalid mode shortname: "m"', pcall_err(meths.set_keymap, 'm', 'lhs', 'rhs', {}))
eq('Invalid mode shortname: "?"', pcall_err(meths.set_keymap, '?', 'lhs', 'rhs', {}))
eq('Invalid mode shortname: "y"', pcall_err(meths.set_keymap, 'y', 'lhs', 'rhs', {}))
eq('Invalid mode shortname: "p"', pcall_err(meths.set_keymap, 'p', 'lhs', 'rhs', {}))
eq('Invalid mode shortname: "a"', pcall_err(meths.set_keymap, 'a', 'lhs', 'rhs', {})) eq('Invalid mode shortname: "a"', pcall_err(meths.set_keymap, 'a', 'lhs', 'rhs', {}))
eq('Invalid mode shortname: "oa"', pcall_err(meths.set_keymap, 'oa', 'lhs', 'rhs', {})) eq('Invalid mode shortname: "oa"', pcall_err(meths.set_keymap, 'oa', 'lhs', 'rhs', {}))
eq('Invalid mode shortname: "!o"', pcall_err(meths.set_keymap, '!o', 'lhs', 'rhs', {})) eq('Invalid mode shortname: "!o"', pcall_err(meths.set_keymap, '!o', 'lhs', 'rhs', {}))
@@ -508,6 +535,11 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
eq('Invalid mode shortname: "map"', pcall_err(meths.set_keymap, 'map', 'lhs', 'rhs', {})) eq('Invalid mode shortname: "map"', pcall_err(meths.set_keymap, 'map', 'lhs', 'rhs', {}))
eq('Invalid mode shortname: "vmap"', pcall_err(meths.set_keymap, 'vmap', 'lhs', 'rhs', {})) eq('Invalid mode shortname: "vmap"', pcall_err(meths.set_keymap, 'vmap', 'lhs', 'rhs', {}))
eq('Invalid mode shortname: "xnoremap"', pcall_err(meths.set_keymap, 'xnoremap', 'lhs', 'rhs', {})) eq('Invalid mode shortname: "xnoremap"', pcall_err(meths.set_keymap, 'xnoremap', 'lhs', 'rhs', {}))
eq('Invalid mode shortname: " "', pcall_err(meths.del_keymap, ' ', 'lhs'))
eq('Invalid mode shortname: "m"', pcall_err(meths.del_keymap, 'm', 'lhs'))
eq('Invalid mode shortname: "?"', pcall_err(meths.del_keymap, '?', 'lhs'))
eq('Invalid mode shortname: "y"', pcall_err(meths.del_keymap, 'y', 'lhs'))
eq('Invalid mode shortname: "p"', pcall_err(meths.del_keymap, 'p', 'lhs'))
eq('Invalid mode shortname: "a"', pcall_err(meths.del_keymap, 'a', 'lhs')) eq('Invalid mode shortname: "a"', pcall_err(meths.del_keymap, 'a', 'lhs'))
eq('Invalid mode shortname: "oa"', pcall_err(meths.del_keymap, 'oa', 'lhs')) eq('Invalid mode shortname: "oa"', pcall_err(meths.del_keymap, 'oa', 'lhs'))
eq('Invalid mode shortname: "!o"', pcall_err(meths.del_keymap, '!o', 'lhs')) eq('Invalid mode shortname: "!o"', pcall_err(meths.del_keymap, '!o', 'lhs'))
@@ -518,22 +550,6 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
eq('Invalid mode shortname: "xnoremap"', pcall_err(meths.del_keymap, 'xnoremap', 'lhs')) eq('Invalid mode shortname: "xnoremap"', pcall_err(meths.del_keymap, 'xnoremap', 'lhs'))
end) end)
it('error on invalid mode shortname', function()
eq('Invalid mode shortname: " "',
pcall_err(meths.set_keymap, ' ', 'lhs', 'rhs', {}))
eq('Invalid mode shortname: "m"',
pcall_err(meths.set_keymap, 'm', 'lhs', 'rhs', {}))
eq('Invalid mode shortname: "?"',
pcall_err(meths.set_keymap, '?', 'lhs', 'rhs', {}))
eq('Invalid mode shortname: "y"',
pcall_err(meths.set_keymap, 'y', 'lhs', 'rhs', {}))
eq('Invalid mode shortname: "p"',
pcall_err(meths.set_keymap, 'p', 'lhs', 'rhs', {}))
eq('Invalid mode shortname: "?"', pcall_err(meths.del_keymap, '?', 'lhs'))
eq('Invalid mode shortname: "y"', pcall_err(meths.del_keymap, 'y', 'lhs'))
eq('Invalid mode shortname: "p"', pcall_err(meths.del_keymap, 'p', 'lhs'))
end)
it('error on invalid optnames', function() it('error on invalid optnames', function()
eq("Invalid key: 'silentt'", eq("Invalid key: 'silentt'",
pcall_err(meths.set_keymap, 'n', 'lhs', 'rhs', {silentt = true})) pcall_err(meths.set_keymap, 'n', 'lhs', 'rhs', {silentt = true}))

View File

@@ -30,6 +30,7 @@ describe('maparg()', function()
buffer=0, buffer=0,
nowait=0, nowait=0,
mode='n', mode='n',
mode_bits=0x01,
abbr=0, abbr=0,
noremap=1, noremap=1,
lnum=0, lnum=0,
@@ -157,6 +158,7 @@ describe('maparg()', function()
buffer = 0, buffer = 0,
expr = 0, expr = 0,
mode = 'n', mode = 'n',
mode_bits = 0x01,
abbr = 0, abbr = 0,
noremap = 1, noremap = 1,
nowait = 0, nowait = 0,

View File

@@ -21,13 +21,13 @@ func Test_maparg()
\ 'lhsraw': "foo\x80\xfc\x04V", 'lhsrawalt': "foo\x16", \ 'lhsraw': "foo\x80\xfc\x04V", 'lhsrawalt': "foo\x16",
\ 'mode': ' ', 'nowait': 0, 'expr': 0, 'sid': sid, 'scriptversion': 1, \ 'mode': ' ', 'nowait': 0, 'expr': 0, 'sid': sid, 'scriptversion': 1,
\ 'lnum': lnum + 1, \ 'lnum': lnum + 1,
\ 'rhs': 'is<F4>foo', 'buffer': 0, 'abbr': 0}, \ 'rhs': 'is<F4>foo', 'buffer': 0, 'abbr': 0, 'mode_bits': 0x47},
\ maparg('foo<C-V>', '', 0, 1)) \ maparg('foo<C-V>', '', 0, 1))
call assert_equal({'silent': 1, 'noremap': 1, 'script': 1, 'lhs': 'bar', call assert_equal({'silent': 1, 'noremap': 1, 'script': 1, 'lhs': 'bar',
\ 'lhsraw': 'bar', 'mode': 'v', \ 'lhsraw': 'bar', 'mode': 'v',
\ 'nowait': 0, 'expr': 1, 'sid': sid, 'scriptversion': 1, \ 'nowait': 0, 'expr': 1, 'sid': sid, 'scriptversion': 1,
\ 'lnum': lnum + 2, \ 'lnum': lnum + 2,
\ 'rhs': 'isbar', 'buffer': 1, 'abbr': 0}, \ 'rhs': 'isbar', 'buffer': 1, 'abbr': 0, 'mode_bits': 0x42},
\ 'bar'->maparg('', 0, 1)) \ 'bar'->maparg('', 0, 1))
let lnum = expand('<sflnum>') let lnum = expand('<sflnum>')
map <buffer> <nowait> foo bar map <buffer> <nowait> foo bar
@@ -35,7 +35,7 @@ func Test_maparg()
\ 'lhsraw': 'foo', 'mode': ' ', \ 'lhsraw': 'foo', 'mode': ' ',
\ 'nowait': 1, 'expr': 0, 'sid': sid, 'scriptversion': 1, \ 'nowait': 1, 'expr': 0, 'sid': sid, 'scriptversion': 1,
\ 'lnum': lnum + 1, 'rhs': 'bar', \ 'lnum': lnum + 1, 'rhs': 'bar',
\ 'buffer': 1, 'abbr': 0}, \ 'buffer': 1, 'abbr': 0, 'mode_bits': 0x47},
\ maparg('foo', '', 0, 1)) \ maparg('foo', '', 0, 1))
let lnum = expand('<sflnum>') let lnum = expand('<sflnum>')
tmap baz foo tmap baz foo
@@ -43,7 +43,7 @@ func Test_maparg()
\ 'lhsraw': 'baz', 'mode': 't', \ 'lhsraw': 'baz', 'mode': 't',
\ 'nowait': 0, 'expr': 0, 'sid': sid, 'scriptversion': 1, \ 'nowait': 0, 'expr': 0, 'sid': sid, 'scriptversion': 1,
\ 'lnum': lnum + 1, 'rhs': 'foo', \ 'lnum': lnum + 1, 'rhs': 'foo',
\ 'buffer': 0, 'abbr': 0}, \ 'buffer': 0, 'abbr': 0, 'mode_bits': 0x80},
\ maparg('baz', 't', 0, 1)) \ maparg('baz', 't', 0, 1))
let lnum = expand('<sflnum>') let lnum = expand('<sflnum>')
iab A B iab A B
@@ -51,7 +51,7 @@ func Test_maparg()
\ 'lhsraw': 'A', 'mode': 'i', \ 'lhsraw': 'A', 'mode': 'i',
\ 'nowait': 0, 'expr': 0, 'sid': sid, 'scriptversion': 1, \ 'nowait': 0, 'expr': 0, 'sid': sid, 'scriptversion': 1,
\ 'lnum': lnum + 1, 'rhs': 'B', \ 'lnum': lnum + 1, 'rhs': 'B',
\ 'buffer': 0, 'abbr': 1}, \ 'buffer': 0, 'abbr': 1, 'mode_bits': 0x0010},
\ maparg('A', 'i', 1, 1)) \ maparg('A', 'i', 1, 1))
iuna A iuna A