nix-doom-emacs-unstraightened/HACKING.md
Marien Zwart b3ed7ea627
Add a Home Manager module
It turns out using Home Manager's `programs.emacs` module does not work
correctly. Document that in HACKING.md for future reference.
2024-04-29 15:46:13 +10:00

89 lines
4.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Internals/design notes
## Why [profiles](https://github.com/doomemacs/doomemacs/tree/master/profiles)?
Because the profile loader runs early enough we can set `doom-profile-data-dir`
(where the generated profile is stored and loaded from) outside `DOOMLOCALDIR`
relatively cleanly. Not using the "global" profile is a largely unintended side
effect, but the changes to other paths made seem largely reasonable so for now
I'm sticking with it.
After the profile loader, the next point we would get control is `doom-start.el`
loading `init.el` from `doom-user-dir`. We currently point `doom-user-dir` into
the store (see below): setting `doom-profile-data-dir` and `doom-profile-dir`
from there (by prepending to the user's `init.el`) would probably also work.
This seems a bit questionable because `doom-profile-dir` is set with `defconst`:
its const-ness is not enforced but I'd prefer not to take advantage of that. I
also have not checked if writing the profile would work out of the box with this
approach.
`noProfileHack` unsets `DOOMPROFILE` from the profile loader. This feels like a
hack, but it does get us the usual `DOOMLOCALDIR`-relative `doom-cache-dir` and
friends back.
## Why put `doom-user-dir`/`DOOMDIR` in the Nix store?
Doom forces my hand. I would prefer for just `packages.el` and possibly
`init.el` to live in the store, but splitting out where those are loaded from
looks non-trivial.
Doom uses `doom-user-dir` as the path to a special module (`:user`).
At profile generation time, this is how `packages.el` gets loaded. We want our
generated `packages.el` to take effect, so we want the `:user` module's path to
be a store path when generating the profile.
Paths to all modules are embedded in the generated profile and used to
initialize `doom-modules` at runtime. Among other things, this controls where
the user's `config.el` is loaded from (it's loaded along with module `config.el`
files). So (without further hacks) the path to `packages.el` at build time and
`config.el` at runtime are the same.
(And even if that wasn't the case, functions like `doom/help-packages` load
`packages.el`, and I currently expect less overall confusion if that loads our
generated `packages.el`, not the original one. So I do think we want the `:user`
module loaded from the store.)
In several places, Doom assumes (at runtime) that `doom-user-dir` and the path
to the `:user` module are the same. This is mostly in functions like
`doom/help-packages` and `doom-module-from-path` that map paths back to modules.
Combine all that and I think consistently having `doom-user-dir` and the `:user`
module live in the Nix store is the least bad option.
This does break things that write to DOOMDIR at runtime. `custom-file` is an
obvious example, but there are probably a few more.
## `programs.emacs.package` / nesting emacsWithPackages
Home Manager's `programs.emacs` wraps its Emacs package with emacsWithPackages.
We don't work as an input to emacsWithPackages.
First bug: emacsWithPackages writes a site-start that loads
`$emacs/share/site-lisp/site-start` first. That is: it assumes the emacs package
it wraps has its own site-start. That's true if it's an actual emacs but at
first glance might also break if it's another emacsWithPackages, because its
site-start goes in a separate `emacs-packages-deps` derivation (I didn't test
this further).
We could fix that (by adding a trivial site-start.el of our own), but there's a
second bug: when Doom loads its profile, it overwrites `load-path`. This defeats
the purpose of having that outer emacsWithPackages in the first place.
During normal interactive startup, the second bug masks the first: site-start
gets loaded from the Doom profile's load path, skipping the outer
emacsWithPackages entirely. So at first glance the Home Manager `programs.emacs`
module will seem to work...
During non-interactive startup, the first bug surfaces. The easiest way of
triggering this is `doom` cli, which fails with:
```
Unexpected error in Dooms core: "/nix/store/3hr4amd670vbf5h1w1jw18y3a9hv1689-source/lisp/doom-cli.el", (file-missing "Cannot open load file" "No such file or directory" "/nix/store/7vvp8axf8h4qrx7mj3mh1dsxj80393k2-emacs-pgtk-with-doom-29.3/share/emacs/site-lisp/site-start")
```
Setting DEBUG=1 makes it more obvious where this fails (doom-cli.el loads
site-start).
Non-interactive use of emacs also seems to trigger this: in particular it breaks
flycheck of elisp code with a similar error message about site-start.