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
18 desktopApplicationFile = pkgs.writeTextFile {
19 name = "emacsclient.desktop";
20 destination = "/share/applications/emacsclient.desktop";
21 text = ''
22 [Desktop Entry]
23 Name=Emacsclient
24 GenericName=Text Editor
25 Comment=Edit text
26 MimeType=text/english;text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++;
27 Exec=emacseditor %F
28 Icon=emacs
29 Type=Application
30 Terminal=false
31 Categories=Development;TextEditor;
32 StartupWMClass=Emacs
33 Keywords=Text;Editor;
34 '';
35 };
36
37in
38{
39
40 options.services.emacs = {
41 enable = mkOption {
42 type = types.bool;
43 default = false;
44 description = lib.mdDoc ''
45 Whether to enable a user service for the Emacs daemon. Use `emacsclient` to connect to the
46 daemon. If `true`, {var}`services.emacs.install` is
47 considered `true`, whatever its value.
48 '';
49 };
50
51 install = mkOption {
52 type = types.bool;
53 default = false;
54 description = lib.mdDoc ''
55 Whether to install a user service for the Emacs daemon. Once
56 the service is started, use emacsclient to connect to the
57 daemon.
58
59 The service must be manually started for each user with
60 "systemctl --user start emacs" or globally through
61 {var}`services.emacs.enable`.
62 '';
63 };
64
65
66 package = mkOption {
67 type = types.package;
68 default = pkgs.emacs;
69 defaultText = literalExpression "pkgs.emacs";
70 description = lib.mdDoc ''
71 emacs derivation to use.
72 '';
73 };
74
75 defaultEditor = mkOption {
76 type = types.bool;
77 default = false;
78 description = lib.mdDoc ''
79 When enabled, configures emacsclient to be the default editor
80 using the EDITOR environment variable.
81 '';
82 };
83 };
84
85 config = mkIf (cfg.enable || cfg.install) {
86 systemd.user.services.emacs = {
87 description = "Emacs: the extensible, self-documenting text editor";
88
89 serviceConfig = {
90 Type = "forking";
91 ExecStart = "${pkgs.bash}/bin/bash -c 'source ${config.system.build.setEnvironment}; exec ${cfg.package}/bin/emacs --daemon'";
92 ExecStop = "${cfg.package}/bin/emacsclient --eval (kill-emacs)";
93 Restart = "always";
94 };
95 } // optionalAttrs cfg.enable { wantedBy = [ "default.target" ]; };
96
97 environment.systemPackages = [ cfg.package editorScript desktopApplicationFile ];
98
99 environment.variables.EDITOR = mkIf cfg.defaultEditor (mkOverride 900 "${editorScript}/bin/emacseditor");
100 };
101
102 meta.doc = ./emacs.md;
103}