Neue Z Shell Vervollständigung mit compsys

Zuletzt editiert am: Do Apr 1 09:57:40 CEST 2004
Die Zsh besitzt seit ein paar Jahren einen neuartigen, Funktionen basierten Vervollständigungsmechanismus der Kommandozeile, der sehr weitgreifende Vervollständigungen samt dem Einsatz von Kommentaren in der Vervollständigung möglich macht.

Mit autoload -U compinit && compinit wird dieser neue Mechanismus wirksam, was man in der Datei .zshrc eintragen sollte. Jetzt sind über 440 mitgelieferte Funktionen verfügbar, die alle mit einem Unterstrich (_) beginnen und mit compdef _funktion kommandoname einem beliebigen Befehl zugeordnet werden können.

Das Besondere an diesem Z-Shell basiertem Mechanismus ist die fast unübersichtlich erscheinene Fülle der Möglichkeiten, auf die Vervollständigungen einzuwirken. Der "Stil", nach dem die ZShell vorgeht, läßt sich dabei sehr weitgehend dem eigenen Geschmack anpassen mittels zstyle (siehe man zshcompsys | less -p "* zstyle .*$" ).

Beispiele für die Verwendung von compdef

  1. Der einfachste aber auch banalste Weg zur Vervollständigung mit einer eigenen Funktion geht mit dem Befehl "compadd".
    _banal() { compadd eins zwei drei vier fuenf ; } Die Funktion muß einen Unterstrich als Anfang besitzen. Hat man die Funktion definiert, dann wird sie nun durch compdef _banal befehl verwendbar.
  2. Ohne viel Programmiererei läßt sich die schon vorhandene Funktion _gnu_generic zum Vervollständigen von Programmen, die die GNU-Option "--" nutzen, gebrauchen. Gedacht waren die langen Optionsnamen mit "--" für eine explizitere Beschreibung einer Option eines Programms. Da aber zusätzlich auch immer noch die Möglichkeit bestehen bleiben sollte, verschiedene Flags kombiniert zu einem einzelnen Wort nach einem '-' anzugeben, wählte man das "--" als eindeutiges Zeichen und konnte so alten Stil und neuen Stil bei einem Konsole-Aufruf weiterverwenden. Dass aber der neue GNU-Stil so wenig benutzt wird, liegt einfach daran, dass er so schreibintensiv ist. Hier kann nun die Funktion _gnu_generic Abhilfe schaffen. Man spart sich das Gucken ins Manual oder den erneuten Aufruf von "--help".
    compdef _gnu_generic tail head gpg kann beispielsweise benutzt werden, um den Befehlen tail, head und gpg nach "--" lange Optionsnamen mitzugeben. Es erscheint dann eine Auswahl. Man gucke sich einmal die Ausgabe von gpg -- nach Eingabe des zuletzt genannten Befehls an. Das ganze Vervollständigungsgeheimnis liegt hier in der Funktion _gnu_generic, die bei allen GNU-Programmen, die --help unterstützen, versucht, die Argumente mit langen Optionen zu ermitteln.
  3. Mit compdef '_files -g "*.log"' programm kann man programm alle *.log Dateien und Ordner ergänzen lassen. Das -g bezieht sich dabei auf globbing. Der Stern steht dann für eine beliebige Anzahl von Buchstaben.

Vervollständigung in Farbe

Mit Hilfe von Ansi-Escapes-Codes war es schon sehr lange möglich, Farbe in das Konsolenleben und in Skripte zu bringen. Der allgemeine Mechanismus wird sehr gut in diesem Artikel von Nico Golde mit Schwerpunkt Bash beschrieben.
Bei der Zsh kann man auch in die Vervollständigung Farbe bringen: Dazu lädt man das complist-Module durch zmodload zsh/complist dazu und definiert mit Hilfe von zstyle einen Vervollständigungsstil.
Die Syntax ist leider etwas kompliziert, nichts desto trotz aber sehr mächtig.
Im nächsten Beispiel muss extendedglob mit 'setopt extendedglob' gesetzt sein:
zstyle ':completion:*:*:tar:*:values' list-colors '=(#b)([A-z]) #(--)*=37=31=32'.
Problem dieser Definition ist die Menge an Informationen auf einer Zeile. Deshalb schlage ich vor, Variablen zu definieren und dann zu benutzen.
zstyle ":completion:*:*:$kommando:*:$tag" list-colors \ "=$zshregex=$standard-farbzahl=$klammer1_farbzahl=$klammer2_farbzahl"
könnte man vielleicht als eine Rohform für eine 3farbige Vervollständigungsform benutzen. Man muss dann nur noch alle Variablen definieren.
Wie man nun sehen kann, ist der erste Teil nach "list-colors" der reguläre Ausdruck, dem ein `=' vorausgeht. Dieser reguläre Ausdruck bestimmt, was eingefärbt wird. Nach dem regulären Ausdruck kommt wieder ein Gleichheitszeichen, danach die Standard-Farben-Nummer, die ohne eine genauere Spezifizierung als Standardfarbe benutzt werden soll. Hierauf folgt wieder ein Gleichheitszeichen, jetzt die Farbnummer für die Worte der ersten Klammer und nach einem weiteren `=' wieder eine Farbnummer f¨r die zweite Klammer.
Auf den regulären Ausdruck muss ich genauer eingehen: (#b)ist nicht Teil dessen, was gesucht ist, sondern ermöglicht erst das Benutzen von Klammern, um dadurch Teile verschieden einzufärben. Alles, was in Klammern danach steht, kann eine unterschiedliche Farbe besitzen. So ist die $klammer1_farbe eigentlich das erste Klammern-Paar nach (#b), insgesamt also das zweite, da ja (#b) nicht mitzuzählen ist. Statt Ansi-Farbzahlen wie 31, 32 und 37 kann man auch eine vordefinierte Farbvariable mit einer Zeichenkette als Index (=assoziatives Array) nutzen. Dazu bindet man mit autoload colors die Variable colors ein. Im Beispiel bedeutet #: "Suche nach 0 oder mehr Leerzeichen", es ist also wie auch das # in (#b) kein Kommentarzeichen!!!

zstyle ':completion:*:*:tar:*:values' list-colors "=(#b)([A-z]) #(--)*=$color[white]=$color[red]=$color[green]"

Andere Quellen der Information

Writing Completion Functions-Linux Magazine