2009-02-17 11 views
11

La maggior parte delle modalità emacs include una sorta di prefisso per attivare le loro funzioni. Ad esempio, quando si utilizza GUD "next" è "C-c C-n". Di queste modalità, molti forniscono buffer speciali in cui è possibile utilizzare una singola chiave per attivare alcune funzionalità (solo 'n' o 'p' per leggere la posta successiva/precedente in GNUS per esempio).Tasti di modifica semi-modali/prefisso automatico

Non tutte le modalità forniscono un tale buffer, tuttavia, e digitando ripetutamente il prefisso può essere noioso. Esiste un po 'noto di elis che consentirà la specifica ad hoc delle chiavi di prefisso da applicare a tutti gli input per un po' di tempo? (Fino a quando non si preme ESC o qualche altra chiave sanzionata, ad esempio)

+0

Stai parlando di modalità secondarie o modalità principali? Puoi dare un esempio specifico? –

+0

In realtà, sarei soddisfatto di qualcosa di ancora meno strutturato di questo: solo un modo per inserire un prefisso e farlo applicare a tutti i tasti che premo fino a quando non premo alcune serie speciali di tasti per uscire da quella modalità. – fdr

risposta

15

Sono d'accordo con la risposta di Joe Casadonte che la strada da percorrere è definire la propria modalità minore (o maggiore).

Detto questo, la tua domanda è interessante.

Ecco una soluzione che richiede una sequenza di tasti, che accetta i tasti del prefisso e promuove quella mappa dei tasti al livello principale.

ad es. Si supponga il seguente mappa della tastiera:

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

Quando si esegue M-x semi-modal-minor-mode, vi verrà chiesto per alcune sequenze di tasti. Se si immette M-g n, allora le seguenti combinazioni di tasti sono impostati:

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

Così ora n non auto-inserimento, ma salta per l'errore successivo. Guarda il codice qui sotto.

Nota: quando questa modalità secondaria è abilitata, <f12> è associato a un comando che disabilita la modalità secondaria. Questo perché le associazioni di tasti potrebbero benissimo disabilitare Emacs (ad esempio, cosa succederebbe se ci fosse un nuovo keybinding per M-x).

A cura di aggiungere questi pensieri: tampone la variabile modo minore è stato originariamente fatto locale, ma che non funziona a meno che non anche effettua il buffer variabile di minor-mode-alist locale (duh). Ma, anche tu (probabilmente) non vuoi questi binding nel minibuffer ... Quindi, non ho intenzione di testarlo b/c dipende davvero da cosa vuoi, ma ho aggiunto un commento al codice riflettendo questo pensiero

Senza ulteriori indugi:

(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

Questo è quello che stavo cercando. Potrei apportare alcune modifiche minori a per renderlo più globale (hai qualche suggerimento? Quando si usa il cscope che salta fuori dal buffer semi-modale mi farà perdere la modalità ... ... ma la modalità minore locale-ish sentire sembra utile troppo. – fdr

+0

(Sembra che la keymap globale sia sufficiente, ma ho pensato che dovrei chiedere nel caso ci fosse qualche altra considerazione alternativa) – fdr

+0

Amico, è davvero fantastico!Non so se lo userei mai, ma è un gran bel pezzo di codice. Se potessi darti più di un voto positivo, lo farei sicuramente! –

1

La parte specifica (modale?) Delle associazioni di tasti in Emacs è realizzata dalle varie mappe locali che oscurano la mappa globale universale. La maggior parte delle modalità principali e secondarie definisce le proprie mappe locali; per esempio, c'è una mappa in modalità gud. I collegamenti chiave in una keymap locale saranno attivati ​​solo quando il buffer corrente è nella rispettiva modalità. È possibile personalizzare una mappa dei tasti specifica della modalità tramite il hook della modalità. Ad esempio, si può mettere questo frammento di codice nel vostro ~/.emacs

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

Maggiori dettagli sulle mappature possono essere trovati in Elisp reference manual.

+0

Questa è un'informazione utile, ma non proprio quella che sto cercando. Considera la modalità pieghevole, che ha cose come "C-c C- @>". Mi piacerebbe specificare rapidamente "C-c C- @" come prefisso in modo da poter digitare ">" per inserire una piega senza chiavi di associazione nel mio .emacs ogni modalità una per una. – fdr

1

Il problema di base qui è che non esiste una mappa di tasti corrente per-se. C'è la keymap globale che è sovrascritta dalla keymap della modalità principale che a sua volta viene sovrascritta da una o più keymap in modalità minore (e sono in grado di intervenire l'una sull'altra in un determinato modo, ne sono sicuro). La definizione di una nuova modalità principale lascerà comunque funzionali i tasti della modalità secondaria, e la definizione di una nuova modalità secondaria avrà effetto solo su tutti i tasti definiti nella mappa dei tasti della modalità secondaria.

Ad esempio, è possibile definire una modalità secondaria che farà ciò che si desidera purché la modalità secondaria sia attiva. Si definisce una nuova modalità minore my-gud-mode che avrà la propria mappa dei tasti. Dovresti quindi definire tutte le associazioni di tasti per esso (ad esempio n, p, ecc.) E dovresti anche definire tutte le chiavi che non vuoi lavorare per essere associate alla funzione ignore. Questo è il vero dolore di questo, rimappando tutte le altre chiavi. La modalità secondaria è facile da accendere e spegnere, però; questo è il vantaggio

Definire una nuova modalità principale sarebbe più semplice a prima vista, in quanto consente di ignorare più "la mappa dei tasti corrente" in un'unica ripresa. Dovrebbe notare la modalità principale corrente in una variabile locale del buffer in modo che possa essere ripristinata più tardi quando la modalità principale temporanea è disattivata. Ma avrai ancora altre modalità minori che si intromettono nella tua mappa dei tasti, quindi non sarà "pura".

Quello che faccio in questa situazione è definire un prefisso più facile! Per roba che uso tutto il tempo, tutto il giorno ogni giorno, do loro un tasto funzione tutto da solo (ad esempio ho F1 messo da parte come la mia chiave in modalità jabber). Per cose meno immediatamente utili, ho altri due tasti funzione messi da parte, F3 e F12 (sono sicuro che c'era qualche ragione per cui li ho scelti molto tempo fa, ma non ricordo più perché). F3 definisce i tasti sempre disponibili, indipendentemente dalla modalità principale. F12 definisce i tasti che dipendono dalla modalità principale. Alcuni esempi:

Ho impostato F3-m- come prefisso per commutare le modalità principali (ad esempio, gli switch F3-mp in modalità cperl) e F3-M- come prefisso per le modalità secondarie (ad es. Commutatori F3-Mv modalità di visualizzazione). Questi sono sempre disponibili, quindi puoi fare qualcosa come legare F3-g- come prefisso Gud e digitare F3-g-p per i precedenti e così via.

Il mio tasto F12 dipende dalla modalità. Quindi, in modalità diritta F12-e chiamerà lo dired-nt-open-in-excel sul file corrente, e in emacs-lisp-mode F12-e chiamerà elint-current-buffer. In qualche modo non li confondo mai.

Se hai bisogno di aiuto nella definizione di keymap come questa, fammi sapere.

0

modalità Viper consente di mappare i comandi ai tasti o sequenze di tasti durante la modalità visiva (inserito con il tasto "ESC"). Torna alla modalità di inserimento con "i".
Dai un'occhiata a viper-in-more-modes.el
Utilizza viper-modify-major-mode.
Mi piace anche usare la viper-vi-global-user-map: a snippet dal mio file .emacs.

Problemi correlati