Wo soll ich eine Lazy-Initialisierung einfügen?


13

Ich möchte dem Latex-Modus eine bestimmte Schlüsselbindung hinzufügen:

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

Gleichzeitig möchte ich es nur einstellen, wenn der bestimmte Modus geladen ist. Daher würde ich gerne wissen, ob es eine Vorliebe (Best Practice) gibt, den entsprechenden Hook ( latex-mode-hook) zu verwenden, um dies zu erreichen, oder die Klausel (with-eval-after-load "tex-mode" ...zum Umbrechen der Schlüsselbindungsdefinition zu verwenden. Ich habe beide getestet und sie funktionieren einwandfrei, aber ich frage mich, welcher Weg der richtige ist.


2
with-eval-after-loadWird einmal geladen , so geht ein Keymap-Wechsel dahin. Hooks werden jedes Mal geladen, wenn der Modus ausgeführt wird , z. B. beim Laden einer neuen Datei, die dem Modus zugeordnet ist, oder wenn der Hook definiert ist. Sie würden zB flyspell-modeoder hl-line-modein einen Haken laden . In meinem verwende init.elich with-eval-after-loadungefähr 160 mal und add-hook110 mal. Ein Lazy Init ist ein guter Init (IMO).
Rasmus

@rasmus klingt wie eine Antwort, wenn Sie die Zeit haben :) Die Unterscheidung, wie oft der Code ausgeführt wird, ist meiner Meinung nach die wichtigste. (Es ist auch das einzige, an das ich denken kann ...)
Sean Allred

Warum es eine schlechte Idee ist, die Tastenkombinationen in Modus-Hooks zu ändern, erfahren Sie unter emacs.stackexchange.com/questions/990/…
tarsius 27.10.14

Antworten:


18

Ein fauler Init ist ein guter Init.

(IMO)

Wann zu verwenden with-eval-after-load

with-eval-after-loadgeladen wird einmal , wenn eine bestimmte Funktion oder Datei wird zuerst geladen wird , so eindeutig ein keymap Wechsel innerhalb eines davon geht. Nicht zuletzt, weil die Keymap zur Init-Zeit möglicherweise nicht bekannt ist [versuchen Sie etwas wie (define-key message-mode-map (kbd "C-c f") 'Footnote-add-footnote)in emacs -q]. Ein Hook ist hier keine gute Lösung, da er die Funktion bei jedem Start des Hooks an eine Taste bindet . Wie tarsius Notizen können Sie mehr lesen , warum nicht an local-set-keyHaken.

Schließlich ist zu beachten , dass with-eval-after-loaddas GNU Emacs 24.4 ist ein 2 - zeiliges Wrapper um , eval-after-loadwo bodynicht in Anführungszeichen gesetzt werden muß.

Wann benutzt man Haken?

Hooks sind Listen von Funktionen, die jedes Mal geladen werden, wenn ein Kriterium erfüllt wird, z. B. wenn ein bestimmter Modus gestartet wird. Hooks werden häufig zum Laden von Nebenmodi wie flyspell-modeoder verwendet hl-line-mode. ZB (add-hook 'org-agenda-mode-hook 'hl-line-mode). Wie Rémi betont, add-hooksist er schlau und wird das Richtige tun, auch wenn die Hook-Variable noch nicht geladen wurde. Trotzdem habe ich viele Klauseln wie die folgenden, die für Geschwindigkeitszuwächse vernachlässigbar sind, aber ein Gefühl für Organisation und Abhängigkeitsstruktur vermitteln:

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

Warum nachhaken org-agenda? Wie immer C-h v org-agenda-mode-hook C-jliefert. Der Haken ist definiert in , org-agenda.elwie gezeigt in *help*.

Zusätzliche Funktionen werden geladen with-eval-after-load

with-eval-after-loadist auch wichtig, um zusätzliche Funktionen zu laden. Wahrscheinlich möchten Sie so etwas wie (with-eval-after-load 'org (require 'org-inlinetask))org-Inlinetasks laden. Um zu sehen warum (find-library "org-inlinetask"). Da org-inlinetasks.eldirekt (require 'org)alle netten autoload, die Ihre freundlichen Emacs-Betreuer mit großer Sorgfalt erstellt haben, werden "ignoriert" und alle org.el(c)geladen.

Was aber, wenn Ihr (persönlicher) Platz defunbenötigt? Wenn Sie wirklich wählerisch sind, können Sie das defuns in eine andere Datei einfügen load-pathund autoloadCookies hinzufügen , oder Sie können Emacs mitteilen, wo die Funktion mit der autoloadFunktion zu finden ist. Dann würde so etwas funktionieren:

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

Oder man könnte genauso require orgwie es seinerseits ziehen würdecdlatex

Und ehrlich gesagt, für die Init-Zeit wird der persönliche Defun die meiste Zeit keine Rolle spielen. Die 1150 Zeilen von persönlichen Defuns (84 Defuns) in meinem init.eladdieren 0.02s gegenüber Vanille-Emacs.

Initialisierungszeit messen

Eine einfache Methode zur Abschätzung der Initialisierungszeit ist

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

(Benchmark gegen emacs -q.

Um eine detailliertere Abschätzung der Initialisierungsengpässe zu erhalten, schauen Sie sich Joe Schafers an esup.

Schließlich verschwindet die Ladezeit nicht auf magische Weise. Sie treiben es nur voran (sofern Sie alle Funktionen in jeder Sitzung verwenden).


1
Sie müssen add-hook nicht in ein with-eval-after-load einfügen, da add-hook die Variable bindet, wenn sie nicht bereits vorhanden ist.
Rémi

Sie haben Recht! Könnte es dennoch Geschwindigkeitsgewinne geben? [Ich werde versuchen, die Antwort später zu aktualisieren, um dies
wiederzugeben

Was ist mit Defuns, die ich später an einen Haken oder eine Schlüsselbindung binden möchte? Soll ich ein Defun außerhalb der definieren, with-eval-after-loadohne die faulen Initialisierungsvorteile zu verlieren?
jrbalderrama

5

eval-after-loadLassen Sie mich zusätzlich zu Ihren Vorschlägen und der Verwendung eines Hakens Folgendes vorschlagen use-package.el. Sie können tun, was Sie brauchen

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

LaTeX wird erst nach Aufforderung geladen .

Nur als Randnotiz: Durch sorgfältige Verwendung von konnte use-packageich meine Startzeiten auf unter eine Sekunde verkürzen. (Früher dauerte es ungefähr vier Sekunden.)


Danke für deinen Vorschlag. Ich habe auch überlegt, use-package zu verwenden, aber ich möchte wirklich herausfinden, wie es ohne zusätzliche Pakete geht.
Jrbalderrama

1
@ jrbalderrama Hinweis, der use-packagemit Emacs 25 ausgeliefert wird.
Sean Allred
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.