So zeigen Sie Steuerzeichen (^ C, ^ D, ^ [,…) in der Shell unterschiedlich an

13

Wenn Sie Steuerzeichen in die Shell eingeben, werden diese in der sogenannten "Caret-Notation" angezeigt. Escape zum Beispiel wird wie ^[in Caret-Notation geschrieben.

Ich mag es, meine Bash-Shell so anzupassen, dass sie cool aussieht. Ich habe zum Beispiel meine geändert PS1und PS2eingefärbt. Ich möchte jetzt, dass Steuerzeichen auch ein einzigartiges Erscheinungsbild erhalten, damit sie sich besser von normalen Zeichen unterscheiden können.

$ # Here I type CTRL-C to abort the command.
$ blahblah^C
          ^^ I want these two characters to be displayed differently

Gibt es eine Möglichkeit, meine Shell Steuerzeichen anders hervorzuheben?

Ist es möglich, sie fett darzustellen oder in anderen Farben als normalem Text darzustellen?

Ich verwende hier die Bash- Shell, aber ich habe die Frage nicht mit bashmarkiert, da es möglicherweise eine Lösung gibt, die für viele verschiedene Shells gilt.

Beachten Sie, dass ich nicht weiß, auf welcher Ebene das Hervorheben von Steuerzeichen stattfindet. Ich dachte zuerst, dass es in der Muschel selbst war. Jetzt habe ich gehört, dass readline steuert, wie Steuerzeichen in Shells wie Bash sind . Die Frage ist also jetzt markiert readlineund ich suche immer noch nach Antworten.

wefwefa3
quelle
Warum hebt die Shell sie Ihrer Meinung nach hervor? für bashsie ist readlinedas Zeug Handhabung und für die meisten anderen ist es die tty - Treiber.
mikeserv
Ich wusste es nicht. Deshalb habe ich die Notiz geschrieben. Es war nur meine Vermutung, weil andere Anwendungen Steuerzeichen mögen viund lessoft anders hervorheben als normaler Text. Ich werde die Frage mit diesen Informationen bearbeiten. Vielen Dank!
wefwefa3
Das macht Sinn. solche Sachen sind für eine Shell schwieriger, weil sie eine zweite Priorität haben. Bei Redakteuren besteht ihre gesamte Aufgabe darin, eine Bildschirm-Dateischnittstelle bereitzustellen. Die Shell ist jedoch ein Befehlsinterpreter für eine zuerst interpretierte Sprache und einen zweiten (oder gar keinen) Zeileneditor .
mikeserv
Readline- wird von anderen Programmen verwendet, sondern auch es ist Teil der bash: es ist eine Bibliothek in ihm verbunden ist. Und die heutigen Muscheln, insbesondere die Bash, tun so ziemlich alles, was Sie sich vorstellen können.
Alexis
Verwenden Sie einfach, zshwas das aus der Box macht.
Stéphane Chazelas

Antworten:

20

Wenn Sie drücken Ctrl+X, schreibt Ihr Terminal-Emulator das Byte 0x18 auf die Masterseite des Pseudo-Terminal-Paares.

Was als nächstes passiert, hängt davon ab, wie die tty line-Disziplin (ein Softwaremodul im Kernel, das sich zwischen der Masterseite (unter Kontrolle des Emulators) und der Slaveseite (mit welchen Anwendungen das Terminal interagiert) befindet) konfiguriert ist.

Ein Befehl zum Konfigurieren dieser tty-Zeilendisziplin ist der sttyBefehl.

Wenn eine dumme Anwendung ausgeführt wird wie catdas nicht bewusst ist , und kümmert sich nicht darum , ob seine stdin ein Terminal ist oder nicht, ist das Terminal in einem Standard kanonische Modus , in dem die Disziplin Geräte tty Linie eine grobe Editor Linie .

Einige interaktive Anwendungen, die mehr als diesen einfachen Zeileneditor benötigen, ändern diese Einstellungen normalerweise beim Start und stellen sie beim Verlassen wieder her. Moderne Muscheln, an ihrem Prompt sind Beispiele für solche Anwendungen. Sie implementieren ihren eigenen erweiterten Zeileneditor.

Während Sie eine Befehlszeile eingeben, versetzt die Shell die tty-Zeilendisziplin in diesen Modus. Wenn Sie die Eingabetaste drücken, um den aktuellen Befehl auszuführen, stellt die Shell den normalen tty-Modus wieder her (wie er vor der Ausgabe der Eingabeaufforderung wirksam war).

Wenn Sie den stty -aBefehl ausführen , werden die aktuellen Einstellungen für die dummen Anwendungen angezeigt . Du bist wahrscheinlich die , um zu sehen icanon, echound die echoctlEinstellungen werden aktiviert.

Was das bedeutet ist, dass:

  • icanon: Der Rohzeileneditor ist aktiviert.
  • echo: Zeichen (dass der Terminal - Emulator schreibt an die Master - Seite) sind vom Typ Echo zurück (zur Verfügung gestellt für das Lesen durch den Terminal - Emulator).
  • echoctl: Anstatt dass wiederholte asis, werden die Steuerzeichen hallte wie ^X.

Angenommen, Sie tippen A B Backspace-aka-Ctrl+H/? C Ctrl+X Backspace Return.

Ihr Terminal - Emulator sendet: AB\bC\x18\b\r. Die Zeilendisziplin gibt zurück: AB\b \bC^X\b \b\b \b\r\nund eine Anwendung, die die Eingabe von der Slave-Seite ( /dev/pts/x) liest, liest AC\n.

Alles, was die Anwendung sieht, ist AC\n, und nur wenn Sie drücken Enter, kann sie keine Kontrolle über die Ausgabe für ^Xdort haben.

Sie werden feststellen, dass für Echo das erste ^H( ^?bei einigen Terminals, siehe eraseEinstellung) \b \bzum Terminal zurückgesendet wurde. Das ist die Folge , um den Cursor zurück zu bewegen, überschrieben mit Raum, bewegt den Cursor wieder zurück, während die zweite ^Hin Folge , \b \b\b \bdiese beiden zu löschen ^und XZeichen.

Das ^X(0x18) selbst wurde in ^und Xfür die Ausgabe übersetzt. Als ob Bes nicht in die Anwendung geschafft hätte, da wir es mit Backspace gelöscht haben.

\r(aka ^M) wurde für das Echo in ( ) und für die Anwendung in \r\n( ^M^J) übersetzt .\n^J

Also, was sind unsere Optionen für diese dummen Anwendungen:

  • deaktiviere echo( stty -echo). Dies ändert effektiv die Art und Weise, wie Steuerzeichen wiedergegeben werden, indem ... nichts wiedergegeben wird. Keine wirkliche Lösung.
  • deaktivieren echoctl. Dadurch wird die Art und Weise geändert, in der Steuerzeichen (außer ^H, ^M... und alle anderen vom Zeileneditor verwendeten) wiedergegeben werden. Sie werden dann unverändert wiedergegeben . Das heißt, das ESC-Zeichen wird als \e( ^[/ 0x1b) Byte gesendet (das vom Terminal als Beginn einer Escape-Sequenz erkannt wird), ^GSie senden ein \a(ein BEL, wodurch Ihr Terminal piept) ... Keine Option .
  • Deaktivieren Sie den Rohzeilen-Editor ( stty -icanon). Nicht wirklich eine Option, da die Rohanwendungen viel weniger verwendbar wären.
  • Bearbeiten Sie den Kernel-Code, um das Verhalten der tty-Zeilendisziplin so zu ändern, dass das Echo eines Steuerzeichens \e[7m^X\e[mstatt nur gesendet wird ^X( \e[7min den meisten Terminals wird hier normalerweise das Rückvideo aktiviert).

Eine Option könnte sein, einen solchen Wrapper zu verwenden rlwrap, der ein schmutziger Hack ist, um dummen Anwendungen einen ausgefallenen Zeileneditor hinzuzufügen. Dieser Wrapper versucht tatsächlich, einfache read()s vom Endgerät zu ersetzen , um Aufrufe des Zeileneditors zu lesen (die den Modus der tty-Zeilendisziplin ändern).

Wenn Sie noch weiter gehen, können Sie sogar Lösungen wie diese ausprobieren , bei denen alle Eingaben vom Terminal entführt werden, um den Zeileneditor von zsh (der zufällig ^Xs im umgekehrten Video hervorhebt ) zu durchlaufen, wobei Sie auf die Funktion des GNU-Bildschirms angewiesen sind :exec.

Für Anwendungen, die einen eigenen Zeileneditor implementieren, müssen sie nun entscheiden, wie das Echo erfolgen soll. bashverwendet readline für das, was keine Unterstützung für das Anpassen der Echowiedergabe von Steuerzeichen bietet.

Für zshfinden Sie unter :

info --index-search='highlighting, special characters' zsh

zshhebt standardmäßig nicht druckbare Zeichen hervor. Sie können die Hervorhebung zum Beispiel anpassen mit:

zle_highlight=(special:fg=white,bg=red)

Für die Hervorhebung von Weiß auf Rot für diese Sonderzeichen.

Die Textdarstellung dieser Zeichen ist jedoch nicht anpassbar.

In einem UTF-8 locale wird 0x18 gemacht als ^X, \u378, \U7fffffff(zwei nicht zugewiesene Unicode - Codepunkte) als <0378>, <7FFFFFFF>, \u200b(eine nicht wirklich druckbaren Unicode - Zeichen) wie <200B>.

\x80in einem iso8859-1-Gebietsschema würde gerendert als ^�... etc.

Stéphane Chazelas
quelle
3

Ich habe normalerweise diesen Code in meiner .bashrc-Datei:

function get_exit_status()
{
        local code=$?
        if [ $code -ne 0 ]
        then
                printf $'\001\033[31m\002'"($code)"$'\001\033[0m\002'" "
        fi
}

und dann rufe ich diese funktion in meiner ps1 auf

PS1='\u@\h \w $(get_exit_status)'

Wenn Sie nun ^ C drücken, wird dies in Ihrer Eingabeaufforderung angezeigt

I@mycomputer ~ ^C
I@mycomputer ~ (130)

Alle Beendigungsstatuscodes, die nicht "0" sind, werden aufgefordert.

toed
quelle
$? wird erweitert, um den Status in der PS1 zu verlassen, z. B. PS1 = '$? \ u @ \ h \ w'
teknopaul