GNU bug report logs - #60341
[PATCH Home] home: services: environment-variables: Add support for literal strings.

Previous Next

Package: guix-patches;

Reported by: Ludovic Courtès <ludo <at> gnu.org>

Date: Mon, 26 Dec 2022 18:21:01 UTC

Severity: normal

Tags: patch

Done: Ludovic Courtès <ludo <at> gnu.org>

Bug is archived. No further changes may be made.

To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 60341 in the body.
You can then email your comments to 60341 AT debbugs.gnu.org in the normal way.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to guix-patches <at> gnu.org:
bug#60341; Package guix-patches. (Mon, 26 Dec 2022 18:21:01 GMT) Full text and rfc822 format available.

Acknowledgement sent to Ludovic Courtès <ludo <at> gnu.org>:
New bug report received and forwarded. Copy sent to guix-patches <at> gnu.org. (Mon, 26 Dec 2022 18:21:01 GMT) Full text and rfc822 format available.

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

From: Ludovic Courtès <ludo <at> gnu.org>
To: guix-patches <at> gnu.org
Cc: Ludovic Courtès <ludo <at> gnu.org>
Subject: [PATCH Home] home: services: environment-variables: Add support for
 literal strings.
Date: Mon, 26 Dec 2022 19:19:38 +0100
* gnu/home/services.scm (<literal-string>): New record type.
(environment-variable-shell-definitions): Split 'shell-quote' into
'quote-string' and 'shell-double-quote'.  Add 'shell-single-quote'.
Add clause for 'literal-string' records.
* tests/guix-home.sh: Test it.
* doc/guix.texi (Essential Home Services): Document it.
---
 doc/guix.texi         | 14 ++++++++++---
 gnu/home/services.scm | 48 ++++++++++++++++++++++++++++++++-----------
 tests/guix-home.sh    |  4 +++-
 3 files changed, 50 insertions(+), 16 deletions(-)

Hi!

I found that it’s occasionally useful to be able to define shell variables
with a value that is to be taken literally, without shell expansion.  This
is what this patch implements.

Thoughts?

Ludo’.

diff --git a/doc/guix.texi b/doc/guix.texi
index efd281d9b0..44361b481a 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -40972,13 +40972,15 @@ The easiest way to extend a service type, without defining a new service
 type is to use the @code{simple-service} helper from @code{(gnu
 services)}.
 
