Die vier Tasten h j k l sind das ikonischste Element der Vim-Bedienung — eine Erbschaft aus den 1970er Jahren, als Bill Joys vi auf einem ADM-3A-Terminal entwickelt wurde, das die Pfeile genau auf diese vier Tasten gedruckt hatte. Heute haben Tastaturen eigene Pfeil-Tasten, und trotzdem ist hjkl die richtige Wahl: die vier Buchstaben liegen direkt unter der Heimreihe der rechten Hand, weshalb jede Cursor-Bewegung ohne Hand-Verschiebung passiert. Dieser Artikel zeigt die hjkl-Basis, den Unterschied zwischen logischen und visuellen Zeilen (gj/gk), die vier wichtigen Zeilen-Anker und warum die meisten Vim-Lehrer empfehlen, die Pfeiltasten in der Lernphase explizit zu deaktivieren.

hjkl — die Heimreihen-Navigation

Die vier Grundbewegungen:

TasteRichtungMnemonik / Historik
hein Zeichen nach links„h" ist links auf der Tastatur
jeine Zeile nach unten„j" wie der Buchstabe, der nach unten zeigt
keine Zeile nach oben„k" wie der Buchstabe, der nach oben zeigt
lein Zeichen nach rechts„l" ist rechts auf der Tastatur

Mit Counts multipliziert: 5h ist fünf Zeichen nach links, 12j zwölf Zeilen nach unten. Wer in einer fünfzigzeiligen Datei zur Mitte will, drückt 25j — keine Pfeil-Reibung, kein Maus-Wechsel.

Die historische Begründung — der ADM-3A — ist 2026 nur noch eine Anekdote, aber die ergonomische Begründung gilt unverändert: hjkl spart Hand-Bewegung. Die rechte Hand bleibt auf der Heimreihe (j, k, l, ;), Cursor-Bewegung passiert mit den Fingern, die ohnehin dort sind. Pfeiltasten erzwingen eine Hand-Verschiebung um etwa 5-10 cm — eine kleine Bewegung, die sich aber bei hundertfacher Wiederholung pro Stunde addiert.

gj/gk — visuelle vs. logische Zeilen

Bei langen, umgebrochenen Zeilen wird der Unterschied zwischen logischen und visuellen Zeilen relevant:

  • Eine logische Zeile ist eine durch \n getrennte Texteinheit — das, was beim Lesen einer Datei mit cat als eine Zeile gilt.
  • Eine visuelle Zeile ist das, was am Bildschirm als eine Zeile erscheint — bei langen logischen Zeilen mit set wrap über mehrere visuelle Zeilen verteilt.

j und k springen über logische Zeilen. Bei einem 200-Zeichen-Paragraph, der auf einem 80-Spalten-Bildschirm in drei visuelle Zeilen gewrappt ist, ist j ein Sprung um den ganzen Paragraphen nach unten — nicht um eine visuelle Zeile.

Für visuelle Zeilen-Navigation gibt es gj und gk:

TasteBewegung
j / keine logische Zeile (\n-Sprung)
gj / gkeine visuelle Zeile (Bildschirm-Sprung)

In Prosa- und Markdown-Workflows fühlt sich gj/gk natürlicher an — der Cursor bewegt sich so, wie das Auge es erwartet. In Code-Workflows, wo Zeilen typisch kurz sind und nicht wrappen, ist der Unterschied irrelevant.

Wer immer visuelle Zeilen will, kann j/k auf gj/gk mappen:

vim ~/.vimrc — j/k als visuelle Zeilen
" j und k folgen visuellen Zeilen statt logischen.
" Bei Counts wieder logische Zeilen — damit `5j` wie erwartet wirkt.
nnoremap <expr> j v:count == 0 ? 'gj' : 'j'
nnoremap <expr> k v:count == 0 ? 'gk' : 'k'

Die <expr>-Variante prüft den Count: ohne Count (visuelle Zeile, „nach unten/oben"), mit Count (logische Zeile, „springe N Zeilen"). Damit 5j weiterhin „fünf logische Zeilen runter" bedeutet, was bei Code-Block-Sprüngen die richtige Semantik ist.

Zeilen-Anker: 0, ^, $, g_

Innerhalb einer Zeile gibt es vier Anker-Positionen:

TastePosition
0Spalte 1 — echter Zeilenanfang (vor Whitespace)
^erstes Nicht-Whitespace-Zeichen der Zeile
$Zeilenende (Cursor auf dem letzten Zeichen)
g_letztes Nicht-Whitespace-Zeichen (Zeilenende ohne Trailing-Whitespace)

Der Unterschied zwischen 0 und ^ wird klar bei eingerücktem Code:

