{ config, pkgs, lib, ... }: let doom-pkgs = with pkgs; [ fira fira-code-nerdfont emacs-all-the-icons-fonts ]; doom-path-pkgs = with pkgs; [ (ripgrep.override {withPCRE2 = true;}) binutils clang-tools cmake editorconfig-core-c fd gcc gdb git gnumake gnutls imagemagick ispell libtool lldb mermaid-filter mlocate nodejs_22 pandoc pandoc-katex python311 python311Packages.debugpy python311Packages.grip texlab texlive.combined.scheme-medium unzip zstd ]; doom-socket-name = "main"; wrapped-emacs = pkgs.symlinkJoin { name = "wrapped-emacs"; paths = [pkgs.emacs29-pgtk]; nativeBuildInputs = [pkgs.makeBinaryWrapper]; postBuild = '' wrapProgram $out/bin/emacs \ --prefix PATH : ${lib.makeBinPath doom-path-pkgs} \ --add-flags "--init-directory=${config.xdg.configHome}/doom-emacs" \ --set DOOMDIR "${config.home.sessionVariables.DOOMDIR}" \ --set DOOMLOCALDIR "${config.home.sessionVariables.DOOMLOCALDIR}" \ --suffix LD_LIBRARY_PATH : "${pkgs.stdenv.cc.cc.lib}/lib" wrapProgram $out/bin/emacsclient \ --prefix PATH : ${lib.makeBinPath doom-path-pkgs} \ --set DOOMDIR "${config.home.sessionVariables.DOOMDIR}" \ --set DOOMLOCALDIR "${config.home.sessionVariables.DOOMLOCALDIR}" \ --suffix LD_LIBRARY_PATH : "${pkgs.stdenv.cc.cc.lib}/lib" \ --add-flags "--socket-name=${doom-socket-name}" ''; }; doom-setup = pkgs.writeShellScript "doom-setup" '' export PATH="${lib.makeBinPath doom-path-pkgs}:$PATH" export EMACS="${wrapped-emacs}/bin/emacs" export DOOMDIR="${config.home.sessionVariables.DOOMDIR}" export DOOMLOCALDIR="${config.home.sessionVariables.DOOMLOCALDIR}" export LD_LIBRARY_PATH "$LD_LIBRARY_PATH:${pkgs.stdenv.cc.cc.lib}/lib" if [ ! -d "$DOOMLOCALDIR" ]; then ${config.xdg.configHome}/doom-emacs/bin/doom install --force --no-env else ${config.xdg.configHome}/doom-emacs/bin/doom "$@" fi ''; in { programs.emacs = { enable = true; package = wrapped-emacs; }; home = { sessionPath = ["${config.xdg.configHome}/doom-emacs/bin"]; sessionVariables = { DOOMDIR = "${config.xdg.configHome}/doom-config"; DOOMLOCALDIR = "${config.xdg.configHome}/doom-local"; }; }; systemd.user.services.doom-emacs-server = { Unit = { Description = "Doom Emacs Server"; }; Service = { ExecStart = "${wrapped-emacs}/bin/emacs --fg-daemon=${doom-socket-name}"; SuccessExitStatus = 15; }; Install = { WantedBy = []; # Lazy start by socket }; }; systemd.user.sockets.doom-emacs-server = { Socket = { ListenStream = "/run/user/%U/emacs/${doom-socket-name}"; DirectoryMode = "0700"; }; Install = { WantedBy = ["sockets.target"]; }; }; xdg = { enable = true; configFile = { "doom-config/splash.png" = { source = ./static/splash.png; }; "doom-config/config.el" = { source = ./static/config.el; }; "doom-config/init.el" = { source = ./static/init.el; onChange = "${doom-setup} sync --force -e"; }; "doom-config/packages.el" = { source = ./static/packages.el; onChange = "${doom-setup} sync --force -u -e"; }; "doom-emacs" = { source = builtins.fetchGit { url = "https://github.com/doomemacs/doomemacs"; rev = "ff3fd15b0249954f3a859e533f6c09a8b1988a72"; }; onChange = "${doom-setup} --force sync -u -e"; }; }; desktopEntries = { emacs = { name = "Doom Emacs"; genericName = "Text Editor"; icon = ./static/icon.png; exec = "${wrapped-emacs}/bin/emacs %F"; terminal = false; categories = ["Application" "Development" "TextEditor"]; mimeType = ["text/*"]; settings = { StartupWMClass = "Doom Emacs"; }; }; emacsclient = { name = "Doom Emacs (Client)"; genericName = "Text Editor"; icon = ./static/icon.png; exec = '' sh -c "if [ -n \\"\\$*\\" ]; then exec ${wrapped-emacs}/bin/emacsclient --alternate-editor= --display=\\"\\$DISPLAY\\" \\"\\$@\\"; else exec emacsclient --alternate-editor= --create-frame; fi" sh %F ''; terminal = false; categories = ["Application" "Development" "TextEditor"]; mimeType = ["text/*"]; settings = { StartupWMClass = "Doom Emacs"; }; }; }; }; home.packages = doom-pkgs; }