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 <jbra...@dismail.de> wrote: > > October 17, 2022 2:38 AM, "Zain Jabbar" <zaijab2...@gmail.com> 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 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. > > I believe that you are referring to using scheme records to configure the > emacs service. :) > > I would recommend using (define-configuration ...) procedure. > > (There is a define-record-type* as well, but I think the consensus is that > define-configuration* is a little easier to use. Does better error handling > and can help you generate documentation from the code). > > You can find examples of that here: > > https://git.savannah.gnu.org/cgit/guix.git/tree/gnu/services/mail.scm > > > > > -- > > Thank you, > > Zain Jabbar -- Thank you, Zain Jabbar On Mon, Oct 17, 2022 at 12:09 PM <jbra...@dismail.de> wrote: > > October 17, 2022 2:38 AM, "Zain Jabbar" <zaijab2...@gmail.com> 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 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. > > I believe that you are referring to using scheme records to configure the > emacs service. :) > > I would recommend using (define-configuration ...) procedure. > > (There is a define-record-type* as well, but I think the consensus is that > define-configuration* is a little easier to use. Does better error handling > and can help you generate documentation from the code). > > You can find examples of that here: > > https://git.savannah.gnu.org/cgit/guix.git/tree/gnu/services/mail.scm > > > > > -- > > Thank you, > > Zain Jabbar -- Thank you, Zain Jabbar