Is there any rule by which the user can determine whether the package configuration requires :init or :config?

up vote 12 down vote accepted

Is there any rule by which the user can determine whether the package configuration requires :init or :config?

There is no general rule which applies to all settings and packages; you just need to familiarise yourself with the meaning of these keywords by reading the README file of use-package.

In summary, the :init block is run at startup, as if you had placed its constituent forms at the top-level (i.e. outside of a typical call to use-package) of your user-init-file. This means they are always run, regardless of whether the corresponding package has been loaded or not.

The :config block, on the other hand, is run after the corresponding package has been loaded, by way of the eval-after-load mechanism.

As such, you can improve your startup time by moving applicable long-running settings from :init to :config. If you need to modify a variable which is only defined after loading a particular package, you similarly need to place this in the :config block. Some variables, such as gnus-home-directory, need to be set before their corresponding package is loaded, so they should be placed in :init. I strongly advise putting all applicable add-hook/remove-hook calls in the :init block, as hooks can be modified even when unbound, and this affords more modularity to your setup.

You can often avoid having to figure out where to place a particular setting by using the new :custom keyword, or by using the Easy Customization interface directly.

I am not sure if there is a general rule (apart from "use :init for preconfiguration before actual package loading and use :config for other, well, configuration").

But I for myself use :init when, for example, I want to add some other mode map keybindings to use functions from "this" package. And still want "this" package to be lazy loaded.

Here is the example of lazy loading of dired-ranger:

(use-package dired-ranger
  :commands (dired-ranger-copy dired-ranger-paste dired-ranger-move)
  :init
  (add-hook 'dired-mode-hook
            (lambda ()
              (define-key dired-mode-map (kbd "M-w") 'dired-ranger-copy)
              (define-key dired-mode-map (kbd "C-y") 'dired-ranger-paste)
              (define-key dired-mode-map (kbd "C-c C-y") 'dired-ranger-move))))

P.S.: If there is no :defer, :commands, :mode and others that makes package loading lazy, then :init and :config should be more or less the same (but :init will be evaluated earlier :) )

  • 4
    Modifying key bindings in a mode hook means they are run every time you open a buffer in that mode. You only need to modify key bindings once, after the package is loaded. You can use the :bind keyword for this, or modify the key bindings in the :config block. – Basil Feb 27 at 14:29
  • Indeed, never thought about it. But :config is too late -- lazy loading will not apply my bindings. And :bind with :map doesn't actually bind it. – Maxim Kim Feb 27 at 17:38
  • 2
    :config is not too late - that's exactly when dired-mode-map is first defined. You're probably just putting it in the wrong use-package form of dired-ranger instead of dired, where dired-mode-map is defined. This might also explain why your :bind does not work. Basically, either you are doing something wrong or use-package has a bug. Do not confuse local keybindings and eval-after-load with global keybindings of autoloaded commands/keymaps. – Basil Feb 27 at 17:55
  • @Basil, thx, you're right. My problem was that I have set use-package-always-ensure and when I try to use-package dired it fails to fetch it from elpa. But having :ensure nil there solves the problem and I can set up chained package loading dired -> dired-ranger using :after. – Maxim Kim Feb 28 at 6:47

Your Answer

 
discard

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.