Moderne Dialog-Programme bieten mehr als nur ein schnelles Eingabefenster für Daten. YAD verfügt über nicht weniger als ein Dutzend Grundfunktionen.
Fragt ein Shell-Skript eine Eingabe ab, erschöpfen sich die Möglichkeiten der eingebauten Funktionen recht schnell. Terminalbasierte Dialoge, wie sie beim Midnight Commander oder dem Mailprogramm Mutt zum Einsatz kommen, bauen heute meist auf GNU Ncurses [1] auf. Das eröffnet zwar neue Möglichkeiten, oft fehlt aber das letzte Quäntchen.
Spezielle Toolkits wie Xdialog, Gtkdialog, Kdialog oder Zenity passen sich dagegen perfekt in die jeweilige Umgebung ein. Sie vereinfachen den Einsatz der zugrundeliegenden Skripte so stark, dass sie diese für weniger versierte Anwender überhaupt erst zugänglich machen. Allerdings fehlten selbst dem neuesten Vertreter der Gattung, Zenity, einige Funktionen. Deshalb forkten interessierte Entwickler es und bauten das Toolkit als YAD [2] (“Yet another Dialog”) weiter aus.
Ein typisches Beispiel für ein YAD-Programm findet sich im Y-PPA-Manager [3] unter Ubuntu (Abbildung 1). Die Software hilft beim Verwalten von PPAs (Personal Package Archives, von Anwendern gepflegte Paketquellen), der Installation von Paketen daraus und einigem mehr. All diese Aufgaben erledigen mehrere kleine Shell-Skripte und einige Python-Funktionen, die eine YAD-Oberfläche zusammenfasst.

Abbildung 1: Der Y-PPA-Manager setzt für die Oberfläche vollständig auf YAD. Neben dem Icon-Modus kommen dabei Textfelder und Listen zum Einsatz.
Das Toolkit YAD bietet eine große Vielfalt von Dialogen an; Abbildung 2 fasst diese auszugsweise zusammen. Neben einfachen Schaltflächen stehen komplexe Dialoge bereit, darunter Auswahlen für Schriften, Farben und Dateien sowie ein Kalender. Den komplexen Dialogen ist gemeinsam, dass sie das ausgewählte Element auf der Standardausgabe bereitstellen. Meistens geschieht das zellen- oder zeilenweise, mit allen Bestandteilen des hervorgehobenen oder aktivierten Bereichs. Trennzeichen separieren dabei mehrere Felder in einer Zeile. Das erlaubt, diese nach Beenden des Dialogs weiter zu verarbeiten.

