Differenze tra l'impostazione dei principali tasti della modalità con un gancio rispetto all'aggiunta alla mappa della modalità


13

Supponiamo che io abbia scaricato una modalità principale chiamata magical-modee che abbia una propria mappa magica chiamata magical-mode-map. Questa modalità fornisce anche un hook magical-mode-hookche viene eseguito ogni volta che magical-modediventa la modalità principale di un buffer. Ora voglio modificare il mio file init per aggiungere alcune combinazioni di tasti personalizzate da usare in quella modalità.

Sembra che ci siano (almeno) due modi per impostare combinazioni di tasti personalizzate per magical-mode. Quello che vedo più comunemente è questo:

(defun my-magical-keys ()
  (local-set-key (kbd "C-i") 'previous-line)
  (local-set-key (kbd "C-k") 'next-line)
  (local-set-key (kbd "C-j") 'backward-char)
  (local-set-key (kbd "C-l") 'forward-char))
(add-hook 'magical-mode-hook 'my-magical-keys)

Ma è anche possibile farlo in questo modo:

(define-key magical-mode-map (kbd "C-i") 'previous-line)
(define-key magical-mode-map (kbd "C-k") 'next-line)
(define-key magical-mode-map (kbd "C-j") 'backward-char)
(define-key magical-mode-map (kbd "C-l") 'forward-char)

Il secondo metodo in realtà mi sembra più pulito. Ci sono dei vantaggi nel farlo in un modo rispetto all'altro?


Uso gli stessi tasti per i comandi di movimento di base. Attenzione: questa è una battaglia in salita e potresti voler imparare un po 'di più sui vincoli chiave prima di iniziare a farlo.
tarsius,

@tarsius Una battaglia davvero in salita. Ho già seguito quella strada, ma ora sono tornato al buon vecchio C-ne C-p. L'esempio è solo un codice fittizio. Volevo trovare alcune modalità di esempio molto semplici e esempi di associazioni, proprio in modo che le associazioni stesse non distogliessero dallo scopo reale della domanda.
nispio,

Risposte:


15

Il secondo approccio è preferibile in quanto modifica la mappa dei tasti della modalità solo una volta.

Se lo fai usando l'hook della modalità, questo verrà chiamato ogni volta che quella modalità è abilitata in alcuni buffer. Farlo di nuovo di solito non avrà alcun effetto perché i tasti sono semplicemente legati a ciò a cui sono già associati. Le keymap della modalità principale sono "locali" rispetto alla modalità principale e non ai singoli buffer che utilizzano tale modalità, quindi se si modifica un'associazione in uno di questi buffer, local-set-keyciò influisce su tutti i buffer con la stessa modalità principale.

local-set-keyè principalmente destinato a essere usato come comando. Dopo aver stabilito che si desidera rendere persistenti alcune modifiche, utilizzare define-keycon la keymap mode come primo argomento.

Se si utilizza un hook per modificare più volte la keymap, ciò potrebbe essere in conflitto con l'uso previsto di local-set-key. Di 'che hai usato M-x local-set-key RET C-i fancy-previous-line RETperché vuoi provare quella variante di previous-line. Se ora si apre un nuovo buffer che utilizza la stessa modalità principale, l'hook verrà eseguito di nuovo e sovrascriverà l'associazione temporanea, in tutti i buffer che utilizzano quella modalità principale, incluso il buffer in cui si era utilizzato in precedenza local-set-key.


Mi piace questa risposta, ma cosa succede se la modalità è caricata automaticamente?
rimedio il

2
È possibile ritardare il caricamento di qualsiasi codice fino a dopo qualche libreria è stata caricata: (eval-after-load 'magical '(progn (define-key magical-mode-map ...) ...)).
tarsius,

4

L'uso (define-key my-magical-mode-map …)è normale.

Quando usi un hook e local-set-key, i tasti vengono aggiunti ogni volta che entri in modalità My Magical in qualche buffer. Questo è strano perché local-set-keyinteressa tutti i buffer che si trovano nella stessa modalità (più in generale, tutti i buffer utilizzano la stessa mappa di tasti). Quindi, se hai apportato modifiche alla keymap, verranno sovrascritte ogni volta che accedi alla modalità My Magical in un buffer.

Il secondo metodo può anche essere fonte di confusione se si personalizza la mappa dei tasti in luoghi diversi. Gli hook vengono eseguiti nell'ordine inverso rispetto all'ordine in cui sono stati aggiunti e fino alla prima esecuzione, non vedrai alcuna traccia delle tue personalizzazioni.


2

Apparentemente non stai chiedendo di definire una keymap in modalità principale ma del codice utente per aggiungere o modificare alcune combinazioni di tasti in una keymap in modalità principale esistente . Dici "personalizzato", il che suggerisce questo, ma potremmo anche chiarirlo.

A dire il vero, ciò che dici di vedere più comunemente per questo non è ciò che viene generalmente utilizzato per definire una keymap in modalità principale. È Non quello che si trova nel codice sorgente di Emacs, per esempio. Ed è non ciò che è raccomandato nel manuale Elisp (nodo Major Mode Conventions).

Volevo solo toglierlo di mezzo, per essere chiari per gli altri: in genere non si desidera utilizzare il gancio di modalità per definire la mappa della modalità principale.


Alla tua domanda sulle personalizzazioni delle chiavi utente -

In ogni caso, non local-set-keyè necessario utilizzare un hook in modalità. Basta usare define-keycon la keymap in modalità principale, esattamente come nel tuo primo esempio. @tarsius lo ha già spiegato bene.

A parte questo, la risposta è: fa poca differenza, in generale , se si vincolano i tasti (usando define-keycon la mappa della modalità) una volta per tutte o si usa il gancio per legarli ogni volta che si entra nella modalità.

Ma può fare la differenza se i collegamenti nella mappa cambiano, ad esempio caricando un altro codice che li modifica. In tal caso, inserendo i binding nel gancio della modalità principale si assicura che quando si accede alla modalità verranno stabiliti i binding. Cioè, assicura che saranno fatti, ma non assicura che nient'altro li cambi in seguito (ad esempio un'altra funzione sullo stesso hook, invocata in seguito). Ricorda che hai poco controllo su ciò che viene eseguito su un hook e quando - a meno che, ovviamente, non sei sicuro che solo il tuo codice lo rovini.

Questa è l'unica differenza in effetti, a cui riesco a pensare. Per te decidere quando consideri quella differenza come un vantaggio dell'uno o dell'altro approccio. FWIW, guardando il mio codice, non credo di legare mai le chiavi a un hook di modalità.


Grazie. Ho modificato la domanda per chiarire, si spera, il fatto che non sto creando una modalità principale, semplicemente aggiungendo i miei collegamenti chiave e la modalità principale esistente .
nispio,

0

La tua denominazione è un po 'confusa (penso che dovresti rimuovere mynella tua seconda parte della domanda).

Comunque supponendo che my-magical-keyssia una funzione di personalizzazione dell'utente di magical-mode, vedo un ovvio vantaggio. È facile rimuovere ( remove-hookagganciando) il gancio in una sola volta.

Il secondo vantaggio è ciò a cui sono destinate le funzioni. Voglio dire, sono riutilizzabili. puoi agganciarli ad altre modalità.

Modificare:

Come ha sottolineato @tarsius, rimuovere l'hook non ripristinerà il comportamento originale e trasformare la funzione in una modalità minore potrebbe essere migliore.


Sto personalizzando un'ipotetica modalità principale chiamata my-magical-mode. Tuttavia, se l'uso del my-prefisso è confuso, posso certamente modificare la domanda.
nispio,

Sì, sarebbe meglio, di solito (almeno come vedo in natura) my-viene aggiunto per le funzioni utente.
kindahero,

1
Concordato. Ho appena applicato il my-modo in cui nessuno avrebbe pensato che stavo chiedendo come configurare una modalità reale chiamata magical-mode(se esiste).
nispio,

1
No, rimuovere il gancio non ripristinerà i vecchi attacchi. Almeno non prima che Emacs venga riavviato, e quindi non vedo dover commentare solo una riga anziché quattro come un grande miglioramento.
tarsius,

2
Per quanto riguarda il secondo vantaggio che menzioni: qui sarebbe preferibile creare una modalità minore che potrebbe essere abilitata per varie modalità principali e / o solo alcuni dei buffer utilizzando una modalità maggiore particolare.
tarsius,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.