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 stty
comando.
Quando si esegue un'applicazione stupida come cat
quella 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 -a
comando, vedrai le impostazioni correnti in uso per le applicazioni stupide . È probabile che tu veda icanon
, echo
e le echoctl
impostazioni 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\n
e 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 ^X
lì.
Noterai che per l' eco , il primo ^H
( ^?
con alcuni terminali, vedi le erase
impostazioni) ha comportato \b \b
l'invio al terminale. Questa è la sequenza per spostare indietro il cursore, sovrascrivere con lo spazio, spostare nuovamente il cursore indietro, mentre il secondo ha ^H
portato \b \b\b \b
a cancellare quei due ^
e X
caratteri.
Lo stesso ^X
(0x18) veniva tradotto in ^
e X
per 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), ^G
si 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[m
invece di solo ^X
(qui di \e[7m
solito abilita il video inverso nella maggior parte dei terminali).
Un'opzione potrebbe essere quella di utilizzare un wrapper come rlwrap
quello è 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 ^X
s nel video al contrario) facendo affidamento sulla :exec
funzionalità dello schermo GNU .
Ora, per le applicazioni che implementano il proprio editor di linee, sta a loro decidere come eseguire l' eco . bash
usa 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
zsh
evidenzia 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>
.
\x80
in un locale iso8859-1 verrebbe eseguito il rendering come ^�
... ecc.
bash
esso èreadline
gestendo quella roba, e per la maggior parte altri è il driver TTY.