text 0 vs. ^ bei Einrückung
" Beispiel-Zeile (mit 4 Leerzeichen Einrückung):
"     console.log("Hello");

0       " springt in Spalte 1 (zwischen den Whitespaces, vor dem ersten)
^       " springt zu "c" — dem ersten echten Zeichen

In der Praxis ist ^ fast immer die nützlichere Variante — Code beginnt selten in Spalte 1, eingerückte Zeilen sind die Norm. 0 ist sinnvoll, wenn man tatsächlich den Whitespace-Bereich braucht (z. B. zum Bearbeiten der Einrückung).

Analog ist g_ die nützlichere Variante von $: viele Editoren produzieren Trailing-Whitespace ohne Absicht, und g_ springt zum letzten bedeutungstragenden Zeichen, nicht zum letzten White-Char. Bei sauberen Dateien sind beide gleichwertig.

Anker mit Operatoren kombiniert

Diese Anker kombinieren sich mit Operatoren zu sehr häufigen Edit-Befehlen:

BefehlBedeutung
d$ / Dbis Zeilenende löschen
d0bis Spalte 1 löschen
d^bis erstem Nicht-Whitespace löschen
c$ / Cbis Zeilenende ändern (= load + Insert)
y$ / Ybis Zeilenende kopieren (Y so in modernem Vim als Default)
>$von hier bis Zeilenende einrücken (selten gebraucht)
gU$bis Zeilenende uppercase

D, C und Y sind klassische Abkürzungen für d$, c$, y$ — sie sparen jeweils einen Tastendruck. D und C sind in jeder Vim-Version Default, Y (als Synonym für y$) ist in modernem Vim und Neovim als Default gesetzt; in alten Versionen ist es noch yy, weshalb manche Konfigs explizit mappen:

vim ~/.vimrc — Y konsistent mit D und C
" Y soll wie D und C funktionieren: bis Zeilenende (nicht ganze Zeile)
nnoremap Y y$

Counts mit hjkl und Anker

Counts wirken auf alle Motions, auch hjkl:

text Counts in der Navigation
10j         " zehn Zeilen nach unten
25l         " 25 Zeichen nach rechts
100k        " 100 Zeilen nach oben

" Auf den Anker-Tasten haben Counts oft keine sinnvolle Bedeutung —
" "5$" springt zur fünften Zeile darunter und dann zum Zeilenende,
" was selten gewollt ist.

Praktisch ist die Kombination Count + Zeilen-Sprung mit gg und G (siehe spätere Artikel zur Sprung-Navigation):

text Direkt zu einer Zeile springen
42G            " zur Zeile 42 (G ohne Count = letzte Zeile)
42gg           " zur Zeile 42 (alternativ-Syntax)
:42            " ebenfalls zur Zeile 42 (Ex-Variante)

42G und :42 sind funktional identisch — beide springen zur Zeile 42. Wer die Zeile schon kennt (z. B. aus einem Compiler-Fehler), kann das direkt eingeben statt mit j/k zu zählen.

Was Vim bei l am Zeilenende tut

Eine kleine Eigenheit: Standardmäßig stoppt l am Zeilenende — der Cursor wandert nicht in die nächste Zeile. Wer das ändern will, gibt es die Option whichwrap:

vim ~/.vimrc — Cursor-Wrap einstellen
" Default ist whichwrap=b,s
" Mit dieser Erweiterung: l und h wrappen über Zeilenende hinaus,
" Pfeiltasten ebenfalls.
set whichwrap+=<,>,h,l,[,]

Im Default-Verhalten ist Vim strikt zeilenorientiert — der Cursor bleibt in der Zeile, in der er ist, bis man explizit mit j/k wechselt. Manche User mögen das nicht und mappen den Wrap-Modus ein; andere finden gerade diese Strenge nützlich, weil sie versehentliche Zeilenwechsel verhindert.

Eine analoge Option: set virtualedit=onemore lässt den Cursor in jeder Zeile eine Position hinter das letzte Zeichen, statt direkt auf dem letzten Zeichen zu stehen. Für viele Editor-Refugees natürlicher.

Pfeiltasten — warum disziplinär verbannen

Die häufigste Empfehlung in Vim-Tutorials lautet: Pfeiltasten in der Lernphase deaktivieren. Der Grund ist nicht religiös, sondern pragmatisch — solange die Pfeile funktionieren, nutzt man sie automatisch, weil sie vertraut sind. Das blockiert das Lernen der hjkl-Reflexe.

vim ~/.vimrc — Pfeile deaktivieren
" Pfeile im Normal-Mode komplett blockieren
nnoremap <Up>    <Nop>
nnoremap <Down>  <Nop>
nnoremap <Left>  <Nop>
nnoremap <Right> <Nop>

