about summary refs log tree commit diff
path: root/users/tazjin/emacs/default.nix
diff options
context:
space:
mode:
Diffstat (limited to 'users/tazjin/emacs/default.nix')
-rw-r--r--users/tazjin/emacs/default.nix177
1 files changed, 177 insertions, 0 deletions
diff --git a/users/tazjin/emacs/default.nix b/users/tazjin/emacs/default.nix
new file mode 100644
index 000000000000..5adf01b2f4b6
--- /dev/null
+++ b/users/tazjin/emacs/default.nix
@@ -0,0 +1,177 @@
+# This file builds an Emacs pre-configured with the packages I need
+# and my personal Emacs configuration.
+{ lib, pkgs, ... }:
+
+pkgs.makeOverridable
+  ({ emacs ? pkgs.emacsGcc }:
+  let
+    emacsWithPackages = (pkgs.emacsPackagesFor emacs).emacsWithPackages;
+
+    # If switching telega versions, use this variable because it will
+    # keep the version check, binary path and so on in sync.
+    currentTelega = epkgs: epkgs.melpaPackages.telega;
+
+    # $PATH for binaries that need to be available to Emacs
+    emacsBinPath = lib.makeBinPath [
+      (currentTelega pkgs.emacsPackages)
+      pkgs.libwebp # for dwebp, required by telega
+    ];
+
+    identity = x: x;
+
+    tazjinsEmacs = pkgfun: (emacsWithPackages (epkgs: pkgfun (with epkgs; [
+      ace-link
+      ace-window
+      avy
+      bazel
+      browse-kill-ring
+      cargo
+      clojure-mode
+      cmake-mode
+      company
+      counsel
+      counsel-notmuch
+      d-mode
+      direnv
+      dockerfile-mode
+      eglot
+      elfeed
+      elixir-mode
+      elm-mode
+      erlang
+      exwm
+      flymake
+      go-mode
+      google-c-style
+      gruber-darker-theme
+      haskell-mode
+      ht
+      hydra
+      idle-highlight-mode
+      ivy
+      ivy-prescient
+      jq-mode
+      kotlin-mode
+      lsp-mode
+      magit
+      markdown-toc
+      meson-mode
+      multi-term
+      multiple-cursors
+      nginx-mode
+      nix-mode
+      notmuch
+      paredit
+      password-store
+      pinentry
+      polymode
+      prescient
+      protobuf-mode
+      rainbow-delimiters
+      rainbow-mode
+      refine
+      request
+      restclient
+      rust-mode
+      sly
+      string-edit
+      swiper
+      telephone-line
+      terraform-mode
+      toml-mode
+      transient
+      undo-tree
+      use-package
+      uuidgen
+      vterm
+      web-mode
+      websocket
+      which-key
+      xelb
+      yaml-mode
+      yasnippet
+      zoxide
+
+      # Wonky stuff
+      (currentTelega epkgs)
+
+      # Custom depot packages (either ours, or overridden ones)
+      tvlPackages.dottime
+      tvlPackages.nix-util
+      tvlPackages.passively
+      tvlPackages.rcirc
+      tvlPackages.term-switcher
+      tvlPackages.tvl
+    ])));
+
+    # Tired of telega.el runtime breakages through tdlib
+    # incompatibility. Target to make that a build failure instead.
+    tdlibCheck =
+      let
+        tgEmacs = emacsWithPackages (epkgs: [ (currentTelega epkgs) ]);
+        verifyTdlibVersion = builtins.toFile "verify-tdlib-version.el" ''
+          (require 'telega)
+          (defvar tdlib-version "${pkgs.tdlib.version}")
+          (when (or (version< tdlib-version
+                              telega-tdlib-min-version)
+                    (and telega-tdlib-max-version
+                          (version< telega-tdlib-max-version
+                                    tdlib-version)))
+             (message "Found TDLib version %s, but require %s to %s"
+                     tdlib-version telega-tdlib-min-version telega-tdlib-max-version)
+            (kill-emacs 1))
+        '';
+      in
+      pkgs.runCommandNoCC "tdlibCheck" { } ''
+        export PATH="${emacsBinPath}:$PATH"
+        ${tgEmacs}/bin/emacs --script ${verifyTdlibVersion} && touch $out
+      '';
+  in
+  lib.fix
+    (self: l: f: (pkgs.writeShellScriptBin "tazjins-emacs" ''
+      export PATH="${emacsBinPath}:$PATH"
+      exec ${tazjinsEmacs f}/bin/emacs \
+        --debug-init \
+        --no-site-file \
+        --no-site-lisp \
+        --no-init-file \
+        --directory ${./config} ${if l != null then "--directory ${l}" else ""} \
+        --eval "(require 'init)" $@
+    '').overrideAttrs
+      (_: {
+        passthru = {
+          # Call overrideEmacs with a function (pkgs -> pkgs) to modify the
+          # packages that should be included in this Emacs distribution.
+          overrideEmacs = f': self l f';
+
+          # Call withLocalConfig with the path to a *folder* containing a
+          # `local.el` which provides local system configuration.
+          withLocalConfig = confDir: self confDir f;
+
+          # Build a derivation that uses the specified local Emacs (i.e.
+          # built outside of Nix) instead
+          withLocalEmacs = emacsBin: pkgs.writeShellScriptBin "tazjins-emacs" ''
+            export PATH="${emacsBinPath}:$PATH"
+            export EMACSLOADPATH="${(tazjinsEmacs f).deps}/share/emacs/site-lisp:"
+            exec ${emacsBin} \
+              --debug-init \
+              --no-site-file \
+              --no-site-lisp \
+              --no-init-file \
+              --directory ${./config} \
+              ${if l != null then "--directory ${l}" else ""} \
+              --eval "(require 'init)" $@
+          '';
+
+          # Expose telega/tdlib version check as a target that is built in
+          # CI.
+          #
+          # TODO(tazjin): uncomment when telega works again
+          inherit tdlibCheck;
+          meta.ci.targets = [ "tdlibCheck" ];
+        };
+      }))
+    null
+    identity
+  )
+{ }