(> emacs vi) → #f


Im Vorkurs zum Informatikstudium gab es unter neben Einführungen in Versionskontrollsysteme, LaTeX, Unixbedinung, etc. auch eine Einführung in den Editor emacs. Dort wurde unter anderem gesagt, dass der emacs ein besserer Editor sei, als der vi.

Das mag für die Ur-Version des vi vielleicht sogar stimmen. Diese kenne ich jedoch nicht, und ich habe sie auch noch nie auf irgend einem Unixsystem gefunden. Wann immer man unter Linux/BSD/Unix/Mac OS X den “vi” installiert, steht dieser i.d.R. für den aktuellen Vim, also den Vi Improved, einem Clone von vi, der kontinuierlich weiterentwickelt wird, und etliche Features bietet, die ihn sehr mächtig machen.

Ich möchte mich hier an den Übungszettel zur emacs Einführung orientieren, und daran zeigen, dass der vi dem emacs in nichts unterlegen ist (meiner Meinung nach lassen sich sogar etliche Sachen um einiges einfacher im vi lösen, als im emacs). Dabei werd ich auch ein paar alternativen Aufzeigen. Zum Schluss möchte ich dann noch ein paar tolle Tipps zum Besten geben, die mir die Arbeit das ein oder andere mal doch um einiges erleichtert haben. Nur damit das niemand falsch versteht, dass soll kein emacs-Bashing sein, oder so – es geht mir lediglich darum diese (in meinen Augen) Falschaussage des Professors zum Thema vi hier mal richtig zu stellen.

  1. Statt mit dem Befehl emacs startet man Vi IMproved mit dem Befehl vim. Auf allen Systemen, die ich kenne ist vi als Alias gesetzt, welcher auf den Vi IMproved verweist. Daraus folgt:
    pygospa@telperion ~ % vi
    pygospa@telperion ~ % vi vorhandeneDate.txt
    pygospa@telperion ~ % vi neueDatei.txt

    Die erste Zeile startet den Vi IMproved mit einem leeren Buffer. Die zweite Zeile lädt den Inhalt einer schon vorhandenen Datei in den Buffer. Der letzte Befehl öffnet einen leeren Buffer, speichert den Inhalt dieses Buffers allerdings in die Datei “neueDatei.txt”, sobald gespeichert wird.

  2. Wir öffnen eine neue leere Datei, in der wir 10 mal schreiben sollen:
    Als erste Uebung mit dem Emacs muss ich 10-mal schreiben:

    Ich lerne mit dem Editor Emacs umzugehen!
    Ich lerne mit dem Editor Emacs umzugehen!
    Ich lerne mit dem Editor Emacs umzugehen!

    Ich lerne mit dem Editor Emacs umzugehen!

    Man solle hierbei mit Copy und Paste (in der GUI?) arbeiten (und ja, in der Aufgabenstellung sind tatsächlich 10 dieser Zeilen angegeben). Ich weiß nicht, ob es in emacs eine Möglichkeit gibt, dies zu vereinfachen. Unter vi würde ich wie folgt vorgehen:

    pygospa@telperion ~ % vi
    i
    Als erste Uebung mit dem vi muss ich 10-mal schreiben:
    
    Ich lerne mit dem Editor vi umzugehen!
    [ESC]yy9p

    Was passiert hier?
    Die erste Zeile sollte durch 1 mittlerweile klar sein. Zeile zwei wechselt in den Eingabemodus. Dazu muss erklärt werden, dass vi verschiedene Modi kennt, in denen er betrieben werden kann. Die zwei wichtigsten sind der Eingabemodus, mit welchem man Text eingeben kann, und der Befehlsmodus, der es einem erlaubt, vi Befehle zu erteilen.
    Wenn wir den Editor vi starten, sind wir im Befehlsmodus. Um in den Eingabemodus zu gelangen Tippen wir alsdann i(nsert). Je nach Konfiguration sollte jetzt auch in der letzten Zeile des Fenster, der Statuszeile eine kleine Information erscheinen, die in etwa so aussieht:

    -- INSERT --                                                    0,1           All

    Jetzt können wir mit dem Tippen loslegen. Wir tippen die ersten zwei Zeilen ab, hören dann aber bei der ersten der 10 Zeilen auf, und machen jetzt am Ende von Zeile 3 folgendes:

    [ESC] wechselt zurück in den Befehlsmodus. Alle weiteren Eingaben sind Befehlsfolgen für vi, keine Eingaben für den Text.
    yy – kopiert eine Zeile in den Zwischenspeicher.
    9p – Pasted den Inhalt aus dem Zwischenspeicher 9 mal.
    Fertig.

    Eine Mächtigkeit von vi ist es, Befehle zu kombinieren. Anders als bei Emacs braucht man hier nicht für jeden neuen Befehl zunächst eine Metataste, die den Befehl einleutet. So sind yy (yank) und 9p (paste) unterschiedliche Befehle, die unterschiedliche Parameter übernehmen.

    Und so kann man nach einer ganzen Zeile vi auch dazu bringen nur Teile zu markieren. Folgende Varianten wären Denkbar:
    3y Kopiert 3 ganze Zeilen, ab der Zeile, in der sich der Cursor befindet (inklusive)
    y$ Kopiert von der Cursorposition bis zum Ende der Zeile.
    yw Kopiert von der Cursorposition bis zum Ende des Worts.

    Und da die Befehle beliebig kombinierbar sind, könnte man auch delete nutzen, welches identisch zu yank funktioniert:
    dd Löscht die Zeile, in der sich der Cursor befindet.
    3d Löscht 3 ganze Zeilen, ab der Zeile, in der sich der Cursor befindet (inklusive)
    d$ Löscht von der Cursorposition bis zum Ende der Zeile.
    dw Löscht von der Cursorposition bis zum Ende des Worts.

    Auch eine gelöschte Zeile befindet sich zunächst immer im Zwischenspeicher. Folglich lässt sich der Befehl auch zum cut-paste benutzen. Folgende Variante würde das Problem also auch lösen:

    pygospa@telperion ~ % vi
    i
    Als erste Uebung mit dem vi muss ich 10-mal schreiben:
    
    Ich lerne mit dem Editor vi umzugehen!
    [ESC]dd10p

    Daneben gibt es auch noch die Möglichkeit so genannte “Blöcke” zu definieren, in dem man an beliebigen Stellen “Marker” setzt und diese Blöcke dann benennt. Eine weitere Alternative wäre der Visuelle Modus, bei dem man mittels des Cursors Text visuell markieren kann. Aber auf die möchte ich hier nicht näher eingehen

  3. Die nächste Aufgabe ist, den Buffer unter der Datei lern.txt zu speichern.

    Das Speichern und Schließen lässt sich wie auch sonst alles wieder über die Tastatur machen. Hierzu lernen wir einen weiteren Modus kennen, den Kommandozeilen-Modus. Eine Kommandozeile leitet sich im Befehlsmodus über ein : ein.
    Der Unterscheid zum Eingabe- und Befehlsmodus ist derjenige, dass in der Eingabe- und im Befehlsmodus die Befehle zum direkten Editieren des Textes dienen. In der Kommandozeile sind die Befehle eher auf der Meta-Ebene. Es geht darum Textstellen zu finden, Texte zu speichern, die Art der Darstellung zu ändern, etc.

    Im letzten Beispiel waren wir schon im Befehlsmodus (durch das Drücken von [ESC]), daher muss jetzt nur noch die richtige Befehlsfolge eingegeben werden:

    :wq lern.txt

    Auch hier haben wir wieder eine Kombination von zwei Befehlen:

    :w lern.txt

    Speichert (Englisch write) den Inhalt des Buffers in der Datei mit dem Namen lern.txt. Ist ein Name schon mal gegeben worden (entweder beim Start mit Zeile 2 oder 3 aus Punkt 1, oder weil w: dateiname schon mal genutzt wurde), dann reicht auch ein :w.

    :q 

    Beendet den Editor.

    Zusammengefasst gibt es folgende Möglichkeiten/Varianten zum Speichern und Beenden:

    :w
    :w <dateiname>
    :wq
    :wq <dateiname>
    :q
    :q!
    :e!

    Die ersten 2 Zeilen haben wir schon kennen gelernt. Die dritte Zeile ist ähnlich wie die erste Zeile dann zu gebrauchen, wenn man den Dateinamen schon mal angegeben hat. Zeile sechs schließt den Editor ohne zu speichern, und Zeile sieben verwirft alle Änderungen seit dem letzten Speichern.

  4. Da wir die verschiedenen Arten zu Speichern und zu Starten von vi schon durch haben, geht es nun zur Aufgabe mit dem Ersetzten von Wörtern.

    Hierzu benötigen wir wieder den Kommandozeilen-Modus. Die zwei Befehle die wir benötigen sind:

    :%s/lerne/kann/g
    :%s/umzugehen/umgehen/g

    Ich möchte wieder kurz ein paar Worte zum Aufbau verlieren. Dieser wird in der Literatur oft angegeben mit:
    :rs/f/t/x

    Ich möchte bei der Erklärung ein wenig anders anfangen, und zwar mit dem /f. Dies ist der Befehl, mit dem man Teile im Buffer finden kann. Der Slash / leitet den Suchbefehl ein. Das f ist ein Platzhalter für einen “Suchbegriff”. Dieser kann entweder ein Wort sein, dass im Text vorkommt, oder aber eine Kombination von verschiedenen Worten, die einem bestimmten Muster entsprechen (so genannten Regular Expressions – darauf möchte ich hier nicht weiter eingehen – es gibt dort gute Webseiten, die einem erklären, wie Regular Expression allgemein, und bei Vim im speziellen funktionieren).

    In unserem Fall entspricht ein :/lerne der Suche nach dem Wort lerne im Buffer. Je nach Einstellung werden dabei alle Vorkommen eingefärbt. Gleichzeitig springt der Cursor zum nächsten Vorkommen des Wortes lerne. Wiederholte Eingabe von :/ ohne weiteres Suchwort sucht dann nach dem nächsten Vorkommen vom lerne. Übrigens kann man bei der Suche das : auch weglassen.

    Gucken wir uns als nächsten s/f/t an. Der Befehl substitution leitet den Ersetzungsbefehl ein. Nach s folgt zunächst ein Suchbefehl (wie wir ihn gerade Kennengelernt haben), danach kommt der Ausdruck, mit dem der Suchausdruck ersetzt werden soll. Dieser wird vom Suchausdruck mit einem / getrennt. Also passiert bei der Eingabe von dem Befehl :s/lerne/kann folgendes:
    – Der Befehl :s leitet eine Substitution ein.
    – Der nächste Ausdruck (in diesem Fall lerne) wird gesucht.
    – Dieser Ausdruck wird mit dem Ausdruck nach dem zweiten / ersetzt, also mit kann.

    Auch diesen Befehl kann man nun mehrfach aufrufen, indem man als nächstes die Kommandozeile wieder einleitet (mit :), und dann einmal die Pfeiltaste nach oben drückt.

    Aber vim wäre nicht vim, wenn man hier nicht noch weiter vereinfachen könnte. Kommen wir nun zum r. Ähnlich wie schon bei den Befehl p, y oder d kann man auch vor den Befehl s einen Parameter schreiben, der den Befehl s auf einen größeren Bereich ausweitet (r steht für range). Für r können verschiedene Werte eingegeben werden. Wir wissen schon was passiert, wenn man ihn weglässt:
    :s/f/t nur in der Zeile, in der sich der Cursor befindet, wird das erste Vorkommen ersetzt.
    :3s/f/t in der 3. Zeile wird das erste Vorkommen ersetzt.
    :1,3s/f/t in der Zeile 1 bis 3 wird jedes erste Vorkommen ersetzt.
    :/p/s/f/t in der nächste Zeile in der das Suchmuster p gefunden wird, wird das nächste vorkommen von f mit t ersetzt.
    :%s/f/t in allen Zeilen wird das erste Vorkommen von f durch t ersetzt.

    Es gibt noch weitere Varianten, aber die habe ich bisher noch nicht gebraucht, daher soll das zunächst einmal reichen 😉

    Jetzt fehlt lediglich noch ein Parameter, nämlich der letzte, das x.
    Dieses steht für weitere Argumente, die Übergeben werden können (in beliebiger Kombination):
    :%s/f/t nur das erste Vorkommen in jeder Zeile wird ersetzt.
    :%s/f/t/g in jeder Zeile (%) wird jedes Vorkommen (global) von f mit t ersetzt.
    :%s/f/t/i die Groß- und Kleinschreibung wird ignoriert.
    :%s/f/t/c (confirm changes) – jedes Ändern muss vorher mit yes für ja, no für nein oder all für das Unterbinden des Nachfragens für alle weiteren Vorkommen bestätigt werden.

    Mithilfe dieses Wissens sollte nun auch die Lösung für die Aufgabe klar sein. Folgende Alternativen würden in diesem speziellen Fall ebenfalls zu erfolgreichen Lösungen führen:

    :3,12s/lerne/kann/g
    :%s/lernen/kann
    :%s/lernen/kann/i
    :%s/lernen/kann/ic
    :1,12s/lernen/kann/icg
  5. Zum Schluss geht es darum, emacs im LaTeX Modus zu starten. Ein solcher Modus existiert für vi nicht. Was jedoch nicht bedeutet, dass der vi kein Syntax-Highlighting kennt – im Gegenteil. Vim kommt mit einer Reihe von vorgefertigten Syntax-Dateien für die verschiedensten Zwecke. Unter Mac OS X ergibt sich:
    pygospa@laurelin ~ % ls -l /usr/share/vim/vim72/syntax/*.vim | wc -l
         519

    Hier findet sich unter anderem auch die tex.vim, welche unsere Tex Dateien einfärbt.

    Auch das Bauen der PDF Datei geht direkt aus vi heraus:

    :!pdflatex lern.tex

    Das Ausrufezeichen ! eröffnet die Möglichkeit einen Shell-Befehl direkt über die Kommandozeile von vi einzugeben. Sogar die Completion der Shell steht dann in der vi-Kommandozeile zur Verfügung.

    Alternativ lässt sich in eine neue Shell wechseln über:

    :sh

    Beim Beenden der Shell über exit kommt man dann zurück zum Editor.

    Vim kommt in verschiedenen Varianten, eine davon ist gVim, welches nicht in einer Konsole läuft, sondern mit einer GUI kommt, und unter einem Fenstersystem bedient wird. Neben der Bedienmöglichkeit, die ich oben beschrieben habe, gibt es auch noch die Möglichkeit, den Editor mithilfe von grafischen Menüs zu bedienen. Für gVim gibt es das Plugin Vim LaTeX, dass diese Menüs um einige interessante LaTeX Menüs ergänzt.

Fazit

Ich hoffe, man sieht, dass der vi dem emacs in nichts nachsteht, anders als es leider in dem Vorkurs Informatik in der Vorlesung zum Editor emacs den Eindruck hatte.

Sicherlich ist schön, dass der Emacs sich mit einem Scheme-Dialekt programmieren lässt – besonders wenn man mit dem Studium anfängt, und dann in der Regel auch Scheme als erste Programmiersprache kennen lernt. Nichts desto trotz wird man in den ersten Semestern wahrscheinlich nicht in die Lage kommen, den Editor programmieren zu müssen. Und bis es dann soweit ist, hat man neben Scheme auch Assembler, C und Java kennengelernt, und kommt auch mit der Programmierung in der Shell zurecht, Scheme wird man jedoch höchst wahrscheinlich nicht mehr nutzen. Vim lässt sich auch programmieren und hat , eine Syntax, die Ähnlichkeiten mit der Bash-Programmierung und C hat.

Was ich gegenüber dem emacs beim vi sehr gerne mag, ist die Tatsache, dass die Befehle beliebig kombiniert werden können, und relativ viel Sachen relativ einfach eingegeben werden können. Beim emacs muss ich beispielsweise Kombinationen von Meta-Tasten mit einer weiteren Taste angeben und das in Folge. Aber das ist natürlich eine Geschmackssache. Der emacs zeichnet sich dadurch aus, dass er viele weitere Funktionen bietet, die mit einem eigentlichen Editor nichts mehr zu tun haben, z.B. ein Mailclient, ein IRC- und einen IM-Client, einen Kalender, Spiele, MP3-Player, Adressdatenbanken, etc. Dies macht ihn aber auch zu einem sehr großen und langsamen Editor (was in heutigen Zeiten natürlich nicht mehr so ins Gewicht fällt). Auf vielen Systemen muss der emacs daher nachinstalliert werden, wohingegen vi als schlanker Editor standardmäßig mitgeliefert wird.

Aber auch wenn der vi um einiges schlanker ist, lässt sich viel damit anstellen. Ich möchte den Artikel hier mit ein paar “Perlen” schließen, die ich sehr häufig nutze.

Vorweg möchte ich aber noch einmal betonen, das beide Editoren ihre Berechtigung haben, und das es definitiv auch eine Geschmacksfrage ist. Wer sich eine eigene Meinung bilden möchte, sollte sich definitiv mal die zeit nehmen und sich jeweils eine Woche lang intensiv mit den Editoren auseinander setzten. Hier nun meine Hand voll Befehle, die meiner Meinung nach echt Gold wert sind:

  • Dies lädt den Inhalt einer Datei, die sich auf einem entfernten Server befindet, in den lokalen Buffer. Beim Speichern wird der Buffer dann über das Protokoll auf den Server zurückgeschrieben. Und das ganze funktioniert auch über rcp, ssh und http.
    pygospa@telperion ~ % vi ftp://username@server.tld:21/html/index.html
  • Wie alle Befehle lässt sich auch der Befehl zum Ausführen eines Shell-Befehls mit anderen Befehlen kombinieren. read liest Zeilenweise den Inhalt des im weiteren folgenden Ausdruck ein und schreibt ihn an die Stelle vom Cursor.
    :r !date -R

    Also gibt der oben genannte Befehl Befehl das aktuelle Datum im RFC 822 Format aus. Nützlich, wenn man Tagebuch führt, oder festhalten möchte, wann man eine bestimmte Änderung an einer Datei durchgeführt hat, etc.

  • Wenn man mit langen (Quell-)Texten arbeiten muss, dann ist die Möglichkeit des “Zusammenfalten” von Textstellen sehr Hilfreich. Hier gibt es zwei Varianten. Zunächst die wahrscheinlich allgemeinere, die auch nicht-Informatiker interessant finden werden. Zunächst eine Beispieldatei:
    I: The Horror in Clay
    The most merciful thing in the world, I think, is the inability of the human mind to correlate all its contents. We live on a placid island of ignorance in the midst of black seas of infinity, and it was not meant that we should voyage far. The sciences, each straining in its own direction, have hitherto harmed us little; but some day the piecing together of dissociated knowledge will open up such terrifying vistas of reality, and of our frightful position therein, that we shall either go mad from the revelation or flee from the deadly light into the peace and safety of a new dark age.
    
    ...
    
    II: The Tale of Inspector Legrasse
    The older matters which had made the sculptor's dream and bas-relief so significant to my uncle formed the subject of the second half of his long manuscript. Once before, it appears, Professor Angell had seen the hellish outlines of the nameless monstrosity, puzzled over the unknown hieroglyphics, and heard the ominous syllables which can be rendered only as "Cthulhu"; and all this in so stirring and horrible a connection that it is small wonder he pursued young Wilcox with queries and demands for data.

    Nun werden auf den beiden Überschriften folgende Befehle im Befehlsmodus eingegeben:

    zf3j
    zf2j

    Das Ergebnis ist nun:

    +--  4 lines: I: The Horror in Clay-----------------------------------------------
    
    ...
    
    +--  3 lines: II: The Tale of Inspector Legrasse----------------------------------

    Die Anzahl der Zeilen, die man angegeben hat, wird also unter der Überschrift “zusammengefaltet”. Dadurch kann man beim Schreiben eigener Texte Teile, die man akut nicht bearbeitet, ausblenden. Will man sich den entsprechenden Teil wieder anzeigen lassen, kann man dies mittels zo öffnen (open), und danach mittels zc wieder schließen (close).

    Für Programmierer gibt es noch eine etwas elegantere Variante. Oft möchte man hier einzelne Funktionen oder Methoden zusammenfassen. Diese sind durch irgend ein syntaktisches Konstrukt als zusammengehöriger Block gekennzeichnet. Wenn diese nach dem Java-Stil formatiert, kann man hier den größten Nutzen herausholen. Wieder einmal ein Beispiel:

    public int chooseDirection() {
       int eingabe;
       System.out.println("(0) Links anlegen, (1) Rechts anlegenn");
       eingabe = Eingabe.leseInt();
       while (eingabe < 0 | eingabe > 1) {
          System.out.printf("Falsche Auswahl - Bitte eingabe wiederholen!n");
          eingabe = Eingabe.leseInt();
       }
       return eingabe;
    }

    Wenn wir diese Funktion zusammenfalten wollen ohne vorher immer die Zeilen zählen zu müssen, bewegen wir uns mit den Cursor einfach irgendwo in die Methode (aber nicht in den while-Block). Nun rufen wir folgenden Befehl auf:

    zfa}

    vi identifiziert nun, in welchem “Block” es sich befindet – mithilfe des Symbols für das Blockende “}” sucht vi nach dem Anfang und faltet diesen Teil dann zusammen. Das Ergebnis ist also:

    +-- 10 lines: public int chooseDirection() {------------------------------------
  • Ein paar “:set” Befehle die sehr nützlich sind:
    Zeilennummern ein/ausschalten:

    :set number
    :set nonumber

    Syntaxhighlighting an/ausschalten (automatisch) oder Syntaxfile explizit angeben.

    :sy on
    :sy off
    :so /usr/share/vim/vim72/syntax/java.vim

    Kopieren von Text, ohne das vi denkt, man möchte Einrückungen haben:

    :set paste
    :set nopaste
  • Rechtschreibkorrektur lässt sich in vim wie folgt starten:
    :set spelllang=de spell 

    Nun werden falsch geschriebene Worte hinterlegt. Folgende Möglichkeiten hat man nun:
    ]s Springe zum nächsten falschen Wort
    [s Springe zum vorherigen falschen Wort
    zG Füge das Wort temporär zum Wörterbuch hinzu (geht beim schließen des Dokuments verloren)
    zg Füge das Wort permanent zum Wörterbuch hinzu
    zug Lösche das Wort, dass zuletzt ins Wörterbuch eingefügt wurde.
    zuG Analog
    z= Zeigt eine Liste von Korrekturalternativen an, die mittels Zahlencode ausgewählt werden können.

  • :dig

    Zeigt eine Liste aller UTF-8 Symbole an. Um ein Symbol auszuwählen gibt man die zwei Zeichen ein, die vor jedem Symbol stehen. Dazu drückt man im Eingabemodus zuerst [STRG][k]. Dann sollte sich der Cursor ändern. Wenn man jetzt den zweistelligen Code eingibt erscheint danach das gewünschte Symbol.
    Beispielsweise führt [STRG][k] Tu zu diesem asiatischen Zeichen, dass eine nette Smilie-Alternative darstellt: ツ

Please comment. I really enjoy your thoughts!

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s