Où dois-je inclure une initialisation paresseuse?

13

Je veux ajouter une liaison de clé spécifique au mode latex:

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

En même temps, je veux le définir uniquement lorsque le mode spécifique est chargé. Je voudrais donc savoir s'il existe une préférence (meilleure pratique) entre l'utilisation du hook approprié ( latex-mode-hook) pour accomplir cela ou l'utilisation de la clause (with-eval-after-load "tex-mode" ...pour encapsuler la définition de liaison de clé. J'ai testé les deux et ils fonctionnent bien, mais je me demande lequel est la bonne façon de le faire.

jrbalderrama
la source
2
with-eval-after-loadest chargé une fois , donc un changement de keymap y va. Les hooks se chargent à chaque exécution du mode , par exemple lors du chargement d'un nouveau fichier associé au mode, ou cependant le hook est défini. Vous chargeriez par exemple flyspell-modeou hl-line-modedans un crochet. Dans mon init.elj'utilise with-eval-after-loadenviron 160 fois et add-hook110 fois. Un init paresseux est un bon init (OMI).
rasmus
@rasmus sonne comme une réponse si vous avez le temps :) La distinction du nombre de fois que le code est exécuté est la principale à considérer, à mon avis. (C'est aussi le seul auquel je puisse penser…)
Sean Allred
Pour savoir pourquoi c'est une mauvaise idée de changer les raccourcis clavier dans les hooks de mode, voir emacs.stackexchange.com/questions/990/…
tarsius

Réponses:

18

Un init paresseux est un bon init.

(OMI)

Quand utiliser with-eval-after-load

with-eval-after-loadest chargé une fois lorsqu'une certaine fonctionnalité ou un fichier est chargé pour la première fois , donc un changement de keymap va clairement à l'intérieur de l'un d'entre eux. Pas des moindres car le keymap peut ne pas être connu au moment de l'initialisation [essayez quelque chose comme (define-key message-mode-map (kbd "C-c f") 'Footnote-add-footnote)dans emacs -q]. Un hook n'est pas une bonne solution ici car il lie la fonction à une clé à chaque démarrage du hook. Comme le note Tarsius , vous pouvez en savoir plus sur pourquoi ne pas le faire local-set-keydans les crochets.

Enfin, notez que with-eval-after-loadGNU Emacs 24.4 est un wrapper de 2 lignes eval-after-loadoù il bodyn'est pas nécessaire de le citer.

Quand utiliser des crochets

Les crochets sont une liste de fonctions chargées à chaque fois qu'un critère est satisfait, par exemple un certain mode est démarré. Une utilisation courante des crochets consiste à charger des modes mineurs, tels que flyspell-modeou hl-line-mode. Par exemple (add-hook 'org-agenda-mode-hook 'hl-line-mode). Comme le souligne Rémi , il add-hooksest intelligent et fera ce qu'il faut même si la variable hook n'a pas encore été chargée. Néanmoins, j'ai de nombreuses clauses comme les suivantes, qui peuvent être négligeables pour les gains de vitesse, mais donnent un sens de l'organisation et de la structure de dépendance:

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

Pourquoi ajouter au crochet après org-agenda? Comme toujours, C-h v org-agenda-mode-hook C-jdélivre. Le crochet est défini org-agenda.elcomme indiqué dans *help*.

Chargement de fonctionnalités supplémentaires with-eval-after-load

with-eval-after-loadest également important pour le chargement de fonctionnalités supplémentaires. Vous voudriez probablement quelque chose comme (with-eval-after-load 'org (require 'org-inlinetask))charger des tâches en ligne d'organisation. Pour voir pourquoi (find-library "org-inlinetask"). Depuis org-inlinetasks.eldirectement (require 'org), tous les éléments agréables autoloadque vos sympathiques responsables Emacs ont pris grand soin à fournir seront "ignorés" et tous org.el(c)seront chargés.

Mais que faire si votre (personnel) defunest requis à plusieurs endroits? Si vous êtes vraiment difficile, vous pouvez mettre les defuns dans un autre fichier de votre load-pathet ajouter des autoloadcookies, ou vous pouvez dire à Emacs où trouver la fonction avec la autoloadfonction. Alors quelque chose comme ça fonctionnerait:

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

Ou vous pourriez tout simplement require orgtirercdlatex

Et, honnêtement, le désamorçage personnel n'aura pas d'importance la plupart du temps. Les 1150 lignes de defuns personnels (84 defuns) dans mon init.elajoute 0,02s sur Emacs vanille.

Mesurer le temps d'initialisation

Un moyen simple d’estimer le temps d’initialisation est

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

(référence par rapport à emacs -q.

Mais pour obtenir une approximation plus détaillée de l'endroit où se trouvent les goulots d'étranglement d'initialisation, consultez Joe Schafer's esup.

Enfin, le temps de chargement ne disparaît pas comme par magie. Vous ne faites que le pousser vers l'avant (dans la mesure où vous utilisez toutes les fonctionnalités de chaque session).

rasmus
la source
1
Vous n'avez pas besoin de mettre add-hook dans with-eval-after-load, car add-hook liera la variable si elle n'est pas déjà là.
Rémi
Tu as raison! Pourrait-il encore y avoir des gains de vitesse? [Je vais essayer de mettre à jour la réponse plus tard pour refléter cela]
rasmus
Qu'en est-il des défuns que plus tard je voudrais attacher à un crochet ou à une attache de clé Dois-je définir un defun en dehors du with-eval-after-loadsans perdre les avantages d'initialisation paresseux?
jrbalderrama
5

En plus de vos suggestions eval-after-loadet de l'utilisation d'un crochet, laissez-moi vous suggérer use-package.el. Vous pouvez faire ce dont vous avez besoin avec

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

LaTeX ne sera chargé qu'après votre demande.

Juste comme remarque: une utilisation prudente de use-packagea réduit mes temps de démarrage à moins d'une seconde. (Cela prenait environ quatre secondes.)

Sean Allred
la source
Merci pour votre suggestion. J'ai également envisagé d'utiliser use-package mais je veux vraiment comprendre comment le faire sans packages supplémentaires.
jrbalderrama
1
@jrbalderrama note qui devrait être livrée use-packageavec Emacs 25.
Sean Allred