Problemas con las combinaciones de teclas cuando se usa la terminal

30

Tengo la siguiente línea en init.el:

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

Funciona muy bien en la ventana de la GUI, pero si emacsse invoca con la -nwopción C-;, no comenta región, solo inserta ;caracteres. M-x comment-region RETfunciona bien sin embargo.

Intenté seguir esta respuesta en un problema similar, pero C-q C-;regresa solo ;y obviamente no quiero vincularme ;.

¿Cómo lograr el efecto deseado?

WeSenseASoulInSearchOfAnswers
fuente
44
Es posible que su terminal (¿qué está usando, por cierto?) No reconozca esa secuencia de comandos. Intente usar el C-;combo y luego use M-x view-lossagepara ver si llega incluso a Emacs.
Dan
Estoy usando gnome-terminal, y M-x view-lossagedevuelve:ESC [ > 1 ; 2 8 0 2 ; 0 c ; ESC x v i e w - l o s s a g e RET
WeSenseASoulInSearchOfAnswers
3
Parece un problema de terminal: si esa combinación de teclas llegara a Emacs, se vería C-;más bien que c ;(o, al menos, obtengo C-;).
Dan
@Dan: ¿Podrías poner eso como respuesta? Eso marcaría la pregunta como respondida y facilitaría ver la solución, lo cual es bueno para otras personas que tienen el mismo problema. ¡Gracias!
Tikhon Jelvis
Resumido y publicado con un enlace adicional para más lectura. También edito el título de la pregunta para hacerlo un poco más general.
Dan

Respuestas:

17

Primero, el problema más general: los emuladores de terminal a menudo están limitados en las secuencias de control y escape que pueden enviar. Entonces: puede ser que el terminal se trague tus caracteres especiales antes de que lleguen a Emacs. Como diagnóstico general, puede presionar C-h l(o M-x view-lossage) para ver si sus combinaciones de teclas se convierten en Emacs.

Para una mayor discusión sobre este problema, eche un vistazo a este hilo de desbordamiento de pila y los enlaces que contiene.

Para resumir el ir y venir en los comentarios, su problema específico sugiere que es el terminal en lugar de Emacs el problema. Cuando lo intentaste C-;y luego M-x view-lossage, lo conseguiste blah blah blah c ; ESC v i e w - l o s s a g e RET. Parece un problema de terminal: si la combinación de teclas llegara a Emacs, la c ;parte se vería así C-;.

Dan
fuente
33

En Shift + Up no es reconocido por Emacs en un terminal , explico cómo los terminales traducen la mayoría de las teclas de función en secuencias de escape, porque la interfaz entre aplicaciones y terminales transmite caracteres (o más bien bytes), no teclas. Solo unas pocas combinaciones de modificador + personaje tienen su propio personaje:

  • Ctrlmás una letra o una de las @[\]^_vueltas en bytes 0–31 (caracteres de control ASCII ).
  • A menudo, Ctrl+ se ?convierte en el byte 127 y Ctrl+ Spacees equivalente a Ctrl+ @(byte 0).
  • Algunas teclas de función son equivalentes a los caracteres de control: Tab= Ctrl+ I, Return= Ctrl+ M, Esc= Ctrl+ [.
  • Y Backspace= Ctrl+ Ho Ctrl+ ?dependiendo de la configuración. Ctrl+ ?es más conveniente para Emacs, ya que Ctrl+ Hes ayuda.
  • Meta+ characterse envía como Escseguido por el carácter .

Entonces, ¿qué pasa con otras combinaciones como Ctrl+ ;o Ctrl+ Shift+ letter? Como no hay un carácter correspondiente, el terminal debe reutilizar un carácter o enviar una secuencia de escape. Muchos terminales ignoran los modificadores cuando no hay un carácter correspondiente, por lo que terminas con Ctrl+ ;envío ;, Ctrl+ Shift+ letterequivalente a Ctrl+ letter, etc.

Los vendedores de terminales siguieron haciendo lo simple durante mucho tiempo. No había un estándar para las secuencias de escape, que se perpetuaba a sí mismo: los vendedores de terminales no lo implementan, las aplicaciones no lo admiten, los usuarios no lo esperan. Algunos emuladores de terminal pueden configurarse para enviar secuencias de escape arbitrarias, por lo que si el suyo puede, puede configurarlo y declarar las secuencias de escape a Emacs (más sobre esto más adelante).

Últimamente, la situación está cambiando, porque ha habido dos propuestas para estandarizar las secuencias de escape. Una es la libtermkey de LeoNerd con la sintaxis . Otro es el xterm de Thomas Dickey con la sintaxis . Las versiones actuales de xterm (≥216) se pueden configurar para cualquier sintaxis configurando el recurso; la función debe activarse configurando un valor distinto de cero.ESC [ codepoint ; modifier uESC [ 2 7 ; modifier ; codepoint ~formatOtherKeysmodifyOtherKeys

Si su emulador de terminal no admite estas sintaxis, pero puede configurarse, elija cualquiera.

Desde Emacs 24.4, Emacs activa automáticamente la modifyOtherKeysfunción cuando detecta que el terminal es xterm versión ≥216. La detección de secuencias de escape de Emacs para codificar claves funciona a través de la variable local-function-key-map. A partir de Emacs 24.4, no todas las secuencias de escape son compatibles. Puede usar el siguiente código en su archivo init para completar el trabajo.

;; 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))

Si la TERMvariable de entorno no está establecida en xtermuna variante como xterm-256color, Emacs no activará esas secuencias. Si Emacs ya tiene soporte para su valor de TERM, puede agregar soporte definiendo una función similar a la anterior, que se ejecutará después de cargar el archivo Lisp cuyo nombre es el valor deTERM . Si Emacs no tiene dicho soporte, puede agregarlo creando un subdirectorio llamado termen algún lugar de su load-path, y creando un archivo Lisp llamado term/$TERM.eldonde $TERMestá el valor de TERM, definiendo una función llamada terminal-init-$TERM.

Mientras escribo, parece que pocos emuladores de terminal distintos de xterm han adoptado estas secuencias de escape. En OSX, puede configurar iTerm2 seleccionando una secuencia de escape para cada combinación de teclas, una por una.

Gilles 'SO- deja de ser malvado'
fuente
2
Tus respuestas sobre este tema son siempre excelentes, Gilles. Muy apreciado.
phils
¡Excelente!. Aunque me cuesta bastante encontrar cómo hacer que urxvt envíe esas secuencias. ¿Podrías echarme una mano? :)
Amós
@Amos No uso rxvt. Debe preguntar en Unix y Linux cómo hacer que urxvt envíe las mismas secuencias de escape que xterm con modifyOtherKeys.
Gilles 'SO- deja de ser malvado'
no funciona en macOS xterm-256color. M-C-%ser reconocido aESC 5
LoranceChen
@LoranceChen Ese es el comportamiento esperado si la modifyOtherKeysfunción no está activa. Tenga en cuenta que solo se admite en versiones recientes de xterm, y solo se activa automáticamente desde Emacs 24.4. No sé si OSX se envía con versiones recientes. Si no funciona y no funciona para usted, le sugiero que haga una nueva pregunta. Mencione las versiones que está utilizando.
Gilles 'SO- deja de ser malvado'
2

La respuesta de Gilles dijo: On OSX, you can configure iTerm2 by selecting an escape sequence for each key combination, one by one. Tuve un pequeño problema para llegar allí, así que aquí una explicación detallada en caso de que seas como yo, confundido.

Si, al ejecutar Emacs en un terminal (p. Ej., El Terminal.app predeterminado de Mac) C-x C-;no se ejecuta comment-line, y desea esa funcionalidad, debe cambiar a iTerm2 (Terminal.app no ​​tiene la capacidad) y crear una asignación de teclas bajo Perfiles ... Claves de la siguiente manera:

^;     ^[[59;5u

Esto se logra haciendo clic en el +botón, que abre una pequeña ventana llamada "Atajo de teclado"; esta ventana tiene inicialmente dos campos; la parte superior tiene un valor de "Haga clic para establecer" y la parte inferior tiene un valor de "Ignorar". Haga clic en el botón superior y escriba C-;. Esto establece la combinación de teclas que ejecutará la acción y el código. Haga clic en el campo inferior, "Acción", y busque y haga clic en "Enviar secuencia de escape", que se encuentra un poco más de la mitad. Después de hacer clic en eso, aparecerá un tercer campo, llamado "Esc +". Dentro de este campo, escriba:

[59;5u

El 59es el código ASCII decimal de la coma, y ​​el 5es el código para Ctrl. Luego presione "OK" para terminar. El combo de teclas correcto para la secuencia de teclas ahora se incluirá en las preferencias de iTerm2. Cuando inicie Emacs en iTerm, ahora tendrá acceso a la C-x C-;funcionalidad.

Piña
fuente