Wer Emacs verstehen will, kommt am Begriff Buffer nicht vorbei. Er ist die wichtigste Abstraktion des ganzen Systems — wichtiger als Fenster, Frames, Modes oder Hooks, weil all diese Begriffe Buffer voraussetzen, um überhaupt Sinn zu ergeben. „Jeder Inhalt in Emacs lebt in einem Buffer" ist kein Marketing-Satz, sondern eine Architektur-Aussage: eine geöffnete Datei ist ein Buffer, ein Hilfe-Text ist ein Buffer, die Ausgabe einer Shell ist ein Buffer, eine E-Mail ist ein Buffer, sogar das kleine Eingabefeld am unteren Fensterrand — der Minibuffer — ist ein Buffer. Dieser Artikel klärt, was ein Buffer technisch ist, wie er sich von einer Datei unterscheidet, welche speziellen Buffer Emacs standardmäßig mitbringt und welche Eigenschaften (Modified, Read-Only, buffer-lokale Variablen) du im Alltag siehst und steuerst.
Was ein Buffer ist
Ein Buffer ist die in-Memory-Repräsentation von editierbarem Inhalt im laufenden Emacs-Prozess. Das ist die ganze Definition — alles Weitere folgt daraus.
Konkret hat jeder Buffer in Emacs eine feste Liste von Eigenschaften, die das System intern verwaltet und die du in der Modeline und über Befehle abfragen kannst:
- einen Namen (eindeutig pro Emacs-Session, Groß-/Kleinschreibung ist signifikant),
- einen Inhalt (eine Folge von Zeichen, optional mit Text-Properties wie Farbe oder Schrift-Eigenschaften),
- einen Major-Mode, der Sprache und Verhalten festlegt (z. B.
python-mode,markdown-mode,dired-mode), - beliebig viele Minor-Modes, die zusätzliches Verhalten überlagern (Zeilennummern, Autovervollständigung, Versionskontroll-Anzeige …),
- eine Cursor-Position, in Emacs Point genannt,
- eine Mark als Gegenstück zum Point für Bereichs-Operationen,
- einen Modified-Status (verändert seit dem letzten Speichern, ja/nein),
- einen Read-Only-Status (schreibgeschützt, ja/nein),
- und — optional — eine Verknüpfung zu einer Datei auf dem Datenträger.
Der letzte Punkt ist der entscheidende. Ein Buffer kann mit einer Datei verknüpft sein, muss es aber nicht. Spezielle Buffer wie *scratch*, *Messages* oder *Help* haben keine Datei — sie existieren nur im Speicher und verschwinden, wenn Emacs beendet wird.
Ein zweiter, oft übersehener Punkt: Ein Buffer existiert unabhängig von seiner Anzeige. Er muss nicht in einem Fenster sichtbar sein, um zu existieren. Du kannst Dutzende Buffer offen haben, von denen nur einer oder zwei tatsächlich in Windows angezeigt werden — die anderen warten geduldig im Speicher und sind über die Buffer-Liste jederzeit erreichbar. Die Trennung zwischen Buffer (was es gibt) und Window (was du gerade siehst) ist eine der prägenden Designentscheidungen von Emacs und Thema des Folgeartikels Fenster und Splits.
Buffer vs. Datei: der zentrale Unterschied
Die wichtigste Hürde beim Einstieg in Emacs ist die saubere mentale Trennung von Datei und Buffer. Andere Editoren verschleiern diese Trennung — bei VS Code, Sublime oder TextEdit fühlt sich „die Datei" und „das, was im Tab steht" wie dasselbe an. In Emacs sind es zwei verschiedene Dinge, und das Verhalten des Systems ergibt nur dann Sinn, wenn man die beiden auseinanderhält.
| Aspekt | Datei | Buffer |
|---|---|---|
| Wo lebt sie/er? | persistent auf der Festplatte | nur im Emacs-Prozess (Hauptspeicher) |
| Identifikation | Pfad, Inode | Buffer-Name |
| Metadaten | Permissions, mtime, Owner | Major-Mode, Modified-Flag, Point, Mark, Read-Only |
| Persistenz | überlebt Emacs-Neustart, Rechner-Neustart | endet mit dem Emacs-Prozess (außer manuell gespeichert) |
| Verknüpfung | unabhängig von Emacs | kann mit einer Datei verbunden sein, muss aber nicht |
Aus dieser Trennung entstehen zwei Verwirrungen, die jedem Einsteiger früher oder später passieren:
- „Ich habe die Datei gespeichert, warum sehe ich noch alte Inhalte?" Antwort: Eine andere Anwendung hat die Datei extern geändert, aber Emacs hat den Buffer nicht neu eingelesen. Der Buffer zeigt weiterhin den Stand, der zuletzt in den Speicher geladen wurde. Lösung: M-x revert-buffer liest die Datei manuell neu in den Buffer. Wer das automatisch haben will, aktiviert M-x global-auto-revert-mode.
- „Ich habe im Buffer editiert, aber die Datei ist unverändert." Antwort: Du hast nur den Buffer im Speicher verändert, nicht die Datei. Solange du nicht mit C-x C-s (
save-buffer) speicherst, bleibt die Datei auf der Festplatte unangetastet. Der Modified-Marker in der Modeline (zwei Sternchen**) zeigt dir genau diesen Zustand: „Buffer geändert, Datei noch nicht aktualisiert".
Die Modeline ist der wichtigste Ort, um diesen Unterschied im Alltag zu sehen — sie zeigt mit -- (unverändert), ** (geändert) und %% (read-only) den Buffer-Zustand auf einen Blick. Details dazu im Artikel Modeline lesen.
Spezielle Buffer und ihre Namen
Buffer-Namen folgen einer informellen Konvention: Wer mit * beginnt und endet (z. B. *scratch*), gilt als nicht datei-gebunden — also als synthetischer Buffer, den Emacs selbst oder ein Paket erzeugt hat. Buffer-Namen, die mit einem Leerzeichen beginnen (z. B. *Minibuf-0*), gelten als intern und werden in der Standard-Buffer-Liste ausgeblendet.
Direkt nach dem Start existieren in jedem Emacs eine Handvoll dieser Spezial-Buffer. Die wichtigsten:
| Buffer-Name | Zweck |
|---|---|
*scratch* | Notiz- und Test-Bereich, Default-Mode ist lisp-interaction-mode; Inhalt geht beim Beenden verloren |
*Messages* | System-Log mit allen Echo-Area-Meldungen, Lade-Hinweisen und Fehlern |
*Help* | wird bei jeder Hilfe-Anfrage (C-h …) neu befüllt |
*Completions* | Liste der möglichen Vervollständigungen im Minibuffer |
*shell* | interaktive Shell innerhalb von Emacs (M-x shell) |
*eshell* | Emacs' eigene, Lisp-basierte Shell (M-x eshell) |
*vterm* | voll funktionsfähiges Terminal-Emulator-Paket (externes Paket) |
*Minibuf-0* | der Minibuffer selbst — als interner Buffer mit führendem Leerzeichen im Namen |
Aus dieser Liste folgen zwei nützliche Beobachtungen:
- Auch der Minibuffer ist ein Buffer. Jede Minibuffer-Eingabe — Datei öffnen, Befehl per Namen aufrufen, Y/N-Frage beantworten — passiert in einem eigenen, kleinen Buffer mit eigenem Major-Mode. Das ist der Grund, warum Cursor-Bewegung, Suchen und sogar Yank/Kill im Minibuffer genauso funktionieren wie in jedem anderen Buffer.
- Der
*scratch*-Buffer ist nicht zufällig im Lisp-Interaction-Mode. Emacs wurde von Anfang an als Lisp-Maschine konzipiert, in der man jederzeit Code auswerten kann.*scratch*ist der dafür vorgesehene Spielplatz: Tippe einen Ausdruck, drücke C-j, und das Ergebnis erscheint in derselben Zeile. Der Buffer wird nicht gespeichert, sein Inhalt geht beim Beenden verloren — das ist beabsichtigt.
Buffer-Eigenschaften: Read-Only, Modified, lokale Variablen
Drei Eigenschaften jedes Buffers tauchen im Alltag immer wieder auf — in der Modeline, in Fehlermeldungen, in Konfigurations-Hinweisen. Es lohnt sich, sie sauber zu kennen.
Modified
Der Modified-Status zeigt, ob der Buffer seit dem letzten Speichern verändert wurde. Jede Tasten-Eingabe, die Inhalt einfügt oder löscht, setzt das Flag automatisch; das Speichern mit C-x C-s setzt es zurück. In der Modeline siehst du das an den Zeichen ganz links neben dem Buffer-Namen: -- bedeutet unverändert, ** bedeutet geändert.
Programmatisch lässt sich das Flag mit set-buffer-modified-p auch manuell setzen oder löschen — selten nötig, aber bei Skripten gelegentlich praktisch. Für den Alltag reicht: Sternchen in der Modeline = vergiss nicht zu speichern.
Read-Only
Mit C-x C-q (read-only-mode) lässt sich jeder Buffer in einen schreibgeschützten Zustand versetzen — und genauso wieder zurück. Das ist eine reine Buffer-Eigenschaft: Die Datei auf der Festplatte bleibt unverändert, nur Emacs verweigert Schreib-Operationen in diesem Buffer. In der Modeline wird der Zustand mit %% angezeigt.
Praktischer Use-Case: Beim Lesen einer fremden Datei drückst du einmal C-x C-q und schützt dich damit gegen versehentliches Tippen. Viele Hilfs-Buffer (*Help*, *Messages*, *Completions*) sind standardmäßig read-only, weil ihr Inhalt nicht editierbar gedacht ist.
Buffer-lokale Variablen
Eine der mächtigsten Konzepte in Emacs sind buffer-lokale Variablen: Eine sehr große Zahl von Konfigurations-Werten kann pro Buffer einen eigenen Wert haben. Beispiele: fill-column (Zeilenlänge für Auto-Fill), indent-tabs-mode (Tab vs. Spaces), tab-width (Tab-Breite). In Python-Buffern willst du andere Werte als in Markdown-Buffern, und genau das macht Emacs automatisch — die Major-Modes setzen ihre Variablen-Werte buffer-lokal.
Du kannst das auch von Hand steuern. Drei Wege gibt es:
M-x make-local-variablemacht eine bestimmte Variable für den aktuellen Buffer lokal. Nachfolgendesetq-Aufrufe wirken nur hier, nicht global.- File-Local Variables in einer ersten Zeile der Datei, z. B.
-*- mode: python; tab-width: 4 -*-— Emacs liest diese beim Öffnen und setzt die Werte buffer-lokal. Auch ein eigener Block am Datei-Ende ist möglich (Local Variables:…End:). - Dir-Local Variables in einer Datei
.dir-locals.elim Projekt-Verzeichnis. Wirken auf alle Buffer, die unterhalb dieses Verzeichnisses geöffnet werden.
Ein typisches File-Local-Beispiel:
# -*- mode: python; tab-width: 4; indent-tabs-mode: nil -*-Damit weiß Emacs: dieser Buffer läuft im python-mode, Tabs sind 4 Spalten breit, eingerückt wird ausschließlich mit Leerzeichen. Die Werte gelten nur für genau diesen Buffer und stören keine globale Konfiguration.
Buffer-Liste und ibuffer
Sobald mehr als zwei oder drei Buffer offen sind, brauchst du eine Übersicht. Emacs bringt dafür zwei Werkzeuge mit:
- C-x C-b öffnet
list-buffers— eine minimalistische Liste aller Buffer mit Name, Größe, Mode und (falls vorhanden) Datei-Pfad. Funktional, aber spartanisch. - M-x ibuffer ist die deutlich komfortablere Alternative. Sortieren nach beliebigen Spalten, Filtern nach Mode, Datei-Pfad oder Buffer-Name, Mass-Operations (markieren und gemeinsam speichern, schließen, revertieren). Wer regelmäßig viele Buffer offen hat, sollte
ibufferals Standard auf C-x C-b legen — das ist eine der lohnendsten Default-Änderungen in Emacs.
Wo dieser Code hingehört
Dieses Snippet gehört in deine zentrale Konfigurations-Datei (~/.emacs.d/init.el oder ~/.config/emacs/init.el). Was diese Datei tut, wann sie gelesen wird und wie man sie sinnvoll strukturiert, erklärt der Artikel Konfiguration mit init.el und early-init.el im Detail.
;; ibuffer statt list-buffers auf C-x C-b
(global-set-key (kbd "C-x C-b") #'ibuffer)Nach einem Emacs-Neustart (oder einem M-x eval-buffer auf der init.el) öffnet C-x C-b die komfortable Variante. Die alte list-buffers-Funktion bleibt erreichbar über M-x list-buffers.
Buffer schließen ohne Datenverlust
Ein Buffer schließen heißt in Emacs „töten" (englisch kill) — der Begriff ist drastisch, aber präzise: Der Buffer wird aus dem Speicher entfernt, sein Inhalt ist weg, der Name wieder frei. Die Tastenkombination:
- C-x k (
kill-buffer) tötet den aktuellen Buffer. Emacs fragt im Minibuffer nach dem Namen (mit dem aktuellen Buffer als Vorschlag) und tötet nach Bestätigung. - C-x 4 0 (
kill-buffer-and-window) tötet zusätzlich das anzeigende Window — praktisch, wenn man den Buffer mit einem Split geöffnet hatte und die Aufteilung nicht zurückbleiben soll.
Zwei wichtige Sicherheits-Eigenschaften:
- Modifizierte Buffer werden nicht stillschweigend getötet. Hat der Buffer ungespeicherte Änderungen UND ist mit einer Datei verbunden, fragt Emacs im Minibuffer nach: „Buffer modified; kill anyway?" — bestätige mit
yes, oder breche mit C-g ab und speichere zuerst. - Eine Datei wird durch
kill-bufferNIE gelöscht.kill-bufferentfernt nur die in-Memory-Repräsentation; die Datei auf der Festplatte bleibt vollständig erhalten. „Buffer schließen" und „Datei löschen" sind in Emacs zwei strikt getrennte Operationen — letzteres geht über M-x delete-file oder über Dired.
Wer mehrere Buffer auf einmal aufräumen will, nutzt ibuffer: Buffer markieren mit m, dann D für „mark for deletion" und x zur Ausführung. Auch hier fragt Emacs bei modifizierten Buffern nach.
Indirekte Buffer — zwei Sichten auf einen Text
Ein selten erklärtes, aber elegantes Feature: indirekte Buffer. Zwei Buffer teilen sich denselben Inhalt, haben aber unterschiedliche Major-Modes, unterschiedliche Narrow-Bereiche, eigenen Point und eigene buffer-lokale Variablen. Bearbeitest du in einem davon, ändert sich der Text auch im anderen — beide zeigen dieselbe Daten, nur durch unterschiedliche „Linsen".
Erzeugen lässt sich ein indirekter Buffer mit:
- M-x clone-indirect-buffer — erzeugt einen indirekten Buffer mit demselben Inhalt im aktuellen Window-Layout (oder in einem neuen Window mit
clone-indirect-buffer-other-window).
Typische Use-Cases:
- Ein langes Org-Dokument zweimal öffnen: einmal mit Outline-View (alle Überschriften eingeklappt), einmal mit voll expandiertem Code-Block-View. Beide Sichten zeigen denselben Text, Editieren in der einen wirkt sofort in der anderen.
- Eine Markdown-Datei im normalen
markdown-modeund parallel imtext-modeohne Syntax-Highlighting, um die Roh-Struktur zu prüfen. - Ein Code-Buffer, der unten genarrowt einen einzelnen Funktionskörper zeigt, und ein zweiter indirekter Buffer mit der vollen Datei für Navigation.
Für die meisten Nutzer ist das Feature selten relevant, aber sauberer als Window-Splits, wenn man wirklich zwei unterschiedlich konfigurierte Sichten auf denselben Inhalt braucht.
Konvention: Buffer-Hierarchie an den Namen erkennen
Buffer-Namen tragen mehr Information, als auf den ersten Blick scheint. Drei wiederkehrende Muster:
| Muster | Bedeutung |
|---|---|
name | normaler, datei-gebundener Buffer (Name = meist Dateiname ohne Verzeichnis) |
name<2>, name<3> | zweiter, dritter Buffer mit ursprünglich identischem Namen (z. B. gleicher Dateiname in zwei Ordnern) |
*name* | synthetischer, nicht datei-gebundener Buffer (Help, Shell, Messages, Compilation …) |
*name* | interner Buffer mit führendem Leerzeichen — in der Standard-Buffer-Liste ausgeblendet |
Die <2>, <3>-Suffixe entstehen automatisch, wenn du zweimal dieselbe Datei aus unterschiedlichen Verzeichnissen öffnest. Sie sind funktional, aber unschön — man sieht ja nicht, welcher Buffer aus welchem Ordner stammt. Genau dafür gibt es das eingebaute Paket uniquify, das die Namen automatisch um Verzeichnis-Anteile erweitert, sobald Kollisionen auftreten. Beispiel: statt init.el und init.el<2> siehst du init.el|emacs und init.el|doom.
;; Buffer-Namen mit Pfad-Bestandteilen statt <2>, <3>, ...
(require 'uniquify)
(setq uniquify-buffer-name-style 'forward)uniquify ist seit Jahrzehnten Built-in und gehört zu den lohnendsten Default-Änderungen — die Standard-Variante mit <2> ist heute eigentlich nur noch aus Kompatibilitätsgründen aktiv. Wo dieses Snippet hingehört, wieder dieselbe Antwort wie oben: in deine Konfigurations-Datei.
Interessantes
Buffer ist die Abstraktion — nicht das Window
Dasselbe Buffer kann gleichzeitig in mehreren Windows sichtbar sein, in unterschiedlichen Frames, sogar mit unterschiedlichen sichtbaren Bereichen. Das Window ist nur eine Sicht — der Buffer ist der Inhalt. Wer diese Trennung verinnerlicht, versteht sofort, warum Emacs bei einem C-x 1 (alle anderen Windows schließen) keinen Inhalt verliert.
Externe Änderungen werden nicht automatisch übernommen
Ändert eine andere Anwendung die Datei auf der Festplatte, bleibt der Emacs-Buffer auf dem alten Stand. M-x revert-buffer lädt manuell neu; M-x global-auto-revert-mode aktiviert das automatisch für alle Buffer. Letzteres ist für Workflows mit Git-Rebase oder externen Formattern fast Pflicht.
`*scratch*` ist nicht datei-gebunden
Der *scratch*-Buffer hat keine Datei und wird beim Beenden von Emacs nicht persistiert. Sein Inhalt ist beim nächsten Start weg — es sei denn, du speicherst ihn explizit mit C-x C-w (write-file) unter einem Pfad. Das ist gewollt: *scratch* ist als folgenloser Spielplatz konzipiert, kein Notiz-Speicher.
Spezial-Buffer mit führendem Leerzeichen sind versteckt
Buffer wie *Minibuf-0* (mit führendem Leerzeichen) werden in der Standard-Buffer-Liste (C-x C-b) absichtlich ausgeblendet — sie sind interner Mechanik vorbehalten. Wer sie wirklich sehen will, nutzt ibuffer mit angepasstem Filter oder ruft sie über C-x b per Namen direkt auf.
Buffer-lokale Variablen sind eines der mächtigsten Konfig-Features
Sehr viele Emacs-Variablen lassen sich pro Buffer (oder pro Mode-Hook) anders setzen als global. Genau deshalb kann ein Python-Buffer mit 4 Spaces einrücken und ein Makefile-Buffer mit Tabs, ohne dass globale Konfiguration nötig ist. Major-Modes setzen ihre Defaults buffer-lokal — du musst selten manuell make-local-variable aufrufen.
`kill-buffer` löscht NIE die Datei
Auch bei datei-gebundenen Buffern entfernt C-x k ausschließlich die in-Memory-Repräsentation. Die Datei am Datenträger bleibt unangetastet — Buffer-Schließen und Datei-Löschen sind in Emacs zwei strikt getrennte Operationen. Wer eine Datei wirklich loswerden will, nutzt M-x delete-file oder den Befehl d/x in Dired.
Indirekte Buffer teilen Inhalt, nicht Konfiguration
Zwei indirekte Buffer auf demselben Text haben eigenen Major-Mode, eigenes Narrowing, eigenen Point. Geteilt wird nur der Textinhalt. Das ist die Grundlage für „zwei Sichten, ein Text"-Workflows — perfekt für lange Org-Dokumente oder parallele Outline-Ansichten.
Weiterführende Ressourcen
Externe Quellen
- GNU Emacs Manual — Buffers — offizielle Einführung in das Buffer-Konzept aus User-Sicht.
- Emacs Lisp Reference Manual — Buffers — die vollständige programmatische Buffer-API für Elisp-Hacker.
- GNU Emacs Manual — Kill Buffer — Details zu
kill-buffer, modifizierten Buffern und Sicherheits-Abfragen. - GNU Emacs Manual — Uniquify — Konfigurations-Optionen für sprechende Buffer-Namen statt
<2>,<3>. - Mastering Emacs — Introduction to Buffers — pragmatische Vertiefung mit vielen Workflow-Tipps.