Doom-emacs: Understanding how to efficiently setup packages.

Created on 10 Oct 2017  路  2Comments  路  Source: hlissner/doom-emacs

After reading through the docs I'm still a bit confused on how to properly load packages. I have noticed an increase in emacs loading time (1s --> 3s) after having added 5 packages.

My private module for doom is version controller here... but I'm mostly wondering - when to use the package! and use-package! macros.

Currently I'm doing the following in packages.el

;; -*- no-byte-compile: t; -*-
;;; private/tees/packages.el

(package! rjsx-mode)
(package! doom-themes)
(package! prettier-js)
(package! browse-at-remote)
(package! yaml-mode)
(package! markdown-mode)


;; This might be slowing boot ... should make this happen on hooks?
(use-package! rjsx-mode        :demand t :config)
;; (use-package! doom-themes      :demand t :config) ;; I think this is already installed
(use-package! prettier-js      :demand t :config)
(use-package! browse-at-remote :demand t :config)
(use-package! yaml-mode        :demand t :config)
(use-package! markdown-mode    :demand t :config)

I noticed that if I don't use :demand a package is not available in M-x.

I'm super new to configuring emacs, but having lots of fun with this. So if you see anything that could be improved let me know...

Thanks for your time and all your hard work!

discussion elisp resolved

Most helpful comment

...when to use the package! and def-package! macros.

The two have very different purposes. A module can have a packages.el and a config.el, so: _only_ use package! in the former and use-package! in the latter.

package! is declarative: meant only for telling Doom what this module's dependencies are (and optionally, where to find them).

use-package! is for configuring plugins and describing to Emacs when (and how) to load them. It is a thin wrapper around use-package. It accepts the same arguments. It is tremendously helpful; I suggest you get to know it better.

I hope that sheds some light on the two!


About your packages.el file: first of all, those use-package! blocks don't belong there, they belong in config.el.

Second, with the exception of prettier-js, those plugins are already present in Doom (so long as you have their respective modules enabled in ~/.emacs.d/init.el

  • rjsx-mode: this is already set up in lang/javascript
  • yaml-mode: in lang/data
  • markdown-mode: in lang/markdown
  • browse-at-remote: Doom uses git-link instead, in feature/version-control; which, so far, seems more reliable than browse-at-remote. The module exposes two relevant commands:

    • +vcs/git-browse: opens the current file+selection in github/bitbucket/gitlab/etc

    • +vcs/git-browse-issues: opens the issue tracker for the current project

    • There are no default bindings for these two, but if you use evil-mode, the :gbrowse and :gissues commands execute them.

Third, Doom sets use-package-always-defer to true. This means plugins defined with def-package! aren't loaded immediately. :demand t tells use-package to do the opposite: load this plugin now! It is expensive to load plugins proactively at startup, so look into use-package. It provides a variety of options for lazy loading a plugin. Here's a snippet of rjsx-mode's config, taken from lang/javascript, for instance:

(use-package! rjsx-mode
  :commands rjsx-mode
  :mode "\\.jsx$"
  :mode "components/.+\\.js$"
  ;; [...]
  )
  • :mode tells Emacs to autoload the plugin when a file matching "*.jsx" or "components/*.js" is opened.
  • :commands is a list of functions (or just one, in this case) that belong to that package. This makes these functions (like rjsx-mode) available to M-x. In any case, if you call rjsx-mode before the plugin is loaded, Emacs will know where to look for it.
  • There are others, like :after, :interpreter, and :magic. :defer N, too, which will load the plugin after N seconds. Use-package is neat!

Anyhow, I hope that helps! Feel free to ask if you have more questions.

All 2 comments

...when to use the package! and def-package! macros.

The two have very different purposes. A module can have a packages.el and a config.el, so: _only_ use package! in the former and use-package! in the latter.

package! is declarative: meant only for telling Doom what this module's dependencies are (and optionally, where to find them).

use-package! is for configuring plugins and describing to Emacs when (and how) to load them. It is a thin wrapper around use-package. It accepts the same arguments. It is tremendously helpful; I suggest you get to know it better.

I hope that sheds some light on the two!


About your packages.el file: first of all, those use-package! blocks don't belong there, they belong in config.el.

Second, with the exception of prettier-js, those plugins are already present in Doom (so long as you have their respective modules enabled in ~/.emacs.d/init.el

  • rjsx-mode: this is already set up in lang/javascript
  • yaml-mode: in lang/data
  • markdown-mode: in lang/markdown
  • browse-at-remote: Doom uses git-link instead, in feature/version-control; which, so far, seems more reliable than browse-at-remote. The module exposes two relevant commands:

    • +vcs/git-browse: opens the current file+selection in github/bitbucket/gitlab/etc

    • +vcs/git-browse-issues: opens the issue tracker for the current project

    • There are no default bindings for these two, but if you use evil-mode, the :gbrowse and :gissues commands execute them.

Third, Doom sets use-package-always-defer to true. This means plugins defined with def-package! aren't loaded immediately. :demand t tells use-package to do the opposite: load this plugin now! It is expensive to load plugins proactively at startup, so look into use-package. It provides a variety of options for lazy loading a plugin. Here's a snippet of rjsx-mode's config, taken from lang/javascript, for instance:

(use-package! rjsx-mode
  :commands rjsx-mode
  :mode "\\.jsx$"
  :mode "components/.+\\.js$"
  ;; [...]
  )
  • :mode tells Emacs to autoload the plugin when a file matching "*.jsx" or "components/*.js" is opened.
  • :commands is a list of functions (or just one, in this case) that belong to that package. This makes these functions (like rjsx-mode) available to M-x. In any case, if you call rjsx-mode before the plugin is loaded, Emacs will know where to look for it.
  • There are others, like :after, :interpreter, and :magic. :defer N, too, which will load the plugin after N seconds. Use-package is neat!

Anyhow, I hope that helps! Feel free to ask if you have more questions.

@hlissner thank you for such a detailed answer. That definitely clears thing up a lot. I had no idea most of those packages were already in Doom ha!

As for the example for rjsx-mode -- that illuminates much. I'm guessing that if I wanted to, say, have all js files in a folder called app I could similarly create a similar (use-package!) call, borrowing from the build in lang/javascript where I could override when the mode is invoked.

This has been a lot of fun for me, coming from spacemacs and learning more elisp and actually (kind of) knowing what's going on; so the details are much appreciated.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Ptival picture Ptival  路  3Comments

oyarsa picture oyarsa  路  3Comments

laishulu picture laishulu  路  3Comments

governorgoat picture governorgoat  路  3Comments

randomizedthinking picture randomizedthinking  路  3Comments