~ruther/guix-local

3f900442b4b3199f8601934ee1674b178858a412 — Ludovic Courtès 6 months ago a1276ea
home: services: bash: Support setting shell variables.

* gnu/home/services.scm (shell-variable-definitions): New procedure.
* gnu/home/services/shells.scm (serialize-shell-variables): New procedure.
(home-bash-configuration)[variables]: New field.
(add-bash-configuration): Honor it.
(home-bash-extension)[variables]: New field.
(home-bash-extensions): Handle ‘variables’.
* doc/guix.texi (Shells Home Services): Update.  Change ‘PS1’ example to use
‘variables’, not ‘environment-variables’.
* doc/he-config-bare-bones.scm: Use ‘variables’ instead of ‘bash-profile’.

Change-Id: I29083d6313d10b1eb9d91eccacfb33efefe60d58
4 files changed, 96 insertions(+), 31 deletions(-)

M doc/guix.texi
M doc/he-config-bare-bones.scm
M gnu/home/services.scm
M gnu/home/services/shells.scm
M doc/guix.texi => doc/guix.texi +44 -23
@@ 50319,6 50319,8 @@ Extend home-shell-profile service only if you really know what you do.
@subsubheading Bash Home Service

@anchor{home-bash-configuration}
@c %start of fragment

@deftp {Data Type} home-bash-configuration
Available @code{home-bash-configuration} fields are:



