2009-02-17 10 views
11

La mayoría de los modos emacs incluyen algún tipo de prefijo para activar sus funciones. Por ejemplo, al usar GUD "siguiente" es "C-c C-n". De estos modos, muchos proporcionan búferes especiales donde se puede usar una sola tecla para activar alguna funcionalidad (solo 'n' o 'p' para leer el correo siguiente/anterior en GNUS por ejemplo).Teclas de edición semi-modal/prefijación automática

Sin embargo, no todos los modos proporcionan dicho búfer, y escribir repetidamente el prefijo puede ser fastidioso. ¿Existe un bit de elisp bien conocido que permita la especificación ad-hoc de claves de prefijo para ser perpendedas a todas las entradas por algún tiempo? (Hasta golpear ESC u otra tecla sancionada, por ejemplo)

+0

¿Estás hablando de modos menores o modos principales? ¿Puedes dar un ejemplo específico? –

+0

En realidad, estaría satisfecho con algo aún menos estructurado que eso: solo una forma de ingresar un prefijo y aplicarlo a todas las teclas que presiono hasta que presiono alguna serie especial de teclas para salir de ese modo. – fdr

Respuesta

15

Estoy de acuerdo con la respuesta de Joe Casadonte de que el camino a seguir es definir su propio modo menor (o mayor).

Dicho esto, tu pregunta es interesante.

Aquí hay una solución que le pide una secuencia de teclas y toma las pulsaciones de tecla del prefijo y promueve ese mapa de teclas al nivel superior.

p. Ej. Asumir el siguiente mapa de teclas:

M-g ESC   Prefix Command 
M-g g   goto-line 
M-g n   next-error 
M-g p   previous-error 

Cuando se ejecuta M-x semi-modal-minor-mode, se le pedirá algunos golpes de teclado. Si introduce M-g n, a continuación, se establecen las siguientes combinaciones de teclas:

ESC   Prefix Command (same as M-g ESC) 
g   goto-line 
n   next-error 
p   previous-error 

Así que ahora n no se auto-inserción, pero salta a la siguiente error. Vea el código a continuación.

Nota: cuando este modo secundario está habilitado, <f12> está vinculado a un comando que deshabilita el modo secundario. Esto se debe a que las combinaciones de teclas podrían muy bien deshabilitar sus Emacs (por ejemplo, ¿qué pasaría si hubiera un nuevo enlace de clave para M-x).

Editado para añadir estos pensamientos: tampón la variable modo menor se hizo originalmente local, pero que no funciona a menos que también tomar la variable buffer minor-mode-alist local (duh). Pero, tú también (probablemente) no quieres estos enlaces en el minibúfer ... Entonces, no voy a probarlo porque realmente depende de lo que quieras, pero he agregado un comentario al código reflejando este pensamiento

Sin más preámbulos:

(defvar semi-modal-minor-mode-keymap (make-sparse-keymap) 
    "keymap holding the prefix key's keymapping, not really used") 
(defvar semi-modal-minor-mode-disable-key (kbd "<f12>") 
    "key to disable the minor mode") 
(defun semi-modal-minor-mode-disable() 
    "disable the minor mode" 
    (interactive) 
    (semi-modal-minor-mode 0)) 

