このmaparg()
機能を使用できます。
ユーザー<C-c>
が通常モードで何かをマップしたかどうかをテストするには、次のように記述します。
if !empty(maparg('<C-c>', 'n'))
ユーザーが何かをマップした場合、{rhs}
変数に保存するには、次のように記述します。
let rhs_save = maparg('<C-c>', 'n')
マッピングに関する詳細情報が必要な場合:
- 沈黙している(
<silent>
議論)?
- 現在のバッファ(
<buffer>
引数)に対してローカルですか?
- ある
{rhs}
表現(の評価<expr>
引数)?
{rhs}
(nnoremap
vs nmap
)を再マッピングしますか?
- ユーザーがで始まる別のマッピングを持っている場合、
<C-c>
Vimはさらに文字が入力されるのを待ち<nowait>
ますか(引数)?
- ...
その後、あなたは、第3及び第4の引数を与えることができる:0
と1
。
0
略語ではなくマッピングを探している1
ため、また、{rhs}
値だけでなく最大の情報を持つ辞書が必要なためです。
let map_save = maparg('<C-c>', 'n', 0, 1)
ユーザーがマッピングで特別な引数を使用せず{rhs}
、復元するためにを再マッピングしないと仮定すると、単純に次のように書くことができます。
let rhs_save = maparg('<C-c>', 'n')
" do some stuff which changes the mapping
exe 'nnoremap <C-c> ' . rhs_save
または、可能性のあるすべての引数を確認して復元するには:
let map_save = maparg('<C-c>', 'n', 0, 1)
" do some stuff which changes the mapping
exe (map_save.noremap ? 'nnoremap' : 'nmap') .
\ (map_save.buffer ? ' <buffer> ' : '') .
\ (map_save.expr ? ' <expr> ' : '') .
\ (map_save.nowait ? ' <nowait> ' : '') .
\ (map_save.silent ? ' <silent> ' : '') .
\ ' <C-c> ' .
\ map_save.rhs
編集:申し訳ありませんが、ユーザーが{rhs}
マッピングのスクリプトローカル関数を呼び出すと、期待どおりに動作しないことに気付きました。
ユーザーの内部に次のマッピングがあるとしますvimrc
。
nnoremap <C-c> :<C-U>call <SID>FuncA()<CR>
function! s:FuncA()
echo 'hello world!'
endfunction
彼がヒット<C-c>
すると、メッセージが表示されますhello world!
。
プラグインでは、すべての情報を含む辞書を保存し、一時的に次のようにマッピングを変更します。
let map_save = maparg('<C-c>', 'n', 0, 1)
nnoremap <C-c> :<C-U>call <SID>FuncB()<CR>
function! s:FuncB()
echo 'bye all!'
endfunction
これで、が表示されますbye all!
。プラグインは何らかの作業を行い、終了すると、前のコマンドでマッピングを復元しようとします。
おそらく次のようなメッセージで失敗します:
E117: Unknown function: <SNR>61_FuncA
61
マッピングコマンドが実行されるスクリプトの単なる識別子です。他の番号でも構いません。プラグインがユーザーのシステムをソースとする42番目のファイルである場合、それはになります42
。
スクリプト内で、マッピングコマンドが実行されると、Vimは表記<SID>
を特別なキーコード<SNR>
に自動的に変換し、その後にスクリプトに固有の番号とアンダースコアが続きます。ユーザーがを押す<C-c>
と、マッピングがスクリプトの外部で実行されるため、どのスクリプトFuncA()
で定義されているかわからないため、これを行う必要があります。
問題は、元のマッピングがプラグインとは異なるスクリプトをソースとしているため、自動翻訳が間違っていることです。スクリプトの識別子を使用しますが、ユーザーの識別子を使用する必要がありますvimrc
。
しかし、手動で翻訳を行うことができます。辞書にmap_save
は、'sid'
値が正しい識別子であるというキーが含まれています。
したがって、以前の復元コマンドをより堅牢にするためにmap_save.rhs
、次のものに置き換えることができます。
substitute(map_save.rhs, '<SID>', '<SNR>' . map_save.sid . '_', 'g')
{rhs}
元のマッピングにが含まれている場合、<SID>
適切に翻訳する必要があります。それ以外の場合は、何も変更しないでください。
また、コードを少し短くしたい場合は、特別な引数を処理する4行を次のように置き換えることができます。
join(map(['buffer', 'expr', 'nowait', 'silent'], 'map_save[v:val] ? "<" . v:val . ">": ""'))
map()
関数リストから各項目を変換する必要があり['buffer', 'expr', 'nowait', 'silent']
、対応するマッピング引数にそのキー内部にいる場合にのみmap_save
、非ゼロです。そしてjoin()
、すべてのアイテムを文字列に結合する必要があります。
したがって、マッピングを保存および復元するより堅牢な方法は次のとおりです。
let map_save = maparg('<C-c>', 'n', 0, 1)
" do some stuff which changes the mapping
exe (map_save.noremap ? 'nnoremap' : 'nmap') .
\ join(map(['buffer', 'expr', 'nowait', 'silent'], 'map_save[v:val] ? "<" . v:val . ">": ""')) .
\ map_save.lhs . ' ' .
\ substitute(map_save.rhs, '<SID>', '<SNR>' . map_save.sid . '_', 'g')
編集2:
私はあなたと同じ問題に直面しています。描画プラグインでマッピングを保存および復元する方法です。そして、私はそれを書いた時点で最初の答えが見えなかった2つの問題を見つけたと思う、それについて申し訳ありません。
最初の問題は、ユーザーが<C-c>
グローバルマッピングだけでなく、バッファローカルマッピングでも使用すると仮定します。例:
nnoremap <C-c> :echo 'global mapping'<CR>
nnoremap <buffer> <C-c> :echo 'local mapping'<CR>
この場合、maparg()
ローカルマッピングを優先します。
:echo maparg('<C-c>', 'n', 0, 1)
---> {'silent': 0, 'noremap': 1, 'lhs': '<C-C>', 'mode': 'n', 'nowait': 0, 'expr': 0, 'sid': 7, 'rhs': ':echo ''local mapping''<CR>', 'buffer': 1}
で確認され:h maparg()
ます:
The mappings local to the current buffer are checked first,
then the global mappings.
ただし、バッファローカルマッピングに興味がない場合や、グローバルマッピングが必要な場合があります。
グローバルマッピングに関する情報を確実に取得するために私が見つけた唯一の方法は、同じキーを使用して、潜在的なシャドウバッファローカルマッピングを一時的にマップ解除しようとすることです。
次の4つの手順で実行できます。
- キーを使用して(潜在的な)バッファローカルマッピングを保存する
<C-c>
:silent! nunmap <buffer> <C-c>
(潜在的な)バッファローカルマッピングを削除するために実行します
- グローバルマッピングを保存(
maparg('<C-c>', 'n', 0, 1)
)
- バッファローカルマッピングを復元する
2番目の問題は次のとおりです。ユーザーがに何もマップしなかったとすると、<C-c>
の出力はmaparg()
空の辞書になります。この場合、復元プロセスはマッピングのインストール(:nnoremap
)ではなく、マッピングの破壊()で構成されます:nunmap
。
これら2つの新しい問題を解決するには、この関数を使用してマッピングを保存します。
fu! Save_mappings(keys, mode, global) abort
let mappings = {}
if a:global
for l:key in a:keys
let buf_local_map = maparg(l:key, a:mode, 0, 1)
sil! exe a:mode.'unmap <buffer> '.l:key
let map_info = maparg(l:key, a:mode, 0, 1)
let mappings[l:key] = !empty(map_info)
\ ? map_info
\ : {
\ 'unmapped' : 1,
\ 'buffer' : 0,
\ 'lhs' : l:key,
\ 'mode' : a:mode,
\ }
call Restore_mappings({l:key : buf_local_map})
endfor
else
for l:key in a:keys
let map_info = maparg(l:key, a:mode, 0, 1)
let mappings[l:key] = !empty(map_info)
\ ? map_info
\ : {
\ 'unmapped' : 1,
\ 'buffer' : 1,
\ 'lhs' : l:key,
\ 'mode' : a:mode,
\ }
endfor
endif
return mappings
endfu
...そしてこれを復元するために:
fu! Restore_mappings(mappings) abort
for mapping in values(a:mappings)
if !has_key(mapping, 'unmapped') && !empty(mapping)
exe mapping.mode
\ . (mapping.noremap ? 'noremap ' : 'map ')
\ . (mapping.buffer ? ' <buffer> ' : '')
\ . (mapping.expr ? ' <expr> ' : '')
\ . (mapping.nowait ? ' <nowait> ' : '')
\ . (mapping.silent ? ' <silent> ' : '')
\ . mapping.lhs
\ . ' '
\ . substitute(mapping.rhs, '<SID>', '<SNR>'.mapping.sid.'_', 'g')
elseif has_key(mapping, 'unmapped')
sil! exe mapping.mode.'unmap '
\ .(mapping.buffer ? ' <buffer> ' : '')
\ . mapping.lhs
endif
endfor
endfu
このSave_mappings()
関数を使用して、マッピングを保存できます。
3つの引数が必要です。
- キーのリスト。例:
['<C-a>', '<C-b>', '<C-c>']
- モード; 例:
n
通常モードまたはx
視覚モード
- ブール値フラグ。の場合
1
、グローバルマッピングに関心があることを意味し0
、ローカルのマッピングに関心がある場合、
これを使うと、キーを使用してグローバルマッピングを救うことができるC-a
、C-b
とC-c
辞書内部で、通常モードでは、:
let your_saved_mappings = Save_mappings(['<C-a>', '<C-b>', '<C-c>'], 'n', 1)
その後、後でマッピングを復元したいときにRestore_mappings()
、を呼び出して、すべての情報を含む辞書を引数として渡すことができます。
call Restore_mappings(your_saved_mappings)
バッファローカルマッピングを保存/復元するときに、3番目の問題が発生する可能性があります。なぜなら、マッピングを保存した瞬間と、それらを復元しようとする瞬間の間に、現在のバッファが変更された可能性があるからです。
この場合、Save_mappings()
現在のバッファの番号を保存することで機能を改善できる可能性があります(bufnr('%')
)。
そして、Restore_mappings()
この情報を使用して、適切なバッファのバッファローカルマッピングを復元します。おそらく:bufdo
コマンドを使用し、前に保存されたバッファー番号に一致するカウントを前に付け、マッピングコマンドでサフィックスを付けることができます。
たぶん次のようなもの:
:{original buffer number}bufdo {mapping command}
bufexists()
その間に削除された可能性があるため、関数を使用して、バッファがまだ存在するかどうかを最初に確認する必要があります。