From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp11.migadu.com ([2001:41d0:403:4789::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms9.migadu.com with LMTPS id uAElCKn/5mRpwQAASxT56A (envelope-from ) for ; Thu, 24 Aug 2023 08:58:49 +0200 Received: from aspmx1.migadu.com ([2001:41d0:403:4789::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp11.migadu.com with LMTPS id 0Jc1CKn/5mQu3gAA9RJhRA (envelope-from ) for ; Thu, 24 Aug 2023 08:58:49 +0200 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id 7A77E43BA0 for ; Thu, 24 Aug 2023 08:58:48 +0200 (CEST) Authentication-Results: aspmx1.migadu.com; dkim=fail ("headers rsa verify failed") header.d=fernseed.me header.s=gm1 header.b=Em5Ec2kl; spf=pass (aspmx1.migadu.com: domain of "guix-patches-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="guix-patches-bounces+larch=yhetil.org@gnu.org"; dmarc=fail reason="SPF not aligned (relaxed)" header.from=fernseed.me (policy=none) ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1692860328; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding:resent-cc: resent-from:resent-sender:resent-message-id:in-reply-to:in-reply-to: references:references:list-id:list-help:list-unsubscribe: list-subscribe:list-post:dkim-signature; bh=DvqZzLx3cdAYyh8v32caOcZil1WbR/KbyPP7KyvDzCY=; b=UaX5dGaBt9lt0D8J9aJmDX5PsQyP0g1ispM9vTtuKPei8vFAxK3xFyy7mlxEA200BKfQwl OQ/yJ4L1DnzSCpqivo6A52tL2TKPGGQAqlrJaVGbChg1Gu2jFdQchj9SkjyzQLutVZd+3i yDZJwuET844GJw7HOpM0UHnLNQ/G+ksTskt+GBLxSxcmnclu+OwDh4jsfDnbGlUCmT31D+ MJY8x0t5NbQEIFl3Tf5TTOl8vQTY2I3DUc5T76O/LfJvLn1D60e4hRgfe/OKSQVDlKul6B PLbmjYxo5phIeMJk3IubvBjKOzCoh1IfvcEJfN+vrx4/NdM3BWuEIfiF///WrQ== ARC-Seal: i=1; s=key1; d=yhetil.org; t=1692860328; a=rsa-sha256; cv=none; b=piIW7JeHtKszVs/8GqrYga/6fuZ/2RKYQqfi2+Tly9K6iSuGmsWfDoMF5lhheDXZTzdM85 JewdJLT1yIkBZG75DAghHcb67fJj6fZlhp/hBPAusTVPPJO/W/2giGKnDvPGiPDYYeZ7TL 4cYkAZjxh8ABeE9lwn7GCviQGvvgu+xPjeWvyQpdf1t4uRNFSoexyO8gt4qAu6pcPHdYfN KoOHRaujs34lMPZieBPCuJIXxRqVXi2nuLMQWCXPG9etfBvO+xJ1RnW41knbSfHkE18lug aRILg/GSd1HOR1FYukd3jH5+p/lHTLUwykjuWmec+g6+JhhxyJkWDgUXeA4lrA== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=fail ("headers rsa verify failed") header.d=fernseed.me header.s=gm1 header.b=Em5Ec2kl; spf=pass (aspmx1.migadu.com: domain of "guix-patches-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="guix-patches-bounces+larch=yhetil.org@gnu.org"; dmarc=fail reason="SPF not aligned (relaxed)" header.from=fernseed.me (policy=none) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qZ4I6-0003gS-OV; Thu, 24 Aug 2023 02:58:02 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qZ4I3-0003er-Fj for guix-patches@gnu.org; Thu, 24 Aug 2023 02:58:00 -0400 Received: from debbugs.gnu.org ([2001:470:142:5::43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1qZ4I3-0004k1-7t for guix-patches@gnu.org; Thu, 24 Aug 2023 02:57:59 -0400 Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1qZ4I7-0000oZ-16 for guix-patches@gnu.org; Thu, 24 Aug 2023 02:58:03 -0400 X-Loop: help-debbugs@gnu.org Subject: [bug#64620] [PATCH] gnu: home: Add home-emacs-service-type. Resent-From: Kierin Bell Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Thu, 24 Aug 2023 06:58:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 64620 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: Ludovic =?UTF-8?Q?Court=C3=A8s?= Cc: 64620@debbugs.gnu.org Received: via spool by 64620-submit@debbugs.gnu.org id=B64620.16928602683069 (code B ref 64620); Thu, 24 Aug 2023 06:58:02 +0000 Received: (at 64620) by debbugs.gnu.org; 24 Aug 2023 06:57:48 +0000 Received: from localhost ([127.0.0.1]:36000 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qZ4Hq-0000nN-FY for submit@debbugs.gnu.org; Thu, 24 Aug 2023 02:57:48 -0400 Received: from relay2-d.mail.gandi.net ([2001:4b98:dc4:8::222]:51077) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qYqVl-0000CQ-JG for 64620@debbugs.gnu.org; Wed, 23 Aug 2023 12:15:16 -0400 Received: by mail.gandi.net (Postfix) with ESMTPSA id CF0BE40006; Wed, 23 Aug 2023 16:15:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=fernseed.me; s=gm1; t=1692807303; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=DvqZzLx3cdAYyh8v32caOcZil1WbR/KbyPP7KyvDzCY=; b=Em5Ec2kloRP2zHe0wNNqZUB6WAZo8gs6AsDvynFOlj/yEa8ZPhGi2HyUyXwDr3pOEwjALx orxa1LUNwBIELEiV9S4PBqHc77cW/2V6OmLpRv8XktJAUBNTGA1WfTp5OKzs40Ipq7JeAD aWwoU4rehSuaqytgu8xz3844zSCgLF0720LXXOB5I3UQW3m4jT6e+dnL9VJNjsvfWeSvld Xs6zkzVAJ6iEQAO07zWZ/n1qCYR0aERMcRQYs+W3G2Rsi5vkXVmvmKhZz4f0ApZ/fwh0Rh PVxymFF5nnr4KdbwGk+wygPl/L4fllIyZbaqiIJ6k318Cbj/TXXw8n/lPaTt6Q== From: Kierin Bell In-Reply-To: <87v8d613hs.fsf@gnu.org> ("Ludovic =?UTF-8?Q?Court=C3=A8s?="'s message of "Wed, 23 Aug 2023 12:01:51 +0200") References: <0173e076aafb6ec389a7ebca5d56b7f4e8a02b6e.1689347338.git.fernseed@fernseed.me> <87v8d613hs.fsf@gnu.org> Date: Wed, 23 Aug 2023 12:14:57 -0400 Message-ID: <87o7ixzqf2.fsf@fernseed.me> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-GND-Sasl: fernseed@fernseed.me X-Mailman-Approved-At: Thu, 24 Aug 2023 02:57:44 -0400 X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: guix-patches@gnu.org List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-patches-bounces+larch=yhetil.org@gnu.org Sender: guix-patches-bounces+larch=yhetil.org@gnu.org X-Migadu-Flow: FLOW_IN X-Migadu-Country: US X-Migadu-Spam-Score: -2.21 X-Spam-Score: -2.21 X-Migadu-Queue-Id: 7A77E43BA0 X-Migadu-Scanner: mx1.migadu.com X-TUID: pHxoknttCdx/ Hi Ludo=E2=80=99, Ludovic Court=C3=A8s writes: > Hi Kierin, > > This is a truly impressive piece of work! > > fernseed@fernseed.me skribis: > >> 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. > > OK, interesting. This seems to be one of the main questions: how far > should we go on the Scheme side? > > In , unmatched-paren chose to not > generate elisp at all from Scheme. The advantage is that the > implementation is simpler; as a user, the model one has to have in mind > is also simpler: you=E2=80=99re still configuring most things the traditi= onal > way in elisp. That=E2=80=99s also its downside: you have to do plumbing = on the > elisp side, when Guix Home in some cases would know what to do. > > I don=E2=80=99t have the answer and I=E2=80=99m not sure what I=E2=80=99d= prefer, but I=E2=80=99m trying > to see the tradeoffs and to map out the design space. My philosophy here, I think, is that we can do both. ('s approach likely provides all of the integration between Guix and Emacs that many would want. David Wilson's patch goes a step further by providing a configuration option to change the Emacs user directory, which I think is a reasonable option to have. (Testing this, though, it turns out that changing the Emacs user directory is not so simple, so the implementation in my patch is more involved). In any case, as we saw, Guix Home does need to serialize some Elisp to do this (or to do anything similar). So, ideally, we would provide some useful mechanisms for serializing Elisp, but not go overboard. It's Scheme, so users can build on things later if reasonable foundations are there. We may want to work on simplifying the implementation here by removing features that add too much complexity. For example, maybe all of the fined-tuned controls over how Emacs servers "inherit" configuration aren't justified given the complexity of the implementation --- especially given that configuration is done via Scheme records, so users can duplicate configuration themselves by just reusing records. (But I do think it makes sense to at least include a subset of those features.) >> 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). > > Why special-case keymaps, of all the things one might one to configure > in Emacs? I understand it=E2=80=99s one of the first things one may want= to > tweak, but then why not add as well, etc.; IOW, where do > we draw the line? > For `emacs-keymap', I created a record type to avoid having nested alists like: '((foo-map . (("C-c a" . foo) ...)) (bar-map . ...) ...) Also, the `emacs-keymap' record has a `repeat?' field, so it can serve the purpose of something like use-package's `:repeat-map' keyword. ...I do like the idea of `', though... Just kidding. >> * 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. > > Are seasoned Emacsers not going to be frustrated because of this? :-) > > They might prefer to have full access to elisp. > I think it probably would be frustrating if it wasn't clear that users do have access to Elisp via the escape hatch fields. Maybe these should be mentioned more prominently in the documentation. They can also specify Elisp directly by using "Elisp expressions" as values in some of the alists --- for example, those that set variables (examples given in the configuration snippets). >> * 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. > > Fun. I=E2=80=99d like to see how we can avoid spreading elisp conditiona= ls in > (guix read-print). > I think the Elisp reader extension could be implemented completely on its own, outside of (guix read-print). The (guix read-print) pretty printer is very nice, though, and it seems relatively simple to adapt it to print Elisp. Though I'm open to better ideas. Most of the changes to `pretty-print-with-comments' are actually fixes that are not Elisp-specific, like preventing newlines where they definitely don't belong. Maybe that could go in a separate commit? >> * 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. > > Great that you=E2=80=99re putting (language elisp parser) to good use! > >> * 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. > > Very nice. > >> * A utility function has been provided for generating the aforementioned >> Scheme records from an existing Emacs init file: >> `elisp-file->home-emacs-configuration'. > > Neat; perhaps =E2=80=98guix home import=E2=80=99 could use it? > I looked into modifying `guix home import', but didn't have time to figure out exactly how to make that work. >> (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@example.net" >> :port 993 >> :stream tls)))) >> ;; Elisp reader extension >> #%(define-key global-map [remap compose-mail] #;comment >> '#$%my-function-name nil)))) > > Could I write: > > #%(progn > (setq x =E2=80=A6) > (setq y =E2=80=A6) > (define-key =E2=80=A6)) > > ? That would seem nicer. > I'm thinking about a way to create a "splicing" version of the `elisp' macro, or something similar, so you could do something like that without serializing the actual `progn'. > #%(body =E2=80=A6) is short for (elisp body =E2=80=A6) right? > > > [...] > Yes, they are equivalent. Most users would probably use the reader extension, unless they want to use Scheme-specific syntax (like `#(...)' for vectors versus `[...]'). >> (configured-packages >> (list >> (emacs-package >> (name 'windmove) >> ;; Autoload a function used by `my--display-buffer-down'. >> (autoloads '(windmove-display-in-direction)) >> (keys-override >> '(("C-M-" . windmove-left) >> ("C-M-" . windmove-right) >> ("C-M-" . windmove-up) >> ("C-M-" . windmove-down) >> ("C-x " >> . my--display-buffer-down))) >> (keys-local >> (list >> (emacs-keymap >> (name 'windmove-repeat-map) >> (repeat? #t) >> (keys '(("" . windmove-left) >> ("" . windmove-right) >> ("" . windmove-up) >> ("" . windmove-down)))))) > > My first reaction is that I don=E2=80=99t see myself my 2K lines (or a su= bset > thereof) of .emacs and .gnus in that style. I can foresee potential > benefits in terms of composability, but the barrier to entry looks too > high. WDYT? > I have about 2K lines of it (a lot of it auto-generated by the import function). As for the barrier to entry, I think we should hear more from others. In my opinion, the benefits of configuring Emacs with Scheme records like this go beyond composability. I think that it is cognitively easier to manage configuration when it is uniform, and the structure forces us to be more deliberate about what we include and why. But maybe that's more of a philosophical debate. >> Finally, unit tests have been added for the new `(guix read-print)' >> functionality, and for the "Elisp expression" syntax. I couldn't make >> unit tests for anything that builds derivations serializing Elisp, >> because '%bootstrap-guile' is apparently too old to load `(guix >> read-print)' on the derivation side. But most of this has gotten quite >> a bit of testing, as all of my personal Emacs config is now generated >> from Scheme. > > I think you could write tests using =E2=80=98guix home container=E2=80=99= and the host=E2=80=99s > store, similar to what =E2=80=98tests/guix-home.sh=E2=80=99 is doing. We= don=E2=80=99t have a > testing strategy for Home services yet, but we should definitely work on > it. > Will look into it. Testing the `elisp-file' function is important, because it does all of the serialization. > That=E2=80=99s it for my initial feedback. I hope others in the Home and= Emacs > teams will chime in! > > Thanks, > Ludo=E2=80=99. > > Thanks, I appreciate the feedback! I have a second version of the patch in the works that fixes 3 cosmetic issues, in case people noticed: 2 comments are confusing and shouldn't be there (code changed but comments didn't), and one line of the documentation in `guix.texi' wasn't properly filled. The actual code has been unchanged for 2 months, even with regular use. Also, the example snippet I gave in the original patch message has an error: --8<---------------cut here---------------start------------->8--- ;; ... (emacs-server (name "sandbox") ;; Server gets its own subdirectory of `user-emacs-directory' ;; when inheritance is disabled. (inherit-directory? #f) ;; Server still inherits configuration from non-server Emacsen ;; unless inheritance is explicitly disabled. (inherit-init? #f) ;; ... (default-init (emacs-configuration (variables `(;; ... ;; Individualized `user-emacs-directory' gets symlinks ;; to all `extra-files' from the `emacs-configuration' ;; used by other Emacsen, so the files can still be ;; referenced. (mail-signature-file . ,(elisp (locate-user-emacs-file "signature"))))) ;; ... )) ;; ... ) --8<---------------cut here---------------end--------------->8--- `inherit-init?' should be set to true. When `inherit-init?' is false, the `signature' file (which was previously created for the non-server Emacsen) will not be created automatically in the Emacs server's user directory. When it is true, all of the files that Guix Home manages in the main Emacs user directory are duplicated in the server's user directory, to ensure that any references to those files in the inherited configuration are still valid. ...Again, maybe this is one of the confusing features that could be simplified. --=20 Kierin Bell GPG Key: FCF2 5F08 EA4F 2E3D C7C3 0D41 D14A 8CD3 2D97 0B36