vim-patch:8.2.4820: not simple programmatic way to find a specific mapping

Problem:    Not simple programmatic way to find a specific mapping.
Solution:   Add getmappings(). (Ernie Rael, closes vim/vim#10273)

659c240cf7

Co-authored-by: Ernie Rael <errael@raelity.com>
This commit is contained in:
zeertzjq 2023-11-09 18:16:49 +08:00
parent a4b80c71ea
commit 2dfcd5a22b
6 changed files with 157 additions and 3 deletions

View File

@ -2612,6 +2612,16 @@ getloclist({nr} [, {what}]) *getloclist()*
echo getloclist(5, {'filewinid': 0}) echo getloclist(5, {'filewinid': 0})
< <
getmappings() *getmappings()*
Returns a |List| of all mappings. Each List item is a |Dict|,
the same as what is returned by |maparg()|, see
|mapping-dict|.
Example to show all mappings with "MultiMatch" in rhs: >
echo getmappings()->filter({_, m ->
\ match(get(m, 'rhs', ''), 'MultiMatch') >= 0
\ })
getmarklist([{buf}]) *getmarklist()* getmarklist([{buf}]) *getmarklist()*
Without the {buf} argument returns a |List| with information Without the {buf} argument returns a |List| with information
about all the global marks. |mark| about all the global marks. |mark|
@ -4161,7 +4171,7 @@ maparg({name} [, {mode} [, {abbr} [, {dict}]]]) *maparg()*
When {dict} is there and it is |TRUE| return a dictionary When {dict} is there and it is |TRUE| return a dictionary
containing all the information of the mapping with the containing all the information of the mapping with the
following items: following items: *mapping-dict*
"lhs" The {lhs} of the mapping as it would be typed "lhs" The {lhs} of the mapping as it would be typed
"lhsraw" The {lhs} of the mapping as raw bytes "lhsraw" The {lhs} of the mapping as raw bytes
"lhsrawalt" The {lhs} of the mapping as raw bytes, alternate "lhsrawalt" The {lhs} of the mapping as raw bytes, alternate

View File

@ -1012,6 +1012,7 @@ Mappings and Menus: *mapping-functions*
digraph_getlist() get all |digraph|s digraph_getlist() get all |digraph|s
digraph_set() register |digraph| digraph_set() register |digraph|
digraph_setlist() register multiple |digraph|s digraph_setlist() register multiple |digraph|s
getmappings() get list of all mappings
hasmapto() check if a mapping exists hasmapto() check if a mapping exists
mapcheck() check if a matching mapping exists mapcheck() check if a matching mapping exists
maparg() get rhs of a mapping maparg() get rhs of a mapping

View File

@ -3175,6 +3175,18 @@ function vim.fn.getline(lnum, end_) end
--- @return any --- @return any
function vim.fn.getloclist(nr, what) end function vim.fn.getloclist(nr, what) end
--- Returns a |List| of all mappings. Each List item is a |Dict|,
--- the same as what is returned by |maparg()|, see
--- |mapping-dict|.
---
--- Example to show all mappings with "MultiMatch" in rhs: >
--- echo getmappings()->filter({_, m ->
--- \ match(get(m, 'rhs', ''), 'MultiMatch') >= 0
--- \ })
---
--- @return any
function vim.fn.getmappings() end
--- Without the {buf} argument returns a |List| with information --- Without the {buf} argument returns a |List| with information
--- about all the global marks. |mark| --- about all the global marks. |mark|
--- ---
@ -5022,7 +5034,7 @@ function vim.fn.map(expr1, expr2) end
--- ---
--- When {dict} is there and it is |TRUE| return a dictionary --- When {dict} is there and it is |TRUE| return a dictionary
--- containing all the information of the mapping with the --- containing all the information of the mapping with the
--- following items: --- following items: *mapping-dict*
--- "lhs" The {lhs} of the mapping as it would be typed --- "lhs" The {lhs} of the mapping as it would be typed
--- "lhsraw" The {lhs} of the mapping as raw bytes --- "lhsraw" The {lhs} of the mapping as raw bytes
--- "lhsrawalt" The {lhs} of the mapping as raw bytes, alternate --- "lhsrawalt" The {lhs} of the mapping as raw bytes, alternate

View File

@ -3957,6 +3957,22 @@ M.funcs = {
params = { { 'nr', 'integer' }, { 'what', 'any' } }, params = { { 'nr', 'integer' }, { 'what', 'any' } },
signature = 'getloclist({nr} [, {what}])', signature = 'getloclist({nr} [, {what}])',
}, },
getmappings = {
args = 0,
desc = [[
Returns a |List| of all mappings. Each List item is a |Dict|,
the same as what is returned by |maparg()|, see
|mapping-dict|.
Example to show all mappings with "MultiMatch" in rhs: >
echo getmappings()->filter({_, m ->
\ match(get(m, 'rhs', ''), 'MultiMatch') >= 0
\ })
]],
name = 'getmappings',
params = {},
signature = 'getmappings()'
},
getmarklist = { getmarklist = {
args = { 0, 1 }, args = { 0, 1 },
base = 1, base = 1,
@ -6170,7 +6186,7 @@ M.funcs = {
When {dict} is there and it is |TRUE| return a dictionary When {dict} is there and it is |TRUE| return a dictionary
containing all the information of the mapping with the containing all the information of the mapping with the
following items: following items: *mapping-dict*
"lhs" The {lhs} of the mapping as it would be typed "lhs" The {lhs} of the mapping as it would be typed
"lhsraw" The {lhs} of the mapping as raw bytes "lhsraw" The {lhs} of the mapping as raw bytes
"lhsrawalt" The {lhs} of the mapping as raw bytes, alternate "lhsrawalt" The {lhs} of the mapping as raw bytes, alternate

View File

@ -2281,6 +2281,49 @@ void f_mapset(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
sid, lnum, false); sid, lnum, false);
} }
/// "maplist()" function
void f_getmappings(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const int flags = REPTERM_FROM_PART | REPTERM_DO_LT;
tv_list_alloc_ret(rettv, kListLenUnknown);
// Do it twice: once for global maps and once for local maps.
for (int buffer_local = 0; buffer_local <= 1; buffer_local++) {
for (int hash = 0; hash < 256; hash++) {
mapblock_T *mp;
if (buffer_local) {
mp = curbuf->b_maphash[hash];
} else {
mp = maphash[hash];
}
for (; mp; mp = mp->m_next) {
if (mp->m_simplified) {
continue;
}
char *keys_buf = NULL;
bool did_simplify = false;
char *lhs = str2special_save(mp->m_keys, true, false);
(void)replace_termcodes(lhs, strlen(lhs), &keys_buf, 0, flags, &did_simplify,
CPO_TO_CPO_FLAGS);
xfree(lhs);
Dictionary dict = mapblock_fill_dict(mp,
did_simplify ? keys_buf : NULL,
buffer_local, true);
typval_T d = TV_INITIAL_VALUE;
(void)object_to_vim(DICTIONARY_OBJ(dict), &d, NULL);
assert(d.v_type == VAR_DICT);
tv_list_append_dict(rettv->vval.v_list, d.vval.v_dict);
api_free_dictionary(dict);
xfree(keys_buf);
}
}
}
}
/// "maparg()" function /// "maparg()" function
void f_maparg(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) void f_maparg(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{ {

View File

@ -372,4 +372,76 @@ func Test_map_restore_negative_sid()
call delete('Xresult') call delete('Xresult')
endfunc endfunc
func Test_getmappings()
new
func s:ClearMaps()
mapclear | nmapclear | vmapclear | xmapclear | smapclear | omapclear
mapclear! | imapclear | lmapclear | cmapclear | tmapclear
mapclear <buffer> | nmapclear <buffer> | vmapclear <buffer>
xmapclear <buffer> | smapclear <buffer> | omapclear <buffer>
mapclear! <buffer> | imapclear <buffer> | lmapclear <buffer>
cmapclear <buffer> | tmapclear <buffer>
endfunc
func s:AddMaps(new, accum)
if len(a:new) > 0 && a:new[0] != "No mapping found"
eval a:accum->extend(a:new)
endif
endfunc
call s:ClearMaps()
call assert_equal(0, len(getmappings()))
" Set up some mappings.
map dup bar
map <buffer> dup bufbar
map foo<C-V> is<F4>foo
vnoremap <script> <buffer> <expr> <silent> bar isbar
tmap baz foo
omap h w
lmap i w
nmap j w
xmap k w
smap l w
map abc <Nop>
nmap <M-j> x
nmap <M-Space> y
" Get a list of the mappings with the ':map' commands.
" Check getmappings() return a list of the same size.
call assert_equal(13, len(getmappings()))
" collect all the current maps using :map commands
let maps_command = []
call s:AddMaps(split(execute('map'), '\n'), maps_command)
call s:AddMaps(split(execute('map!'), '\n'), maps_command)
call s:AddMaps(split(execute('tmap'), '\n'), maps_command)
call s:AddMaps(split(execute('lmap'), '\n'), maps_command)
" Use getmappings to get all the maps
let maps_getmappings = getmappings()
call assert_equal(len(maps_command), len(maps_getmappings))
" make sure all the mode-lhs are unique, no duplicates
let map_set = {}
for d in maps_getmappings
let map_set[d.mode .. "-" .. d.lhs .. "-" .. d.buffer] = 0
endfor
call assert_equal(len(maps_getmappings), len(map_set))
" For everything returned by getmappings, should be the same as from maparg.
" Except for "map dup", bacause maparg returns the <buffer> version
for d in maps_getmappings
if d.lhs == 'dup' && d.buffer == 0
continue
endif
let d_maparg = maparg(d.lhs, d.mode, v:false, v:true)
call assert_equal(d_maparg, d)
endfor
call s:ClearMaps()
call assert_equal(0, len(getmappings()))
endfunc
" vim: shiftwidth=2 sts=2 expandtab " vim: shiftwidth=2 sts=2 expandtab