A sensible starting point for hacking your own Emacs configuration.
Please note: rational-emacs
is under active development. While the intent
of this project is to provide a stable Emacs configuration for use by
anyone, it is not yet stable enough for everyday or production use. The
rapid pace of changes could cause your configuration to break on your next
pull of the repository. If you are not expecting or prepared to encounter
such issues, we would recommend you wait for things to stabilize a bit
before using.
Install emacs >= 27.2 from your distribution’s repositories.
Clone this repository to ~/.emacs.d
or ~/.config/emacs
:
git clone https://github.com/SystemCrafters/rational-emacs ~/.config/emacs
This will set up the minimal configuration. If you’d like a more fully-configured experience, see Customization.
This configuration and all associated modules intend to follow the below priniciples.
NOTE: Some of these may change over time as we learn from this process.
The core configuration only sets up Emacs to have a cleaner presentation with
sensible defaults. It is up to the user to decide which of the various
rational-*
modules to load and when to load them.
Configuration modules should depend on other modules and the base configuration as little as possible. When a configuration module needs to integrate with other functionality in Emacs, the standard extensibility points of each package should be used (instead of expecting our own configuration module).
The implication is that someone should be able to install or copy code from a
rational-*
module into their own configuration without using Rational Emacs.
Where possible, we will leverage built-in Emacs functionality instead of external packages, for example:
project.el
instead ofProjectile
tab-bar-mode
instead ofPerspective.el
,persp-mode
,eyebrowse
, etceglot
instead oflsp-mode
(becauseeglot
prioritizes built-in functionality)- Possibly
vc-mode
by default
Some people prefer to use Emacs in the terminal instead of as a graphical program. This configuration should work well in this case too! This also enables the use of Emacs in Termux on Android.
It should be possible to customize aspects of the Rational Emacs configuration inside of a Guix Home configuration so that things like font sizes, themes, etc can be system-specific.
It can also use packages installed via the Guix package manager instead of
package.el
.
Chemacs2
is an excellent tool for enabling the use of multiple Emacs
configurations simultaneously. This configuration will behave well when used
with Chemacs2
so that users can try and use different Emacs configurations as
needed.
Instead of providing a higher-level configuration system out of the box like other Emacs configurations, we follow standard Emacs Lisp patterns so that you can learn by reading the configuration.
Not everyone will agree with our decisions, so each customization should be
easily reversible in the users config.el
file.
Why choose this configuration over Doom Emacs, Spacemacs, Prelude, or others?
The goal of this configuration is to make it easier to write your own Emacs configuration while using pre-made configuration parts maintained by the community. Instead of using a monolithic, all-encompassing approach, we strive to ensure that all parts of this configuration are optional or interchangeable.
You should even be able to use the configuration modules we provide with your
own init.el
file without using this base configuration repo!
Here is a list of the built-in modules that you may load. They are located in
directory $RATIONAL_EMACS_HOME/modules
, which are in the directory your git
clone from listing li#git_clone. Follow the links to each to get more
information about how they can be configured!
- rational-defaults
- Sensible default settings for Emacs
- rational-use-package
- Configuration for
use-package
- rational-updates
- Tools to upgrade Rational Emacs
- rational-completion
- A better selection framework configuration based on
Vertico
- rational-ui
- Extra UI configuration for a better experience (mode line, etc)
- rational-windows
- Window management configuration
- rational-editing
- Settings for the editing component (whitespace trimming etc.)
- rational-evil
- An
evil-mode
configuration - rational-org
- A few tweaks to Org-mode (org-appear, clickable hyperlinks etc.)
- rational-project
- Built in project management alternative to
projectile
- rational-speedbar
- A file-tree
- rational-screencast
- Tools for doing screencasts
- rational-compile
- Set up automatic compilation for some emacs-lisp files
- rational-desktop
- A desktop environment centered around
EXWM
- rational-present
- Tools for giving presentations
- rational-workspace
- An improved workspace experience based on
tab-bar-mode
- rational-shell
- A starter configuration for
eshell
andvterm
To add your own customization to this configuration, create a configuraton file in one of the following directories:
~/.rational-emacs/
~/.config/rational-emacs/
Rational Emacs looks out for two configuration files in one of those places:
config.el
– General configuration. Here you can set any Emacs configuration variables, face attributes, themes, etc. In short: anything that would normally go intoinit.el
goes here.early-config.el
– Configuration that needs to happen early during Emacs startup (see “The Early Init File” in the Emacs Manual for details), like customizing the process of initializing the package system etc. In short: anything, that would normally go intoearly-init.el
goes here.
If you prefer to explicitly control where your config.el
and early-config.el
are found for Rational Emacs, you may provide a value for the
RATIONAL_EMACS_HOME
environment variable, either on the command line or in
your shell configuration. This variable should only contain the path to the
config.el
files, for example:
RATIONAL_EMACS_HOME=~/my-rational-emacs-config
The rational config files (config.el
and early-config.el
) are found in the
rational-config-path
. That path will match exactly one of the following
scenarios, in the order specified:
- Using
Chemacs2
(See below for more on this)- The environment variable
RATIONAL_EMACS_HOME
is used if provided in the profile definition. - The
rational-emacs
subdirectory of the profile is used when no environment variable is provided in the profile definition.
- The environment variable
- Use the value found in the
RATIONAL_EMACS_HOME
environment variable. - The environment variable
XDG_CONFIG_HOME
is present or the path$HOME/.config/rational-emacs
exists.- These normally resolve to the same file, so build the path from the
XDG_CONFIG_HOME
environment variable or the explicit path~/.config/rational-emacs
- These normally resolve to the same file, so build the path from the
- Use the
HOME
environment variable to make the path, which expands to$HOME/.rational-emacs
.
Once the rational-config-path
is determined, if it does not exist in the
filesystem, it is created. However, just the path is created, the files
config.el
and early-config.el
must be created by you.
To make use of the sensible defaults that Rational Emacs aims to provide, the first thing in your user configuration is to choose, which of the modules you want to use.
Let’s say for example, you want to have a look at all the modules, but you
don’t want to use evil-mode
and you have no use for the screencasting module.
Also, you need the advanced project management features of projectile, so you
don’t want built-in project management either. In that case, your example
config might begin like this:
(require 'rational-defaults) ; Sensible default settings for Emacs
(require 'rational-use-package) ; Configuration for `use-package`
(require 'rational-updates) ; Tools to upgrade Rational Emacs
(require 'rational-completion) ; selection framework based on `vertico`
(require 'rational-ui) ; Better UI experience (modeline etc.)
(require 'rational-windows) ; Window management configuration
(require 'rational-editing) ; Whitspace trimming, auto parens etc.
;(require 'rational-evil) ; An `evil-mode` configuration
(require 'rational-org) ; org-appear, clickable hyperlinks etc.
;(require 'rational-project) ; built-in alternative to projectile
(require 'rational-speedbar) ; built-in file-tree
;(require 'rational-screencast) ; show current command and binding in modeline
;; Further settings and customizations follow here...
;; ...
More detailed example config files can be found in the folder examples
.
The custom.el
file will hold the auto-generated code from the Emacs
Customization UI, and other packages that similarly add code to the variables
and faces form in the init.el
file.
Customizable values are defined with the defcustom
form, and can be
customized using the Easy Customization UI. A complete discussion is out of
scope for this document, instead see the Emacs Manual for more information.
There are several states a value can be in, for our purposes, we will only
consider two of them: the default state and the changed state. These are not
the “official” names but easily convey the concepts of the variable. If a
value is in the default state, looking in the Customization UI, the state
will be listed as STANDARD
. Rational Emacs takes the approach of using the
customize-set-variable
to update the values defined with
defcustom
. This will show the values as SET for current session only
in
the Customization UI. This is normal since the values are set each time
emacs starts. They are technically “SAVED” since they exist as emacs-lisp
code, but since they are not in a custom-set-variables
form the
Customization UI only sees them as “SET for the current session only”.
A SAVED and set
value means the Customization code has written the
configuration to disk to be loaded again the next time Emacs starts. When
Emacs saves the configuration from the Customization UI, it simply adds a
couple of forms to the end of your initialization file (typically
init.el
), with comments warning about having more than one form with the
same name:
(custom-set-variables
;; custom-set-variables was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
'(rational-ui-default-font '(:font "JetBrains Mono" :weight light :height 185))
'(rational-ui-display-line-numbers t))
(custom-set-faces
;; custom-set-faces was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
)
When rational-load-custom-file
is non-nil (the default), the custom.el
file is loaded after the initialization process, including after the user
config.el
is loaded.
The customization variable values (as set in init.el
with
customize-set-variables
) are in the SET for current session only
state,
unless altered by a saved customization loaded from custom.el
. Any values
set through the Customization UI or other work flows, for example by using
the org-agenda-to-front
or org-remove-file
functions, which write to the
custom-set-variables
form, are preserved in the custom.el
file if they are
saved for future sessions (as by the Customization UI widget, or by code).
To not load the custom file
, change the value for the
rational-load-custom-file
to nil
in your config.el
.
Using customize-set-variable
in Emacs Lisp has the same effect as using
the Customization UI, except the customization is not saved to custom.el
as if you had used the Customization UI and used the widget to save the
customizations for future sessions.
If you choose to follow this pattern, customizing variables in your
config.el
only (not using the UI) then you may never need to load
custom.el
. However, there are some caveats: using certain work flows with
Org Agenda files or risky variables in .dir-locals.el
which write to the
custom.el
file will never be applied, even though they are saved in the
custom file.
If you have the Chemacs2
configuration cloned to ~/.emacs.d
or
~/.config/emacs
, you can clone rational-emacs
anywhere you like and add an
entry to it in your ~/.emacs-profiles.el
file:
You can then put your early-config.el
and config.el
files in the subfolder
~/path/to/rational-emacs/rational-emacs
. So, for example if you installed
Rational Emacs to ~/.rational-emacs
, then your early-config.el
and
config.el
files would be in the path ~/.rational-emacs/rational-emacs
. This
is the default path, but you can change the name to something else, see below
for examples.
(("rational" . ((user-emacs-directory . "~/path/to/rational-emacs"))))
If you prefer to put your Rational Emacs customizations elsewhere (for example
in a folder called `config` or maybe `personal`), you can specify the
RATIONAL_EMACS_HOME
environment variable, for example like this:
(("rational" . ((user-emacs-directory . "~/path/to/rational-emacs")
(env . (("RATIONAL_EMACS_HOME" . "~/path/to/rational-emacs/personal"))))))
Or some place completely different:
(("rational" . ((user-emacs-directory . "~/path/to/rational-emacs")
(env . (("RATIONAL_EMACS_HOME" . "~/rational-config/personal"))))))
Then launch it with emacs --with-profile rational
!
This is a community-run modular Emacs configuration, for which we appreciate feedback in the form of issues and pull requests. Feel free to open an issue prior to opening a pull request if you’re not certain your idea is in the spirit of the Principles.
If you enjoy crafting your computing experience, join the SystemCrafters community!
- Prefer
customize-set-variable
instead ofsetq
fordefcustom
values. This helps make sure constructors or setters attached to the variable are run when the value is set. - Provide
defcustom
variables for things we expect the user to modify and make sure it is in the appropriate group. - Provide verbose doc-strings for
defvar
,defcustom
,defun
,defmacro
, etc to clearly document what is going on. - Make sure to follow doc-string guidelines (see Documentation Tips or <a href=”info:elisp#Documentation Tips”>elisp#Documentation Tips)
- Add comments for blocks of code, especially to describe why the code is present, or the intention. These comments serve as documentation when reading the code where a doc-string is not an option.
- Add or update documentation in the docs folder. Especially for new modules, please provide the info file with your PR. (see Contributing Documentation)
- If your PR addresses an issue, whether it closes or fixes the issue, or is just related to it, please add the issue number in your commit message or the description of your PR so they can be linked together.
We welcome your questions and ideas, please open an issue if you have one!
- If you feel there is a defect with what we provide, please provide the steps necessary to reproduce the issue. A minimal configuration, a link to your configuration, or a gist/pastebin link or similar is appreciated to help us work toward a solution together.
- If you feel there is a missing feature, please describe your feature in as much detail as possible so we understand your request.
- If you have a question, be as specific as possible so we can understand how to help you as best we can.
- PRs to address any of the issues you might raise are appreciated and encouraged! If you don’t provide one, please be patient with us, it may take longer to fix an issue or provide a missing feature. That being said, please feel free to check on the status of issues from time to time if it has been a while since the last activity.
Some tips when things don’t seem to work right.
This scenario happened frequently when upgading to Emacs 28. It also may occur in other scenarios as well. Usually, you will see some message indicating some symbol is void or some function or command does not exist. More often than not, the package maintainer is using a feature from another package which has not yet been released. The new feature is available in the development version of the package however.
Here are some example issues where things went wrong:
- Wrong number of arguments error
- Example config doesn’t start
- there are some bugs in package “helpful”
Here are some strategies:
- Check the code on the package source control page (ie GitHub, GitLab or
whatever), and make sure the missing code is present on the
master
branch. - Look at the code associated with the released version (you need to look at the most recent tag for this). If the code is missing there, ask the maintainer for a new release. Often, there are years between releases of Emacs packages, but that depends completely on the package maintainer. Some of them release more frequently, others only on request.
Once you have done the steps above, you can choose to take one of these actions in your configuration:
- Option 1
- Use
M-x package-list-packages
to display the list of packages. - Find the package in the list which doesn’t work for you, it will have either the installed or dependency status.
- Press the
enter
key to get more details on the package an look near the bottom of the metadata, you should see a line with “Other Versions”. Choose the development version - it will have a version number that looks like a date and the text(melpa)
next to it. Pressenter
on this version. - Following the step above will take you to the same package but from the
MELPA repository, and you’ll see a button at the top labeled
Install
. Click this button. - Optionally you can go back to the list of packages, find previous installed version, press the letter ‘D’ and then the letter ‘X’ to uninstall that version.
- Restart Emacs
- Use
- Option 2
- Edit your
early-config.el
file. - Near the bottom, add a line similar to this to pin the offending package
to MELPA (make sure to replace package-name with the name of the actual
package):
(add-to-list 'package-pinned-packages (cons 'package-name "melpa"))
- Use
M-x package-list-packages
to display the list of packages. - Find the package in the list, press the letter ‘D’ and the letter ‘X’ to uninstall that package.
- Restart Emacs, the package should be installed from MELPA thus using the development version of the package instead of the released version.
- Edit your
Regardless, always feel free to open an issue here and we can help you
out. Please be as complete as possible in your description of the
problem. Include any stack traces Emacs provides (ie start Emacs with: emacs
--debug-init
), mention the version number of the package you are installing,
and anything you might have tried but which didn’t work for you.
This code is licensed under the MIT License. Why? So you can copy the code from this configuration!