Warum deaktiviert bash die automatische Vervollständigung für einige Befehle und wie kann ich sie aktivieren?

9

Es kommt mir oft vor, dass Bash die automatische Vervollständigung für bestimmte Befehle deaktiviert. Dies zwingt mich, dem Befehlsnamen ein zufälliges Symbol hinzuzufügen, die automatische Vervollständigung zu verwenden und dann den Befehlsnamen zu korrigieren. Das ist ziemlich nervig. Zum Beispiel:

# I type:
openvpn s<tab>
# Nothing happens, so I add x
openvpnx s<tab>
# Now this expands to
openvpnx somepath

# Same with ./configure or many other commands...

Gibt es eine Möglichkeit, die Deaktivierung zu deaktivieren, damit die automatische Vervollständigung IMMER funktioniert?

Petr
quelle
Wollen Sie damit sagen, dass "openvpn" nicht der richtige Befehl ist? dass „openvpnx“ ist der richtige Befehl, und Sie erwarten , was? Bash, um "openvpn" zu vervollständigen, nachdem Sie "s [TAB]" eingegeben haben? Sollten Sie nach "openvpn" auf die Tabulatortaste klicken, damit dies zu "openvpnx" führt?
Jeff Schaller
Nein, ich versuche zu sagen, dass ich, wenn ich den richtigen Befehl "openvpn" verwende und dann die automatische Vervollständigung für den Pfad nicht mehr funktioniert, den Befehlsnamen verkrüppeln muss, damit er funktioniert, und dann den Namen zurücksetzen muss
Petr
1
Ich habe das gleiche Problem mit openvpn. Es scheint keine aktiven openvpn-Vervollständigungsskripte für openvpn zu geben, aber die normale Dateivervollständigung ist deaktiviert. Wenn ich das tue complete -p openvpn, bekomme ich bash: complete: openvpn: no completion specification.Aber das Drücken der Tabulatortaste nach dem Tippen openvpn bringt nichts. Wenn ich complete -ralle Vervollständigungen lösche und dann nach der Eingabe die Tabulatortaste drücke openvpn , erhalte ich eine normale dateibasierte Vervollständigung. Das no completion specificationist messleading. Da es den gleichen Fehler für nicht existierende Befehle zurückgibt, zum Beispiel, wenn ich es tue complete -p nonexistent.
Denis Nikolaenko
Meine Antwort ist keine "neue Frage". Ich sage, bash_completion muss systematisch überarbeitet werden. Wie können Sie erwarten, dass einige interessante Fragen mit einer klaren Antwort beantwortet werden? Das Q wird nicht vollständig beantwortet. Ich stimme dem ursprünglichen Q zu, ich stimme den gegebenen Antworten zu. Aber das Q wird NICHT beantwortet, und Sie helfen nicht, sondern regieren nur.
Ich habe meine Antwort komplett neu geschrieben. Kann es "wieder geöffnet" werden? Es ist alles in einem alarmierenden Rosa getränkt.

Antworten:

6

Auflistung der Vervollständigungen

Sie können sehen, was Bash / Readline zum Ausführen eines Befehls verwendet complete -p command, z. B. wenn ich ausgeführt werde complete -p openvpn, erhalte ich

bash: complete: openvpn: no completion specification

Dies zeigt, dass die von meiner Shell verwendete Readline keine spezifische Vervollständigung für den openvpnBefehl hat, sodass standardmäßig die traditionelle Form der Vervollständigung verwendet wird, dh Dateinamen.

Ein weiteres Beispiel (um eine definierte Vervollständigung zu demonstrieren):

$ complete -p dillo
complete -F _filedir_xspec dillo

Dies zeigt an, dass eine benannte Funktion _filedir_xspecverwendet wird, um Vervollständigungen für den dilloBefehl bereitzustellen .

Vervollständigungen entfernen

Verwenden Sie die -rOption mit der completeintegrierten Option, um eine definierte Vervollständigung zu entfernen :

complete -r openvpn
Anthony Geoghegan
quelle
Hallo, aber wie füge ich die automatische Vervollständigung für openvpn hinzu?
Topsy
Beachten Sie, dass bash Vervollständigungsfunktionen scheinbar complete -p <COMMAND>träge lädt und möglicherweise erst funktioniert, wenn die Vervollständigung für COMMAND aufgerufen wurde.
user84207
6

Bash hat programmierbare Vervollständigung . Seit 1999 ist es möglich, die Vervollständigung von Befehlsargumenten an den Befehl anzupassen und nicht nur Dateinamen zu vervollständigen. Dateinamen sind die Standardeinstellungen, wenn keine befehlsspezifische Vervollständigung konfiguriert wurde (daher erhalten Sie Dateinamen, wenn Sie den Befehl in ändern openvpnx).

Die programmierbare Vervollständigung wird normalerweise durch Laden aktiviert /etc/bash_completion. Wenn Sie keine programmierbare Vervollständigung wünschen und Dateinamen auch in Kontexten, in denen Dateinamen keinen Sinn ergeben, immer vervollständigen möchten, entfernen Sie diese aus Ihrer .bashrc.

