Problemas com atalhos de teclas ao usar o terminal

30

Eu tenho a seguinte linha em init.el:

(global-set-key [(control \;)] 'comment-region)

Funciona muito bem na janela da GUI, mas se emacsfor chamado com a -nwopção, C-;não comenta a região, apenas insere o ;caractere. M-x comment-region RETfunciona bem no entanto.

Tentei seguir esta resposta em um problema semelhante, mas C-q C-;retorna apenas ;e obviamente não quero vincular-me ;.

Como alcançar o efeito desejado?

WeSenseASoulInSearchOfAnswers
fonte
4
É possível que o seu terminal (o que você está usando, a propósito?) Não reconheça essa sequência de comandos. Tente usar o C-;combo e use M-x view-lossagepara ver se ele está chegando ao Emacs.
Dan
Estou usando gnome-terminale M-x view-lossageretorna:ESC [ > 1 ; 2 8 0 2 ; 0 c ; ESC x v i e w - l o s s a g e RET
WeSenseASoulInSearchOfAnswers 10/10
3
Parece um problema terminal: se essa combinação de teclas chegasse ao Emacs, pareceria C-;mais do que c ;(ou, pelo menos, eu entendo C-;).
Dan
@ Dan: Você poderia colocar isso como uma resposta? Isso marcaria a pergunta como respondida e tornaria mais fácil a solução, o que é bom para outras pessoas com o mesmo problema. Obrigado!
Tikhon Jelvis 10/10
Resumido e publicado com um link adicional para mais leitura. Também edite o título da pergunta para torná-la um pouco mais geral.
Dan

Respostas:

17

Primeiro, a questão mais geral: os emuladores de terminal geralmente são limitados nas seqüências de controle e escape que podem enviar. Portanto: pode ser que o terminal engula seus caracteres especiais antes que eles cheguem ao Emacs. Como diagnóstico geral, você pode pressionar C-h l(ou M-x view-lossage) para ver se suas combinações de teclas fazem parte do Emacs.

Para mais discussões sobre esse problema, consulte este thread do Stack Overflow e os links nele.

Para resumir as idas e vindas dos comentários, seu problema específico sugere que é o terminal, e não o Emacs, que é o problema. Quando você tentou C-;e depois M-x view-lossageconseguiu blah blah blah c ; ESC v i e w - l o s s a g e RET. Isso parece um problema terminal: se a combinação de teclas chegasse ao Emacs, a c ;parte seria parecida C-;.

Dan
fonte
33

No Shift + Up não é reconhecido pelo Emacs em um terminal , explico como os terminais convertem a maioria das teclas de função em seqüências de escape, porque a interface entre aplicativos e terminais transmite caracteres (ou melhor, bytes), não chaves. Apenas algumas combinações de modificador + caractere têm seu próprio caractere:

  • Ctrlalém de uma letra ou uma das @[\]^_transformações em bytes de 0 a 31 (caracteres de controle ASCII ).
  • Freqüentemente Ctrl+ se ?transforma em byte 127 e Ctrl+ Spaceé equivalente a Ctrl+ @(byte 0).
  • Algumas teclas de função são equivalentes aos caracteres de controle: Tab= Ctrl+ I, Return= Ctrl+ M, Esc= Ctrl+ [.
  • E Backspace= Ctrl+ Hou Ctrl+, ?dependendo da configuração. Ctrl+ ?é mais conveniente para o Emacs, pois Ctrl+ Hé ajuda.
  • Meta+ characteré enviado conforme Escseguido pelo caractere .

Então, e outras combinações como Ctrl+ ;ou Ctrl+ Shift+ letter? Como não há caractere correspondente, o terminal precisa reutilizar um caractere ou enviar uma sequência de escape. Muitos terminais ignoram modificadores quando não há caracteres correspondentes, então você acaba com Ctrl+ ;envio ;, Ctrl+ Shift+ letterequivalente a Ctrl+ letter, etc.

Os fornecedores de terminais continuaram fazendo a coisa simples por um longo tempo. Não havia um padrão para seqüências de escape, que se perpetuavam - os fornecedores de terminais não o implementam, os aplicativos não o suportam, os usuários não esperam. Alguns emuladores de terminal podem ser configurados para enviar seqüências de escape arbitrárias; portanto, se o seu puder, você pode configurá-lo e declarar as seqüências de escape para o Emacs (mais sobre isso mais adiante).

Ultimamente, a situação está mudando, porque houve duas propostas para padronizar as seqüências de escape. Um deles é a libtermkey do LeoNerd, com a sintaxe . Outro é o xterm de Thomas Dickey com a sintaxe . As versões atuais do xterm (≥216) podem ser configuradas para qualquer uma das sintaxes, definindo o recurso; o recurso deve ser ativado definindo-o como um valor diferente de zero.ESC [ codepoint ; modifier uESC [ 2 7 ; modifier ; codepoint ~formatOtherKeysmodifyOtherKeys

Se o seu emulador de terminal não suportar essas sintaxes, mas puder ser configurado, escolha um dos dois.

Desde o Emacs 24.4, o Emacs ativa automaticamente o modifyOtherKeysrecurso quando detecta que o terminal é da versão xterm ≥216. Detecção de Emacs de seqüências de escape para as chaves codificar funciona através da variável local-function-key-map. No Emacs 24.4, nem todas as seqüências de escape são suportadas. Você pode usar o seguinte código no seu arquivo init para concluir o trabalho.

;; xterm with the resource ?.VT100.modifyOtherKeys: 1
;; GNU Emacs >=24.4 sets xterm in this mode and define
;; some of the escape sequences but not all of them.
(defun character-apply-modifiers (c &rest modifiers)
  "Apply modifiers to the character C.
MODIFIERS must be a list of symbols amongst (meta control shift).
Return an event vector."
  (if (memq 'control modifiers) (setq c (if (or (and (<= ?@ c) (<= c ?_))
                                                (and (<= ?a c) (<= c ?z)))
                                            (logand c ?\x1f)
                                          (logior (lsh 1 26) c))))
  (if (memq 'meta modifiers) (setq c (logior (lsh 1 27) c)))
  (if (memq 'shift modifiers) (setq c (logior (lsh 1 25) c)))
  (vector c))
(defun my-eval-after-load-xterm ()
  (when (and (boundp 'xterm-extra-capabilities) (boundp 'xterm-function-map))
    (let ((c 32))
      (while (<= c 126)
        (mapc (lambda (x)
                (define-key xterm-function-map (format (car x) c)
                  (apply 'character-apply-modifiers c (cdr x))))
              '(;; with ?.VT100.formatOtherKeys: 0
                ("\e\[27;3;%d~" meta)
                ("\e\[27;5;%d~" control)
                ("\e\[27;6;%d~" control shift)
                ("\e\[27;7;%d~" control meta)
                ("\e\[27;8;%d~" control meta shift)
                ;; with ?.VT100.formatOtherKeys: 1
                ("\e\[%d;3u" meta)
                ("\e\[%d;5u" control)
                ("\e\[%d;6u" control shift)
                ("\e\[%d;7u" control meta)
                ("\e\[%d;8u" control meta shift)))
        (setq c (1+ c))))))
(eval-after-load "xterm" '(my-eval-after-load-xterm))

Se a TERMvariável de ambiente não estiver definida como xtermou uma variante como xterm-256color, o Emacs não ativará essas seqüências. Se o Emacs já tiver suporte para o seu valor de TERM, você poderá adicionar suporte definindo uma função semelhante à acima, a ser executada após carregar o arquivo Lisp cujo nome é o valor deTERM . Se o Emacs não tiver esse suporte, você poderá adicioná-lo criando um subdiretório chamado termem algum lugar no seu load-pathe criando um arquivo Lisp chamado term/$TERM.elwhere $TERMé o valor de TERM, definindo uma função chamada terminal-init-$TERM.

Enquanto escrevo, parece que poucos emuladores de terminal, exceto o xterm, adotaram essas seqüências de escape. No OSX, você pode configurar o iTerm2 selecionando uma sequência de escape para cada combinação de teclas, uma por uma.

Gilles 'SO- parar de ser mau'
fonte
2
Suas respostas sobre esse assunto são sempre excelentes, Gilles. Muito apreciado.
Phillip #
Ótimo!. Embora eu tenha dificuldade em encontrar como fazer o urxvt enviar essas seqüências. Você poderia me dar uma mão :)
Amos
@ Amos eu não uso rxvt. Você deve perguntar no Unix e Linux como fazer o urxvt enviar as mesmas seqüências de escape que o xterm com modifyOtherKeys.
Gilles 'SO- stop be evil'
não funciona no macOS xterm-256color. M-C-%ser reconhecido comoESC 5
LoranceChen
@LoranceChen Esse é o comportamento esperado se o modifyOtherKeysrecurso não estiver ativo. Observe que ele é suportado apenas nas versões recentes o suficiente do xterm e só é ativado automaticamente desde o Emacs 24.4. Não sei se o OSX vem com versões recentes. Se não funcionar e não estiver funcionando para você, sugiro que faça uma nova pergunta. Mencione as versões que você está usando.
Gilles 'SO- stop be evil'
2

A resposta de Gilles afirmou: On OSX, you can configure iTerm2 by selecting an escape sequence for each key combination, one by one. Eu tive um pequeno problema para chegar lá, então aqui está uma explicação detalhada, caso você seja como eu, confusa.

Se, ao executar o Emacs em um terminal (por exemplo, Terminal.app padrão do Mac), C-x C-;não executar comment-line, e você desejar essa funcionalidade, deverá mudar para o iTerm2 (o Terminal.app não tem capacidade) e criar um Mapeamento de Chaves em Perfis ... Teclas da seguinte maneira:

^;     ^[[59;5u

Isso é feito clicando no +botão, que abre uma pequena janela chamada "Atalho do teclado"; esta janela possui inicialmente dois campos; a parte superior possui o valor "Clique para definir" e a parte inferior possui o valor "Ignorar". Clique no botão superior e digite C-;. Isso define a combinação de teclas que executará a ação e o código. Clique no campo inferior, "Ação", localize e clique em "Enviar sequência de escape", que está um pouco abaixo da metade. Depois que você clicar nele, um terceiro campo aparecerá, chamado "Esc +". Dentro deste campo, digite:

[59;5u

O 59código ASCII decimal da vírgula e 5o código para Ctrl. Então pressione "OK" para finalizar. A combinação correta de teclas para a sequência de teclas agora será incluída nas preferências do iTerm2. Ao iniciar o Emacs no iTerm, você terá acesso à C-x C-;funcionalidade.

Pinha
fonte