Unterschied zwischen init und config im use-package

16

Ich habe eine Konfiguration wie diese:

(use-package html-mode
  :mode "\\.html\\'"
  :config
  (progn
    (add-hook 'html-mode-hook 'turn-off-auto-fill)))

Wenn ich jetzt eine HTML-Datei besuche, stelle ich fest, dass diese auto-fillnicht deaktiviert ist. Aber wenn ich :initstatt :config, auto-fillwird ausgeschaltet. Meine Frage ist also, wann die Befehle unter :configausgeführt werden?

Sibi
quelle

Antworten:

16

Sie unterscheiden sich, wenn das Paket zurückgestellt wird, dh erst geladen wird, wenn es benötigt wird. In diesem Fall :initwird sie zum Zeitpunkt des ersten Lesens Ihrer emacs-Datei :configausgeführt , jedoch zum Zeitpunkt des tatsächlichen Ladens des Pakets.

In Ihrem Beispiel modeverzögert die Verwendung von implizit das Laden des Pakets. Sie haben das Paket so konfiguriert, dass es beim ersten Aufrufen einer HTML-Datei geladen wird.

Sie könnten :demandsicherstellen, dass das Paket immer beim Start geladen wird, aber mit größerer Wahrscheinlichkeit setzen Sie Ihren Haken in das, was Sie hier tun möchten :init.

Aus dem Dokumentationsstring:

:init Code to run when `use-package' form evals.

Da Sie dies in Ihre Benutzer-Init-Datei einfügen, bedeutet dies im Grunde, dass es beim Start ausgeführt wird.

:config Runs if and when package loads.

Also nicht ausführen, bis das Paket tatsächlich geladen wird.

:defer Defer loading of package -- automatic if :commands, :bind, :bind*,  :mode or :interpreter are used.

Beachten Sie die Liste der Dinge, die ein Paket automatisch zurückstellen. Wenn Sie use-packagedie Bedingungen angeben, unter denen Sie dieses Paket benötigen, wird davon ausgegangen, dass Sie es erst laden möchten, wenn diese Bedingungen vorliegen.

:demand Prevent deferred loading in all cases.

Stellen Sie sicher, dass das Paket beim Start geladen wird, unabhängig von den anderen von Ihnen angegebenen Optionen.

Aktualisieren

Dies basierend auf den jüngsten Kommentaren noch einmal zu überprüfen ... Was ich oben gesagt habe, ist alles wahr, aber ich denke nicht, dass es die Frage richtig beantwortet. Das eigentliche Problem hierbei ist, dass html-modees sich nicht um ein Paket handelt, sondern um einen vom Paket definierten Modus sgml-mode. Das funktioniert bei mir wie erwartet:

(use-package sgml-mode
  :mode ("\\.html\\'" . html-mode)
  :config (add-hook 'html-mode-hook 'turn-off-auto-fill))

Im ursprünglichen Beispiel wird der :configAusdruck nie ausgewertet, da ein Paket mit dem Namen html-modenie geladen wird. Das Verschieben desselben Ausdrucks :initfunktioniert, da der Init-Code immer ausgewertet wird, unabhängig davon, ob das Paket jemals geladen wird.

Glucas
quelle
@npostavs Danke, erwähnenswert. Ich bin noch nicht selbst zu-package 2.0 übergegangen. Zum einen benutze ich es :idleziemlich häufig und habe die Auswirkungen von ": Leerlauf wurde entfernt" nicht untersucht.
Glucas
1
Ich verstehe immer noch nicht, warum, wenn er eine HTML-Datei besucht und das Laden des Pakets auslöst, auto-fillnicht deaktiviert ist, dh der Konfigurationscode nicht ausgeführt wird. Ich habe das gleiche Problem.
Ken Williams
@KenWilliams Ist dein Problem auch mit dem HTML-Modus? Ich denke, das eigentliche Problem hier ist, dass html-modees sich nicht um ein Paket handelt. Zumindest in meiner aktuellen Emacs-Version html-modeist das im Paket definiert sgml-mode. Wenn Sie use-packagealso beim html-modeLaden eines Pakets mit dem Namen auffordern, etwas zu tun, wird dieser Code nie ausgeführt, da niemals ein solches Paket geladen wird. Sie müssen das HTML-Modus-Setup in a einfügen (use-package sgml-mode ....).
Glucas
Entschuldigung - mein Problem ist mit org-mode, nicht html-mode. Ein ähnliches Problem besteht darin, dass das Paket aufgerufen wird org-mode, aber das ELPA-Paket aufgerufen wird org. Vielleicht ist das verwirrend (oder ich)?
Ken Williams
7

Dieses Beispiel hat es mir sehr leicht gemacht, den Unterschied zwischen :initund zu verstehen :config. Nehmen wir ein Beispiel für ein ace-windowPaket (dies kann jedoch ein beliebiges Paket sein). Fügen Sie dies in Ihre init.elDatei ein:

(use-package ace-window
  :ensure t
  :defer t
  :config
  (progn
    (message "ace window: hello world")))

Jetzt öffne deinen Emacs und sieh im *Messages*Puffer nach, ob es irgendeine hello worldNachricht gibt. Sie können keine finden, da das Paket zurückgestellt wird. Wechseln Sie nun von configzu init:

(use-package ace-window
  :ensure t
  :defer t
  :init
  (progn
    (message "ace window: hello world")))

Schließen Sie nun den Emac und öffnen Sie ihn erneut. Überprüfen Sie den *Messages*Puffer. Die Meldung wird angezeigt, ace window: hello worldda der Code ausgeführt wird, unabhängig davon, wann er :initangegeben wurde. In diesem Fall configwird es nur ausgeführt, wenn dieses Paket geladen ist.

Sibi
quelle
Das hilft, nur eine Nebenfrage, was ist der Unterschied zwischen dem Keyword :initund :prefaceIhrem Beispiel?
Promotion
@doctorate: :prefacewird ausgeführt, auch wenn das betreffende Paket deaktiviert ist, wohingegen :inites nur ausgeführt wird, wenn ein Paket aktiviert ist.
bbenne10