diff --git a/autoload/vm/maps.vim b/autoload/vm/maps.vim index 2e2fce4..a3eb40f 100644 --- a/autoload/vm/maps.vim +++ b/autoload/vm/maps.vim @@ -118,6 +118,16 @@ fun! s:Maps.end(keep_permanent) abort silent! cunmap silent! cunmap + " restore saved buffer mappings + if exists('b:VM_saved_buffer_maps') + for key in keys(b:VM_saved_buffer_maps) + let K = b:VM_saved_buffer_maps[key] + let mode = key[0] + let lhs = key[1:] + call s:restore_mapping(mode, lhs, K) + endfor + endif + " restore permanent mappings if a:keep_permanent for m in g:Vm.maps.permanent | exe m | endfor @@ -180,6 +190,7 @@ fun! s:build_buffer_maps() abort " Run once per buffer. Generate buffer mappings and integrate custom ones. let b:VM_maps = [] let b:VM_unmaps = [] + let b:VM_saved_buffer_maps = {} let check_maps = get(b:, 'VM_check_mappings', g:VM_check_mappings) let force_maps = get(b:, 'VM_force_maps', get(g:, 'VM_force_maps', [])) @@ -253,18 +264,19 @@ fun! s:assign(plug, key, buffer, ...) abort "check if the mapping can be applied: this only runs for buffer mappings "a:1 is a bool that is true if mappings must be checked "a:2 can contain a list of mappings that will be applied anyway (forced) - "otherwise, if a buffer mapping already exists, the remapping fails, and - "a debug line is added + "otherwise, if a buffer mapping already exists, save it for later restoration + "and override it (previously it would fail) if a:0 && a:1 && index(a:2, k) < 0 let K = maparg(k, m, 0, 1) if !empty(K) && K.buffer let b = 'b'.bufnr('%').': ' " Handle Neovim mappings with Lua functions as rhs let rhs = has_key(K, 'rhs') ? K.rhs : '' + " Save the existing buffer mapping for restoration + let b:VM_saved_buffer_maps[m.k] = K if m != 'i' - let s = b.'Could not map: '.k.' ('.a:plug.') -> ' . rhs + let s = b.'Overriding buffer map: '.k.' ('.a:plug.') -> ' . rhs call add(b:VM_Debug.lines, s) - return '' else let s = b.'Overwritten imap: '.k.' ('.a:plug.') -> ' . rhs call add(b:VM_Debug.lines, s) @@ -288,6 +300,38 @@ fun! s:unmap(key, buffer) abort endfun +fun! s:restore_mapping(mode, lhs, mapinfo) abort + " Restore a saved buffer mapping from mapinfo dict. + " The mapinfo dict comes from maparg() with dict=1 parameter. + let cmd = a:mode + let cmd .= a:mapinfo.noremap ? 'noremap ' : 'map ' + let cmd .= a:mapinfo.buffer ? ' ' : '' + let cmd .= a:mapinfo.silent ? ' ' : '' + let cmd .= a:mapinfo.nowait ? ' ' : '' + let cmd .= a:mapinfo.expr ? ' ' : '' + let cmd .= a:lhs . ' ' + + " Handle the rhs - check if it's a Lua callback (Neovim) + if has_key(a:mapinfo, 'callback') + " For Neovim with Lua callbacks, we need to use the callback + " This is a bit tricky, but we can use the sid and lnum if available + if has_key(a:mapinfo, 'rhs') && !empty(a:mapinfo.rhs) + let cmd .= a:mapinfo.rhs + else + " If we can't get the rhs, skip restoration and log a warning + echohl WarningMsg + echom 'VM: Could not restore Lua callback mapping for ' . a:lhs + echohl None + return + endif + else + let cmd .= a:mapinfo.rhs + endif + + execute cmd +endfun + + fun! s:check_warnings() abort " Notify once per buffer if errors have happened. if get(g:, 'VM_show_warnings', 1) && !empty(b:VM_Debug.lines)