
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 .zshrc
e/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 ␛[A
ou ␛OA
dependendo se o terminal foi colocadotransmissão do tecladomodo ou não. As entradas smkx
e rmkx
terminfo podem ser usadas para colocar ou retirar um terminal desse modo.
A kcuu1
entrada 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/zshrc
arquivo 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 $key
matriz 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 $key
hash, você pode fazer:
bindkey $terminfo[kcuu1] history-beginning-search-backward
bindkey ${terminfo[kcuu1]/O/[} history-beginning-search-backward
Veja também:
- Minhas teclas de cursor não funcionam(FAQ sobre maldições)
- Por que não consigo usar as teclas do cursor no (qualquer) shell?(FAQ xterm)
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
,CUU
e 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
SS3
3 sequências de turno único.
- No modo normal, as teclas de seta enviam as sequências ECMA-48
-
⇐ Este é o teclado da calculadora.
-
- No modo normal, as teclas de seta enviam as sequências de controle ECMA-48
CUB
,CUF
,CUU
e, 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
SS3
3 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).
- No modo normal, as teclas de seta enviam as sequências de controle ECMA-48
A ␛
[
A
sequência que você disse ao ZLE para vincular a um widget é um alias ECMA-48 de 7 bits para a CSI
A
sequência de controle, que é a CUP
sequê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 bindkey
comandos 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 putty
tipo de terminal, às vezes a sequência do modo normal DEC VT, como registros terminfo parao rxvt
tipo de terminal, mas nunca a DECFNK
sequê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ájáe felizmente assumindo que seu terminal sempre será como um DEC VT com seu bindkey
comando 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 à CUP
sequê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 bindkey
comando adicional para cada CUP
sequê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 fish
shell, sofrem da mesma forma. (O fish
pessoal 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 (comparelibtermkey
que 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
- https://unix.stackexchange.com/a/444270/5132
- "Recursos do teclado". Informações do programador de terminal de vídeo VT510. EK-VT510-RM. Novembro de 1993. Digital.
- https://unix.stackexchange.com/a/289871/5132
- Jonathan de Boyne Pollard (14/05/2018).Alguns terminais precisam do modo teclado (smkx). bug da casca de peixe #2139.
- https://unix.stackexchange.com/a/419092/5132