1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6
7 cfg = config.services.emacs;
8
9 editorScript = pkgs.writeScriptBin "emacseditor" ''
10 #!${pkgs.runtimeShell}
11 if [ -z "$1" ]; then
12 exec ${cfg.package}/bin/emacsclient --create-frame --alternate-editor ${cfg.package}/bin/emacs
13 else
14 exec ${cfg.package}/bin/emacsclient --alternate-editor ${cfg.package}/bin/emacs "$@"
15 fi
16 '';
17
18in
19{
20
21 options.services.emacs = {
22 enable = mkOption {
23 type = types.bool;
24 default = false;
25 description = ''
26 Whether to enable a user service for the Emacs daemon. Use `emacsclient` to connect to the
27 daemon. If `true`, {var}`services.emacs.install` is
28 considered `true`, whatever its value.
29 '';
30 };
31
32 install = mkOption {
33 type = types.bool;
34 default = false;
35 description = ''
36 Whether to install a user service for the Emacs daemon. Once
37 the service is started, use emacsclient to connect to the
38 daemon.
39
40 The service must be manually started for each user with
41 "systemctl --user start emacs" or globally through
42 {var}`services.emacs.enable`.
43 '';
44 };
45
46
47 package = mkPackageOption pkgs "emacs" { };
48
49 defaultEditor = mkOption {
50 type = types.bool;
51 default = false;
52 description = ''
53 When enabled, configures emacsclient to be the default editor
54 using the EDITOR environment variable.
55 '';
56 };
57
58 startWithGraphical = mkOption {
59 type = types.bool;
60 default = config.services.xserver.enable;
61 defaultText = literalExpression "config.services.xserver.enable";
62 description = ''
63 Start emacs with the graphical session instead of any session. Without this, emacs clients will not be able to create frames in the graphical session.
64 '';
65 };
66 };
67
68 config = mkIf (cfg.enable || cfg.install) {
69 systemd.user.services.emacs = {
70 description = "Emacs: the extensible, self-documenting text editor";
71
72 serviceConfig = {
73 Type = "forking";
74 ExecStart = "${pkgs.bash}/bin/bash -c 'source ${config.system.build.setEnvironment}; exec ${cfg.package}/bin/emacs --daemon'";
75 ExecStop = "${cfg.package}/bin/emacsclient --eval (kill-emacs)";
76 Restart = "always";
77 };
78
79 unitConfig = optionalAttrs cfg.startWithGraphical {
80 After = "graphical-session.target";
81 };
82 } // optionalAttrs cfg.enable {
83 wantedBy = if cfg.startWithGraphical then [ "graphical-session.target" ] else [ "default.target" ];
84 };
85
86 environment.systemPackages = [ cfg.package editorScript ];
87
88 environment.variables.EDITOR = mkIf cfg.defaultEditor (mkOverride 900 "emacseditor");
89 };
90
91 meta.doc = ./emacs.md;
92}