Re: Creating an Emacs Home Configuration Service
Aloha All, Thank you for your input! It's all been very constructive. I will do my best on that patch. On Wed, Oct 19, 2022 at 10:56 AM wrote: > > October 19, 2022 4:25 PM, "Zain Jabbar" wrote: > > > Aloha All, > > > > Thank you for your insightful messages. Sorry my code did not work as > > smoothly as I would have liked. I have a =home-environment= definition > > that hopefully works for you. You can put everything into one > > configuration as you described. I do that in the following source > > block. For some reason I liked the idea of separate definitions of > > each package, so that Guile and Guix Home kind of acts like a > > =use-package= declaration. Though that was needless abstraction on my > > end. > > I do not know if it is a needless abstraction. I am just bouncing ideas > around with you. :) > > > > > #+BEGIN_SRC scheme > > (use-modules (srfi srfi-1) > > (ice-9 pretty-print) > > (gnu home) > > (gnu packages) > > (gnu services) > > (gnu home services) > > (gnu services configuration) > > (guix gexp) > > (guix transformations)) > > > > (define file-likes? (list-of file-like?)) > > > > (define-configuration/no-serialization emacs-configuration > > (emacs-packages > > (file-likes (list (specification->package "emacs-next"))) "Files") > > (early-init > > (list '()) "Early-Init") > > (init > > (list '()) "Init")) > > > > (define-public emacs-configuration-service > > (service-type (name (symbol-append 'emacs-configuration)) > > (extensions > > (list (service-extension > > home-profile-service-type > > (lambda (config) (emacs-configuration-emacs-packages config))) > > (service-extension > > home-xdg-configuration-files-service-type > > (lambda (config) > > (list > > `("emacs/init.el" ,(scheme-file "init.el" > > (emacs-configuration-init config) > > #:splice? #:t)) > > `("emacs/early-init.el" ,(scheme-file "early-init.el" > > (emacs-configuration-early-init config) > > #:splice? #:t))) > > (default-value (emacs-configuration)) > > (description "Configures Emacs init.el"))) > > > > (define-public minimal-home-environment > > (home-environment > > (services > > (list > > (service emacs-configuration-service > > (emacs-configuration > > (emacs-packages > > (list > > (specification->package "bash") > > (specification->package "emacs-next") > > (specification->package "emacs-debbugs") > > (specification->package "emacs-evil") > > (specification->package "emacs-paredit") > > (specification->package "emacs-anzu"))) > > (init '((evil-mode 1) > > ;; Please add more config here > > ;; Begining of emacs init configuration after evil-mode 1 > > > > ;; End emacs init configuration > > )) > > (early-init '((setq warning-suppress-log-types '((comp) (comp))) > > (setq warning-suppress-types '((comp) (comp))) ; A > > serious stack of pringles here > > > > minimal-home-environment > > #+END_SRC > > > > I saved this file to =minimal-working-example.scm= and ran a container using > > =guix home -N --share=/tmp container ./minimal-working-example.scm=. > > This should spawn a shell in which you can run =emacs= (as terminal). > > Furthermore we can also run the info help command and get to the > > debbugs page. > > > > The =init= and =early-init= configuration options take in > > S-Expressions not files. Under the hood the service uses =scheme-file= > > which takes in an expression. I am open to suggestions for other file > > mechanisms, like if, for example, G-Expressions are more natural here. > > I found that I did not know how to naturally append G-Expressions > > together and that the S-Expressions can "bleed" into the config using > > backquotes. So I chose just sticking in a list of expressions for > > Emacs. Something Andrew Tropin taught me, if you are working in a > > =*.scm= file and you want to evaluate elisp, use =M-x eval-region= or > > =M-x edit-indirect-region= (with the usual stipulation that if you do > > this very often we can bind it to a key). > > I would say when you submit your service to guix-devel others will give > you some options too. I like the idea of S-expressions though. > > > > If my interpretation of 13.1 Declaring the Home Environment is > > correct, we should expect an error associated with XDG_RUNTIME_DIR as > > the necessary variables will be set via the Operating-System > > declaration. The next error I believe is emacs wanting to make a file > > where the home container does not have read or write permissions. My > > =guix home= declaration with the =share= parameter should hopefully > > help with this error. Oddly enough if we do not specify the > > installation of =bash=, Emacs says it cannot uncompress the info > > manuals because there is no =sh=. That is why I included =bash= into > > the emacs packages list. I do think a lot of these "solutions" will be > > unncessecary if users were to use =guix home reconfigure= rather than > > user the container. Though it's nice to debug them there. > > Thanks for the explanation! -- Thank you, Zain Jabbar
Re: Creating an Emacs Home Configuration Service
Aloha All, Super awesome to hear from you! I'm quite star stuck. Thank you for showcasing Andrew Tropin's rde project. I believe the =features= abstraction have potential and make more intuitive sense for the design of configurable programs. There is a lot for me to learn from this design choice. As it stands, =features= are not in Guix proper, are there plans to merge them? How will they end up relating to the existing home services feature set? On Wed, Oct 19, 2022 at 5:36 AM Ludovic Courtès wrote: > > Hi Zain, and welcome! > > Zain Jabbar skribis: > > > Running =guix home search emacs= returns nothing. I also could not find an > > email using =C-u M-x debbugs-gnu= about an Emacs configuration service. > > > > This is my first email to this mailing address. Please give me pointers on > > formatting and further improvements. > > > > I have attempted to make an =emacs-home-service-type= so that it is > > possible to configure Emacs using Guix home. This code is extremely > > preliminary hence I don't even think it is worth sending as a patch. Also I > > have never worked on a multi person Git project before and do not know how > > to solve the keyring error I get when using guix pull. I will outline what > > my code does and what features I would like to add. > > I am all for something like you describe, and the code you sent may be > good starting point! > > The rde project¹ by Andrew Tropin et al. may be a good source of > inspiration. The “features” abstraction in particular seems to be > well-suited for Emacs. But overall it’s reasonable to start small, with > a low-level approach to combine and configure Emacs packages. > > Thanks, > Ludo’. > > ¹ https://trop.in/rde/manual -- Thank you, Zain Jabbar
Re: Creating an Emacs Home Configuration Service
Aloha All, Thank you for your insightful messages. Sorry my code did not work as smoothly as I would have liked. I have a =home-environment= definition that hopefully works for you. You can put everything into one configuration as you described. I do that in the following source block. For some reason I liked the idea of separate definitions of each package, so that Guile and Guix Home kind of acts like a =use-package= declaration. Though that was needless abstraction on my end. #+BEGIN_SRC scheme (use-modules (srfi srfi-1) (ice-9 pretty-print) (gnu home) (gnu packages) (gnu services) (gnu home services) (gnu services configuration) (guix gexp) (guix transformations)) (define file-likes? (list-of file-like?)) (define-configuration/no-serialization emacs-configuration (emacs-packages (file-likes (list (specification->package "emacs-next"))) "Files") (early-init (list '()) "Early-Init") (init (list '()) "Init")) (define-public emacs-configuration-service (service-type (name (symbol-append 'emacs-configuration)) (extensions (list (service-extension home-profile-service-type (lambda (config) (emacs-configuration-emacs-packages config))) (service-extension home-xdg-configuration-files-service-type (lambda (config) (list `("emacs/init.el" ,(scheme-file "init.el" (emacs-configuration-init config) #:splice? #:t)) `("emacs/early-init.el" ,(scheme-file "early-init.el" (emacs-configuration-early-init config) #:splice? #:t))) (default-value (emacs-configuration)) (description "Configures Emacs init.el"))) (define-public minimal-home-environment (home-environment (services (list (service emacs-configuration-service (emacs-configuration (emacs-packages (list (specification->package "bash") (specification->package "emacs-next") (specification->package "emacs-debbugs") (specification->package "emacs-evil") (specification->package "emacs-paredit") (specification->package "emacs-anzu"))) (init '((evil-mode 1) ;; Please add more config here ;; Begining of emacs init configuration after evil-mode 1 ;; End emacs init configuration )) (early-init '((setq warning-suppress-log-types '((comp) (comp))) (setq warning-suppress-types '((comp) (comp))) ; A serious stack of pringles here minimal-home-environment #+END_SRC I saved this file to =minimal-working-example.scm= and ran a container using =guix home -N --share=/tmp container ./minimal-working-example.scm=. This should spawn a shell in which you can run =emacs= (as terminal). Furthermore we can also run the info help command and get to the debbugs page. The =init= and =early-init= configuration options take in S-Expressions not files. Under the hood the service uses =scheme-file= which takes in an expression. I am open to suggestions for other file mechanisms, like if, for example, G-Expressions are more natural here. I found that I did not know how to naturally append G-Expressions together and that the S-Expressions can "bleed" into the config using backquotes. So I chose just sticking in a list of expressions for Emacs. Something Andrew Tropin taught me, if you are working in a =*.scm= file and you want to evaluate elisp, use =M-x eval-region= or =M-x edit-indirect-region= (with the usual stipulation that if you do this very often we can bind it to a key). If my interpretation of 13.1 Declaring the Home Environment is correct, we should expect an error associated with XDG_RUNTIME_DIR as the necessary variables will be set via the Operating-System declaration. The next error I believe is emacs wanting to make a file where the home container does not have read or write permissions. My =guix home= declaration with the =share= parameter should hopefully help with this error. Oddly enough if we do not specify the installation of =bash=, Emacs says it cannot uncompress the info manuals because there is no =sh=. That is why I included =bash= into the emacs packages list. I do think a lot of these "solutions" will be unncessecary if users were to use =guix home reconfigure= rather than user the container. Though it's nice to debug them there. On Wed, Oct 19, 2022 at 8:19 AM wrote: > > October 18, 2022 3:42 PM, "Zain Jabbar" wrote: > > > Here is a minimal reproducible(-ish needs change in module name) > > example configuration which installs =emacs-debbugs= (and not much > > else). > > Cool I am CC-ing guix devel. > > > #+BEGIN_SRC scheme > > (define-module (zaijab minimal-working-example) > > #:use-module (srfi srfi-1) > > #:use-module (ice-9 pretty-print) > > #:use-module (gnu home) > > #:use-module (gnu packages) > > #:use-module
Re: Creating an Emacs Home Configuration Service
Aloha Guix Development Team, Thank you for this email. Your advice was directed very kindly and is very helpful. I have tried to revise the code based on your email. I also checked the setting for plaintext mode in GMail; I hope this makes the email easier to read. First, I define a configuration (without serialization currently). #+BEGIN_SRC scheme (define file-likes? (list-of file-like?)) (define-configuration/no-serialization emacs-configuration (emacs-packages (file-likes (list (specification->package "emacs-next"))) "Files") (early-init (list '()) "Early-Init") (init (list '()) "Init")) #+END_SRC Then, I define an =emacs-configuration-service= that takes in a configuration. This service will add packages in the =emacs-packages= to the profile, and append the S-Expressions in =early-init= and =init= to $XDG_CONFIG_HOME/emacs/early-init.el and $XDG_CONFIG_HOME/emacs/init.el respectively. The service has definition, #+BEGIN_SRC scheme (define-public emacs-configuration-service (service-type (name (symbol-append 'emacs-configuration)) (extensions (list (service-extension home-profile-service-type (lambda (config) (emacs-configuration-emacs-packages config))) (service-extension home-xdg-configuration-files-service-type (lambda (config) (list `("emacs/init.el" ,(scheme-file "init.el" (emacs-configuration-init config) #:splice? #:t)) `("emacs/early-init.el" ,(scheme-file "early-init.el" (emacs-configuration-early-init config) #:splice? #:t))) (default-value (emacs-configuration)) (description "Configures Emacs init.el"))) #+END_SRC This version of the service is one big service that only takes in one configuration file. So in order to configure bits and pieces of Emacs, for example evil-mode and vertico we can append emacs-configurations into one big configuration. I do this as follows. #+BEGIN_SRC scheme (define evil-configuration (emacs-configuration (emacs-packages (list (specification->package "emacs-evil"))) (init '((evil-mode 1) (define vertico-configuration (emacs-configuration (emacs-packages (list (specification->package "emacs-vertico"))) (init '((vertico-mode 1) (define-public total-emacs-configuration (fold (lambda (config-1 config-2) (emacs-configuration (init (append (emacs-configuration-init config-1) (emacs-configuration-init config-2))) (early-init (append (emacs-configuration-early-init config-1) (emacs-configuration-early-init config-2))) (emacs-packages (append (emacs-configuration-emacs-packages config-1) (emacs-configuration-emacs-packages config-2) (emacs-configuration) (list evil-configuration vertico-configuration))) #+END_SRC We can actually go crazy with this idea. The next source block is a generalization of the last one. Rather than declaring the list of configurations, we have Guile figure out all of the bound =emacs-configurations= in the current module and append them that way. #+BEGIN_SRC scheme (define-public total-emacs-configuration (fold (lambda (config-1 config-2) (emacs-configuration (init (append (emacs-configuration-init config-1) (emacs-configuration-init config-2))) (early-init (append (emacs-configuration-early-init config-1) (emacs-configuration-early-init config-2))) (emacs-packages (append (emacs-configuration-emacs-packages config-1) (emacs-configuration-emacs-packages config-2) (emacs-configuration) (filter emacs-configuration? (map variable-ref (filter variable-bound? (hash-map->list (lambda (x y) y) (struct-ref (current-module) 0))) #+END_SRC What further improvements could I add to this system? The end goal (hopefully) is to help add another home service to Guix. I was inspired by David Wilson's call to action during his Guix Home talk at the 10 year anniversary event. On Mon, Oct 17, 2022 at 12:09 PM wrote: > > October 17, 2022 2:38 AM, "Zain Jabbar" wrote: > > > Aloha Guix Development Team, > > > > Running =guix home search emacs= returns nothing. I also could not find an > > email using =C-u M-x > > debbugs-gnu= about an Emacs configuration service. > > > > This is my first email to this mailing address. Please give me pointers on > > formatting and further > > improvements. > > I think you sent an html email. Generally you want to send plain text > emails. :) > > > I have attempted to make an =emacs-home-service-type= so that it is > > possible to configure Emacs > > using Guix home. This code is extremely preliminary hence I don't even > > think it is worth sending as > > a patch. Also I have never worked on a multi person Git project before and > > do not know how to solve > > the keyring error I get when using guix pull. I will outline wha
Creating an Emacs Home Configuration Service
Aloha Guix Development Team, Running =guix home search emacs= returns nothing. I also could not find an email using =C-u M-x debbugs-gnu= about an Emacs configuration service. This is my first email to this mailing address. Please give me pointers on formatting and further improvements. I have attempted to make an =emacs-home-service-type= so that it is possible to configure Emacs using Guix home. This code is extremely preliminary hence I don't even think it is worth sending as a patch. Also I have never worked on a multi person Git project before and do not know how to solve the keyring error I get when using guix pull. I will outline what my code does and what features I would like to add. #+BEGIN_SRC scheme (define* (emacs-configuration-service name #:key (init '()) (early-init '()) (emacs-packages '())) (service-type (name (symbol-append 'emacs- name '-configuration)) (extensions (list (service-extension home-profile-service-type (lambda (config) emacs-packages)) (service-extension home-files-service-type (lambda (config) (list `(,(string-append ".config/emacs/services/" (symbol->string name) ".el") ,(scheme-file (string-append (symbol->string name) ".el") init #:splice? #t)) `(,(string-append ".config/emacs/early-services/" (symbol->string name) ".el") ,(scheme-file (string-append "early-" (symbol->string name) ".el") early-init #:splice? #t))) (default-value #f) (description "Configures Emacs init.el"))) (define-public emacs-init-service-type (service-type (name 'home-emacs) (extensions (list (service-extension home-profile-service-type (lambda (config) (list emacs-next))) (service-extension home-files-service-type (lambda (config) (list `(".config/emacs/early-init.el" ,(scheme-file "early-init.el" '((mapc 'load (file-expand-wildcards "~/.config/emacs/early-services/*.el"))) #:splice? #t)) `(".config/emacs/init.el" ,(scheme-file "init.el" '((mapc 'load (file-expand-wildcards "~/.config/emacs/services/*.el"))) #:splice? #t))) (default-value #f) (description "Configures Emacs init.el"))) #+END_SRC I define a general configuration service generator which takes in four things: 1. The =name= of the service 2. The configuration to be ran in =init.el= 3. The configuration to be ran in =early-init.el= 4. The packages in Guix to be added to the =home-profile=. After giving the =name=, =packages=, and =config.el= files we get a new service type that we can add to our home declaration. This service will then add a file in =~/.config/emacs/services/emacs-{NAME}-configuration.el=. I then have another service that places an =init.el= which loads everything in the service directory. If we want to install and configure =evil-mode= using this =home-service= we may define the following somewhere. #+BEGIN_SRC scheme (define-public emacs-evil-service-type (emacs-configuration-service 'evil #:emacs-packages (list emacs-evil) #:init '((evil-mode 1 #+END_SRC Within our =home-environment= we may add the service using: #+BEGIN_SRC scheme (home-environment ;; ...Things in the home-environment... (services (list ;; ...Other Services... (service emacs-evil-service-type #+END_SRC There are some missing features I want to add. 1. Have the =home-emacs-*-service-type= service-types add to the =init.el= directly rather than within a folder to be loaded. I couldn't add two files with the same name to the store. So I have emacs-evil.el in the store to be placed separately later rather than appending to the existing init.el file. 2. Have Emacs update whenever the =home-environment= is updated. Meaning, if I did not add =(service emacs-evil-service-type)= in my =home-environment= then obviously =M-x evil-mode= should not work. But after adding the service then I want =M-x evil-mode= to work without having to restart Emacs. I do not understand the Emacs loading system on Guix well enough to know why it does not work. Skipping all of the =home-service= stuff, running =guix install emacs-evil-mode= then =(guix-emacs-autoload-packages)= does not let emacs know that =evil-mode= is installed. I would need to close Emacs and start Emacs again for Emacs to know about =evil-mode= being installed. 3. Use configurations somehow. I have completely neglected this feature in my system. I do not know what would be useful there. -- Thank you, Zain Jabbar