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}
( nnoremap
vs 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: 0
ve 1
.
0
çünkü bir kısaltma değil bir eşleme arıyorsunuz 1
ve 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
61
yalnı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_save
bir 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_save
sı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:
n
normal mod veya x
görsel mod için
- boole bayrağı; eğer öyleyse
1
, bu, küresel eşlemelerle ilgilendiğiniz anlamına gelir ve 0
yereldir.
Bununla beraber, tuşlarını kullanarak küresel eşleşmelerini kurtarabilecek C-a
, C-b
ve C-c
sö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 :bufdo
komutu 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.