Yad erzeugt in Shell-Skripten einfache bis komplexe Dialoge. Ganz ohne Tücken funktioniert das sehr leistungsfähige Tool allerdings nicht.
Bei Yad [1] handelt es sich um einen Fork des früher häufig benutzten Programms Zenity [2], den der Entwickler Victor Ananjevsky seit vielen Jahren kontinuierlich weiterentwickelt. Er konzipierte Yad für den direkten Einsatz in der Standard-Shell Bash. Das Tool nimmt Eingaben entgegen und produziert grafisch aufbereitete Ausgaben. Der Artikel “Neue Oberfläche” aus LinuxUser 06/2014 fasst die damals zur Verfügung stehenden Dialogtypen zusammen [3]. Inzwischen kamen neue Dialoge hinzu, etwa Benachrichtigungen in Form einfacher Menüs.
In vielen Fällen lassen sich mit Yad auf sehr einfache Weise gute Ergebnisse erzielen, manchmal bedarf es aber auch einer Vor- oder Nachbereitung der Daten. In diesem Artikel geht es zunächst einmal um einfache Beispiele.
Zähler und Countdown
Ein einfacher Zähler, der im Sekundentakt von 1 bis 10 zählt und damit eine einfache Stoppuhr simuliert, lässt sich mit Yad in einer Zeile realisieren (Listing 1, Zeile 1). Die runden Klammern erzeugen in diesem Beispiel in der Bash eine Sub-Shell, deren Ausgaben via Pipe bei Yad landen. Die Sub-Shell führt die For-Schleife durch die Anweisung sleep 1 im Sekundentakt aus. $(seq 1 10) erzeugt dabei die gewünschte Zahlenfolge von 1 bis 10 (Abbildung 1).
Listing 1
Zähler und Countdown
( for i in $(seq 1 10); do echo $i; sleep 1; done ) | yad --progress [...] | yad --progress --title=Countdown --geometry=200x50 ( for i in $(seq 0 10 100); do echo "#$i"; sleep 1; done ) | yad --progress --auto-close --geometry=300x50 yad --timeout-indicator=top --timeout=5 yad --timeout-indicator=top --timeout=3 ; if [ $? -eq 70 ] ; then echo TIMEOUT ; fi