Es scheint, dass Sie eine benutzerdefinierte Vervollständigung für Argumente für den openvpnBefehl haben und dass dieser Vervollständigungscode nichts für das erste Argument bietet. Ich weiß nicht, warum das so ist, es könnte ein Fehler im Abschlusscode sein. Nützlicher Vervollständigungscode würde Optionen und ihre Argumente vervollständigen. Führen Sie aus complete -p openvpn, um festzustellen, für welchen Code Argumente vervollständigt werden openvpn. Sie können diesen benutzerdefinierten Abschlusscode mit deaktivieren complete -r openvpn, aber dann kehren Sie nur zu den Dateinamen zurück, was in der Befehlszeile von openvpnnur nach einigen Optionen nützlich ist .

Unabhängig von den Abschlusseinstellungen können Sie einen Dateinamen jederzeit vervollständigen, indem Sie complete-filename(Standardbindung :) M-/anstelle von complete( TAB) aufrufen .

Gilles 'SO - hör auf böse zu sein'
quelle
1
Hm, aber ich erhalte "bash: complete: ./configure: keine Abschlussspezifikation" für ./configure, aber es erlaubt mir nicht, den Dateipfad automatisch
Petr
@Petr Das liegt daran, dass die Abschlussspezifikation für configure, nicht für ist ./configure. Es wird der Basisname des Befehls berücksichtigt, nicht der vollständige Pfad.
Gilles 'SO - hör auf böse zu sein'
3

Das erste Problem ist, dass der openvpnBinärname mit seinem Eintrag im Verzeichnis init.d übereinstimmt.

complete | grep -i openvpn

ergibt

complete -F _service /etc/init.d/openvpn

Unter Ubuntu und Derivaten stammt dies aus dem Code in /usr/share/bash-completion/bash_completion(Teil des bash-completionPakets).

for svcdir in ${sysvdirs[@]}; do
    for svc in $svcdir/!($_backup_glob); do
        [[ -x $svc ]] && complete -F _service $svc
    done
done

Kommentieren Sie diesen Block aus. Starten Sie Ihre Bash-Instanz neu. Versuchen Sie, die automatische Vervollständigung openvpnmit TAB durchzuführen, und tun Sie dies

complete | grep -i openvpn

Das produziert

complete -F _openvpn /etc/init.d/openvpn

Das zweite Problem kommt von /usr/share/bash-completion/completions/openvpn. Es versucht, .conf-Dateien aus / etc / openvpn automatisch zu vervollständigen und ist ein Hindernis, wenn Sie versuchen, openvpn mit einer Ad-hoc-Konfigurationsdatei auszuführen, die außerhalb von / etc / openvpn liegt.

Löschen Sie es einfach und starten Sie Ihre Bash-Instanz neu.

sudo rm /usr/share/bash-completion/completions/openvpn

Jetzt sollten Sie die Standard-Dateivervollständigung für den Befehl openvpn mit der TAB-Taste erhalten.

Wenn du läufst

complete -p | grep openvpn

Nachdem Sie versucht haben, nach openvpn automatisch zu vervollständigen, sollten Sie jetzt erhalten

