{ config, inputs, lib, localUsername ? lib.my.username, pkgs, this, ... }: with lib; let cfg = config.nixfiles.modules.emacs; in { options.nixfiles.modules.emacs.enable = mkEnableOption "GNU Emacs"; config = mkIf cfg.enable { secrets.authinfo = { file = "${inputs.self}/secrets/authinfo"; owner = localUsername; }; nixfiles.modules = { fonts.enable = true; git.client.enable = true; gnupg.enable = true; }; hm = { xdg.configFile = mapAttrs (_: value: value // { onChange = with config.hm.programs; '' export EMACSDIR="''${XDG_CONFIG_HOME:-$HOME/.config}/emacs" export DOOMDIR="''${XDG_CONFIG_HOME:-$HOME/.config}/doom" if [[ ! -d "$EMACSDIR/.git" ]]; then ${git.package}/bin/git clone --depth=1 --branch=master \ "https://github.com/doomemacs/doomemacs" "$EMACSDIR" fi if [[ ! -d "$DOOMDIR" ]]; then mkdir -p "$DOOMDIR/snippets" fi if [[ -x "$EMACSDIR/bin/doom" ]]; then if [[ ! -d "$EMACSDIR/.local" ]]; then PATH="''${PATH:-/bin:/usr/bin:/usr/local/bin}:${emacs.package}/bin:${git.package}/bin" \ "$EMACSDIR/bin/doom" install --force --verbose fi PATH="''${PATH:-/bin:/usr/bin:/usr/local/bin}:${emacs.package}/bin:${git.package}/bin" \ "$EMACSDIR/bin/doom" sync -e -p --force --verbose fi ''; }) { "doom/init.el".source = ./doom/init.el; "doom/packages.el".source = ./doom/packages.el; "doom/config.el" = { text = concatLines [ ( let # NOTE gopls will require the "go" executable which must be provided # by the project's flake/shell. extraBins = with pkgs; [ (aspellWithDicts (p: with p; [en ru])) # :checkers (spell +aspell) (python3.withPackages (p: with p; [ black # :lang python :editor format isort # :lang python pyflakes # :lang python python-lsp-server # :lang (python +lsp) ])) asmfmt # :editor format bash-language-server # :lang (sh +lsp) clang-tools # :lang (cc +lsp) :editor format cmake # :term vterm cmake-format # :lang cc :editor format cmigemo # :lang japanese css-language-server # :lang (web +lsp) dhall-language-server # :lang (dhall +lsp) dockerfile-language-server # :tools (docker +lsp) editorconfig # :tools editorconfig fd # doom! gcc # :tools magit :term vterm gnumake # :term vterm gnuplot # :lang (org +gnuplot) gnutls # doom! go-language-server # :lang (go +lsp) gomodifytags # :lang go gore # :lang go gotests # :lang go gotools # :lang go graphviz # :lang (org +roam2) :lang plantuml html-language-server # :lang (web +lsp) html-tidy # :lang web jre # :lang plantuml json-language-server # :lang (json +lsp) libtool # :term vterm nix-language-server # :lang (nix +lsp) nodePackages.eslint # :lang (json +lsp) nodePackages.js-beautify # :lang web nodePackages.prettier # :editor format nodePackages.stylelint # :lang web nodejs # :tools debugger pandoc # :lang org markdown latex perl # term vterm pinentry-emacs # doom! pre-commit # :tools magit ripgrep # doom! rust-analyzer # :lang (rust +lsp) rustfmt # :lang rust shellcheck # :lang sh shfmt # :lang sh :editor format sqlite # :lang (org +roam2) :tools lookup texlab # lang (tex +lsp) # FIXME https://github.com/NixOS/nixpkgs/issues/235434 # texlive.combined.scheme-full # :lang org tex unzip # :tools debugger wordnet # :tools (lookup +dictionary +offline) yaml-language-server # :lang (yaml +lsp) zls # :lang (zig +lsp) zstd # :emacs undo ] ++ ( # GDB doesn't support[1] Apple Silicon. # # [1]: https://inbox.sourceware.org/gdb/6b48224b-9e2e-518d-793b-df4fc5514884@arm.com/ if (this.system != "aarch64-darwin") then [gdb] # :tools debugger else [lldb] # :tools debugger ) ++ optionals (!pkgs.stdenv.isDarwin) [ # NOTE Haskell is pretty much broken every couple of days on # MacOS and I usually don't write anything in Haskell while # I'm on my work laptop, so... ShellCheck seems to be working, # though. haskellPackages.ormolu # :lang haskell :editor format haskellPackages.haskell-language-server # :lang (haskell +lsp) haskellPackages.cabal-fmt # :lang haskell :editor format haskellPackages.cabal-install # :lang haskell haskellPackages.hoogle # :lang haskell ]; in '' ;; This will integrate packages which are required by various ;; modules without polluting the user's profile. (setq exec-path (append exec-path '(${ concatMapStringsSep " " (x: ''"${x}/bin"'') extraBins }))) (setenv "PATH" (concat (getenv "PATH") ":${ concatMapStringsSep ":" (x: "${x}/bin") extraBins }")) (appendq! auth-sources '("${config.secrets.authinfo.path}")) ;; Font must be set to N+2 because otherwise it looks too small. (setq doom-font (font-spec :family "${config.fontScheme.monospaceFont.family}" :size ${toString (config.fontScheme.monospaceFont.size + 2)}) doom-unicode-font doom-font) ;; :app irc (setq circe-default-nick "${my.username}" circe-default-realname "${my.email}" circe-default-user circe-default-nick) ;; :lang plantuml (setq org-plantuml-jar-path "${pkgs.plantuml}/lib/plantuml.jar") ;; :input japanese (setq migemo-dictionary "${pkgs.cmigemo}/share/migemo/utf-8/migemo-dict") ;; :input japanese ;; (setq skk-large-jisyo "${pkgs.skk-dicts}/share/skk/SKK-JISYO.L") ;; :lang nix (setq nix-nixfmt-bin "${pkgs.writeShellScript "nixfmt" '' ${pkgs.alejandra}/bin/alejandra --quiet "$@" ''}") '' ) (with config.hm.accounts.email; let mu4eAccounts = let muAccounts = filter (a: a.mu.enable) (attrValues accounts); in concatMapStringsSep "\n" (a: with a; let personalAddresses = concatMapStringsSep " " (v: ''"${v}"'') aliases; in '' (set-email-account! "${name}" '((user-full-name . "${realName}") (user-mail-address . "${address}") (mu4e-inbox-folder . "/${name}/${folders.inbox}") (mu4e-sent-folder . "/${name}/${folders.sent}") (mu4e-drafts-folder . "/${name}/${folders.drafts}") (mu4e-trash-folder . "/${name}/${folders.trash}") (mu4e-refile-folder . "/${name}/Archive") (+mu4e-personal-addresses . (${personalAddresses}))) t) '') muAccounts; in '' (setq mu4e-root-maildir "${maildirBasePath}") ${mu4eAccounts} '') (builtins.readFile ./doom/config.el) ]; }; }; programs.emacs = { enable = true; package = pkgs.emacs28; # Pin to avoid surprises. }; }; }; }