Como exibir caracteres de controle (^C, ^D, ^[, ...) de maneira diferente no shell

Como exibir caracteres de controle (^C, ^D, ^[, ...) de maneira diferente no shell

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 PS1e PS2fiquei 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 bashporque 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 readlinee 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 sttycomando.

Ao executar um aplicativo idiota como catesse, 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 -acomando, verá as configurações atuais em uso para oaplicativos idiotas. É provável que você veja as icanonconfigurações echoe echoctlsendo 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 eraseconfiguração) resultou no \b \benvio 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 ^Hresultou em \b \b\b \bapagar esses dois caracteres ^e .X

O ^Xpróprio (0x18) estava sendo traduzido para ^e Xpara 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), ^Gvocê 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[mem vez de apenas ^X(aqui \e[7mgeralmente habilita vídeo reverso na maioria dos terminais).

Uma opção poderia ser usar um wrapper como rlwrapesse, 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 ^Xs 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. bashusa 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

zshdestaca 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>.

\x80em 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.

informação relacionada