guix-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[bug#60753] [PATCH] gnu: home: Add home-emacs-service-type.


From: David Wilson
Subject: [bug#60753] [PATCH] gnu: home: Add home-emacs-service-type.
Date: Thu, 12 Jan 2023 19:27:02 +0200
User-agent: mu4e 1.8.11; emacs 28.2

Hey (!

"(" <paren@disroot.org> writes:
> home-emacs-shepherd-services isn't defined here :(  Doesn't this cause an 
> unbound-variable
> error?  (Also, most of the reason I wrote this service was to support 
> auto-starting emacs
> --daemon :))

Whoops, in my haste to send out the patch I forgot to take that out!

Yes, I saw that you meant to run Emacs as a daemon and I think it should
be added to this service (or another daemon-specific service) in a
future patch.  I figured it would be easier to get a patch accepted
without the daemon functionality just yet since there seemed to be more
feedback about that aspect in your patch thread.

Here's an update to my patch that actually works (sorry if I'm doing
this wrong, it's been a while since I worked on a patch thread!) --

Co-authored-by: ( <paren@disroot.org>
---
 doc/guix.texi               |  77 +++++++++++++++
 gnu/home/services/emacs.scm | 185 ++++++++++++++++++++++++++++++++++++
 gnu/local.mk                |   1 +
 3 files changed, 263 insertions(+)
 create mode 100644 gnu/home/services/emacs.scm

diff --git a/doc/guix.texi b/doc/guix.texi
index 751d0957d8..62fefde1ea 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -111,6 +111,7 @@ Copyright @copyright{} 2022 (@*
 Copyright @copyright{} 2022 John Kehayias@*
 Copyright @copyright{} 2022 Ivan Vilata-i-Balaguer@*
 Copyright @copyright{} 2023 Giacomo Leidi@*
+Copyright @copyright{} 2023 David Wilson@*

 Permission is granted to copy, distribute and/or modify this document
 under the terms of the GNU Free Documentation License, Version 1.3 or
@@ -41061,6 +41062,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 Services.                          Services for 
configuring Emacs.
 * Guix: Guix Home Services.                            Services for Guix.
 @end menu
 @c In addition to that Home Services can provide
@@ -41914,6 +41916,81 @@ The package providing the @code{/bin/dbus-daemon} 
command.
 @end table
 @end deftp

+@node Emacs Home Services
+@subsection Emacs Home Services
+
+@defvr {Scheme Variable} home-emacs-service-type
+This is the service type for configuring the Emacs text editor.  It
+enables you to assemble @file{init.el} and @file{early-init.el} files
+from snippets in your home configuration and other Emacs Lisp files you
+have in your personal configuration folder.
+
+This service can be extended using the @code{home-emacs-extension} type.
+
+Note that if you have an existing @file{~/.emacs} and/or
+@file{~/.emacs.d}, the configuration aspect of this service will not be
+loaded, as the former location takes precedence over
+@file{~/.config/emacs}.  This service uses the latter path 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} command.
+
+@item @code{packages} (default: @code{'()})
+Additional packages required by the Emacs configuration.
+
+@item @code{user-emacs-directory} (default: @file{~/.cache/emacs})
+The directory beneath which additional per-user Emacs-specific files are 
placed.
+
+@item @code{init-file} (default: @code{'()})
+Configuration text or files to include in @file{init.el}.
+
+@item @code{early-init-file} (default: @code{'()})
+Configuration text or files to include in @file{early-init.el}.
+
+@item @code{load-paths} (default: @code{'()})
+Additional load paths to add to Emacs' @code{load-path} variable.  Lines
+will be inserted at the beginning of @file{early-init.el}.
+
+@item @code{native-compile?} (default: @code{#f})
+Whether to compile 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.
+@end table
+@end deftp
+
+@deftp {Data Type} home-emacs-extension
+The extension record for @code{home-emacs-service-type}.
+
+@table @asis
+@item @code{packages} (default: @code{'()})
+Additional packages required by the Emacs configuration.
+
+@item @code{init-file} (default: @code{'()})
+Configuration text or files to include in @file{init.el}.
+
+@item @code{early-init-file} (default: @code{'()})
+Configuration text or files to include in @file{early-init.el}.
+
+@item @code{load-paths} (default: @code{'()})
+Additional load paths to add to Emacs' @code{load-path} variable.  Lines
+will be inserted at the beginning of @file{early-init.el}.
+@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..7a821fed8a
--- /dev/null
+++ b/gnu/home/services/emacs.scm
@@ -0,0 +1,185 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2022 ( <paren@disroot.org>
+;;; Copyright © 2023 David Wilson <david@daviwil.com>
+;;;
+;;; 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)
+  #: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 (ice-9 match)
+  #:use-module (srfi srfi-1)
+  #:use-module (srfi srfi-26)
+
+  #:export (emacs-variables
+            home-emacs-configuration
+            home-emacs-extension
+            home-emacs-service-type))
+
+(define list-of-file-likes?
+  (list-of file-like?))
+
+(define (string-or-file-like? val)
+  (or (string? val)
+      (file-like? val)))
+
+(define list-of-string-or-file-likes?
+  (list-of string-or-file-like?))
+
+(define-configuration/no-serialization home-emacs-configuration
+  (emacs
+   (file-like emacs)
+   "The package providing the @file{/bin/emacs} command.")
+  (packages
+   (list-of-file-likes '())
+   "Additional packages required by the Emacs configuration.")
+  (user-emacs-directory
+   (string "~/.cache/emacs")
+   "Directory beneath which additional per-user Emacs-specific files are 
placed.")
+  (init-file
+   (text-config '())
+   "Configuration text or files to include in init.el.")
+  (early-init-file
+   (text-config '())
+   "Configuration text or files to include in early-init.el.")
+  (load-paths
+   (list-of-string-or-file-likes '())
+   "Additional load paths to add to Emacs' @code{load-path} variable.  Lines
+will be inserted at the beginning of early-init.el.")
+  (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."))
+
+(define (home-emacs-profile-packages config)
+  (cons (home-emacs-configuration-emacs config)
+        (home-emacs-configuration-packages 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 (serialize-emacs-load-paths config)
+  #~(string-append
+     ";; Additional load paths\n"
+     #$@(map (lambda (load-path)
+               #~(format #f "(add-to-list 'load-path \"~a\")" #$load-path))
+             (home-emacs-configuration-load-paths config))
+     "\n\n"))
+
+(define (serialize-emacs-user-directory config)
+  (format #f
+          ";; Set the `user-emacs-directory` to a writeable path\n(setq 
user-emacs-directory \"~a\")\n\n"
+          (home-emacs-configuration-user-emacs-directory config)))
+
+(define (home-emacs-xdg-configuration-files config)
+  `(("emacs/early-init.el"
+     ,(apply mixed-text-file
+             (cons* "early-init.el"
+                    (serialize-emacs-load-paths config)
+                    (serialize-emacs-user-directory config)
+                    (home-emacs-configuration-early-init-file config))))
+    ("emacs/init.el"
+     ,(apply mixed-text-file
+             (cons "init.el"
+                   (home-emacs-configuration-init-file config))))))
+
+(define-configuration/no-serialization home-emacs-extension
+  (packages
+   (list-of-file-likes '())
+   "Additional packages required by the Emacs configuration.")
+  (init-file
+   (text-config '())
+   "Configuration text or files to include in init.el.")
+  (early-init-file
+   (text-config '())
+   "Configuration text or files to include in early-init.el.")
+  (load-paths
+   (list-of-string-or-file-likes '())
+   "Additional load paths to add to Emacs' @code{load-path} variable.  Lines
+will be inserted at the beginning of early-init.el."))
+
+(define (home-emacs-extensions original-config extension-configs)
+  (match-record original-config <home-emacs-configuration>
+    (packages load-paths init-file early-init-file)
+    (home-emacs-configuration
+     (inherit original-config)
+     (packages
+      (append packages
+              (append-map
+               home-emacs-extension-packages extension-configs)))
+     (init-file
+      (append init-file
+              (append-map
+               home-emacs-extension-init-file extension-configs)))
+     (early-init-file
+      (append early-init-file
+              (append-map
+               home-emacs-extension-early-init-file extension-configs)))
+     (load-paths
+      (append load-paths
+              (append-map
+               home-emacs-extension-load-paths extension-configs))))))
+
+(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-xdg-configuration-files-service-type
+           home-emacs-xdg-configuration-files)))
+   (default-value (home-emacs-configuration))
+   (compose identity)
+   (extend home-emacs-extensions)
+   (description
+    "Configure the GNU Emacs extensible text editor.")))
+
+(define scheme-value->emacs-value
+  (match-lambda (#t (quote 't))
+                (#f (quote 'nil))
+                (val val)))
+
+(define (emacs-variables var-alist)
+  "Converts an alist of variable names and values into a @code{setq}
+expression that can be used in an Emacs configuration.  Scheme values
+@code{#t} and @code{#f} will be converted into @code{t} and @code{nil},
+respectively."
+  #~(string-append
+     "(setq"
+     #$@(map (lambda (var)
+               #~(format #f "\n  ~a ~s"
+                         (quote #$(car var))
+                         #$(scheme-value->emacs-value (cdr var))))
+             var-alist)
+     ")\n\n"))
diff --git a/gnu/local.mk b/gnu/local.mk
index 184f43e753..35d88b4dd6 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -89,6 +89,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.1





reply via email to

[Prev in Thread] Current Thread [Next in Thread]