24

I have a configuration like this:

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

Now when I go and visit an HTML file, I observe that auto-fill is not turned off. But if I use :init instead of :config, auto-fill gets turned off. So my question is when are the commands under :config executed ?

Sibi
  • 3,603
  • 2
  • 22
  • 35

2 Answers2

27

They are different if the package is deferred, i.e. not loaded until it is needed. In that case :init will be executed at the time your emacs file is first read, but :config will be executed at the time the package is actually loaded.

In your example, the use of mode implicitly defers loading the package. You have configured the package to be loaded the first time an html file is visited.

You could use :demand to make sure the package is always loaded at startup, but more likely what you want to do here is put your hook in :init.

From the docstring:

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

Since you're putting this in your user-init file, that basically means it will run at startup.

:config Runs if and when package loads.

So, not run until the package is actually being loaded..

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

Note the list of things that automatically make a package deferred. Basically if you tell use-package the conditions in which you need this package, it assumes you don't want to load it until those conditions arise.

:demand Prevent deferred loading in all cases.

Make sure the package is loaded at startup, regardless of what other options you've specified.

Update

Revisiting this based on the recent comments... What I said above is all true, but I don't think it correctly answers the question. The root problem here is actually that html-mode is not a package, but rather a mode defined by the package sgml-mode. This works as expected for me:

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

In the original example, the :config expression never gets evaluated because a package named html-mode never gets loaded. Moving the same expression to :init works because init code is always evaluated, regardless of whether the package ever gets loaded.

glucas
  • 20,175
  • 1
  • 51
  • 83
  • 1
    See [Semantics of :init is now consistent](https://github.com/jwiegley/use-package/#semantics-of-init-is-now-consistent) – npostavs Mar 30 '15 at 18:04
  • @npostavs Thanks, worth noting. I haven't yet moved to use-package 2.0 myself. For one thing, I use `:idle` pretty extensively and haven't looked into the impact of ":idle has been removed". – glucas Mar 30 '15 at 19:24
  • 1
    I still don't understand why, when he visits an HTML file and triggers the package to load, `auto-fill` is not turned off, i.e. the config code didn't run. I have the same problem. – Ken Williams Oct 28 '15 at 15:10
  • @KenWilliams Your issue is with html-mode as well? I think the actual problem here is that `html-mode` is not a package. At least in my current version of Emacs, `html-mode` is defined in the package `sgml-mode`. So if you tell `use-package` to do something when a package named `html-mode` is loaded that code never runs because no such package is ever loaded. You need to put html-mode setup in a `(use-package sgml-mode ....)`. – glucas Oct 28 '15 at 15:33
  • Sorry - my issue is with `org-mode`, not `html-mode`. A similar issue there is that the package is called `org-mode`, but the ELPA package is called `org`. Maybe that's confusing it (or me)? – Ken Williams Oct 28 '15 at 16:16
  • Right - you'd need to `(use-package org :config ....)`, since org.el is providing the feature `org`. – glucas Oct 28 '15 at 16:59
  • I still couldn't figure it out, so I posted a new question: http://emacs.stackexchange.com/questions/17710/use-package-with-config-to-set-variables . Thanks for your help! – Ken Williams Oct 28 '15 at 22:58
11

This example made me much easy to understand the difference between :init and :config. Let's take an example of ace-window package (but this can be any package). Put this in your init.el file:

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

Now open your emacs and see in the *Messages* buffer to see if there any hello world message. You won't be able to find any because the package is deferred. Now change from config to init:

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

Now close and re-open emacs and inspect the *Messages* buffer. You will see the message ace window: hello world because the code is run no matter what when :init is given. In the case of config it will be only run when that package is loaded.

Sibi
  • 3,603
  • 2
  • 22
  • 35
  • 1
    that helps, just a side question, what is the difference then between the keyword `:init` and `:preface` based on your example? – doctorate Jul 14 '17 at 11:19
  • 2
    @doctorate: `:preface` is run even if the package in question is **disabled** whereas `:init` is only run when a package is enabled. – bbenne10 Jul 02 '18 at 12:31