@@ 50333,13 50335,19 @@ use Guix System, is it safe to set this to @code{#f}, as in this case
this is already taken care of by the globally installed
@file{/etc/bashrc}.

@item @code{environment-variables} (default: @code{'()}) (type: alist)
Association list of environment variables to set for the Bash session.  The
rules for the @code{home-environment-variables-service-type} apply
here (@pxref{Essential Home Services}).  The contents of this field will be
added after the contents of the @code{bash-profile} field.
@item @code{environment-variables} (default: @code{()}) (type: alist)
Association list of environment variables to set for the Bash session.
The rules for the @code{home-environment-variables-service-type} apply
here (@pxref{Essential Home Services}).  The contents of this field will
be added after the contents of the @code{bash-profile} field.

@item @code{aliases} (default: @code{%default-bash-aliases}) (type: alist)
@item @code{variables} (default: @code{()}) (type: alist)
Bash variables (not to be confused with environment variables) to be set
in @file{.bashrc} for use by interactive shells.  A typical example of
such variables is @code{HISTSIZE} and related history variables
(@pxref{Bash Variables,,, bash,Bash Reference Manual}).

@item @code{aliases} (type: alist)
Association list of aliases to set for the Bash session.  The aliases
will be defined after the contents of the @code{bashrc} field has been
put in the @file{.bashrc} file.  The alias will automatically be quoted,


@@ 50355,27 50363,31 @@ turns into
alias ls="ls -alF"
@end example

@item @code{bash-profile} (default: @code{'()}) (type: text-config)
@item @code{bash-profile} (default: @code{()}) (type: text-config)
List of file-like objects, which will be added to @file{.bash_profile}.
Used for executing user's commands at start of login shell (In most
cases the shell started on tty just after login).  @file{.bash_login}
won't be ever read, because @file{.bash_profile} always present.

@item @code{bashrc} (default: @code{'()}) (type: text-config)
@item @code{bashrc} (default: @code{()}) (type: text-config)
List of file-like objects, which will be added to @file{.bashrc}.  Used
for executing user's commands at start of interactive shell (The shell
for interactive usage started by typing @code{bash} or by terminal app
or any other program).

@item @code{bash-logout} (default: @code{'()}) (type: text-config)
@item @code{bash-logout} (default: @code{()}) (type: text-config)
List of file-like objects, which will be added to @file{.bash_logout}.
Used for executing user's commands at the exit of login shell.  It won't
be read in some cases (if the shell terminates by exec'ing another
process for example).

@end table

@end deftp


@c %end of fragment

You can extend the Bash service by using the @code{home-bash-extension}
configuration record, whose fields must mirror that of
@code{home-bash-configuration} (@pxref{home-bash-configuration}).  The


@@ 50385,14 50397,14 @@ Bash Reference Manual}.

For example, here is how you would define a service that extends the
Bash service such that @file{~/.bash_profile} defines an additional
environment variable, @env{PS1}:
shell variable, @env{PS1}:

@lisp
(define bash-fancy-prompt-service
  (simple-service 'bash-fancy-prompt
                  home-bash-service-type
                  (home-bash-extension
                   (environment-variables
                   (variables
                    '(("PS1" . "\\u \\wλ "))))))
@end lisp



@@ 50400,34 50412,43 @@ You would then add @code{bash-fancy-prompt-service} to the list in the
@code{services} field of your @code{home-environment}.  The reference of
@code{home-bash-extension} follows.

@c %start of fragment

@deftp {Data Type} home-bash-extension
Available @code{home-bash-extension} fields are:

@table @asis
@item @code{environment-variables} (default: @code{'()}) (type: alist)
Additional environment variables to set.  These will be combined with the
environment variables from other extensions and the base service to form one
coherent block of environment variables.
@item @code{environment-variables} (default: @code{()}) (type: alist)
Additional environment variables to set.  These will be combined with
the environment variables from other extensions and the base service to
form one coherent block of environment variables.

@item @code{aliases} (default: @code{'()}) (type: alist)
@item @code{variables} (default: @code{()}) (type: alist)
Extra Bash variables (not to be confused with environment variables) to
be set in @file{.bashrc} for use by interactive shells.

@item @code{aliases} (default: @code{()}) (type: alist)
Additional aliases to set.  These will be combined with the aliases from
other extensions and the base service.

@item @code{bash-profile} (default: @code{'()}) (type: text-config)
Additional text blocks to add to @file{.bash_profile}, which will be combined
with text blocks from other extensions and the base service.
@item @code{bash-profile} (default: @code{()}) (type: text-config)
Additional text blocks to add to @file{.bash_profile}, which will be
combined with text blocks from other extensions and the base service.

@item @code{bashrc} (default: @code{'()}) (type: text-config)
@item @code{bashrc} (default: @code{()}) (type: text-config)
Additional text blocks to add to @file{.bashrc}, which will be combined
with text blocks from other extensions and the base service.

@item @code{bash-logout} (default: @code{'()}) (type: text-config)
Additional text blocks to add to @file{.bash_logout}, which will be combined
with text blocks from other extensions and the base service.
@item @code{bash-logout} (default: @code{()}) (type: text-config)
Additional text blocks to add to @file{.bash_logout}, which will be
combined with text blocks from other extensions and the base service.

@end table

@end deftp

@c %end of fragment

@subsubheading Zsh Home Service

@deftp {Data Type} home-zsh-configuration

M doc/he-config-bare-bones.scm => doc/he-config-bare-bones.scm +3 -2
@@ 13,8 13,9 @@
            (service home-bash-service-type
                     (home-bash-configuration
                      (guix-defaults? #t)
                      (bash-profile (list (plain-file "bash-profile" "\
export HISTFILE=$XDG_CACHE_HOME/.bash_history")))))
                      (variables
                       `(("HISTFILE" . "$XDG_CACHE_HOME/.bash_history")
                         ("HISTSIZE" . "50000")))))

            (simple-service 'test-config
                            home-xdg-configuration-files-service-type

M gnu/home/services.scm => gnu/home/services.scm +23 -1
@@ 1,7 1,7 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2021-2023 Andrew Tropin <andrew@trop.in>
;;; Copyright © 2021 Xinglu Chen <public@yoctocell.xyz>
;;; Copyright © 2022-2023 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2022-2023, 2025 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2023 Carlo Zancanaro <carlo@zancanaro.id.au>
;;;
;;; This file is part of GNU Guix.


@@ 58,6 58,7 @@

            with-shell-quotation-bindings
            environment-variable-shell-definitions
            shell-variable-definitions
            home-files-directory
            xdg-configuration-files-directory
            xdg-data-files-directory


@@ 241,6 242,27 @@ ensures variable values are properly quoted."
                                  "\n")))
              variables))))

(define (shell-variable-definitions variables)
  "Return a gexp that evaluates to a list of POSIX shell statements defining
VARIABLES, a list of variable name/value pairs, as shell variables (not
environment variables).  The returned code ensures variable values are
properly quoted."
  (with-shell-quotation-bindings
   #~(string-append
      #$@(map (match-lambda
                ((key . (or (? string? value)
                            (? file-like? value)
                            (? gexp? value)))
                 #~(string-append #$key "="
                                  (shell-double-quote #$value)
                                  "\n"))
                ((key . (? literal-string? value))
                 #~(string-append #$key "="
                                  (shell-single-quote
                                   #$(literal-string-value value))
                                  "\n")))
              variables))))

(define (environment-variables->setup-environment-script vars)
  "Return a file that can be sourced by a POSIX compliant shell which
initializes the environment.  The file will source the home

M gnu/home/services/shells.scm => gnu/home/services/shells.scm +26 -5
@@ 2,6 2,7 @@
;;; Copyright © 2021 Andrew Tropin <andrew@trop.in>
;;; Copyright © 2021 Xinglu Chen <public@yoctocell.xyz>
;;; Copyright © 2023 Efraim Flashner <efraim@flashner.co.il>
;;; Copyright © 2025 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;


@@ 121,6 122,9 @@ service type can be extended with a list of file-like objects.")))
(define (serialize-posix-env-vars field-name val)
  (environment-variable-shell-definitions val))

(define (serialize-shell-variables field value)
  (shell-variable-definitions value))


;;;
;;; Zsh.


@@ 347,6 351,13 @@ rules for the @code{home-environment-variables-service-type} apply
here (@pxref{Essential Home Services}).  The contents of this field will be
added after the contents of the @code{bash-profile} field."
   (serializer serialize-posix-env-vars))
  (variables
   (alist '())
   "Bash variables (not to be confused with environment variables) to be set
in @file{.bashrc} for use by interactive shells.  A typical example of such
variables is @code{HISTSIZE} and related history variables (@pxref{Bash
Variables,,, bash, Bash Reference Manual})."
   (serializer serialize-shell-variables))
  (aliases
   (alist %default-bash-aliases)
   "Association list of aliases to set for the Bash session.  The aliases will be


@@ 425,10 436,12 @@ if [ -f ~/.bashrc ]; then source ~/.bashrc; fi

     ,@(list (file-if-not-empty
              'bashrc
              (if (home-bash-configuration-guix-defaults? config)
                  (list (plain-file-content %default-bashrc) "\n"
                        (serialize-field 'aliases))
                  (list (serialize-field 'aliases))))
              (let ((user-settings (list (serialize-field 'variables) "\n"
                                         (serialize-field 'aliases))))
                (if (home-bash-configuration-guix-defaults? config)
                    (cons* (plain-file-content %default-bashrc) "\n"
                           user-settings)
                    user-settings)))
             (file-if-not-empty 'bash-logout)))))

(define (add-bash-packages config)


@@ 440,6 453,10 @@ if [ -f ~/.bashrc ]; then source ~/.bashrc; fi
   "Additional environment variables to set.  These will be combined with the
environment variables from other extensions and the base service to form one
coherent block of environment variables.")
  (variables
   (alist '())
   "Extra Bash variables (not to be confused with environment variables) to be
set in @file{.bashrc} for use by interactive shells.")
  (aliases
   (alist '())
   "Additional aliases to set.  These will be combined with the aliases from


@@ 459,13 476,17 @@ with text blocks from other extensions and the base service."))

(define (home-bash-extensions original-config extension-configs)
  (match-record original-config <home-bash-configuration>
    (environment-variables aliases bash-profile bashrc bash-logout)
    (environment-variables variables aliases bash-profile bashrc bash-logout)
    (home-bash-configuration
     (inherit original-config)
     (environment-variables
      (append environment-variables
              (append-map
               home-bash-extension-environment-variables extension-configs)))
     (variables
      (append variables
              (append-map
               home-bash-extension-variables extension-configs)))
     (aliases
      (append aliases
              (append-map