Ich habe eine AutocMD für TeX- und Markdown-Dateien, um die Datei automatisch zu speichern. Nichts Ungewöhnliches:
autocmd CursorHold *.tex,*.md w
Da jedoch die benutzerdefinierten Einstellungen für diese Dateien zunahmen, habe ich sie aufgeteilt in ftplugin/tex.vim
und ftplugin/markdown.vim
:
" ftplugin/tex.vim
autocmd CursorHold *.tex w
" ftplugin/markdown.vim
autocmd CursorHold *.md w
Jetzt werden diese Dateien nur für die entsprechenden Dateien bereitgestellt, sodass der Mustervergleich überflüssig ist. Anscheinend kann autocmd
s pufferlokal sein. Von :h autocmd-buffer-local
:
Buffer-local autocommands are attached to a specific buffer. They are useful
if the buffer does not have a name and when the name does not match a specific
pattern. But it also means they must be explicitly added to each buffer.
Instead of a pattern buffer-local autocommands use one of these forms:
<buffer> current buffer
<buffer=99> buffer number 99
<buffer=abuf> using <abuf> (only when executing autocommands)
<abuf>
Das scheint für eine solche Verwendung gedacht zu sein. Jetzt können beide ftplugin/tex.vim
und ftplugin/markdown.vim
haben:
autocmd CursorHold <buffer> w
Ich bin nicht wirklich besorgt über die tatsächliche Erweiterung, solange der Dateityp korrekt ist. Dies erspart mir die Sorge über *.md
und *.markdown
und alle anderen Erweiterungen, die für Markdown gültig sind.
Ist diese Verwendung <buffer>
korrekt? Gibt es irgendwelche Fallstricke, auf die ich achten sollte? Wird es chaotisch, wenn ich einen Puffer lösche und einen anderen öffne (hoffentlich werden die Zahlen nicht kollidieren, aber ...)?
up
(kurz für:update
) wäre besser alsw
in Ihrem AutocMD (vermeiden Sie unnötige Schreibvorgänge).w
fehlgeschlagen. Wiederholt.:up
tut in diesem Fall nichts. :)Antworten:
Ich denke, es ist richtig, aber Sie müssen es nur in eine Augroup einschließen und diese löschen, um sicherzustellen, dass die autocmd nicht jedes Mal dupliziert wird, wenn Sie einen Befehl ausführen, der denselben Puffer neu lädt.
Wie Sie erklärt haben,
<buffer>
können Sie sich mit dem speziellen Muster auf den in der Datei implementierten Mechanismus zur Erkennung von Dateitypen verlassen$VIMRUNTIME/filetype.vim
.In dieser Datei finden Sie die in Vim integrierten Autocmds, die für die Einstellung des richtigen Dateityps für einen bestimmten Puffer verantwortlich sind. Zum Beispiel für Abschriften:
In Ihrem Dateityp-Plugin können Sie für jede von Ihnen installierte Autocmd die gleichen Muster kopieren. So speichern Sie beispielsweise den Puffer automatisch, wenn sich der Cursor einige Sekunden lang nicht bewegt hat:
Aber
<buffer>
ist viel weniger ausführlich:Außerdem, wenn eines Tages eine andere Erweiterung gültig ist und
$VIMRUNTIME/filetype.vim
aktualisiert wird, um sie einzuschließen, werden Ihre AutocMDS nicht informiert. Und Sie müssen alle Muster in Ihren Dateityp-Plugins aktualisieren.Ich bin nicht sicher, aber ich glaube nicht, dass Vim die Puffernummer eines gelöschten Puffers wiederverwenden kann. Ich konnte den relevanten Abschnitt in der Hilfe nicht finden, aber ich habe diesen Absatz von vim.wikia.com gefunden :
Außerdem werden, wie @ Tumbler41 erklärte, beim Löschen eines Puffers dessen Autocmds entfernt. Von
:h autocmd-buflocal
:Wenn Sie sich selbst überprüfen möchten, können Sie dies tun, indem Sie die Ausführlichkeitsstufe von Vim auf 6 erhöhen. Sie können dies vorübergehend für nur einen Befehl tun, indem Sie den
:verbose
Modifikator verwenden. So können Sie in Ihrem Abschriftenpuffer Folgendes ausführen:Wenn Sie dann die Nachrichten von Vim überprüfen:
Sie sollten eine Zeile sehen, die so aussieht:
Wo
42
war die Nummer Ihres Abschriftenpuffers?Es gibt drei Situationen, die ich als Fallstricke betrachten würde und die das spezielle Muster betreffen
<buffer>
. In zwei Fällen<buffer>
kann es sich um ein Problem handeln, in den anderen um eine Lösung.Fallstricke 1
Zunächst sollten Sie vorsichtig sein, wie Sie die Augroups Ihrer pufferlokalen Autocmds löschen. Sie müssen mit diesem Snippet vertraut sein:
Sie könnten also versucht sein, es für Ihre pufferlokalen autocmds zu verwenden, die nicht modifiziert wurden, wie folgt:
Dies hat jedoch einen unerwünschten Effekt.
A
Wenn Sie einen Abschriftenpuffer zum ersten Mal laden, rufen wir ihn auf , seine Autocmd wird korrekt installiert. Wenn Sie dann neu ladenA
, wird die autocmd (wegenautocmd!
) gelöscht und neu installiert. Die Augroup verhindert also korrekterweise das Duplizieren der Autocmd.Angenommen, Sie laden einen zweiten Abschriftenpuffer, nennen wir ihn
B
in einem zweiten Fenster. ALLE autocmds der Augroup werden gelöscht: das ist die autocmd vonA
und die vonB
. Dann wird eine SINGLE-Autocmd für installiertB
.Wenn Sie also eine Änderung vornehmen
B
und einige Sekunden warten,CursorHold
bis sie ausgelöst wird, wird sie automatisch gespeichert. Wenn Sie jedoch zurückkehrenA
und dasselbe tun, wird der Puffer nicht gespeichert. Dies liegt daran, dass beim letzten Laden eines Markdown-Puffers ein Ungleichgewicht zwischen dem Entfernten und dem Hinzugefügten aufgetreten ist. Sie haben mehr entfernt, als Sie hinzugefügt haben.Die Lösung besteht darin, nicht ALLE AutocMDS zu entfernen, sondern nur die des aktuellen Puffers, indem das spezielle Muster
<buffer>
an:autocmd!
folgende Adresse übergeben wird :Beachten Sie, dass Sie
CursorHold
jedes Ereignis in der Zeile, in der autocmds entfernt werden , durch einen Stern ersetzen können:Auf diese Weise müssen Sie nicht alle Ereignisse angeben, die Ihre Autocmds abhören, wenn Sie die Augroup löschen möchten.
Fallstricke 2
Es gibt noch eine weitere Falle, aber diesmal
<buffer>
ist es nicht das Problem, sondern die Lösung.Wenn Sie eine lokale Option in ein Dateityp-Plugin einfügen, geschieht dies wahrscheinlich folgendermaßen:
Dies funktioniert erwartungsgemäß für pufferlokale Optionen, jedoch nicht immer für fensterlokale Optionen. Um das Problem zu veranschaulichen, können Sie das folgende Experiment versuchen. Erstellen Sie die Datei
~/.vim/after/ftdetect/potion.vim
und schreiben Sie darin:Diese Datei legt automatisch den Dateityp
potion
für jede Datei mit der Erweiterung fest.pn
. Sie müssen es nicht in eine Augroup einschließen, da Vim es für diese bestimmte Art von Datei automatisch ausführt (siehe:h ftdetect
).Wenn die Zwischenverzeichnisse auf Ihrem System nicht vorhanden sind, können Sie sie erstellen.
Als nächstes erstellen Sie das Dateityp-Plugin
~/.vim/after/ftplugin/potion.vim
und schreiben darin:Standardmäßig
potion
bewirkt diese Einstellung in einer Datei, dass die Tabulatorzeichen als^I
und das Zeilenende als angezeigt werden$
.Erstellen Sie nun ein Minimum
vimrc
. innen/tmp/vimrc
schreiben:... um die Dateityp-Plugins zu aktivieren.
Erstellen Sie außerdem eine Trankdatei
/tmp/pn.pn
und eine zufällige Datei/tmp/file
. Schreiben Sie in die Trankdatei Folgendes:Schreiben Sie in die Zufallsdatei den Pfad zur Trankdatei
/tmp/pn.pn
:Starten Sie nun Vim mit einem Minimum an Initialisierungen, indem Sie nur die Quelle auswählen
vimrc
und beide Dateien in vertikalen Ansichtsfenstern öffnen:Sie sollten 2 vertikale Ansichtsfenster sehen. Die Zaubertrank-Datei auf der linken Seite zeigt das Ende von Zeilen mit Dollarzeichen an, die Zufallsdatei auf der rechten Seite zeigt sie überhaupt nicht an.
Setzen Sie den Fokus auf die Zufallsdatei und drücken Sie
gf
, um die Trankdatei anzuzeigen, deren Pfad sich unter dem Cursor befindet. Sie sehen jetzt den gleichen Trankpuffer im rechten Ansichtsfenster, aber dieses Mal wird das Zeilenende nicht mit Dollarzeichen angezeigt. Und wenn Sie tippen:setlocal list?
, sollte Vim antworten mitnolist
:Die ganze Kette von Ereignissen:
... ist nicht aufgetreten, weil der erste von ihnen,
BufRead
nicht aufgetreten ist, als Sie gedrückt habengf
. Der Puffer wurde bereits geladen.Es mag unerwartet erscheinen, weil Sie beim Hinzufügen
setlocal list
in Ihrem Potion-Dateityp-Plugin möglicherweise gedacht haben, dass es die'list'
Option in jedem Fenster aktivieren würde, in dem ein Potion-Puffer angezeigt wird .Das Problem ist nicht spezifisch für diesen neuen
potion
Dateityp. Sie können es auch mit einermarkdown
Datei erleben .Es ist auch nicht spezifisch für die
'list'
Option. Sie können es mit anderen Fenstern-lokalen Einstellungen erfahren, wie'conceallevel'
,'foldmethod'
,'foldexpr'
,'foldtitle'
, ...Es ist auch nicht spezifisch für den
gf
Befehl. Sie können es mit anderen Befehlen erleben, die den im aktuellen Fenster angezeigten Puffer ändern können: globale Markierung,C-o
(in der fensterlokalen Sprungliste rückwärts bewegen),,:b {buffer_number}
...Zusammenfassend werden die fensterlokalen Optionen nur dann korrekt festgelegt, wenn:
BufRead
sie gefeuert werden muss):split
(In diesem Fall sollten die fensterlokalen Optionen von dem Fenster übernommen werden, in dem der Befehl ausgeführt wurde.)Andernfalls sind die fensterlokalen Optionen möglicherweise nicht richtig eingestellt.
Eine mögliche Lösung wäre, sie nicht direkt über ein Dateityp-Plugin festzulegen, sondern über eine in diesem installierte AutocMD, die sie abhört
BufWinEnter
. Dieses Ereignis sollte jedes Mal ausgelöst werden, wenn ein Puffer in einem Fenster angezeigt wird.Also zum Beispiel, anstatt dies zu schreiben:
Du würdest folgendes schreiben:
Und hier finden Sie wieder das spezielle Muster
<buffer>
.Fallstricke 3
Wenn Sie den Dateityp Ihres Puffers ändern, bleiben die AutocMDS erhalten. Wenn Sie sie entfernen möchten, müssen Sie Folgendes konfigurieren
b:undo_ftplugin
(siehe:h undo_ftplugin
) und den folgenden Befehl einfügen:Versuchen Sie jedoch nicht, die Augroup selbst zu entfernen, da es noch einige Abschriftenpuffer geben kann, in denen sich Autocmds befinden.
FWIW, dies ist das UltiSnips-Snippet, das ich verwende, um Folgendes festzulegen
b:undo_ftplugin
:Und hier ist ein Beispiel für den Wert, den ich habe
~/.vim/after/ftplugin/awk.vim
:Als Randnotiz verstehe ich, warum Sie die Frage gestellt haben, denn als ich nach allen Zeilen gesucht habe, in denen das spezielle Muster
<buffer>
in den Standarddateien von Vim verwendet wurde:Ich habe nur 9 Übereinstimmungen gefunden (möglicherweise finden Sie mehr oder weniger Übereinstimmungen, ich verwende Vim Version 8.0 mit Patches bis zu
134
). Und unter den 9 Übereinstimmungen sind 7 in der Dokumentation, nur 2 wurden tatsächlich beschafft. Sie sollten sie in $ VIMRUNTIME / syntax / dircolors.vim finden :Ich weiß nicht , ob es ein Problem verursachen kann, aber sie sind nicht in einem augroup, die jedes Mal , bedeutet , dass Sie einen Puffer , dessen Dateityp neu zu laden ist
dircolors
(es passiert , wenn Sie eine Datei mit dem Namen bearbeiten.dircolors
,.dir_colors
oder dessen Pfad endet mit/etc/DIR_COLORS
), Das Syntax-Plugin fügt eine neue pufferlokale Autocmd hinzu.Sie können dies folgendermaßen überprüfen:
Der letzte Befehl sollte dies anzeigen:
Laden Sie nun den Puffer neu und fragen Sie erneut nach den pufferlokalen Autocmds für den aktuellen Puffer:
Dieses Mal werden Sie sehen:
Nach jedem der Datei neu zu laden,
s:reset_colors()
unds:preview_color('.')
wird ein weiteres Mal aufgerufen werden, jedes Mal , wenn einer der VeranstaltungCursorHold
,CursorHoldI
,CursorMoved
,CursorMovedI
wird gefeuert.Dies ist wahrscheinlich kein großes Problem, da
dircolors
ich auch nach mehrmaligem Neuladen einer Datei keine merkliche Verlangsamung oder ein unerwartetes Verhalten von Vim feststellen konnte.Wenn es ein Problem für Sie ist, können Sie sich an den Betreuer des Syntax-Plugins wenden. Wenn Sie jedoch in der Zwischenzeit die Duplizierung von autocmds verhindern möchten, können Sie
dircolors
mithilfe der Datei ein eigenes Syntax-Plugin für Dateien erstellen~/.vim/syntax/dircolors.vim
. Darin würden Sie den Inhalt des ursprünglichen Syntax-Plugins importieren:In letzterem Fall würden Sie die autocmds einfach in eine Augroup einschließen, die Sie löschen würden. Also würden Sie diese Zeilen ersetzen:
... mit diesen:
Beachten Sie, dass, wenn Sie Ihr
dircolors
Syntax-Plugin mit der Datei erstellt haben~/.vim/after/syntax/dircolors.vim
, dies nicht funktioniert, da das Standardsyntax-Plugin zuvor verwendet wurde. Bei Verwendung von~/.vim/syntax/dircolors.vim
wird Ihr Syntax-Plug-In vor dem Standard-Plug-In bereitgestellt und es wird die pufferlokale Variable festgelegtb:current_syntax
, die verhindert, dass das Standardsyntax-Plug-In bereitgestellt wird, da es diesen Schutz enthält:Die allgemeine Regel scheint zu lauten: Verwenden Sie die Verzeichnisse
~/.vim/ftplugin
und~/.vim/syntax
, um ein benutzerdefiniertes Dateityp- / Syntax-Plugin zu erstellen und zu verhindern, dass das nächste Plugin (für denselben Dateityp) im Laufzeitpfad (einschließlich der Standard-Plugins) bezogen wird. Und Gebrauch~/.vim/after/ftplugin
,~/.vim/after/syntax
nicht zu verhindern , dass andere Plugins von Quellen zu werden, aber nur das letzte Wort haben , auf dem Wert von einigen Einstellungen.quelle
autocmd!
mitautocmd! CursorHold <buffer>
inaugroup
Blöcken ist ein besonders kritischer Punkt - und sollte im Vorfeld hervorgehoben werden. Trotzdem ... das ist eine erstaunliche Investition von Zeit, Mühe und blutigen Tränen.