GNU bug report logs - #64620
[PATCH] gnu: home: Add home-emacs-service-type.

Previous Next

Package: guix-patches;

Reported by: fernseed <at> fernseed.me

Date: Fri, 14 Jul 2023 15:50:02 UTC

Severity: normal

Tags: patch

Full log


Message #38 received at 64620 <at> debbugs.gnu.org (full text, mbox):

From: Liliana Marie Prikler <liliana.prikler <at> gmail.com>
To: Kierin Bell <fernseed <at> fernseed.me>
Cc: 64620 <at> debbugs.gnu.org
Subject: Re: [PATCH] gnu: home: Add home-emacs-service-type.
Date: Tue, 29 Aug 2023 06:24:03 +0200
Am Montag, dem 28.08.2023 um 18:27 -0400 schrieb Kierin Bell:
> > 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?
> > 
> 
> So when ready, I will open a new issue and send a patch series as per
> the manual.
No need, you can reuse this one.

> I'll also explore opening a separate issue for the "general
> improvements" to (guix read-print) that are not strictly part of the
> Elisp serialization functionality.  I'll try to find a way to clearly
> annotate that patch with examples of each change and how it affects
> output.
Same here, just use --reroll-count=2 or -v 2 on git send-email.

> Many of the changes I'm calling "general improvements" seem to affect
> Elisp output more than Scheme.  E.g., improper lists and alists
> aren't used as extensively in Scheme, none of the defined %SPECIAL-
> FORMS for Scheme accept list arguments in the right places or empty
> bodies, etc.
> 
> But you make a good point re: guix style.  I managed to contrive an
> example package definition that demonstrates most of the changes.
> 
> Here is the output of guix style without the patch:
> 
> --8<---------------cut here---------------start------------->8---
> (define-public foo
>   (package
>     (name "foo")
>     ;; ...
>     (arguments
>      (list
>       ;; *** (1) ***
>       #:make-flags #~(list "VERBOSE=1"
>                            #~more-flags "..."
>                            #~(long-gexp-that-would-protrude-beyond-
> max-width))
>       #:phases #~(modify-phases %standard-phases
>                    (add-after 'install 'foo-fix
>                      (lambda _
>                        (substitute* "some-file"
>                          (("match1")
>                           ;; *** (2) ***
>                           (string-join (list
>                                         "list would protrude if not
> preceded by newline")))
>                          (("match2")
>                           "replacement")))))))
>     ;; *** (3) ***
>     (inputs `(,bar ,baz
>               ,quux
>               ,quuux
>               ,quuuux
>               ,quuuuux))
>     (native-search-paths
>      (list (search-path-specification
>             (variable "FOO-PATH")
>             (files '("foo-dir"))
>             ;; *** (4) ***
>             (file-pattern
>                           "^string\\ with\\ backlashes\\ that\\
> would\\ protrude$")
>             (file-type 'regular))))
>     (properties '((tunable? . #t)
>                   ;; *** (5) ***
>                   (upstream-name . "foo-with-a-long-upstream-name-
> that-would-protrude")))
>     ;; ...
>     (license gpl3+)))
> --8<---------------cut here---------------end--------------->8---
> 
> 
> ...And here it is with the patch:
> 
> --8<---------------cut here---------------start------------->8---
> (define-public foo
>   (package
>     (name "foo")
>     ;; ...
>     (arguments
>      (list
>       ;; (1) No newline before special read syntaxes when they would
> not
>       ;;     protrude beyond MAX-WIDTH.
>       ;;
>       ;;     [ Only relevant where a special read syntax occurs after
>       ;;     the first argument in a function call and is not
> preceded
>       ;;     by a keyword. ]
>       #:make-flags #~(list "VERBOSE=1" #~more-flags "..."
>                            #~(long-gexp-that-would-protrude-beyond-
> max-width))
>       #:phases #~(modify-phases %standard-phases
>                    (add-after 'install 'foo-fix
>                      (lambda _
>                        (substitute* "some-file"
>                          (("match1")
>                           ;; (2) Newline and proper indentation
> before
>                           ;;     first argument of function call when
>                           ;;     it would protrude beyond MAX-WIDTH.
>                           ;;
>                           ;;     [ Only relevant when first argument
>                           ;;     of function call is a list that has
>                           ;;     elements that would protrude beyond
>                           ;;     MAX-WIDTH. ]
>                           (string-join
>                            (list
>                             "list would protrude if not preceded by
> newline")))
>                          ;; XXX: Should there be a newline after
>                          ;; `("match2")'?  In Elisp, newlines like
>                          ;; that seemed to get annoying, but perhaps
>                          ;; it would actually be better here.
>                          (("match2") "replacement")))))))
>     ;; (3) Quoted lists longer than LONG-LIST with second element on
>     ;;     its own line, like the remaining elements.
>     ;;
>     ;;     [ Fixes an obvious bug. ]
>     (inputs `(,bar
>               ,baz
>               ,quux
>               ,quuux
>               ,quuuux
>               ,quuuuux))
>     (native-search-paths
>      (list (search-path-specification
>             (variable "FOO-PATH")
>             (files '("foo-dir"))
>             ;; (4) Newline and proper indentation before string with
>             ;;     backslashes that would protrude.
>             ;;
>             ;;    [ Fixes obvious bug --- backslashes must be
>             ;;    accounted for in strings to avoid weird issues. ]
>             (file-pattern
>              "^string\\ with\\ backlashes\\ that\\ would\\
> protrude$")
>             (file-type 'regular))))
>     (properties '((tunable? . #t)
>                   ;; (5) Newline before the dot and end of improper
> lists.
>                   (upstream-name
>                    . "foo-with-a-long-upstream-name-that-would-
> protrude")))
>     ;; ...
>     (license gpl3+)))
> --8<---------------cut here---------------end--------------->8---
> 
> ...Again, these improvements become much more important in a 2k line
> Elisp init file.
I'd imagine, but there are some good things in it for (guix style) too.
Some bugs still remain, like not splitting after #:phases to keep long
lines in check, but that's beyond the scope.

> > > ---
> > > 
> > > 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 "user <at> example.net"
> > >                                     :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)?
> > 
> 
> Yes, `elisp' and `#%' are just like `gexp' and `#~'.  `(elisp a b)'
> would be a syntax error.  (And #%#$@(a b) is interesting; hadn't
> tried that one :) --- but it doesn't work.)
> 
> I plan on adding a convenience macro `elisp*' so that (elisp* a b)
> expands to (list (elisp a) (elisp b)).  This would make, e.g., the
> above `elisp-file' invocation much nicer.
SGTM.

Cheers

This bug report was last modified 106 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.