Meine Vim-Kenntnisse nach einem Jahr

Lesezeit: 10 Minuten

Blog Post Cover

Seit ungefähr einem Jahr beschäftige ich mich nun mit Vim. Angefangen hat alles mit einer internen Linux-Schulung und dem Vorsatz, dem etwas eigenwilligen Texteditor zumindest einen Monat lang eine ehrliche Chance zu geben. Aus dem Monat ist mittlerweile ein Jahr geworden. In dieser Zeit habe ich Learning the vi and Vim Editors von Arnold Robbins und Elbert Hannah gelesen, zahlreiche Videos zu Vim und Neovim geschaut und vor allem viel ausprobiert.

Dieser Artikel soll weder ein Vim-Tutorial noch eine vollständige Auflistung aller Funktionen werden. Dafür gibt es das Benutzerhandbuch – und Menschen, die Vim bereits seit mehreren Jahrzehnten verwenden. Ich möchte stattdessen festhalten, wie ich Vim nach meinem ersten Jahr tatsächlich nutze: Welche Befehle sind bereits ins Muskelgedächtnis übergegangen? Welche Konzepte finde ich besonders nützlich? Und von welchen Funktionen weiß ich zwar, denke im entscheidenden Moment aber trotzdem nicht daran?

Der Text ist damit vor allem eine Momentaufnahme. Vermutlich werde ich einige der folgenden Gewohnheiten in ein paar Jahren umständlich oder sogar ziemlich unsinnig finden. Genau deshalb möchte ich sie aufschreiben.

Vom File Tree zur direkten Suche

Beginnen wir mit der Navigation zwischen Dateien. Aktuell arbeite ich noch recht häufig mit einem klassischen File Tree. Dafür nutze ich netrw, den eingebauten, vielleicht etwas angestaubten Dateiexplorer von Vim. Mit der Taste - öffne ich das Verzeichnis der aktuellen Datei und kann mich von dort durch das Projekt bewegen. - fühlt sich für mich am intuitivsten an, weil die Standard-Taste, mit der man in netrw eine Ebene nach oben springt, ebenfalls - ist.

netrw in Action

Für meinen Bedarf ist netrw vollkommen ausreichend. Natürlich gibt es interessante Alternativen wie oil.nvim, mit denen man ein Verzeichnis wie einen normalen Buffer bearbeiten kann. Dateien lassen sich dann ähnlich verschieben, umbenennen oder löschen wie gewöhnlicher Text. Das finde ich durchaus spannend. Trotzdem versuche ich bei grundlegenden Funktionen möglichst nah am Standard zu bleiben. In meinem Arbeitsalltag hantiere ich regelmäßig auf Servern, auf denen nur Vim oder teilweise sogar nur vi installiert ist. Dort stehen mir keinerlei Plugins zur Verfügung.

Gleichzeitig versuche ich, den File Tree immer seltener zu verwenden. In einem bekannten Projekt weiß ich meist schon ungefähr, welche Datei ich suche. Dann ist es schneller, den Namen direkt über Telescope einzugeben, anstatt mich durch mehrere Verzeichnisse zu klicken. Mit find_files suche ich nach Dateien, mit live_grep nach Text im gesamten Projekt. Beides verwende ich täglich, obwohl es vermutlich nur einen kleinen Teil dessen abdeckt, was Telescope eigentlich kann.

Telescope in Action

Den File Tree nutze ich deshalb vor allem dann, wenn ich einen unbekannten Bereich des Projekts erkunden und dessen Struktur verstehen möchte. Für alles, was ich bereits kenne, greife ich zunehmend zur Suche. Die wenigen Dateien, zwischen denen ich während einer Aufgabe ständig hin- und herspringe, lege ich zusätzlich in Harpoon ab. So hat mittlerweile jedes Werkzeug eine recht klare Aufgabe: netrw zum Erkunden, Telescope zum Finden und Harpoon zum schnellen Wechseln.

Wie ich mich innerhalb einer Datei bewege

Bei Vim denkt man vermutlich zuerst an h, j, k und l. Tatsächlich verwende ich zumindest j und k weiterhin häufig, oft zusammen mit einem Count. Wenn das Ziel zehn Zeilen weiter unten liegt, tippe ich 10j, anstatt zehnmal dieselbe Taste zu drücken. Relative Zeilennummern sind dafür aus meiner Sicht unverzichtbar. Ohne sie müsste ich den Abstand entweder selbst zählen oder im Kopf subtrahieren – beides möchte ich beim Programmieren eher nicht tun.

Noch häufiger nutze ich allerdings Ctrl-d und Ctrl-u, um jeweils eine halbe Bildschirmseite nach unten oder oben zu springen. Für den Anfang und das Ende einer Datei sind gg und G inzwischen ebenfalls vollständig ins Muskelgedächtnis übergegangen.

