use-layer
is a nicer way to write your .spacemacs
configuration file.
Under the covers, it is a use-package
rip-off, all the credit should go to
John Wiegley and contributors to the use-package
project. I merely
copy-pasted the core macro and tweaked it a bit.
The main goal is to provide a way to group all related configuration for a
layer in one single form, instead of spreading it out all over the
.spacemacs
file, much like what use-package
does for packages.
Another goal is to avoid disrupting the way the layer system currently works,
this is why use-layer
does not hook itself into any Spacemacs code, and must
explicitly be wired into your own configuration (see below for instructions).
It is a proof of concept, don’t use it in your own config just yet. I am currently gathering feedback to see if this a useful addition to the spacemacs repertoire, or merely just a personal preference.
Adding a layer to your Spacemacs configuration is currently
dotspacemacs-configuration-layers '(better-defaults)
With use-layer
:
(use-layer better-defaults)
This isn’t much better than what Spacemacs already does, honestly, but read on for more.
Spacemacs already has a way to configure layers with :variables
.
dotspacemacs-configuration-layers
'(
(auto-completion :variables
auto-completion-enable-sort-by-usage t)
)
use-layer
supports this through :def
(use-layer auto-completion
:def
(auto-completion :variables
auto-completion-enable-sort-by-usage t))
:def
ensures use-layer
is retro-compatible with Spacemacs: the :def
form is exported as-is, and any future addition to the
dotspacemacs-configuration-layers
grammar is supported.
Many packages do not have :variables
, but instead require you to put some code in dotspacemacs/user-config
.
dotspacemacs-configuration-layers '(mu4e)
(defun dotspacemacs/user-config ()
;; configure mu4e, cf. http://develop.spacemacs.org/layers/+email/mu4e/README.html
(with-eval-after-load 'mu4e-alert
;; Enable Desktop notifications
(mu4e-alert-set-default-style 'notifications)))
This a bit unfortunate, as now you have two places in your configuration that needs to stay in sync.
(use-layer mu4e
:user-config
(with-eval-after-load 'mu4e-alert
;; Enable Desktop notifications
(mu4e-alert-set-default-style 'notifications)))
Now, use-layer
does not help with the mu4e
layer’s expectations about
when functions should execute, but at least all the configuration is pulled
together under one form.
If a layer pulls in a package you don’t want, in Spacemacs you need to add it
to add it to dotspacemacs-excluded-packages
.
dotspacemacs-configuration-layers
'(eshell)
dotspacemacs-excluded-packages
'(vi-tilde-fringe)
Unfortunately, this means that some configuration, related to the
installation and configuration of the eshell
layer, is done somewhere else.
If you ever change your mind about using eshell
or excluding
vi-tilde-fringe
, will you remember why?
(use-layer eshell
:excluded-packages (vi-tilde-fringe))
This way, it is easy to remember months after writing this code that you
decided to exclude vi-tilde-fringe
when installing the eshell
layer.
Let’s say I want to install the eshell
layer, but not the eshell-z
package, and configure the fasd
layer to provide an alternative to z
.
In Spacemacs, this is configured in 3 different parts of the config file
(defun dotspacemacs/layers ()
(setq-default
dotspacemacs-configuration-layers '(eshell fasd) ;; <--- here (1)
dotspacemacs-excluded-packages ;; <--- here (2)
'(
;; exclude `eshell-z' because fasd has an implementation of `z' I like better
eshell-z
)))
(defun dotspacemacs/user-config () ;; <-- and here (3)
(defun eshell/z (&rest args)
(when args
(let ((cmd (s-join " " (-concat (list "fasd" "-dl1") args))))
(cd (s-chomp (shell-command-to-string cmd)))))))
But all of those variables and functions may contain unrelated configuration
for other layers, and it starts to become a mess. I guess you could create
your own eshell+fasd layer and use that, but I don’t think it’s worth it
maintenance-wise. use-layer
does not aim to replace layers, it makes it
easier to configure them in a maintainable way while still benefiting from
the community-configured aspects of Spacemacs. Or at least, that’s the
objective :)
Here is the same configuration using use-layer
:
(use-layer eshell)
(use-layer fasd
:excluded-packages (eshell-z)
:user-config
(defun eshell/z (&rest args)
(when args
(let ((cmd (s-join " " (-concat (list "fasd" "-dl1") args))))
(cd (s-chomp (shell-command-to-string cmd))))))
Which I believe is a better representation of the intent: when installing
fasd
, override eshell-z
with a different, user-defined eshell/z
function.
I made the conscious choice not to mess around with dotspacemacs-*
variables, so wiring use-layer
in your configuration is a bit more involved
than your typical package or layer install.
One issue is that this cannot be packaged as a MELPA recipe, because we need
to load use-layer
before Spacemacs reads it’s own config, a classic
chicken-and-egg situation.
Review the code and check that it does not do anything sketchy! this is the internet
Paste the code somewhere (I’ll assume in ~/.spacemacs.d/use-layer.el
)
;; This file is loaded by Spacemacs at startup.
;; It must be stored in your home directory.
(add-to-list 'load-path dotspacemacs-directory)
(require 'use-layer)
dotspacemacs-configuration-layers
(append use-layer-configuration-layers
'(
;; all your layers currently configured
helm
better-defaults
(auto-completion :variables
auto-completion-enable-sort-by-usage t)
eshell
fasd
))
dotspacemacs-excluded-packages
(append use-layer-excluded-packages
'(
;; all your packages currently excluded
eshell-z
))
(defun dotspacemacs/user-init ()
;; your current user-init code goes here
(run-hooks 'use-layer-init-hook)
;; or here
)
(defun dotspacemacs/user-config ()
;; your current user-config code goes here
(run-hooks 'use-layer-config-hook)
;; or here
)
(add-to-list 'load-path dotspacemacs-directory)
(require 'use-layer)
(use-layer better-defaults)
(use-layer auto-completion
:def
(auto-completion :variables
auto-completion-enable-sort-by-usage t))
;; ...
(defun dotspacemacs/layers ()
;; ...
dotspacemacs-configuration-layers
(append use-layer-configuration-layers
'(
helm
eshell
fasd
))
)
;; ..
(defun dotspacemacs/user-init ()
;; ...
)
(defun dotspacemacs/user-config ()
;; ...
)
There are not statistics, as it is assumed that Spacemacs should handle this.
use-layer
requires explicit use of progn
in :user-config
and
:user-init
. Etc.
I think the current implementation covers a fair bit of my use-cases, but what do you need? Currently, there is