(define-minor-mode semi-modal-minor-mode 
    "local minor mode that prompts for a prefix key and promotes that keymap to the toplevel 
e.g. If there are bindings like the following: 

M-g ESC   Prefix Command 
M-g g   goto-line 
M-g n   next-error 
M-g p   previous-error 

And you enter 'M-g n' when prompted, 
then the minor mode keymap has the bindings 
    g -> goto-line 
    n -> next-error 
    p -> previous-error 
    ESC -> Prefix Command (same as M-g ESC) 

The variable semi-modal-minor-mode-disable-key is bound to disable the minor mode map. 
This is provided because often the mappings make the keyboard unusable. 
Use at your own risk." 
    nil " Semi" semi-modal-minor-mode-keymap 
    (make-local-variable 'semi-modal-minor-mode) 
    (make-local-variable 'minor-mode-map-alist) 
    (let ((pair-holding-keymap-to-modify (assq 'semi-modal-minor-mode minor-mode-map-alist))) 
    (setcdr pair-holding-keymap-to-modify (make-sparse-keymap)) 
    (if semi-modal-minor-mode 
     (let (key 
       keymap) 
      ;; all but last (b/c we want a prefix 
      (setq key (substring (read-key-sequence "Enter a full key combination, the prefix will be used: ") 0 -1)) 
      (if (and (not (equal "" key)) 
        (not (equal (kbd "C-g") key)) 
        (let ((semi-modal-minor-mode nil)) 
        (keymapp (setq keymap (key-binding key))))) 
       (progn 
       (setcdr pair-holding-keymap-to-modify (copy-keymap keymap)) 
       (when semi-modal-minor-mode-disable-key 
        (define-key (cdr pair-holding-keymap-to-modify) 
        semi-modal-minor-mode-disable-key 'semi-modal-minor-mode-disable))) 
      (semi-modal-minor-mode 0)))))) 
+0

Esto es lo que he estado buscando. Puedo hacer algunas modificaciones menores para hacerlo más global (¿tiene alguna sugerencia? Al usar cscope saltando del búfer semi-modal, haré que pierda la modalidad ...) pero el modo menor local-ish parece útil también. – fdr

+0

(Parece que el mapa de teclas global sería suficiente, pero pensé que debería preguntar solo en caso de que hubiera alguna otra consideración alternativa) – fdr

+0

¡Amigo, eso es increíble!No sé si alguna vez lo usaría, pero es una gran pieza de código. ¡Si pudiera darle más de un voto positivo, seguramente lo haría! –

1

La parte específica de modo (modal?) De las vinculaciones de teclas en Emacs se realiza mediante varios mapas locales que eclipsan el mapa global universal. La mayoría de los modos mayor y menor definen sus propios mapas locales; por ejemplo, hay un mapa en modo gud. Las asociaciones de teclas en un mapa de teclas local se activarán solo cuando el búfer en uso esté en el modo correspondiente. Puede personalizar un mapa de teclas específico de modo a través del gancho del modo. Por ejemplo, es posible poner este fragmento en su ~/.emacs

 
    (add-hook 'gud-mode-hook 
     (lambda() 
     (local-set-key (kbd "C-n") 
         (lookup-key (current-local-map) (kbd "C-c C-n"))))) 

Más detalles acerca de los mapas de teclas se pueden encontrar en Elisp reference manual.

+0

Esta es información útil, pero no exactamente lo que estoy buscando. Considere el modo plegado, que tiene cosas como "C-c C- @>". Me gustaría especificar rápidamente "C-c C- @" como mi prefijo, así que puedo simplemente escribir ">" para ingresar un pliegue sin llaves de enlace en mis .emacs en cada modo, uno por uno. – fdr

1

El problema básico aquí es que no existe un mapa de teclas actual per se. Existe el mapa de teclas global que se reemplaza por el mapa de teclas del modo principal, que a su vez es anulado por uno o más mapas de teclas de modo menor (y pueden cruzarse el uno al otro de alguna manera definida, estoy seguro). La definición de un nuevo modo principal aún dejará las teclas de modo menor funcionales, y la definición de un nuevo modo menor solo afectará a las teclas que defina en el mapa de teclas del modo secundario.

Por ejemplo, puede definir un modo menor que hará lo que desee mientras el modo menor esté activo. Usted define un nuevo modo menor my-gud-mode que tendrá su propio mapa de teclas. Debería definir todas sus asignaciones de teclas (p. Ej., N, p, etc.) y también debería definir todas las teclas que no deseaba que estuvieran vinculadas a la función ignore. Ese es el verdadero dolor de esto, remapeando todas las otras claves. Sin embargo, el modo menor es fácil de activar y desactivar; esa es la ventaja.

Definir un nuevo modo principal sería más fácil a primera vista, ya que le permitirá anular más del "mapa de teclas actual" en una sola toma. Debe tener en cuenta el modo principal actual en una variable local de búfer para que pueda restaurarse más tarde cuando se apaga el modo principal temporal. Pero todavía tendrá otros modos menores que entren en su mapa de teclas, por lo que no será "puro".

¡Lo que hago en esta situación es definir un prefijo más fácil! Para las cosas que utilizo todo el tiempo, todo el día todos los días, les doy una tecla de función por sí solas (por ejemplo, tengo F1 reservada como mi tecla de modo jabber). Para cosas menos útiles, tengo otras dos teclas de función reservadas, F3 y F12 (estoy seguro de que hubo alguna razón por la que las elegí hace mucho tiempo, pero ya no recuerdo por qué). F3 define las claves que están siempre disponibles, independientemente del modo principal. F12 define claves que dependen del modo principal. Algunos ejemplos:

He configurado F3-m- como un prefijo para cambiar los modos principales (por ejemplo, F3-mp cambia a cperl-mode) y F3-M- como un prefijo para modos menores (por ejemplo, F3-Mv alterna modo de vista). Estos están siempre disponibles, por lo que podría hacer algo como unir F3-g- para ser su prefijo gud, y escribir F3-g-p para el anterior y así sucesivamente.

Mi tecla F12 depende del modo. Entonces, en modo directo, F12-e llamará al dired-nt-open-in-excel en el archivo actual, y en emacs-lisp-mode F12-e llamará al elint-current-buffer. De alguna manera, nunca los confundí.

Si necesita ayuda para definir mapas de teclas como este, hágamelo saber.

0

modo Viper le permite asignar comandos a las teclas o secuencias de teclas en el modo visual (introducida mediante la tecla "ESC"). Vuelve al modo insertar con "i".
Eche un vistazo a viper-in-more-modes.el
Utiliza viper-modify-major-mode.
También me gusta usar el viper-vi-global-user-map: un snippet de mi archivo .emacs.