Jak wyświetlać znaki kontrolne (^ C, ^ D, ^ [,…) inaczej w powłoce

13

Po wpisaniu znaków kontrolnych w powłoce są one wyświetlane przy użyciu tak zwanej „notacji karetki”. Na przykład Escape jest zapisywane ^[w notacji karetki.

Lubię dostosowywać moją powłokę bash, aby wyglądała fajnie. Na przykład zmieniłem moje PS1i zostałem PS2pokolorowany. Chcę teraz, aby postacie kontrolne również zyskały niepowtarzalny wygląd, aby były bardziej odróżnialne od zwykłych postaci.

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

Czy istnieje sposób, aby moja powłoka wyróżniała znaki sterujące inaczej?

Czy można wyświetlać je pogrubioną czcionką, a może wyświetlać je w innym kolorze niż zwykły tekst?

Używam tutaj powłoki bash , ale nie otagowałem tego pytania, bashponieważ być może istnieje rozwiązanie, które dotyczy wielu różnych powłok.

Zauważ , że nie wiem, na jakim poziomie występuje podświetlanie znaków kontrolnych. Najpierw pomyślałem, że to w samej skorupce. Teraz słyszałem, że to readline kontroluje, jak znaki kontrolne znajdują się w powłokach, takich jak bash . Pytanie jest więc otagowane readlinei wciąż szukam odpowiedzi.

wefwefa3
źródło
jak myślisz, dlaczego powłoka je wyróżnia? o bashto jest readlineobsługa takich rzeczy, a dla większości innych jest sterownik tty.
mikeserv
Nie wiedziałem Dlatego napisałem notatkę. Po prostu zgadłem, ponieważ inne aplikacje lubią vii lessczęsto wyróżniają znaki sterujące inaczej niż zwykły tekst. Przeredaguję pytanie za pomocą tych informacji. Dziękuję Ci!
wefwefa3
to ma sens. tego rodzaju rzeczy są trudniejsze dla powłoki, ponieważ jest to rodzaj drugiego priorytetu. w przypadku edytorów ich całym zadaniem jest zapewnienie interfejsu pliku screen <>, ale powłoka jest najpierw interpretatorem poleceń dla interpretowanego języka i edytorem linii (lub wcale) .
mikeserv
Readline jest używany przez inne programy, ale także jest częścią bash: jest to biblioteka z nim połączona. Dzisiejsze pociski, zwłaszcza bash, robią prawie wszystko, co możesz wymyślić.
Alexis
Wystarczy użyć, zshktóry robi to po wyjęciu z pudełka.
Stéphane Chazelas,

Odpowiedzi:

20

Po naciśnięciu Ctrl+Xemulator terminala zapisuje bajt 0x18 po stronie master pary pseudo-terminali.

To, co stanie się potem, zależy od tego, jak skonfigurowana jest dyscyplina linii tty (moduł oprogramowania w jądrze, który znajduje się między stroną główną (pod kontrolą emulatora) a stroną podrzędną (z którymi aplikacje działające w terminalu wchodzą w interakcje)).

Poleceniem skonfigurowania tej dyscypliny linii tty jest sttypolecenie.

Podczas uruchamiania takiej głupiej aplikacji catnie jest ona świadoma i nie ma znaczenia, czy jej standardowe wejście jest terminalem, czy nie, terminal jest w domyślnym trybie kanonicznym , w którym dyscyplina linii tty implementuje prosty edytor linii .

Niektóre interaktywne aplikacje, które wymagają więcej niż tego prostego edytora linii, zwykle zmieniają te ustawienia podczas uruchamiania i przywracają je po wyjściu. Nowoczesne powłoki, na ich polecenie, są przykładami takich aplikacji. Wdrażają własny, bardziej zaawansowany edytor linii.

Zazwyczaj podczas wprowadzania wiersza poleceń powłoka wprowadza dyscyplinę linii tty w tym trybie, a po naciśnięciu klawisza enter w celu uruchomienia bieżącego polecenia powłoka przywraca normalny tryb tty (tak jak działał przed wydaniem monitu).

Jeśli uruchomisz stty -apolecenie, zobaczysz bieżące ustawienia używane dla głupich aplikacji . Prawdopodobnie zobaczysz icanon, echoi echoctlustawienia są włączone.

Oznacza to, że:

  • icanon: ten edytor linii surowej jest włączony.
  • echo: znaki, które wpisujesz (które emulator terminala zapisuje po stronie master) są odbijane echem (udostępniane do odczytu przez emulator terminala).
  • echoctl: zamiast echa asis, znaki kontrolne są echo jako ^X.

Powiedzmy, że piszesz A B Backspace-aka-Ctrl+H/? C Ctrl+X Backspace Return.

Terminal Emulator wyśle: AB\bC\x18\b\r. Dyscyplina liniowa wyświetli echo : AB\b \bC^X\b \b\b \b\r\na aplikacja, która odczyta dane wejściowe od strony slave ( /dev/pts/x), odczyta AC\n.

Wszystko, co widzi aplikacja, jest dostępne AC\ntylko po naciśnięciu przycisku, Enterdzięki czemu nie może mieć żadnej kontroli nad danymi wyjściowymi ^X.

Zauważysz, że dla echa , pierwszy ^H( ^?z niektórymi terminalami, patrz eraseustawienie) spowodował \b \bodesłanie z powrotem do terminala. Jest to sekwencja cofania kursora, nadpisywania spacją, cofania kursora z powrotem, podczas gdy druga ^Hspowodowała \b \b\b \busunięcie tych dwóch znaków ^i Xznaków.

Sam ^X(0x18) był tłumaczony na ^i Xna wyjście. Jak B, nie sprawiają, że do wniosku, że my usunął go z Backspace.

\r(aka ^M) został przetłumaczony na \r\n( ^M^J) dla echa i \n( ^J) dla aplikacji.

Jakie są nasze opcje dla tych głupich aplikacji:

  • disable echo( stty -echo). To skutecznie zmienia sposób echa znaków kontrolnych, ... nie odbijając niczego. Niezupełnie rozwiązanie.
  • wyłącz echoctl. Że zmienia znaki sterujące sposób (inne niż ^H, ^M... i wszystkie inne te używane przez edytor linia) są echem. Są one następnie odtwarzane w niezmienionej formie. Oznacza to na przykład, że znak ESC jest wysyłany jako \e( ^[/ 0x1b) bajt (który jest rozpoznawany przez terminal jako początek sekwencji ucieczki), ^Gwysyłasz \a(BEL, co powoduje, że twój terminal emituje sygnał dźwiękowy) ... Brak opcji .
  • wyłącz edytor linii raw ( stty -icanon). Nie jest to właściwie opcja, ponieważ zwykłe aplikacje stałyby się znacznie mniej przydatne.
  • edytuj kod jądra, aby zmienić zachowanie dyscypliny linii tty, dzięki czemu echo znaku sterującego wysyła \e[7m^X\e[mzamiast po prostu ^X(tutaj \e[7mzwykle włącza odwrotne wideo w większości terminali).

Opcją może być użycie takiego opakowania rlwrapto brudny hack, aby dodać fantazyjny edytor linii do głupich aplikacji. To opakowanie próbuje zastąpić proste read()s od urządzenia końcowego na wywołania edytora linii readline (które zmieniają tryb dyscypliny linii tty).

Idąc jeszcze dalej, można nawet spróbować rozwiązania, takie jak ten , który przechwytuje wszystkie dane wejściowe z terminala, aby przejść przez edytor linii zsh (co zdarza się atrakcją ^Xs w negatywie) powołując się na ekranie GNU :execfunkcji.

Teraz w przypadku aplikacji, które implementują własny edytor linii, to od nich zależy, jak echo zostanie wykonane. bashużywa readline dla tego, co nie ma żadnego wsparcia w dostosowywaniu sposobu wyświetlania echa znaków kontrolnych.

Na zshstronie:

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

zshdomyślnie podświetla znaki niedrukowalne. Możesz dostosować podświetlanie, na przykład:

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

Dla biało-czerwonego podświetlenia dla tych znaków specjalnych.

Tekstowej reprezentacji tych znaków nie można jednak dostosowywać.

W UTF-8, 0x18 będzie wyświetlany jako ^X, \u378, \U7fffffff(nieprzypisane dwa punkty kodowe Unicode) jako <0378>, <7FFFFFFF>, \u200b(a nie-naprawdę druku znaków Unicode) jako <200B>.

\x80w lokalizacji iso8859-1 będą renderowane jako ^�... itd.

Stéphane Chazelas
źródło
3

Zwykle mam ten kod w moim pliku .bashrc:

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

a następnie wywołuję tę funkcję w moim PS1

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

Dzięki temu, jeśli naciśniesz ^ C, zobaczysz to w monicie

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

Zostaną wyświetlone monity o wszystkie kody zakończenia wyjścia, które nie są „0”.

palcami
źródło
$? rozwija się, aby wyjść ze statusu na PS1, np. PS1 = „$? \ u @ \ h \ w”
teknopaul