As teclas do cursor são divertidas.

As teclas do cursor são divertidas.

Eu uso o shell zsh como shell padrão no Ubuntu e no Arch.

Configurei um atalho (seta para cima) para preencher automaticamente o histórico em meu shell zsh, usando a seguinte linha em meu .zshrc:

bindkey "^[[A" history-beginning-search-backward

No entanto, quando eu forneço .zshrce/ou reinicio no Ubuntu, o atalho não funciona (eu só recebo o comando anterior, não importa o que comecei a digitar), enquanto no Arch funciona bem (eu só recebo o último comando começando com o que Eu digitei).

Alguém sabe como resolver isso?

Responder1

Na maioria dos terminais do tipo xterm, o Up(e é semelhante para a maioria das teclas de navegação) envia ␛[Aou ␛OAdependendo se o terminal foi colocadotransmissão do tecladomodo ou não. As entradas smkxe rmkxterminfo podem ser usadas para colocar ou retirar um terminal desse modo.

A kcuu1entrada terminfo (cursor para cima em 1) descreve a sequência enviada Upquando emtransmissão do tecladomodo, isto é ␛OA.

O Debian e derivados possuem um /etc/zsh/zshrcarquivo que faz uma

function zle-line-init () {
   emulate -L zsh
   printf > /dev/tty '%s' ${terminfo[smkx]}
}

O que coloca o terminal nesse modo quando zle está ativo, o que significa que agora você pode confiar no banco de dados terminfo para saber quais sequências de caracteres as chaves transmitem.

O arquivo tambémdefine uma $keymatriz associativacom base nas entradas terminfo para ajudá-lo a mapeá-las para widgets. Então, nesses sistemas, você pode fazer:

(($+key[Up])) && bindkey $key[Up] history-beginning-search-backward

Para algo que funciona em sistemas onde o terminal estátransmissão do tecladomodo e aqueles que não possuem ou não possuem o $keyhash, você pode fazer:

bindkey $terminfo[kcuu1] history-beginning-search-backward
bindkey ${terminfo[kcuu1]/O/[} history-beginning-search-backward

Veja também:

Responder2

As teclas do cursor são divertidas.

Embora não sejam tão divertidos quanto editar teclas, que sãorealmentediversão.

Você temdois conjuntosde teclas de cursor em seu teclado, aquelas noteclado do cursore aqueles noteclado da calculadora.

A maioria dos emuladores de terminal tenta (às vezes muito mal) empregar o modelo de VTs DEC, onde cada conjunto de teclas é comutável individualmente entremodo de aplicaçãoemodo normalusando as configurações do modo privado DECCKM(modo do teclado do cursor) e DECNKM(modo do teclado numérico), respectivamente. A ideia do modo de aplicativo é essencialmente que as teclas do teclado relevante se transformem em teclas de função extras do aplicativo.

⇐ Este é o teclado do cursor.
  • No modo normal, as teclas de seta enviam as sequências ECMA-48 CUB, CUF, CUUe de controle, a menos que o modificador esteja em vigor, caso em que enviam sequências de controle.CUD⎇ AltDECFNK
  • No modo de aplicação, as teclas de seta enviam SS33 sequências de turno único.
⇐ Este é o teclado da calculadora.
  • No modo normal, as teclas de seta enviam as sequências de controle ECMA-48 CUB, CUF, CUUe, a menos que o modificador esteja em vigor, caso em que enviam sequências de controle, ou a menos que a combinação de bloqueio numérico e shift faça com que enviem dígitos.CUD⎇ AltDECFNK
  • No modo de aplicação, as teclas de seta enviamum conjunto diferente de SS33 sequências de turno único (a menos que, novamente, a combinação de bloqueio numérico e turno faça com que eles enviem dígitos).

A [ Asequência que você disse ao ZLE para vincular a um widget é um alias ECMA-48 de 7 bits para a CSI Asequência de controle, que é a CUPsequência de controle ("Cursor UP"). Essa sequência de controle só é gerada por VTs DEC e seus emuladores de terminal imitador quando um teclado está no modo normal e o ⎇ Altmodificador não está em vigor. Não corresponderá às sequências de mudança enviadas quando os teclados relevantes estiverem no modo de aplicação.

O banco de dados terminfo turva as águas e causa diversão extra aqui, porque não emprega esse modelo para E/S de terminal. Em vez disso, ele emprega seu própriodiferentemodelo que incorpora noções de teclas "locais" e "remotas", o que não é o que a comutação de aplicação/modo normal DEC VT realmente envolve; e possui um único mecanismo de comutação local/remoto, que acaba alternandoambosteclados entre os modos aplicativo/normal de forma indivisível.

terminfo é a maneira de não conectar a um tipo de terminal específico como você está configurando o ZLE, caso você se encontre com um terminal ou emulador de terminal que não imite um DEC VT. E o shell Z fornece maneiras de acessar as entradas de capacidade necessárias do registro do banco de dados. Portanto, você pode ler no terminfo quais sequências de controle o terminfo espera que as teclas do cursor para cima/para baixo/esquerda/direita produzam e emitir bindkeycomandos apropriados que mapeiam essas sequências de controle para widgets.

O problema é que terminfo é inadequado para este trabalho. Só tem como gravarumsequência de controle por tecla, enquanto como você pode ver as teclas podem enviarpelo menostrês sequências diferentes, dependendo do modo e dos modificadores pressionados. (Os modificadores podem influenciar as sequências de controle enviadas de forma bastante significativa no modelo DEC VT.) Portanto, você precisa mudar o terminal para o modo que gera o que terminfo diz para você esperar.

Mas fica pior: terminfo não é consistente. A sequência de controle única às vezes é a sequência do modo de aplicação DEC VT, como registros terminfo parao puttytipo de terminal, às vezes a sequência do modo normal DEC VT, como registros terminfo parao rxvttipo de terminal, mas nunca a DECFNKsequência. Portanto, você não tem como saber se deve mudar para o modo de aplicativo ou para o modo normal com qualquer terminal ou emulador de terminal. O que funcionará bem para um, dará errado para outro.

A outra abordagem, portanto, é ignorar terminfo e perceber que você estáe felizmente assumindo que seu terminal sempre será como um DEC VT com seu bindkeycomando original. Você só precisa de dois deles, para ter certeza de que, esteja seu terminal em modo aplicativo ou modo normal, a sequência de controle que ele envia será correspondida:

bindkey "^[OA" histórico-início-pesquisa-retroceder

No entanto, isso não funcionará com teclas modificadoras sendo pressionadas, o que adiciona parâmetros extras à CUPsequência de controle que faz com que a correspondência simplista de strings que o ZLE usa falhe quando tudo o que ele está procurando é simples e antigo sem parâmetros CUP. Você deve emitir manualmente um bindkeycomando adicional para cada CUPsequência de controle possível resultante de cada combinação possível de modificadores.

sequência 1 8 |
enquanto lê -ri
fazer
    bindkey "^[[1;${i}A" histórico-início-pesquisa-para trás
feito

ZLE não está sozinho aqui. Outros programas baseados em terminfo, como o fishshell, sofrem da mesma forma. (O fishpessoal do shell também descobriu que a escolha do modo aplicativo/normal que funciona corretamente para um emulador de terminal pode dar errado para outro.) Reestruturando isso (comparelibtermkeyque possui um analisador de sequência de controle ECMA-48 real para entrada) nesses programas está muito atrasado. Mas ninguém abordou isso ainda.

Leitura adicional

informação relacionada