maparg()İşlevi kullanabilirsiniz .
Kullanıcının bir şeyi <C-c>normal modda eşleyip eşlemediğini test etmek için şunu yazarsınız:
if !empty(maparg('<C-c>', 'n'))
Kullanıcı bir şeyi eşlediyse, {rhs}değişkeninde saklamak için şunu yazarsınız:
let rhs_save = maparg('<C-c>', 'n')
Eşleme hakkında daha fazla bilgi istiyorsanız, örneğin:
- sessiz
<silent>mi ( tartışma)?
- geçerli arabellek (
<buffer>bağımsız değişken) için yerel mi?
- olan
{rhs}bir ifade (değerlendirilmesi <expr>bağımsız değişkeni)?
{rhs}( nnoremapvs nmap) 'yi yeniden hatırlıyor mu?
- kullanıcı ile başlayan başka bir eşleme varsa,
<C-c>Vim daha fazla karakterin yazılmasını bekler <nowait>mi ( bağımsız değişken)?
- ...
Sonra, üçüncü ve dördüncü bir argüman verebilirsin: 0ve 1.
0çünkü bir kısaltma değil bir eşleme arıyorsunuz 1ve yalnızca {rhs}değeri değil, maksimum bilgi içeren bir sözlük istediğiniz için :
let map_save = maparg('<C-c>', 'n', 0, 1)
Kullanıcının eşlemesinde özel bir argüman kullanmadığını ve {rhs}geri yüklemek için yeniden eşleme yapmadığını varsayarsak , şunları yazabilirsiniz:
let rhs_save = maparg('<C-c>', 'n')
" do some stuff which changes the mapping
exe 'nnoremap <C-c> ' . rhs_save
Veya olası tüm argümanlardan emin olmak ve geri yüklemek için:
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
Düzenleme: Üzgünüm, kullanıcı {rhs}eşleme bir komut dosyası yerel işlevi çağırırsa beklendiği gibi işe yaramayacağını fark ettim .
Kullanıcının kendi içinde aşağıdaki eşleştirmeye sahip olduğunu varsayalım vimrc:
nnoremap <C-c> :<C-U>call <SID>FuncA()<CR>
function! s:FuncA()
echo 'hello world!'
endfunction
Vurulduğunda <C-c>mesajı görüntüler hello world!.
Eklentinizde, tüm bilgileri içeren bir sözlüğü kaydedersiniz, ardından eşlemesini geçici olarak şu şekilde değiştirirsiniz:
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
Şimdi görüntülenecektir bye all!. Eklentiniz biraz işe yarıyor ve bittiğinde eşlemeyi önceki komutla geri yüklemeye çalışıyor.
Muhtemelen şöyle bir mesajla başarısız olacaktır:
E117: Unknown function: <SNR>61_FuncA
61yalnızca eşleme komutunuzun yürütüleceği komut dosyasının tanımlayıcısıdır. Başka bir sayı olabilir. Eklentiniz kullanıcının sistemine ait 42. dosya ise, olacaktır 42.
Bir komut dosyasının içinde, bir eşleme komutu yürütüldüğünde, Vim gösterimi otomatik olarak <SID>özel anahtar koduna <SNR>, ardından komut dosyası için benzersiz bir sayıya ve bir alt çizgiye dönüştürür. Bunu yapmak zorundadır, çünkü kullanıcı vurduğunda <C-c>, eşleme komut dosyasının dışında yürütülür ve böylece hangi komut dosyasının FuncA()tanımlandığını bilemez .
Sorun, orijinal eşlemenin eklentinizden farklı bir komut dosyasında kaynaklanmış olması, bu yüzden burada otomatik çeviri yanlış. Komut dosyanızın tanımlayıcısını kullanırken, kullanıcının tanımlayıcısını kullanmalıdır vimrc.
Ancak çeviriyi elle yapabilirsiniz. Sözlük , değeri doğru tanımlayıcı olan map_savebir anahtar içeriyor 'sid'.
Dolayısıyla, önceki geri yükleme komutunu daha sağlam hale getirmek için aşağıdakilerle değiştirebilirsiniz map_save.rhs:
substitute(map_save.rhs, '<SID>', '<SNR>' . map_save.sid . '_', 'g')
{rhs}Orijinal eşlemeden biri varsa, <SID>düzgün bir şekilde çevrilmelidir. Aksi takdirde hiçbir şey değiştirilmemelidir.
Kodu biraz kısaltmak isterseniz, özel argümanlarla ilgilenen 4 satırı şu şekilde değiştirebilirsiniz:
join(map(['buffer', 'expr', 'nowait', 'silent'], 'map_save[v:val] ? "<" . v:val . ">": ""'))
map()Fonksiyon listeden her bir öğeyi dönüştürmek gerekir ['buffer', 'expr', 'nowait', 'silent']tekabül haritalama tartışma içine ama onun anahtar içeride sadece map_savesıfırdan farklıdır. Ve join()tüm öğeleri bir dizeye birleştirmelisiniz.
Bu nedenle, eşlemeyi kaydetmek ve geri yüklemek için daha sağlam bir yol olabilir:
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')
Edit2:
Sizinle aynı sorunla karşılaşıyorum, bir çizim eklentisindeki bir eşlemeyi nasıl kaydedebilir ve geri yükleyebilirim. Sanırım ilk cevabın yazdığım sırada görmediği 2 konu buldum, bunun için üzgünüm.
İlk sorun, kullanıcının <C-c>global bir haritalamada ve aynı zamanda bir tampon-yerel haritalamada kullandığını varsayalım . Misal:
nnoremap <C-c> :echo 'global mapping'<CR>
nnoremap <buffer> <C-c> :echo 'local mapping'<CR>
Bu durumda, maparg()yerel eşlemeye öncelik verir:
: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}
Hangi teyit edilir :h maparg():
The mappings local to the current buffer are checked first,
then the global mappings.
Ama belki arabellek-yerel haritalama ile ilgilenmiyorsunuzdur, belki de global olanı istiyorsunuz.
Global haritalama hakkında güvenilir bir şekilde bilgi edinmenin tek yolu, aynı anahtarı kullanarak potansiyel, gölgelenme, arabellek-yerel haritalamanın geçici olarak eşlemesini kaldırmaya çalışmaktır.
4 adımda yapılabilir:
- tuşunu kullanarak (potansiyel) bir arabellek yerel eşlemesini kaydetme
<C-c>
:silent! nunmap <buffer> <C-c>(potansiyel) arabellek-yerel eşlemeyi silmek için yürütme
- genel eşlemeyi kaydet (
maparg('<C-c>', 'n', 0, 1))
- arabellek yerel eşlemesini geri yükle
İkinci konu şudur. Kullanıcının hiçbir şeyi eşlemediğini varsayalım <C-c>, o zaman çıktısı maparg()boş bir sözlük olacaktır. Ve bu durumda, geri yükleme işlemi bir eşlemenin ( :nnoremap) kurulumundan değil, bir eşlemenin ( ) imha edilmesinden ibarettir :nunmap.
Bu 2 yeni sorunu çözmeye çalışmak için, eşlemeleri kaydetmek üzere bu işlevi deneyebilirsiniz:
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
... ve bunları geri yüklemek için:
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()Fonksiyon eşleştirmeleri kaydetmek için kullanılabilir.
3 argüman bekliyor:
- bir anahtar listesi; misal:
['<C-a>', '<C-b>', '<C-c>']
- bir mod; örnek:
nnormal mod veya xgörsel mod için
- boole bayrağı; eğer öyleyse
1, bu, küresel eşlemelerle ilgilendiğiniz anlamına gelir ve 0yereldir.
Bununla beraber, tuşlarını kullanarak küresel eşleşmelerini kurtarabilecek C-a, C-bve C-csözlükten içinde normal modda,:
let your_saved_mappings = Save_mappings(['<C-a>', '<C-b>', '<C-c>'], 'n', 1)
Daha sonra, eşlemeleri geri yüklemek istediğinizde Restore_mappings(), tüm bilgileri içeren sözlüğü bağımsız değişken olarak ileterek arayabilirsiniz :
call Restore_mappings(your_saved_mappings)
Arabellek-yerel eşlemeleri kaydederken / geri yüklerken 3. bir sorun olabilir. Çünkü, eşlemeleri kaydettiğimiz an ile bunları geri yüklemeye çalıştığımız an arasında, geçerli arabellek değişmiş olabilir.
Bu durumda, Save_mappings()işlev geçerli arabellek ( bufnr('%')) sayısı kaydedilerek geliştirilebilir .
Ve sonra, Restore_mappings()sağ tampondaki arabellek-yerel eşlemelerini geri yüklemek için bu bilgileri kullanır. Muhtemelen :bufdokomutu kullanabilir, ikincisine bir sayı ekleyebilir (daha önce kaydedilen arabellek numarasıyla eşleşebilir) ve eşleme komutuyla ekleyebiliriz.
Belki şöyle bir şey:
:{original buffer number}bufdo {mapping command}
İlk önce arabellek hala var olup olmadığını kontrol etmeliyiz bufexists(), çünkü bu arada, silinebilirdi.