Posts
Emacs and XDG sitting on a tree
Where to place my Emacs configuration? That is the question!
This fairly simple question has surprisingly many answers, as it often happens with projects as old as Emacs:
- Historically Emacs’s user config was a file called
.emacs
, placed in your home directory - Later you could use the name
init.el
as an alias to.emacs
- And then there’s the option that’s probably most common today - placing your configuration
under the
.emacs.d
folder, where you usually have aninit.el
that potentially refers to other Emacs Lisp libraries
But wait, there’s more! Emacs 27.1 introduced
XDG_CONFIG_HOME
support, and Emacs 29.1 extended the level of XDG base directory specification support in Emacs.XDG, which stands for X Desktop Group, is a set of standards and specifications developed by freedesktop.org to promote interoperability among different desktop environments, primarily in Unix-like operating systems. The group focuses on ensuring that applications can work seamlessly across various desktop environments by adhering to common guidelines.
Their most notable work to date is the XDG base directory specification. In a nutshell this specification outlines the environment variables that define where user-specific data files, configuration files, and cache files should be stored. For instance, it specifies directories like
$XDG_CONFIG_HOME
for configuration files and$XDG_DATA_HOME
for data files.1Most of the time the XDG config home would be
~/.config
and there would be a subfolder there for the configuration of each application. In Emacs’s case that would be~/.config/emacs
. I hope it’s clear that the idea here is to reduce the clutter at the top-level and to make sure that each application stores its configuration in a predictable place.I think it’s really great that Emacs is (slowly) adopting the industry standards and I believe that over the course of time the XDG config folder will become the preferred place to store your Emacs configuration. That’s why I encourage everyone to move in this direction and unclutter their home folder a bit.
Just keep in mind a couple of things:
- You’ll have to make sure that folders like
~/.emacs.d
don’t exist anymore, as they’d have precedence over the XDG config folder. The configuration resolution happens like this:
Emacs looks for your init file using the filenames
~/.emacs.el
,~/.emacs
, or~/.emacs.d/init.el
in that order; you can choose to use any one of these names. (Note that only the locations directly in your home directory have a leading dot in the location’s basename.)Emacs can also look in an XDG-compatible location for init.el, the default is the directory
~/.config/emacs
. This can be overridden by settingXDG_CONFIG_HOME
in your environment, its value replaces~/.config
in the name of the default XDG init file. However~/.emacs.d
,~/.emacs
, and~/.emacs.el
are always preferred if they exist, which means that you must delete or rename them in order to use the XDG location.Note also that if neither the XDG location nor
~/.emacs.d
exist, then Emacs will create~/.emacs.d
(and therefore use it during subsequent invocations).Emacs will set user-emacs-directory to the directory it decides to use.
Not the best defaults IMO (especially falling back to creating
.emacs.d
), but you can’t fight tradition! Or rather - fighting tradition is pretty hard…- Some packages might have hardcoded the path in which they store their own configuration. In general they should be relying on
user-emacs-directory
, which will be auto-set to whatever directory Emacs discovered its configuration in, but there will always be some packages that probably didn’t do “the right thing”.
I’m guessing that we’re not really getting rid of
~/.emacs.d
any time soon (or ever), but I’m hoping that article like this one might speed up a bit the process. Time will tell.macOS users should keep in mind that unfortunately macOS doesn’t set the standard XDG environment variables, as it has its own notion of where things like configuration files, application cache, etc should be stored. Still, it’s fairly easy to just set the missing variables yourself (e.g. in your
.zshrc
):export XDG_CONFIG_HOME = $HOME/.config export XDG_DATA_HOME = $HOME/.local/share export XDG_STATE_HOME = $HOME/.local/state export XDG_CACHE_HOME = $HOME/.cache
So, has anyone moved their Emacs config to respect the XDG conventions already? How smooth was the process for you?
P.S. If you’re curious to learn more about how Emacs’s configuration discover process I’d suggest reading this chapter of the Emacs Manual. Good stuff!
-
Check out the XDG base directory specification for more details. ↩
- Historically Emacs’s user config was a file called
Ensure all packages are installed by default with use-package
I’m quite fond of
use-package
and I’ve organized my personal Emacs setup around it for a while now. One thing that I don’t like very much is that by default almost I have to add:ensure t
to almost everyuse-package
block, as I want all external packages to be installed if they are not present. That’s quite handy when I’m setting up Emacs on a new computer.1 Think something like:(use-package zenburn-theme :ensure t :config (load-theme 'zenburn t))
Not a big deal for a few packages, but kind of annoying if you have 50+ packages in your
init.el
. There’s a pretty simple solution to this problem, though. Just add the following bit of configuration to your Emacs setup:(setq use-package-always-ensure t)
Now instead of specifying
:ensure t
you can specify:ensure nil
for the packages you don’t want to install automatically. Note that for built-packages (e.g.dired
) it doesn’t really matter if a package is using:ensure t
or:ensure nil
.2Which approach do you prefer? Are you the type of person who ensures every package is installed when absent or not? Why do you prefer one approach over the other?
-
I know that a lot of people object to this approach, as you’re not sure what versions of the packages you’d get as
package.el
is a bit primitive compared to something like Ruby’s Bundler or Node’snpm
, but in practice I’ve rarely had issues with my approach and it has saved me a great deal of time. ↩ -
package-installed-p
will returnt
for those. ↩
-
Tracking World Time with Emacs
In today’s highly connected world it’s often useful to keep track of time in several time zones. I work in a company with employees all over the world, so I probably keep track of more time zones than most people.
So, what are the best ways to do this? I know what you’re thinking - let’s just buy an Omega Aqua Terra Worldtimer mechanical watch for $10,000 and be done with it!1 While this will definitely get the job done and improve the looks of your wrist immensely, there’s a cheaper and more practical option for you - Emacs. Did you know that Emacs has a command named
world-clock
that does exactly what we want?2 If you invoke it you’ll see something like this:Seattle Monday 11 March 02:45 PDT New York Monday 11 March 05:45 EDT London Monday 11 March 09:45 GMT Paris Monday 11 March 10:45 CET Bangalore Monday 11 March 15:15 IST Tokyo Monday 11 March 18:45 JST
Hmm, looks OK but the greatest city in the world (Sofia, Bulgaria) is missing from the list… That’s totally unacceptable! We can fix this by tweaking the variable
world-clock-list
:(setq world-clock-list '(("America/Los_Angeles" "Seattle") ("America/New_York" "New York") ("Europe/London" "London") ("Europe/Paris" "Paris") ("Europe/Sofia" "Sofia") ("Asia/Calcutta" "Bangalore") ("Asia/Tokyo" "Tokyo")))
Let’s try
M-x world-clock
again now:Seattle Monday 11 March 02:51 PDT New York Monday 11 March 05:51 EDT London Monday 11 March 09:51 GMT Paris Monday 11 March 10:51 CET Sofia Monday 11 March 11:51 EET Bangalore Monday 11 March 15:21 IST Tokyo Monday 11 March 18:51 JST
Much better!
By the way, you don’t really have to edit
world-clock-list
, as by default it’s configured to mirror the value ofzoneinfo-style-world-list
. The choice is yours.You can also configure the way the world time entries are displayed using
world-clock-time-format
. Let’s switch to a style with shorter day and month names:(setq world-clock-time-format "%a %d %b %R %Z")
This will result in:
Seattle Mon 11 Mar 06:06 PDT New York Mon 11 Mar 09:06 EDT London Mon 11 Mar 13:06 GMT Paris Mon 11 Mar 14:06 CET Sofia Mon 11 Mar 15:06 EET Bangalore Mon 11 Mar 18:36 IST Tokyo Mon 11 Mar 22:06 JST
Check out the docstring of
format-time-string
(C-h f
format-time-string
) for more details, as the options here are numerous.That’s all I have for you today. I hope you learned something useful. Keep hacking!
Run Buffer-specific Commands with M-X
No Emacs keybinding is more iconic than
M-x
(execute-extented-command
) - it allows you to run any Emacs command from the minibuffer and it sounds a lot like Emacs!1 It doesn’t get better than this… or does it?Emacs 29 introduced a new keybinding that’s aiming to give
M-x
a run for its money - namelyM-X
(execute-extended-command-for-buffer
). It’s described like this:Query user for a command relevant for the current mode, and then execute it. This is like ‘execute-extended-command’, but it limits the completions to commands that are particularly relevant to the current buffer. This includes commands that have been marked as being specially designed for the current major mode (and enabled minor modes), as well as commands bound in the active local key maps.
So, it basically narrows the list of commands that you can execute to those that make the most sense in the context of the current buffer (mostly commands coming from the current major mode and enabled minor modes). I can easily see it becoming more useful than
M-x
when exploring some functionality that you’re not familiar with, as the results you’d get are narrower and you’d be more likely to find what you’re looking for.That’s all I have for you today. On February 29th we covered a small new feature in Emacs 29. That makes me feel good! Keep hacking!
-
Try pronouncing
M-x
out loud. ↩
-
Changing The Emacs Configuration Directory
I’ve noticed recently that I’ve missed one small, but very handy addition to Emacs 29 - the
--init-dir
command-line options. According the release notes:Emacs now supports setting ‘user-emacs-directory’ via ‘–init-directory’. Use the ‘–init-directory’ command-line option to set ‘user-emacs-directory’.
Basically, this allows you to instruct Emacs where to read its configuration from. By default that’s
.emacs.d
, but with this option you can easily override the default. That’s extremely handy when you want to try out different Emacs setups. Here’s some example:# Use Emacs Prelude $ emacs --init-dir ~/emacs-distros/prelude # Use Spacemacs $ emacs --init-dir ~/emacs-distros/spacemacs
I’m guessing this command-line options will be enough for most people who casually switch between different configurations and will reduce the need for them to rely on more sophisticated tools like chemacs or with-emacs.
Admittedly, I never used any such tools and I’d just symlink different dirs to
.emacs.d
, so--init-dir
will definitely improve my workflow a bit.That’s all I have for you today! Keep hacking!
Subscribe via RSS | View Older Posts