Sunday, 26 October 2025
I while back I wrote up a sketch to interpret Ini-style configuration files for Emacs. Here I want to present and discuss the idea briefly.
For those wondering how a “ini-style init file” looks like (I
certainly would), I translated parts of my init.el into a
syntax that ini.el can handle, to give an idea of how these
files look like:
enable inhibit-startup-screen
set mode-line-compact long
set font-use-system-font t
disable menu-bar-mode
bind C-c k compile
eval set compile-command (format "make -k -j%d " (num-processors))
[package avy]
unset avy-single-candidate-jump
global bind C-z avy-goto-word-or-subword-1
[/package]
add-hook text-mode-hook flyspell-mode
add-hook prog-mode-hook flyspell-prog-mode
[feature flymake]
bind M-n flymake-goto-next-error
bind M-p flymake-goto-prev-error
(defalias 'list-issues #'flymake-show-buffer-diagnostics)
[/feature]
[package bash-completion]
(bash-completion-setup)
[/package]
[package proof-general]
[package focus]
[package markdown-mode]
add-hook before-save-hook time-stampThe idea here is to do the right thing most of the time,
while still allowing for arbitrary complicated configurations using
Eli’s, as lines that start with an opening parenthesis are just regular
Lisp expressions that treated just like they would be in an
init.el.
More details on the syntax can be found in the ini.el
file under the “Syntax” section.
There are three main approaches to configuring Emacs that one can compare this idea to:
init.el,use-package or my not well known
setup.el,customize-centric approach, which usually means not
writing Elisp on your own.I consider my approach to be a merge of the first two. Settings like
bind and set are mapped directly to their
obvious corresponding S-expressions. Depending on the exact command and
modifiers the concrete replacement might differ, but the point is that
it does what you want it to do. You cannot bind keys in a map before the
map has been loaded, so the
bind M-n flymake-goto-next-error above will expand to
(with-eval-after-load 'flymake
(keymap-set flymake-mode-map "M-n" #'flymake-goto-next-error))You can of course just write this out directly, as any line beginning
with an opening parenthesis is read directly and
interpreted directly. The connection to configuration macros is that
this allows us to just express what we want to (“bind this command”),
without having to write what we have to (“… after loading this
feature”).
The main advantage of my advantage I see is that the syntax is more
conventional and thus easier to adopt for some people who are not yet
familiar with Lisp, and haven’t internalised what to quote and when. I
would claim that for most packages, the keywords I have defined up until
now will cover well over 90% of the use-cases. The fact that
set expands to setopt also means that it is
easy to respect user options as user options and not mistreat them as
symbols. Prior to the addition of setopt in Emacs 28, it
was necessary to use customize-set-variable, which much
like set required user option names to be quoted and would
only set a single user option per expression. I think a good maxim of
design is to make it easy to do the right thing, where “easy” and
“right” are intentionally kept vague. Looking through my
init.el, I notice patterns such as the fact that most user
options I set are either self-evaluating forms or quoted, so it made
sense for me that set would be non-evaluating by default as
well.
Another advantage of the simpler but rigid syntax is that I can
imagine an extension to customize that can reasonably
figure out what to change in a init.ini file, which is much
more difficult in a general elisp file, as we have no notion of
structure such as the feature or package
blocks I have proposed above. This would serve to bridge the gulf
between generated custom-set-variables blocks that many
users sadly discard by setting custom-file to
"/dev/null" and the manually written configuration file. I
have heard many people dismissing the customize interface just due to
the reason that it generates code that they do not want in their
init.el, which I think is a shame.
The initial sketch appears to work, though I have to admit that I am
not using it personally yet, as I don’t have a need to switch myself and
seldom adjust anything anymore in my init.el (remember,
compulsive and constant tweaking of configuration files is a sign that
you are doing something wrong!). So I would be interested in the
opinions of new and intermediate users as to the potential advantages
and pitfalls of this idea. Feel free to send me a message with your
unfiltered opinions or to share this page with someone who might be
interested.
If this idea seems interesting, it would be worth developing into a proper package, with good error messages and syntax highlighting. If it is well received and reliable, it would be interesting to consider merging it into Emacs itself one day.