Come visualizzare i caratteri di controllo (^ C, ^ D, ^ [,…) in modo diverso nella shell


13

Quando si digitano i caratteri di controllo nella shell, questi vengono visualizzati usando quella che viene chiamata "notazione". La fuga, ad esempio, viene scritta come ^[nella notazione con il cursore.

Mi piace personalizzare la mia shell bash per renderla bella. Ad esempio ho cambiato il mio PS1e PS2per diventare colorato. Ora voglio che anche i personaggi di controllo abbiano un aspetto unico per renderli più distinguibili dai personaggi normali.

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

C'è un modo per evidenziare diversamente i caratteri di controllo della shell?

È possibile farli visualizzare in grassetto o magari farli apparire in colori diversi dal normale testo?

Sto usando bash shell qui ma non ho taggato la domanda bashperché forse esiste una soluzione che si applica a molte shell diverse.

Nota che non so a che livello si evidenzieranno i personaggi di controllo. Ho pensato inizialmente che fosse nel guscio stesso. Ora ho sentito che è readline che controlla come i personaggi di controllo sono nelle shell come bash . Quindi la domanda è ora taggata readlinee sto ancora cercando risposte.


perché pensi che la shell li stia mettendo in evidenza? per bashesso è readlinegestendo quella roba, e per la maggior parte altri è il driver TTY.
Mikeserv,

Non lo sapevo. Ecco perché ho scritto la nota. Era solo una mia ipotesi perché altre applicazioni come vie lessspesso evidenziano i caratteri di controllo in modo diverso dal testo normale. Modificherò la domanda con queste informazioni. Grazie!
wefwefa3,

ha senso. quel tipo di roba è più difficile per una shell perché è una seconda priorità. con gli editor il loro intero compito è fornire un'interfaccia di file <>, ma la shell è prima un interprete di comandi per un linguaggio interpretato e un secondo editor di riga (o per niente) .
Mikeserv,

Readline è usato da altri programmi, ma anche che è parte di bash: si tratta di una libreria collegata in esso. E le conchiglie di oggi, specialmente bash, fanno praticamente qualsiasi cosa tu possa pensare.
alexis

Basta usare zshciò che lo fa immediatamente.
Stéphane Chazelas,

Risposte:


20

Quando si preme Ctrl+X, l'emulatore di terminale scrive il byte 0x18 sul lato principale della coppia pseudo-terminale.

Cosa succederà dopo dipende da come viene configurata la disciplina tty line (un modulo software nel kernel che si trova tra il lato master (sotto il controllo dell'emulatore) e il lato slave (con cui interagiscono le applicazioni in esecuzione nel terminale)).

Un comando per configurare quella disciplina tty line è il sttycomando.

Quando si esegue un'applicazione stupida come catquella non è a conoscenza e non importa se il suo stdin è un terminale o meno, il terminale è in una modalità canonica predefinita in cui la disciplina tty line implementa un editor di linee grezze .

Alcune applicazioni interattive che richiedono più di quell'editor di linea grezza in genere modificano tali impostazioni all'avvio e le ripristinano all'uscita. Le shell moderne, al loro prompt, sono esempi di tali applicazioni. Implementano il proprio editor di linee più avanzato.

In genere, mentre si immette una riga di comando, la shell inserisce la disciplina della linea tty in quella modalità e quando si preme invio per eseguire il comando corrente, la shell ripristina la normale modalità tty (come era in vigore prima di emettere il prompt).

Se esegui il stty -acomando, vedrai le impostazioni correnti in uso per le applicazioni stupide . È probabile che tu veda icanon, echoe le echoctlimpostazioni siano abilitate.

Ciò significa che:

  • icanon: quell'editor di linea grezza è abilitato.
  • echo: i caratteri digitati (che l'emulatore di terminale scrive sul lato principale) vengono ripetuti (resi disponibili per la lettura dall'emulatore di terminale).
  • echoctl: invece di essere riecheggiato asis, i caratteri di controllo vengono ripetuti come ^X.

Quindi, supponiamo che tu digiti A B Backspace-aka-Ctrl+H/? C Ctrl+X Backspace Return.

Il tuo emulatore di terminale invierà: AB\bC\x18\b\r. La disciplina riga eco indietro: AB\b \bC^X\b \b\b \b\r\ne un'applicazione che legge l'input dal lato slave ( /dev/pts/x) leggerà AC\n.

Tutto ciò che l'applicazione vede è AC\n, e solo quando la tua stampa Enternon può avere alcun controllo sull'output per ^Xlì.

Noterai che per l' eco , il primo ^H( ^?con alcuni terminali, vedi le eraseimpostazioni) ha comportato \b \bl'invio al terminale. Questa è la sequenza per spostare indietro il cursore, sovrascrivere con lo spazio, spostare nuovamente il cursore indietro, mentre il secondo ha ^Hportato \b \b\b \ba cancellare quei due ^e Xcaratteri.

Lo stesso ^X(0x18) veniva tradotto in ^e Xper l'output. Ad esempio B, non è arrivato all'applicazione, poiché l'abbiamo eliminato con Backspace.

\r(aka ^M) è stato tradotto in \r\n( ^M^J) per echo e \n( ^J) per l'applicazione.

Quindi, quali sono le nostre opzioni per quelle applicazioni stupide :

  • disable echo( stty -echo). Questo cambia efficacemente il modo in cui i personaggi di controllo vengono fatti eco, non ... facendo eco a nulla. Non proprio una soluzione.
  • disabilita echoctl. Ciò cambia il modo in cui i caratteri di controllo (diversi da ^H, ^M... e tutti gli altri utilizzati dall'editor di riga) vengono ripetuti. Vengono quindi fatti eco così come sono. Cioè, ad esempio, il carattere ESC viene inviato come byte \e( ^[/ 0x1b) (che viene riconosciuto come l'inizio di una sequenza di escape dal terminale), ^Gsi invia un \a(un BEL, facendo suonare il terminale) ... Non un'opzione .
  • disabilitare l'editor delle linee grezze ( stty -icanon). Non è un'opzione in quanto le applicazioni grezze diventerebbero molto meno utilizzabili.
  • modifica il codice del kernel per cambiare il comportamento della disciplina tty line in modo che l' eco di un personaggio di controllo invii \e[7m^X\e[minvece di solo ^X(qui di \e[7msolito abilita il video inverso nella maggior parte dei terminali).

Un'opzione potrebbe essere quella di utilizzare un wrapper come rlwrapquello è un trucco sporco per aggiungere un editor di linea di fantasia alle applicazioni stupide. Quel wrapper in effetti tenta di sostituire semplici read()s dal dispositivo terminale a chiamate all'editor di linea readline (che modifica la modalità della disciplina tty line).

Andando ancora oltre, potresti persino provare soluzioni come questa che dirotta tutto l'input dal terminale per passare attraverso l'editor di linee di zsh (che capita di evidenziare ^Xs nel video al contrario) facendo affidamento sulla :execfunzionalità dello schermo GNU .

Ora, per le applicazioni che implementano il proprio editor di linee, sta a loro decidere come eseguire l' eco . bashusa readline per ciò che non ha alcun supporto per personalizzare il modo in cui i personaggi di controllo vengono ripetuti.

Per zsh, vedi:

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

zshevidenzia i caratteri non stampabili per impostazione predefinita. È possibile personalizzare l'evidenziazione con ad esempio:

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

Per l'evidenziazione del bianco su rosso per quei caratteri speciali.

La rappresentazione testuale di questi personaggi non è personalizzabile.

In una localizzazione UTF-8, 0x18 saranno resi come ^X, \u378, \U7fffffff(due punti di codice unicode non assegnati) come <0378>, <7FFFFFFF>, \u200b(un carattere unicode stampabile non-veramente) come <200B>.

\x80in un locale iso8859-1 verrebbe eseguito il rendering come ^�... ecc.


3

Di solito ho questo codice nel mio file .bashrc:

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

e poi chiamo questa funzione nella mia PS1

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

Con questo, se premi ^ C lo vedrai nel tuo prompt

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

Verranno richiesti tutti i codici di stato di uscita che non sono "0".


$? si espande per uscire dallo stato in PS1, ad esempio PS1 = '$? \ u @ \ h \ w'
teknopaul
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.