+@findex literal-string
 @lisp
 (simple-service 'some-useful-env-vars-service
 		home-environment-variables-service-type
 		`(("LESSHISTFILE" . "$XDG_CACHE_HOME/.lesshst")
                   ("SHELL" . ,(file-append zsh "/bin/zsh"))
                   ("USELESS_VAR" . #f)
-                  ("_JAVA_AWT_WM_NONREPARENTING" . #t)))
+                  ("_JAVA_AWT_WM_NONREPARENTING" . #t)
+                  ("LITERAL_VALUE" . ,(literal-string "$@{abc@}"))))
 @end lisp
 
 If you include such a service in you home environment definition, it
@@ -40986,11 +40988,17 @@ will add the following content to the @file{setup-environment} script
 (which is expected to be sourced by the login shell):
 
 @example
-export LESSHISTFILE=$XDG_CACHE_HOME/.lesshst
-export SHELL=/gnu/store/2hsg15n644f0glrcbkb1kqknmmqdar03-zsh-5.8/bin/zsh
+export LESSHISTFILE="$XDG_CACHE_HOME/.lesshst"
+export SHELL="/gnu/store/2hsg15n644f0glrcbkb1kqknmmqdar03-zsh-5.8/bin/zsh"
 export _JAVA_AWT_WM_NONREPARENTING
+export LITERAL_VALUE='$@{abc@}'
 @end example
 
+Notice that @code{literal-string} above lets us declare that a value is
+to be interpreted as a @dfn{literal string}, meaning that ``special
+characters'' such as the dollar sign will not be interpreted by the
+shell.
+
 @quotation Note
 Make sure that module @code{(gnu packages shells)} is imported with
 @code{use-modules} or any other way, this namespace contains the
diff --git a/gnu/home/services.scm b/gnu/home/services.scm
index 99035686f1..2c1f58fddf 100644
--- a/gnu/home/services.scm
+++ b/gnu/home/services.scm
@@ -1,6 +1,7 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2021 Andrew Tropin <andrew <at> trop.in>
 ;;; Copyright © 2021 Xinglu Chen <public <at> yoctocell.xyz>
+;;; Copyright © 2022 Ludovic Courtès <ludo <at> gnu.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -33,6 +34,7 @@ (define-module (gnu home services)
   #:use-module (guix i18n)
   #:use-module (guix modules)
   #:use-module (srfi srfi-1)
+  #:use-module (srfi srfi-9)
   #:use-module (ice-9 match)
   #:use-module (ice-9 vlist)
 
@@ -47,6 +49,10 @@ (define-module (gnu home services)
             home-run-on-change-service-type
             home-provenance-service-type
 
+            literal-string
+            literal-string?
+            literal-string-value
+
             environment-variable-shell-definitions
             home-files-directory
             xdg-configuration-files-directory
@@ -171,32 +177,50 @@ (define home-profile-service-type
 configuration files that the user has declared in their
 @code{home-environment} record.")))
 
+;; Representation of a literal string.
+(define-record-type <literal-string>
+  (literal-string str)
+  literal-string?
+  (str literal-string-value))
+
 (define (environment-variable-shell-definitions variables)
   "Return a gexp that evaluates to a list of POSIX shell statements defining
 VARIABLES, a list of environment variable name/value pairs.  The returned code
 ensures variable values are properly quoted."
-  #~(let ((shell-quote
-           (lambda (value)
-             ;; Double-quote VALUE, leaving dollar sign as is.
-             (let ((quoted (list->string
-                            (string-fold-right
+  #~(let* ((quote-string
+            (lambda (value quoted-chars)
+              (list->string (string-fold-right
                              (lambda (chr lst)
-                               (case chr
-                                 ((#\" #\\)
-                                  (append (list chr #\\) lst))
-                                 (else (cons chr lst))))
+                               (if (memq chr quoted-chars)
+                                   (append (list chr #\\) lst)
+                                   (cons chr lst)))
                              '()
                              value))))
-               (string-append "\"" quoted "\"")))))
+           (shell-double-quote
+            (lambda (value)
+              ;; Double-quote VALUE, leaving dollar sign as is.
+              (string-append "\"" (quote-string value '(#\" #\\))
+                             "\"")))
+           (shell-single-quote
+            (lambda (value)
+              ;; Single-quote VALUE to enter a literal string.
+              (string-append "'" (quote-string value '(#\' #\\))
+                             "'"))))
       (string-append
        #$@(map (match-lambda
                  ((key . #f)
                   "")
                  ((key . #t)
                   #~(string-append "export " #$key "\n"))
-                 ((key . value)
+                 ((key . (? string? value))
                   #~(string-append "export " #$key "="
-                                   (shell-quote #$value) "\n")))
+                                   (shell-double-quote #$value)
+                                   "\n"))
+                 ((key . (? literal-string? value))
+                  #~(string-append "export " #$key "="
+                                   (shell-single-quote
+                                    #$(literal-string-value value))
+                                   "\n")))
                variables))))
 
 (define (environment-variables->setup-environment-script vars)
diff --git a/tests/guix-home.sh b/tests/guix-home.sh
index d5e2dadbb5..423ebf6f33 100644
--- a/tests/guix-home.sh
+++ b/tests/guix-home.sh
@@ -81,7 +81,8 @@ trap 'chmod -Rf +w "$test_directory"; rm -rf "$test_directory"' EXIT
 
    (simple-service 'add-environment-variable
                    home-environment-variables-service-type
-                   '(("TODAY" . "26 messidor")))
+                   `(("TODAY" . "26 messidor")
+                     ("LITERAL" . ,(literal-string "${abc}"))))
 
    (simple-service 'home-bash-service-extension-test
                    home-bash-service-type
@@ -149,6 +150,7 @@ EOF
     grep -q "the content of ~/.config/test.conf" "${HOME}/.config/test.conf"
     grep '^export PS1="\$GUIX_ENVIRONMENT λ "$' "${HOME}/.bash_profile"
     ( . "${HOME}/.guix-home/setup-environment"; test "$TODAY" = "26 messidor" )
+    ( . "${HOME}/.guix-home/setup-environment"; test "$LITERAL" = '${abc}' )
 
     # This one should still be here.
     grep "stay around" "$HOME/.config/random-file"

base-commit: 9369c1ccf47d9bf6f2e28a9454c1c329a2044f19
-- 
2.38.1





Information forwarded to guix-patches <at> gnu.org:
bug#60341; Package guix-patches. (Tue, 27 Dec 2022 03:03:01 GMT) Full text and rfc822 format available.

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

From: Andrew Tropin <andrew <at> trop.in>
To: Ludovic Courtès <ludo <at> gnu.org>, 60341 <at> debbugs.gnu.org
Cc: Ludovic Courtès <ludo <at> gnu.org>
Subject: Re: [bug#60341] [PATCH Home] home: services: environment-variables:
 Add support for literal strings.
Date: Tue, 27 Dec 2022 07:02:23 +0400
[Message part 1 (text/plain, inline)]
On 2022-12-26 19:19, Ludovic Courtès wrote:

> * gnu/home/services.scm (<literal-string>): New record type.
> (environment-variable-shell-definitions): Split 'shell-quote' into
> 'quote-string' and 'shell-double-quote'.  Add 'shell-single-quote'.
> Add clause for 'literal-string' records.
> * tests/guix-home.sh: Test it.
> * doc/guix.texi (Essential Home Services): Document it.
> ---
>  doc/guix.texi         | 14 ++++++++++---
>  gnu/home/services.scm | 48 ++++++++++++++++++++++++++++++++-----------
>  tests/guix-home.sh    |  4 +++-
>  3 files changed, 50 insertions(+), 16 deletions(-)
>
> Hi!
>
> I found that it’s occasionally useful to be able to define shell variables
> with a value that is to be taken literally, without shell expansion.  This
> is what this patch implements.
>
> Thoughts?

Hi Ludo,

the code looks good.

I'm a little conserned that one need to learn a new abstraction to
properly quote the expression instead of just using " or ' inside value
string, but we already have af4c103595a725194318f40fc5aba110772ff417 and
with the current state of the code this change looks rational and
idiomatic.  Also, it makes the interface more high-level, which can be
good in some circumstances.

>
> Ludo’.
>
> diff --git a/doc/guix.texi b/doc/guix.texi
> index efd281d9b0..44361b481a 100644
> --- a/doc/guix.texi
> +++ b/doc/guix.texi
> @@ -40972,13 +40972,15 @@ The easiest way to extend a service type, without defining a new service
>  type is to use the @code{simple-service} helper from @code{(gnu
>  services)}.
>  
> +@findex literal-string
>  @lisp
>  (simple-service 'some-useful-env-vars-service
>  		home-environment-variables-service-type
>  		`(("LESSHISTFILE" . "$XDG_CACHE_HOME/.lesshst")
>                    ("SHELL" . ,(file-append zsh "/bin/zsh"))
>                    ("USELESS_VAR" . #f)
> -                  ("_JAVA_AWT_WM_NONREPARENTING" . #t)))
> +                  ("_JAVA_AWT_WM_NONREPARENTING" . #t)
> +                  ("LITERAL_VALUE" . ,(literal-string "$@{abc@}"))))
>  @end lisp
>  
>  If you include such a service in you home environment definition, it
> @@ -40986,11 +40988,17 @@ will add the following content to the @file{setup-environment} script
>  (which is expected to be sourced by the login shell):
>  
>  @example
> -export LESSHISTFILE=$XDG_CACHE_HOME/.lesshst
> -export SHELL=/gnu/store/2hsg15n644f0glrcbkb1kqknmmqdar03-zsh-5.8/bin/zsh
> +export LESSHISTFILE="$XDG_CACHE_HOME/.lesshst"
> +export SHELL="/gnu/store/2hsg15n644f0glrcbkb1kqknmmqdar03-zsh-5.8/bin/zsh"
>  export _JAVA_AWT_WM_NONREPARENTING
> +export LITERAL_VALUE='$@{abc@}'
>  @end example
>  
> +Notice that @code{literal-string} above lets us declare that a value is
> +to be interpreted as a @dfn{literal string}, meaning that ``special
> +characters'' such as the dollar sign will not be interpreted by the
> +shell.
> +
>  @quotation Note
>  Make sure that module @code{(gnu packages shells)} is imported with
>  @code{use-modules} or any other way, this namespace contains the
> diff --git a/gnu/home/services.scm b/gnu/home/services.scm
> index 99035686f1..2c1f58fddf 100644
> --- a/gnu/home/services.scm
> +++ b/gnu/home/services.scm
> @@ -1,6 +1,7 @@
>  ;;; GNU Guix --- Functional package management for GNU
>  ;;; Copyright © 2021 Andrew Tropin <andrew <at> trop.in>
>  ;;; Copyright © 2021 Xinglu Chen <public <at> yoctocell.xyz>
> +;;; Copyright © 2022 Ludovic Courtès <ludo <at> gnu.org>
>  ;;;
>  ;;; This file is part of GNU Guix.
>  ;;;
> @@ -33,6 +34,7 @@ (define-module (gnu home services)
>    #:use-module (guix i18n)
>    #:use-module (guix modules)
>    #:use-module (srfi srfi-1)
> +  #:use-module (srfi srfi-9)
>    #:use-module (ice-9 match)
>    #:use-module (ice-9 vlist)
>  
> @@ -47,6 +49,10 @@ (define-module (gnu home services)
>              home-run-on-change-service-type
>              home-provenance-service-type
>  
> +            literal-string
> +            literal-string?
> +            literal-string-value
> +
>              environment-variable-shell-definitions
>              home-files-directory
>              xdg-configuration-files-directory
> @@ -171,32 +177,50 @@ (define home-profile-service-type
>  configuration files that the user has declared in their
>  @code{home-environment} record.")))
>  
> +;; Representation of a literal string.
> +(define-record-type <literal-string>
> +  (literal-string str)
> +  literal-string?
> +  (str literal-string-value))
> +
>  (define (environment-variable-shell-definitions variables)
>    "Return a gexp that evaluates to a list of POSIX shell statements defining
>  VARIABLES, a list of environment variable name/value pairs.  The returned code
>  ensures variable values are properly quoted."
> -  #~(let ((shell-quote
> -           (lambda (value)
> -             ;; Double-quote VALUE, leaving dollar sign as is.
> -             (let ((quoted (list->string
> -                            (string-fold-right
> +  #~(let* ((quote-string
> +            (lambda (value quoted-chars)
> +              (list->string (string-fold-right
>                               (lambda (chr lst)
> -                               (case chr
> -                                 ((#\" #\\)
> -                                  (append (list chr #\\) lst))
> -                                 (else (cons chr lst))))
> +                               (if (memq chr quoted-chars)
> +                                   (append (list chr #\\) lst)
> +                                   (cons chr lst)))
>                               '()
>                               value))))
> -               (string-append "\"" quoted "\"")))))
> +           (shell-double-quote
> +            (lambda (value)
> +              ;; Double-quote VALUE, leaving dollar sign as is.
> +              (string-append "\"" (quote-string value '(#\" #\\))
> +                             "\"")))
> +           (shell-single-quote
> +            (lambda (value)
> +              ;; Single-quote VALUE to enter a literal string.
> +              (string-append "'" (quote-string value '(#\' #\\))
> +                             "'"))))
>        (string-append
>         #$@(map (match-lambda
>                   ((key . #f)
>                    "")
>                   ((key . #t)
>                    #~(string-append "export " #$key "\n"))
> -                 ((key . value)
> +                 ((key . (? string? value))
>                    #~(string-append "export " #$key "="
> -                                   (shell-quote #$value) "\n")))
> +                                   (shell-double-quote #$value)
> +                                   "\n"))
> +                 ((key . (? literal-string? value))
> +                  #~(string-append "export " #$key "="
> +                                   (shell-single-quote
> +                                    #$(literal-string-value value))
> +                                   "\n")))
>                 variables))))
>  
>  (define (environment-variables->setup-environment-script vars)
> diff --git a/tests/guix-home.sh b/tests/guix-home.sh
> index d5e2dadbb5..423ebf6f33 100644
> --- a/tests/guix-home.sh
> +++ b/tests/guix-home.sh
> @@ -81,7 +81,8 @@ trap 'chmod -Rf +w "$test_directory"; rm -rf "$test_directory"' EXIT
>  
>     (simple-service 'add-environment-variable
>                     home-environment-variables-service-type
> -                   '(("TODAY" . "26 messidor")))
> +                   `(("TODAY" . "26 messidor")
> +                     ("LITERAL" . ,(literal-string "${abc}"))))
>  
>     (simple-service 'home-bash-service-extension-test
>                     home-bash-service-type
> @@ -149,6 +150,7 @@ EOF
>      grep -q "the content of ~/.config/test.conf" "${HOME}/.config/test.conf"
>      grep '^export PS1="\$GUIX_ENVIRONMENT λ "$' "${HOME}/.bash_profile"
>      ( . "${HOME}/.guix-home/setup-environment"; test "$TODAY" = "26 messidor" )
> +    ( . "${HOME}/.guix-home/setup-environment"; test "$LITERAL" = '${abc}' )
>  
>      # This one should still be here.
>      grep "stay around" "$HOME/.config/random-file"
>
> base-commit: 9369c1ccf47d9bf6f2e28a9454c1c329a2044f19

-- 
Best regards,
Andrew Tropin
[signature.asc (application/pgp-signature, inline)]

Information forwarded to guix-patches <at> gnu.org:
bug#60341; Package guix-patches. (Tue, 03 Jan 2023 22:53:01 GMT) Full text and rfc822 format available.

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

From: Ludovic Courtès <ludo <at> gnu.org>
To: Andrew Tropin <andrew <at> trop.in>
Cc: 60341 <at> debbugs.gnu.org
Subject: Re: bug#60341: [PATCH Home] home: services: environment-variables:
 Add support for literal strings.
Date: Tue, 03 Jan 2023 23:52:44 +0100
Hi,

Andrew Tropin <andrew <at> trop.in> skribis:

> On 2022-12-26 19:19, Ludovic Courtès wrote:

[...]

>> I found that it’s occasionally useful to be able to define shell variables
>> with a value that is to be taken literally, without shell expansion.  This
>> is what this patch implements.
>>
>> Thoughts?
>
> Hi Ludo,
>
> the code looks good.
>
> I'm a little conserned that one need to learn a new abstraction to
> properly quote the expression instead of just using " or ' inside value
> string, but we already have af4c103595a725194318f40fc5aba110772ff417 and
> with the current state of the code this change looks rational and
> idiomatic.  Also, it makes the interface more high-level, which can be
> good in some circumstances.

Yeah, the shell/Scheme mixture is a bit weird; it’s sort of in-between
because you can’t completely ignore that it’s shell code under the hood.

Looking at <https://issues.guix.gnu.org/54469>, I think we should strive
to not generate non-working shell snippets.  Automatic quoting and this
‘literal-string’ construct are a way to achieve that.

Ludo’.




Information forwarded to guix-patches <at> gnu.org:
bug#60341; Package guix-patches. (Wed, 04 Jan 2023 05:26:01 GMT) Full text and rfc822 format available.

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

From: Andrew Tropin <andrew <at> trop.in>
To: Ludovic Courtès <ludo <at> gnu.org>
Cc: 60341 <at> debbugs.gnu.org
Subject: Re: bug#60341: [PATCH Home] home: services: environment-variables:
 Add support for literal strings.
Date: Wed, 04 Jan 2023 09:24:55 +0400
[Message part 1 (text/plain, inline)]
On 2023-01-03 23:52, Ludovic Courtès wrote:

> Hi,
>
> Andrew Tropin <andrew <at> trop.in> skribis:
>
>> On 2022-12-26 19:19, Ludovic Courtès wrote:
>
> [...]
>
>>> I found that it’s occasionally useful to be able to define shell variables
>>> with a value that is to be taken literally, without shell expansion.  This
>>> is what this patch implements.
>>>
>>> Thoughts?
>>
>> Hi Ludo,
>>
>> the code looks good.
>>
>> I'm a little conserned that one need to learn a new abstraction to
>> properly quote the expression instead of just using " or ' inside value
>> string, but we already have af4c103595a725194318f40fc5aba110772ff417 and
>> with the current state of the code this change looks rational and
>> idiomatic.  Also, it makes the interface more high-level, which can be
>> good in some circumstances.
>
> Yeah, the shell/Scheme mixture is a bit weird; it’s sort of in-between
> because you can’t completely ignore that it’s shell code under the hood.
>
> Looking at <https://issues.guix.gnu.org/54469>, I think we should strive
> to not generate non-working shell snippets.  Automatic quoting and this
> ‘literal-string’ construct are a way to achieve that.

Yep, I think this is a way to go.

-- 
Best regards,
Andrew Tropin
[signature.asc (application/pgp-signature, inline)]

Reply sent to Ludovic Courtès <ludo <at> gnu.org>:
You have taken responsibility. (Thu, 05 Jan 2023 14:20:02 GMT) Full text and rfc822 format available.

Notification sent to Ludovic Courtès <ludo <at> gnu.org>:
bug acknowledged by developer. (Thu, 05 Jan 2023 14:20:02 GMT) Full text and rfc822 format available.

Message #19 received at 60341-done <at> debbugs.gnu.org (full text, mbox):

From: Ludovic Courtès <ludo <at> gnu.org>
To: Andrew Tropin <andrew <at> trop.in>
Cc: 60341-done <at> debbugs.gnu.org
Subject: Re: bug#60341: [PATCH Home] home: services: environment-variables:
 Add support for literal strings.
Date: Thu, 05 Jan 2023 15:18:41 +0100
Andrew Tropin <andrew <at> trop.in> skribis:

> On 2023-01-03 23:52, Ludovic Courtès wrote:

[...]

>> Yeah, the shell/Scheme mixture is a bit weird; it’s sort of in-between
>> because you can’t completely ignore that it’s shell code under the hood.
>>
>> Looking at <https://issues.guix.gnu.org/54469>, I think we should strive
>> to not generate non-working shell snippets.  Automatic quoting and this
>> ‘literal-string’ construct are a way to achieve that.
>
> Yep, I think this is a way to go.

Alright, pushed as 73684dc90e013f2f0cca1097b0c944bb9aa88709.

Thanks!

Ludo’.




Information forwarded to guix-patches <at> gnu.org:
bug#60341; Package guix-patches. (Sun, 08 Jan 2023 02:30:02 GMT) Full text and rfc822 format available.

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

From: Trev <trev <at> trevdev.ca>
To: 60341 <at> debbugs.gnu.org
Subject: Thanks
Date: Sat, 7 Jan 2023 18:29:32 -0800
I always knew my `environment-variables` were a mess.  This patch broke
my guix home config and send me down a confusing rabbit hole to this
submission.  My environment-variables form looks so nice now ;P

-- 

Trev : 0FB7 D06B 4A2A F07E AD5B  1169 183B 6306 8AA1 D206




bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Sun, 05 Feb 2023 12:24:05 GMT) Full text and rfc822 format available.

This bug report was last modified 2 years and 197 days ago.

Previous Next


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