Abbildung 2: Eine Auswahl der mit YAD verfügbaren Dialoge. Neben ganz einfachen Meldungen, Auswahlen, Schiebereglern und Eingabefeldern stehen auch komplexe Dialoge wie etwa zum Öffnen von Dateien bereit.
Die Ausgabe einfacher Dialoge mit Buttons oder Schiebereglern geschieht normalerweise in der folgenden Form:
VAR=$(yad -->Typ)
Die Klammern sorgen dafür, dass der YAD-Befehl in einer Subshell läuft, deren aktueller Wert – etwa von einem Schieberegler mit --scale – beim Verlassen in der angegebenen Variablen landet.
Welche Dialoge YAD wie öffnet, das legen Sie über spezielle Schalter fest. Die Software unterstützt dabei zwei Arten von Optionen: Generelle, die sich auf das gesamte Verhalten und Aussehen beziehen (Tabelle “Globale Optionen”), sowie spezielle, die sich auf das aktuelle Fenster beziehen (Tabelle “Dialogtypen”).
Globale Optionen
| Option | Wirkung |
|---|---|
| Fensterpositionen | |
--width=Breite |
voreingestellte Breite |
--height=Höhe |
voreingestellte Höhe |
--geometry=Breite,Höhe+X,Y |
Größe und (optional) Position |
| Timeout | |
--timeout=Sekunden |
Zeit bis zum Schließen des Fensters |
--timeout-indicator=Position |
Position des Indikators |
| Beschriftungen und Icons | |
--text=Text |
Text im Fenster, nicht editierbar |
--text-align=Ausrichtung |
Ausrichtung des Texts |
--selectable-labels |
erlaubt Texte mit der Maus zu markieren und kopieren |
--no-markup |
ignoriert Markup-Anweisungen |
--image=Bild |
Bild oder Icon links im Fenster |
--image-on-top |
Bild oder Icon erscheint oberhalb statt links |
--icon-theme=Theme |
verwendetes Theme (voreingestellt: default) |
| Schalter | |
--button=Text:ID |
siehe Text |
--no-buttons |
keine Buttons darstellen |
--buttons-layout=Layout |
Varianten: spread, edge, start, end, center |
| Fenster | |
--title=Titel |
Fenstertitel |
--window-icon=Icon |
(erklärendes) Icon |
--undecorated |
Fenster ohne Dekoration |
--borders=Breite |
Breite des Rands in Pixeln |
--sticky |
Dialog erscheint auf allen Desktops |
--fixed |
feste Fenstergröße |
--center |
Dialog in der Mitte des Desktops |
--mouse |
öffnet den Dialog unter der Maus |
--on-top |
öffnet den Dialog über allen anderen Fenstern |
--skip-taskbar |
Fenster erscheint nicht in Taskbar/Pager |
| Diverses | |
-h |
Kurzhilfe |
--display=Display |
verwendetes Display |
--rest=Datei |
Datei mit zusätzlichen Optionen |
Dialogtypen
| Option | Typ |
|---|---|
--calendar |
Kalender |
--color |
Farbauswahldialog |
--dnd |
Drag & Drop-Fenster |
--entry |
Texteinträge (editierbar) |
--icons |
Icons als Buttons |
--file |
Dateiauswahl |
--font |
Schriftauswahl |
--form |
Formulare |
--list |
allgemeine Listen |
--multi-progress |
mehrfache Fortschrittsanzeigen |
--notebook |
Notizbuch |
--notification |
Desktop-Benachrichtigungen |
--print |
Druckdialog |
--progress |
Fortschrittsanzeige |
--text-info |
Infotext |
--scale |
Schieberegler |
Daneben verfügt jeder Dialog über weitere, teils umfangreiche Optionen, die das genaue Verhalten einstellen. Bei Fortschrittsanzeigen lässt sich mittels --pulsate ein animierter Balken erzeugen, durch --auto-close beendet sich der Dialog beim Erreichen von 100 Prozent. Für eine Laufrichtung von rechts nach links sorgt --rtl; --auto-kill beendet den aufrufenden Prozess, falls der Anwender den Dialog abbricht.
TIPP
Für jedes in der Tabelle “Dialogtypen” angegebene Widget zeigt YAD mit --help-Typ die speziellen Optionen an, die größtenteils auch in der Manpage beschrieben sind.
Bei einfachen Dialogen, die beispielsweise Meldungen durch --text="Meldung" anzeigen, gibt es immer die Möglichkeit, eine oder mehrere Schaltflächen zu integrieren. Dabei definieren Sie jede mittels --button=Text:ID. Der zuerst definierte Schalter ist dabei vorausgewählt.
Nach einem Gleichheitszeichen geben Sie den Text für die Schaltfläche an, den Sie zwischen doppelten Hochkommas einschließen, falls er Leerzeichen enthält. Innerhalb des Texts gelingt ein einfaches Markup mittels Pango [4], wobei YAD jedoch derzeit noch nicht alle Features korrekt unterstützt.
Jede Schaltfläche eines Dialogs erhält zusätzlich bei Bedarf nach einem auf den Text folgenden Doppelpunkt eine eindeutige numerische ID, deren Wert YAD als Rückgabewert verwendet, sofern Sie den Dialog mit dem entsprechenden Button beendet haben. Bei der Vergabe der IDs gilt es, zu beachten, dass YAD zwei Rückgabewerte bereits automatisch erzeugt: So symbolisiert 252 das Verlassen des Dialogs mittels [Esc]; 70 kommt zum Einsatz, wenn Sie keine Auswahl treffen und ein Timeout den Dialog beendet.
Texte, die Sie mittels --text= anzeigen, stehen nicht via Auswahl bereit, und der Dialog bietet keine Möglichkeit, diese zu editieren. Wünschen Sie dies, so geben Sie dem Dialog zusätzlich die Option --selectable-labels mit.
Die Variable $? enthält den Rückgabewert des letzten im Vordergrund ausgeführten Befehls. Diesen binden Sie zum Beispiel über PS1='[$?] :' in .bashrc in den Prompt mit ein oder werten ihn davon unabhängig aus. Details erklärt die Manpage zur Bash.
Das Auswerten im Skript erfolgt üblicherweise durch If-Konstrukte (Listing 1). Zeile 1 liefert TRUE zurück, falls der Button den Wert 5 zurückgab. Anstelle der Konstruktion mit den doppelten eckigen Klammern besteht die Möglichkeit, auf den Test-Befehl zurückzugreifen: Das erzeugt in einigen Fällen einen verständlicheren Code. Die Bash zeigt mit help test an, welche Tests sie mit welchen Optionen unterstützt.
Listing 1
if [[ "$?" -eq "5" ]];then ...; fi
Die Option --no-buttons unterdrückt die Anzeige von Schaltflächen. Damit das Fenster automatisch wieder verschwindet, bietet sich die Option --timeout=Sekunden an (Listing 2). Noch mehr Dramatik erhält das Fenster, wenn ein Indikator mit --timeout-indicator=Position die verbleibende Zeit anzeigt (Abbildung 3).
Listing 2
$ yad --entry --text='As time goes by...' --timeout=22 --timeout-indicator=right

