Ao usar o shell bash, tentei usar Shift+ LEFTpara destacar e copiar o comando que digitei (em vez de usar o mouse). No entanto, consegui muitos C's. Mais tarde, percebi que Shift+ UPfaz A
, Shift+ DOWNfaz B
e Shift+ RIGHTtambém faz D
.
Por que isso acontece?
Acho que é dos dados brutos de pressionamento de tecla ( ^[[A
, ^[[B
, ^[[C
e ^[[D
), mas é apenas uma letra maiúscula (não ^[[
no início).
Este é um protocolo de entrada de teclado que remonta à década de 1980, e seu shell, não seu "driver de terminal" (seja lá o que for) como na resposta de M. Vazquez-Abrams, não está lidando com ele corretamente. Além disso, é uma sequência de controle perfeitamente válida.
Fundo
Os terminais emitem sequências de controle para teclas de função e teclas estendidas. Eles podem emitir sequências de controle DECFNK, que são sequências de controle introduzidas por CSI; Sequências de controle de teclas de função do Linux, que são um tipo diferente de sequência introduzida por CSI; Sequências de controle de tecla de função do console SCO, que são um terceiro tipo de sequência introduzida por CSI; caracteres únicos deslocados, prefixados com SS3; ou, como neste caso, sequências padrão ECMA-48 para várias coisas.
(SS3 e CSI são caracteres de controle, na faixa C1. Single Shift 3 e Control Sequence Introducer.)
Você tem dois teclados específicos em seu teclado (semelhante ao IBM Modelo M ou similar), um teclado de calculadora e um teclado de cursor. O modelo empregado pelos emuladores de terminal estilo DEC VT (que é a maioria dos emuladores de terminal que você provavelmente encontrará, desde aquele em seu kernel até o unicode-rxvt) é que ambos os teclados têm modos de aplicativo/normal selecionáveis separadamente. Um aplicativo TUI de tela inteira, algo que usa as bibliotecas libedit ou GNU readline (ou ZLE), como seu shell, e alguns outros tipos de aplicativos especificam qual modo eles desejam e, em seguida, ouvem as sequências de controle vindas do terminal lendo rajadas de caracteres (com base no fato de que um humano não pode digitar uma sequência de controle ECMA-48 completa em qualquer lugar tão rápido quanto um terminal ou um emulador de terminal envia sequências de controle,Escchave do emulador de terminal enviando uma sequência de controle começando com o caractere ␛).
Portanto, pode-se escolher entre o modo de aplicativo, onde não se pode saber quais modificadores estão pressionados, mas pode-se distinguir as duas teclas de seta para a esquerda, e o modo normal, onde não se pode distinguir entre duas teclas de seta, mas pode-se saber quais modificadores estão pressionados.
Em mais detalhes: Os aumentos de DEC para as sequências de controle ECMA-48 são que a sequência de controle tem dois parâmetros:
É assim que os terminais DEC VT têm feito as coisas desde os anos 80. Nos últimos anos, vários emuladores de terminal finalmente introduziram a mesma funcionalidade (embora, como mencionado, o XTerm tenha entendido errado).
O que está acontecendo.
O problema é que sua biblioteca GNU readline, libedit, ZLE e assim por diante não lidam com o protocolo adequadamente . Eles não são totalmente culpados. Eles contam com os sistemas termcap e terminfo, que simplesmente não estão à altura do trabalho aqui. termcap e terminfo realmente não têm a noção de uma sequência de controle de entrada que pode variar , muito menos teclados de modo múltiplo.
Para isso, você deve olhar para o Vim, que pode ser programado com substituições especiais para terminfo para especificar sequências de controle que seguem o protocolo acima (cf.
:help xterm-modifier-keys
Vim), ou NeoVIM, que usa libtermkey de Paul Evans e seu driver CSI . O driver CSI da libtermkey é como alguém deve lidar com a entrada do teclado adequadamente a partir de emuladores de terminal semelhantes ao DEC VT. É um analisador de máquina de estado ECMA-48 real que decodifica sequências de controle corretamente.Mas o que seu shell está fazendo é procurar entradas para as teclas de seta em terminfo e apenas corresponder a essas sequências de controle específicas .
Especificamente:
kcub1
capacidade de seu terminal em seu registro terminfo. Aqui está o do registroteken
, por exemplo:1
;
2
D
. Em vez disso, está usando as alternativas de 7 bits e enviando␛
[
1
;
2
D
, onde␛
[
é a maneira de codificar CSI em caracteres de 7 bits.Qual é o modo de falha depende exatamente de qual conjunto de sequências de entrada ele está tentando corresponder ao padrão, pois isso determina quantos caracteres ele engole antes de determinar que possui uma sequência sem correspondências possíveis. É claro que isso, por sua vez, depende do que o registro terminfo/termcap do seu terminal realmente contém e de qual tipo de terminal você disse ao seu shell que seu terminal é.
Conserta
A correção local para esse tipo de coisa é ser criativo com as combinações de teclas em seu shell. É por isso que, por exemplo, você encontrará pessoas fazendo esse tipo de coisa com o shell Z em seus
.zshrc
s:Infelizmente, não há correção não local. Isso envolveria a rearquitetura do tratamento de entrada do seu shell de forma bastante significativa. Tal rearquitetura está muito atrasada. (Testemunha NeoVIM.) Mas ninguém o abordou ainda.
Leitura adicional
DECFNK
. "Funções de controle ANSI". Informações do Programador de Terminal VT510 . EK-VT510-RM. Novembro de 1993. Digital.Pressionar Ctrl+ Vfará com que o próximo pressionamento de tecla seja inserido literalmente. Para Shift+ ↑isso resulta em "^[[1;2A". O driver do terminal consome o "^[[1;2" como uma sequência de escape inválida, deixando apenas o "A".