[PATCH 0/1] gnu: home: Add home-emacs-service-type.

  • Done
  • quality assurance status badge
Details
4 participants
  • Liliana Marie Prikler
  • Ludovic Courtès
  • Christopher Baines
  • (
Owner
unassigned
Submitted by
(
Severity
normal
Merged with
(
(address . guix-patches@gnu.org)(name . ()(address . paren@disroot.org)
20221021192328.4833-1-paren@disroot.org
Hey Guix!

This patch finally adds a home-emacs-service-type, which supports:

- Setting up the ``init.el'' and ``early-init.el'' files.
- Automatically running the Emacs daemon.
- Natively compiling the given Emacs packages if ``native-compile?''
is enabled.
- Loading the given Emacs packages *without* installing them into
the profile, by setting EMACSLOADPATH and EMACSNATIVELOADPATH
appropriately before launching the daemon.
- Enabling ``--debug-init''.

I hope it'll see plenty of use :)

( (1):
gnu: home: Add home-emacs-service-type.

doc/guix.texi | 51 ++++++++++++
gnu/home/services/emacs.scm | 162 ++++++++++++++++++++++++++++++++++++
gnu/local.mk | 1 +
3 files changed, 214 insertions(+)
create mode 100644 gnu/home/services/emacs.scm


base-commit: 4716cea6256523a8ecf90a426d675bfb7620f3e4
--
2.38.0
(
[PATCH 1/1] gnu: home: Add home-emacs-service-type.
(address . 58693@debbugs.gnu.org)(name . ()(address . paren@disroot.org)
20221021192458.4956-1-paren@disroot.org
* gnu/local.mk (GNU_SYSTEM_MODULES): Add gnu/home/services/emacs.scm.
* gnu/home/services/emacs.scm (home-emacs-configuration): New
record type.
(home-emacs-service-type): New variable.
* doc/guix.texi: Document them.
---
doc/guix.texi | 51 ++++++++++++
gnu/home/services/emacs.scm | 162 ++++++++++++++++++++++++++++++++++++
gnu/local.mk | 1 +
3 files changed, 214 insertions(+)
create mode 100644 gnu/home/services/emacs.scm

Toggle diff (251 lines)
diff --git a/doc/guix.texi b/doc/guix.texi
index 3bf2dee752..dc27b7437e 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -40517,6 +40517,7 @@ services)}.
* Shepherd: Shepherd Home Service. Managing User's Daemons.
* SSH: Secure Shell. Setting up the secure shell client.
* Desktop: Desktop Home Services. Services for graphical environments.
+* Emacs: Emacs Home Service. Service for running Emacs.
* Guix: Guix Home Services. Services for Guix.
@end menu
@c In addition to that Home Services can provide
@@ -41348,6 +41349,56 @@ The package providing the @code{/bin/dbus-daemon} command.
@end table
@end deftp
+@node Emacs Home Service
+@subsection Emacs Home Service
+
+@defvr {Scheme Variable} home-emacs-service-type
+This is the service type for configuring the Emacs text editor and
+running its daemon.
+
+Note that if you have an existing @file{~/.emacs} and/or
+@file{~/.emacs.d}, the configuration aspect of this service will
+not function, as they take precedence over @file{~/.config/emacs},
+which this service uses in the interest of cleanliness. To migrate
+to the XDG directory, run these commands:
+
+@example
+$ cp ~/.emacs.d $XDG_CONFIG_HOME/emacs
+$ cp ~/.emacs $XDG_CONFIG_HOME/emacs/init.el
+@end example
+@end defvr
+
+@deftp {Data Type} home-emacs-configuration
+The configuration record for @code{home-emacs-service-type}.
+
+@table @asis
+@item @code{emacs} (default: @code{emacs})
+The package providing the @file{/bin/emacs} and @file{/bin/emacsclient}
+commands.
+
+@item @code{packages} (default: @code{'()})
+Packages providing Emacs plugins to add to the daemon's load paths.
+
+@item @code{native-compile?} (default: @code{#f})
+Whether to recompile all @code{packages}, using the provided @code{emacs}
+package in place of @code{emacs-minimal}, which will enable native
+compilation if the @code{emacs} package supports it. All
+non-@code{-minimal} Emacs packages at version 28 or above should support
+native compilation.
+
+@item @code{init-file} (default: @code{(plain-file "init.el" "")})
+The file-like to use as @file{init.el}, the main Emacs configuration
+file.
+
+@item @code{early-init-file} (default: @code{(plain-file "early-init.el" "")})
+The file-like to use as @file{early-init.el}, which is loaded early in
+the initialisation process, before the GUI is started.
+
+@item @code{debug?} (default: @code{#f})
+Whether to enable detailed debug log output with backtraces.
+@end table
+@end deftp
+
@node Guix Home Services
@subsection Guix Home Services
diff --git a/gnu/home/services/emacs.scm b/gnu/home/services/emacs.scm
new file mode 100644
index 0000000000..a727a2f246
--- /dev/null
+++ b/gnu/home/services/emacs.scm
@@ -0,0 +1,162 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2022 ( <paren@disroot.org>
+;;;
+;;; This file is part of GNU Guix.
+;;;
+;;; GNU Guix is free software; you can redistribute it and/or modify it
+;;; under the terms of the GNU General Public License as published by
+;;; the Free Software Foundation; either version 3 of the License, or (at
+;;; your option) any later version.
+;;;
+;;; GNU Guix is distributed in the hope that it will be useful, but
+;;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;;; GNU General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
+
+(define-module (gnu home services emacs)
+ #:use-module (gnu home services)
+ #:use-module (gnu home services shepherd)
+ #:autoload (gnu packages emacs) (emacs-minimal
+ emacs)
+ #:use-module (gnu services configuration)
+ #:use-module (guix gexp)
+ #:use-module (guix packages)
+ #:use-module (guix records)
+ #:use-module (srfi srfi-1)
+ #:use-module (srfi srfi-26)
+
+ #:export (home-emacs-configuration
+ home-emacs-service-type))
+
+(define list-of-file-likes?
+ (list-of file-like?))
+
+(define-configuration/no-serialization home-emacs-configuration
+ (emacs
+ (file-like emacs)
+ "The package providing @file{/bin/emacs}.")
+ (packages
+ (list-of-file-likes '())
+ "Packages to add to the Emacs plugin load path.")
+ (native-compile?
+ (boolean #f)
+ "Whether to compile the @code{packages} using the Emacs package
+provided as the value of the @code{emacs} field, which will enable
+native compilation if the @code{emacs} package supports it.")
+ (init-file
+ (file-like (plain-file "init.el" ""))
+ "File-like to use as the initialisation Lisp file.")
+ (early-init-file
+ (file-like (plain-file "early-init.el" ""))
+ "File-like to use as the pre-initialisation Lisp file.")
+ (debug?
+ (boolean #f)
+ "Whether to enable debugging."))
+
+(define (home-emacs-profile-packages config)
+ (list (home-emacs-configuration-emacs config)))
+
+(define (home-emacs-transformed-packages config)
+ (map (if (home-emacs-configuration-native-compile? config)
+ (package-input-rewriting
+ `((,emacs-minimal
+ . ,(home-emacs-configuration-emacs config))))
+ identity)
+ (let ((packages (home-emacs-configuration-packages config)))
+ (concatenate
+ (cons packages
+ (map (compose (cute map second <>)
+ package-transitive-propagated-inputs)
+ packages))))))
+
+(define (home-emacs-shepherd-services config)
+ (list (shepherd-service
+ (provision '(emacs))
+ (documentation "Start the Emacs daemon.")
+ (modules '((ice-9 ftw)
+ (srfi srfi-1)
+ (srfi srfi-26)))
+ (start
+ #~(make-forkexec-constructor
+ (list #$(file-append
+ (home-emacs-configuration-emacs config)
+ "/bin/emacs")
+ "--fg-daemon" "--eval"
+ (format #f "~s"
+ `(progn
+ (setq custom-file
+ (concat (or (getenv "XDG_CONFIG_HOME")
+ (concat (getenv "HOME")
+ "/.config"))
+ "/emacs/custom.el"))
+ (load custom-file)))
+ #$@(if (home-emacs-configuration-debug? config)
+ (list "--debug-init")
+ '()))
+ #:log-file
+ (format #f "~a/emacs.log"
+ (or (getenv "XDG_LOG_HOME")
+ (format #f "~a/.local/var/log"
+ (getenv "HOME"))))
+ #:environment-variables
+ (let ((env-var
+ (lambda (name path)
+ (define (regular-directory? directory)
+ (not (member directory (list "." ".."))))
+
+ (define (package-paths package)
+ (let ((directory (string-append package "/" path)))
+ (if (file-exists? directory)
+ (cons directory
+ (map (cute string-append directory "/" <>)
+ (scandir directory regular-directory?)))
+ '())))
+
+ (let ((old-value (getenv name)))
+ (string-append
+ name "="
+ (string-join
+ (append-map
+ package-paths
+ (list #$@(home-emacs-transformed-packages config)))
+ ":" (if old-value
+ 'suffix
+ 'infix))
+ (or old-value ""))))))
+ (append (default-environment-variables)
+ (list (env-var "EMACSLOADPATH"
+ "share/emacs/site-lisp")
+ (env-var "EMACSNATIVELOADPATH"
+ "lib/emacs/native-site-lisp"))))))
+ (stop
+ #~(make-forkexec-constructor
+ (list #$(file-append
+ (home-emacs-configuration-emacs config)
+ "/bin/emacsclient")
+ "--eval" "(kill-emacs)"))))))
+
+(define (home-emacs-xdg-configuration-files config)
+ `(("emacs/early-init.el"
+ ,(home-emacs-configuration-early-init-file config))
+ ("emacs/init.el"
+ ,(home-emacs-configuration-init-file config))))
+
+(define home-emacs-service-type
+ (service-type
+ (name 'home-emacs)
+ (extensions
+ (list (service-extension
+ home-profile-service-type
+ home-emacs-profile-packages)
+ (service-extension
+ home-shepherd-service-type
+ home-emacs-shepherd-services)
+ (service-extension
+ home-xdg-configuration-files-service-type
+ home-emacs-xdg-configuration-files)))
+ (default-value (home-emacs-configuration))
+ (description
+ "Configure and run the GNU Emacs extensible text editor.")))
diff --git a/gnu/local.mk b/gnu/local.mk
index 8247180bef..3431c771b8 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -88,6 +88,7 @@ GNU_SYSTEM_MODULES = \
%D%/home/services.scm \
%D%/home/services/desktop.scm \
%D%/home/services/symlink-manager.scm \
+ %D%/home/services/emacs.scm \
%D%/home/services/fontutils.scm \
%D%/home/services/guix.scm \
%D%/home/services/pm.scm \
--
2.38.0
L
L
Liliana Marie Prikler wrote on 22 Oct 2022 11:41
(address . control@debbugs.gnu.org)
9c453dd100e4d66d458a217f448c0b2362adc2f2.camel@gmail.com
merge 58693 58652
thanks

Am Freitag, dem 21.10.2022 um 20:24 +0100 schrieb (:
Toggle quote (51 lines)
> +(define-configuration/no-serialization home-emacs-configuration
> +  (emacs
> +   (file-like emacs)
> +   "The package providing @file{/bin/emacs}.")
> +  (packages
> +   (list-of-file-likes '())
> +   "Packages to add to the Emacs plugin load path.")
> +  (native-compile?
> +   (boolean #f)
> +   "Whether to compile the @code{packages} using the Emacs package
> +provided as the value of the @code{emacs} field, which will enable
> +native compilation if the @code{emacs} package supports it.")
> +  (init-file
> +   (file-like (plain-file "init.el" ""))
> +   "File-like to use as the initialisation Lisp file.")
> +  (early-init-file
> +   (file-like (plain-file "early-init.el" ""))
> +   "File-like to use as the pre-initialisation Lisp file.")
> +  (debug?
> +   (boolean #f)
> +   "Whether to enable debugging."))
> +
> +(define (home-emacs-profile-packages config)
> +  (list (home-emacs-configuration-emacs config)))
> +
> +(define (home-emacs-transformed-packages config)
> +  (map (if (home-emacs-configuration-native-compile? config)
> +           (package-input-rewriting
> +            `((,emacs-minimal
> +              . ,(home-emacs-configuration-emacs config))))
> +           identity)
> +       (let ((packages (home-emacs-configuration-packages config)))
> +         (concatenate
> +          (cons packages
> +                (map (compose (cute map second <>)
> +                              package-transitive-propagated-inputs)
> +                     packages))))))
> +
> +(define (home-emacs-shepherd-services config)
> +  (list (shepherd-service
> +         (provision '(emacs))
> +         (documentation "Start the Emacs daemon.")
> +         (modules '((ice-9 ftw)
> +                    (srfi srfi-1)
> +                    (srfi srfi-26)))
> +         (start
> +          #~(make-forkexec-constructor
> +             (list #$(file-append
> +                      (home-emacs-configuration-emacs config)
> +                      "/bin/emacs")
> +                   "--fg-daemon" "--eval"
You should probably use a systemd-style constructor/destructor pair.

Toggle quote (10 lines)
> +                   (format #f "~s"
> +                           `(progn
> +                             (setq custom-file
> +                                   (concat (or (getenv
> "XDG_CONFIG_HOME")
> +                                               (concat (getenv
> "HOME")
> +                                                       "/.config"))
> +                                           "/emacs/custom.el"))
> +                             (load custom-file)))
This one should be customizable by the user using init.el or early-
init.el -- alternatively, you could set up a custom-file parameter and
use that *if given*.

Toggle quote (8 lines)
> +                   #$@(if (home-emacs-configuration-debug? config)
> +                          (list "--debug-init")
> +                          '()))
> +             #:log-file
> +             (format #f "~a/emacs.log"
> +                     (or (getenv "XDG_LOG_HOME")
> +                         (format #f "~a/.local/var/log"
> +                                 (getenv "HOME"))))
XDG_LOG_HOME and ~/.local/var are guix home idiosyncrasies that ought
to be removed. The XDG-supported variable/value pair is XDG_STATE_HOME
and ~/.local/state.

Toggle quote (35 lines)
> +             #:environment-variables
> +             (let ((env-var
> +                    (lambda (name path)
> +                      (define (regular-directory? directory)
> +                        (not (member directory (list "." ".."))))
> +
> +                      (define (package-paths package)
> +                        (let ((directory (string-append package "/"
> path)))
> +                          (if (file-exists? directory)
> +                              (cons directory
> +                                    (map (cute string-append
> directory "/" <>)
> +                                         (scandir directory regular-
> directory?)))
> +                              '())))
> +
> +                      (let ((old-value (getenv name)))
> +                        (string-append
> +                         name "="
> +                         (string-join
> +                          (append-map
> +                           package-paths
> +                           (list #$@(home-emacs-transformed-packages
> config)))
> +                          ":" (if old-value
> +                                  'suffix
> +                                  'infix))
> +                         (or old-value ""))))))
> +               (append (default-environment-variables)
> +                       (list (env-var "EMACSLOADPATH"
> +                                      "share/emacs/site-lisp")
> +                             (env-var "EMACSNATIVELOADPATH"
> +                                      "lib/emacs/native-site-
> lisp"))))))
You should collect the emacs package plus lisp packages into a profile.
This will make it easier to set emacs-related variables.
Alternatively, you could use (guix search-paths) directly.

Toggle quote (12 lines)
> +         (stop
> +          #~(make-forkexec-constructor
> +             (list #$(file-append
> +                      (home-emacs-configuration-emacs config)
> +                      "/bin/emacsclient")
> +                   "--eval" "(kill-emacs)"))))))
> +
> +(define (home-emacs-xdg-configuration-files config)
> +  `(("emacs/early-init.el"
> +     ,(home-emacs-configuration-early-init-file config))
> +    ("emacs/init.el"
> +     ,(home-emacs-configuration-init-file config))))
You're missing an escape hatch for additional elisp files like
custom.el

Cheers
C
C
Christopher Baines wrote on 3 Nov 2022 17:15
tag 58693 moreinfo
(address . control@debbugs.gnu.org)
87bkpodng5.fsf@cbaines.net
tags 58693 + moreinfo
quit
L
L
Ludovic Courtès wrote on 8 Nov 2022 13:59
Re: bug#58693: [PATCH 0/1] gnu: home: Add home-emacs-service-type.
(name . ()(address . paren@disroot.org)(address . 58693@debbugs.gnu.org)
87r0ydpppd.fsf_-_@gnu.org
Hi!

"(" <paren@disroot.org> skribis:

Toggle quote (4 lines)
> +@defvr {Scheme Variable} home-emacs-service-type
> +This is the service type for configuring the Emacs text editor and
> +running its daemon.

I would happily use some Guix Home service to configure Emacs, but I
don’t want to start it as a daemon (currently I start it from
~/.xsession as I use EXWM).

Could we somehow decouple the daemon aspect from the rest?

Anyhow, I’m glad to see this work—thank you!

Ludo’.
(
(name . Ludovic Courtès)(address . ludo@gnu.org)(address . 58693@debbugs.gnu.org)
CO722PUIF0EZ.15MR603XCFC8F@guix-framework
Heya,

On Tue Nov 8, 2022 at 12:59 PM GMT, Ludovic Courtès wrote:
Toggle quote (6 lines)
> I would happily use some Guix Home service to configure Emacs, but I
> don’t want to start it as a daemon (currently I start it from
> ~/.xsession as I use EXWM).
>
> Could we somehow decouple the daemon aspect from the rest?

There's virtually no point in doing so. This service doesn't generate ELisp from
a Scheme config, as I think Emacs is too flexible for that; instead, it lets you
choose the packages, init file, etc to pass to the daemon (which is what is meant
by "configure", I suppose).

-- (
(
Superseded
(address . control@debbugs.gnu.org)
CRJY94RLQVVE.2KS5EOOGXQDHL@guix-framework
close 58693
thanks

Superseded by 62549.

-- (
-----BEGIN PGP SIGNATURE-----

iQGzBAABCgAdFiEE6Vh10NblKE5doNlW7ImHg/nqI20FAmQl3PUACgkQ7ImHg/nq
I21cwQv/aXtTZ1l053bit113L8wSRhhyBQxBHj8UPhP2EFcrbDyqINf5WE8JHwcc
dOm28jKYWUhB4BkuiUlRiDQns91e9A4uAi4rwzE+902k6UFr2sfO4EA9j1iXNqWb
fBedyaUsvsKQqjkJ7DB2uH7gY304bFYspoEXP3ID4OT2xq2skF9pa+J3twvlhZaO
2RAvGQ2AkoCVW0KEeKCpTZYTQv451/gq2RXUBG/uPEuZ6dOx+qXlHMyOx9ECgRcL
S9XxqQGAIPRQKhU97rkWd7Q0MmtU2GxjP2UIK/p+lR713fnMwiyJaH8Yh+B3Bm7s
zMlzPbDFxE8D66EhilFiiRc/FdKjsLDrOzLDBOmaWDiVC7BdY83SuDw/OJ3ekTK3
+vpH9EfnkY9g48ky8CiqMz0wZwYJPul1/CNoJk+lAWxId7jLqIAl1psQtrGoB4Bn
3hiH+RKJlTNtUeLk2nGVWi3KDOQWH4z/rIA8T/Cu/ASgMHn7fvVL+F72BCiJQeko
t7BxHJiU
=lV7R
-----END PGP SIGNATURE-----


?
Your comment

This issue is archived.

To comment on this conversation send an email to 58693@debbugs.gnu.org

To respond to this issue using the mumi CLI, first switch to it
mumi current 58693
Then, you may apply the latest patchset in this issue (with sign off)
mumi am -- -s
Or, compose a reply to this issue
mumi compose
Or, send patches to this issue
mumi send-email *.patch