Wer Vim wirklich verstehen will, kommt an einem Konzept nicht vorbei: der Operator-Motion-Grammatik. Sie ist der Grund, warum Vim aus knapp zwei Dutzend Tasten eine Sprache mit hunderten von präzisen Edit-Befehlen erzeugt — und sie ist gleichzeitig der Punkt, an dem Vim sich von jedem anderen Editor abhebt. Statt für jede Aktion eine eigene Tastenkombination zu lernen, kombinierst du Verben (Operatoren wie löschen, kopieren, ändern) mit Objekten (Motions und Text-Objects). Jede Verb-Objekt-Kombination ergibt einen atomaren, wiederholbaren Befehl. Dieser Artikel ist die vollständige Referenz: der komplette Operator-Katalog, alle Motion-Typen, die Sonderregel doppelter Operator und das Zusammenspiel mit Text-Objects.

Die Grammatik in einem Satz

Vims Edit-Sprache hat die Struktur:

[Count] Operator [Count] Motion-oder-Text-Object

Beide Counts sind optional, der Operator und die Motion sind Pflicht. Gelesen wird das wie ein Imperativ-Satz: „Tu (Operator) X-mal mit (Motion oder Object)". Die häufigsten Beispiele:

TastenfolgeLesart
dw„lösche bis zum nächsten Wort"
cw„ändere bis zum nächsten Wort"
yiw„kopiere das innere Wort"
ci"„ändere den Inhalt zwischen Anführungszeichen"
>ap„rücke den ganzen Absatz ein"
gUw„mache das nächste Wort uppercase"
=G„auto-indent bis zum Buffer-Ende"
d3f,„lösche bis zum dritten Komma"

Wer diese Lesbarkeit einmal sieht, kann jeden neuen Vim-Befehl in derselben Form formulieren — und neue Operatoren oder Motions sind sofort mit dem bekannten Rest kombinierbar.

Der vollständige Operator-Katalog

Vim hat eine überschaubare Anzahl Operatoren — alle anderen Edit-Aktionen sind Kombinationen dieser Verben mit Objekten:

OperatorAktion
ddelete — löschen, Inhalt landet im Register
cchange — löschen und in Insert-Mode wechseln
yyank — kopieren ins Register
> / <indent right / left — Einrückung um eine Shiftwidth ändern
=auto-indent über equalprg oder filetype-Plugin
gu / gUlowercase / uppercase
g~case toggle
gq / gwformat — Zeilen nach textwidth umbrechen
g?rot13 — Caesar-Verschlüsselung um 13 Stellen (Kuriosum)
!filter — durch externen Shell-Befehl schicken
zffold create — Bereich zu einem Fold zusammenfassen
gccomment (in Vim 9.1+ optional, sonst Plugin) — Bereich kommentieren
g@operatorfunc-trigger — eigener Operator via Lua/Vimscript

Drei davon verdienen besondere Erwähnung, weil sie im Alltag massiv unterschätzt werden:

= (auto-indent) ruft das filetype-spezifische Einrück-Plugin auf. =G formatiert alles ab Cursor bis zum Buffer-Ende, =ap einen ganzen Absatz, == die aktuelle Zeile. In Code-Files ersetzt das oft einen kompletten Formatter-Plugin-Aufruf.

gq (format) umbricht Text nach der textwidth-Option. gqap reformatiert einen Absatz so, dass keine Zeile länger als z. B. 80 Zeichen wird — ohne externes Tool, ohne Plugin. Für Markdown- und Prosa-Edits unverzichtbar.

! (filter) schickt den Bereich durch einen Shell-Befehl und ersetzt ihn durch dessen Output. !ap sort -u sortiert einen Absatz und entfernt Duplikate. !ap jq . formatiert ein JSON-Stück. !ap awk '{print NR, $0}' nummeriert Zeilen. Ein extrem mächtiges Werkzeug für strukturierte Daten.

Die drei Motion-Typen — und warum sie zählen

