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

From: Liliana Marie Prikler <[email-masked]>
Date: Sat, 26 Aug 2023 22:01:46 +0200

Am Freitag, dem 14.07.2023 um 11:12 -0400 schrieb Kierin Bell
<[email-masked]>
> 
> * gnu/home/services/emacs.scm: New file.
> * gnu/local.mk (GNU_SYSTEM_MODULES): Add new file.
> * tests/home/services/emacs.scm: New tests file.
> * Makefile.am (SCM_TESTS): Add new tests file.
AFAIK we use "Register" instead of "Add".
> * doc/guix.texi (Emacs Home Services): New node.
I'd cut this series into two (or more, see below) patches right around
here, putting everything below this line into the first patch(es) and
everything above into the second/nth.
> * guix/read-print.scm (read-with-comments, read-with-
> comments/sequence):
> Add new ELISP? and UNELISP-EXTENSIONS? keyword arguments to support
> reading Elisp.
> (%newline-forms): Add `home-emacs-configuration'.
> (%elisp-special-forms, %elisp-natural-whitespace-string-forms)
> (%elisp-special-symbol-chars, %elisp-confusable-number-symbols)
> (%elisp-basic-chars, %elisp-simple-escape-chars): New variables.
> (special-form-lead, printed-string, symbol->display-string): Add new
> ELISP? keyword argument.
> (atom->elisp-string): New helper function.
> (pretty-print-with-comments): New ELISP? and SPECIAL-FORMS keyword
> arguments to support serialization to Elisp.  

> General improvements:
> enable pretty-printing of alists and improper lists; only print lists
> of
> constants with one element per line when length exceeds LONG-LIST; do
> not print newline before special read syntax forms (e.g., `'', `#~',
> etc.) unless they would exceed MAX-WIDTH; include backslashes when
> calculating whether a string would exceed MAX-WIDTH; do not print
> extraneous newline when special form has an empty body; print
> newlines
> after list arguments of special forms; print first argument after
> function on newline with same indentation as function when it would
> exceed MAX-WIDTH.
> * tests/read-print.scm: Add new tests and update old tests which fail
> due to improvements.
These general improvements should perhaps also been given their own
patch(es).  Also, since read-print is used in guix style, I'd be
interested in seeing how the output improves from your changes.  Do you
have easy comparisons?

> ---
> 
> This patch builds on patches from ( and David Wilson for a
> `home-emacs-service-type' (https://issues.guix.gnu.org/58693,
> https://issues.guix.gnu.org/60753,
> https://issues.guix.gnu.org/62549).
> 
> Many of the features of the prior patches have been included, but the
> major focus here is to configure Emacs in Scheme rather than
> symlinking
> to existing configuration files.
> 
> Here are some of the broad strokes:
> 
> * The following record types have been introduced to encapsulate
>   configuration for Emacs: `emacs-configuration' (for general
>   configuration), `emacs-package' (for package-specific
> configuration),
>   `emacs-keymap' (for configuration of local keymaps), and
>   `emacs-server' (for configuration of Emacs servers).
> 
> * Most configuration fields are either flat lists or alists that are
>   considerably abstracted from their final serialized Elisp
>   representation, but escape hatches are provided for both pulling in
>   existing configuration files and specifying s-expressions directly.
> 
> * All serialized Elisp is pretty-printed much how we would expect to
> see
>   it in Emacs (for example, with proper indentation according to the
>   `lisp-indent-function' symbol property, etc.).  This has been
>   accomplished by adding a new keyword argument to
>   `pretty-print-with-comments' from `(guix read-print)', among other
>   improvements.
> 
> * Emacs package configuration can either be serialized as `use-
> package'
>   forms or as equivalent, more minimalist s-expressions.  Users can
>   define their own package serializers, too.
> 
> * For specifying s-expressions, an "Elisp expression" syntax has been
>   implemented that is essentially a lighter-weight version G-
> expressions.
>   (I try to explain why this is helpful in the documentation.)
> 
> * A reader extension has been implemented that allows for "Elisp
>   expressions" to be specified directly with Elisp read syntax, and
>   Scheme values (including file-like objects or G-expressions) can in
>   turn be "unquoted" within that Elisp code.  Also, comments and
>   whitespace can be included within the Elisp code via the `#;'
>   (comment), `#>' (newline), and `;^L' (page break) forms.
> 
> * Each Emacs server has its own user init and early init files, which
>   can optionally inherit configuration from the init files used by
>   non-server Emacsen.  Each server can also inherit the "main"
>   `user-emacs-directory', or it can use its own subdirectory.
> 
> * The `home-emacs-service-type' can be extended, with subordinate
>   configuration records being merged intelligently when possible.
> 
> * A utility function has been provided for generating the
> aforementioned
>   Scheme records from an existing Emacs init file:
>   `elisp-file->home-emacs-configuration'.
> 
> Here's an example configuration for the `home-emacs-service-type'
> demonstrating some of these features:
> 
> --8<---------------cut here---------------start------------->8---
> (use-modules (gnu home)
>              (gnu services)
>              (guix gexp)
>              (gnu home services)
>              (gnu home services emacs)
>              (gnu packages emacs-xyz)
>              (gnu packages file)
>              (gnu packages compression))
> 
> (define %my-function-name 'my--compose-mail)
> 
> (define %gnus-init-file
>   (elisp-file "gnus.el"
>               (list
>                (elisp (setq gnus-select-method '(nnnil "")))
>                (elisp (setq gnus-secondary-select-methods
>                             '((nnml "")
>                               (nntp "news.gmane.io"))))
>                (elisp (setq mail-sources
>                             '((imap :server "mail.example.net"
>                                     :user "[email-masked]"
>                                     :port 993
>                                     :stream tls))))
>                ;; Elisp reader extension
>                #%(define-key global-map [remap compose-mail]
> #;comment
>                    '#$%my-function-name nil))))
I assume that each elisp or #% only handles a single expression, am I
correct?  Or do we also have (elisp a b) and #%@(a b)?

Cheers