summaryrefslogtreecommitdiff
path: root/modules/emacs/default.nix
diff options
context:
space:
mode:
Diffstat (limited to 'modules/emacs/default.nix')
-rw-r--r--modules/emacs/default.nix270
1 files changed, 270 insertions, 0 deletions
diff --git a/modules/emacs/default.nix b/modules/emacs/default.nix
new file mode 100644
index 0000000..2230ee0
--- /dev/null
+++ b/modules/emacs/default.nix
@@ -0,0 +1,270 @@
+{
+ config,
+ inputs,
+ lib,
+ pkgs,
+ ...
+}:
+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 = my.username;
+ };
+
+ nixfiles.modules = {
+ common.xdg.defaultApplications.emacsclient = [
+ "application/atom+xml"
+ "application/json"
+ "application/rss+xml"
+ "application/schema+json"
+ "application/xhtml+xml"
+ "application/xml"
+ "text/csv"
+ "text/plain"
+ ];
+ git.client.enable = true;
+ gnupg.enable = true;
+ password-store.enable = true;
+ profiles.dev.enable = true;
+ profiles.email.enable = true;
+ };
+
+ hm = {
+ stylix.targets.emacs.enable = false;
+
+ 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
+ ${getExe git.package} clone --depth=1 --branch=master \
+ "https://github.com/doomemacs/doomemacs" "$EMACSDIR"
+ fi
+
+ if [[ ! -d "$DOOMDIR/snippets" ]]; 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 --gc --force --verbose
+ fi
+ '';
+ }
+ )
+ {
+ "doom/init.el".source = ./doom/init.el;
+ "doom/packages.el".source = ./doom/packages.el;
+ "doom/config.el" = {
+ text = concatLines [
+ (
+ let
+ extraBins = with pkgs; [
+ (aspellWithDicts (
+ p: with p; [
+ en
+ ru
+ ]
+ )) # :checkers (spell +aspell)
+ asmfmt # :editor format
+ cargo # :lang rust
+ clang-tools # :lang (cc +lsp) :editor format
+ cmake-format # :lang cc :editor format
+ cmigemo # :lang japanese
+ config.hm.programs.emacs.package # !doom
+ config.nix.package # !doom
+ delve # :lang go :tools debugger
+ dockerfile-language-server-nodejs # :tools (docker +lsp)
+ dockfmt # :tools docker :editor format
+ editorconfig-core-c # :tools editorconfig
+ fd # doom!
+ gcc # :lang cc
+ ghc # :lang haskell
+ gnuplot # :lang (org +gnuplot)
+ gnutar # :tools tree-sitter
+ gnutls # doom! :app irc
+ go # :lang go
+ godef # :lang go
+ gomodifytags # :lang go
+ gopls # :lang (go +lsp)
+ gore # :lang go
+ gotests # :lang go
+ gotools # :lang go
+ graphviz # :lang (org +roam2) :lang plantuml
+ gzip # :tools tree-sitter
+ haskellPackages.cabal-fmt # :lang haskell :editor format
+ haskellPackages.cabal-install # :lang haskell
+ haskellPackages.haskell-language-server # :lang (haskell +lsp)
+ haskellPackages.hoogle # :lang haskell
+ haskellPackages.ormolu # :lang haskell :editor format
+ html-tidy # :lang web :editor format
+ jdk # :lang java :lang plantuml :checkers grammar
+ languagetool # :checkers grammar
+ libxml2 # :lang data :editor format
+ markdownlint-cli # :lang markdown
+ nil # :lang (nix +lsp)
+ nixfmt # :lang nix :editor format
+ nls # :lang (nickel +lsp)
+ nodePackages.bash-language-server # :lang (sh +lsp)
+ nodePackages.eslint # :lang (json +lsp)
+ nodePackages.js-beautify # :lang web
+ nodePackages.prettier # :editor format
+ nodePackages.stylelint # :lang web
+ nodePackages.vscode-css-languageserver-bin # lang (web +lsp)
+ nodePackages.vscode-html-languageserver-bin # lang (web +lsp)
+ nodePackages.vscode-json-languageserver-bin # lang (json +lsp)
+ nodejs # :tools debugger
+ pandoc # :lang org markdown latex
+ pinentry-emacs # doom!
+ pipenv # :lang python
+ poetry # :lang python
+ pre-commit # :tools magit
+ python3 # :lang python
+ python3Packages.black # :lang python :editor format
+ python3Packages.isort # :lang python :editor format
+ python3Packages.nose # :lang python
+ python3Packages.pyflakes # :lang python :editor format
+ python3Packages.pytest # :lang python
+ python3Packages.python-lsp-server # :lang python :editor format
+ ripgrep # doom!
+ rust-analyzer # :lang (rust +lsp)
+ rustc # :lang rust
+ rustfmt # :lang rust
+ shellcheck # :lang sh
+ shfmt # :lang sh :editor format
+ sops
+ sqlite # :lang (org +roam2) :tools lookup
+ terraform-ls # :tools (terraform +lsp)
+ texlab # lang (tex +lsp)
+ texlive.combined.scheme-full # :lang org tex
+ unzip # :tools debugger
+ wordnet # :tools (lookup +dictionary +offline)
+ yaml-language-server # :lang (yaml +lsp)
+ zig # :lang zig :editor format
+ zls # :lang (zig +lsp)
+ zstd # :emacs undo
+ gdb # :tools debugger
+ ];
+ in
+ ''
+ ;; 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}"))
+
+ ;; HACK Explicitly load specific Emacs packages from Nixpkgs.
+ ;; For some reason providing them as "extraPackages" doesn't
+ ;; work.
+ (add-to-list 'load-path "${pkgs.mu.mu4e}/share/emacs/site-lisp/mu4e")
+ (add-to-list 'load-path "${pkgs.emacsPackages.vterm}/share/emacs/site-lisp/elpa/vterm-${pkgs.emacsPackages.vterm.version}")
+
+ (appendq! auth-sources '(("${config.secrets.authinfo.path}")))
+
+ ;; :input japanese
+ (setq migemo-dictionary "${pkgs.cmigemo}/share/migemo/utf-8/migemo-dict"
+ migemo-options '("--quiet" "--emacs")
+ skk-large-jisyo "${pkgs.skk-dicts}/share/SKK-JISYO.L"
+ skk-show-inline t)
+
+ ;; :editor parinfer
+ (setq parinfer-rust-auto-download nil
+ parinfer-rust-library "${pkgs.parinfer-rust}/lib/libparinfer_rust.so")
+
+ ;; :lang (org +roam2) :email mu4e
+ (setq emacsql-sqlite-executable "${getExe pkgs.emacsql-sqlite}")
+
+ ;; :lang plantuml
+ (setq plantuml-jar-path "${pkgs.plantuml}/lib/plantuml.jar"
+ plantuml-executable-path "${getExe' pkgs.plantuml "plantuml"}"
+ org-plantuml-jar-path plantuml-jar-path
+ org-plantuml-executable-path plantuml-executable-path)
+
+ ;; :app irc
+ (setq circe-default-nick "${my.username}"
+ circe-default-realname "${my.email}"
+ circe-default-user circe-default-nick)
+ ''
+ )
+ (with config.stylix.fonts; ''
+ (setq doom-font "${monospace.name}-${toString sizes.terminal}"
+ doom-serif-font "${serif.name}-${toString sizes.terminal}"
+ doom-variable-pitch-font "${sansSerif.name}-${toString sizes.terminal}")
+ '')
+ (
+ 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.emacs29;
+ };
+
+ bash.initExtra = mkAfter ''
+ export PATH="$PATH:$XDG_CONFIG_HOME/emacs/bin"
+
+ # https://github.com/akermu/emacs-libvterm
+ if [[ "$INSIDE_EMACS" = vterm ]] && [[ -n "$EMACS_VTERM_PATH" ]] && [[ -f "$EMACS_VTERM_PATH/etc/emacs-vterm-bash.sh" ]]; then
+ source "$EMACS_VTERM_PATH/etc/emacs-vterm-bash.sh"
+ fi
+
+ # Not sourced from inside Emacs for some reason. Maybe it's not
+ # considered an interactive shell?
+ [[ -f ~/.profile ]] && . ~/.profile
+ '';
+ };
+ };
+ };
+}