Skip to content

Commit

Permalink
feat: improve mapping saver
Browse files Browse the repository at this point in the history
  • Loading branch information
kuuote committed Mar 12, 2024
1 parent 342f712 commit 1a41a6b
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 41 deletions.
44 changes: 4 additions & 40 deletions autoload/skkeleton.vim
Original file line number Diff line number Diff line change
Expand Up @@ -177,25 +177,6 @@ endfunction "}}}

let g:skkeleton#mapped_keys = extend(get(g:, 'skkeleton#mapped_keys', []), skkeleton#get_default_mapped_keys())

let s:mapbuf = {}

" 現在のマッピングを保存する
" disable時に復元される
function skkeleton#save_map(mode, lhs)
if type(a:lhs) == v:t_string
let list = [a:lhs]
else
let list = a:lhs
endif
let b = bufnr()
let s:mapbuf[b] = get(s:mapbuf, b, {})
let s:mapbuf[b][a:mode] = get(s:mapbuf[b], a:mode, {})
let mapbuf = s:mapbuf[b][a:mode]
for lhs in list
let mapbuf[lhs] = get(mapbuf, lhs, maparg(lhs, a:mode, v:false, v:true))
endfor
endfunction

function! skkeleton#map() abort
if mode() ==# 'n'
let modes = ['i', 'c']
Expand All @@ -204,10 +185,9 @@ function! skkeleton#map() abort
let modes = [mode()]
let mode = mode()
endif
let b = bufnr()
let s:mapbuf[b] = get(s:mapbuf, b, {})
let s:mapbuf[b][mode] = get(s:mapbuf[b], mode, {})
let mapbuf = s:mapbuf[b][mode]

call skkeleton#internal#map#save(mode)

for c in g:skkeleton#mapped_keys
" notation to lower
if len(c) > 1 && c[0] ==# '<' && c !=? '<bar>'
Expand All @@ -223,36 +203,20 @@ function! skkeleton#map() abort
let func = match[1]
endif
endfor
let mapbuf[c] = get(mapbuf, c, maparg(c, mode, v:false, v:true))
execute printf('%snoremap <buffer> <nowait> %s <Cmd>call skkeleton#handle(%s, {"key": %s})<CR>',
\ mode,
\ c, string(func), string(k))
endfor
endfunction

function! skkeleton#unmap() abort
let b = bufnr()
let mapbuf = get(s:mapbuf, b, {})
for [mode, keys] in items(mapbuf)
for [key, map] in items(keys)
if get(map, 'buffer', 0)
call mapset(mode, v:false, map)
else
execute printf('%sunmap <buffer> %s', mode, key)
endif
endfor
endfor
let s:mapbuf[b] = {}
endfunction

function! skkeleton#disable()
if g:skkeleton#enabled
doautocmd <nomodeline> User skkeleton-disable-pre
" cmdline関係ないオプションだけなので辞書登録時はスキップ
if mode() !=# 'c'
call skkeleton#internal#option#restore()
endif
call skkeleton#unmap()
call skkeleton#internal#map#restore()
let g:skkeleton#mode = ''
doautocmd <nomodeline> User skkeleton-mode-changed
doautocmd <nomodeline> User skkeleton-disable-post
Expand Down
27 changes: 27 additions & 0 deletions autoload/skkeleton/internal/map.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
let s:vault = {}

function skkeleton#internal#map#save(mode) abort
let bufnr = bufnr()
let s:vault[bufnr] = get(s:vault, bufnr, {})
let buf = s:vault[bufnr]
if has_key(buf, a:mode)
return
endif
if exists('*nvim_buf_get_keymap')
let buf[a:mode] = nvim_buf_get_keymap(bufnr, a:mode)
elseif exists('*maplist')
let buf[a:mode] = maplist()->filter('v:val.buffer && v:val.mode == a:mode')
endif
endfunction

function skkeleton#internal#map#restore() abort
let bufnr = bufnr()
let buf = get(s:vault, bufnr, {})
for [mode, maps] in items(buf)
execute mode .. 'mapclear <buffer>'
for m in maps
call mapset(m)
endfor
endfor
silent! unlet s:vault[bufnr]
endfunction
21 changes: 21 additions & 0 deletions autoload/skkeleton/internal/map_test.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
" so %
" TODO: rewrite with test framework

function s:assert_equal(expected, actual)
let v:errors = []
if assert_equal(a:expected, a:actual)
throw v:errors[0]
endif
endfunction

source <script>:h/map.vim
nmapclear <buffer>
nnoremap <buffer> a b
call skkeleton#internal#map#save('n')
nnoremap <buffer> b a
call s:assert_equal(2, execute('nnoremap <buffer>')->split('\n')->len())
call skkeleton#internal#map#restore()
call s:assert_equal(1, execute('nnoremap <buffer>')->split('\n')->len())


3 changes: 2 additions & 1 deletion denops/skkeleton/function/dictionary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ export async function registerWord(context: Context): Promise<boolean> {
const denops = context.denops!;
const state = context.state as HenkanState;
await batch(denops, async (denops) => {
await denops.call("skkeleton#save_map", "c", cmapKeys);
await denops.call("skkeleton#internal#map#save", "c");
for (const k of cmapKeys) {
await mapping.map(denops, k, "__skkeleton_return__<CR>", {
buffer: true,
silent: true,
mode: "c",
});
}
Expand Down
32 changes: 32 additions & 0 deletions denops/skkeleton/function/dictionary_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,35 @@ test({
assertEquals(context.preEdit.output(""), "");
},
});

test({
mode: "all",
name: "Unregistered internal mapping",
async fn(denops: Denops) {
currentKanaTable.get();
const state: HenkanState = {
type: "henkan",
mode: "okuriari",
directInput: false,
feed: "",
henkanFeed: "",
okuriFeed: "hoge",
previousFeed: false,
table: getKanaTable("rom"),
word: "",
candidates: [],
candidateIndex: -1,
};
const context = currentContext.get();
context.state = state;
await denops.cmd(
'autocmd CmdlineEnter * ++once call feedkeys("\\<Esc>", "n")',
);
await registerWord(context);
const ctrlg = await denops.call("maparg", "c", "<C-g>", false, true);
const esc = await denops.call("maparg", "c", "<Esc>", false, true);

assertEquals(ctrlg, {});
assertEquals(esc, {});
},
});

0 comments on commit 1a41a6b

Please sign in to comment.