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 an init.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.1

    Most 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 setting XDG_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!

    1. Check out the XDG base directory specification for more details. 

  • 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 every use-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.2

    Which 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?

    1. 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’s npm, but in practice I’ve rarely had issues with my approach and it has saved me a great deal of time. 

    2. package-installed-p will return t 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 of zoneinfo-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!

    1. Mechanical watches are another passion of mine. 

    2. It was named display-time-world before Emacs 28.1. The command was originally introduced in Emacs 23.1. 

  • 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 - namely M-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!

    1. 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