¿Cómo unir C- [de verdad?

10

C-[es equivalente a la tecla de escape en los teclados de inglés de EE. UU., por lo tanto, cualquier intento de vincularlo dañará el M-comportamiento.

Emacs parece no tener problemas <escape>para C-[distinguir y aparte en los marcos de la GUI. Lo siguiente funciona bien y los enlaces que comienzan con M-siguen funcionando:

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

Sin embargo, si me ato

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

De repente, Emacs se vuelve loco y se une como un M-xdescanso Además, al presionar se C-[niega a activar el lambda encuadernado. Curiosamente, C-x @ c [(aplicar el control del modificador para abrir el paréntesis) todavía dice C-[ is undefined.

¿Hay alguna forma de vincular algo C-[sin romper emacs?

Kristóf Marussy
fuente

Respuestas:

7

Realmente no puede cambiar el C-[enlace en los mapas a nivel de usuario, como lo haría con global-set-key. Sin embargo, puede cambiarlo como un evento de teclado antes de que llegue a esos mapas de teclas. Puedes decir por ejemplo:

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

y luego usar [control-bracketleft]en tus mapas de teclas. Bastante simple, ¿no?

Edición del director

Desafortunadamente, no es tan simple, y esta solución requiere algunos ajustes, que parecerán muy dolorosos. Has sido advertido. Pero veamos primero por qué los mapas a nivel de usuario no pueden responder la pregunta. A continuación, me refiero al manual de Emacs Lisp para emacs 26.1 cuando digo "ver algo" sin más precisión.

C-[se interpreta en una etapa muy temprana como el carácter de control ASCII ESC(ver 21.7.1 - Eventos de teclado ). Este código se extiende al resto del lugar como prefijo para secuencias más largas. Hay una razón para eso: en ESCrealidad es el prefijo meta (ver meta-prefix-char), y todos los enlaces que leen M-algo se traducirán en una secuencia que comienza con ESC. Por lo tanto, cambiar el mapa global no será suficiente: primero debe cambiar meta-prefix-char, luego reasignar ESCa su nuevo meta-prefix-charmapa en todos y cada uno de los mapas que utiliza M-antes de poder mapear con seguridad C-[.

OK entonces, por supuesto: usemos input-decode-map. Hay un par de mapas similares que podríamos sentir la tentación de usar (ver secciones 21.8.3 y 22.14), pero sigamos con este. Y bueno ... esto funciona! Ya terminaste, ¿no?

En realidad, no, la historia no termina aquí. Esto funciona ... siempre que esté utilizando un sistema de ventanas. Si, debido a la mala suerte, te encarcelan en la consola de Linux en un estado de emergencia, te das cuenta de cuán dramática se ha vuelto la situación: las teclas de flecha Homey, por supuesto M-, los enlaces, son basura. ¿Por qué? Porque cuando el terminal dice ESC(lo que hace cuando escribe C-[), realmente significa ESC , y comienza una secuencia del mismo tipo que usa para transmitir caracteres no ASCII.

Al observar el desastre, puede considerar prudente proteger la input-decode-mapmodificación anterior de tal manera que se active solo en el caso de que un sistema de ventanas controle el teclado:

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

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

Las terminales entonces funcionan como solían hacerlo.

Ahora, ¿podemos tratar con C-[terminales? En realidad, sí podemos, tanto en la consola de Linux como en los otros emuladores de terminal con los que puedo jugar. Pero eso hace que la historia sea bastante larga, ya que nuevos personajes entran en escena. Porque ya no es solo emacs: el terminal tiene ahora el papel central.

Vamos a escuchar lo que la consola de Linux tiene que decir. Escriba C-vantes de alguna tecla para escucharla sin formato. C-[es ESC; también lo es Esc. La flecha hacia arriba suena como ESC [ A, mientras M-aes ESC A. Hmm ... Parece que esta circunvolución de tecla meta en emacs no es así? De todas formas.

A menos que esté listo para jugar algunos trucos en función del tiempo transcurrido entre los acontecimientos de carácter (que por cierto no se distinguirá Escde C-[), parece que tenemos más remedio que decir la consola de lo que en realidad no me refiero ESCcuando escribimos C-[. Además, parece que muy pronto ese C-[no es el único problema con los códigos de terminales de stock: la mayoría de las veces los modificadores borran la información transmitida. Necesitamos personalizar el terminal por la misma razón que personalizamos emacs: sería mucho más práctico si lo hiciéramos.

En este punto, se atreverá a mirar a fondo los ojos de la documentación de su terminal: páginas loadkeys(1)de manual para la consola de Linux, para xterm xterm(1)en la sección Vinculaciones de teclas personalizadas , y lo que no sé para otros terminales. En KDE konsole, puede definir traducciones personalizadas en Configuración / Editar perfil actual ... luego Teclado . Aquí hay un extracto de ~/.local/share/konsole/Test.keytab después de jugar con este último diálogo:

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

Una vez que haya enviado el terminal ESC O 5 [para C-[(como en la configuración anterior), puede volver a emacs. Por supuesto, aún no has terminado.

Para indicar a emacs qué dialecto usa un terminal determinado, puede ajustarlo input-decode-map. Sí, este es fortuitamente el que hemos modificado al comienzo de esta historia, y este es el que term/xterm.eltoca cuando se trata de xterm. Un buen lugar para el ajuste es tty-setup-hook(ver sección 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))
        )
      )))

Tenga en cuenta que este gancho solo se ejecuta si está en una terminal. Por lo tanto, no puede insertar aquí el código para la inicialización del sistema de ventanas. Aquí está la función de traducción por sí misma:

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

Y luego puedes descansar un poco: es el final del viaje. Por supuesto, si no te interesan las terminales, es rápido, ya que te saltearás toda la parte dolorosa. Pero admitirás que también es bastante incompleto.

Dos notas finales:

  • Elijo ESC O 5 [codificar C-[. Este es solo un ejemplo: no voy a fingir que es una buena opción. Solo la 5 parte, lo que significa C-, parece obedecer algún tipo de convención establecida

  • configurar la consola de Linux deja un mal gusto: no parece posible hacer el enlace sin usar un símbolo intermedio existente , y los que necesitaría no existen . Utilizo símbolos en el rango F21- F246como en la mayoría de los ejemplos de Internet, pero no es muy satisfactorio. Está bien para algunos enlaces no relacionados, pero no servirá un esquema sistemático.

Editar

  • He completado esto con el Esccaso, que tiene su propia personalidad, en otra publicación: Cómo eliminar enlaces a la tecla de prefijo ESC
  • Aquí hay un fragmento de una configuración para alimentar loadkeys. Puse esto en /root/custom.kmap, y lo cargué cuando lo necesito (lo cual es raro). Mi configuración real también asigna flechas y diferentes combinaciones de modificadores, pero es bastante larga, la elección de símbolos y secuencias es cuestionable, y no estoy seguro de que los códigos de teclas de mi teclado coincidan con los suyos. Así que vamos a mantenerlo a su debido nivel: esto no es más que una ilustración.

    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
fuente
1
Gracias, esa es una gran respuesta. Pero seguramente incluso una gran respuesta como esta seguramente no necesita ser lanzada a la parte superior de la página principal 34 veces. Cada bache tiene un pequeño costo que es compartido por la comunidad: verificar si hay spam, buscar si hay contenido nuevo e interesante, etc. ¿Quizás podría agrupar mejoras menores? O simplemente quédate con lo que tienes. Hablando por experiencia, no existe la publicación perfecta, en algún momento solo tienes que seguir adelante.
Gilles 'SO- deja de ser malvado'
@Gilles Lo tengo, y perdón por eso. No sabía que había algún problema para ajustar esto a voluntad.
Champignac
0

La siguiente solución es un poco torpe, pero parece funcionar:

Dejar ~/.xbindkeysrccontener lo siguiente:

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

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

Ahora xbindkeysse traducirá C-[a C-<f13>y C-]a C-<f14>, por lo que se pueden unir en emacs libremente. Probablemente querrás unirte abort-recursive-edita algo que no sea C-], por ejemplo C-S-g,.

La desventaja es que ahora C-[se rompe en todas las aplicaciones, excepto en Emacs, que podría solucionarse agregando algo de lógica para probar si la combinación de teclas se envía a emacs ...

Kristóf Marussy
fuente
FWIW, no creo que haya nada de especial C-].
Malabarba
Sí, yo tampoco, pero por alguna extraña razón, mi C-]encuadernación dejó de funcionar después de encender Xbindkeys, así que también recuperé esa.
Kristóf Marussy