Files
nixos-configs/home/roles/emacs/default.nix
John Ogle 4a450a216b feat(emacs): Add prebuilt Doom option using nix-doom-emacs-unstraightened
Implement pre-built Doom Emacs packages for the live USB image, eliminating
the need to run `doom sync` after first boot.

Changes:
- Add nix-doom-emacs-unstraightened flake input
- Add homeModule to all three module sets (nixos, unstable, darwin)
- Add `prebuiltDoom` option to emacs role (default: false)
- Enable prebuiltDoom for live-usb configuration
- Pin custom packages in packages.el for deterministic builds:
  - claude-code-ide, gptel-tool-library, beads

When prebuiltDoom=true, all Doom packages are compiled at nix build time
using emacs-overlay. The doom configuration is stored in the nix store
(read-only), and no `doom sync` is required at runtime.

This is ideal for:
- Live USB images
- Immutable/reproducible systems
- Offline deployments

Closes: nixos-configs-1wd
2026-01-10 10:44:03 -08:00

113 lines
3.2 KiB
Nix

{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.home.roles.emacs;
doomEmacs = pkgs.fetchFromGitHub {
owner = "doomemacs";
repo = "doomemacs";
rev = "38d94da67dc84897a4318714dcc48494c016d8c4";
sha256 = "sha256-Uc6qONH3jjUVDgW+pPBCGC7mh88ZY05u1y37fQrsxq0=";
};
# Shared emacs packages
emacsPackages = epkgs: [
epkgs.vterm
epkgs.treesit-grammars.with-all-grammars
];
# Default emacs configuration with vterm support
defaultEmacsPackage =
if pkgs.stdenv.isDarwin
then pkgs.emacs-macport.pkgs.withPackages emacsPackages
else pkgs.emacs.pkgs.withPackages emacsPackages;
# Path to doom config directory (relative to this file)
doomConfigDir = ./doom;
in
{
options.home.roles.emacs = {
enable = mkEnableOption "Doom Emacs with vterm and tree-sitter support";
prebuiltDoom = mkOption {
type = types.bool;
default = false;
description = ''
Use nix-doom-emacs-unstraightened to pre-build all Doom packages at
nix build time. This eliminates the need to run `doom sync` after
first boot, making it ideal for live USB images or immutable systems.
When enabled, the doom configuration is read-only (stored in nix store).
'';
};
};
config = mkIf cfg.enable (mkMerge [
# Common configuration for both modes
{
home.packages = [
pkgs.emacs-all-the-icons-fonts
pkgs.fira-code
pkgs.fontconfig
pkgs.graphviz
pkgs.isort
pkgs.nerd-fonts.fira-code
pkgs.nerd-fonts.droid-sans-mono
pkgs.nil # nix lsp language server
pkgs.nixfmt-rfc-style
(pkgs.ripgrep.override {withPCRE2 = true;})
pkgs.pipenv
pkgs.poetry
pkgs.python3
];
fonts.fontconfig.enable = true;
}
# Standard Doom Emacs mode (requires doom sync at runtime)
(mkIf (!cfg.prebuiltDoom) {
programs.emacs = {
enable = true;
package = defaultEmacsPackage;
};
# Mount emacs and tree-sitter grammars from nix store
home.file = {
"${config.xdg.configHome}/emacs".source = doomEmacs;
};
home.sessionPath = [
"${config.xdg.configHome}/emacs/bin"
];
home.sessionVariables = {
DOOMDIR = "${config.xdg.configHome}/doom";
DOOMLOCALDIR = "${config.xdg.dataHome}/doom";
};
# TODO: Use mkOutOfStoreSymlink instead?
home.activation.doomConfig = lib.hm.dag.entryAfter ["writeBoundary"] ''
# Always remove and recreate the symlink to ensure it points to the source directory
rm -rf "${config.xdg.configHome}/doom"
ln -sf "${config.home.homeDirectory}/nixos-configs/home/roles/emacs/doom" "${config.xdg.configHome}/doom"
'';
})
# Pre-built Doom Emacs mode (no doom sync needed - ideal for live USB)
(mkIf cfg.prebuiltDoom {
programs.doom-emacs = {
enable = true;
doomDir = doomConfigDir;
doomLocalDir = "${config.xdg.dataHome}/doom";
# Add extra packages that aren't part of Doom but needed for our config
extraPackages = epkgs: [
epkgs.vterm
epkgs.treesit-grammars.with-all-grammars
];
};
})
]);
}