Anular globalmente el enlace de claves en Emacs


100

¿Cómo puedo establecer un enlace de clave que anule globalmente y tenga prioridad sobre todos los demás enlaces para esa clave? Quiero anular todos los mapas de modo mayor / menor y asegurarme de que mi enlace esté siempre en efecto.

Esto, por supuesto, no funciona:

(global-set-key "\C-i" 'some-function)

Funciona text-mode, pero cuando lo uso lisp-mode, C-ise recupera lisp-indent-line.

Puedo revisar y anular este enlace en lisp-modey en cualquier otro modo individualmente, pero debe haber una manera más fácil. Cada vez que instalo un nuevo modo para un nuevo tipo de archivo, tengo que volver atrás y comprobar para asegurarme de que el nuevo modo no anula todas mis combinaciones de teclas.

Quiero hacer esto porque quiero emular enlaces que ya aprendí y arraigé de otros editores.

Respuestas:


149

Utilizo un modo menor para todas mis combinaciones de teclas de "anulación":

(defvar my-keys-minor-mode-map
  (let ((map (make-sparse-keymap)))
    (define-key map (kbd "C-i") 'some-function)
    map)
  "my-keys-minor-mode keymap.")

(define-minor-mode my-keys-minor-mode
  "A minor mode so that my key settings override annoying major modes."
  :init-value t
  :lighter " my-keys")

(my-keys-minor-mode 1)

Esto tiene el beneficio adicional de poder desactivar todas mis modificaciones de una sola vez (solo deshabilite el modo menor) en caso de que alguien más esté manejando el teclado o si necesito ver qué hace una combinación de teclas predeterminada.

Tenga en cuenta que es posible que deba desactivar esto en el minibúfer:

(defun my-minibuffer-setup-hook ()
  (my-keys-minor-mode 0))

(add-hook 'minibuffer-setup-hook 'my-minibuffer-setup-hook)

1
Esto parece una buena idea. ¿Hay alguna forma de asegurarse de que su modo menor no pelee con otros modos menores?
Brian Carper

3
Asegúrese de que su modo menor esté primero en la lista minor-mode-map-alist.
Trey Jackson

2
Trey tiene razón. Por lo general, poner esto cerca del final de su .emacs es suficiente. Además, la mayoría de los enlaces que anularía serían los que están configurando los modos principales ... los modos menores generalmente permanecen fuera del camino.
scottfrazer

Seguí este enfoque, pero luego me di cuenta de que todo lo que vincule a Ci también se vinculará a la tecla TAB. ¿Alguna sugerencia?
Steve

3
Brian Carper: Aquí hay una mejora para lidiar con los modos menores cargados posteriormente: stackoverflow.com/questions/683425/…
phils

30

Como adición a la respuesta de scottfrazer , escribí lo siguiente para que mis combinaciones de teclas conserven la prioridad, incluso si las bibliotecas cargadas posteriormente traen nuevos mapas de teclas propios.

Debido a que los mapas de teclas se pueden generar en tiempo de compilación, loadparecía el mejor lugar para hacer esto.

(add-hook 'after-load-functions 'my-keys-have-priority)

(defun my-keys-have-priority (_file)
  "Try to ensure that my keybindings retain priority over other minor modes.

Called via the `after-load-functions' special hook."
  (unless (eq (caar minor-mode-map-alist) 'my-keys-minor-mode)
    (let ((mykeys (assq 'my-keys-minor-mode minor-mode-map-alist)))
      (assq-delete-all 'my-keys-minor-mode minor-mode-map-alist)
      (add-to-list 'minor-mode-map-alist mykeys))))

Pegué su script pero no tuvo ningún efecto :(
alper

@alper Le sugiero que publique una pregunta con todos los detalles relevantes, incluido el código que está usando realmente, y un ejemplo / receta específica para reproducir el problema.
phils

21

Instalar use-package, evaluar y listo:

(require 'bind-key)
(bind-key* "C-i" 'some-function)

5
Instalar solo bind-key es suficiente para el caso de uso, aunque use-package depende de bind-key.
xuchunyang

2
Este (paquete 'bind-key') parece ser la solución más conveniente; gracias por compartir.
oligilo

No pude encontrar coincidencias para use-package:Install package: use-package [No Match]
alper

14

Encontré esta pregunta mientras buscaba "emacs undefine org mode keybindings", porque quería desvincular el comportamiento existente de Cc Cb para permitir que mi mapa global bury-buffer funcione en un búfer de organización.

Esta terminó siendo la solución más simple para mí:

(add-hook 'org-mode-hook
      (lambda ()
        (local-unset-key (kbd "C-c C-b"))))

1
Esto es específico del modo y no aborda el panorama general a pesar de que funciona para su caso de uso único.
RichieHH

12

Aunque la respuesta de scottfrazer es exactamente lo que pediste, mencionaré para la posteridad otra solución.

Del manual de Emacs :

"No defina la letra Cc como una clave en los programas Lisp. Las secuencias que constan de Cc y una letra (mayúscula o minúscula) están reservadas para los usuarios; son las únicas secuencias reservadas para los usuarios, así que no las bloquee".

Si vincula sus enlaces globales personales a Cc más una letra, entonces "debería" estar seguro. Sin embargo, esto es simplemente una convención, y cualquier modo puede anular sus enlaces.


3
No esperaba que el modo org, de todos los modos, rompiera esta regla. 'Cc Ch' me dice que Cc a, b, c y l están vinculados a org-agenda, org-iswitchb, org-capture y org-store-link, respectivamente.
Nate Parsons

7
Afaik, vincular estos es el primer paso que sugiere org-mode para usarlo, pero el usuario tiene que definirlos él mismo (es decir, no se hace por defecto), y puede elegir cualquier otro mientras lo hace. (también, es porque se supone que estas vinculaciones son globales, no vinculadas al modo principal de la organización)
Nikana Reklawyks

3

Si desea "usar siempre las combinaciones de teclas en el mapa, a menos que las anule explícitamente para un mapa de modo específico", y asumiendo que está utilizando el enfoque de scottfrazier , desea:

(defun locally-override (key cmd)
  (unless (local-variable-p 'my-keys-minor-mode-map)
    (set (make-variable-buffer-local 'my-keys-minor-mode-map)
         (make-sparse-keymap))
    (set-keymap-parent my-keys-minor-mode-map 
                       (default-value 'my-keys-minor-mode-map)))
  (define-key my-keys-minor-mode-map key cmd))

Entonces

(locally-override "\C-i" nil)

debería eliminar el enlace "\ Ci" del modo menor sólo en el búfer actual. Advertencia: esto no está completamente probado, pero parece el enfoque correcto. El objetivo de establecer el padre en lugar de simplemente hacer frente al valor global de my-keys-minor-mode-map es que cualquier cambio posterior al valor global se refleje automáticamente en el valor local.


2

No creo que puedas. Eso es aproximadamente equivalente a decir que desea definir una variable global que no se pueda ocultar mediante declaraciones de variables locales en funciones. El alcance simplemente no funciona de esa manera.

Sin embargo, puede haber una forma de escribir una función elisp para revisar la lista de modos y reasignarla en cada uno de ellos.


Esta idea de delimitación es técnicamente correcta, pero overriding-local-mapestá diseñada específicamente para anular todos los demás mapas. Sin embargo, es peligroso usarlo.
event_jr

2

A menos que realmente desee hacer esto usted mismo, debe verificar y ver si alguien más ya lo ha hecho.

Hay un paquete para Emacs que proporciona combinaciones de teclas similares a las de Windows. Debería poder encontrarlo a través de Google.


4
El paquete en el que está pensando probablemente sea cua-mode.
Drew

1
Sí, ese es el paquete.
JesperE
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.