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.nix304
1 files changed, 170 insertions, 134 deletions
diff --git a/users/tazjin/emacs/default.nix b/users/tazjin/emacs/default.nix
index df73c05ffb..46843432f1 100644
--- a/users/tazjin/emacs/default.nix
+++ b/users/tazjin/emacs/default.nix
@@ -1,153 +1,189 @@
 # This file builds an Emacs pre-configured with the packages I need
 # and my personal Emacs configuration.
-#
-# On NixOS machines, this Emacs currently does not support
-# Imagemagick, see https://github.com/NixOS/nixpkgs/issues/70631.
-#
-# Forcing Emacs to link against Imagemagick currently causes libvterm
-# to segfault, which is a lot less desirable than not having telega
-# render images correctly.
-{ depot, lib, ... }:
+{ depot, lib, pkgs, ... }:
 
-let
-  inherit (depot) third_party;
+pkgs.makeOverridable
+  ({ emacs ? pkgs.emacs29 }:
+  let
+    emacsPackages = (pkgs.emacsPackagesFor emacs);
+    emacsWithPackages = emacsPackages.emacsWithPackages;
 
-  emacsWithPackages = (third_party.emacsPackagesGen third_party.emacs27).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;
 
-  # Pick telega from unstable channel for recent fixes.
-  unstable = import third_party.nixpkgsSrc {};
-  telegaUnstable = (unstable.emacsPackagesGen third_party.emacs27).telega;
+    # $PATH for binaries that need to be available to Emacs
+    emacsBinPath = lib.makeBinPath [
+      (currentTelega pkgs.emacsPackages)
+      pkgs.libwebp # for dwebp, required by telega
+    ];
 
-  # $PATH for binaries that need to be available to Emacs
-  emacsBinPath = lib.makeBinPath [ telegaUnstable ];
+    identity = x: x;
 
-  identity = x: x;
+    # tree-sitter grammars for various ts-modes
+    customTreesitGrammars = emacs.pkgs.treesit-grammars.with-grammars (g: with g; [
+      tree-sitter-bash
+      tree-sitter-c
+      tree-sitter-cmake
+      tree-sitter-cpp
+      tree-sitter-css
+      tree-sitter-dockerfile
+      tree-sitter-go
+      tree-sitter-gomod
+      tree-sitter-hcl
+      tree-sitter-html
+      tree-sitter-java
+      tree-sitter-json
+      tree-sitter-latex
+      tree-sitter-make
+      tree-sitter-nix
+      tree-sitter-python
+      tree-sitter-rust
+      tree-sitter-sql
+      tree-sitter-toml
+      tree-sitter-yaml
+    ]);
 
-  tazjinsEmacs = pkgfun: (emacsWithPackages(epkgs: pkgfun(
-  # Actual ELPA packages (the enlightened!)
-  (with epkgs.elpaPackages; [
-    ace-window
-    avy
-    flymake
-    pinentry
-    rainbow-mode
-    undo-tree
-    xelb
-  ]) ++
+    tazjinsEmacs = pkgfun: (emacsWithPackages (epkgs: pkgfun (with epkgs; [
+      ace-link
+      ace-window
+      avy
+      bazel
+      browse-kill-ring
+      cargo
+      clojure-mode
+      consult
+      deft
+      direnv
+      elixir-mode
+      elm-mode
+      erlang
+      depotExwm
+      go-mode
+      google-c-style
+      gruber-darker-theme
+      haskell-mode
+      ht
+      hydra
+      idle-highlight-mode
+      inspector
+      jq-mode
+      kotlin-mode
+      kubernetes
+      magit
+      markdown-toc
+      multiple-cursors
+      nginx-mode
+      nix-mode
+      notmuch
+      paredit
+      password-store
+      pinentry
+      prescient
+      protobuf-mode
+      rainbow-delimiters
+      rainbow-mode
+      request
+      restclient
+      rust-mode
+      sly
+      string-edit-at-point
+      terraform-mode
+      undo-tree
+      uuidgen
+      vertico
+      vterm
+      web-mode
+      websocket
+      which-key
+      xelb
+      yasnippet
+      zetteldeft
+      zoxide
 
-  # MELPA packages:
-  (with epkgs.melpaPackages; [
-    ace-link
-    bazel-mode
-    browse-kill-ring
-    cargo
-    clojure-mode
-    cmake-mode
-    counsel
-    counsel-notmuch
-    dash-functional
-    direnv
-    dockerfile-mode
-    eglot
-    elixir-mode
-    elm-mode
-    erlang
-    geiser
-    go-mode
-    gruber-darker-theme
-    haskell-mode
-    ht
-    hydra
-    idle-highlight-mode
-    intero
-    ivy
-    ivy-pass
-    ivy-prescient
-    jq-mode
-    kotlin-mode
-    lispy
-    lsp-mode
-    magit
-    markdown-toc
-    meson-mode
-    multi-term
-    multiple-cursors
-    nginx-mode
-    nix-mode
-    notmuch # this comes from pkgs.third_party
-    org-journal
-    org-ql
-    paredit
-    password-store
-    pg
-    polymode
-    prescient
-    protobuf-mode
-    racket-mode
-    rainbow-delimiters
-    refine
-    request
-    restclient
-    sly
-    string-edit
-    swiper
-    telegaUnstable
-    telephone-line
-    terraform-mode
-    toml-mode
-    transient
-    use-package
-    uuidgen
-    web-mode
-    websocket
-    which-key
-    yaml-mode
-    yasnippet
-  ]) ++
+      # experimental (not otherwise embedded in config yet)
+      orderless
+      corfu
+      eat
 
-  # Custom packages
-  (with depot.tools.emacs-pkgs; [
-    dottime
-    nix-util
-    term-switcher
-    tvl
+      # Wonky stuff
+      (currentTelega epkgs)
+      customTreesitGrammars # TODO(tazjin): how is this *supposed* to work?!
 
-    # patched / overridden versions of packages
-    depot.third_party.emacs.exwm
-    depot.third_party.emacs.rcirc
-    depot.third_party.emacs.vterm
-    depot.third_party.emacs.explain-pause-mode
-  ]))));
-in lib.fix(self: l: f: third_party.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)" $@
-  '' // {
-    # Call overrideEmacs with a function (pkgs -> pkgs) to modify the
-    # packages that should be included in this Emacs distribution.
-    overrideEmacs = f': self l f';
+      # Custom depot packages (either ours, or overridden ones)
+      tvlPackages.dottime
+      tvlPackages.nix-util
+      tvlPackages.passively
+      tvlPackages.rcirc
+      tvlPackages.term-switcher
+      tvlPackages.treecrumbs
+      tvlPackages.tvl
 
-    # Call withLocalConfig with the path to a *folder* containing a
-    # `local.el` which provides local system configuration.
-    withLocalConfig = confDir: self confDir f;
+      # Dynamic/native modules
+      depot.users.tazjin.gio-list-apps
+    ])));
 
-    # Build a derivation that uses the specified local Emacs (i.e.
-    # built outside of Nix) instead
-    withLocalEmacs = emacsBin: third_party.writeShellScriptBin "tazjins-emacs" ''
+    # 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.runCommand "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"
-      export EMACSLOADPATH="${(tazjinsEmacs f).deps}/share/emacs/site-lisp:"
-      exec ${emacsBin} \
+      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 ""} \
+        --directory ${./config} ${if l != null then "--directory ${l}" else ""} \
+        --eval "(add-to-list 'treesit-extra-load-path \"${customTreesitGrammars}/lib\")" \
         --eval "(require 'init)" $@
-    '';
-  }) null identity
+    '').overrideAttrs
+      (_: {
+        passthru = {
+          # Expose original Emacs used for my configuration.
+          inherit emacs;
+
+          # Expose the pure emacs with all packages.
+          inherit emacsPackages;
+          emacsWithPackages = tazjinsEmacs f;
+
+          # 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;
+
+          # 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
+  )
+{ }