Sie könnten die maparg()
Funktion verwenden.
Um zu testen, ob der Benutzer <C-c>
im normalen Modus etwas zugeordnet hat, schreiben Sie:
if !empty(maparg('<C-c>', 'n'))
Wenn der Benutzer etwas zugeordnet hat, um das {rhs}
in einer Variablen zu speichern , würden Sie schreiben:
let rhs_save = maparg('<C-c>', 'n')
Wenn Sie weitere Informationen zum Mapping wünschen, z.
- ist es still (
<silent>
argument)?
- Ist es lokal für den aktuellen Puffer (
<buffer>
Argument)?
- ist die
{rhs}
Bewertung eines Ausdrucks ( <expr>
Argument)?
- wird das
{rhs}
( nnoremap
vs nmap
) neu zugeordnet?
- Wenn der Benutzer eine andere Zuordnung hat, die mit "" beginnt
<C-c>
, wartet Vim darauf, dass weitere Zeichen eingegeben werden ( <nowait>
Argument)?
- ...
Dann könnten Sie ein drittes und ein viertes Argument anführen: 0
und 1
.
0
weil Sie nach einer Zuordnung suchen und nicht nach einer Abkürzung, und 1
weil Sie ein Wörterbuch mit einem Maximum an Informationen und nicht nur dem {rhs}
Wert wollen:
let map_save = maparg('<C-c>', 'n', 0, 1)
Angenommen, der Benutzer hat in seinem Mapping kein spezielles Argument verwendet und das Mapping wird nicht neu zugeordnet. Um {rhs}
es wiederherzustellen, können Sie einfach schreiben:
let rhs_save = maparg('<C-c>', 'n')
" do some stuff which changes the mapping
exe 'nnoremap <C-c> ' . rhs_save
Oder um sicher zu gehen und alle möglichen Argumente wiederherzustellen:
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
Bearbeiten: Sorry, ich habe gerade festgestellt, dass es nicht wie erwartet funktioniert, wenn der Benutzer eine skriptlokale Funktion im {rhs}
Mapping aufruft .
Angenommen, der Benutzer hat die folgende Zuordnung in seinem vimrc
:
nnoremap <C-c> :<C-U>call <SID>FuncA()<CR>
function! s:FuncA()
echo 'hello world!'
endfunction
Wenn er trifft <C-c>
, wird die Nachricht angezeigt hello world!
.
Und in Ihrem Plugin speichern Sie ein Wörterbuch mit allen Informationen und ändern dann vorübergehend seine Zuordnung wie folgt:
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
Jetzt wird es angezeigt bye all!
. Ihr Plugin leistet einige Arbeit, und wenn es vorbei ist, versucht es, die Zuordnung mit dem vorherigen Befehl wiederherzustellen.
Es wird wahrscheinlich mit einer Nachricht fehlschlagen, die so aussieht:
E117: Unknown function: <SNR>61_FuncA
61
ist nur die Kennung des Skripts, in dem Ihr Zuordnungsbefehl ausgeführt werden würde. Es könnte jede andere Nummer sein. Wenn es sich bei Ihrem Plugin um die 42. Datei auf dem System des Benutzers handelt, ist dies der Fall 42
.
Wenn in einem Skript ein Zuordnungsbefehl ausgeführt wird, übersetzt Vim die Notation automatisch <SID>
in den speziellen Schlüsselcode <SNR>
, gefolgt von einer für das Skript eindeutigen Zahl und einem Unterstrich. Dies muss geschehen, da <C-c>
das Mapping bei einem Treffer des Benutzers außerhalb des Skripts ausgeführt wird und daher nicht weiß, in welchem Skript FuncA()
es definiert ist.
Das Problem ist, dass das ursprüngliche Mapping in einem anderen Skript als Ihrem Plugin erstellt wurde, sodass hier die automatische Übersetzung falsch ist. Dabei wird die Kennung Ihres Skripts verwendet, während die Kennung des Benutzers verwendet werden sollte vimrc
.
Sie können die Übersetzung aber auch manuell vornehmen. Das Wörterbuch map_save
enthält einen Schlüssel mit dem Namen, 'sid'
dessen Wert der richtige Bezeichner ist.
Um den vorherigen Wiederherstellungsbefehl robuster zu machen, können Sie ihn ersetzen map_save.rhs
durch:
substitute(map_save.rhs, '<SID>', '<SNR>' . map_save.sid . '_', 'g')
Wenn die {rhs}
des Originalmappings enthalten ist <SID>
, sollte es richtig übersetzt werden. Ansonsten sollte nichts geändert werden.
Und wenn Sie den Code ein wenig verkürzen möchten, können Sie die 4 Zeilen, die sich um die speziellen Argumente kümmern, ersetzen durch:
join(map(['buffer', 'expr', 'nowait', 'silent'], 'map_save[v:val] ? "<" . v:val . ">": ""'))
Die map()
Funktion sollte jedes Element aus der Liste ['buffer', 'expr', 'nowait', 'silent']
in das entsprechende Zuordnungsargument konvertieren, jedoch nur, wenn sein Schlüssel map_save
nicht Null ist. Und join()
sollte alle Elemente zu einer Zeichenfolge verbinden.
Ein robusterer Weg zum Speichern und Wiederherstellen des Mappings könnte also sein:
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:
Ich stehe vor dem gleichen Problem wie Sie: Speichern und Wiederherstellen eines Mappings in einem Zeichen-Plugin. Und ich glaube, ich habe zwei Probleme gefunden, die die ursprüngliche Antwort zum Zeitpunkt meines Schreibens nicht gesehen hat. Tut mir leid.
Angenommen, der Benutzer verwendet das erste Problem <C-c>
in einer globalen Zuordnung, aber auch in einer pufferlokalen Zuordnung. Beispiel:
nnoremap <C-c> :echo 'global mapping'<CR>
nnoremap <buffer> <C-c> :echo 'local mapping'<CR>
In diesem Fall maparg()
wird der lokalen Zuordnung Vorrang eingeräumt:
: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}
Welches ist bestätigt in :h maparg()
:
The mappings local to the current buffer are checked first,
then the global mappings.
Aber vielleicht interessiert Sie das pufferlokale Mapping nicht, vielleicht möchten Sie das globale.
Die einzige Möglichkeit, die Informationen zur globalen Zuordnung zuverlässig abzurufen, besteht darin, die Zuordnung einer potenziellen, schattierenden, pufferlokalen Zuordnung mit demselben Schlüssel vorübergehend aufzuheben.
Dies könnte in 4 Schritten erfolgen:
- Speichern Sie ein (potentielles) pufferlokales Mapping mit der Taste
<C-c>
- ausführen
:silent! nunmap <buffer> <C-c>
, um ein (potentielles) pufferlokales Mapping zu löschen
- speichere das globale Mapping (
maparg('<C-c>', 'n', 0, 1)
)
- Stellen Sie die pufferlokale Zuordnung wieder her
Das zweite Problem ist das folgende. Angenommen, der Benutzer hat nichts zugeordnet <C-c>
, dann ist die Ausgabe von maparg()
ein leeres Wörterbuch. In diesem Fall besteht der Wiederherstellungsprozess nicht in der Installation eines Mappings ( :nnoremap
), sondern in der Zerstörung eines Mappings ( :nunmap
).
Um diese zwei neuen Probleme zu lösen, können Sie diese Funktion verwenden, um Zuordnungen zu speichern:
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
... und dieses, um sie wiederherzustellen:
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
Die Save_mappings()
Funktion kann zum Speichern von Zuordnungen verwendet werden.
Es werden 3 Argumente erwartet:
- eine Liste von Schlüsseln; Beispiel:
['<C-a>', '<C-b>', '<C-c>']
- Ein Modus; Beispiel:
n
für normalen Modus oder x
für visuellen Modus
- eine boolesche Flagge; Wenn dies der
1
Fall ist , bedeutet dies, dass Sie an globalen Zuordnungen interessiert sind, und wenn dies der Fall ist 0
, an lokalen
Mit ihm können Sie die globalen Zuordnungen speichern mit den Tasten C-a
, C-b
und C-c
, im normalen Modus, in einem Wörterbuch:
let your_saved_mappings = Save_mappings(['<C-a>', '<C-b>', '<C-c>'], 'n', 1)
Wenn Sie die Zuordnungen später wiederherstellen möchten, können Sie Folgendes aufrufen Restore_mappings()
und das Wörterbuch mit allen Informationen als Argument übergeben:
call Restore_mappings(your_saved_mappings)
Beim Speichern / Wiederherstellen von pufferlokalen Zuordnungen kann ein drittes Problem auftreten. Denn zwischen dem Zeitpunkt, zu dem wir die Zuordnungen gespeichert haben, und dem Zeitpunkt, zu dem wir versuchen, sie wiederherzustellen, hat sich möglicherweise der aktuelle Puffer geändert.
In diesem Fall Save_mappings()
könnte die Funktion möglicherweise durch Speichern der Nummer des aktuellen Puffers ( bufnr('%')
) verbessert werden .
Und dann Restore_mappings()
würde diese Informationen verwenden , um die Puffer-local - Zuordnungen im rechten Puffer wiederherzustellen. Wir könnten den :bufdo
Befehl wahrscheinlich verwenden , dem letzteren eine Zählung voranstellen (die mit der zuvor gespeicherten Puffernummer übereinstimmt) und ihn mit dem Zuordnungsbefehl versehen.
Vielleicht so etwas wie:
:{original buffer number}bufdo {mapping command}
Mit der Funktion müssten wir zunächst prüfen, ob der Puffer noch vorhanden ist bufexists()
, da er zwischenzeitlich gelöscht werden könnte.