Como vincular C- [de verdade?

10

C-[é equivalente à tecla de escape nos teclados em inglês dos EUA, portanto, qualquer tentativa de vinculá-la afetará o M-comportamento.

Emacs parece não ter revelador problemas <escape>e C-[para além de quadros GUI. O seguinte funciona bem e as ligações que começam com M-continuam funcionando:

(global-set-key (kbd "<escape>") (lambda () (interactive) (message "<escape>")))

No entanto, se eu ligar

(global-set-key (kbd "C-[") (lambda () (interactive) (message "C-[")))

de repente, o emacs enlouquece e vincula como uma M-xpausa. Além disso, pressionar C-[se recusa a acionar a lambda vinculada. Curiosamente, C-x @ c [(aplique o controle do modificador ao suporte) ainda diz C-[ is undefined.

Existe alguma maneira de vincular algo C-[sem quebrar o emacs?

Kristóf Marussy
fonte

Respostas:

7

Você não pode realmente alterar a C-[ligação nos mapas no nível do usuário, como faria com global-set-key. No entanto, você pode alterá-lo como um evento de teclado antes de atingir esses mapas de teclas. Você pode dizer, por exemplo:

(define-key input-decode-map 
    (kbd "C-[") 
    [control-bracketleft])

e depois use [control-bracketleft]nos seus mapas de teclas. Muito simples, não é?

Corte do Diretor

Infelizmente, não é tão simples, e essa solução requer alguns ajustes, que parecerão muito dolorosos. Voce foi avisado. Mas vamos ver primeiro por que os mapas no nível do usuário não podem responder à pergunta. A seguir, refiro-me ao manual do Emacs Lisp para o emacs 26.1 quando digo "ver algo" sem mais precisão.

C-[é interpretado muito cedo como o caractere de controle ASCII ESC(consulte 21.7.1 - Eventos do teclado ). Esse código está espalhado em todos os outros lugares como prefixo para seqüências mais longas. Há uma razão para isso: ESCé realmente o meta prefixo (consulte meta-prefix-char), e todas as ligações que lêem M-algo serão traduzidas para uma sequência que começa com ESC. Assim, alterar o mapa global não será suficiente: você precisa primeiro mudar e meta-prefix-char, em seguida, remapear ESCpara o seu novo meta-prefix-charem cada mapa usado M-antes de poder mapear com segurança C-[.

OK, é claro: vamos usar input-decode-map. Existem alguns mapas semelhantes que podemos ficar tentados a usar (consulte as seções 21.8.3 e 22.14), mas vamos nos ater a este. E bem ... isso funciona! Você terminou, não está?

Na verdade, não, a história não termina aqui. Isso funciona ... desde que você esteja usando um sistema de janelas. Se, devido à má sorte, você estiver preso no console do linux em um estado de emergência, você perceberá o quão dramática a situação se tornou: teclas de seta Homee M-, é claro , ligações, são tudo lixo. Por quê? Porque quando o terminal diz ESC(o que faz quando você digita C-[), realmente significa ESC e inicia uma sequência do mesmo tipo usada para transmitir caracteres não ASCII.

Observando o desastre, considere prudente proteger a input-decode-mapmodificação acima de forma que ela seja ativada apenas no caso de um sistema de janelas estar controlando o teclado:

(let ((frame (framep (selected-frame))))
  (or (eq  t  frame)
      (eq 'pc frame)

      (define-key input-decode-map 
                  (kbd "C-[") 
                  [control-bracketleft])
     )))

Os terminais então funcionam como costumavam.

Agora, podemos lidar com C-[terminais? Na verdade, sim, podemos, no console linux e nos outros emuladores de terminal com os quais posso brincar. Mas isso torna a história bastante longa, à medida que novos personagens entram em cena. Pois não há mais emacs por si só: o terminal tem agora o papel central.

Vamos dar uma olhada no que o console linux tem a dizer. Digite C-vantes de alguma tecla para ouvir claramente. C-[é ESC; assim é Esc. A seta para cima soa como ESC [ A, enquanto M-aé ESC A. Hmm ... Parece que essa meta-circunvolução no emacs não é? De qualquer forma.

A menos que nós estamos prontos para jogar alguns truques com base no tempo decorrido entre os eventos de caracteres (que por sinal não vai distinguir Esca partir C-[), parece que não tenho escolha a não ser dizer a consola o que realmente não significam ESCquando digitamos C-[. Além disso, parece que em breve esse C-[não é o único problema com os códigos dos terminais de estoque: os modificadores geralmente apagam as informações transmitidas. Precisamos personalizar o terminal pela mesma razão que personalizamos o emacs: seria muito mais prático se o fizermos.

Neste ponto, você deve se aprofundar nos olhos da documentação do seu terminal: páginas de manual loadkeys(1)do console linux, xterm xterm(1)na seção Custom Key Bindings e o que eu não sei sobre outros terminais. Em KDE konsole, você pode definir traduções personalizadas em Configurações / Editar perfil atual ... e depois em Teclado . Aqui está um trecho de ~/.local/share/konsole/Test.keytab depois de jogar com este último diálogo:

key [+Ctrl+AnyModifier : "\EO*["

Assim que tiver o envio de terminal ESC O 5 [para C-[(como na configuração acima), você pode voltar para emacs. Pois é claro, você ainda não terminou.

Para instruir o emacs qual dialeto usa um determinado terminal, você pode ajustar input-decode-map. Sim, é por sorte o que modificamos no início desta história, e é term/xterm.elexatamente o que toca quando o xterm está envolvido. Um bom local para o ajuste é tty-setup-hook(consulte a seção 40.1.3):

(add-hook 'tty-setup-hook 
   (lambda ()
    (let ((term (getenv "TERM")))
      (cond 
        (;; xterm-function-map not in doc, but in term/xterm.el
         (boundp 'xterm-function-map) 
         (map-my-term-codes xterm-function-map))

        ((equal term "linux")
         (map-my-term-codes input-decode-map))
        )
      )))

Esteja ciente de que este gancho só funciona se você estiver em um terminal. Portanto, você não pode inserir aqui o código para a inicialização do sistema de janelas. Aqui está a função de tradução por si só:

(defun map-my-term-codes (map)
      (define-key map (kbd "M-O 5 [") 
                      [control-bracketleft])
      )

E então você pode descansar um pouco: é o fim da jornada. Claro, se você não se importa com terminais, é rápido, pois você pulará toda a parte dolorosa. Mas você admitirá que também é bastante incompleto.

Duas notas finais:

  • Eu escolho ESC O 5 [codificar C-[. Este é apenas um exemplo: não vou fingir que é uma boa escolha. Apenas a 5 parte, o que significa C-, parece obedecer a algum tipo de convenção estabelecida

  • configurar o console linux deixa um gosto ruim: não parece possível fazer a ligação sem usar um símbolo existente intermediário , e aqueles que eu precisaria não existem . Eu uso símbolos no intervalo F21- F246como na maioria dos exemplos da Internet, mas não é muito satisfatório. Não há problema em algumas ligações não relacionadas, mas não servirá um esquema sistemático.

Editar

  • Concluí isso com o Esccaso - que tem personalidade própria - em outro post: Como remover ligações à chave de prefixo ESC
  • Aqui está um fragmento de uma configuração para alimentar loadkeys. Coloquei isso em /root/custom.kmap e carrego quando preciso (o que é raro). Minha configuração atual também mapeia setas e diferentes combinações de modificador, mas é bastante longo, a escolha de símbolos e seqüências é questionável, e não tenho certeza de que os códigos de teclas do meu teclado correspondam aos seus. Então, vamos mantê-lo no seu devido nível: isso não passa de uma ilustração.

    keymaps 0-127
    
    # http://tldp.org/HOWTO/Keyboard-and-Console-HOWTO-15.html
    # web+man:keymaps
    # web+man:loadkeys
    
    # escape
    keycode  1  = F100
        alt keycode  1 = Escape # keep the Escape behavior somewhere          
    
    # keycode  26 = bracketleft
        control keycode 26 = F115 # Control_bracketleft does not exist          
    
    string F100     = "\033OO" # map this to [escape] in map-my-term-codes
    string F115     = "\033O5["
    
Champignac
fonte
11
Obrigado, é uma ótima resposta. Mas, certamente, mesmo uma ótima resposta como essa certamente não precisa ser levada ao topo da página 34 vezes. Cada aumento tem um pequeno custo que é compartilhado pela comunidade: verificação de spam, verificação de novos conteúdos interessantes etc. Talvez você possa agrupar pequenas melhorias? Ou apenas fique com o que você tem. Falando por experiência própria, não existe uma postagem perfeita; em algum momento, você apenas precisa seguir em frente.
Gilles 'SO- stop be evil'
@ Gilles Entendi, e desculpe por isso. Eu não sabia que havia algum problema ao ajustar isso conforme desejado.
Champignac
0

A solução a seguir é um pouco confusa, mas parece funcionar:

Vamos ~/.xbindkeysrcconter o seguinte:

"xvkbd -xsendevent -text '\[Control_L]\[F13]'"
  m:0x14 + c:34

"xvkbd -xsendevent -text '\[Control_L]\[F14]'"
  m:0x14 + c:35

Agora xbindkeysserá traduzido C-[para C-<f13>e C-]para C-<f14>, para que possam ser vinculados livremente no emacs. Você provavelmente desejará vincular-se abort-recursive-edita algo diferente de C-], por exemplo C-S-g,.

A desvantagem é que agora C-[está quebrado em todos os aplicativos, exceto no Emacs, que podem ser corrigidos adicionando alguma lógica para testar se a combinação de teclas está sendo enviada ao emacs ...

Kristóf Marussy
fonte
FWIW, acho que não há nada de especial C-].
Malabarba
Sim, eu também não, mas por algum motivo estranho minha C-]ligação parou de funcionar depois que eu iniciei o Xbindkeys, então eu recuperei essa também.
Kristóf Marussy