First, we need to make sure we are starting with a clean slate.
If you are starting from scratch, but have started Emacs already, you probably already have generated some amount of configuration files. For more information: Init File, or on the web: Init File. If you’re on Windows, also see Windows HOME, or on the web: Windows HOME.
You must decide if you wish to remove them or rename them to something else.
If you aren’t starting from scratch, then you probably have some configuration already working and you want to add or use some of the configuration found in Crafted Emacs. You probably have to adapt and rewrite parts of your configuration to work with Crafted Emacs.
Wherever you decide to put your Emacs configuration will be known as
user-emacs-directory
for the rest of this guide.
To use Crafted Emacs, you will need to download the repository. It is up to you where you clone to. If you are not sure where to clone to, you can use your home directory.
git clone --depth 1 https://github.com/SystemCrafters/crafted-emacs
For the rest of this guide, the location where you cloned Crafted Emacs to will
be known as crafted-emacs-home
.
After cloning the crafted-emacs repository, we need to let Emacs know how to load Crafted Emacs.
The Emacs startup process has several steps, more than what will be
discussed here. We will briefly cover the early-init.el
file which Emacs
allows user to affect some configuration options which occur before Emacs
draws the initial frame (often known as the “window” in a graphical
windowing system). For more information on early-init.el
see
Early Init File, or on the web: Early Init File.
For our purposes, this is where we initialize the package system.
In the user-emacs-directory
:
- Create a file called
early-init.el
- Add this single line of code (which assumes the
crafted-emacs-home
is thecrafted-emacs
directory found in your home folder):
(load "~/crafted-emacs/modules/crafted-early-init-config")
Loading crafted-early-init-config
will do the following:
- Setup the
package-archives
list to include the following list of package repositories:- GNU Elpa: Contains packages which are licensed under the GNU GPL (GNU General Public License) and for which the author has signed the copyright release to the Free Software Foundation. The package archive is maintained by the GNU Emacs maintainers.
- Non-GNU Elpa: Contains packages which are licensed as free software and for which authors have not signed the copyright release required for GNU Elpa. Authors must however follow a list of rules for package submission. The decision to include a package is left to the discretion of the GNU Emacs maintainers.
- MELPA Stable:
MELPA is a community-authored package archive with a wide range of
packages available.
The stable repository contains packages which have a
version tag in their
git
repository. These are pulled and built on a regular basis as needed when the tag version changes. - MELPA:
Like MELPA Stable, but packages are based on the latest commit
in the respective
git
repository (essentially, development versions). These will have version numbers similar to this:20210701.839
which is essentially a date stamp when the package was built.
- Prioritize the list of package repositories to be in the order listed above. This means, we prefer to get packages from GNU Elpa first, if not found, then try the next repository down the list, finally trying to get the package from MELPA as a last resort. This is because Crafted Emacs prefers released versions, if available, for all packages installed.
- Check to make sure the repository cache archives are up-to-date,
and update if needed. This check is performed when Emacs is
starting, and will check to see if the repository cache is older
than one day. To check less frequently, set the variable
crafted-package-update-days
to a higher value. To not perform the check at all, set thecrafted-package-perform-stale-archive-check
variable tonil
.
Once Crafted Emacs is up and running, no stale checks are made. Thus, if you run
Crafted Emacs for several days without restarting Emacs, you’ll need to refresh
the package repository archive caches manually. This is done automatically when
running package-list-packages
.
Outside of special use-cases, this single line of code will be
your entire early-init.el
file.
The init.el
file is where most of the work of configuring Emacs will
occur. Let’s start by creating the init.el
file in your
user-emacs-directory
and add this code:
(setq custom-file (expand-file-name "custom.el" user-emacs-directory))
(when (and custom-file
(file-exists-p custom-file))
(load custom-file nil :nomessage))
Emacs customization is largely a matter of setting the values of certain
variables. The Emacs customization system will store these in the file known as
the custom-file
which defaults to your initialization file, in this case called
init.el
. We’d rather keep that separate from what we are doing in the init.el
file as that code is auto-generated by Emacs. In a sense, it is a duplication of
the work we will be doing as the values we set programmatically will also be
stored in this file and loaded by the code above.
For more information on the custom-file
see Saving Customizations,
or on the web: Saving Customizations.
Right below the custom-file
setup, add the following line (which assumes
the crafted-emacs-home
is the crafted-emacs
directory found in your
home folder):
(load "~/crafted-emacs/modules/crafted-init-config")
In a rough outline, the crafted-init-config
:
- sets up the load-path, so code from
modules
andcustom-modules
can be loaded withrequire
- sets up the
info
system to make this documentation accessible from within Emacs’ info buffer - ensures all customizations and packages are saved to the
custom-file
These lines define the top of our init.el
, everything else will be put
below.
Now that you have bootstrapped Crafted Emacs, you can start configuring Emacs using Crafted Emacs Modules.
The standard approach to finding and installing packages is to use the command
M-x list-packages
, which will bring up a user interface to search for
packages, review the package details, install, update or remove package. For
more information: Packages or on the web: Packages.
Crafted Emacs uses the selection facilities for batch-installation of packages.
This means all packages are added to a list (namely package-selected-packages
)
and installed at once.
;; Example: Adding "vertico" to the package-selected-packages list (init.el)
(add-to-list 'package-selected-packages 'vertico)
Additionally, Crafted Emacs provides a few modules which are bundled together
packages for installation. Each of these modules simply adds one or more package
names to the package-selected-packages
list, for example:
;; snippet of crafted-completion-packages.el:
;; not all package names are shown here, the list is shortened for
;; brevity.
(add-to-list 'package-selected-packages 'cape)
(add-to-list 'package-selected-packages 'consult)
(add-to-list 'package-selected-packages 'corfu)
After all packages are selected, they are installed at once with
package-install-selected-packages
. Adding packages after this line will not
install them.
;; adding the `:noconfirm' flag will cause all the packages listed in
;; the `package-selected-packages' variable to be installed without
;; prompting you to confirm that choice.
(package-install-selected-packages :noconfirm)
There are two types of modules provided by Crafted Emacs.
- Package modules (bundle together multiple packages for installation)
- Configuration modules (configuration for multiple packages)
The module definitions can be found in crafted-emacs-home/modules/
.
As explained earlier in the guide, you can add packages manually using
add-to-list
. Additionally, Crafted Emacs provides a few modules which are
bundled together packages for installation. Each of these modules simply adds
one or more package names to the package-selected-packages
list. The bundles of
packages are split up by logical categories (ui, completion, writing, …).
To load one of these bundles, use:
;; Add package definitions for completion packages
;; to `package-selected-packages'.
(require 'crafted-completion-packages)
;; install selected packages (as shown earlier)
(package-install-selected-packages :noconfirm)
To list all the available package bundle available, you can run:
# In a shell/term from the crafted-emacs-home directory
ls ./modules/*-packages.el
The configuration code provided by Crafted Emacs is to be loaded after installing all the packages.
;; install selected packages
(package-install-selected-packages :noconfirm)
;; load configuration for the completion packages
(require 'crafted-completion-config)
It should be noted that the package definitions are not required to use the configuration. You can manually add a subset of packages, the configuration code will only apply the configuration for those packages:
;; Only select vertico from the crafted-completions module.
(add-to-list 'package-selected-packages 'vertico)
;; install selected packages
(package-install-selected-packages :noconfirm)
;; Load configuration for the completion packages.
;; This will only apply the vertico section of the configuration module.
(require 'crafted-completion-config)
To list all the available configuration modules, you can run:
# In a shell/term from the crafted-emacs-home directory
ls ./modules/*-config.el
The example assumes you have cloned crafted-emacs to your home directory.
Example early-init.el
:
;; Set up package archives
(load "~/crafted-emacs/modules/crafted-early-init-config")
Example init.el
:
;; Set up custom.el file
(setq custom-file (expand-file-name "custom.el" user-emacs-directory))
(when (and custom-file
(file-exists-p custom-file))
(load custom-file nil :nomessage))
;; Bootstrap crafted-emacs in init.el
(load "~/crafted-emacs/modules/crafted-init-config")
;; Add package definitions for completion packages
;; to `package-selected-packages'.
(require 'crafted-completion-packages)
;; Manually select "ef-themes" package
(add-to-list 'package-selected-packages 'ef-themes)
;; Install selected packages
(package-install-selected-packages :noconfirm)
;; Load configuration for the completion module
(require 'crafted-completion-config)
See the examples
folder in the git-repo for more examples.
Crafted Emacs generally groups modules into pairs of files, one for
enabling/installing helpful packages, and the other for applying
configuration. If you want to use both the configuration file and packages file
for every Crafted Emacs module, you end up with quite a few require
statements.
You might instead prefer this handy helper function that requires both the config and packages files for every module:
(defun crafted-emacs-load-modules (modules)
"Initialize crafted-emacs modules.
MODULES is a list of module names without the -packages or
-config suffixes. Note that any user-provided packages should be
added to `package-install-selected-packages' before invoking this
function."
(dolist (m modules)
(require (intern (format "crafted-%s-packages" m)) nil :noerror))
(package-install-selected-packages :noconfirm)
(dolist (m modules)
(require (intern (format "crafted-%s-config" m)) nil :noerror)))
Drop this function into your init.el
and then use it to require your Crafted
Emacs modules. This replaces any existing (require 'crafted-...)
statements that
you may already have in your configuration:
;; Any extra packages in addition to the ones added by crafted-emacs
;; modules go here before we call `crafted-emacs-load-modules'.
(customize-set-variable 'package-selected-packages '(ef-themes magit))
(crafted-emacs-load-modules '(defaults completion ui ide))
The function crafted-emacs-load-modules
avoids the “-packages” and “-config”
suffixes by using two tricks. The first is an alternative form of require
, using
the fourth argument :noerror
to avoid erroring when a module symbol isn’t
found. This is helpful when a Crafted Emacs module has one of “config” or
“packages”, but not both.
The second trick takes a Crafted Emacs module name, like ide
, and expands it
into its complete feature name, crafted-ide-config
. Format string handles
interpolation for us, expanding the initial name into a string
"crafted-ide-config"
. However, require
expects a symbol, so the string returned
by format
must be turned back into a symbol via the intern
function.
As described previously, by default Crafted Emacs will save both the list
package-selected-packages
and all customizations to your customization file
(e.g. custom.el
).
You can customize that, too. To change that behaviour, add one or both of the following lines to your config:
(customize-set-variable 'crafted-init-auto-save-customized nil)
(customize-set-variable 'crafted-init-auto-save-selected-packages nil)
Whether or not to save these settings to custom.el
is ultimately a matter of
personal preference. You probably won’t notice a difference either way.
In the case of the customizations, we call the function
customize-save-customized
under the hood, which is originally intended for users
who use the Customization UI to try out a bunch of settings and then decide to
conserve the state of their Emacs session. If you are such a user, you still
have to run customize-save-customized
manually, because the settings above save
the customizations during startup (via the after-init-hook
). So it saves the
customizations that are already present in your configuration.
So why did we turn that on, if it’s redundant? It has to do with another use of the customization file:
When you want to leave Crafted Emacs behind, your customization file will
reflect much of your present settings. In particular, it will contain the
settings that you haven’t added to your config yourself, but that stem from some
Crafted Emacs module. So to leave Crafted Emacs behind, you don’t need to go
through the code of the modules and consider all the ifs and whens we had to
consider for different users. You can see the resulting settings for you. It’s
all there in you customization file. Combine it with the stuff you added
yourself and you have the basis for your new init.el
.
True, to achieve that, these customizations don’t need to be saved every
session. When you decide to leave Crafted Emacs behind, you can just run
customize-save-customized
and package--save-selected-packages
manually and
achieve the same result. But we want to make it as easy as possible for users to
leave Crafted Emacs behind. And as it doesn’t have any noticeable effect on
startup time, we just do it automatically every session and even spare you the
need to run those two functions.
Still, if you prefer not to save customizations and/or the list of selected packages during each startup, you can turn that behaviour off as described above.
Please note: These variables only affect whether Crafted Emacs will or won’t
automatically store anything set by customize-set-variable
, but that doesn’t
hinder other processes in Emacs to do so.
Congratulations, Crafted Emacs is now set up for you to start your configuration.
Here are some pointers to get you started:
- For more details on Crafted Emacs Modules: Modules
- For more information and explanations on customizing Emacs: Customization
- Want to use a different package manager? See Using alternative package managers