Advice needed installing doom-emacs

I have recently trying to use NixOS on the desktop, so I am still migrating my dotfiles to NixOS and home-manager. Everything is going quite ok for now, but I have some doubts about how to install doom-emacs. Following the install instructions, I should clone the repository to $HOME/.emacs.d. I guess that there is nothing inherently wrong in just running git clone and call it a day (it would work), but I would like to integrate it in my configuration so I don’t have to worry about it next time I have to install it. I have tried searching for better ways to do it, but it seems like it is out of the scope of the NixOS tools (since it happens in $HOME) and I am not sure if there is a way to do it using home-manager.

To more experienced users (or people already using doom-emacs): how would you proceed? Any pointers and ideas are welcome!

If you really want to install it declaratively there is GitHub - vlaci/nix-doom-emacs: doom-emacs packaged for Nix

2 Likes

Why did you italicize “really” - is there a question as to the wisdom of doing it?

TIA!

Doom already has a declarative package manager (straight.el), so most people (including Henrik himself) don’t manage doom through nix.

4 Likes

Ok, I will just leave this answer here in case anyone is trying something similar. The essence of it can be summed up in @mjlbach’s last comment:

[…] most people (including Henrik himself) don’t manage doom through nix.

That is not only because it is in a certain way redundant to use Nix and straight.el; it is because doom-emacs needs to be cloned into ~/.emacs.d and that directory must be writable. I could not find a good way to do it using Nix, so in a quick way to bootstrap it in case I install this config in a new machine, I decided to set up my ~/.doom.d directory through home-manager this way:

home.file.".doom.d" = {
  source = path/to/my/git/repo;
  recursive = true;
  onChange = readFile path/to/reload;
};

The notable thing is the onChange option being set to a script I made to reload the configuration. Initially, this script was simply a call to doom sync, but I added a simple check to detect if there was no configuration. If not, the script clones the repository and installs everything:

#!/bin/sh
DOOM="$HOME/.emacs.d"

if [ ! -d "$DOOM" ]; then
	git clone https://github.com/hlissner/doom-emacs.git $DOOM
	$DOOM/bin/doom -y install
fi

$DOOM/bin/doom sync

It works but I still want to polish some round edges:

  • When creating a new generation, the output from this onChange script is not shown to the user, and if it has to install emacs-doom it takes a long time with no feedback.
  • The current code simply clones the repository; I should try to pin the version/revision somehow to ensure that the install is the same.
3 Likes

I am grateful, this is helpful!

A couple of questions:

  • Did you figure out how to pin versions of the doom?
  • How would I upgrade doom with this setup?
    Seems like for now deleting ~/.emacs.d would trigger new install and that would pull in upgrads, is that correct?
  • Do you have your dotfiles available anywhere for the reference?

Did you figure out how to pin versions of the doom?

I did not, but I guess that it should suffice with checking out a certain commit of the emacs-doom repo in the example script I showed before.

How would I upgrade doom with this setup? Seems like for now deleting ~/.emacs.d would trigger new install and that would pull in upgrads, is that correct?

You would also need to change the ~/.doom.d directory in some way - any change will do, just enough to trigger a new onChange event. But I guess that would be enough, yes.

Do you have your dotfiles available anywhere for the reference?

I do, in fact. I hope they are not too convoluted and they can be helpful.

1 Like

Doom’s Emacs directory doesn’t strictly have to be writable. You can set the DOOMLOCALDIR to a writable location instead, that is the only part that has to be writable and it can be in an arbitrary location.

Also, once the Emacs directory has been updated via git, running doom sync -u is the same as doom upgrade.

I’ve got the following in my home.nix (irrelevant bits elided):

{ pkgs, config, lib, ... }:

{
  home = {
    sessionPath = [ "${config.xdg.configHome}/emacs/bin" ];
    sessionVariables = {
      DOOMDIR = "${config.xdg.configHome}/doom-config";
      DOOMLOCALDIR = "${config.xdg.configHome}/doom-local";
    };
  };

  xdg = {
    enable = true;
    configFile = {
      "doom-config/config.el".text = "…";
      "doom-config/init.el".text = "…";
      "doom-config/packages.el".text = "…";
      "emacs" = {
        source = builtins.fetchGit "https://github.com/hlissner/doom-emacs";
        onChange = "${pkgs.writeShellScript "doom-change" ''
          export DOOMDIR="${config.home.sessionVariables.DOOMDIR}"
          export DOOMLOCALDIR="${config.home.sessionVariables.DOOMLOCALDIR}"
          if [ ! -d "$DOOMLOCALDIR" ]; then
            ${config.xdg.configHome}/emacs/bin/doom -y install
          else
            ${config.xdg.configHome}/emacs/bin/doom -y sync -u
          fi
        ''}";
      };
    };
  };

  home.packages = with pkgs; [
    # DOOM Emacs dependencies
    binutils
    (ripgrep.override { withPCRE2 = true; })
    gnutls
    fd
    imagemagick
    zstd
    nodePackages.javascript-typescript-langserver
    sqlite
    editorconfig-core-c
    emacs-all-the-icons-fonts
  ];
}
4 Likes
Hosted by Flying Circus.