*usr_41.txt* Für Vim version 6.2. Letzte Änderung: 2003-Jun-01 VIM BENUTZERHANDBUCH - von Bram Moolenaar Ein Vim-Skript schreiben Vims Skriptsprache wird für die Startup-Datei vimrc, Syntax-Dateien und viele andere Dinge verwendet. Dieses Kapitel erklärt die Elemente, die in einem Vim-Skript benutzt werden können. Davon gibt es eine Menge, daher ist dies ein langes Kapitel. |41.1| Einführung |41.2| Variablen |41.3| Ausdrücke |41.4| Bedingungen |41.5| Einen Ausdruck ausführen |41.6| Funktionen benutzen |41.7| Eine Funktion definieren |41.8| Ausnahmen |41.9| Verschiedene Anmerkungen |41.10| Ein Plugin schreiben |41.11| Ein Dateityp-Plugin schreiben |41.12| Ein Kompiler-Plugin schreiben Nächstes Kapitel: |usr_42.txt| Neue Menüs hinzufügen Voriges Kapitel: |usr_40.txt| Neue Befehle machen Inhaltsübersicht: |usr_toc.txt| ============================================================================== *41.1* Einführung *vim-script-intro* Ihre erste Erfahrung mit Vim-Skripten ist die Datei vimrc. Vim liest sie beim Start und führt die Befehle aus. Sie können Optionen auf Werte setzen, die Sie bevorzugen. Und Sie können jeden Doppelpunkt-Befehl in ihr benutzen (Befehle, die mit »:« starten, diese werden manchmal Ex-Befehle oder Befehlszeilen-Befehle genannt. Syntax-Dateien sind ebenfalls Vim-Skripte. So wie Dateien, die für einen bestimmten Dateityp Optionen setzen. Ein kompliziertes Makro kann in einer eigenen Vim-Skript-Datei definiert werden. Sie können sich nun weitere Möglichkeiten ausmalen. Lassen Sie uns mit einem einfachen Beispiel beginnen: > :let i = 1 :while i < 5 : echo "Zähler ist" i : let i = i + 1 :endwhile < Anmerkung: Die »:« werden hier nicht wirklich gebraucht. Sie brauchen sie nur, wenn Sie einen Befehl in Vim tippen. In einer Vim-Skript-Datei können sie ausgelassen werden. Wir benutzen Sie hier dennoch, um klar zu machen, dass dies Doppelpunkt-Befehle sind, und um sie sich von den Befehlen des Normalmodus abheben zu lassen. In der ersten Zeile verknüpft der Befehl »:let« einen Wert mit einer Variablen. Die generische Form ist: > :let {variable} = {ausdruck} In diesem Falle ist der Variablenname »i« und der Ausdruck ist ein einfacher Wert, die Zahl eins. Der Befehl »:while« beginnt eine Schleife. Die generische Form ist: > :while {bedingung} : {anweisungen} :endwhile Die Anweisungen bis zum entsprechenden »:endwhile« werden so lange ausgeführt, wie die Bedingung wahr ist. Die hier benutzte Bedingung ist der Ausdruck »i < 5«. Dies ist wahr, wenn die Variable i kleiner als fünf ist. Der Befehl »:echo« gibt seine Argumente aus. In diesem Falle die Zeichenkette »Zähler ist« und den Wert der Variablen i. Da i eins ist, gibt dies aus: Zähler ist 1 ~ Dann kommt noch ein Befehl »:let i =«. Der benutzte Wert ist der Ausdruck »I + 1«. Dies addiert eins zu der Variablen i und weist den neuen Wert derselben Variablen zu. Die Ausgabe des Beispiel-Codes: Zähler ist 1 ~ Zähler ist 2 ~ Zähler ist 3 ~ Zähler ist 4 ~ Anmerkung: Falls Sie eine While-Schleife schreiben, die immer weiter läuft können Sie sie mit CTRL-C (CTRL-Pause unter Windows) unterbrechen. DREI ARTEN VON ZAHLEN Zahlen können dezimal, hexadezimal oder oktal sein. Eine hexadezimale Zahl beginnt mir »0x« oder »0X«. »0x1f« ist zum Beispiel dezimal 31. Eine oktale Zahl beginnt mit einer Null. »017« ist dezimal 15. Achtung: setzen Sie keine Null vor eine dezimale Zahl, sie wird dann als oktale Zahl interprätiert! Der Befehl »:echo« gibt immer dezimale Zahlen aus. Beispiel: > :echo 0x7f 036 < 127 30 ~ Eine Zahl wird mit einem Minus-Zeichen negativ gemacht. Dies funktioniert auch für hexadezimale und oktale Zahlen. Das Minus-Zeichen wird auch für die Substraktion verwandt. Vergleichen Sie dies mit dem vorigen Beispiel: > :echo 0x7f -036 < 97 ~ Whitespace in einem Ausdruck wird ignoriert. Dennoch empfiehlt es sich, ihn zu benutzen, um Elemente zu trennen, um den Ausdruck leichter lesbar zu machen. Um zum Beispiel oben die Verwechslung mit einer negativen Zahl zu vermeiden, setzen Sie ein Leerzeichen zwischen das Minus-Zeichen und die darauf folgende Zahl: > :echo 0x7f - 036 ============================================================================== *41.2* Variablen Ein Variablenname besteht aus ASCII-Buchstaben, Ziffern und dem Unterstrich. Er kann nicht mit einer Ziffer beginnen. Gültige Variablennamen sind: counter _aap3 very_long_variable_name_with_underscores FuncLength LENGTH Ungültige Namen sind »foo+bar« und »6var«. Diese Variablen sind global. Um eine Liste aktuell definierter Variablen zu sehen, benutzen Sie diesen Befehl: > :let Sie können überall globale Variablen verwenden. Dies bedeutet auch, dass, wenn eine Variable »zaehler« in einer Skript-Datei benutzt wird, sie auch in einer andereren Datei benutzt werden könnte. Dies führt bestenfalls zu Verwirrung, schlimmstenfalls zu wirklichen Problemen. Um dies zu vermeiden, können Sie eine Variable lokal zu einem Skript verwenden, indem Sie »s:« voranstellen. Ein Skript enthält zum Beispiel diesen Code: > :let s:count = 1 :while s:count < 5 : source other.vim : let s:count = s:count + 1 :endwhile Weil »s:count« lokal zu diesem Skript ist, können Sie sicher sein, dass das Einlesen von »other.vim« diese Variable nicht verändert. Falls »other.vim« ebenfalls eine Variable »s:count« enthält, ist dies eine andere Einheit, lokal zu diesem Skript. Mehr über Variablen, die lokal zu einem Skript sind, unter: |script-variable| Es gibt noch mehr Arten von Variablen, siehe |internal-variables|. Die am häufigsten gebrauchten sind: b:name Variable lokal zu einem Puffer w:name Variable lokal zu einem Fenster g:name globale Variable (auch in einer Funktion) v:name von Vim vordefinierte Variable VARIABLEN LöSCHEN Variablen belegen Speicher und erscheinen in der Ausgabe des Befehls »:let«. Um eine Variable zu löschen, benutzen Sie den Befehl »:unlet«. Beispiel: > :unlet s:count Dies löscht die skript-lokale Variable »s:count« um den Speicher freizugeben, den sie belegt. Wenn Sie nicht sicher sind, ob die Variable existiert und Sie keine Fehlermeldung wollen, wenn sie es nicht tut, hängen Sie »!« an: > :unlet! s:count Wenn ein Skript terminiert, werden die in ihm benutzten lokalen Variablen nicht automatisch freigegeben. Das nächste Mal, wenn das Skript ausgeführt wird, kann es immernoch den alten Wert benutzen. Beispiel: > :if !exists("s:aufruf_zaehler") : let s:aufruf_zaehler = 0 :endif :let s:aufruf_zaehler = s:aufruf_zaehler + 1 :echo s:aufruf_zaehler "Male aufgerufen" Die Funktion »exists()« prüft, ob eine Variable bereits definiert wurde. Ihr Argument ist der Name der Variablen, die man überprüfen will. Nicht die Variable selbst! Falls Sie dies tun würden: > :if !exists(s:aufruf_zaehler) Dann wird der Wert von s:aufruf_zaehler als der Name der Variablen, die exists() überprüft, genommen. Das ist nicht, was Sie wollen. Das Ausrufezeichen ! negiert einen Wert. Wenn der Wert wahr war, wird er falsch. Wenn er falsch war, wird er wahr. Sie können es als »nicht« lesen. Also kann »if !exists()« als »if not exists()« gelesen werden. Was Vim als wahr betrachtet, ist alles, was nicht Null ist. Null ist falsch. ZEICHENKETTENVARIABLEN UND -KONSTANTEN So weit wurden nur Zahlen für den Variablenwert benutzt. Zeichenketten können auch benutzt werden. Zahlen und Zeichenketten sind die Typen von Variablen, die Vim unterstützt. Der Typ ist dynamisch, er wird jedes Mal gesetzt, wenn der Variablen mit »:let« ein Wert zugewiesen wird. Um einer Variablen einen Zeichenkettenwert zuzuweisen, müssen Sie eine Zeichenkettenkonstante benutzen. Davon gibt es zwei Typen. Zuerst die Zeichenkette in doppelten Zitatzeichen: > :let name = "peter" :echo name < peter ~ Falls Sie ein doppeltes Zitatzeichen in die Zeichenkette einbeziehen wollen, stellen Sie ihm einen Rückwärtsschrägstrich voran: > :let name = "\"peter\"" :echo name < "peter" ~ Um den Rückwärtsschrägstrich zu vermeiden, können Sie eine Zeichenkette in einfachen Zitatzeichen verwenden: > :let name = '"peter"' :echo name < "peter" ~ In einer Zeichenkette mit einfachen Zitatzeichen sind alle Zeichen wie sie sind. Der Nachteil: Es ist unmöglich, ein einfaches Zitatzeichen einzubeziehen. Ein Rückwärtsschrägstrich wird wörtlich genommen, also können Sie ihn nicht benutzen, um die Bedeutung des Zeichens danach zu verändern. In Zeichenketten mit doppelten Zitatzeichen ist es möglich, besondere Zeichen zu verwenden. Hier sind ein Paar nützliche: \t \n , Zeilenumbruch \r , \e \b , Backspace \" " \\ \. Rückwärtsschrägstrich \ \ CTRL-W Die letzten zwei sind nur Beispiele. Die Form »\« kann benutzt werden, um die Sondertaste »name« einzubeziehen. Siehe |expr-quote| für die volle Liste besonderer Elemente in einer Zeichenkette. ============================================================================== *41.3* Ausdrücke Vim hat eine reichhaltige, aber dennoch einfache Weise, um Ausdrücke zu behandeln. Sie können die Definition hier lesen: |expression-syntax|. Hier werden wir die gebräuchlichsten zeigen. Die oben erwähnten Zahlen, Zeichenketten und Variablen sind selbst Ausdrücke. Also können Sie überall, wo ein Ausdruck erwartet wird, eine Zahl, Zeichenkette oder Variable verwenden. Andere Grundelemente in einem Ausdruck sind: $NAME Umgebungsvariable &name Option @r Register Beispiele: > :echo "Der Wert von 'tabstop' ist" &ts :echo "Ihr Heimverzeichnis ist" $HOME :if @a > 5 Die Form &name kann benutzt werden, um den Wert einer Option zwischen zu speichern, sie auf einen neuen Wert zu setzen, etwas zu tun und den alten Wert zu restaurieren. Beispiel: > :let save_ic = &ic :set noic :/Der Beginn/,$delete :let &ic = save_ic Dies stellt sicher, dass das Muster »Der Beginn« mit deaktivierter Option 'ignorecase' benutzt wird. Jedoch behält es den Wert, den der Benutzer gesetzt hat. MATHEMATIK Es wird interessanter, wenn wir diese Grundelemente kombinieren. Lassen Sie uns mit Mathematik auf Zahlen beginnen a + b Addition a - b Subtraktion a * b Multiplikation a / b Division a % b Modulo Die gewöhnliche Präzedenz wird benutzt. Beispiel: > :echo 10 + 5 * 2 < 20 ~ Gruppierung mit Klammern. Keine Überraschungen hier. Beispiel: > :echo (10 + 5) * 2 < 30 ~ Zeichenketten können mit ».« verkettet werden. Beispiel: > :echo "foo" . "bar" < foobar ~ Wenn der Befehl »:echo« mehrere Argumente erhält, trennt er sie mit einem Leerzeichen. In diesem Beispiel ist das Argument ein einzelner Ausdruck, also wird kein Leerzeichen eingefügt. Aus der Sprache C entliehen ist der konditionale Ausdruck: a ? b : c Falls »a« wahr ergibt, wird »b« verwandt, ansonsten wird »c« benutzt. Beispiel: > :let i = 4 :echo i > 5 ? "i is big" : "i is small" < i is small ~ Die drei Teile des Konstrukts werden immer zuerst berechnet, also könnten Sie als als das Folgende funktionieren sehen: (a) ? (b) : (c) ============================================================================== *41.4* Bedingungen Der Befehl »:if« führt die folgenden Anweisungen aus, bis zum übereinstimmenden »:endif«, nur wenn eine Bedingung erfüllt ist. Die generische Form ist: :if {bedingung} {anweisungen} :endif Nur wenn der Ausdruck {bedingung} wahr (nicht-null) ergibt, werden die {anweisungen} ausgeführt. Dies müssen immer noch gültige Befehle sein. Falls sie Müll enthalten, ist es Vim nicht möglich, das »:endif« zu finden. Sie können auch »:else« verwenden. Die generische Form hierfür ist: :if {bedingung} {anweisungen} :else {anweisungen} :endif Der zweite Block {anweisungen} wird nur ausgeführt, wenn der erste nicht wird. Schließlich gibt es »:elseif«: :if {bedingung} {anweisungen} :elseif {bedingung} {anweisungen} :endif Dies funktioniert genauso, wie »:else« und dann »if« zu verwenden, aber ohne ein extra »:endif« zu benutzen. Ein nützliches Beispiel für Ihre vimrc ist, die Option 'term' zu prüfen, und abhängig von ihrem Wert etwas zu tun: > :if &term == "xterm" : " Mache etwas für xterm :elseif &term == "vt100" : " Mache etwas für ein VT100-Terminal :else : " Mache etwas für andere Terminals :endif LOGISCHE OPERATIONEN Wir haben bereits einige in den Beispielen benutzt. Dies sind die am häufigsten verwandten: a == b gleich a != b ungleich a > b größer als a >= b größer als oder gleich a < b kleiner als a <= b kleiner als oder gleich Das Ergebnis ist eins, falls die Bedingung erfüllt ist, sonst null. Ein Beispiel: > :if v:version >= 600 : echo "Gratulation" :else : echo "Sie benutzen eine alte Version. Aktualisieren Sie!" :endif Hier ist »v:version« eine von Vim definierte Variable, die den Wert der Vim-Version hat. 600 ist für Version 6.0. Version 6.1 hat den Wert 601. Dies ist sehr nützlich beim Schreiben eines Skript, das mit verschiedenen Versionen von Vim funktionieren soll. |v:version| Die logischen Operatoren funktionieren sowohl für Zahlen wie auch für Zeichenketten. Beim Vergleich zweier Zeichenketten wird der mathematische Unterschied benutzt. Dies vergleicht Byte-Werte, was für manche Sprachen eventuell nicht richtig ist. Beim Vergleich einer Zeichenkette mit einer Zahl wird die Zeichenkette zuerst in eine Zahl verwandelt. Dies ist ein wenig verzwickt, wenn eine Zeichenkette nicht wie eine Zahl aussieht, wird die Zahl Null verwandt. Beispiel: > ;if 0 == "eins" : echo "ja" :endif Dies gibt »ja« aus, weil »eins« nicht wie eine Zahl aussieht, es also zur Zahl Null konvertiert wird. Für Zeichenketten gibt es zwei weitere Elemente: a =~ b stimmt mit überein a !~ b stimmt nicht mit überein Das linke Element »a« wird als Zeichenkette verwandt. Das rechte Element »b« wird als Muster benutzt, wie beim Suchen. Beispiel: > :if str =~ " " : echo "str enthält ein Leerzeichen" :elseif str !~ '\.$' : echo "str endet nicht mit einem Punkt" :endif Beachten Sie den Gebrauch der einfach zitierten Zeichenkette. Dies ist nützlich, weil Rückwärtsschrägstriche in doppelt zitierten Zeichenketten verdoppelt werden müssten, und Muster dazu neigen, viele Rückwärtsschrägstriche zu enthalten. Die Option 'ignorecase' wird beim Vergleich von Zeichenketten benutzt. Wenn Sie dies nicht wollen, hängen Sie »#« an, für Übereinstimmung von Groß-/Kleinschreibung, und »?«, um dies zu ignorieren. Also vergleicht »==?« zwei Zeichenketten auf Gleichheit, während Groß-/Kleinschreibung ignoriert wird. Und »!~#« prüft, ob ein Muster nicht passt, auch Groß-/Kleinschreibung überprüfend. Für die volle Tabelle siehe |expr-==|. MEHR ÜBER SCHLEIFEN Der Befehl »:while« wurde bereits erwähnt. Zwei weitere Anweisungen können zwischen dem »:while« und dem »:endwhile« benutzt werden: :continue Springe zurück zum Beginn der While-Schleife; die Schleife wird fortgesetzt. :break Springe vorwärts zum »:endwhile«; die Schleife wird abgebrochen. Beispiel: > :while zaehler < 40 : call tue_etwas() : if flag_ueberspringen : continue : endif : if flag_beendet : break : endif : sleep 50m :endwhile Der Befehl »:sleep« lässt Vim ein Nickerchen machen. »50m« gibt fünzig Millisekunden an. Ein weiteres Beispiel ist »:sleep 4«, was für vier Sekunden schläft. ============================================================================== *41.5* Einen Ausdruck ausführen So weit wurden die Befehle in dem Skript von Vim direkt ausgeführt. Der Befehl »:execute« erlaubt das Ausführen des Ergebnisses eines Ausdrucks. Dies ist eine sehr mächtige Möglichkeit, Befehle aufzubauen und sie ausführen zu lassen. Ein Beispiel ist ein Tag anzuspringen, das in einer Variablen enthalten ist: > :execute "tag " . tag_name Der ».« wird verwandt, um die Zeichenkette »tag « mit dem Wert der Variablen »tag_name« zu verketten. Angenommen, »tag_name« hat den Wert »get_cmd«, dann ist der ausgeführte Befehl: > :tag get_cmd Der Befehl »:execute« kann nur Doppelpunkt-Befehle ausführen. Der Befehl »:normal« führt Befehl des Normalmodus aus. Jedoch ist sein Argument kein Ausdruck, sondern die wörtlichen Befehlszeichen. Beispiel: > :normal gg=G Dies springt in die erste Zeile und formatiert alle Zeilen mit dem Operator »=«. Damit »:normal« mit einem Ausdruck funktioniert, kombinieren Sie »:execute« mit ihm. Beispiel: > :execute "normal " . normal_befehle Die Variable »normal_befehle« muss die Normal-Modus-Befehle enthalten. Stellen Sie sicher, dass das Argument für »:normal« ein vollständiger Befehl ist. Ansonsten läuft Vim in das Ende des Arguments und führt den Befehl nicht aus. Falls Sie zum Beispiel den Einfüge-Modus starten, müssen Sie auch den Einfüge-Modus verlassen. Dies funktioniert: > :execute "normal INeuer Text \" Dies fügt »Neuer Text « in der aktuellen Zeile ein. Beachten Sie den Gebrauch der Sondersequenz »\«. Dies vermeidet, dass sie ein wirkliches -Zeichen in Ihr Skript einfügen müssen. ============================================================================== *41.6* Funktionen benutzen Vim definiert viele Funktionen und bietet so einen großen Betrag an Funktionaltität. Einige wenige Beispiele werden in diesem Abschnitt gegeben. Sie können die ganze Liste hier finden: |functions|. Eine Funktion wird mit dem Befehl »:call« aufgerufen. Die Parameter werden in Klammern übergeben, getrennt durch Kommata. Beispiel: > :call search("Date: ", "W") Dies ruft die Funktion search() auf, mit den Argumenten »Date: « und »W«. Die Funktion search() benutzt ihr erstes Argument als Suchmuster und das zweite als Flags. Das Kennzeichen »W« bedeutet, dass die Suche am Ende der Datei nicht an ihrem Beginn fortgesetzt werden soll (wrap around). Eine Funktion kann in einem Ausdruck aufgerufen werden. Beispiel: > :let zeile = getline(".") :let ersetzt = substitute(zeile, '\a', "*", "g") :call setline(".", ersetzt) Die Funktion getline() holt eine Zeile aus der aktuellen Datei. Ihr Argument ist eine Spezifikation der Zeilennummer. In diesem Falle wird ».« benutzt, was die Zeile meint, wo sich der Cursor befindet. Die Funktion substitute() tut etwas ähnliches wie der Befehl »:substitute«. Das erste Argument ist die Zeichenkette, auf der die Ersetzung stattfinden soll. Das zweite Argument ist das Muster, das dritte die Ersetzungszeichenkette. Schließlich sind die letzten Argumente die Flags. Die Funktion setline() setzt die Zeile, die durch das erste Argument spezifiziert wird, auf eine neue Zeichenkette, das zweite Argument. In diesem Beispiel wird die Zeile unter dem Cursor ersetzt durch das Ergebnis von substitute(). Also ist der Effekt der drei Anweisungen gleich: > :substitute/\a/*/g Die Funktionen benutzen wird interessanter, wenn Sie mehr Arbeit vor und nach dem Aufruf von substitute() erledigen. FUNKTIONEN *function-list* Es gibt viele Funktionen. Wir werden Sie hier erwähnen, gruppiert nach ihrem Verwendungszweck. Sie können hier eine alphabetische Liste finden: |functions|. Benutzen Sie CTRL-] auf dem Funktionsnamen, um zu einer detailierten Hilfe zu ihr zu springen. Zeichenketten-Manipulation nr2char() gibt ein Zeichen nach seinem ASCII-Wert char2nr() gibt den ASCII-Wert eines Zeichens escape() schützt Zeichen in einer Zeichenkette mit einem »\« strtrans() übersetzt eine Zeichenkette, um sie druckbar zu machen tolower() konvertiert eine Zeichenkette in Kleinbuchstaben toupper() konvertiert eine Zeichenkette in Großbuchstaben match() Position, wo ein Muster in einer Zeichenkette übereinstimmt matchend() Postion, wo eine Musterübereinstimmung in einer Zeichenkette endet matchstr() Übereinstimmung eines Musters in einer Zeichenkette stridx() erster Index einer kurzen in einer langen Zeichenkette strridx() letzter Index einer kurzen in einer langen Zeichenkette strlen() Länge einer Zeichenkette substitute() ersetze eine Musterübereinstimmung durch eine Zeichenkette strpart() liefert Teil einer Zeichenkette expand() expandiert besondere Schlüsselwörter type() Typ einer Variablen Arbeiten mit dem Text im aktuellen Puffer: byte2line() liefert Zeilennummer bei einer bestimmten Byte-Zahl line2byte() Byte-Zahl bei einer bestimmten Zeile col() Spalten-Nummer des Cursors oder einer Marke virtcol() Bildschirm-Spalte des Cursors oder einer Marke line() Zeilen-Nummer von Cursor oder Marke wincol() Fensterspaltennummer des Cursors winline() Fensterzeilennummer des Cursors getline() liefert eine Zeile oder Liste von Zeilen aus dem aktuellen Puffer setline() ersetzt eine Zeile im Puffer append() fügt eine Zeichenkette an einer Zeilennummer an indent() Einrückung einer bestimmten Zeile cindent() rückt eine Zeile nach Einrückung für C ein lispindent() rückt eine Zeile nach Einrückung für Lisp ein nextnonblank() findet nächste nicht-leere Zeile prevnonblank() findet vorige nicht-leere Zeile search() findet eine Übereinstimmung für ein Muster searchpair() findet das andere Ende eines Start/Skip/End Systemfunktionen und Manipulation von Dateien: browse() öffnet Datei-Anfrage glob() expandiere Wildcards globpath() expandiere Wildcards in einer Reihe von Verzeichnissen resolve() findet heraus, wohin ein Shortcut zeigt fnamemodify() modifiziert einen Dateinamen executable() prüft, ob ein ausführbares Programm existiert filereadable() prüft, ob eine Datei gelesen werden kann isdirectory() prüft, ob ein Verzeichnis existiert getfsize() liefert die Größe einer Datei getftime() liefert Modifikationszeit einer Datei localtime() liefert aktuelle Zeit strftime() konvertiert Zeit in Zeichenkette getcwd() liefert das aktuelle Arbeitsverzeichnis tempname() liefert den Namen einer temporären Datei delete() löscht eine Datei rename() benennt eine Datei um system() liefert das Ergebnis eines Shell-Befehls hostname() Rechnername Puffer, Fenster und die Argumentenliste: argc() Anzahl von Einträgen in der Argumentenliste argidx() aktuelle Position in der Argumentenliste argv() liefert einen Eintrag aus der Argumentenliste bufexists() prüft, ob ein Puffer existiert buflisted() prüft, ob ein Puffer existiert und gelistet ist bufloaded() prüft, ob ein Puffer existiert und geladen ist bufname() liefert den Namen eines bestimmten Puffers bufnr() liefert die Puffernummer eines bestimmten Puffers winnr() liefert die Fensternummer für das aktuelle Fenster bufwinnr() liefert die Fensternummer eines bestimmten Puffers winbufnr() liefert die Puffernummer eines bestimmten Fensters Falten: foldclosed() prüft auf eine geschlossene Faltung in einer bestimmten Zeile foldlevel() prüft auf die Faltungsebene in einer bestimmten Zeile foldtext() erzeugt die für eine geschlossene Faltung angezeigte Zeile Syntax und Hervorhebung: hlexists() prüft, ob eine Hervorhebungsgruppe existiert hlID() liefert ID einer Hervorhebungsgruppe synID() liefert Syntax-ID an einer bestimmten Position synIDattr() liefert ein bestimmtes Attribut einer Syntax-ID synIDtrans() liefert übersetzte Syntax-ID Verläufe: histadd() fügt ein Element einem Verlauf hinzu histdel() löscht ein Element aus einem Verlauf histget() liefert ein Element aus einem Verlauf histnr() liefert den höchsten Index einer Verlaufsliste Interaktiv: confirm() lässt den Benutzer eine Auswahl machen getchar() holt ein Zeichen vom Benutzer getcharmod() liefert die Modifikatoren für das letzte eingegebene Zeichen input() holt eine Zeile vom Benutzer inputsecret() holt eine Zeile vom Benutzer ohne sie anzuzeigen inputdialog() holt eine Zeile vom Benutzer in einem Dialog Vim-Server: serverlist() gibt eine Liste von Server-Namen zurück remote_send() sendet Befehlszeichen an einen Vim-Server remote_expr() wertet einen Ausdruck in einem Vim-Server aus server2client() sendet eine Antwort an einen Client eines Vim-Servers remote_peek() prüft, ob es eine Antwort von einem Vim-Server gibt remote_read() liest eine Antwort von einem Vim-Server foreground() bewegt das Vim-Fenster in den Vordergrund remote_foreground() bewegt das Fenster des Vim-Servers in den Vordergrund Verschiedenes: mode() liefert aktuelle Editiermodus visualmode() der letzte benutzte visuelle Modus hasmapto() prüft, ob eine Belegung existiert mapcheck() prüft, ob eine passende Belegung existiert maparg() liefert die rechte Seite einer Belegung exists() prüft, ob eine Variable, Funktion usw. existiert has() prüft, ob ein Feature von Vim unterstützt wird cscope_connection() prüft, ob eine CScope-Anbindung existiert did_filetype() prüft, ob ein automatischer Befehl eines Dateityps benutzt wurde eventhandler() prüft, ob von einem Ereignis-Behandler aufgerufen wurde getwinposx() X-Position des Vim-GUI-Fensters getwinposy() Y-Position des Vim-GUI-Fensters winheight() liefert Höhe eines bestimmten Fensters winwidth() liefert Breite eines bestimmten Fensters libcall() ruft eine Funktion in einer externen Bibliothek auf libcallnr() ebenso, gibt eine Zahl zurück ============================================================================== *41.7* Eine Funktion definieren Vim ermöglicht es Ihnen, eigene Funktionen zu definieren. Die grundlegende Funktions-Deklaration beginnt wie folgt: > :function {name}({var1}, {var2}, ...) : {body} :endfunction < Anmerkung: Funktions-Namen müssen mit einem Großbuchstaben beginnen. Lassen Sie uns eine kurze Funktion definieren, die die kleinere von zwei Zahlen zurückgibt. Sie beginnt mit dieser Zeile: > :function Min(num1, num2) Dies sagt Vim, dass die Funktion »Min« heißt und zwei Argumente nimmt, »num1« und »num2«. Als erstes müssen wir überprüfen, welche Zahl kleiner ist: > : if a:num1 < a:num2 Das besondere Präfix »a:« sagt Vim, dass die Variable ein Funktions-Argument ist. Weisen wir nun der Variablen »smaller« den Wert der kleineren Zahl zu: > : if a:num1 < a:num2 : let smaller = a:num1 : else : let smaller = a:num2 : endif Die Variable »smaller« ist eine lokale Variable. In einer Funktion benutzte Variablen sind lokal, solange ihnen nicht etwas wie »g:«, »a:« oder »s:« vorangestellt wird. Anmerkung: Um innerhalb einer Funktion auf eine globale Variable zuzugreifen, müssen Sie ihr »g:« voranstellen. Also wird innerhalb einer Funktion »g:count« für die globale Funktion »count« verwandt, und ein einfaches »count« ist eine andere Variable, die zur Funktion lokal ist. Nun benutzen wir die Anweisung »:return« um die kleinere Zahl an den Aufrufer zurückzugeben. Die Funktion endet schließlich: > : return smaller :endfunction Die vollständige Funktions-Definition ist wie folgt: > :function Min(num1, num2) : if a:num1 < a:num2 : let smaller = a:num1 : else : let smaller = a:num2 : endif : return smaller :endfunction Eine benutzerdefinierte Funktion wird genauso aufgerufen, wie eine eingebaute. Nur der Name ist verschieden. Die Funktion Min kann so benutzt werden: > :echo Min(5, 8) Erst jetzt wird die Funktion ausgeführt, und die Zeilen werden von Vim interpretiert. Falls es Fehler gibt, wie das Nutzen einer undefinierten Variablen oder Funktion, erhalten Sie nun eine Fehlermeldung. Beim Definieren der Funktion werden diese Fehler nicht erkannt. Wenn eine Funktion »:endfunction« erreicht, oder »:return« wird ohne Argument benutzt, gibt die Funktion Null zurück. Um eine bereits existierende Funktion erneut zu definieren, benutzen Sie »:function« mit dem !-Modifikator: > :function! Min(num1, num2, num3) EINEN BEREICH BENUTZEN Dem Befehl »:call« kann ein Zeilenbereich gegeben werden. Dies kann eine von zwei Bedeutungen haben. Wenn eine Funktion mit dem Schlüsselwort »range« definiert wurde, kümmert sie sich selbst um den Zeilenbereich. Der Funktion werden die Variablen »a:firstline« und »a:lastline« übergeben. Diese haben die Zeilennummern des Bereiches, mit dem die Funktion aufgerufen wurde. Beispiel: > :function Count_words() range : let n = a:firstline : let count = 0 : while n <= a:lastline : let count = count + Wordcount(getline(n)) : let n = n + 1 : endwhile : echo "found " . count . " words" :endfunction Sie können diese Funktion aufrufen mit: > :10,30call Count_words() Sie wird einmal ausgeführt und gibt die Anzahl an Worten aus. Die andere Möglichkeit einen Zeilenbereich zu benutzen ist, eine Funktion ohne das Schlüsselwort »range« zu definieren. Die Funktion wird einmal für jede Zeile in dem Bereich aufgerufen, mit dem Cursor in dieser Zeile. Beispiel: > :function Number() : echo "line " . line(".") . " contains: " . getline(".") :endfunction Falls Sie diese Funktion aufrufen mit: > :10,15call Number() wird die Funktion sechs Mal aufgerufen. VARIABLE ANZAHL VON ARGUMENTEN Vim ermöglicht Ihnen, Funktionen zu definieren, die eine variable Anzahl von Argumenten haben. Der folgende Befehl zum Beispiel definiert eine Funktion, die ein Argument haben muss (start), und die bis zu 20 zusätzliche Argumente haben kann: > :function Show(start, ...) Die Variable »a:1« enthält das erste optionale Argument, »a:2« das zweite und so weiter. Die Variable »a:0« enthält die Anzahl von zusätzlichen Argumenten Zum Beispiel: > :function Show(start, ...) : echohl Title : echo "Show is " . a:start : echohl None : let index = 1 : while index <= a:0 : execute 'echon " Arg " . index . " is " . a:' . index : let index = index + 1 : endwhile : echo "" :endfunction Dies benutzt den Befehl »:echohl« um die für den nächsten »:echo«-Befehl benutzte Hervorhebung anzugeben. »:echohl None« deaktiviert dies. Der Befehl »:echon« funktioniert wie »:echo«, gibt aber keinen Zeilenumbruch aus. FUNKTIONEN AUFLISTEN Der Befehl »:function« listet die Namen und Argumente aller benutzerdefinierten Funktionen auf: > :function < function Show(start, ...) ~ function GetVimIndent() ~ function SetSyn(name) ~ Um zu sehen, was eine Funktion tut, benutzen Sie ihren Namen als Argument für »:function«: > :function SetSyn < 1 if &syntax == '' ~ 2 let &syntax = a:name ~ 3 endif ~ endfunction ~ FEHLERSUCHE Die Zeilennummer ist nützlich, wenn Sie eine Fehlermeldung erhalten, oder bei der Fehlersuche. Siehe |debug-scripts| für den Fehlersuche-Modus. Sie können auch die Option 'verbose' auf 12 oder höher setzen, um alle Funktionsaufrufe zu sehen. Setzen Sie sie auf 15 oder höher um jede ausgeführte Zeile zu sehen. EINE FUNKTION LÖSCHEN Um die Funktion Show() zu löschen: > :delfunction Show Sie erhalten eine Fehlermeldung, wenn die Funktion nicht existiert. ============================================================================== *41.8* Ausnahmen Beginnen wir mit einem Beispiel: > :try : read ~/templates/pascal.tmpl :catch /E484:/ : echo "Sorry, the Pascal template file cannot be found." :endtry Der Befehl »:read« scheitert, falls die Datei nicht existiert. Statt eine Fehlermeldung zu generieren, fängt dieser Code den Fehler auf und gibt dem Benutzer stattdessen eine nette Meldung. Für die Befehle zwischen »:try« und »:endtry« werden Fehler in Ausnahmen verwandelt. Eine Ausnahme ist eine Zeichenkette. Im Falle eines Fehlers enthält die Zeichenkette die Fehlernummer. Und jede Fehlermeldung hat eine Nummer. In diesem Fall enthält der Fehler, den wir auffangen, »E484:«. Diese Nummer bleibt garantiert dieselbe (der Text kann sich ändern, z.B. übersetzt werden). Wenn der Befehl »:read« einen anderen Fehler verursacht, passt das Muster »E484:« nicht. Also wird diese Ausnahme nicht aufgefangen und resultiert in der üblichen Fehlermeldung. Sie sind vielleicht versucht, dies zu tun: > :try : read ~/templates/pascal.tmpl :catch : echo "Sorry, the Pascal template file cannot be found." :endtry Dies bedeutet, dass alle Fehler aufgefangen werden. Dann aber sehen Sie keine nützlichen Fehler, so wie eine ungültige Moduszeile. Ein weiterer nützlicher Mechanismus ist der Befehl »:finally«: > :let tmp = tempname() :try : exe ".,$write " . tmp : exe "!filter " . tmp : .,$delete : exe "$read " . tmp :finally : call delete(tmp) :endtry Dies filtert die Zeilen vom Cursor bis zum Dateiende durch das Programm »filter«, das einen Dateinamen als Argument nimmt. Egal, ob das Filtern funktioniert, etwas geht zwischen »:try« und »:finally« schief, oder der Benutzer bricht das Filtern ab, indem er CTRL-C drückt, »call delete(tmp)« wird jederzeit ausgeführt. Dies stellt sicher, dass man nicht die temporäre Datei zurücklässt. Weiter Informationen über Ausnahme-Behandlung können im Referenzhandbuch gefunden werden: |exception-handling|. ============================================================================== *41.9* Verschiedene Anmerkungen Hier ist eine Sammlung von Elementen, die auf Vim-Skripte zutreffen. Sie werden auch anderswo erwähnt, aber formen eine nette Prüfliste. Das Zeichen für das Zeilenende hängt vom System ab. Unix benutzt ein einzelnes -Zeichen. Unter MS-DOS, Windows, OS/2 und so wird benutzt. Dies ist wichtig, wenn Belegungen verwandt werden, die in einem enden. Siehe |:source_crnl|. WHITE SPACE Leere Zeilen sind erlaubt und werden ignoriert. Führende Leerzeichen und Tabulatoren werden immer ignoriert. Der Whitespace zwischen Parametern (z.B zwischen dem 'set' und dem 'cpoptions' im Beispiel unten) wird reduziert auf ein Leerzeichen und spielt die Rolle eines Trenners, der Whitespace nach dem letzten (sichtbaren) Zeichen kann situationsabhängig ignoriert werden oder auch nicht, siehe unten. Für einen »:set«-Befehl, der das Zeichen »=« (gleich) enthält, so wie in: > :set cpoptions =aABceFst wird der Whitespace unmittelbar vor dem Zeichen »=« ignoriert. Aber es darf kein Whitespace nach dem »=«-Zeichen sein! Um ein Whitespace-Zeichen im Wert einer Option zu verwenden, muss es durch einen »\« (Backslash) geschützt werden, wie in dem folgenden Beispiel: > :set tags=my\ nice\ file Dasselbe Bespiel geschrieben als > :set tags=my nice file resultiert in einem Fehler, weil es interpretiert wird als: > :set tags=my :set nice :set file KOMMENTARE Das Zeichen " (das doppelte Anführungszeichen) leitet einen Kommentar ein. Alles nach und einschließlich dieses Zeichens bis zum Zeilenende wird als Kommentar betrachtet und ignoriert, außer bei Befehlen, die keine Kommentare beachten, wie in den Beispielen unten gezeigt. Ein Kommentar kann an jeder Zeichen-Position auf der Zeile beginnen. Bei einigen Befehlen gibt es »Fallen« mit Kommentaren. Beispiele: > :abbrev dev development " shorthand :map o#include " insert include :execute cmd " do it :!ls *.c " list C files Die Abkürzung 'dev' wird expandiert zu 'development " shorthand'. Die Belegung von ist tatsächlich die ganze Zeile nach dem 'o# ....', einschließlich dem '" insert include'. Der »execute«-Befehl ergibt einen Fehler. Der »!«-Befehl schickt alles nach ihm an die Shell, was einen Fehler wegen eines unbalancierten '"'-Zeichens verursacht. Nach den Befehlen »:map«, »:abbreviate«, »:execute« und »!« kann kein Kommentar stehen (es gibt ein paar Befehle mehr mit dieser Einschränkung). Für die Befehle »:map«, »:abbreviate« und »:execute« gibt es einen Trick: > :abbrev dev development|" shorthand :map o#include|" insert include :execute cmd |" do it Mit dem Zeichen '|' wird ein Befehl vom nächsten getrennt. Und dieses nächste Zeichen ist nur ein Kommentar. Man beachte, das hier kein Leerzeichen vor dem '|' in der Abkürzung und der Belegung ist. Bei diesen Befehlen wird jedes Zeichen bis zum Zeilenende oder dem '|' einbezogen. Als Konsequenz dieses Verhaltens sieht man nicht immer, das nachstehende Leerzeichen einbezogen werden: > :map o#include Um diese Probleme zu vermeiden, können Sie die Option 'list' setzen, wenn Sie vimrc-Dateien editieren. FALLEN Ein noch größeres Problem ensteht im folgenden Beispiel: > :map ,ab o#include :unmap ,ab Hier funktioniert der unmap-Befehl nich, weil er versucht »,ab « freizugeben. Dies existiert nicht als Belegungsfolge. Ein Fehler wird ausgegeben, der sehr schwer zu identifizieren ist, weil das nachstehende Leerzeichen in »:unmap ,ab « nicht sichtbar ist. Und es ist dasselbe wie wenn man einen Kommentar nach einem »unmap«-Befehl benutzt: > :unmap ,ab " comment Hier wird der Teil, der Kommentar, ist ignoriert. Vim versucht dennoch »,ab «, freizugeben, was nicht existiert. Wir schreiben es um als: > :unmap ,ab| " comment DIE ANSICHT WIEDERHERSTELLEN Manchmal will man eine Änderung machen und dahin zurück gehen, wo der Cursor war. Die relative Position wiederherstellen wäre auch nett, so dass dieselbe Zeile die oberste im Fenster ist. Dieses Beispiel kopiert die aktuelle Zeile, setzt sie über die erste Zeile der Datei, und stellt dann die Ansicht wieder her: > map ,p ma"aYHmbgg"aP`bzt`a Was dies tut: > ma"aYHmbgg"aP`bzt`a < ma setze Markierung a bei Cursor-Position "aY kopiere aktuelle Zeile in Register a Hmb gehe zur obersten Zeile im Fenster und setze dort Markierung b gg gehe zur ersten Zeile der Datei "aP setze kopierte Zeile über sie `b gehe zurück zur obersten Zeile der Anzeige zt positioniere den Text im Fenster wie vorher `a gehe zurück zur gespeicherten Cursor-Position PAKETIERUNG Um zu vermeiden, dass Ihre Funktionsnamen Funktionen beeinflussen, die Sie von anderen erhalten, benutzen Sie dieses Schema: - Stellen Sie jedem Funktionsnamen eine einzigartige Zeichenkette voran. Ich benutze oft eine Abkürzung. Zum Beispiel wird »OW_« für Funktionen des Optionsfensters verwandt. - Packen Sie die Definitionen Ihrer Funktionen in eine Datei. Setzen Sie eine globale Variable, die anzeigt, dass die Funktionen geladen wurden. Wenn die Datei erneut eingelesen wird, geben Sie erst die Funktionen frei. Beispiel: > " Dies ist das Paket XXX if exists("XXX_loaded") delfun XXX_one delfun XXX_two endif function XXX_one(a) ... body of function ... endfun function XXX_two(b) ... body of function ... endfun let XXX_loaded = 1 ============================================================================== *41.10* Ein Plugin schreiben *write-plugin* Sie können ein Vim-Skript so schreiben, dass viele Leute es benutzen können. Dies nennt sich Plugin. Vim-Benutzer können Ihr Skript in ihr Plugin-Verzeichnis legen und seine Features auf der Stelle nutzen |add-plugin|. Tatsächlich gibt es zwei Typen von Plugins: globale Plugins: Für alle Typen von Dateien. Dateityp-Plugins: Nur für Dateien eines bestimmten Typs. In diesem Abschnitt wird der erste Typ erklärt. Die meisten Elemente sind auch relevant für das Schreiben von Dateityp-Plugins. Die Spezifika für Dateityp-Plugins folgen im nächsten Abschnitt |write-filetype-plugin|. NAME Zuallererst müssen Sie einen Namen für Ihr Plugin wählen. Die Features, die von dem Plugin bereitgestellt werden werden, sollten anhand seines Namens klar sein. Und es sollte unwahrscheinlich sein, dass jemand anderes ein Plugin mit demselben Namen schreibt, das etwas anderes tut. Und bitte begrenzen Sie den Namen auf acht Zeichen, um Probleme auf alten Windows-Systemen zu vermeiden. Ein Skript, welches Tipp-Fehler korrigiert, könnte »typecorr.vim« genannt werden. Wir benutzen es hier als Beispiel. Damit das Plugin für jeden funktioniert, sollte es einigen wenigen Richtlinien folgen. Diese werden Schritt-für-Schritt erklärt. Das komplette Beispiel-Plugin steht am Ende. KÖRPER Lassen Sie uns mit dem Körper des Plugins beginnen, den Zeilen, die tatsächlich die Arbeit erledigen: > 14 iabbrev teh the 15 iabbrev otehr other 16 iabbrev wnat want 17 iabbrev synchronisation 18 \ synchronization 19 let s:count = 4 Die tatsächliche Liste sollte selbstverständlich viel länger sein. Die Zeilennummern wurden nur hinzugefügt, um ein Paar Dinge zu erläutern, übernehmen Sie sie nicht in Ihre Plugin-Datei! KOPF Sie werden dem Plugin vermutlich neue Korrekturen hinzufügen, und bald haben Sie mehrere Versionen herumliegen. Und wenn Sie die Datei verteilen, werden die Leute wissen wollen, wer dieses wundervolle Plugin schrieb und wohin sie Anmerkungen schicken können. Deshalb stellen Sie Kopfzeilen an den Beginn Ihres Plugins: > 1 " Vim global plugin for correcting typing mistakes 2 " Last Change: 2000 Oct 15 3 " Maintainer: Bram Moolenaar Über Copyright und Lizensierung: Da Plugins sehr nützlich sind, und es kaum wert ist, ihre Verteilung zu begrenzen, erwägen Sie bitte, Ihr Plugin entweder in die Public-Domain oder unter die Vim-Lizenz |license| zu stellen. Eine kurze Zeile hierüber nahe des Beginn des Plugins sollte ausreichend sein. Beispiel: > 4 " License: This file is placed in the public domain. ZEILENFORTSETZUNG, SEITENEFFEKTE VERMEIDEN *use-cpo-save* Oben in Zeile 18 wird der Mechanismus der Zeilen-Fortsetzung benutzt |line-continuation|. Benutzer, bei denen 'compatible' gesetzt ist, werden hier Probleme, eine Fehlermeldung bekommen. Wir können nicht einfach 'compatible' neu setzen, weil dies viele Seiteneffekte hat. Um dies zu vermeiden, setzen wir die Option 'cpoptions' auf ihren Vim-Standardwert und stellen sie später wieder her. Das erlaubt die Benutzung von Zeilen-Fortsetzung und lässt das Skript für die meisten Leute funktionieren. Es wird so gemacht: > 11 let s:save_cpo = &cpo 12 set cpo&vim .. 42 let &cpo = s:save_cpo Wir speichern zunächst den alten Wert von 'cpoptions' in der Variablen s:save_cpo. Am Ende des Plugins wird dieser Wert wiederhergestellt. Beachten Sie, dass eine skript-lokale Variable benutzt wird |s:var|. Eine globale Variable könnte bereits für etwas anderes in Gebrauch sein. Benutzen Sie immer skript-lokale Variablen für Dinge, die nur in dem Skript benutzt werden. NICHT LADEN Es ist möglich, dass ein Nutzer nicht immer dieses Plugin laden möchte. Oder der System-Administrator hat es in das system-weite Plugin-Verzeichnis gelegt, aber ein Nutzer hat sein eigenes Plugin, das er nutzen möchte. Dann muss der Nutzer eine Möglichkeit haben, das Laden dieses bestimmten Plugins zu deaktivieren. Dies macht es möglich: > 6 if exists("loaded_typecorr") 7 finish 8 endif 9 let loaded_typecorr = 1 Dies vermeidet es auch, dass wenn das Skript zweimal geladen wird, dass es Fehlermeldungen für das Neudefinieren von Funktionen und Schwierigkeiten bei automatischen Befehlen, die zweimal hinzugefügt werden, verursacht. BELEGUNGEN Nun lassen Sie uns das Plugin interessanter machen: Wir fügen eine Belegung hinzu, die eine Korrektur für das Wort unter dem Cursor hinzufügt. Um dem Nutzer zu erlauben, zu definieren, welche Tasten eine Belegung in einem Plugin benutzt, kann das Element benutzt werden: > 22 map a TypecorrAdd Das »TypecorrAdd« macht die Arbeit, mehr darüber weiter unten. Der Nutzer kann die Variable »mapleader« auf die Tastenfolge setzen, mit der er diese Belegung starten lassen möchte. Falls der Nutzer also dies macht: > let mapleader = "_" definiert die Belegung »_a«. Falls der Nutzer dies nicht tat, wird der Standardwert benutzt, was ein Backslash ist. Dann wird eine Belegung für »\a« definiert. Beachten Sie, dass benutzt wird, dies verursacht eine Fehlermeldung, falls die Belegung der Tastenfolge bereits existiert. |:map-| Aber was, falls der Nutzer seine eigene Tastenfolge definieren möchte? Wir können dies mit folgendem Mechanismus erlauben: > 21 if !hasmapto('TypecorrAdd') 22 map a TypecorrAdd 23 endif Dies prüft, ob eine Belegung von »TypecorrAdd« bereits existiert, und definiert die Belegung von »a« nur dann, falls nicht. Der Nutzer hat nun die Möglichkeit, dies in seine vimrc zu packen: > map ,c TypecorrAdd Dann ist die belegte Tastenfolge »,c« statt »_a« oder »\a«. STÜCKE Wenn ein Skript länger wird, möchte man oft die Arbeit in Portionen aufteilen. Man kann hierfür Funktionen oder Belegungen benutzen. Aber man will nicht, dass diese Funktionen oder Belegungen andere Skripte beeinflussen. Man könnte zum Beispiel eine Funktion Add() definieren, aber ein anderes Skript könnte versuchen, dieselbe Funktion zu definieren. Um dies zu vermeiden, definieren wir die Funktion lokal zum Skript, indem wir ihr »s:« voranstellen. Wir definieren eine Funktion, die eine neue Tipp-Korrektur hinzufügt: > 30 function s:Add(from, correct) 31 let to = input("type the correction for " . a:from . ": ") 32 exe ":iabbrev " . a:from . " " . to .. 36 endfunction Jetzt können wir innerhalb des Skripts die Funktion s:Add() aufrufen. Falls ein anderes Skript ebenfalls s:Add() definiert, ist sie lokal zu jenem Skript und kann nur von dem Skript aufgerufen werden, in dem sie definiert wurde. Es kann auch eine globale Funktion Add() geben (ohne »s:«, die wieder eine andere Funktion ist. kann mit Belegungen verwandt werden. Es generiert eine Skript-ID, die das aktuelle Skript identifiziert. In unserem Tipp-Korrektur-Plugin verwenden wir es folgendermaßen: > 24 noremap