Einfache Tab-Vervollständigung in Bash und Zsh schreiben
(mill-build.org)- Einführung, wie sich in Bash und Zsh eine Tab-Vervollständigung implementieren lässt, die auch für bereits vollständig eingegebene Wörter Beschreibungen anzeigt
- Bash und Zsh verwenden unterschiedliche APIs für die Tab-Vervollständigung, und nur Zsh bietet standardmäßig die Funktion Beschreibungen in der Vervollständigung anzuzeigen
- Es wird eine Struktur implementiert, die Kandidaten mit
_generate_foo_completionserzeugt und in Bash überCOMPREPLY, in Zsh übercompaddzurückgibt - Um die Beschreibungsfunktion von Zsh auch in Bash umzusetzen, werden Beschreibungen in die Kandidaten-Strings eingebettet und nur bei einem einzelnen Kandidaten wieder entfernt
- Selbst bei einem einzelnen Kandidaten wird die Funktion verbessert, indem absichtlich Mehrdeutigkeit hinzugefügt wird, damit bei Eingabe von
<TAB>eine Beschreibung angezeigt wird - Das finale Skript bietet in beiden Shells dieselbe User Experience und unterstützt Teil-Vervollständigung, vollständige Vervollständigung und die Anzeige von Kandidaten-Beschreibungen
Hintergrund des Problems
- Tab-Vervollständigung (tab-completion) ist nützlich, um Befehle oder Flags zu erkunden, und hilft besonders dann, wenn man eine API oder ein CLI-Tool zum ersten Mal nutzt
- Zsh zeigt standardmäßig nur dann Beschreibungen an, wenn es mehrere Kandidaten gibt, Bash kann das nur über zusätzliche Konfiguration
- Für bereits vollständig eingegebene Wörter zeigen jedoch beide Shells keine Beschreibungen an
- Dadurch müssen Nutzer, um eine Beschreibung zu sehen, den folgenden umständlichen Ablauf durchlaufen
- Einige Zeichen löschen, sodass mehrere Kandidaten passen
- Die Taste
<TAB>drücken, um die Kandidatenliste anzuzeigen - Die gewünschte Beschreibung visuell suchen
- Die gelöschten Zeichen erneut eingeben, um den Befehl auszuführen
Überblick über den Lösungsansatz
- Auch bei einem einzelnen Kandidaten wird eine Dummy-Vervollständigung (dummy completion) hinzugefügt, um Mehrdeutigkeit zu erzeugen
- Dadurch geben sowohl Bash als auch Zsh die Kandidatenliste samt Beschreibung aus
- Dabei muss jedoch darauf geachtet werden, dass der Beschreibungstext nicht in den eigentlichen Befehl eingefügt wird
Grundkonzept
- Tab-Vervollständigung arbeitet so, dass bei Eingabe von
<TAB>das aktuelle Wort und die Cursorposition übernommen und anschließend mögliche Kandidatenlisten zurückgegeben werden - Bash: Kandidaten werden dem Array
COMPREPLYzugewiesen - Zsh: Kandidaten werden mit dem Befehl
compaddregistriert - Die Funktion
_generate_foo_completionsgibt Kandidaten-Strings aus; in der Praxis können diese dynamisch auf Basis des CLI-Status erzeugt werden
Bash und Zsh gleichzeitig unterstützen
- Implementierung passend für jede Shell über die Funktionen
_complete_foo_bashund_complete_foo_zsh - Unterscheidung über
if [ -n "${ZSH_VERSION:-}" ]; then ... elif [ -n "${BASH_VERSION:-}" ]; then ... fi - Nutzer registrieren das Skript in
.bashrcoder.zshrcund wenden es anschließend an
Anzeige von Beschreibungen in Zsh
- Für Kandidaten-Strings wird das Format
Name: Beschreibungverwendet - Zsh: Übergibt Name und Beschreibung als parallele Arrays mit
compadd -d raw -- $trimmed - Bash: Übergibt nur Kandidaten an
COMPREPLY, bei denen der Beschreibungsteil entfernt wurde (standardmäßig ohne Beschreibungsunterstützung)
Beschreibungen in Bash implementieren
- Bei mehreren Kandidaten werden Strings mit enthaltener Beschreibung unverändert angezeigt
- Nur bei einem einzelnen Kandidaten wird die Beschreibung entfernt
- Dabei wird das Verhalten der Bash-Vervollständigung genutzt, die nur das gemeinsame Präfix einfügt, sodass die Beschreibung nicht in die tatsächliche Eingabe übernommen wird
Beschreibungen auch bei einem einzelnen Kandidaten anzeigen
- Damit auch bei
<TAB>auf einem vollständig vervollständigten Wort eine Beschreibung erscheint, wird ein Dummy-Kandidat ergänzt, um Mehrdeutigkeit zu erzwingen - Zsh: Fügt den Dummy-Kandidaten sowohl zu den beiden parallelen Arrays
rawundtrimmedhinzu - Bash: Fügt bei einem einzelnen Kandidaten nur den Namen zu
trimmedhinzu
Endergebnis
- Bei mehreren Kandidaten werden Name und Beschreibung vollständig angezeigt
- Auch bei einem einzelnen Kandidaten lässt sich die Beschreibung per
<TAB>anzeigen - Bash und Zsh bieten beide dieselbe User Experience
- Anwendungsbeispiel:
$ foo <TAB> apple: a common fruit banana: starchy and high in potassium apricot: sour fruit... cherry: small and sweet...
1 Kommentare
Hacker-News-Kommentare
fish_update_completionsauszuführen, wenn ein interessantes Programm eine man-Seite bereitstellt~/.cache/fish/generated_completions/curlbedeutet-L„Follow redirects“,-O„Write output to file named as remote file“car TABzublkdiscarderweitert wird und dadurch auch dann Fehlverhalten entsteht, wenn cargo gar nicht im PATH ist--helpanbieten, frage ich mich, ob fish etwas Ähnliches wie_gnu_genericin zsh odercomplete -F _longoptin bash hatzypper search fish-completioneingegeben habe, kamen über 200 Pakete heraus, was mir irgendwie verdächtig vorkamcomplete-filename, gebunden an M-/, die den Kontext ignorieren und nur Dateinamen vervollständigenlsvervollständige und danach den Befehl änderecomplete -ralles wie gewünscht funktioniert, deutet darauf hin, dass das Problem bei den bash-completion-Skripten liegt$fpathinstalliert, werden sie gecacht und die Startgeschwindigkeit steigt_gnu_genericeine einfache Vervollständigung auf Basis von--helpclap_completein Rust, die Option--generatein ripgrep und die Laufzeit-Erzeugung von Vervollständigungen in PHP Symfony--completion, den gemeinsame Parser-Bibliotheken automatisch implementierencomplete_kill_1Signalnamen einträgt, bekommt der erste Parameter des Befehlskilleine passende Vervollständigungset-java-homewird mit_describedie Liste~/apps/java/*nach Versionen vervollständigt