Quando você digita caracteres de controle no shell, eles são exibidos usando o que é chamado de "notação de intercalação". Escape, por exemplo, é escrito como ^[
na notação de sinal de intercalação.
Eu gosto de personalizar meu shell bash para torná-lo legal. Eu, por exemplo, mudei o meu PS1
e fiquei PS2
colorido. Agora, quero que os caracteres de controle tenham uma aparência única e os tornem mais distinguíveis dos caracteres comuns.
$ # Here I type CTRL-C to abort the command.
$ blahblah^C
^^ I want these two characters to be displayed differently
Existe uma maneira de fazer meu shell destacar caracteres de controle de maneira diferente?
É possível fazê-lo exibi-los em uma fonte em negrito ou talvez fazê-los aparecer em cores diferentes do texto normal?
Estou usando o shell bash aqui, mas não marquei a pergunta bash
porque talvez exista uma solução que se aplique a muitos shells diferentes.
Observe que não sei em que nível o destaque dos caracteres de controle ocorre. Eu primeiro pensei que estava na própria concha. Agora ouvi dizer que é a linha de leitura que controla como os caracteres de controle estão em conchas como o bash . Portanto, a pergunta agora está marcada readline
e eu ainda estou procurando respostas.
bash
ele éreadline
lidar com essas coisas, e para a maioria dos outros é o driver tty.vi
eless
geralmente destacam os caracteres de controle de maneira diferente do texto comum. Vou editar a pergunta com esta informação. Obrigado!zsh
que faz isso fora da caixa.Respostas:
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 aicanon
,echo
eechoctl
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 aerase
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^
eX
caracteres.O próprio
^X
(0x18) estava sendo traduzido para^
eX
para saída. ComoB
, 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 :
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.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 .stty -icanon
). Não é realmente uma opção, pois os aplicativos brutos se tornariam muito menos utilizáveis.\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 substituirread()
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:zsh
destaca caracteres não imprimíveis por padrão. Você pode personalizar o destaque com, por exemplo: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.fonte
Geralmente, tenho esse código no meu arquivo .bashrc:
e então eu chamo essa função no meu PS1
Com isso, se você pressionar ^ C, verá no seu prompt
Todos os códigos de status de saída que não são "0" serão solicitados.
fonte