Motions können in einer der drei Formen wirken: charwise, linewise oder blockwise. Diese Form bestimmt, wie der Operator den Bereich behandelt — und sie ist nicht immer offensichtlich.

TypBedeutungTypische Motions
charwisevon Cursor-Position bis zur Ziel-Positionh, l, w, b, e, f<x>, t<x>, 0, $, /pattern
linewiseganze Zeilen, vom Anfang bis zum Endej, k, gg, G, H, M, L, }, {, ]], [[
blockwiserechteckiger Block (selten als reine Motion)hauptsächlich nach <C-v>-Visual-Auswahl

Beispiel-Verhalten: dl löscht ein Zeichen rechts (charwise — eine Position). dj löscht zwei Zeilen — die aktuelle UND die darunter, weil j linewise wirkt. Das ist nicht intuitiv für Anfänger und eine häufige Quelle von „warum hat das jetzt mehr gelöscht als ich wollte".

Motion-Typ erzwingen

Vim lässt den Default-Typ einer Motion überschreiben. Nach einem Operator kann man v, V oder <C-v> einschieben, um den Typ zu erzwingen:

text Motion-Typ überschreiben
dj                 " linewise — löscht zwei Zeilen
dvj                " charwise! — löscht nur von Cursor bis zur entsprechenden
                   " Spalte in der nächsten Zeile (selten gewollt, aber möglich)

dw                 " charwise — bis zum nächsten Wort
dVw                " linewise! — löscht die ganze aktuelle Zeile,
                   " unabhängig vom Wort-Stopp

d3w                " drei Wörter (charwise)
d<C-v>3w           " blockwise — Rechteck von Cursor über drei Wörter

Diese Erzwingung ist selten nötig, aber gut zu wissen für Sonderfälle.

Die Verdopplungs-Regel

Eine Vim-Sonderregel, die nicht in das Grammatik-Schema passt, aber in der Praxis ständig vorkommt: ein doppelter Operator wirkt auf die aktuelle Zeile.

TastenfolgeWirkung
ddaktuelle Zeile löschen
yyaktuelle Zeile kopieren
ccaktuelle Zeile ändern (Inhalt weg, Einrückung bleibt, Insert)
>>aktuelle Zeile einrücken
<<aktuelle Zeile ausrücken
==aktuelle Zeile auto-indent
gqq / gwwaktuelle Zeile formatieren
guu / gUUaktuelle Zeile lowercase / uppercase

Die Logik dahinter: ein „leere Motion" gibt es nicht — also wird der wiederholte Operator als „diese eine Zeile" interpretiert. Das ist eine Bequemlichkeits-Konvention, weil die Zeile als Edit-Einheit so häufig vorkommt, dass die Sonder-Schreibweise sich lohnt.

Mit Count funktioniert auch das: 3dd löscht drei Zeilen, 5yy kopiert fünf, 10== formatiert zehn Zeilen.

Operatoren mit Text-Objects

Während Motions von Cursor bis Ziel wirken, beschreiben Text-Objects einen abgeschlossenen Bereich, unabhängig von der Cursor-Position innerhalb. Die Kombination Operator + Text-Object ist Vims am häufigsten unterschätztes Idiom.

Text-ObjectBedeutung
iw / awinner word / a word — Wort, mit oder ohne umgebenden Whitespace
is / asinner / a sentence (Satz)
ip / apinner / a paragraph (Absatz)
i" / a"Inhalt zwischen "..." / inkl. der Anführungszeichen
i' / a'Inhalt zwischen '...' / inkl.
i` / a`Inhalt zwischen Backticks
i( / a( (oder ib / ab)Inhalt der Klammer / inkl. Klammern
i{ / a{ (oder iB / aB)Inhalt der geschweiften Klammer / inkl.
i[ / a[Inhalt der eckigen Klammer / inkl.
it / atinner / a HTML-/XML-Tag-Inhalt

Die Konvention ist einheitlich: i = inner (Inhalt ohne die Grenze), a = around (mit Grenze). i" markiert nur den String, a" inklusive der Anführungszeichen.

Das Killer-Feature: Text-Objects funktionieren egal wo der Cursor innerhalb der Region steht. Wer mitten in einem Funktionsaufruf foo(bar, baz, qux) steht, kann mit einem einzigen di( den gesamten Inhalt der Klammer löschen — der Cursor muss nicht erst zur Klammer.

text Praktische Operator-Text-Object-Kombis
" Aufgabe: in `foo("hello world")` den String ändern
" Cursor steht irgendwo innerhalb der Anführungszeichen
ci"NEU<Esc>          " "hello world" wird zu "NEU"

" Aufgabe: einen Funktionsaufruf samt Klammern löschen
da(                  " löscht z. B. "foo(arg1, arg2)" — alles inkl. Klammern

" Aufgabe: HTML-Tag-Inhalt ändern
cit                  " <p>Inhalt</p> → <p></p> + Insert

" Aufgabe: einen ganzen Absatz duplizieren
yap                  " Absatz kopieren
p                    " einfügen — ergibt zwei identische Absätze

" Aufgabe: ein Wort uppercase machen
gUiw                 " inner word uppercase

Wer diese Kombinationen verinnerlicht hat, hat den eigentlichen Vim-Sprung gemacht. Die ausführliche Behandlung aller Text-Objects folgt im Kapitel Text Objects.

Operatoren im Visual-Mode

Im Visual-Mode dreht sich die Reihenfolge um: erst Selektion, dann Operator. Funktional identisch zur Operator-Motion-Schreibweise:

text Operator-Motion vs. Visual
" Drei Wörter löschen — zwei Schreibweisen

d3w                  " Normal-Mode: Operator + Motion mit Count
v3wd                 " Visual-Mode: Selektion + Operator

" Gleiches Ergebnis, identische Operationen.

In der Visual-Variante ist der Operator nur das letzte Zeichen — die Motion ist schon in der sichtbaren Selektion erledigt. Das macht Visual-Mode besonders nützlich, wenn:

  • der Bereich nicht klar per Motion beschreibbar ist (z. B. eine spezifische, ungewöhnliche Spanne),
  • der Bereich vor dem Operator visuell verifiziert werden soll,
  • die Operation ein Block ist (<C-v>), für den es keine direkte Operator-Schreibweise gibt.

Eine kleine Eleganz: jede Visual-Selektion startet implizit einen operator-pending-mode beim Operator-Druck. Wer v3w markiert hat und d drückt, ist genau in derselben Logik wie bei d3w — Vim macht keinen Unterschied.

Eigene Operatoren via operatorfunc

Vim erlaubt eigene Operatoren über das Konzept der operatorfunc. Das ist die fortgeschrittene Variante, mit der Plugins wie vim-surround ihre Funktionalität implementieren. Konkret:

vim ~/.vimrc — eigener Operator
" Eigener Operator: gK = Wort/Bereich an Online-Wörterbuch schicken
function! s:LookupOperator(type) abort
  let saved = @"
  execute "normal! `[v`]y"
  let word = @"
  let @" = saved
  " ... hier würde dann der Wörterbuch-Aufruf passieren
  echo "Looked up: " . word
endfunction

nnoremap gK :set operatorfunc=<SID>LookupOperator<CR>g@
" Aufruf: gKiw → schaut das innere Wort nach

Der Mechanismus: nach g@ springt Vim in den operator-pending-mode, sammelt eine Motion oder ein Text-Object und ruft anschließend die zugewiesene operatorfunc mit dem Markierungs-Typ als Argument auf. Innerhalb der Funktion stehen die Marks `[ und `] für Bereichs-Anfang und -Ende.

Diese Mechanik ist die Grundlage für eine ganze Klasse von Plugins. Wer einmal verstanden hat, wie operatorfunc arbeitet, kann jedes dieser Plugins lesen — und im Bedarfsfall einen eigenen Mini-Operator bauen.

Warum die Grammatik skaliert

Die eigentliche Stärke der Operator-Motion-Grammatik ist ihre kombinatorische Erweiterbarkeit. Vim hat etwa:

  • 10 wichtige Operatoren (d, c, y, gu, gU, >, <, =, gq, !)
  • 30+ wichtige Motions (h/j/k/l, w/b/e, f/t, /, gg/G, %, ...)
  • 12 wichtige Text-Objects (iw/aw, ip/ap, i"/a", i(/a(, it/at, ...)

Das ergibt rein rechnerisch 10 × (30 + 12) = 420 verschiedene atomare Edit-Befehle — und das ohne Counts, ohne erzwungene Motion-Typen, ohne den Visual-Mode-Zweig. Mit Counts und Variationen kommt man schnell in den vierstelligen Bereich.

Ein nicht-modaler Editor müsste jeden dieser Befehle als eigene Tastenkombination dokumentieren und im Tastatur-Hilfemenü unterbringen. Vim erreicht das gleiche Repertoire mit ~50 Bausteinen, die alle frei kombinierbar sind. Das ist nicht „kleverer Editor" — das ist eine Sprache, und genau wie bei natürlichen Sprachen ist der eigentliche Lerngewinn nicht der einzelne Befehl, sondern die Fähigkeit, neue Befehle aus bekannten Teilen zu formulieren.

Und das ist auch das Lernziel der ersten Vim-Wochen: nicht „möglichst viele Tastenkombinationen auswendig lernen", sondern die Grammatik internalisieren. Wer einmal denkt „delete inner word" und automatisch diw tippt, hat den Sprung gemacht.

Interessantes

Operator + Motion ist keine Erfindung von Vim

Die Idee stammt aus ed und vi — Bill Joys vi (1976) hatte bereits Operatoren wie d, c, y und kombinierbare Motions. Vim hat das Vokabular massiv erweitert (Text-Objects, eigene Operatoren), aber das Grundprinzip ist über 50 Jahre alt und hat sich nicht überholt.

`y` mit Motion ist nicht-destruktiv — der Cursor springt zurück

Nach einem Yank kehrt der Cursor an die Startposition zurück. y3w markiert drei Wörter, kopiert sie und der Cursor steht wieder am Anfang. Bei d oder c springt der Cursor an die Stelle, an der der gelöschte Bereich war — sinnvoll, weil dort der nächste Edit folgt.

`==` ist Vims unauffälliger Code-Formatter

Wer eine eingerückt unsaubere Datei hat, drückt gg=G — alles auswählen, auto-indent. Für viele Sprachen ist das eingebaut sauber, für andere lädt es das filetype-spezifische Indent-Plugin. Ein Mini-Formatter ohne weitere Konfiguration.

`gq` und `gw` unterscheiden sich subtil

Beide formatieren Zeilen. gq lässt den Cursor an der Ende-Position des Edit-Blocks. gw lässt ihn an der Start-Position — nützlich, wenn man danach von vorne weiterschreiben will.

`!` ist Vims Brücke zur ganzen Shell-Welt

Wer einen Range mit !command filtert, kann jeden Unix-Befehl als Editor-Operation nutzen. !ap sort -u, !ap jq ., !ap python3 -c '...', !ap awk '...'. Das macht Vim zu einer Editor-Shell-Hybrid-Umgebung, in der Daten-Transformationen ohne externes Tool ablaufen.

`g~`, `gu`, `gU` als Case-Operatoren — `~` ist die Ausnahme

Klein-Tilde ~ (ohne g) ist kein Operator, sondern ein eigenständiger Befehl: er toggelt das Zeichen unter dem Cursor und bewegt sich eins nach rechts. g~iw ist die Operator-Variante (toggle the inner word). Beide haben ihre Anwendung — ~ als schneller Ein-Zeichen-Toggle, g~ für größere Bereiche.

Weiterführende Ressourcen

Externe Quellen

Verwandte Artikel

/ Weiter

Zurück zu Modi

Zur Übersicht