%20de%20maneira%20diferente%20no%20shell.png)
Quando você digita caracteres de controle no shell, eles são exibidos usando o que é chamado de "notação circunflexa". Escape, por exemplo, é escrito ^[
em notação de circunflexo.
Gosto de personalizar meu shell bash para torná-lo legal. Por exemplo, mudei o meu PS1
e PS2
fiquei colorido. Agora quero que os personagens de controle também tenham uma aparência única para torná-los mais distinguíveis dos personagens normais.
$ # 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 exibi-los em negrito ou talvez fazê-los aparecer em cores diferentes do texto normal?
estou usandofestashell aqui, mas não marquei a pergunta bash
porque talvez haja uma solução que se aplique a muitos shells diferentes.
Observaçãoque não sei em que nível ocorre o realce dos caracteres de controle. A princípio pensei que estivesse no próprio shell. Agora ouvi dizer que éLeia a linhaque controla como os caracteres de controle estão em shells comofesta. Portanto, a pergunta agora está marcada readline
e ainda estou procurando respostas.
Responder1
Quando você pressiona Ctrl+X, seu emulador de terminal grava o byte 0x18 no lado mestre do par de pseudoterminais.
O que acontece a seguir depende de como a disciplina de linha tty (um módulo de software no kernel que fica entre o lado mestre (sob o controle do emulador) e o lado escravo (com o qual os aplicativos em execução no terminal interagem)) está configurada.
Um comando para configurar issodisciplina de linha ttyé o stty
comando.
Ao executar um aplicativo idiota como cat
esse, não reconhece e não se importa se seu stdin é um terminal ou não, o terminal está em um padrãocanônicomodo onde a disciplina de linha tty implementa um brutoeditor de linha.
Alguns aplicativos interativos que precisam de mais do que issoeditor de linhanormalmente altera essas configurações na inicialização e restaura-as ao sair. Conchas modernas,no seu promptsão exemplos de tais aplicações. Eles implementam seu próprio editor de linha mais avançado.
Normalmente, enquanto você insere uma linha de comando, o shell coloca a disciplina de 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 oaplicativos idiotas. É provável que você veja as icanon
configurações echo
e echoctl
sendo ativadas.
O que isso significa é que:
icanon
: esse editor de linha bruto está habilitado.echo
: os caracteres que você digita (que o emulador de terminal grava no lado mestre) sãoecoouback (disponibilizado para leitura pelo emulador de terminal).echoctl
: em vez de serecoouasis, os personagens de controle sãoecooucomo^X
.
Então, digamos que você digite A B Backspace-aka-Ctrl+H/? C Ctrl+X Backspace Return.
Seu emulador de terminal enviará: AB\bC\x18\b\r
. A disciplina de linhaecoback: 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 não possa ter nenhum controle sobre a saída ^X
.
Você notará isso poreco, o primeiro ^H
( ^?
com alguns terminais, veja 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 com espaço, mover o cursor para trás novamente, enquanto a segunda ^H
resultou em \b \b\b \b
apagar esses dois caracteres ^
e .X
O ^X
próprio (0x18) estava sendo traduzido para ^
e X
para saída. Tipo B
, ele não chegou ao aplicativo, pois o excluímos com Backspace.
\r
(também conhecido como ^M
) foi traduzido para \r\n
( ^M^J
) para eco e \n
( ^J
) para aplicação.
Então, quais são as nossas opções para aquelesburroformulários:
- desativar
echo
(stty -echo
). Isso efetivamente muda a forma como os personagens de controle são ecoados, por... não ecoar nada. Não é realmente uma solução. - desativar
echoctl
. Isso muda a maneira como os caracteres de controle (exceto^H
,^M
... e todos os outros usados pelo editor de linha) são ecoados. Eles são entãoecooucomo é. Ou seja, por exemplo, o caracter 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, fazendo seu terminal apitar)... Não é uma opção . - desabilitar o editor de linhas brutas (
stty -icanon
). Não é realmente uma opção, pois os aplicativos rudimentares se tornariam muito menos utilizáveis. - edite o código do kernel para alterar o comportamento da disciplina de linha tty para que oecode um caractere de controle envia
\e[7m^X\e[m
em vez de apenas^X
(aqui\e[7m
geralmente habilita vídeo reverso na maioria dos terminais).
Uma opção poderia ser usar um wrapper como rlwrap
esse, um hack sujo para adicionar um editor de linha sofisticado a aplicativos idiotas. Na verdade, esse wrapper 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 até tentar soluções comoEsteque sequestra todas as entradas do terminal para passar pelo editor de linha do zsh (que destaca ^X
s no vídeo reverso) dependendo do recurso da tela GNU :exec
.
Agora, para aplicativos que implementam seu próprio editor de linha, cabe a eles decidir como oecoé feito. bash
usa readline para aquilo que não tem suporte para personalizar como os caracteres de controle são ecoados.
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 destaque em branco sobre vermelho para esses caracteres especiais.
A representação de texto desses caracteres não é personalizável.
Em uma localidade UTF-8, 0x18 será renderizado como ^X
, \u378
, \U7fffffff
(dois pontos de código Unicode não atribuídos) como <0378>
, <7FFFFFFF>
, \u200b
(um caractere Unicode não realmente imprimível) como <200B>
.
\x80
em uma localidade iso8859-1 seria renderizado como ^�
... etc.
Responder2
Normalmente tenho este código em meu arquivo .bashrc:
function get_exit_status()
{
local code=$?
if [ $code -ne 0 ]
then
printf $'\001\033[31m\002'"($code)"$'\001\033[0m\002'" "
fi
}
e então eu chamo essa função no meu PS1
PS1='\u@\h \w $(get_exit_status)'
Com isso, se você pressionar ^C você verá no seu prompt
I@mycomputer ~ ^C
I@mycomputer ~ (130)
Todos os códigos de status de saída que não sejam “0” serão solicitados.