1{
2 config,
3 lib,
4 pkgs,
5 ...
6}:
7let
8
9 cfg = config.services.emacs;
10
11 editorScript = pkgs.writeShellScriptBin "emacseditor" ''
12 if [ -z "$1" ]; then
13 exec ${cfg.package}/bin/emacsclient --create-frame --alternate-editor ${cfg.package}/bin/emacs
14 else
15 exec ${cfg.package}/bin/emacsclient --alternate-editor ${cfg.package}/bin/emacs "$@"
16 fi
17 '';
18
19in
20{
21
22 options.services.emacs = {
23 enable = lib.mkOption {
24 type = lib.types.bool;
25 default = false;
26 description = ''
27 Whether to enable a user service for the Emacs daemon. Use `emacsclient` to connect to the
28 daemon. If `true`, {var}`services.emacs.install` is
29 considered `true`.
30 '';
31 };
32
33 install = lib.mkOption {
34 type = lib.types.bool;
35 default = false;
36 description = ''
37 Whether to install a user service for the Emacs daemon. Once
38 the service is started, use emacsclient to connect to the
39 daemon.
40
41 The service must be manually started for each user with
42 "systemctl --user start emacs" or globally through
43 {var}`services.emacs.enable`.
44 '';
45 };
46
47 package = lib.mkPackageOption pkgs "emacs" { };
48
49 defaultEditor = lib.mkOption {
50 type = lib.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 = lib.mkOption {
59 type = lib.types.bool;
60 default = config.services.xserver.enable;
61 defaultText = lib.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 = lib.mkIf (cfg.enable || cfg.install) {
69 systemd.user.services.emacs =
70 {
71 description = "Emacs: the extensible, self-documenting text editor";
72
73 serviceConfig = {
74 Type = "notify";
75 ExecStart = "${pkgs.runtimeShell} -c 'source ${config.system.build.setEnvironment}; exec ${cfg.package}/bin/emacs --fg-daemon'";
76 # Emacs exits with exit code 15 (SIGTERM), when stopped by systemd.
77 SuccessExitStatus = 15;
78 Restart = "always";
79 };
80
81 unitConfig = lib.optionalAttrs cfg.startWithGraphical {
82 After = "graphical-session.target";
83 };
84 }
85 // lib.optionalAttrs cfg.enable {
86 wantedBy = if cfg.startWithGraphical then [ "graphical-session.target" ] else [ "default.target" ];
87 };
88
89 environment.systemPackages = [
90 cfg.package
91 editorScript
92 ];
93
94 environment.variables.EDITOR = lib.mkIf cfg.defaultEditor (lib.mkOverride 900 "emacseditor");
95 };
96
97 meta.doc = ./emacs.md;
98}