Emacs als Markdown-Editor
Wer mein Linux-Buch gelesen hat weiß, dass ich nicht im Vi-Lager zuhause bin, sondern zu den Emacs-Fans zähle. Beim Programmieren verwende ich diverse Editoren und IDEs, von VSCode über IntelliJ bis hin zu Xcode. Aber längere Texte (sprich: Bücher) schreibe ich seit Jahrzehnten ausschließlich mit dem Emacs. Ich habe ein paar halbherzige Versuche mit anderen Editoren gemacht, aber ich bin immer wieder zurückgekommen.
Meine Emacs-Liebe hat weniger mit der Großartigkeit dieses Programms zu tun als viel mehr damit, dass ich mir im Laufe der Zeit ein eigenes Setup mit Tastenkürzeln und Zusatzfunktionen gebastelt habe. Davon bin ich jetzt abhängig, meine Finger wollen sich nicht mehr umgewöhnen.

Die Motivation für diesen Blogbeitrag ist die immer wiederkehrende Frage, womit ich meine Markdown-Texte verfasse. Vielleicht finden andere Emacs-Fans in der nachfolgenden .emacs-Datei Ideen, die sie noch nicht kennen; vielleicht schreibt mir auch jemand im Forum, welches Feature ich bisher übersehen habe.
Dieser Beitrag ist aber keinesfalls ein Versuch, Sie vom Emacs zu überzeugen. Ein Neustart heute bei Null — da würde ich höchstwahrscheinlich bei einem deutlich moderneren Programm landen (möglicherweise bei zed). Dieser Text will Ihnen auch nicht meine Tastenkürzel aufzwingen. Die sind im Laufe der Zeit eher zufällig entstanden. Aber dieser Teil von .emacs lässt sich ja am einfachsten anpassen.
Die Datei .emacs
Die Konfiguration des Emacs erfolgt in der Datei .emacs. Die Anweisungen dort müssen in der Programmiersprache Elisp formuliert werden. Das ist die Emacs-Variante der heute ansonsten kaum noch gebräuchlichen Sprache Lisp. Früher war Elisp eine Hürde für viele Emacs-Einsteiger, und in einigen frühen Auflagen meines Linux-Buchs hatte ich sogar ein kurzes Elisp-Kapitel untergebracht. Heute sagen Sie Claude oder einem anderen KI-Tool, was Sie erreichen wollen, schon bekommen Sie den erforderlichen Code. (Manchmal klappt es erst im zweiten oder dritten Versuch.) Dank KI ist die Elisp-Syntaxhürde also überwunden.
Der Emacs liest .emacs automatisch beim Start. Spätere Änderungen gelten daher erst mit dem nächsten Start oder indem Sie die geänderten Zeilen markieren und mit Alt+X eval-region Return ausführen.
Meine Konfiguration
Die ersten Zeilen im folgenden Listing aktivieren einige allgemeine Einstellungen. cua-mode erlaubt die vertrauten Tastenkürzel Strg+C, Strg+X und Strg+V für Kopieren, Ausschneiden und Einfügen. Im originalen Emacs gibt es dafür andere Kürzel, die parallel aktiv bleiben. save-place-mode bewirkt, dass der Emacs die letzte Cursor-Position in jeder geöffneten Datei dauerhaft speichert. Damit das Arbeitsverzeichnis nicht mit Backup-Dateien übersät wird, landen Emacs-Backups gesammelt in ~/.emacs.d/backups/.
Moderne Emacs-Konfigurationen laden Erweiterungspakete über package.el nach. Das Standard-Repository des Emacs enthält nur wenige Pakete; deshalb binde ich MELPA ein, das mit Abstand größte Community-Repository mit Tausenden von Erweiterungen. Beim ersten Start auf einem neuen Rechner aktualisiert der Emacs automatisch die Paketliste (package-refresh-contents), sodass alle benötigten Pakete sofort installiert werden können.
Das Makro use-package bündelt je ein Paket zusammen mit seiner Konfiguration, Hooks und Tastenkürzel-Bindungen in einem einzigen Block. Die Einstellung use-package-always-ensure t sorgt dafür, dass fehlende Pakete automatisch nachinstalliert werden, ohne manuelles Eingreifen.
Der markdown-mode aus dem gleichnamigen Paket steht im Zentrum des Setups. Der Modus hebt Markdown-Syntax farbig hervor und aktiviert über Hooks mehrere Begleitmodi: visual-line-mode sorgt für weiche Zeilenumbrüche ohne harte Zeilenenden in der Datei, display-line-numbers-mode blendet Zeilennummern ein, und visual-fill-column-mode begrenzt die Textbreite auf 100 Zeichen.
adaptive-wrap ist ein kleines, aber feines Detail: Wenn eine Zeile weich umgebrochen wird, rückt die Folgezeile so ein, dass Listenelemente (* oder -) korrekt untereinander ausgerichtet bleiben. unfill ergänzt den eingebauten Befehl fill-paragraph (bei mir F4): Statt einen Absatz auf mehrere kurze Zeilen zu verteilen, fasst unfill-paragraph alle Zeilen eines Absatzes wieder zu einer einzigen langen Zeile zusammen. Das ist hilfreich, wenn Markdown-Quellen von anderen Tools weiterverarbeitet werden.
Das Paket vertico erweitert den Emacs-Minibuffer um eine vertikale Auswahlliste (siehe den folgenden Screenshot). Beim Wechsel zwischen Buffern (F1) sehe ich alle offenen Dateien auf einen Blick inklusive Dateigröße, Modus und Pfad — letzteres dank marginalia, das die Listeneinträge um nützliche Zusatzinformationen ergänzt. orderless macht die Suche komfortabler: Ich kann mehrere Suchbegriffe mit Leerzeichen trennen und in beliebiger Reihenfolge eingeben.
Die benutzerdefinierte vertico-sort-override-function ändert die Sortierreihenfolge im Buffer-Switcher: Statt alphabetischer Reihenfolge erscheinen die zuletzt verwendeten Buffer ganz oben in der Liste. Bei vielen Dateien finde ich die zuletzt verwendeten Datei schneller.
swap-char (F11) vertauscht die zwei Zeichen an der Cursor-Position. Tippfehler wie getsern statt gestern lassen sich damit sofort korrigieren: Cursor auf das erste falsche Zeichen, einmal F11, fertig.
change-case (F12) wechselt die Groß- bzw. Kleinschreibung des Zeichens unter dem Cursor. change-word-case (F9) tut dasselbe für den ersten Buchstaben des aktuellen Worts, unabhängig davon, wo im Wort der Cursor gerade steht.
point-to-register-1 (F5) / jump-to-register-1 (F6): Mit F5 speichere ich die aktuelle Position, mit F6 springe ich dorthin zurück. Beim Sprung wird gleichzeitig die neue Position gespeichert, sodass ich mit wiederholten F6-Drücken zwischen zwei weit entfernten Textstellen hin- und herspringen kann. Ich finde das praktisch, wenn ich parallel an zwei Stellen eines langen Dokuments arbeite.
expand-abbrev-or-dabbrev (F3) versucht zunächst, eine gespeicherte Abkürzung zu expandieren. In .abbrevs_defs habe ich einige solche Abkürzungen gespeichert, z.B. ms für »Microsoft« oder rhel für »Red Hat Enterprise Linux«. Falls keine passt, greift dabbrev-expand und vervollständigt das angefangene Wort anhand von Vorkommen im selben Buffer. Praktisch für lange Schlüsselwörter.
Beim Einlesen der .emacs-Datei lädt der Editor automatisch alle erforderlichen Pakete herunter. Wenn dabei Download-Fehler auftreten, müssen Sie eventuell den MELPA-Cache aktualisieren. Dazu führen Sie Alt+X package-refresh-contents Return aus und starten den Emacs dann neu.
;; Datei ~/.emacs
;; ======== Grundeinstellungen ====================================
(cua-mode 1) ;Cut&Paste mit Strg+C/X/V
(setq inhibit-startup-message t) ;kein Emacs-Startbildschirm
(setq screen-preserve-screen-position t) ;zurück zur letzten Zeile
(setq scroll-step 5) ;bei Scrollen Sprünge von 5 Zeilen
(column-number-mode 1) ; ... Spaltennummern in der Statusleiste
(abbrev-mode 0) ;kein automatisches expand-abbrev
(setq require-final-newline t) ;letzte Zeile automatisch mit Return abschließen
(save-place-mode) ;Cursor-Position innerhalb der Datei merken
;; automatische Backups nicht im lokalen Verzeichnis, sondern in ~/.emacs.d/backups/
(setq backup-directory-alist
`(("." . ,(concat user-emacs-directory "backups"))))
(setq auto-save-file-name-transforms
`((".*" ,(concat user-emacs-directory "backups/") t)))
;; Spaltenbreite für Zeilennummern (nur Markdown)
(setq-default display-line-numbers-width 4)
;; Abkürzungstabelle automatisch laden und speichern
;; Falls ~/.abbrev_defs nicht existiert, leere Datei anlegen (kein Fehler)
(let ((abbrev-file "~/.abbrev_defs"))
(unless (file-exists-p abbrev-file)
(write-region "" nil abbrev-file))
(read-abbrev-file abbrev-file))
(setq save-abbrevs t) ;automat. speichern
;; ======== Packages ================================================
;; package.el initialisieren und MELPA-Repo hinzufügen (falls erforderlich)
(require 'package)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
(package-initialize)
;; Paket-Repo aktualisieren (first run / new machine)
(when (not package-archive-contents)
(package-refresh-contents))
;; alle erforderlichen Pakete automatisch laden
(unless (package-installed-p 'use-package)
(package-install 'use-package))
(require 'use-package)
(setq use-package-always-ensure t)
;; scratch-Buffer automatisch speichern (https://github.com/Fanael/persistent-scratch)
(use-package persistent-scratch
:config
(persistent-scratch-setup-default))
;; weiche Zeilenumbrüche mit Einrückung bei Listen etc.
(use-package adaptive-wrap
:hook (visual-line-mode . adaptive-wrap-prefix-mode))
;; Spalte mit Zeilennummern / zentrierter Text
(use-package visual-fill-column
:hook (markdown-mode . visual-fill-column-mode)
:config
(setq-default visual-fill-column-width 100)
(setq visual-fill-column-width 100))
;; Markdown-Modus
(use-package markdown-mode
:mode (("\\.text\\'" . markdown-mode)
("\\.md\\'" . markdown-mode))
:hook ((markdown-mode . visual-line-mode) ; soft-wrap long lines
(markdown-mode . display-line-numbers-mode) ; show line numbers
(markdown-mode . visual-fill-column-mode) ; center text within column width
(markdown-mode . (lambda () (setq fill-column 79))))) ; hard-wrap at 79 chars
;; Unfill: mehrzeilige Absätze zu einer langen Zeile verbinden (Shift+F4)
(use-package unfill)
;; mehr Komfort im Minibuffer
(use-package vertico
:config
(vertico-mode 1)
; sort buffer list by 'recently shown'
(setq vertico-sort-override-function
(lambda (candidates)
(if (eq minibuffer-history-variable 'buffer-name-history)
(let ((hist (symbol-value minibuffer-history-variable)))
(sort candidates
(lambda (a b)
(let ((pa (or (cl-position a hist :test #'equal) most-positive-fixnum))
(pb (or (cl-position b hist :test #'equal) most-positive-fixnum)))
(< pa pb)))))
candidates))))
(use-package orderless
:config
(setq completion-styles '(orderless basic)))
(use-package marginalia
:config
(marginalia-mode 1))
;; schönere Statuszeile (setzt voraus, dass die JetBrains Nerd Fonts
;; installiert und als Emacs-Font verwendet werden)
(use-package nerd-icons
:config
(setq nerd-icons-font-family "JetBrainsMono Nerd Font"))
(use-package doom-modeline
:after nerd-icons
:config
(doom-modeline-mode 1)
(setq doom-modeline-height 25)
(setq doom-modeline-icon t))
;; Ligaturen (setzt ebenfalls einen Nerd Font voraus)
(use-package ligature
:config
(ligature-set-ligatures 't '("!=" "!==" "->" "<-" "=>" "<=>" ">=" "<=" "//"))
(global-ligature-mode t))
;; ======== Farben ================================================
(set-face-attribute 'line-number nil
:height 0.8 :foreground "#ffffff" :background "#dddddd")
(set-face-attribute 'link nil
:foreground "RoyalBlue3" :underline nil)
;; für Markdown-Modus
(with-eval-after-load 'markdown-mode
(set-face-attribute 'markdown-italic-face nil
:inherit 'italic :foreground "dark magenta" :slant 'italic)
(set-face-attribute 'markdown-pre-face nil
:inherit 'font-lock-constant-face))
(with-eval-after-load 'doom-modeline
(set-face-attribute 'doom-modeline-buffer-modified nil
:foreground "firebrick" :weight 'bold))
;; ======== eigene Funktionen ===================================================
(defun expand-abbrev-or-dabbrev () ;Expansion von Abkürzung: F3
(interactive)
(unless (expand-abbrev) ;falls keine Abkürzung existiert
(dabbrev-expand nil))) ;dynamische Expansion
(defvar my-point-register 1
"Hilfsvariable für jump-to-register-1: merkt sich, welches Register aktiv ist.")
(defun point-to-register-1 () ;Position in Reg. 1 speichern: F5
(interactive)
(setq my-point-register 1)
(point-to-register 1))
(defun jump-to-register-1 () ;Position wechseln: F6
(interactive) ;springt zur Position, die mit F5
(if (= my-point-register 1) ; gespeichert wurde ...
(progn
(setq my-point-register 2)
(point-to-register 2)
(jump-to-register 1))
(progn
(setq my-point-register 1)
(point-to-register 1)
(jump-to-register 2))))
(defun swap-char () ;zwei Buchstaben an der Cursor-Position
(interactive) ;vertauschen: F11
(save-excursion
(forward-char)
(transpose-chars 1)))
(defun change-case () ;Groß- und Kleinschreibung des Zeichens
(interactive) ;an der Cursorposition ändern: F12
(let ((zeichen (char-after (point))))
(if (> zeichen 64)
(progn
(setq zeichen (logxor zeichen 32))
(insert-char zeichen 1)
(delete-char 1))
(forward-char 1))))
(defun change-word-case () ;Groß- und Kleinschreibung des ersten
(interactive) ;Zeichens eines Worts verändern: F9
(point-to-register 2)
(backward-word 1)
(change-case)
(jump-to-register 2))
(defun unfill-paragraph-and-advance () ;Absatz zusammenfügen und zum nächsten springen: S-F4
(interactive)
(unfill-paragraph)
(forward-paragraph)
(skip-chars-forward "\n")
(recenter))
(defun toggle-fill-column-width () ;Zeilenumbruch zwischen 100 und 1000 Zeichen wechseln
(interactive)
(setq-local visual-fill-column-width
(if (eq visual-fill-column-width 100) 1000 100))
(visual-fill-column-mode 1))
;; ======== Tastenkürzel ======================================================
(global-set-key [f1] 'switch-to-buffer) ;F1 Buffer wechseln
(global-set-key [f2] 'other-window) ;F2 Fenster wechseln
(global-set-key [f3] 'expand-abbrev-or-dabbrev) ;F3 Abkürzung erweitern
(global-set-key [f4] 'fill-paragraph) ;F4 Absatz umbrechen
(global-set-key [S-f4] 'unfill-paragraph-and-advance) ;S-F4 Absatz zusammenfügen + nächster
(global-set-key [f5] 'point-to-register-1) ;F5 Position speichern
(global-set-key [f6] 'jump-to-register-1) ;F6 zu Position springen
(global-set-key [f7] 'goto-line) ;F7 goto line
(global-set-key [f8] 'toggle-fill-column-width) ;F8 kurze/lange Zeilen
(global-set-key [f9] 'change-word-case) ;F9 Groß/Klein Wort
(global-set-key [f10] 'undo) ;F10 Undo
(global-set-key [f11] 'swap-char) ;F11 Buchst. vertauschen
(global-set-key [f12] 'change-case) ;F12 Groß-/Klein ändern
;; Mac-Tastatur: fn+ctrl+cursor to start/end of buffer
(global-set-key [C-prior] 'beginning-of-buffer)
(global-set-key [C-next] 'end-of-buffer)
;; Guillemets-Eingabe mit Alt+Q / Shift+Alt+Q
(defun insert-guillemot1 ()
(interactive)
(insert "«"))
(defun insert-guillemot2 ()
(interactive)
(insert "»"))
(global-set-key [?\M-q] 'insert-guillemot1) ;Alt+Q: «
(global-set-key [?\M-Q] 'insert-guillemot2) ;Shift+Alt+Q: »
;; macOS: rechte Alt-Taste zur Eingabe von Sonderzeichen wie @ oder € verwenden
(when (eq system-type 'darwin)
(setq mac-right-option-modifier nil) ; LeftAlt + L -> @ etc.
)
Quellen / Links
Die oben abgedruckte Datei können Sie als dotemacs.txt herunterladen.
- https://www.gnu.org/software/emacs/
- https://www.gnu.org/software/emacs/documentation.html
- https://www.gnu.org/software/emacs/manual/html_node/eintr/
- https://www.emacswiki.org
- https://github.com/chrisdone-archive/elisp-guide (Elisp Guide)
- https://en.wikipedia.org/wiki/Lisp_(programming_language)
- https://melpa.org/ (Erweiterungspakete)
- https://github.com/doomemacs/doomemacs (Emacs-Statuszeile)
Andere .emacs-Beispiele

KDE treibt den Wechsel zu Wayland voran und bestätigt den Abschied von X11 in Plasma 6.8. Die aktuelle Nutzung zeigt eine deutliche Tendenz. Die Entwickler bereiten Plasma 6.7 als letzte Version mit X11 Unterstützung vor. Danach beginnt die Entfernung des alten Codes und die Optimierung der modernen Umgebung. Der Schritt soll die Wartung vereinfachen und […]
Das COSMIC Team arbeitet an einem neuen Frosted Glass Effekt, der bald im Desktop landen könnte. Die Optik erinnert an frühere transparente Designs und wirkt bereits erstaunlich ausgereift. System76 Chef Carl Richell gab auf X einen kurzen Einblick in den aktuellen Stand. Er erklärte, dass der Effekt bewusst dezent startet. Nutzer können die Intensität später […]
IBM und Red Hat starten mit Project Lightwell eine große Sicherheitsinitiative. Das Vorhaben soll offene Software besser schützen und Unternehmen verlässliche Updates liefern. Im Zentrum steht ein vertrauenswürdiges Clearinghouse, das sensible Sicherheitsmeldungen bündelt. Firmen können dort entdeckte Schwachstellen einreichen. IBM prüft gemeldete Fehler mit KI Unterstützung und erstellt geprüfte Korrekturen. Diese Patches decken nicht nur […]
Euro Office steht kurz vor dem offiziellen Start und erscheint am 9. Juni als stabile Version. Das Projekt soll Europas Abhängigkeit von großen US Diensten verringern. Nextcloud und IONOS treiben die Entwicklung gemeinsam voran. Beide wollen eine verlässliche Office Lösung bieten, die sich gut in bestehende Plattformen einfügt. Die Suite wird direkt in Nextcloud Hub […]
KDE Linux konnte im Mai spürbare Schritte nach vorne machen und gewinnt an Struktur. Das Projekt stärkt seine Grundlagen und bringt mehr Kontrolle in Aufbau und Pflege des Systems. Die Entwickler setzen nun auf den eigenen kde‑builder, um KDE Software direkt zu kompilieren. Das frühere Erstellen von Arch‑Paketen entfällt damit. Die Distribution bleibt zwar technisch […]
Der Linux Coffee Talk, das lockere Format rund um Linux, Open Source und Technik im Alltag. Ohne Hype, ohne Clickbait, dafür mit echten Einordnungen der Meldungen, Meinungen und einem Überblick über die wichtigsten FOSS-/Linux-News aus Mai 2026. Wir sprechen über Distributionen, Tools, Datenschutz, Nerd-Themen und alles, was uns Linux-User bewegt. Perfekt für alle, die stets […]
Flatpak könnte künftig stärker auf systemd Services setzen. Diese mögliche Richtung sorgt bei vielen Nutzern für Diskussionen. Besonders betroffen wären Distributionen ohne systemd Unterstützung. Die Entwickler arbeiten derzeit an einer neuen Architektur. Sie nennen das Konzept „Flatpak Next-Generation Sandboxing“ und prüfen grundlegende Änderungen. Ziel ist eine stabilere Verwaltung laufender Anwendungen. Auch die Integration moderner Desktop […]
Linux steht für Freiheit und Vielfalt an Linux Distributionen. Doch die wachsende Zahl an Distributionen wirft eine alte Frage neu auf. Hilft diese Auswahl wirklich jedem oder entsteht ein Effekt, der eher bremst als befreit. Viele Nutzer lieben die große Auswahl, doch andere fühlen sich schnell allein gelassen oder gar überfordert. Neue Distros erscheinen fast […]
AlmaLinux 10.2 erscheint als stabile Ausgabe und setzt auf Linux Kernel 6.12. Die neue Version basiert auf RHEL 10.2 erweitert den Funktionsumfang deutlich und stärkt die Unterstützung älterer Hardware. Besonders spannend ist die Rückkehr klassischer Treiber und die Einführung von i686 Paketen für 32 Bit Software. Die Distribution bietet nun Btrfs Boot Support. Damit lassen […]
Die Diskussion um neue Altersprüfgesetze sorgt seit Monaten für Unruhe in der Open Source Welt. Nun bewegen sich Kalifornien und Colorado und schaffen klare Ausnahmen für freie Betriebssysteme und Community Software. Beide US Bundesstaaten reagieren damit auf deutliche Kritik aus der Linux Gemeinschaft. Kalifornien arbeitet derzeit an einer Anpassung des Digital Age Assurance Act. Der […]
MX Linux 25.2 erscheint als aktualisierte Ausgabe und setzt auf eine stabile Basis. Die neue Version der MX Linux 25 Serie nutzt Debian 13.5 und liefert aktuelle Pakete. Die AHS Variante setzt auf Linux 7.0 und richtet sich an Nutzer mit neuer Hardware. Die regulären Ausgaben verwenden den Debian Kernel 6.12. Die AHS Edition mit […]
Linux Mint gibt einen frühen Ausblick auf die kommenden Verbesserungen für die nächste Ausgabe. Die Entwickler arbeiten an spürbar schnellerer Dateiverwaltung und neuen Werkzeugen für den Alltag. Nemo reagiert nun flotter auf Eingaben. Der Dateimanager passt seine Darstellung dynamisch an und zeigt viele Ordner sofort. Die bisherige Verzögerung fällt damit in vielen Fällen weg. Auch […]
Fedora verabschiedet sich vom Deepin Desktop Environment (DDE). Die Entscheidung folgt einer langen Reihe technischer Warnsignale und fehlender Pflege durch das verbliebene Entwicklerteam. FESCo, das zentrale technische Gremium des Projekts, stimmte dem Vorschlag zu, nachdem wiederholte Hinweise auf ungeprüfte sicherheitsrelevante Komponenten aufkamen. Besonders betroffen waren der Dateimanager und mehrere Dienste, die sensible Schnittstellen nutzten. Fedora […]
Die Linux Firmware Landschaft erhält neuen Rückenwind. HP unterstützt nun als weiterer Premier Sponsor den Linux Vendor Firmware Service (LVFS) und reiht sich damit neben Dell und Lenovo ein. Das Projekt gewinnt damit einen weiteren großen Hersteller, der die Zukunft sicherer Firmware Updates auf Linux Systemen aktiv mitgestaltet. Hinter dem Dienst steht die bekannte fwupd […]
Mozilla liefert mit Firefox 151 ein Update, das viele Bereiche verbessert. Die größte Neuerung betrifft den integrierten PDF Viewer. Nutzer können nun mehrere PDFs direkt im Browser zusammenführen. Externe Werkzeuge werden dafür nicht mehr benötigt. Diese Funktion stärkt den praktischen Nutzen des Browsers deutlich und macht alltägliche Aufgaben einfacher. Linux und macOS erhalten lokale Profil […]
Red Hat stellt zwei neue Versionen seiner Unternehmensdistribution vor. RHEL 10.2 und RHEL 9.8 setzen stark auf moderne KI Werkzeuge. Im Mittelpunkt steht der neue Goose Assistent, der direkt im Terminal hilft. Goose nutzt MCP Integration und liefert farblich verbesserte Ausgaben. Red Hat verspricht schnellere Problemlösungen und einen leichteren Einstieg für neue Administratoren. Beide Versionen […]