Разница между init и config в use-package

16

У меня есть такая конфигурация:

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

Теперь, когда я захожу и посещаю файл HTML, я замечаю, что auto-fillон не выключен. Но если я использую :initвместо :config, auto-fillвыключается. Поэтому мой вопрос: когда выполняются команды :config?

Сиби
источник

Ответы:

16

Они отличаются, если пакет откладывается, т.е. не загружается до тех пор, пока он не понадобится. В этом случае :initон будет выполнен во время первого чтения вашего файла emacs, но :configбудет выполнен во время фактической загрузки пакета.

В вашем примере использование modeнеявно откладывает загрузку пакета. Вы настроили пакет для загрузки при первом посещении html-файла.

Вы можете использовать :demandэто, чтобы убедиться, что пакет всегда загружается при запуске, но более вероятно, что вы хотите сделать здесь, это вставить свой крючок :init.

Из строки документации:

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

Поскольку вы помещаете это в свой пользовательский файл инициализации, это в основном означает, что он будет запускаться при запуске.

:config Runs if and when package loads.

Так что не запускайте, пока пакет на самом деле не загружается ..

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

Обратите внимание на список вещей, которые автоматически делают пакет отложенным. В основном, если вы указываете use-packageусловия, в которых вам нужен этот пакет, предполагается, что вы не хотите загружать его, пока эти условия не возникнут.

:demand Prevent deferred loading in all cases.

Убедитесь, что пакет загружается при запуске, независимо от того, какие другие опции вы указали.

Обновить

Возвращаясь к этому, основываясь на недавних комментариях ... Все, что я сказал выше, правда, но я не думаю, что это правильно отвечает на вопрос. Основная проблема здесь на самом деле в том, что html-modeэто не пакет, а режим, определенный пакетом sgml-mode. Это работает, как и ожидалось для меня:

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

В исходном примере :configвыражение никогда не оценивается, поскольку пакет с именем html-modeникогда не загружается. Перемещение одного и того же выражения в :initрабочее состояние, потому что код инициализации всегда вычисляется независимо от того, был ли загружен пакет.

glucas
источник
@npostavs Спасибо, стоит отметить. Я еще не перешел на использование пакета 2.0. Во-первых, я использую :idleдовольно широко и не изучал влияние ": холостой ход был удален".
glucas
1
Я до сих пор не понимаю, почему, когда он посещает файл HTML и запускает пакет для загрузки, auto-fillне выключается, т.е. код конфигурации не запускается. У меня точно такая же проблема.
Кен Уильямс,
@KenWilliams Ваша проблема также связана с html-режимом? Я думаю, что настоящая проблема здесь в том, что html-modeэто не пакет. По крайней мере, в моей текущей версии Emacs, html-modeэто определено в пакете sgml-mode. Поэтому, если вы скажете use-packageчто-то делать, когда html-modeзагружен пакет с именем, этот код никогда не запускается, потому что такой пакет никогда не загружается. Вам нужно поместить настройку html-режима в (use-package sgml-mode ....).
glucas
Извините - моя проблема с org-mode, а не html-mode. Аналогичная проблема заключается в том, что пакет вызывается org-mode, но вызывается пакет ELPA org. Может это смущает (или меня)?
Кен Уильямс,
7

Этот пример помог мне понять разницу между :initи :config. Давайте рассмотрим пример ace-windowпакета (но это может быть любой пакет). Поместите это в свой init.elфайл:

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

Теперь откройте свой emacs и посмотрите в *Messages*буфере, чтобы увидеть, есть ли какое-либо hello worldсообщение. Вы не сможете найти их, потому что пакет отложен. Теперь измените с configна init:

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

Теперь закройте и снова откройте emacs и осмотрите *Messages*буфер. Вы увидите сообщение, ace window: hello worldпотому что код запускается независимо от того, когда :initон задан. В случае этого configон будет запущен только тогда, когда этот пакет загружен.

Сиби
источник
это помогает, только побочный вопрос, в чем же разница между ключевым словом :initи :prefaceна основе вашего примера?
докторская степень
@doctorate: :prefaceзапускается, даже если данный пакет отключен, тогда как :initзапускается только при включенном пакете.
bbenne10