Wenn das Ziel nicht sichtbar ist, suche ich meistens mit /. Selbst bei vergleichsweise kurzen Distanzen ist das für mich oft schneller, als mich mit mehreren Bewegungsbefehlen dorthin vorzuarbeiten. f verwende ich ebenfalls, allerdings deutlich seltener. Interessanterweise muss ich bei den jeweiligen Wiederholungsbefehlen manchmal noch kurz überlegen: War es jetzt n für den nächsten Suchtreffer oder ; für die nächste Fundstelle von f? Die rückwärts gerichteten Varianten ? und F verwende ich so gut wie nie. Offenbar ist es für mich einfacher, ein paar Zeichen zu weit zu springen und dann zurückzugehen, als von Anfang an in die andere Richtung zu suchen.

Marks sind ein weiteres Konzept, das ich theoretisch nützlich finde. Mit ma lässt sich eine Position markieren, mit `a kann man später exakt dorthin zurückspringen. In der Praxis denke ich nur selten daran. Ähnlich geht es mir mit der Jump List.

Wie ich Text bearbeite

Der Moment, in dem Vim für mich wirklich Sinn ergab, hatte weniger mit der Navigation als mit Text Objects zu tun. Kombinationen wie ciw, ci" oder ci( gehören mittlerweile zu meinen meistgenutzten Befehlen. Ich muss nicht erst ein Wort oder den Inhalt einer Klammer markieren und danach löschen. Stattdessen beschreibe ich direkt, was ich ändern möchte.

Genau darin liegt für mich weiterhin die größte Stärke von Vim. Die einzelnen Befehle lassen sich wie Bestandteile einer Sprache kombinieren. c steht für change, i für inside und w für word. Aus drei kleinen Bausteinen wird „ändere den Inhalt dieses Wortes“. Dasselbe Prinzip funktioniert mit Anführungszeichen, Klammern, Absätzen und zahlreichen anderen Textbereichen. Irgendwann hört man auf, die einzelnen Buchstaben bewusst zu übersetzen.

Daneben besteht mein Alltag aus ziemlich unspektakulären Befehlen: yy zum Kopieren einer Zeile, dd zum Löschen und p zum Einfügen. Gerade diese einfachen Kombinationen zeigen aber gut, warum sich Vim nach einiger Zeit so flüssig anfühlt. Für viele kleine Änderungen muss ich weder etwas markieren noch die Hände von ihrer normalen Position auf der Tastatur wegbewegen.

Eine Funktion, die ich erst kürzlich gelernt habe, ist gq. Damit lässt sich Text neu formatieren und entsprechend der eingestellten Textbreite umbrechen. Bei Markdown-Dateien verwende ich beispielsweise gqap: gq around paragraph, sprich den aktuellen Absatz formatieren.

Der unterschätzte Punkt

Einer meiner liebsten Vim-Befehle ist der Punkt .. Er wiederholt die letzte Änderung. Das klingt zunächst nicht besonders spektakulär, lässt sich aber mit fast allem kombinieren.

Möchte ich beispielsweise dasselbe Wort an mehreren Stellen ändern, suche ich nach dem ersten Vorkommen, ändere es mit ciw, springe mit n zum nächsten Treffer und wiederhole die Änderung mit .. Danach wechseln sich nur noch n und . ab. Ich verwende den Punkt bereits regelmäßig und habe trotzdem das Gefühl, sein Potenzial noch nicht vollständig auszunutzen. Häufig bemerke ich erst im Nachhinein, dass ich eine Änderung so wesentlich einfacher hätte wiederholen können.

Macros verfolgen eine ähnliche Idee, gehen aber noch einen Schritt weiter. Eine ganze Folge von Befehlen lässt sich aufzeichnen und anschließend beliebig oft abspielen. Wenn ich ein passendes Problem erkenne, sind Macros äußerst praktisch. Das Erkennen ist allerdings der schwierige Teil. Meist beginne ich eine Änderung von Hand und stelle erst beim fünften Durchlauf fest, dass ein Macro sinnvoll gewesen wäre.

Vim und die Kommandozeile

Ein größerer Teil von Learning the vi and Vim Editors beschäftigt sich mit dem Ex-Editor, der noch immer unter der Oberfläche von Vim steckt. Vor dem Buch war die kleine Kommandozeile, die nach einem Doppelpunkt erscheint, für mich hauptsächlich der Ort für :w, :q und gelegentlich :split. Inzwischen verstehe ich deutlich besser, wie Bereiche, Befehle und reguläre Ausdrücke dort zusammenspielen.

Besonders häufig nutze ich Suchen und Ersetzen. Mit :%s/search/replace/gc gehe ich durch alle Treffer einer Datei und bestätige jede Ersetzung einzeln. Das c am Ende ist für mich wichtig, weil ich so nicht blind jede Fundstelle verändere. Gleichzeitig hat mich die Verwendung von :s endlich dazu gezwungen, reguläre Ausdrücke vernünftig zu lernen, anstatt deren Syntax jedes Mal neu nachzuschlagen.

Noch interessanter finde ich die Verbindung zur Linux-Kommandozeile. Mit :! kann Vim praktisch jedes verfügbare Kommando ausführen. Ein markierter Bereich lässt sich mit !sort direkt durch sort schicken; die Ausgabe ersetzt anschließend den ursprünglichen Text. Mit :r !command landet die Ausgabe eines Befehls direkt in der aktuellen Datei. Dadurch stehen nicht nur die Funktionen des Editors zur Verfügung, sondern auch Werkzeuge wie sort, jq oder column.

Wenn ich die Shell doch einmal direkt benötige, lege ich Neovim mit Ctrl-z in den Hintergrund. Nach dem Shell-Befehl bringt mich fg zurück in den Editor. Diese enge Verbindung zwischen Editor und Kommandozeile ist eine der Eigenschaften, die ich an Vim besonders mag. Viele grafische Editoren können externe Programme natürlich ebenfalls ausführen. In Vim fühlt es sich jedoch wie ein natürlicher Bestandteil des Editors an und nicht wie eine nachträglich angebaute Funktion.

Mein aktueller Werkzeugkasten

Neovim selbst bildet nur die Grundlage meines Setups. Einige Plugins möchte ich inzwischen nicht mehr missen. Telescope, Harpoon und netrw habe ich bereits erwähnt. Für die Arbeit mit Git verwende ich täglich Lazygit, das ich direkt aus Neovim heraus öffne.

Lazygit in Action

Lazygit nimmt mir viele wiederkehrende Git-Befehle ab, ohne vollständig zu verbergen, was im Hintergrund passiert. Jede Aktion wird in einen normalen Git-Befehl übersetzt und im Command Log angezeigt. Dadurch kann ich bequem arbeiten und lerne nebenbei weiterhin etwas über Git. Diese Kombination gefällt mir deutlich besser als grafische Oberflächen, bei denen kaum nachvollziehbar ist, welcher Befehl gerade ausgeführt wurde.

Daneben kümmert sich mein Setup um LSP, Autovervollständigung, Formatierung, Linting und Debugging. Meine vollständige Konfiguration liegt öffentlich in meinen Dotfiles. Sie verändert sich weiterhin regelmäßig. Gerade das ist einer der Gründe, weshalb ich meine Lua-Kenntnisse ausbauen möchte: Ich will die Konfiguration nicht nur aus Beispielen zusammensetzen, sondern besser verstehen und gezielter an meinen Workflow anpassen können.

Was ich kenne, aber kaum verwende

Ein Jahr mit Vim reicht problemlos aus, um mehr Funktionen kennenzulernen, als man anschließend tatsächlich benutzt. Neben Marks und Macros betrifft das bei mir vor allem Registers außerhalb der System-Zwischenablage. Ich weiß, dass ich gelöschten oder kopierten Text gezielt in verschiedenen Registern ablegen und später wieder abrufen kann. In der Praxis verwende ich meistens trotzdem den einfachsten Weg.

Auch Folds mit zf, zo und zc habe ich ausprobiert, aber noch nicht in meinen Alltag integriert. Dasselbe gilt für die eingebaute Insert-Mode-Completion über Ctrl-x, Abbreviations mit :ab, die Rechtschreibprüfung über :setlocal spell und die Command-History mit Ctrl-f. All diese Funktionen sind nützlich. Bisher sind die Situationen, in denen ich an sie denke, allerdings seltener als die Situationen, in denen ich sie gebrauchen könnte.

Außerdem begegnet mir in Videos regelmäßig :norm. Damit lässt sich ein Normal-Mode-Befehl auf einen ganzen Zeilenbereich anwenden. Das klingt genau nach einer Funktion, die ich sehr nützlich finden werde, sobald ich mich endlich ernsthaft damit beschäftige. Ähnlich sieht es mit dem gezielten Verschieben und Skalieren von Splits aus: Ich weiß, dass es geht, greife aber noch nicht selbstverständlich zu den passenden Befehlen.

In einem Jahr kann ich diesen Artikel erneut lesen und prüfen, was davon inzwischen sitzt. Vielleicht verwende ich dann Marks täglich, erledige Änderungen mit :norm, die ich heute noch einzeln vornehme, und schüttele über 0i den Kopf. Vielleicht hat sich auch kaum etwas verändert und ich arbeite weiterhin mit denselben zwanzig Befehlen.

Beides wäre in Ordnung. Vim zu lernen bedeutet für mich nicht, irgendwann jeden Befehl auswendig zu kennen. Es bedeutet, den eigenen Werkzeugkasten nach und nach zu erweitern – und gelegentlich festzustellen, dass eine Funktion, die man seit Monaten kennt, plötzlich im Muskelgedächtnis angekommen ist.