Dove devo includere un'inizializzazione lazy?


13

Voglio aggiungere una specifica associazione di tasti alla modalità latex:

(define-key latex-mode-map (kbd "<f6>") 'my-latex-defun)

Allo stesso tempo, voglio impostarlo solo quando viene caricata la modalità specifica. Quindi vorrei sapere se esiste una preferenza (best practice) tra l'uso dell'hook appropriato ( latex-mode-hook) per realizzarlo o l'uso della clausola (with-eval-after-load "tex-mode" ...per racchiudere la definizione di associazione chiave. Ho provato entrambi e funzionano bene, tuttavia mi chiedo quale sia il modo giusto per farlo.


2
with-eval-after-loadviene caricato una volta , quindi un cambiamento di keymap va lì. Gli hook vengono caricati ogni volta che viene eseguita la modalità , ad es. Al caricamento di un nuovo file associato alla modalità o comunque viene definito l'hook. Carichi ad es. flyspell-modeO hl-line-modecon un gancio. Nel mio init.eluso with-eval-after-loadcirca 160 volte e add-hook110 volte. Un init pigro è un buon init (IMO).
rasmus,

@rasmus suona come una risposta se hai tempo :) La distinzione di quante volte viene eseguito il codice è la principale da considerare, secondo me. (È anche l'unico che mi viene in mente ...)
Sean Allred,

Per quale motivo è una cattiva idea cambiare i tasti di scelta
rapida

Risposte:


18

Un init pigro è un buon init.

(IMO)

Quando usare with-eval-after-load

with-eval-after-loadviene caricato una volta quando una determinata funzione o file viene caricato per la prima volta, quindi una modifica della keymap va chiaramente all'interno di una di queste. Non da ultimo perché la keymap potrebbe non essere nota al momento dell'inizializzazione [prova qualcosa come (define-key message-mode-map (kbd "C-c f") 'Footnote-add-footnote)in emacs -q]. Un hook non è una buona soluzione qui poiché associa la funzione a un tasto ogni volta che viene avviato l'hook. Come Tarsius note, è possibile leggere di più sul perché non al local-set-keydi ganci.

Infine, nota che with-eval-after-loadGNU Emacs 24.4 è un wrapper a 2 righe attorno al eval-after-loadquale bodynon è necessario quotarlo.

Quando usare i ganci

Gli hook sono un elenco di funzioni caricate ogni volta che viene soddisfatto un criterio, ad esempio viene avviata una determinata modalità. Un uso comune di hook è caricare modalità secondarie, come flyspell-modeo hl-line-mode. Es (add-hook 'org-agenda-mode-hook 'hl-line-mode). Come sottolinea Rémi , add-hooksè intelligente e farà la cosa giusta anche se la variabile hook non è ancora stata caricata. Tuttavia, ho molte clausole come le seguenti, che possono essere trascurabili per gli aumenti di velocità, ma danno un senso di organizzazione e struttura di dipendenza:

(with-eval-after-load 'org-agenda
  (add-hook 'org-agenda-mode-hook 'hl-line-mode))

Perché aggiungere all'hook dopo org-agenda? Come sempre, C-h v org-agenda-mode-hook C-joffre. Il gancio è definito org-agenda.elcome mostrato in *help*.

Caricamento di funzioni extra with-eval-after-load

with-eval-after-loadè anche importante per il caricamento di funzioni extra. Probabilmente vorresti qualcosa come (with-eval-after-load 'org (require 'org-inlinetask))caricare org inlinetasks. Per vedere il perché (find-library "org-inlinetask"). Dal momento che org-inlinetasks.eldirettamente (require 'org), tutto il bello autoloadche i tuoi amichevoli manutentori di Emacs si sono presi molta cura di fornire saranno "ignorati" e tutti org.el(c)saranno caricati.

Ma cosa succede se il tuo (personale) defunè richiesto in più posti? Se sei veramente esigente, potresti inserire le defuns in un altro file nel tuo load-pathe aggiungere autoloadcookie, oppure puoi dire a Emacs dove trovare la funzione con la autoloadfunzione. Quindi qualcosa del genere funzionerebbe:

(autoload 'org-cdlatex-mode "org" "cdlatex mode from org.")
(with-eval-after-load "latex"
  (add-hook 'TeX-mode-hook 'org-cdlatex-mode))

O potresti proprio require orgcome a sua volta tirerebbecdlatex

E, onestamente, il defun personale non avrà molta importanza per il tempo di init per la maggior parte del tempo. Le 1150 linee di defuns personali (84 defuns) nel mio init.elaggiungono 0.02s su Emacs alla vaniglia.

Misurazione del tempo di inizializzazione

Un modo semplice per approssimare il tempo di inizializzazione è

time emacs --eval "(kill-emacs)"

(benchmark contro emacs -q.

Ma per avere un'approssimazione più dettagliata di dove sono i colli di bottiglia di inizializzazione, dai un'occhiata a Joe Schafer esup.

Infine, il tempo di caricamento non scompare magicamente. Lo stai solo spingendo in avanti (nella misura in cui usi tutte le funzionalità in ogni sessione).


1
Non è necessario inserire add-hook in con-eval-after-load, perché add-hook vincolerà la variabile se non è già presente.
Rémi,

Hai ragione! Potrebbe comunque esserci ancora un aumento di velocità? [Proverò ad aggiornare la risposta in seguito per riflettere questo]
rasmus

Che dire di defuns che in seguito vorrei legare a un hook o a un key binding. Devo definire una defun al di fuori di with-eval-after-loadsenza perdere vantaggi di inizializzazione pigra?
jrbalderrama,

5

Oltre ai tuoi suggerimenti eval-after-loade all'uso di un hook, lasciami suggerire use-package.el. Puoi fare quello che ti serve

(use-package latex
  :ensure auctex
  :bind ("<f6>" . my-latex-defun))

LaTeX non verrà caricato fino a dopo averlo richiesto.

Proprio come una nota a margine: un uso attento di use-packageha ridotto i miei tempi di avvio a meno di un secondo. (Una volta impiegava circa quattro secondi.)


Grazie per il tuo suggerimento. Ho anche pensato di usare use-package ma voglio davvero capire come farlo senza pacchetti aggiuntivi.
jrbalderrama,

1
@jrbalderrama nota che use-packageverrà spedito con Emacs 25.
Sean Allred,
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.