Was andere Editoren „die geöffnete Datei" oder „den aktuellen Tab" nennen, heißt in Vim Buffer — und der Unterschied zwischen diesen Begriffen ist mehr als terminologisch. Ein Buffer ist Vims im Speicher gehaltene Repräsentation eines Inhalts: meistens einer Datei, manchmal auch eines synthetischen Texts (Help, Quickfix, Terminal-Output, Plugin-UI). Vim trennt dieses Konzept sauber von Window (Anzeigefläche) und Tab (Layout-Container) — und genau diese Trennung ist der Grund, warum Vim mit zehn offenen Buffern in zwei Fenstern und drei Tabs nicht durcheinander kommt. Dieser Artikel klärt, was ein Buffer technisch ist, wie er sich von verwandten Konzepten unterscheidet, was „hidden buffer" bedeutet und warum die Option set hidden in nahezu jeder modernen Vim-Konfig steht.
Was ein Buffer ist — und was nicht
Ein Buffer in Vim ist ein im Speicher gehaltener Inhalt. Drei Bedingungen sind charakteristisch:
- Er hat einen Inhalt (Text, Code, Output, …).
- Er hat einen Namen (meistens ein Dateipfad, manchmal ein synthetischer Bezeichner wie
[No Name]oder[Help]). - Er hat einen Zustand (modified/unmodified, hidden/active, listed/unlisted, …).
Was ein Buffer nicht zwingend hat:
- Keine Datei muss existieren. Ein neu erzeugter Buffer (
:enew) heißt[No Name]und kann ohne Datei-Bindung bearbeitet werden, bis er erstmals gespeichert wird. - Kein sichtbares Fenster muss vorhanden sein. Ein Buffer kann im Speicher offen sein, ohne aktuell auf dem Bildschirm zu erscheinen — siehe „hidden buffers" weiter unten.
Die zentrale Folge: in Vim sind „Datei öffnen" und „Datei anzeigen" zwei verschiedene Operationen. Mit :e file.txt lädst du den Inhalt in einen Buffer und zeigst ihn an. Mit :badd file.txt lädst du ihn in einen Buffer, ohne ihn anzuzeigen. Beide Wege sind legitim.
:e foo.txt " Buffer 1 erzeugt + im aktuellen Fenster angezeigt
:e bar.txt " Buffer 2 erzeugt + ersetzt die Anzeige im Fenster
" Buffer 1 ist NICHT geschlossen — er ist nur "hidden"
:ls " zeigt beide Buffer in der Liste
:b 1 " zu Buffer 1 zurückwechselnBuffer ≠ Window ≠ Tab
Diese drei Konzepte hängen zusammen, sind aber strikt getrennt:
| Konzept | Was es ist | Beispiel |
|---|---|---|
| Buffer | im Speicher gehaltener Inhalt | „der Text von main.go" |
| Window | Anzeigefläche, die einen Buffer zeigt | „das obere Fenster, das aktuell main.go zeigt" |
| Tab | Layout-Container, der ein oder mehrere Windows gruppiert | „der dritte Tab, der zwei Fenster zeigt" |
Daraus ergeben sich nicht-intuitive Möglichkeiten:
- Ein Buffer kann in mehreren Windows gleichzeitig angezeigt sein — z. B. eine Datei oben und unten im Split, beide synchronisiert.
- Ein Buffer kann in keinem Window offen sein und trotzdem im Speicher leben (hidden).
- Ein Tab enthält ein oder mehrere Windows, jedes Window zeigt einen Buffer.
Die häufigste Verwechslung: Vim-Tabs sind nicht das, was VS Code oder Sublime „Tabs" nennt. Dort ist ein Tab eine geöffnete Datei. In Vim ist ein Tab ein Workspace-Layout — z. B. ein Tab für Frontend-Arbeit (zwei Splits, drei Buffer), ein Tab für Backend (anderes Layout). Mehr dazu im Artikel Tabs richtig verstehen.
Mit :ls (Liste der Buffer), :windo (auf jedes Window wirken), :tabdo (auf jeden Tab wirken) hast du jeweils Befehle, die explizit eine der drei Ebenen ansprechen. Wer den Unterschied verinnerlicht hat, navigiert in einem komplexen Vim-Setup mühelos.
Buffer-Eigenschaften und Statusline-Flags
Jeder Buffer hat eine Reihe von Eigenschaften, die :ls als kompakte Flag-Liste neben dem Namen anzeigt:
:ls
" Beispiel-Ausgabe:
" 1 #h "src/main.go" line 42
" 2 a "src/util.go" line 1
" 3 %a + "src/handler.go" line 78
" 4 h "README.md" line 1
" 5 - "[No Name]" line 0Die Spalte zwischen Buffer-Nummer und Dateiname ist eine Flag-Kombination. Die wichtigsten Flags:
| Flag | Bedeutung |
|---|---|
% | aktueller Buffer (der, der im aktuellen Window angezeigt wird) |
# | alternate Buffer (der zuletzt angezeigte) — erreichbar mit <C-^> |
a | active: in einem Window sichtbar |
h | hidden: im Speicher, aber kein Window zeigt ihn |
- | unlisted: erscheint nicht in :ls-Default-Ausgabe |
+ | modifiziert: ungespeicherte Änderungen |
= | read-only |
x | read-error |
Die Flags lassen sich kombinieren — %a + bedeutet z. B. „aktueller Buffer, aktiv, mit ungespeicherten Änderungen". Das ist der typische Status, während man eine Datei editiert.
Der + neben einem Buffer ist eines der wichtigsten visuellen Signale: er bedeutet „diese Datei hat Änderungen, die du noch nicht gespeichert hast". :w setzt ihn zurück, :q! verwirft die Änderungen und schließt den Buffer.
Hidden Buffers — und warum set hidden Standard ist
Im Vim-Default kommt eine subtile Restriktion: wenn du in einem Window eine Datei änderst und sie ungespeichert ist, kannst du kein anderes Buffer in dasselbe Window laden, ohne erst zu speichern oder zu verwerfen. Vim verweigert den Wechsel mit:
E37: No write since last change (add ! to override)
Diese Vorsicht ist gut gemeint — sie verhindert, dass du versehentlich ungespeicherte Änderungen verlierst. In der Praxis ist sie aber lästig: man arbeitet an main.go, will kurz util.go aufrufen, soll aber erst speichern.
Die Option set hidden ändert dieses Verhalten: Vim erlaubt das Verstecken modifizierter Buffer im Hintergrund, ohne sie zu speichern oder zu verlieren. Sie werden hidden, bleiben aber komplett im Speicher — inklusive Undo-Historie. Beim Zurückwechseln (:b N) ist der vorherige Stand exakt wieder da.
" Modifizierte Buffer dürfen "hidden" werden.
" Ohne diese Option fordert Vim vor jedem Buffer-Wechsel
" ein Speichern oder Verwerfen — was im Workflow stört.
set hiddenset hidden ist in jeder modernen Vim-Konfig praktisch verpflichtend. Es ändert das Bedien-Modell zum Besseren — und Vim warnt beim Beenden immer noch vor ungespeicherten Buffern (:qa zeigt sie und fordert eine Entscheidung).
In Neovim ist hidden seit 0.6 ohnehin Default. In Vim ist es weiterhin opt-in.
Synthetische Buffer
Nicht jeder Buffer entspricht einer Datei. Vim erzeugt regelmäßig synthetische Buffer für Editor-interne Funktionen. Eine kurze Übersicht:
| Synthetischer Buffer | Wann er erscheint |
|---|---|
[No Name] | neu erzeugter Buffer ohne Datei-Bindung (:enew) |
| Help-Buffer | beim Öffnen einer Hilfeseite mit :help |
| Quickfix-Buffer | bei :copen (Quickfix-Liste) |
| Location-List-Buffer | bei :lopen |
| Terminal-Buffer | bei :terminal (Vim 8+) |
| Dirvish/netrw | beim Öffnen eines Verzeichnisses |
| Plugin-UI | von Plugins wie fzf, fugitive, vim-airline-Konfig-Fenstern |
Synthetische Buffer haben oft das Flag - (unlisted) — sie tauchen in der Default-:ls-Ausgabe nicht auf. Mit :ls! (mit Ausrufezeichen) zeigt Vim auch unlisted Buffers. Praktisch zur Diagnose, wenn ein Plugin seltsame Zustände erzeugt.
Diese Buffer verhalten sich grundsätzlich wie normale — Motions, Mappings, Suche, alles funktioniert. Was sie unterscheidet, ist meist die buftype-Option, die ihr Speicher- und Schreib-Verhalten festlegt (z. B. nofile für „nicht als Datei speichern", quickfix für die Quickfix-Mechanik).
Buffer-Listing und Inspektion
Die Standard-Werkzeuge zur Buffer-Übersicht:
:ls " gelistete Buffer
:ls! " alle Buffer, auch unlisted (Help, Terminal, ...)
:buffers " Synonym für :ls
:files " Synonym für :ls
" Mit Filter-Flag — nur Buffer in bestimmten Zuständen
:ls + " nur modifizierte Buffer
:ls a " nur aktive (in Windows sichtbare) Buffer
:ls h " nur hidden Buffer
:ls - " nur unlisted BufferDie Filter-Flags lassen sich kombinieren — :ls a+ zeigt nur aktive und modifizierte Buffer, was im Alltag oft genau die richtige Eingrenzung ist.
Pro Buffer interessieren weitere Eigenschaften, die nicht in der :ls-Liste stehen. Zum Inspizieren:
:echo bufnr('%') " Nummer des aktuellen Buffers
:echo bufname('%') " Name des aktuellen Buffers
:echo bufname(2) " Name von Buffer Nr. 2
:echo getbufvar(1, '&filetype') " Filetype von Buffer 1
:echo getbufline(1, 1, '$') " gesamte Inhalts-Liste von Buffer 1Solche Abfragen sind selten im Alltag nötig, aber zentral, wenn man eigene Vim-Skripte schreibt, die mehrere Buffer koordinieren.
Buffer schließen — die drei Wege
Vim kennt drei verschiedene Befehle, um einen Buffer „zu schließen", mit unterschiedlichen Konsequenzen:
| Befehl | Was passiert |
|---|---|
:bd | buffer delete — Buffer aus der Liste entfernen, Speicher freigeben |
:bw | buffer wipeout — wie bd, plus alle assoziierten Settings, Marks |
:bunload | Buffer entladen — Inhalt aus Speicher, aber bleibt in der Liste |
Im Alltag ist :bd der Standard. Es entfernt den Buffer komplett, schließt assoziierte Windows (oder zeigt den vorherigen Buffer dort) und gibt Speicher frei. Buffer-Marks bleiben für die Session aber erhalten.
:bw ist die schärfere Variante — Vim vergisst auch alle assoziierten Mark-Daten und Buffer-lokalen Settings. Sinnvoll, wenn ein Buffer wirklich vollständig vergessen werden soll, z. B. wenn man eine Datei umbenannt hat und der alte Buffer im Weg ist.
:bunload ist eine selten gebrauchte Spezial-Variante: der Buffer bleibt in der Liste, aber sein Inhalt wird aus dem Speicher entfernt. Vor allem für sehr große Dateien interessant, wenn man die Liste behalten, aber RAM freigeben will.
:bd " aktuellen Buffer schließen
:bd file.txt " Buffer mit Namen file.txt schließen
:bd 3 " Buffer Nr. 3 schließen
:3,5bd " Buffer 3 bis 5 schließen
:%bd " ALLE Buffer schließen (mit Bedacht)
:%bd | e# " alle schließen außer dem aktuellenDie letzte Variante (:%bd | e#) ist ein verbreitetes Idiom, um „alle Buffer schließen außer dem aktuellen" — sinnvoll, wenn die Buffer-Liste übervoll geworden ist und man frisch starten will.
Interessantes
`` springt zwischen den letzten zwei Buffern
Eine der nützlichsten unauffälligen Vim-Tasten: <C-^> (oder <C-6> auf manchen Layouts) wechselt zum alternate buffer, also dem zuletzt aktiven. Wer regelmäßig zwischen Code-Datei und Test-Datei springt, hat damit eine Zwei-Tasten-Operation.
Buffer-Nummer ist nicht stabil — Name ist die bessere Referenz
Buffer-Nummern werden vergeben in der Reihenfolge des Erscheinens und können sich ändern, wenn Buffer geschlossen werden. Wer in Skripten oder Plugins auf einen Buffer referenziert, sollte den Namen (z. B. bufnr('main.go')) oder einen mark-basierten Ansatz wählen — nicht die nackte Nummer.
`buftype` kategorisiert synthetische Buffer
Vims Option buftype (per Buffer) sagt, welcher „Typ" Buffer es ist: leer = normale Datei, nofile = synthetisch ohne Datei-Bindung, quickfix = Quickfix-Liste, help = Help-Buffer, terminal = Terminal-Buffer. Plugins setzen diese Option, um ihr UI-Buffer-Verhalten zu steuern.
`set hidden` in Neovim ist Default
Neovim hat hidden seit 0.6 als Default aktiviert. In Vim bleibt es opt-in. Wer Konfigs zwischen den Editoren teilt, sollte set hidden explizit setzen — dann ist das Verhalten überall gleich.
Modifizierte hidden Buffer und :q schützen sich gegenseitig
Vim warnt beim Beenden, wenn modifizierte (hidden oder nicht) Buffer existieren — :qa zeigt die Liste und fordert eine Entscheidung. Wer trotzdem alles wegwerfen will, nutzt :qa!. Es ist also kein Risiko, modifizierte Buffer hidden zu lassen; Vim ist beim Beenden gründlich.
`:ls!` ist ein Diagnose-Werkzeug für Plugin-Verhalten
Wenn ein Plugin sich seltsam verhält und seine UI-Buffer im Weg sind, zeigt :ls! alle Buffer inklusive der unlisted. Damit findet man oft schnell, dass z. B. drei vergessene fzf-Buffer im Speicher liegen — und kann sie gezielt mit :bw aufräumen.
Weiterführende Ressourcen
Externe Quellen
- Vim Help: windows.txt — Buffer/Window/Tab-Modell im offiziellen Manual.
- Vim Help: :buffers — die Buffer-Listings-Befehle.
- Vim Help: hidden — die hidden-Option im Detail.
- Vim Help: buftype — Buffer-Typen für synthetische Buffer.
- Drew Neil — Practical Vim, Tip 36-37 — Buffer-Workflow in der Praxis.