" Auch im Insert-Mode (umstrittener, aber konsequent)
inoremap <Up>    <Nop>
inoremap <Down>  <Nop>
inoremap <Left>  <Nop>
inoremap <Right> <Nop>

" Auch in Visual
vnoremap <Up>    <Nop>
vnoremap <Down>  <Nop>
vnoremap <Left>  <Nop>
vnoremap <Right> <Nop>

Drei Tage schmerzhaftes Umlernen, danach ist hjkl unter den Fingern automatisch. Wer es radikaler will, klebt sich für eine Woche Pflaster über die Pfeil-Tasten auf der physischen Tastatur — eine erstaunlich wirksame Methode.

Nach dem Lernprozess kann man die Mappings wieder entfernen — die Pfeile sind dann nur noch verfügbar, werden aber kaum noch gebraucht.

Pfeile im Command-Line-Mode behalten

Eine Ausnahme: im Command-Line-Mode (nach :, /, ?) sind Pfeile nützlich für History-Navigation (Up/Down) und für Cursor-Bewegung im Befehl (Left/Right). Sie sollten nicht disabled werden:

vim ~/.vimrc — Pfeile nur außerhalb der Command-Line blockieren
" NICHT mappen — Command-Line lassen Pfeile intakt
" (cnoremap würde sie auch dort blocken — bewusst nicht!)

Praxis-Workflows

Drei typische Navigations-Szenarien:

Workflow 1: zur Funktion-Definition springen

text Workflow 1
" In Zeile 200 eines Codes, Funktion ist in Zeile 50
50G              " direkt zur Zeile 50
^                " zum ersten Nicht-Whitespace-Zeichen

Workflow 2: am Zeilenende ein Semikolon ergänzen

text Workflow 2
" Cursor irgendwo in der Zeile
$a;<Esc>         " ans Ende, append, ; tippen, zurück in Normal

" Oder kompakter mit A (siehe Insert-Mode-Artikel):
A;<Esc>           " A = Insert am Zeilenende — zwei Tasten gespart

Workflow 3: zwischen Zeilen-Anfang und -Ende pendeln

text Workflow 3
" Schnell die Einrückung kontrollieren
^                " erstes Nicht-Whitespace
g_               " letztes Nicht-Whitespace
^                " zurück zum Anfang

Interessantes

hjkl ist eine ADM-3A-Erbschaft, kein Mythos

Bill Joys Tastatur in den 1970er Jahren hatte die Pfeil-Symbole tatsächlich auf den Tasten h, j, k, l aufgedruckt. Das Layout ist seitdem aus historischen Gründen geblieben — und hat sich durch die Heimreihen-Position als ergonomisch überlegen erwiesen. Die Geschichte ist gut belegt, kein Internet-Mythos.

`gj`/`gk` sind in Markdown- und Prosa-Workflows essentiell

Bei langen Sätzen, die über mehrere visuelle Zeilen wrappen, ist j ein Sprung über den ganzen Paragraph — was beim Lesen verwirrt. gj/gk folgen der Anzeige. Wer viel mit Prosa arbeitet, mappt sich typischerweise j/k auf gj/gk.

`^` ist `0` für gut erzogene Programmierer

Wer in eingerücktem Code arbeitet, will praktisch nie die Spalte-1-Position (0), sondern das erste sinnvolle Zeichen (^). ^ ist im Alltag deutlich öfter die richtige Wahl — und sollte als Reflex aufgebaut werden.

`D` = `d$`, `C` = `c$`, `Y` sollte `y$` sein

Die Großbuchstaben-Varianten sparen einen Tastendruck und sind ein verbreitetes Idiom. Y als Default-yy ist in alten Vims eine Inkonsistenz — in modernem Vim ist Y = y$, in alten Versionen lohnt das explizite Mapping.

Pfeile blockieren bringt mehr als 10 Cheat-Sheets

Mappen der Pfeile auf <Nop> ist eine erstaunlich wirksame Lern-Maßnahme. Drei bis fünf Tage Unbequemlichkeit, danach ist hjkl automatisch — und der Editor fühlt sich anders an. Wer es nicht aushält, kann auf Insert-Mode-Pfeile verzichten und nur Normal-Mode mappen.

`set virtualedit=onemore` für IDE-Reflexe

In den meisten Editoren steht der Cursor hinter dem letzten Zeichen einer Zeile. In Vim direkt auf dem letzten Zeichen. Wer das nicht mag, schaltet virtualedit=onemore ein — und kann den Cursor eine Position weiter setzen. Im Alltag eher Geschmacks- als Notwendigkeitsfrage.

Weiterführende Ressourcen

Externe Quellen

Verwandte Artikel

/ Weiter

Zurück zu Navigation

Zur Übersicht