complete -F _minimal openvpn`

Ein besserer Ansatz wäre gewesen, Bash-Completion-Skripte für openvpn zu reparieren / zu erweitern. Aber das ist eine Geschichte für einen anderen Tag.


Wenn Sie später zum ursprünglichen Zustand des bash-completionPakets zurückkehren möchten, installieren Sie es einfach mit dem folgenden Befehl neu.

apt-get install --reinstall bash-completion
Denis Nikolaenko
quelle
1

Der traurige Teil meiner Antwort ist: Bash (via Readline) hat so viele Möglichkeiten zur Vervollständigung. Eine normale Linux-Distribution kann jedoch die grundlegende Dateinamenerweiterung mit [tab] (oder [tab] [tab]) durch Hinzufügen einer Optionserweiterung stören . In meinem Fall ist es das Paket "Bash-Vervollständigung" , das mir das im ursprünglichen Q beschriebene Verhalten verleiht.

Es ist nicht nur ein openvpnProblem. Q sagt: "zum Beispiel".

Mit bind -p | grep completebekomme ich:

"\C-i": complete
"\e\e": complete
"\e!": complete-command
"\e/": complete-filename
...
"\e\C-i": dynamic-complete-history
"\eg": glob-complete-word
"\e*": insert-completions
# menu-complete (not bound)
...
"\C-x/": possible-filename-completions

Hier ist TAB = ctrl-i an die Grundfunktion gebunden complete. Die anderen Bindungen auf meinem Archlinux habe ich gerade ausprobiert. Mit "ta [esc] [star]" kann ich alle Befehle ab "ta" in meine Befehlszeile einfügen.

Die completeReadline-Funktion wird in man bash erklärt:

Abschluss

vollständig (TAB)

Versuchen Sie, den Text vor dem Punkt zu vervollständigen. Bash versucht, den Text als Variable (wenn der Text mit $ beginnt), Benutzername (wenn der Text mit ~ beginnt), Hostname (wenn der Text mit @ beginnt) oder Befehl (einschließlich Aliasnamen und Funktionen) zu behandeln. Wenn keines davon eine Übereinstimmung ergibt, wird versucht , den Dateinamen zu vervollständigen.

Ich kann das nur teilweise reproduzieren. Ich denke, man bash vergisst zu erwähnen, dass es davon abhängt, ob Sie ein erstes Wort oder ein zweites, drittes usw. Wort [tab].

Ich habe Dateien, die mit "ba" beginnen, in meinem Heim- / Arbeitsverzeichnis. Wenn ich an der Eingabeaufforderung "ba [tab]" eingebe, erhalte ich diese Namen nicht, sondern nur Befehle von badblocksbis bashbug. Dies ist ein vernünftiges Verhalten: Das erste Wort gibt Ihnen Befehle, die folgenden Wörter Dateinamen. Und wenn Sie "$ [tab]" eingeben, erhalten Sie wirklich eine schöne Liste von Variablennamen.

Wenn ich [Tab] sage, meine ich eigentlich [Tab] [Tab]. Aber wir gewöhnen uns so sehr daran, dass wir nicht einmal bemerken, was diese "vollständige" Readline-Funktion alles macht. Mit den Variationen "complete-" können Sie steuern, wonach gesucht wird (Befehl, Dateiname, Variable) und was mit der Liste zu tun ist, wenn mehr als eine Übereinstimmung vorliegt (Möglichkeit).

Diese Readline-Funktionen werden mit vielen Standardbindungen geliefert. Beide man bashund man readlinelisten die Funktionen und ihre Standardbindungen auf. Verwenden Sie zum Überprüfen bind -p wie oben. Dies ist auch die Basis für die ~/.inputrcDatei. Ich habe gerade eine gemacht (es gab nur eine kryptische / etc / inputrc):

set colored-completion-prefix on
set colored-stats on

Mit farbigen Statistiken bekomme ich eine farbige Liste, wie bei ls --color. Nach "bi [tab] [tab]" sehe ich "bind" in Weiß und "bison" in grün, was mir sagt, dass "bind" keine ausführbare Datei ist (sondern eine eingebaute ... dies ist eine BEFEHLserweiterung ... "bind" ist nicht einmal ein Dateiname!).

set show-all-if-ambiguous on

Dies steuert die Registerkarte im Vergleich zur doppelten Registerkarte. Nachdem ich es hinzugefügt und eingegeben habe

cd s[tab]

Ich bekomme direkt eine farbige Liste aller Dateinamen. Verzeichnisse, Links, normale Dateien usw. werden alle in ihrer eigenen Farbe angezeigt.

Diese Readline-Variablen können Sie mit sehen bind -v. Um eine .inputrc-Änderung zu testen, starten Sie eine neue Bash mit "bash" und beenden Sie dann. Oder erneut anmelden.

Die nächste Schicht ist in/usr/share/bash-completion

Es enthält Skripts pro Befehl, hauptsächlich aus den Paketen util-linux und systemd. Es gibt eine Mount- (2 Kb) und eine Systemctl- (13 Kb) Datei. Die Mount-Datei ist interessant: Sie gibt Ihnen / proc / filesystems, nachdem Sie "-t" eingegeben haben.

Normalerweise erhalte ich nach "mount -t [tab]" FILENAMES. Nachdem ich diese "Mount" -Datei gefunden habe, bekomme ich wirklich fs-Typen wie ext2, ext3 und ext4. Ich gehe:

complete -r mount

um diese Funktion zu entfernen. (Dies completeist ein Shell-eingebauter Befehl)

Die dritte Schicht ist das zusätzliche "Bash-Completion" -Paket . Ich habe es bereits deinstalliert, nachdem ich es zum Testen installiert hatte. Mit diesem Paket habe ich diese nette Funktion zum Erweitern von Optionen und auch Paketnamen erhalten. Ich könnte "tar - [tab]" eingeben und sehe alle Optionen. Aber die Dateinamenerweiterung ging in vielen Konstellationen verloren. Amd nicht nur auf Archlinux.

Dieses Bash-Completion-Paket gab mir ein 2000-Zeilen-Skript "bash_completion" und viele Befehlsdateien. Die für "Teer" war 700 Zeilen voller Funktionen. Dies zu beheben ist also keine Lösung.

Wenn Sie sich wirklich für diese [Tab] vollständigen Feinheiten interessieren, müssen Sie unten beginnen und eine oder zwei Readline-Funktionen auswählen complete, die nicht an andere Tasten als [Tab] gebunden sind. Meine obige Standardkonfiguration funktioniert wirklich, aber ich habe nie etwas anderes als [tab] verwendet. Jetzt möchte ich die richtigen Funktionen auf die richtigen Tasten einstellen. Mit oder ohne dieses optionserweiternde Bash-Completion-Paket.


quelle