Abbildung 3: Ein Timeout-Indikator zeigt an, wie lange YAD das Fenster noch offen hält.
Besonders häufig kommen Dialoge für die Eingabe von kurzen Texten zum Einsatz. YAD unterstützt dies mit dem Typ --entry. Voreingestellt bleibt das Feld für die Eingabe leer, durch --entry-text=Vorgabe belegen Sie es mit einem bereits ausgewählten Text. Das vereinfacht zwar einiges, erweist sich aber bei der Eingabe von Passwörtern oder ähnlichen Daten als nicht praktikabel.
Daher bietet YAD mit --hide-text eine Möglichkeit, Texte zu maskieren. Ein Punkt repräsentiert dabei jedes eingegebene Zeichen. Möchten Sie für das Eingabefeld eine Beschriftung vergeben, erreichen Sie dies mittels --entry-label=Beschriftung (Abbildung 4).

Abbildung 4: Bei der Eingabe von Passwörtern möchte sich niemand auf die Eingabe schauen lassen. YAD bietet einen entsprechenden Dialog an.
Die Option --entry erzeugt voreingestellt sogenannte Combo-Boxen, sofern nicht nur ein Argument vorhandenen ist. Eine solche Combo-Box nimmt mehrere Einträge auf, deren maximale Anzahl sich nach der Größe des Bildschirms richtet und höchstens 50 betragen darf. Alle Einträge erscheinen in einer Auswahlliste.
Es spielt dabei übrigens keine Rolle, wie Sie diese Einträge erzeugen, also ob Sie diese fest im Quelltext vorgeben oder aus Variablen, externen Dateien oder den Ausgaben von Befehlen beziehen. Um dem Benutzer die Möglichkeit zu geben, die Texte zu bearbeiten, aktivieren Sie diese Eigenschaft mittels --editable.
Die flexiblen Listen in YAD (Option --list) verallgemeinern das Prinzip der beliebig vielen Einträge weiter. Sie ermöglichen Listen, aus denen Sie bestimmte Zeilen zum weiteren Bearbeiten auswählen und eventuell sogar editieren dürfen.
Füllstand
Der Befehl df erzeugt eine Ausgabe mit sechs Spalten (Listing 3). Um diese mit YAD aufzubereiten, definieren Sie zunächst mit --column=Beschriftung die Spaltentitel. Diese Optionen dürfen Sie beliebig oft verwenden. Es folgen zeilenweise die Inhalte, getrennt durch die in $IFS vereinbarten Zeichen (Listing 4). Der Einsatz von Grep bewirkt, dass YAD nur die relevanten Zeilen berücksichtigt – also solche, die mit /dev/ beginnen (Abbildung 5).
Listing 3
# df Dateisystem Größe Benutzt Verf. Verw% Eingehängt auf /dev/sda6 20G 17G 3,3G 84% / dev 3,9G 0 3,9G 0% /dev run 3,9G 932K 3,9G 1% /run tmpfs 3,9G 6,0M 3,9G 1% /dev/shm tmpfs 3,9G 0 3,9G 0% /sys/fs/cgroup tmpfs 3,9G 1,2G 2,8G 30% /tmp /dev/sda7 25G 14G 9,3G 60% /media/sda7 /dev/sda10 20G 18G 224M 99% /media/sda10 /dev/sda8 20G 17G 1,4G 93% /media/sda8 /dev/sda5 3,6G 2,5G 1,1G 71% /media/sda5 /dev/sda11 20G 17G 1,8G 91% /home /dev/sda12 231G 94G 126G 43% /media/sda12
Listing 4
# yad --list --column=Device --column=Size --column=used --column=free --column=% --column=Mount $(df |grep -e '^/dev/' )
Ein Doppelklick auf eine Zeile erzeugt eine Ausgabe in der Form /dev/sda7|25G|14G|9,3G|60%|/media/sda7|. YAD verwendet voreingestellt die Pipe als Trenner, über --separator=Trennzeichen dürfen Sie ein anderes Zeichen festlegen.
Das Verfahren funktioniert gut, sofern die Anzahl der ausgegebenen Spalten konstant bleibt. Was aber, wenn diese variiert? So liefert fdisk -l bei einigen Zeilen eine zusätzliche Spalte (“Boot”) (Listing 5). Diese ließe sich einfach “normalisieren”, indem Sie mittels tr '*' ' ' das Sternchen durch ein Leerzeichen ersetzen.
Listing 5
Disk /dev/sda: 698,7 GiB, 750156374016 bytes, 1465149168 sectors /dev/sda1 2048 411647 204800 7 HPFS/NTFS/exFAT ... /dev/sda9 1412820992 1426785834 6982421+ 82 Linux swap / Solaris ...
Derartige Listen bringen eine nützliche Besonderheit mit: Über --checklist sorgen Sie dafür, dass die erste Spalte wie eine Checkbox arbeitet. Beim Beenden des Dialogs gibt YAD dann nur die Zeilen mit aktivierten Schaltern aus. Alternativ erzeugen Sie mit --radiolist einander ausschließende Elemente.
Eine andere Möglichkeit, die Ausgaben von df zu visualisieren, hat der YAD-Autor Victor ananasik Ananjevsky als xdf entwickelt (Listing 6): Er nutzt die Fortschrittsanzeigen als Balkendiagramm, durch --multi-progress sogar für mehrere parallele Ausgaben. Dabei zeigt --bar=... den jeweiligen Füllstand jedes Dateisystems.
Listing 6
#! /bin/bash
# -*- mode: sh -*-
#
# Graphical frontend for df(1) command
# Author: Victor Ananjevsky <ananasik@gmail.com>, 2012
#
eval exec yad --image=drive-harddisk --text="Disk\ usage" --buttons-layout=end --multi-progress \
$(df -h $1 | tail -n +2 | awk '{printf "--bar=\"<b>%s</b> (%s) [%s/%s]\" %s ", $6, $1, $3, $2, $5}')
YAD anpassen
Als Gtk-basiertes Programm ist YAD in der Lage, spezielle Parameter für Widgets zu verwenden. Das geschieht auf zwei Arten: In der Konfigurationsdatei ~/.gtkrc-2.0 legen Sie global den Stil fest. Dazu dienen die Zeilen aus Listing 7.
Listing 7
style "timeout-indicator"
{
GtkProgressBar::min-horizontal-bar-height = 5
GtkProgressBar::min-vertical-bar-width = 5
}
widget "*yad-timeout-indicator" style "timeout-indicator"
Falls Sie den Style nur temporär bereitstellen möchten, bietet sich ein anderer Ansatz an. Er erzeugt die passende Datei und bindet diese anschließend über die Umgebungsvariable ein (Listing 8). Sie verwenden das entsprechende Stück Code einfach im Skript, das dieses Widget nutzt.
Listing 8
cat > /tmp/gtkrc.yad <<EOF
style "timeout-indicator"
{
GtkProgressBar::min-horizontal-bar-height = 5
GtkProgressBar::min-vertical-bar-width = 5
}
widget "*yad-timeout-indicator" style "timeout-indicator"
EOF
if [ -n "$GTK_RC_FILES" ]; then
export GTK_RC_FILES="$GTK_RC_FILES:/tmp/gtkrc.yad"
else
export GTK_RC_FILES="/tmp/gtkrc.yad"
fi
Fazit
YAD gehört derzeit zu den umfangreichsten Toolkits für Shell-Skripte. Es fällt leicht, damit die Ein- und Ausgaben übersichtlicher zu gestalten. Das Programm funktioniert wie ein Satz Lego-Steine, aus dem Sie die benötigten Optionen nur zusammenzuklicken brauchen.
Nicht ganz so einfach gelingt das Zuordnen von Daten zu Feldern oder Spalten, sodass hier einige Experimente anfallen. Bei Problemen empfiehlt es sich, die Testdaten zunächst gut vorbereitet direkt in den Quelltext zu schreiben und in einem separaten Schritt das Aufbereiten mittels externer Werkzeugen zu testen.
Infos
[1] Ncurses: http://www.gnu.org/software/ncurses/ncurses.html
[2] YAD: https://code.google.com/p/yad/
[3] Y-PPA-Manager: https://www.linux-community.de/
[4] Pango Markup: http://www.pygtk.org/docs/pygtk/pango-markup-language.html






