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.
This commit is contained in:
parent
7848f69115
commit
b3ed7ea627
4 changed files with 215 additions and 5 deletions
34
HACKING.md
34
HACKING.md
|
|
@ -53,3 +53,37 @@ 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 Doom’s 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.
|
||||
|
|
|
|||
62
README.md
62
README.md
|
|
@ -37,6 +37,40 @@ doom-config.url = "...";
|
|||
doom-config.flake = false;
|
||||
```
|
||||
|
||||
Next, you have two options:
|
||||
|
||||
#### Home Manager
|
||||
|
||||
Add Unstraightened's home-manager module:
|
||||
|
||||
``` nix
|
||||
imports = [ inputs.nix-doom-emacs-unstraightened.hmModule ];
|
||||
```
|
||||
|
||||
Configure it:
|
||||
|
||||
``` nix
|
||||
programs.doom-emacs = {
|
||||
enable = true;
|
||||
doomDir = inputs.doom-config;
|
||||
# Any Emacs >= 29 should work. Defaults to pkgs.emacs.
|
||||
emacs = pkgs.emacs29-pgtk;
|
||||
};
|
||||
```
|
||||
|
||||
There are a few other options, see below.
|
||||
|
||||
If you set `services.emacs.enable = true`, that will run Unstraightened as well
|
||||
(Unstraightened sets itself as `services.emacs.package`). Set
|
||||
`programs.doom-emacs.provideEmacs = false` or override `services.emacs.package`
|
||||
if you want a vanilla Emacs daemon instead.
|
||||
|
||||
> [!WARNING]
|
||||
> Using the overlay described below with `programs.emacs.package` will not work
|
||||
> correctly (see HACKING.md for details).
|
||||
|
||||
#### Overlay
|
||||
|
||||
Add Unstraightened's overlay. Typically that means adding:
|
||||
|
||||
``` nix
|
||||
|
|
@ -45,7 +79,7 @@ nixpkgs.overlays = [ inputs.nix-doom-emacs-unstraightened.overlays.default ];
|
|||
|
||||
to a home-manager or NixOS module.
|
||||
|
||||
Next, you have two options:
|
||||
The overlay adds two packages:
|
||||
|
||||
- To install Unstraightened in parallel with a normal Emacs, add:
|
||||
|
||||
|
|
@ -69,10 +103,6 @@ Next, you have two options:
|
|||
`emacsclient` and other helpers (similar to [`emacsWithPackages` in
|
||||
nixpkgs](https://nixos.org/manual/nixos/stable/#module-services-emacs-adding-packages)).
|
||||
|
||||
If you use home-manager, setting `programs.emacs.package = pkgs.emacsWithDoom
|
||||
{ ... };` should work (and `services.emacs` should be able to use this
|
||||
package).
|
||||
|
||||
### Without flakes
|
||||
|
||||
This is currently not explicitly supported, but should be possible (use
|
||||
|
|
@ -109,6 +139,12 @@ welcome, as are (within reason) changes necessary to support use without flakes.
|
|||
There are a few other settings but they are not typically useful. See the
|
||||
source.
|
||||
|
||||
The home-manager module supports the same options, as well as:
|
||||
|
||||
- `provideEmacs`: disable this to only provide a `doom-emacs` binary, not an
|
||||
`emacs` binary (that is: it switches from `emacsWithDoom` to `doomEmacs`). Use
|
||||
this if you want to install vanilla Emacs in parallel.
|
||||
|
||||
## Comparison to "normal" Doom Emacs
|
||||
|
||||
- Unstraightened updates Doom and its dependencies along with the rest of your
|
||||
|
|
@ -261,6 +297,22 @@ Safe to ignore, for the same reason as the previous warning.
|
|||
|
||||
## Frequently Anticipated Questions
|
||||
|
||||
### How do I add more packages?
|
||||
|
||||
Add `(package! foo)` to `packages.el`.
|
||||
|
||||
Do not wrap emacsWithDoom in emacsWithPackages. See HACKING.md for why this will
|
||||
not work.
|
||||
|
||||
If this is not sufficient, file an issue. I can add a hook to add more packages
|
||||
from Nix: I just don't want to add that hook unless someone has a use for it.
|
||||
|
||||
### How do I add packages not in Emacs overlay?
|
||||
|
||||
Add `(package! foo :recipe ...)` to `packages.el`.
|
||||
|
||||
If this is not sufficient, file an issue explaining what you're trying to do.
|
||||
|
||||
### What's wrong with `straight.el`?
|
||||
|
||||
`straight.el` is great, but its features are somewhat at odds with Nix:
|
||||
|
|
|
|||
|
|
@ -62,5 +62,9 @@
|
|||
doomEmacs = args: (callPackages args).doomEmacs;
|
||||
emacsWithDoom = args: (callPackages args).emacsWithDoom;
|
||||
};
|
||||
hmModule = import ./home-manager.nix {
|
||||
doomSource = doomemacs;
|
||||
emacsOverlay = emacs-overlay.overlays.package;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
120
home-manager.nix
Normal file
120
home-manager.nix
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
# Copyright 2024 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
{ doomSource, emacsOverlay }:
|
||||
{ config, options, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.programs.doom-emacs;
|
||||
inherit (lib) literalExpression mkEnableOption mkIf mkMerge mkOption types;
|
||||
in {
|
||||
options = {
|
||||
programs.doom-emacs = {
|
||||
enable = mkEnableOption "Doom Emacs";
|
||||
|
||||
emacs = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.emacs;
|
||||
defaultText = literalExpression "pkgs.emacs";
|
||||
example = literalExpression "pkgs.emacs29-pgtk";
|
||||
description = "The Emacs package to wrap.";
|
||||
};
|
||||
|
||||
doomDir = mkOption {
|
||||
type = types.path;
|
||||
example = literalExpression "./doom";
|
||||
description = "The DOOMDIR to build from and bundle.";
|
||||
};
|
||||
|
||||
doomLocalDir = mkOption {
|
||||
type = types.path;
|
||||
default = "${config.xdg.dataHome}/nix-doom";
|
||||
defaultText = literalExpression ''"''${config.xdg.dataHome}/nix-doom"'';
|
||||
example = literalExpression "~/.local/state/doom";
|
||||
description = ''
|
||||
DOOMLOCALDIR.
|
||||
|
||||
`~` is expanded, but shell variables are not! Use `config.xdg.*`, not
|
||||
`XDG_DATA_*`.'';
|
||||
};
|
||||
|
||||
profileName = mkOption {
|
||||
type = types.str;
|
||||
default = "nix";
|
||||
example = literalExpression "";
|
||||
description = "Doom profile. Set to the empty string to disable.";
|
||||
};
|
||||
|
||||
noProfileHack = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
example = true;
|
||||
description = ''
|
||||
Use a hack to make Doom use normal paths (relative to DOOMLOCALDIR).
|
||||
|
||||
Has no effect if doomProfile is unset (set to the empty string).
|
||||
|
||||
Currently not recommended: unset doomProfile instead;
|
||||
'';
|
||||
};
|
||||
|
||||
provideEmacs = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
example = false;
|
||||
description = ''
|
||||
If enabled (the default), provide "emacs" (and "emacsclient", etc).
|
||||
If disabled, provide a "doom-emacs" binary.
|
||||
|
||||
Disable this to install doom-emacs in parallel with vanilla Emacs.
|
||||
'';
|
||||
};
|
||||
|
||||
finalEmacsPackage = mkOption {
|
||||
type = types.package;
|
||||
visible = false;
|
||||
readOnly = true;
|
||||
description = "The final Emacs-compatible package";
|
||||
};
|
||||
|
||||
finalDoomPackage = mkOption {
|
||||
type = types.package;
|
||||
visible = false;
|
||||
readOnly = true;
|
||||
description = "The final doom-emacs package";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable (mkMerge [
|
||||
(let
|
||||
doomPackages = (pkgs.extend emacsOverlay).callPackages ./doom.nix {
|
||||
inherit doomSource;
|
||||
inherit (cfg) emacs doomDir doomLocalDir profileName noProfileHack;
|
||||
};
|
||||
in
|
||||
{
|
||||
programs.doom-emacs.finalDoomPackage = doomPackages.doomEmacs;
|
||||
programs.doom-emacs.finalEmacsPackage = doomPackages.emacsWithDoom;
|
||||
})
|
||||
{
|
||||
home.packages = [(
|
||||
if cfg.provideEmacs then cfg.finalEmacsPackage else cfg.finalDoomPackage
|
||||
)];
|
||||
}
|
||||
(mkIf (options.services ? emacs && cfg.provideEmacs) {
|
||||
services.emacs.package = cfg.finalEmacsPackage;
|
||||
})
|
||||
]);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue