Quando você pressiona Ctrl+X, o emulador de terminal grava o byte 0x18 no lado principal do par pseudo-terminal.
O que acontece a seguir depende de como a disciplina tty line (um módulo de software no kernel que fica entre o lado mestre (sob controle do emulador) e o lado escravo (com o qual os aplicativos em execução no terminal interagem)) está configurada.
Um comando para configurar essa disciplina de linha tty é o stty
comando.
Ao executar um aplicativo idiota como cat
esse não está ciente e não se importa se seu stdin é um terminal ou não, o terminal está no modo canônico padrão , onde a disciplina de linha tty implementa um editor de linha bruta .
Alguns aplicativos interativos que precisam mais do que o editor de linha bruta geralmente alteram essas configurações na inicialização e as restauram ao sair. As conchas modernas, quando solicitadas, são exemplos dessas aplicações. Eles implementam seu próprio editor de linha mais avançado.
Normalmente, enquanto você digita uma linha de comando, o shell coloca a disciplina da linha tty nesse modo e, quando você pressiona enter para executar o comando atual, o shell restaura o modo tty normal (como estava em vigor antes de emitir o prompt).
Se você executar o stty -a
comando, verá as configurações atuais em uso para os aplicativos mudos . É provável que você ver a icanon
, echo
e echoctl
definições a ser habilitado.
O que isso significa é que:
icanon
: esse editor de linha bruta está ativado.
echo
: os caracteres digitados (que o emulador de terminal grava no lado mestre) são repetidos (disponibilizados para leitura pelo emulador de terminal).
echoctl
: em vez de serem repetidos como asis, os caracteres de controle são repetidos como ^X
.
Então, digamos que você digite A B Backspace-aka-Ctrl+H/? C Ctrl+X Backspace Return.
Seu emulador de terminal irá enviar: AB\bC\x18\b\r
. A disciplina de linha ecoará de volta :,AB\b \bC^X\b \b\b \b\r\n
e um aplicativo que lê a entrada do lado escravo ( /dev/pts/x
) lerá AC\n
.
Tudo o que o aplicativo vê é AC\n
, e somente quando você pressiona, Enterpara que ele não possa ter nenhum controle na saída por ^X
lá.
Você notará que, para eco , o primeiro ^H
( ^?
com alguns terminais, consulte a erase
configuração) resultou no \b \b
envio de volta ao terminal. Essa é a sequência para mover o cursor para trás, substituir o espaço, mover o cursor para trás novamente, enquanto o segundo ^H
resultou na \b \b\b \b
exclusão desses dois ^
e X
caracteres.
O próprio ^X
(0x18) estava sendo traduzido para ^
e X
para saída. Como B
, não chegou ao aplicativo, pois o excluímos com Backspace.
\r
(aka ^M
) foi traduzido para \r\n
( ^M^J
) para eco e \n
( ^J
) para o aplicativo.
Então, quais são as nossas opções para essas aplicações idiotas :
- desativar
echo
( stty -echo
). Isso muda efetivamente a maneira como os caracteres de controle são repetidos, ... não repetindo nada. Não é realmente uma solução.
- desativar
echoctl
. Isso muda os caracteres de controle caminho (exceto ^H
, ^M
... e todos os outros utilizados pelo editor de linha) são ecoados. Eles são ecoados como estão. Por exemplo, o caractere ESC é enviado como o byte \e
( ^[
/ 0x1b
) (que é reconhecido como o início de uma sequência de escape pelo terminal), ^G
você envia um \a
(um BEL, emitindo um bipe no terminal) ... Não é uma opção .
- desative o editor de linha bruta (
stty -icanon
). Não é realmente uma opção, pois os aplicativos brutos se tornariam muito menos utilizáveis.
- edite o código do kernel para alterar o comportamento da disciplina de linha tty, para que o eco de um caractere de controle seja enviado em
\e[7m^X\e[m
vez de apenas ^X
(aqui \e[7m
geralmente habilita o vídeo reverso na maioria dos terminais).
Uma opção poderia ser usar um invólucro como rlwrap
esse, um hack sujo para adicionar um editor de linhas sofisticado a aplicativos burros. Com efeito, esse invólucro tenta substituir read()
s simples do dispositivo terminal por chamadas para o editor de linha readline (que alteram o modo da disciplina de linha tty).
Indo ainda mais longe, você pode tentar soluções como esta, que sequestram toda a entrada do terminal para passar pelo editor de linha do zsh (que por acaso destaca ^X
s no vídeo reverso), contando com o :exec
recurso da tela GNU .
Agora, para aplicativos que implementam seu próprio editor de linha, cabe a eles decidir como o eco é feito. bash
usa readline para aquilo que não tem suporte para personalizar como os caracteres de controle são repetidos.
Para zsh
, veja:
info --index-search='highlighting, special characters' zsh
zsh
destaca caracteres não imprimíveis por padrão. Você pode personalizar o destaque com, por exemplo:
zle_highlight=(special:fg=white,bg=red)
Para branco e vermelho, destaque para esses caracteres especiais.
A representação de texto desses caracteres não é personalizável.
Em um locale UTF-8, 0x18 será processado como ^X
, \u378
, \U7fffffff
(dois pontos de código unicode não atribuídos), como <0378>
, <7FFFFFFF>
, \u200b
(um caractere Unicode não-realmente impressa) como <200B>
.
\x80
em um código de idioma iso8859-1 seria renderizado como ^�
... etc.
bash
ele éreadline
lidar com essas coisas, e para a maioria dos outros é o driver tty.