Rational Emacs!
There is a new project in town! It is called Rational Emacs and is intended to be a sensible starting point for configuring Emacs. I've been contributing to it for a bit (along with many others, of course), and I have learned a few things along the way.
Project Principles
I'm particularly attracted to the principles behind this project. It's always good to start with some basic ideas around how to approach things:
- Minimal, modular configuration. The intent with this is to provide modules that can be independently included and provides as little as possible for configuration.
- Prioritize built-in Emacs functionality. I love this! The idea is to use very few external packages, and the ones to use should be chosen for their enhancement of core features rather than complete rewrites. The examples are:
project.el
instead ofProjectile
tab-bar-mode
instead ofPerspective.el
or otherseglot
instead oflsp
as it is built to leverage built-in functionality.corfu
instead ofcompany
- And the list goes on.
- Works well in the terminal. As some people prefer the terminal, or have no option (for example, over an ssh connection), this should still work well.
- Helps you learn Emacs Lisp. This is a great feature! Things should (ideally) be consistently and clearly written so it is possible to understand what is going on in the configuration.
For myself, I really resonate with these ideas. My own configuration has been growing more and more towards these principles for a while. I stopped using use-package
because I wanted to figure out how to manage packages and configuration without macros hiding that from me. I still am using a lot more packages that are not quite that close to core Emacs, but that will be changing soon.
For the things I've contributed, I've tried to keep things reversible as well. So, whatever configuration I provide, the eventual user should be able to easily reverse or override that decision with one of their own.
The Journey So Far
There was an initial flurry of activity the first week and a lot got done quickly. I think for the most part, the community of people participating have agreed on just about everything. The discussions have been super interesting, insightful, and thought provoking. There has been a lot to gain from just reading people's posts on issues and pull requests. It's a very rich field full of diversity!
The second and third weeks have seen much less activity. Life happens, and this project isn't the highest priority for the maintainer. Inevitably, things have slowed to a temporary halt. I'm sure additional people will eventually be added to list of maintainers, but for the moment, we are a little bit stalled.
Stuff I've Learned
There is so much, I'm not sure I'll capture it all here.
- Skeleton and Tempo are interesting replacements for the venerable Yasnippets package, and both are built-in. Neither are documented very well (at all!) but reading the code was interesting and then providing a skeleton for “rational modules” was fun.
- Tempel is a nice enhancement to tempo.
- Corfu as a Company replacement is quite nice. Sometimes I like the way company automatically pops up a list of completions, and sometimes I don't. With corfu, I have to remember to press the
TAB
key to get the menu, which, in most cases, I do like. I used a different key with company, butTAB
works for me. - Abbrev and dabbrev are still relevant. I have used these in the past, but found yasnippets to be more approachable and functional. Add tempo/tempel and suddenly these come back to life. Who knew?
Still learning my way around with these (and other) tools already built-in to Emacs, but I don't see that I'm any less productive using them and it didn't take any time (for me) to embrace them fully.
Straight vs Package
I think one of the fun things about this project is I don't quite agree with one of the decisions. I don't think it is a bad decision, I just think it is one of the corner cases that doesn't quite line up with the principles. That decision is the one to use straight.el
rather than package.el
. The latter is built-in to Emacs and the former is not. Today, I tried to see what it would take to override that decision in my personal configuration. Turns out, it wasn't so difficult as to be impossible. My configuration of package.el
takes advantage of a lot of things that aren't well known; for example elpa priorities and pinned packages. The hard part, though, has to do with performance. I did manage to get it to load Emacs a little faster than using straight.el
, but only barely. The key was not calling package-refresh-contents
on startup1.
Using straight.el
is a big win in a couple places:
- No automatic package loading and activation; it only loads the packages you choose to configure. So, you could have something installed you aren't using and
straight
won't load that package. There is a way to do something similar withpackage
and I leverage that configuration, but it's not the default as it is withstraight
. - No need to call
package-refresh-contents
to download a list of packages. This is done when you installstraight
and it gets updated intelligently. This is a bit more of a conundrum withpackage.el
as you need to callpackage-refresh-contents
at least once before you can actually install packages, especially since we are adding more than just the “gnu” elpa to the list of sources from which to get packages. You also don't want to call that function everytime Emacs loads. There is a way to handle it, but it does complicate things a bit andstraight.el
is, well, pretty straight forward. - You can freeze versions and make your configuration reproducible with exactly the same package code on multiple machines. That is harder to do with
package.el
but possible. Withstraight
, it's just a call tostraight-freeze-versions
.
There is a lot more to it than all that which makes straight
a cool tool to use.
On the cons side of things though, there are at least these:
- No interface to see what you have installed. Using
list-packages
, you won't see any of the packages you installed withstraight
. You can sorta figure it out usingdired
on theuser-emacs-directory/straight/build
path, but you won't see what versions are installed or if anything needs to be updated. - It is not built-in, which seems to be in conflict with the aforementioned Project Principles.
While it seems like I have gone on a rant about it, I do indeed like straight.el
and I don't think its use in this project is wrong. We can make the choice to use it as the benefits outweigh the costs, at least for a given target audience.
Target Audience
I'm not exactly sure who the target audience is. You could say, it is anyone who wants to use Emacs. I'm not sure that would be accurate though. Any new user coming to Emacs may not want to use Rational Emacs as a first attempt at configuring their Emacs. In theory, they could… just need to create a config.el
file and use require
statements to pull in the modules they want and they get a rational set of minimal defaults out of the box (see the example-config.el
from the project repo as an example). Much more than that though… like adding additional packages or (re)configuring some of the packages we install will require some Emacs Lisp knowledge. That, to me, makes it seem like we are targeting someone who has used Emacs for long enough to not be scared away by having to type lisp as the configuration language. Do we call that an intermediate beginner? How much Emacs knowledge are we expecting they have to use this project? We do not intend to be a Doom or Spacemacs replacement. We are closer to Prelude philosophically.
Where From Here?
We'll continue to develop Rational Emacs. Is it usable today? Sure it is! At least with the caveat you are willing to read through the code to see what it does and possibly write (some of) your own configuration.
Will I migrate my configuration to Rational Emacs? Probably not, but we'll see. Will I take some of the ideas from there and implement them in my configuration? Absolutely. Already doing it. All that being said, I am working on trying to see if migrating my configuration to Rational Emacs can be done or if I just end up rewriting and overriding everything from Rational Emacs. If it is the latter case, then I'm not really using Rational Emacs, which is kinda where I am at the moment.
I am enjoying the project quite a bit, as well as the evolving community working on it, so I do plan to continue submitting pull requests and being active on the discussions on the issues list.
Tags: #emacs
Footnotes
1 For the curious, I created two helper functions, one to check to see if every package in a list was installed and a second to map over that list and install them. Then I have an unless
block check the first and call the second. If the first call passes, then the second function (and thus package-refresh-contents
) is never called.