Bearbeiten und Färben der Liste der Tab-Vervollständigungen von Bash

8

Folgendes möchte ich haben. Wenn die Tab-Vervollständigung nicht eindeutig ist und Bash die Liste der Möglichkeiten druckt. Ich möchte, dass es das nächste Zeichen färbt, das ich in jedes Wort in der Liste drücken soll.

Folgendes habe ich bisher getan. In meiner .bashrc habe ich folgende Funktion definiert und den vollständigen Befehl aufgerufen

_colourunique() {
    local word=${COMP_WORDS[COMP_CWORD]}
    COMPREPLY=($(compgen -f -- "${word}"))
    if [[ "$word" ]] && [[ ${#COMPREPLY[@]} -gt 1 ]]; then
        local  w
        local  i=0
        for ((i=0;i<${#COMPREPLY[@]};i++)) ; do
            w=${COMPREPLY[$i]}
            n=${#word}
            COMPREPLY[$i]="${w:0:n}\033[91m${w:n:1}\033[0m${w:$((n+1))}"
        done
    fi
}

complete -D -F _colourunique

Aber es funktioniert nicht ... Wenn ich tippe

ls D[TAB]

Es wird automatisch vervollständigt als

ls D\033[91m

Anstatt die Möglichkeiten Dokumente, Desktop usw. aufzulisten. Was könnte hier falsch laufen? Oder gibt es einen anderen direkten Weg, um dies zu erreichen?

UPDATE 1:

Ich glaube ich verstehe was hier passiert. Da ich jedem Wort in COMPREPLY \ 033 [91m] hinzufüge, sieht bash, dass dieser Teil allen gemeinsam ist, und vervollständigt diesen gemeinsamen Begriff automatisch in der Eingabeaufforderung selbst. (anstatt einfach die Liste zu drucken)

Daher denke ich nicht, dass diese Methode zum Bearbeiten des COMPREPLY-Arrays der richtige Weg ist. Gibt es eine andere Methode?

UPDATE 2:

Um die Einheitlichkeit zu bewahren, habe ich versucht, ein $ i und \ b in den String einzufügen.

COMPREPLY[$i]="${w:0:n}$i\b\033[91m${w:n:1}\033[0m${w:$((n+1))}"

Jetzt werden die möglichen Tab-Vervollständigungen wie folgt gedruckt.

D0\b\033[91mo\033[0mwnloads  D1\b\033[91me\033[0msktop

Das heißt, die Liste wird als solche gedruckt. Es gibt keine Auswertung von \ b oder \ 033 [91m Zeichen. :-(

UPDATE 3:

Da die Antworten so aussehen, gibt es keine Möglichkeit, das zu erreichen, was ich in Bash will (es sei denn, ich wechsle zu zsh). Ich entschied mich für eine andere Option. Ich werde versuchen, den nächsten eindeutigen Tastenanschlag an das Ende jedes Wortes anzuhängen, damit es auffällt.

Es folgt der bisherige Code.

SanitiseString () {
    local String="$1"
    local j
    for j in \\ \! \@ \# \$ \% \^ \& \* \( \) \+ \{ \[ \] \} \| \; \: \" \' \, \? \ ; do
        String=${String//"$j"/\\"$j"}
    done
    echo "$String"
}

_colourunique() {
    saveIFS=$IFS
    IFS=$'\n'                                   
    local word=${COMP_WORDS[COMP_CWORD]}
    COMPREPLY=($(compgen -f -- "${word}"))
    if [[ "$word" ]] ; then
        local  w
        local  i=0
        for ((i=0;i<${#COMPREPLY[@]};i++)) ; do
            w="${COMPREPLY[$i]}"
            n=${#word}
            w=$(SanitiseString "$w")
            if  [[ ${#COMPREPLY[@]} -gt 1 ]] ; then
                COMPREPLY[$i]="$w :${w:n:1}"
            else
                COMPREPLY[$i]="$w"
            fi
        done
    fi
    IFS=$saveIFS
}

complete -D -F _colourunique

Dadurch werden die Optionen mit dem nächsten eindeutigen Tastendruck gedruckt, der durch Folgendes getrennt ist:

Der Code weist jedoch immer noch zwei irritierende Probleme auf. was ich lösen muss

  1. Das / am Ende von automatisch vervollständigten Verzeichnissen wird nicht mehr angehängt
  2. Der intelligente Abstand nach der automatischen Vervollständigung wird nicht mehr ausgeführt.

Irgendwelche Vorschläge?

Indiajoe
quelle
Ich glaube nicht, dass Sie tun können, was Sie versuchen. Die Escape-Sequenzen, die zum Formatieren der Ausgabe verwendet werden, sollten eigentlich nicht Teil der Ausgabe sein, bashbieten jedoch einfach keinen Hook für die benutzerdefinierte Formatierung der möglichen Vervollständigungen.
Chepner
1
Die einfache Antwort ist, zu zsh zu wechseln, wo dies eine Konfigurationsoption ist.
Gilles 'SO - hör auf böse zu sein'
Da es so aussieht, kann ich in Bash nicht machen, was ich will. Ich versuche stattdessen etwas anderes zu tun. Ich habe ein Update hinzugefügt, das das nächste eindeutige Schlüsselwort, das durch: getrennt ist, an die zu druckende Liste anfügt.
Indien

Antworten:

2

Obwohl dies nicht genau das ist, wonach Sie gefragt haben, habe ich beschlossen, diese Antwort zu posten, weil ich ursprünglich die gleiche Idee hatte wie Sie, aber am Ende löse ich sie so und finde sie sogar besser als das Färben.

Diese Option kann für die GNU-Readline-Bibliothek festgelegt werden :

Vervollständigungspräfix-Anzeigelänge Die Länge des allgemeinen Präfixes einer Liste möglicher Vervollständigungen in Zeichen, die ohne Änderung angezeigt wird. Bei einem Wert größer als Null werden häufig verwendete Präfixe, die länger als dieser Wert sind, durch Auslassungspunkte ersetzt, wenn mögliche Abschlüsse angezeigt werden.

So zum Beispiel diese Zeile in ~ / .inputrc :

set completion-prefix-display-length 2

macht den Trick auch (wenn das gemeinsame Präfix länger als zwei Zeichen ist).

Martin Jiřička
quelle
0

Meine .c ist nicht so heiß, aber wenn ich in http://git.savannah.gnu.org/cgit/bash.git/snapshot/bash-master.tar.gz herumlese, sieht es für mich so aus, als wäre COMPREPLY nichts weiter als nicht aktivierte Textdaten. iow, selbst wenn ein Escape korrekt eingefügt wird, wird es als nicht magische / nicht spezielle Darstellung der Zeichen gedruckt, mit denen wir sie ausdrücken.

wie \033oder \enicht das einzelne Zeichen "Escape", sondern die vier oder zwei Zeichen von Backslashes und Nullen, Dreien und Es.

Ich stieß mit verschiedenen Iterationen printf/ echo/ evalvor dem Tauchen in die .c , um zu sehen , wie es tatsächlich behandeln die Werte in COMPREPLY.

könnte falsch sein, aber überprüfen Sie strlist_print()in lib/sh/stringlist.caussieht wie COMPREPLY eine Struktur vom Typ String ist (wie definiert in externs.h).

jrrs
quelle
Was bedeutet das? Wollen Sie STRINGLIST sagen, weil diese speziell behandelt werden und Fluchten… entkommen sind?
Evi1M4chine