Wenn es einen einzigen Vim-Befehl gibt, der das ganze Bedien-Modell zusammenfasst, dann ist es der Punkt: . wiederholt den letzten Edit-Befehl. Klingt unspektakulär — wird aber zum mächtigsten Werkzeug im täglichen Edit-Workflow, sobald man die zugrunde liegende Designphilosophie versteht. Vim-Edits werden bewusst so klein und atomar formuliert, dass sie wiederholbar bleiben. Wer in dieser Logik denkt, ersetzt ganze Macro-Sequenzen oder mehrfache :substitute-Aufrufe durch zwei Tasten: n., n., n.. Dieser Artikel klärt, was Vim genau als „letzten Edit" zählt, zeigt den klassischen Such-Edit-Repeat-Loop, listet die Grenzen des Punkt-Befehls und führt das Plugin vim-repeat als Brücke ein.
Was Vim als „letzten Edit" zählt
. wiederholt die zuletzt ausgeführte Edit-Operation. Was Vim als eine solche Operation zählt, ist präzise definiert: alles, was zwischen dem Eintritt in einen Edit-Modus und der Rückkehr in den Normal-Mode passiert ist.
Konkret zählt zu einem Edit-Block:
- Ein Operator-Motion-Befehl wie
dw,c$,>ap,gUiw. - Ein Operator mit doppeltem Buchstaben für die ganze Zeile:
dd,yy,==. - Eine Insert-Mode-Sequenz von
i(odera,o,c{motion},s, ...) bis<Esc>. - Ein Einzel-Befehl wie
x,X,~,r<char>. - Eine Visual-Operation: Visual-Mode betreten, Bereich wählen, Operator drücken — wird als ein Block gespeichert.
Was nicht zählt:
- Reine Motions wie
j,w,gg,/pattern. Sie ändern den Buffer nicht und sind keine Edits. - Ex-Befehle wie
:w,:s/foo/bar/g,:!cmd. Sie haben eigene Wiederholungs-Mechanismen — siehe unten. - Undo/Redo (
u,<C-r>). Sie sind Meta-Operationen.
Diese Definition hat eine wichtige Konsequenz: . wiederholt nicht „die letzte Tastenfolge", sondern „die letzte buffer-verändernde Aktion". Wer zwischen zwei Edits navigiert oder eine Suche ausführt, ändert nichts an dem, was . wiederholen würde.
" 1. Edit: dw löscht ein Wort
dw
" 2. Motion: 5j springt fünf Zeilen runter
5j
" 3. . → wiederholt dw, NICHT 5j (Motion zählt nicht)
.
" 4. Edit: ciwNEU<Esc> ändert das innere Wort
ciw NEU<Esc>
" 5. Suche: /foo<CR>
/foo<CR>
" 6. . → wiederholt ciwNEU<Esc>, NICHT /foo
.Der klassische Such-Edit-Repeat-Loop
Der häufigste praktische Einsatz von . ist die Kombination mit Suche. Das Muster:
1. Mit /pattern an die erste Stelle springen.
2. Edit ausführen — typischerweise eine kompakte Operator-Object-Sequenz.
3. Mit n zur nächsten Trefferstelle.
4. Mit . den Edit wiederholen.
5. Wiederholen ab Punkt 3.
In Tasten ausgedrückt: /foo<CR> einmal, dann cw bar<Esc> n . n . n . für jede weitere Stelle. Die einzige Tipparbeit ist der erste Edit — danach sind es zwei Tasten pro Vorkommen.
" Aufgabe: in einer Datei alle Vorkommen von "TODO" durch "DONE" ersetzen,
" aber jedes Vorkommen einzeln kontrolliert.
/TODO<CR> " erste Stelle finden
cw DONE<Esc> " Wort ändern (change inner word — Stelle ändern)
n " nächste Stelle finden
. " denselben Edit wiederholen
n " nächste
. " wiederholen
" ... so weiter, bis Vim "search hit BOTTOM, continuing at TOP" sagtVergleich zu Alternativen:
:%s/TODO/DONE/gcwürde alle ersetzen mit interaktiver Bestätigung. Etwa gleich schnell, aber als Ex-Befehl in einer Pipeline weniger flexibel.:%s/TODO/DONE/gersetzt alle auf einmal. Schnellste Variante, aber keine Kontrolle über einzelne Stellen.- Klassisches IDE-Find-and-Replace mit Buttons. Vergleichbar in der Anzahl Aktionen, aber Mausoperationen statt Tastatur.
Der Vim-Way mit n. hat einen Vorteil, der erst beim zweiten Hinschauen sichtbar wird: du kannst zwischen Stellen entscheiden. Wenn die nächste Stelle nicht ersetzt werden soll, drückst du n (zur übernächsten), nicht .. Wenn dort ein anderer Edit nötig ist, machst du ihn, und ab dann wiederholt . den neuen Edit. Diese Flexibilität in der Mitte eines Massen-Edits hat kein :s-Befehl.
„Make the change easy to repeat"
Eine der zentralen Vim-Designphilosophien lautet: strukturiere Edits so, dass . sie reproduzieren kann. In der Praxis heißt das, einen Edit so kurz und atomar wie möglich zu formulieren — eine einzige Operator-Object-Kombi, gefolgt von Esc, ohne zwischendurch zu navigieren.
Ein konkretes Beispiel — Aufgabe: am Ende jeder Funktions-Zeile soll ein Kommentar // done ergänzt werden. Drei Lösungsansätze:
Variante A: nicht-idiomatisch
" Cursor in der ersten Funktions-Zeile
$a // done<Esc> " $ Sprung ans Zeilenende, a für Append, Text, Esc
" Zweite Funktion:
" Cursor manuell zur Zeile bewegen (Motions oder Suche)
$a // done<Esc> " gleiche Tastenfolge wiederDrei Probleme: jede Iteration ist 13 Tasten, der Cursor muss neu gesetzt werden, und das $a ist eine zusammengesetzte Sequenz, die nicht als atomarer Edit zählt — . würde nicht funktionieren wie erwartet.
Variante B: idiomatischer
" Cursor irgendwo in der Zeile
A // done<Esc> " A = Append am Zeilenende, Text, Esc
" Zur nächsten Funktions-Zeile (mit Suche oder Motion)
]m " z. B. nächste Funktion in C/Java
. " wiederholt A // done<Esc>
]m
.A ist ein einzelner Befehl, der „Insert am Zeilenende" als atomare Operation durchführt. A // done<Esc> zählt als ein Edit-Block und ist mit . reproduzierbar — egal wo der Cursor in der Zeile steht.
Variante C: vollständig idiomatisch mit Suche
" Mit Suche zur ersten passenden Zeile
/function<CR> " erste Funktion finden
A // done<Esc> " am Zeilenende ergänzen
" Loop:
n. " nächste Funktion, gleicher Edit
n.
n.Die Suche tut die Navigation, der Punkt tut den Edit. Zwei Tasten pro Iteration. Das ist der eigentliche Vim-Way — und Variante B/C unterscheiden sich konzeptionell signifikant von A.
Counts mit .
. respektiert Counts auf zwei Arten:
Der ursprüngliche Count wird übernommen
Wenn der letzte Edit einen Count enthielt, wiederholt . mit demselben Count:
3dw " drei Wörter löschen
. " noch drei Wörter löschen (insgesamt sechs)Ein neuer Count überschreibt
Wer vor . einen neuen Count drückt, ersetzt damit den alten:
3dw " drei Wörter löschen
5. " jetzt FÜNF Wörter löschen (nicht 5×3)
1. " jetzt EIN Wort löschenDas ist eine elegante Bequemlichkeit: ein zu großer ursprünglicher Count lässt sich beim Wiederholen ohne neue Operator-Motion-Eingabe verkleinern oder vergrößern.
Was . NICHT wiederholt
Drei Klassen von Operationen sind außerhalb von .:
Ex-Befehle haben eigene Wiederholungs-Mechanismen
. wiederholt keine Ex-Befehle. :s/foo/bar/ wird nicht durch . reproduziert. Für Ex-Befehle gibt es eigene Repeat-Tasten:
| Befehl | Wiederholung |
|---|---|
:s | & (gleicher Befehl, ohne Flags) oder :&& (mit gleichen Flags) |
: | @: führt den letzten Ex-Befehl nochmals aus |
//? | n (vorwärts) / N (rückwärts) für die Such-Wiederholung |
q-Macro | @@ wiederholt das letzte ausgeführte Macro |
& als Wiederholung für :s ist im Alltag sehr nützlich — eine schnelle Substitution kann mit & auf den nächsten Match in jeder Zeile angewendet werden, ohne den vollen :s-Befehl neu einzutippen.
Reine Motions zählen nicht als Edit
Wer j, gg, f( oder /pattern ausführt, ändert den Buffer nicht — . ignoriert diese Befehle vollständig. Erst der nächste echte Edit wird als „letzte Operation" gespeichert.
Plugin-Befehle: ja-nein-vielleicht
Plugins, die ihre Aktionen über :-Befehle oder Lua/Vimscript-Funktionen ausführen, sind für . per Default unsichtbar. Das gilt z. B. für viele klassische Vim-Operationen aus tpopes Sammlung — :Surround, :Commentary, :GitStatus. Genau dafür gibt es das Plugin vim-repeat, siehe nächster Abschnitt.
vim-repeat — die Brücke für Plugin-Edits
Das Plugin tpope/vim-repeat erweitert . um Plugin-Awareness. Es stellt eine kleine API bereit, mit der Plugins ihre Aktionen als „wiederholbar" markieren können. Sobald vim-repeat installiert ist und ein Plugin diese API nutzt, funktioniert . auch für Plugin-Befehle.
Die wichtigsten Plugins, die vim-repeat voraussetzen:
- vim-surround —
ysiw",cs"',ds(werden durch.wiederholbar. - vim-commentary —
gcc,gcapwerden wiederholbar. - vim-unimpaired — diverse
[.../]...-Bindings.
" Plugin-Setup mit vim-plug
call plug#begin()
Plug 'tpope/vim-repeat' " Voraussetzung — zuerst!
Plug 'tpope/vim-surround' " ysiw" und Co.
Plug 'tpope/vim-commentary' " gcc / gcap
call plug#end()Ohne vim-repeat würde z. B. ysiw" (mit vim-surround) das innere Wort in Anführungszeichen setzen — und . würde nicht funktionieren wie erwartet, sondern den letzten eingebauten Edit reproduzieren. Mit vim-repeat wird der vim-surround-Befehl als wiederholbar erkannt, und . macht das, was man intuitiv erwartet.
Die Empfehlung ist klar: wer Plugins von tpope (oder im selben Stil) nutzt, sollte vim-repeat als ersten Eintrag in der Plugin-Liste haben.
Übungs-Aufgaben
Wer Dot-Repeat verinnerlichen will, kann ein paar Übungen am eigenen Code probieren:
| Aufgabe | Idiomatischer Vim-Weg |
|---|---|
Alle Vorkommen von var durch let ersetzen, einzeln kontrolliert | /var<CR>cwlet<Esc> → n. × n |
Am Ende jedes import-Statements ein ; ergänzen | /^import<CR>A;<Esc> → n. × n |
| Drei Wörter pro Zeile uppercase machen, dann eine Zeile weiter | gU3w → j. × n |
| Bei einer Liste die ersten zwei Klammern aus jeder Zeile entfernen | dt( → j. × n |
| HTML-Tags in mehreren Zeilen ändern | /foo<CR>cit bar<Esc> → n. × n |
Der gemeinsame Nenner: jeder Edit ist eine kurze, atomare Sequenz, die mit <Esc> endet. Wer den Edit zu komplex baut (mehrere Operator-Motion-Kombis hintereinander, ohne Esc), zerstört die .-Wiederholbarkeit und muss eines der anderen Werkzeuge nutzen (Macro, :s, manuelles Wiederholen).
Besonderheiten
`.` ist Vims einprägsamster Befehl
Ein einzelner Punkt — auf jeder Tastatur leicht erreichbar, kein Modifier, keine Sequenz. Das ist Absicht: Vim's Designer wollten den am häufigsten benötigten Befehl auf die am bequemsten erreichbare Taste legen. Wer dot-repeat wirklich nutzt, drückt diese Taste hunderte Male pro Stunde.
`.` funktioniert auch nach Buffer-Wechseln
Der letzte Edit bleibt gespeichert, auch wenn du in einen anderen Buffer wechselst. dw in file1.txt, dann :b file2.txt, dann . — das löscht ein Wort in der zweiten Datei. Per-Buffer wird der Edit nicht zurückgesetzt.
`@:` ist `.` für Ex-Befehle
Wer :s/foo/bar/g ausgeführt hat und ihn auf eine andere Zeile anwenden will, kann @: drücken — das wiederholt den letzten Ex-Befehl. Mit @@ danach wiederholt sich der gleiche @:-Aufruf. So lässt sich ein Ex-Befehl auf eine ganze Liste von Zielen anwenden.
`:&&` wiederholt `:s` mit gleichen Flags
& allein wiederholt nur das Pattern der letzten Substitution — ohne g-Flag. :&& (Doppel-Ampersand) wiederholt mit den gleichen Flags. Praktisch zum Durchgehen einer Datei: erste Substitution mit Flags, dann auf jeder weiteren Zeile :&&.
Macros sind Dots auf Steroiden
Wenn der zu wiederholende „Edit" mehrere Operator-Motion-Kombis und Bewegungen enthält, geht . nicht mehr. Dort beginnen Macros: qa ... q zeichnet eine Sequenz auf, @a spielt sie ab. Das Konzept wird im Kapitel Editieren fortgeschritten ausführlich behandelt.
`vim-repeat` ist eine Plugin-Voraussetzung, kein eigenes Plugin
Niemand installiert vim-repeat für sich selbst — es bietet keine eigenen Tastenkombinationen. Es ist eine Library, die andere Plugins (vor allem tpope's) zum Funktionieren brauchen. Wer ein tpope-Plugin nutzt und feststellt, dass . nicht wie erwartet wirkt: vim-repeat als ersten Plugin-Eintrag prüfen.
Weiterführende Ressourcen
Externe Quellen
- Vim Help: single-repeat — offizielle Definition des Punkt-Befehls.
- Vim Help: complex-repeat — Macros als Erweiterung.
- tpope/vim-repeat — die Plugin-Brücke für
.-Repeat. - Drew Neil — Practical Vim, Tip 2-4 — drei Tipps speziell zur Wiederholung; „The Dot Formula" als prägende Erklärung.
- Drew Neil: Vimcasts — Episode 1 „Show invisibles" — frühe Vimcasts demonstrieren das Search-Edit-Repeat-Idiom in jeder Episode.