Verhindern Sie, dass die Bash-Vervollständigung die Unterstrichvariable $_ ändert

Verhindern Sie, dass die Bash-Vervollständigung die Unterstrichvariable $_ ändert

Bei Verwendung der Tab-Vervollständigung in Bash $_wird die Variable geändert:

$ mkdir test
$ cd <TAB><TAB> $_
bash: cd: -d: invalid option
cd: usage: cd [-L|[-P [-e]]] [dir]

(Dadurch <TAB><TAB>werden alle Dateien im aktuellen Verzeichnis aufgelistet, aber ich verwende die Ausgabe letztendlich nicht und schreibe $_stattdessen. Der in dieser Zeile ausgeführte Befehl lautet einfach cd $_.)

Das erwartete Verhalten wäre eine Änderung in ./test.

Wie kann ich verhindern, dass die Bash-Vervollständigung geändert wird $_?

Antwort1

Sie verwenden diebash-completionPaket (oder ein Derivat). Für jede Argumentvervollständigung des cdBefehls (wie in der complete -pAusgabe gezeigt):

complete -o nospace -F _cd cd

Die _cdFunktion wird aufgerufen, um die Vervollständigungen zu bestimmen (der Kürze halber leicht bearbeitet):

_cd()
{
    local cur prev words cword
    _init_completion || return

    local IFS=$'\n' i j k

    compopt -o filenames

    if [[ -z "${CDPATH:-}" || "$cur" == ?(.)?(.)/* ]]; then
        _filedir -d
        return 0
    fi
    ....

Wenn Sie beispielsweise ein Verzeichnis ohne CDPATHSet abschließen, ist das zuletzt angezeigte Argument eines angezeigten Befehls -d, und dieses wird automatisch in platziert _. Es gibt mehrere andere Codepfade in dieser Funktion mit ähnlichen Nebeneffekten.

Da _es sich um eine interne Bash handelt, ist ein herkömmliches Speichern/Wiederherstellen (wie beiIFS) wird nicht wie erhofft funktionieren. Siekönntemach es mit einem kleinen Trick:

_cd()
{
    local save_="$_"
    ...
    : $save_
    return 0

Sie müssen _sofort beim Eintritt in eine Funktion speichern, :ist der Nullbefehl, der an sich nichts tut, aber die üblichen Nebenwirkungen eines Befehls hat, wie z. B. das Setzen _. Dieser Wiederherstellungsvorgang wird für jeden Rückgabepunkt jeder potenziell störenden Funktion erforderlich sein. Auch hier gibt es eine Feinheit: Normalerweise _wird sofort nach einer Rückkehr von einer Funktion gesetzt (wie erwartet zum letzten Argument des Funktionsaufrufs), was diese Methode unwirksam machen würde. Dies geschieht jedoch nicht, wenn eine Vervollständigungsfunktion aufgerufen wird, da sie nicht explizit aufgerufen wird. Ich halte dies nicht für sehr robust ...

(Ich bevorzugeGeschichte Erweiterung, und bleiben Sie bei !$dem, bei dem dieses Problem nicht auftritt.)

verwandte Informationen