Abbildung 1: Um einen einfachen Zähler zu generieren genügt der Aufruf yad --progress.
Das Beispiel lässt sich beliebig anpassen und erweitern. Zunächst versieht Yad die Anzeige des aktuellen Werts mit einem Prozentzeichen. Um das zu verhindern, hilft es, bei der Ausgabe der Zahlenfolge eine Raute (#) voranzustellen. Dann interpretiert Yad die Daten als reine Werte. Den Code echo $i ersetzen Sie dafür durch echo "# $i". Das Leerzeichen zwischen der Raute und $i dient nur der besseren Lesbarkeit und hat sonst keine weitere Bedeutung. Alternativ funktioniert der Zähler auch als Countdown. In diesem Fall muss die mittels seq erzeugte Zahlenfolge also umgekehrt erscheinen. Dafür sorgt die Anweisung seq 10 -1 1.
Auch das Ändern der Fensteroptik steuert Yad über Optionen. Die Dimensionen passen Sie mit --width und --height an, die Angabe erfolgt in Pixeln. Zusammengefasst funktioniert das auch via --geometry. Die Anweisung --title versieht das Fenster mit einem Titel. Enthält das Argument Leerzeichen, muss es zwischen doppelten Hochkommas stehen (Listing 1, Zeile 2) (Abbildung 2).

Abbildung 2: Mit wenigen Optionen gestaltet Yad die Ausgabe als Countdown und versieht das in seiner Größe festgelegte Fenster mit einem Titel.
Nun benötigt das generierte Fenster möglicherweise gar keinen Close-Button, der in unserem Beispiel viel zu groß ausfällt. Die Anweisung --no-buttons unterdrückt dessen Darstellung. Für Fälle, in denen das Zählen aufwärts erfolgt, kennt Yad noch die Option --auto-close. Sie bewirkt, dass sich der erzeugte Dialog automatisch beim Erreichen des Endwerts schließt (Listing 1, Zeile 3).
Es gibt aber auch eine ganz andere Möglichkeit, einen Countdown-Zähler zu realisieren, Yad kennt einen eigenen, speziellen Modus dafür. Mit der Option --timeout lässt sich das Schließen der Dialogfenster und das Terminieren von Yad selbst festlegen. Auf Wunsch zeigt die Option --timeout-indicator (Abbildung 3) dazu auch einen Verlaufsbalken an (Listing 1, Zeile 4). Solange Sie nur eine Anzeige benötigen, gestalten sich beide Varianten mehr oder weniger identisch. Wenn es aber darum geht, die verstrichene Zeit für etwas zu nutzen, dann wandelt sich die reine Darstellung zu einer im Skript zu verarbeitenden Eingabe.

Abbildung 3: Auf Wunsch blendet Yad auch einen Verlaufsbalken im Fenster ein.
Yad kennt zwei Arten von Rückgaben: Der Standardausgabekanal gibt Werte (Texte oder Zahlen) aus, die sich in normalen Variablen speichern lassen. Unabhängig davon generiert der Befehl aber auch einen klassischen, von der Situation abhängigen Rückgabewert, wie ihn die meisten Programme auf der Shell erzeugen. Wie immer bedeutet der Rückgabewert 0: alles in Ordnung, keine besonderen Vorkommnisse. Alle anderen Rückgabewerte weisen auf Besonderheiten wie etwa Fehler hin. Wenn Yad einen Dialog aufgrund eines abgelaufenen Timeouts terminiert, erzeugt es stets den Rückgabewert 70. Um diese Exit-Codes auszuwerten, verwenden Sie die interne Bash-Variable $?, die den Rückgabewert des zuletzt ausgeführten Befehls enthält (Listing 1, Zeile 5).
Es gibt noch viele weitere Optionen, die bei den unterschiedlichsten Dialogtypen eine Rolle spielt. Die wichtigsten fasst die Tabelle “Wichtige allgemeine Optionen von Yad” zusammen.
|
Option |
Funktion |
|---|---|
|
|
Setzt den Fenstertitel. |
|
|
Definiert ein Icon für das Fenster. |
|
|
Stellt Breite und Höhe des Dialogfensters ein. |
|
|
Legt die Position des Dialogfensters von der linken oberen Bildschirmecke fest. |
|
|
Fasst |
|
|
Zeit bis zum automatischen Beenden des Dialogs. Als Return Code generiert Yad |
|
|
Mögliche Werte für die Position: |
|
|
Definiert einen im Dialogfenster angezeigten Text, die dafür verwendete Breite der Textbox und die Textausrichtung darin. |
|
|
Ein kleines Bild oder Icon, das in Originalgröße am linken Rand des Dialogfensters erscheint. |
|
|
Erlaubt ein anderes als das voreingestellte Icon-Theme zu verwenden. |
|
|
Behält die Originalgröße von Icons bei. |
|
|
Legt einen Pfad fest, unter dem Yad zusätzlich nach Icons sucht. Die Option lässt sich auch mehrfach angeben. |
|
|
Text lässt sich aus dem Dialogfenster heraus ins Clipboard kopieren. |
|
|
Erzeugt abweichende Ausgaben für logische Ausdrücke; voreingestellt verwendet Yad |
|
|
Liest Argumente beispielsweise für Listen (aber keine Optionen) aus der angegebenen Datei. Jede Zeile entspricht einem Argument. |
|
|
Erlaubt es, einen anderen als den voreingestellten Rückgabewert |
|
|
Erlaubt GTK+, den CSS-Code aus dem angegebenen String zu verwenden. Enthält der Parameter einen Dateinamen mit Pfad, wertet Yad den Inhalt aus. |
|
|
Legt fest, wie Yad horizontale und vertikale Rollbalken verwendet. Es gibt die drei Möglichkeiten |
Menüs gestalten
Eine der neueren Entwicklungen von Yad betrifft den Notification-Modus. Er ermöglicht auf einfache Weise und mit wenig Code das Erzeugen eigener Menüs. Dazu nutzen Notifications die bei den modernen Desktop-Environments vorhandenen speziellen Anzeigebereiche. Bei XFCE und vielen anderen befindet er sich in der Leiste beziehungsweise dem Panel oder lässt sich dort hinzufügen (Abbildung 4).
Eine Besonderheit bei Yads Notification-Menüs besteht in der extrem einfachen Syntax, was schon die Online-Hilfe zeigt (Listing 2). Die Option --notification erzeugt das Menü. Was darin steht, legt das Argument von --menu fest. Der Schalter --no-middle verhindert, dass Yad sich beendet, sobald Sie die mittlere Maustaste drücken, was voreingestellt geschieht. Die Größe von Icons, die Yad im Notification-Bereich anzeigt, stellen Sie mit dem Argument hinter --icon-size ein, der Schalter --hidden unterdrückt eine Anzeige des Icons. Allerdings funktionieren dann auch keine Menüs mehr.
Listing 2
Hilfe zu Notifications
$ yad --help-notification
Aufruf:
yad [OPTION ?] - Yet another dialoging program
Benachrichtigungssymbol-Einstellungen
--notification Benachrichtigung
--menu=STRING Set initial popup menu
--no-middle Disable exit on middle click
--hidden Doesn't show icon at startup
--icon-size=SIZE Set icon size for fully specified
icons (default - 16)
Allerdings fehlt in der Online-Hilfe eine wichtige Funktion im Notification-Modus, nämlich --command. Als Argument dieser Option dient ein Shell-Befehl, den Yad ausführt, sobald Sie mit der linken Maustaste auf das Yad-Icon im Notification-Bereich klicken. Auch hier dient das Terminieren von Yad als voreingestellte Aktion. Das erfolgt also immer, solange Sie nicht über yad --notification --command=Befehl einen alternativen Befehl definieren. Hier wäre auch eine leere Eingabe mittels --command='' möglich. Zum Testen der Option eignet sich der Befehl eject, der die DVD-Schublade öffnet. Rufen Sie Yad mit dem Befehl aus der ersten Zeile von Listing 3 auf, öffnet ein linker Mausklick auf das Yad-Icon zwar die Laufwerksklappe, beendet dabei Yad aber nicht.
Listing 3
Befehle und Menüs
$ yad --notification --command=eject $ yad --notification --menu='Xterm!xterm|Editor!gedit' $ yad --notification --separator='§' --item-separator='%' --menu='...'
Es gibt noch eine Reihe weiterer Optionen, die Yad in diesem Modus auswertet, beispielsweise --listen oder --tooltip zusammen mit --text. In der bisher vorgestellten Form erzeugt Yad im Notification-Modus noch kein Menü. Da gilt es, zuvor als Argument der Option --menu zwischen einfachen Hochkommas in der Form 'Text!Befehl|...' zu definieren. Der Aufruf aus der zweiten Zeile von Listing 3 erzeugt das Menü aus Abbildung 5.

Abbildung 5: Eine einfache, mit Yad generierte Menüdefinition.
Jeder Menüeintrag besteht also aus zwei Teilen, dem Menütext und der beim Aufruf ausgeführten Befehlszeile. Zwischen Menütext und Befehlszeile steht als Item-Separator voreingestellt das Ausrufezeichen. Nach der Befehlszeile und vor dem nächsten Menüeintrag folgt | (die Pipe) als Separatorzeichen. Die beiden Trennzeichen lassen sich per Option von den Vorgaben abweichend vereinbaren (Listing 3, letzte Zeile).
Eine solche eigene Definition benötigen Sie dann, wenn beispielsweise das Pipe-Symbol in den Befehlszeilen auftritt. Wichtig: Yad interpretiert die Zeichen zwischen den Trennzeichen literal, benötigt also keine zusätzlichen Hochkommas oder Maskierungszeichen, sofern einfache Hochkommas die gesamte Zeichenkette einschließen. Verwenden Sie stattdessen doppelte Leerzeichen, nimmt die Bash in der Zeichenkette automatisch Ersetzungen vor.
FIFO als neuer Kanal
Die Methode, Menüeinträge direkt als Argument von --menu anzugeben, wirkt zwar auf den ersten Blick angenehm einfach, führt aber schnell zu unlesbaren und damit potenziell fehlerträchtigen Befehlszeilen. Sie beanspruchen schnell mehrere Zeilen im Terminal, sodass sich kaum noch unterscheiden lässt, wo der eine Eintrag endet und der andere beginnt. Zudem verwendet die Art, in der Yad die Argumente interpretiert, Zeilenumbrüche als Teile der Eingaben. Eine Alternative besteht darin, das gesamte Argument für das Menü in einem Bash-Array zu verwalten, das Sie dann in der Befehlszeile als Argument der Option --menu übergeben.
Es gibt noch eine weitere, sehr elegante Methode, um Yad im Notification-Modus zu betreiben und dabei sogar die Menüs zur Laufzeit zu ändern. Diese Variante setzt aber auf zusätzliche Datenkanäle in der Bash und eignet sich daher eher für fortgeschrittene Anwender. Dazu richten Sie zuerst eine FIFO ein (Listing 4, erste Zeile), die Sie dann als zusätzlichen Kanal etablieren (zweite Zeile). Zu guter Letzt starten Sie Yad im Hintergrund und verbinden es mit der FIFO (letzte Zeile).
Listing 4
Anbindung per FIFO
$ mkfifo FIFO $ exec 3<> FIFO $ yad --notification --listen <&3 &
Nun lassen sich Einstellungen mit dem Aufruf echo Einstellung >&3 an Yad senden; wobei die Software drei Schlüsselwörter erkennt: icon enthält den Pfad zum Icon, das im Notification-Bereich erscheint, tooltip den Tooltip dafür. Über menu geben Sie neue Menüs vor. Da echo die neuen Menüs als Argumente angibt, müssen Sie hier die normalen Regeln der Shell berücksichtigen. Zeilenumbrüche lassen sich beliebig verwenden, als Maskierungszeichen kommt der Backslash \ zum Einsatz. Allerdings berücksichtigt Yad Einrückungen am Anfang von Zeilen, was mitunter zu einer verschobenen Darstellung der Menüs führt (Abbildung 6). Möchten Sie weitere Optionen verwenden, wie etwa --command oder --no-middle, müssen Sie das beim Aufruf von Yad bereits berücksichtigen, etwa in der Formyad --notification --no-middle.

Abbildung 6: Tabulatoren am Anfang von Menüzeilen führen zu Einrückungen.
Listing 5 zeigt das Skript yadmenu.sh, mit dem Yad ein Anwendermenü erzeugt. Der Aufruf FIFO=$(mktemp) (Zeile 5) erzeugt einen zufälligen, eindeutigen Dateinamen unter /tmp/. Falls eine Datei mit diesem Namen schon existiert, löscht das Skript sie (Zeile 6). Mit dem Namen erzeugt Mkfifo eine spezielle Datei vom Typ Fifo, auch als benannte Pipe bezeichnet, die zur Kommunikation mit Yad dient (Zeile 7), und bindet sie als Kanal ein (Zeile 9). Um zu verhindern, dass sich das Programm bei einem linken Mausklick schließt, starten Sie Yad hier mit der Option --command='...' (Zeile 11).
Listing 5
yadmenu.sh
#!/bin/bash # yadmenu.sh # Time-stamp: <2021-09-15 13:39:05> # FIFO erstellen FIFO="$(mktemp)" rm $FIFO mkfifo $FIFO # Kanal etablieren exec 3<> $FIFO # Yad starten yad --notification --command='xterm -e pacui u' --listen <&3 & # Menü definieren >&3 echo "menu:\ PW!y-showpw.sh|\ GEEQIE!geeqie|\ XTERM!xterm|\ yay CLEAN!xterm -e "yay -Scc"|\ PACUI!xterm -e pacui|\ EDIT MENU!gedit /usr/local/bin/y-menu.sh|\ X-TILE 1!x-tile 1|\ ... fin!echo "kill $$" \ " # Tooltip definieren >&3 echo "TOOLTIP:Mittels TOOLTIP: eingestellter Tooltip!" # Icon definieren >&3 echo "icon:/usr/share/icons/Adwaita/16x16/emblems/emblem-favorite-symbolic.symbolic.png"
Das Menü selbst definiert echo ab Zeile 13. Die Schreibweisen echo >&3 und >&3 echo stehen gleichwertig nebeneinander und entsprechen echo "..." >&3. Die Bash erlaubt es, das Umleiten auch an erster Position in der Befehlszeile vorzunehmen, was es erleichtert, die Argumente schnell auszutauschen.
Eine Besonderheit weist die vorletzte Zeile der Menüdefinition auf (Zeile 21): Sie erzeugt den Menüeintrag ... fin und generiert beim Anklicken die Ausgabe kill PID. Die Prozessnummer bezieht sich dabei auf die Shell, die als Interpreter für das Skript dient. Damit erlaubt es diese Ausgabe, den Prozess zu beenden. Die Definitionen des Tooltip-Texts (Zeile 24) und des Notification-Icons (Zeile 26) erfolgen analog zur Menüdefinition. Schlüsselwörter wie ICON:, TOOLTIP: und MENU: dürfen Sie sowohl groß wie auch klein schrieben.
Das Skript yadmenu.sh machen Sie vor dem Aufruf mittels chmod a+x yadmenu.sh ausführbar. Rufen Sie es von einem Terminal aus auf, lässt es sich mit kill PID beenden. Alternativ starten Sie es nicht als eigenständigen Prozess, sondern führen es mit source ./yadmenu.sh in der aktuellen Shell aus. In diesem Fall lassen sich der Tooltip, das Icon und die Menüeinträge vom Terminal aus mittels >&3 echo "..." verändern, ohne das Skript vorher neu zu starten.
Icons
Nicht nur im Notification-Modus lässt sich für Yad ein Icon auswählen. Es liegt nahe, den eingebauten Icon-Browser von Yad dafür zu verwenden. Im Idealfall erzeugt der Befehl aus der ersten Zeile von Listing 6 eine Übersicht aller im angegebenen Verzeichnis enthaltenen Icons (Abbildung 7). Allerdings greift das Tool dabei nicht direkt auf die Bildchen zu, sondern wertet die enthaltenen .desktop-Dateien aus. Die enthalten jedoch oft Fehler, die bei Yad in der aktuellen Version 10.1 im Test zu einem Absturz führten.
Listing 6
Icons
$ yad --icons --read-dir=Verzeichnis $ yad --form --field='Wähle ein Icon:ICON"
Abbildung 7: Der Icon-Browser von Yad erfasst Icons anhand der im Verzeichnis hinterlegten .desktop-Dateien. Fehler in diesen Files führen allerdings zum Absturz des Programms.
Es gibt aber eine Alternative: Im Formularmodus gestattet Yad, direkt ein Icon auszuwählen (Listing 6, zweite Zeile). In diesem Modus zeigt Yad links das Icon an. Um es auswählen, klicken Sie auf das rechte Icon (Abbildung 8). Im sich daraufhin öffnenden Dialogfenster zeigt Yad links oben neben dem Feld Sizes das aktuell ausgewählte Icon an. Darunter befinden sich nach Kategorien sortierte Icons. Unter Filename finden Sie den Pfad, unter Sizes die verfügbaren Größen. Die Pfadangabe lässt sich bei gedrückter Umschalttaste mit der Maus auswählen und kopieren.
Abbildung 8: Die Alternative zum Icon-Browser: Im Formularmodus lässt sich das gewünschte Icon direkt auswählen.
Fazit
Yad bietet vielfältige Möglichkeiten, um in der Bash grafische Dialoge zu erstellen. Dank seiner eingängigen Syntax eignet es sich zumindest in den Grundzügen auch für Einsteiger, die über ein Shell-Skript mit Fenstern experimentieren möchten. (tle/jlu)
Infos
-
YAD-Workshop: Karsten Günther, “Neue Oberfläche”, LU 06/2014, S. 58, https://www.linux-community.de/30568






