GNU bug report logs - #55420
[PATCH 0/2] Add a function to parse emacs elisp's package header

Previous Next

Package: guix-patches;

Reported by: Fredrik Salomonsson <plattfot <at> posteo.net>

Date: Sat, 14 May 2022 23:01: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 55420 in the body.
You can then email your comments to 55420 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#55420; Package guix-patches. (Sat, 14 May 2022 23:01:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Fredrik Salomonsson <plattfot <at> posteo.net>:
New bug report received and forwarded. Copy sent to guix-patches <at> gnu.org. (Sat, 14 May 2022 23:01:02 GMT) Full text and rfc822 format available.

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

From: Fredrik Salomonsson <plattfot <at> posteo.net>
To: guix-patches <at> gnu.org
Cc: Fredrik Salomonsson <plattfot <at> posteo.net>
Subject: [PATCH 0/2] Add a function to parse emacs elisp's package header
Date: Sat, 14 May 2022 23:00:17 +0000
When writing a guix.scm file for an emacs packages, I wanted a way to fetch
the version I specify in the header of the elisp file. I found that I could do
that with the lisp-mnt library in emacs. Unfortunately none of the emacs
utility functions in guix/build/emacs-utils.scm return the output of an
elisp expression.

With these two patches I aim to add that functionality.

I spilt it in two functions:

emacs-batch-script: Run an arbitrary elisp expression and return the output as
a string.

emacs-header-parse: Given a header section and a file it will return the value
of that section.

For example (emacs-header-parse "version" "path/to/an/elisp/package.el")

Reason for the spilt is that people might want to run other elisp snippets.

Fredrik Salomonsson (2):
  guix: emacs-utils: Add emacs-batch-script.
  guix: emacs-utils: Add emacs-header-parse.

 guix/build/emacs-utils.scm | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)


base-commit: 3935451f63c078cae9a928d87c6838ec3138abc0
-- 
2.36.0





Information forwarded to guix-patches <at> gnu.org:
bug#55420; Package guix-patches. (Sat, 14 May 2022 23:06:02 GMT) Full text and rfc822 format available.

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

From: Fredrik Salomonsson <plattfot <at> posteo.net>
To: 55420 <at> debbugs.gnu.org
Cc: Fredrik Salomonsson <plattfot <at> posteo.net>
Subject: [PATCH 1/2] guix: emacs-utils: Add emacs-batch-script.
Date: Sat, 14 May 2022 23:05:07 +0000
* guix/build/emacs-utils.scm (emacs-batch-script): New procedure.
---
 guix/build/emacs-utils.scm | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/guix/build/emacs-utils.scm b/guix/build/emacs-utils.scm
index 60a754b9e9..8d40b9e139 100644
--- a/guix/build/emacs-utils.scm
+++ b/guix/build/emacs-utils.scm
@@ -3,6 +3,7 @@
 ;;; Copyright © 2014 Alex Kost <alezost <at> gmail.com>
 ;;; Copyright © 2018, 2020, 2022 Maxim Cournoyer <maxim.cournoyer <at> gmail.com>
 ;;; Copyright © 2019 Liliana Marie Prikler <liliana.prikler <at> gmail.com>
+;;; Copyright © 2022 Fredrik Salomonsson <plattfot <at> posteo.net>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -22,10 +23,13 @@
 (define-module (guix build emacs-utils)
   #:use-module (guix build utils)
   #:use-module (ice-9 format)
+  #:use-module (ice-9 popen)
+  #:use-module (ice-9 rdelim)
   #:export (%emacs
             emacs-batch-eval
             emacs-batch-edit-file
             emacs-batch-disable-compilation
+            emacs-batch-script
             emacs-generate-autoloads
             emacs-byte-compile-directory
 
@@ -69,6 +73,15 @@ (define (emacs-batch-disable-compilation file)
       (add-file-local-variable 'no-byte-compile t)
       (basic-save-buffer))))
 
+(define (emacs-batch-script expr)
+  "Execute the Elisp code EXPR in Emacs batch mode and return output."
+  (call-with-port
+      (open-pipe*
+       OPEN_READ
+       (%emacs) "--quick" "--batch"
+       (string-append "--eval=" (expr->string expr)))
+    read-string))
+
 (define (emacs-generate-autoloads name directory)
   "Generate autoloads for Emacs package NAME placed in DIRECTORY."
   (let* ((file (string-append directory "/" name "-autoloads.el"))
-- 
2.36.0





Information forwarded to guix-patches <at> gnu.org:
bug#55420; Package guix-patches. (Sat, 14 May 2022 23:06:02 GMT) Full text and rfc822 format available.

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

From: Fredrik Salomonsson <plattfot <at> posteo.net>
To: 55420 <at> debbugs.gnu.org
Cc: Fredrik Salomonsson <plattfot <at> posteo.net>
Subject: [PATCH 2/2] guix: emacs-utils: Add emacs-header-parse.
Date: Sat, 14 May 2022 23:05:08 +0000
* guix/build/emacs-utils.scm (emacs-header-parse): New procedure.
---
 guix/build/emacs-utils.scm | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/guix/build/emacs-utils.scm b/guix/build/emacs-utils.scm
index 8d40b9e139..76d9464806 100644
--- a/guix/build/emacs-utils.scm
+++ b/guix/build/emacs-utils.scm
@@ -32,6 +32,7 @@ (define-module (guix build emacs-utils)
             emacs-batch-script
             emacs-generate-autoloads
             emacs-byte-compile-directory
+            emacs-header-parse
 
             as-display
             emacs-substitute-sexps
@@ -97,6 +98,14 @@ (define* (emacs-byte-compile-directory dir)
                 (byte-recompile-directory (file-name-as-directory ,dir) 0 1))))
     (emacs-batch-eval expr)))
 
+(define (emacs-header-parse section file)
+  "Parse the header SECTION in FILE and return it as a string."
+  (emacs-batch-script
+   `(progn
+     (require 'lisp-mnt)
+     (find-file ,file)
+     (princ (lm-header ,section)))))
+
 (define as-display         ;syntactic keyword for 'emacs-substitute-sexps'
   '(as display))
 
-- 
2.36.0





Information forwarded to guix-patches <at> gnu.org:
bug#55420; Package guix-patches. (Wed, 01 Jun 2022 20:39:02 GMT) Full text and rfc822 format available.

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

From: Ludovic Courtès <ludo <at> gnu.org>
To: Fredrik Salomonsson <plattfot <at> posteo.net>
Cc: 55420 <at> debbugs.gnu.org
Subject: Re: bug#55420: [PATCH 0/2] Add a function to parse emacs elisp's
 package header
Date: Wed, 01 Jun 2022 22:38:38 +0200
Hi Fredrik,

The patches LGTM modulo cosmetic issues:

Fredrik Salomonsson <plattfot <at> posteo.net> skribis:

> * guix/build/emacs-utils.scm (emacs-batch-script): New procedure.

[...]

> +(define (emacs-batch-script expr)
> +  "Execute the Elisp code EXPR in Emacs batch mode and return output."
> +  (call-with-port
> +      (open-pipe*
> +       OPEN_READ
> +       (%emacs) "--quick" "--batch"
> +       (string-append "--eval=" (expr->string expr)))
> +    read-string))

I suggest something like:

  (let* ((pipe (open-pipe* …))
         (output (read-string pipe))
         (status (close-pipe pipe)))
    (unless (zero? status)
      ;; Use SRFI-34 + either a &message condition or (better)
      ;; a dedicate SRFI-35 condition type for the error.
      (raise (condition …)))
    output)

That way, execution failures would be caught and reported.

Ludo’.
     




Information forwarded to guix-patches <at> gnu.org:
bug#55420; Package guix-patches. (Wed, 01 Jun 2022 20:40:01 GMT) Full text and rfc822 format available.

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

From: Ludovic Courtès <ludo <at> gnu.org>
To: Fredrik Salomonsson <plattfot <at> posteo.net>
Cc: 55420 <at> debbugs.gnu.org
Subject: Re: bug#55420: [PATCH 0/2] Add a function to parse emacs elisp's
 package header
Date: Wed, 01 Jun 2022 22:39:11 +0200
Fredrik Salomonsson <plattfot <at> posteo.net> skribis:

> * guix/build/emacs-utils.scm (emacs-header-parse): New procedure.

LGTM!

Could you send a v2 of these patches?

Thanks in advance,
Ludo’.




Information forwarded to guix-patches <at> gnu.org:
bug#55420; Package guix-patches. (Thu, 02 Jun 2022 02:54:01 GMT) Full text and rfc822 format available.

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

From: Fredrik Salomonsson <plattfot <at> posteo.net>
To: Ludovic Courtès <ludo <at> gnu.org>
Cc: 55420 <at> debbugs.gnu.org
Subject: Re: bug#55420: [PATCH 0/2] Add a function to parse emacs elisp's
 package header
Date: Thu, 02 Jun 2022 02:53:42 +0000
Hi Ludo,

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

> Hi Fredrik,
>
> The patches LGTM modulo cosmetic issues:
>
> Fredrik Salomonsson <plattfot <at> posteo.net> skribis:
>
>> * guix/build/emacs-utils.scm (emacs-batch-script): New procedure.
>
> [...]
>
>> +(define (emacs-batch-script expr)
>> +  "Execute the Elisp code EXPR in Emacs batch mode and return output."
>> +  (call-with-port
>> +      (open-pipe*
>> +       OPEN_READ
>> +       (%emacs) "--quick" "--batch"
>> +       (string-append "--eval=" (expr->string expr)))
>> +    read-string))
>
> I suggest something like:
>
>   (let* ((pipe (open-pipe* …))
>          (output (read-string pipe))
>          (status (close-pipe pipe)))
>     (unless (zero? status)
>       ;; Use SRFI-34 + either a &message condition or (better)
>       ;; a dedicate SRFI-35 condition type for the error.
>       (raise (condition …)))
>     output)
>
> That way, execution failures would be caught and reported.

Thank you for the feedback. I update the procedure to use a dedicated
SRFI-35 condition type. But I cannot figure out how to capture the error
message from emacs, as I want the condition type to contain both the
expression as well as the error you get from emacs.

Here is what I have so far:

    (define-condition-type &emacs-batch-error &error
      emacs-batch-error?
      (expression emacs-batch-error-expression)
      (message emacs-batch-error-message))
    
    (define (emacs-batch-script expr)
      "Execute the Elisp code EXPR in Emacs batch mode and return output."
      (let* ((error-pipe (open-output-string))
             (pipe (with-error-to-port error-pipe
                     (lambda ()
                       (open-pipe*
                        OPEN_READ
                        (%emacs) "--quick" "--batch"
                        (string-append "--eval=" (expr->string expr))))))
             (output (read-string pipe))
             (error (get-output-string error-pipe))
             (status (close-pipe pipe)))
        (unless (zero? status)
          (raise (condition (&emacs-batch-error
                             (expression expr)
                             (message error)))))
        output))

Here is the output when I test it out in the guix repl:
--------------------------------------------------------------------------------
scheme@(guix-user)> (use-modules (guix build emacs-utils))
(use-modules (guix build emacs-utils))
scheme@(guix-user)> (emacs-batch-script '(prog (princ "hello")))
(emacs-batch-script '(prog (princ "hello")))
ice-9/boot-9.scm:1685:16: In procedure raise-exception:
Wrong type (expecting exact integer): #<&emacs-batch-error expression: (prog (princ "hello")) message: "">

Entering a new prompt.  Type `,bt' for a backtrace or `,q' to continue.
scheme@(guix-user) [1]> 
--------------------------------------------------------------------------------

Note the message is empty in #<&emacs-batch-error…>. It should contain:

Debugger entered--Lisp error: (void-function prog)
  (prog (princ "hello"))
  command-line-1(("--eval=(prog (princ \"hello\"))"))
  command-line()
  normal-top-level()

Any idea what I'm doing wrong?

Thanks

-- 
s/Fred[re]+i[ck]+/Fredrik/g




Information forwarded to guix-patches <at> gnu.org:
bug#55420; Package guix-patches. (Thu, 02 Jun 2022 13:46:01 GMT) Full text and rfc822 format available.

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

From: Ludovic Courtès <ludo <at> gnu.org>
To: Fredrik Salomonsson <plattfot <at> posteo.net>
Cc: 55420 <at> debbugs.gnu.org
Subject: Re: bug#55420: [PATCH 0/2] Add a function to parse emacs elisp's
 package header
Date: Thu, 02 Jun 2022 15:44:53 +0200
Hi,

Fredrik Salomonsson <plattfot <at> posteo.net> skribis:

> Here is what I have so far:
>
>     (define-condition-type &emacs-batch-error &error
>       emacs-batch-error?
>       (expression emacs-batch-error-expression)
>       (message emacs-batch-error-message))
>     
>     (define (emacs-batch-script expr)
>       "Execute the Elisp code EXPR in Emacs batch mode and return output."
>       (let* ((error-pipe (open-output-string))
>              (pipe (with-error-to-port error-pipe
>                      (lambda ()
>                        (open-pipe*
>                         OPEN_READ
>                         (%emacs) "--quick" "--batch"
>                         (string-append "--eval=" (expr->string expr))))))
>              (output (read-string pipe))
>              (error (get-output-string error-pipe))
>              (status (close-pipe pipe)))
>         (unless (zero? status)
>           (raise (condition (&emacs-batch-error
>                              (expression expr)
>                              (message error)))))
>         output))

Unfortunately ‘open-pipe*’ is not smart enough to redirect stderr to a
non-file port (a string port in this case).

One way around it would be to merge stdout and stderr, like so:

  (parameterize ((current-error-port (current-output-port)))
    (open-pipe* …))

but then you get both on the same stream, which could be a problem for
instance if Emacs emits warnings and such.

You could work around it by establishing a second pipe:

  (match (pipe)
    ((stderr-input . stderr-output)
     (parameterize ((current-error-port stderr-output))
       (open-pipe* …))))

Here you should be able to read, in the parent process, from
‘stderr-input’.

Another option is to not try to capture stderr: after all, that’ll get
printed on the screen anyway.

HTH,
Ludo’.




Information forwarded to guix-patches <at> gnu.org:
bug#55420; Package guix-patches. (Sun, 05 Jun 2022 00:20:02 GMT) Full text and rfc822 format available.

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

From: Fredrik Salomonsson <plattfot <at> posteo.net>
To: 55420 <at> debbugs.gnu.org
Cc: Fredrik Salomonsson <plattfot <at> posteo.net>
Subject: [PATCH v2 1/2] guix: emacs-utils: Add emacs-batch-script.
Date: Sun,  5 Jun 2022 00:19:23 +0000
* guix/build/emacs-utils.scm (emacs-batch-script): New procedure.

* tests/build-emacs-utils.scm: New file.

* Makefile.am (TESTS): Add `tests/build-emacs-utils.scm'.
---
 Makefile.am                 |  1 +
 guix/build/emacs-utils.scm  | 30 +++++++++++++++++++++++++++
 tests/build-emacs-utils.scm | 41 +++++++++++++++++++++++++++++++++++++
 3 files changed, 72 insertions(+)
 create mode 100644 tests/build-emacs-utils.scm

diff --git a/Makefile.am b/Makefile.am
index e8d4b7ef8a..4a8514ea3a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -469,6 +469,7 @@ SCM_TESTS =					\
   tests/boot-parameters.scm			\
   tests/bournish.scm				\
   tests/builders.scm				\
+  tests/build-emacs-utils.scm			\
   tests/build-utils.scm			\
   tests/cache.scm				\
   tests/challenge.scm				\
diff --git a/guix/build/emacs-utils.scm b/guix/build/emacs-utils.scm
index 60a754b9e9..1684bf3262 100644
--- a/guix/build/emacs-utils.scm
+++ b/guix/build/emacs-utils.scm
@@ -3,6 +3,7 @@
 ;;; Copyright © 2014 Alex Kost <alezost <at> gmail.com>
 ;;; Copyright © 2018, 2020, 2022 Maxim Cournoyer <maxim.cournoyer <at> gmail.com>
 ;;; Copyright © 2019 Liliana Marie Prikler <liliana.prikler <at> gmail.com>
+;;; Copyright © 2022 Fredrik Salomonsson <plattfot <at> posteo.net>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -22,10 +23,19 @@
 (define-module (guix build emacs-utils)
   #:use-module (guix build utils)
   #:use-module (ice-9 format)
+  #:use-module (ice-9 popen)
+  #:use-module (ice-9 rdelim)
+  #:use-module (srfi srfi-34)
+  #:use-module (srfi srfi-35)
   #:export (%emacs
             emacs-batch-eval
             emacs-batch-edit-file
             emacs-batch-disable-compilation
+            emacs-batch-script
+
+            emacs-batch-error?
+            emacs-batch-error-message
+
             emacs-generate-autoloads
             emacs-byte-compile-directory
 
@@ -69,6 +79,26 @@ (define (emacs-batch-disable-compilation file)
       (add-file-local-variable 'no-byte-compile t)
       (basic-save-buffer))))
 
+(define-condition-type &emacs-batch-error &error
+  emacs-batch-error?
+  (message emacs-batch-error-message))
+
+(define (emacs-batch-script expr)
+  "Execute the Elisp code EXPR in Emacs batch mode and return output."
+  (let* ((error-pipe (pipe))
+         (port (parameterize ((current-error-port (cdr error-pipe)))
+                 (open-pipe*
+                  OPEN_READ
+                  (%emacs) "--quick" "--batch"
+                  (string-append "--eval=" (expr->string expr)))))
+         (output (read-string port))
+         (status (close-pipe port)))
+    (close-port (cdr error-pipe))
+    (unless (zero? status)
+      (raise (condition (&emacs-batch-error
+                         (message (read-string (car error-pipe)))))))
+    output))
+
 (define (emacs-generate-autoloads name directory)
   "Generate autoloads for Emacs package NAME placed in DIRECTORY."
   (let* ((file (string-append directory "/" name "-autoloads.el"))
diff --git a/tests/build-emacs-utils.scm b/tests/build-emacs-utils.scm
new file mode 100644
index 0000000000..03b73b1fed
--- /dev/null
+++ b/tests/build-emacs-utils.scm
@@ -0,0 +1,41 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2022 Fredrik Salomonsson <plattfot <at> posteo.net>
+;;;
+;;; This file is part of GNU Guix.
+;;;
+;;; GNU Guix is free software; you can redistribute it and/or modify it
+;;; under the terms of the GNU General Public License as published by
+;;; the Free Software Foundation; either version 3 of the License, or (at
+;;; your option) any later version.
+;;;
+;;; GNU Guix is distributed in the hope that it will be useful, but
+;;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;;; GNU General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
+
+
+(define-module (test build-emacs-utils)
+  #:use-module (guix tests)
+  #:use-module (guix build emacs-utils)
+  #:use-module (guix build utils)
+  #:use-module ((guix utils)
+                #:select (call-with-temporary-directory))
+  #:use-module (srfi srfi-34)
+  #:use-module (srfi srfi-64))
+
+(test-begin "build-emacs-utils")
+
+(test-equal "print foo from emacs"
+  "foo"
+  (emacs-batch-script '(princ "foo")))
+
+(test-assert "emacs-batch-script: raise &emacs-batch-error on failure"
+  (guard (c ((emacs-batch-error? c)
+             (string-contains (emacs-batch-error-message c)
+                              "Lisp error: (wrong-type-argument numberp \"three\")")))
+    (emacs-batch-script '(mapcar 'number-to-string (list 1 2 "three")))))
+
+(test-end "build-emacs-utils")

base-commit: 271736117e3f09b616a2dbd5d74c9595926c9297
-- 
2.36.1





Information forwarded to guix-patches <at> gnu.org:
bug#55420; Package guix-patches. (Sun, 05 Jun 2022 00:20:02 GMT) Full text and rfc822 format available.

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

From: Fredrik Salomonsson <plattfot <at> posteo.net>
To: 55420 <at> debbugs.gnu.org
Cc: Fredrik Salomonsson <plattfot <at> posteo.net>
Subject: [PATCH v2 2/2] guix: emacs-utils: Add emacs-header-parse.
Date: Sun,  5 Jun 2022 00:19:24 +0000
* guix/build/emacs-utils.scm (emacs-header-parse): New procedure.

* tests/build-emacs-utils.scm ("emacs-header-parse: fetch version",
  "emacs-header-parse: fetch keywords", "emacs-header-parse: fetch
  nonexistent author"): New tests.
---
 guix/build/emacs-utils.scm  |  9 +++++++++
 tests/build-emacs-utils.scm | 30 ++++++++++++++++++++++++++++++
 2 files changed, 39 insertions(+)

diff --git a/guix/build/emacs-utils.scm b/guix/build/emacs-utils.scm
index 1684bf3262..8ee547f2b3 100644
--- a/guix/build/emacs-utils.scm
+++ b/guix/build/emacs-utils.scm
@@ -38,6 +38,7 @@ (define-module (guix build emacs-utils)
 
             emacs-generate-autoloads
             emacs-byte-compile-directory
+            emacs-header-parse
 
             as-display
             emacs-substitute-sexps
@@ -114,6 +115,14 @@ (define* (emacs-byte-compile-directory dir)
                 (byte-recompile-directory (file-name-as-directory ,dir) 0 1))))
     (emacs-batch-eval expr)))
 
+(define (emacs-header-parse section file)
+  "Parse the header SECTION in FILE and return it as a string."
+  (emacs-batch-script
+   `(progn
+     (require 'lisp-mnt)
+     (find-file ,file)
+     (princ (lm-header ,section)))))
+
 (define as-display         ;syntactic keyword for 'emacs-substitute-sexps'
   '(as display))
 
diff --git a/tests/build-emacs-utils.scm b/tests/build-emacs-utils.scm
index 03b73b1fed..57647caaa2 100644
--- a/tests/build-emacs-utils.scm
+++ b/tests/build-emacs-utils.scm
@@ -38,4 +38,34 @@ (define-module (test build-emacs-utils)
                               "Lisp error: (wrong-type-argument numberp \"three\")")))
     (emacs-batch-script '(mapcar 'number-to-string (list 1 2 "three")))))
 
+(define (test-emacs-header-parse section)
+  (call-with-temporary-directory
+   (lambda (directory)
+     (let ((mock-elisp-file (string-append directory "/foo.el")))
+       (call-with-output-file mock-elisp-file
+         (lambda (port)
+           (display ";;; foo --- mock emacs package -*- lexical-binding: t -*-
+
+;; Created: 4 Jun 2022
+;; Keywords: lisp test
+;; Version: 1.0.0
+;;; Commentary:
+;;; Code:
+;;; foo.el ends here
+"
+                    port)))
+       (emacs-header-parse section mock-elisp-file)))))
+
+(test-equal "emacs-header-parse: fetch version"
+    "1.0.0"
+  (test-emacs-header-parse "version"))
+
+(test-equal "emacs-header-parse: fetch keywords"
+    "lisp test"
+  (test-emacs-header-parse "keywords"))
+
+(test-equal "emacs-header-parse: fetch nonexistent author"
+    "nil"
+  (test-emacs-header-parse "author"))
+
 (test-end "build-emacs-utils")
-- 
2.36.1





Information forwarded to guix-patches <at> gnu.org:
bug#55420; Package guix-patches. (Sun, 05 Jun 2022 00:43:01 GMT) Full text and rfc822 format available.

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

From: Fredrik Salomonsson <plattfot <at> posteo.net>
To: Ludovic Courtès <ludo <at> gnu.org>
Cc: 55420 <at> debbugs.gnu.org
Subject: Re: bug#55420: [PATCH 0/2] Add a function to parse emacs elisp's
 package header
Date: Sun, 05 Jun 2022 00:42:34 +0000
Hi Ludo,

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

> Hi,
>
> Fredrik Salomonsson <plattfot <at> posteo.net> skribis:
>
>> Here is what I have so far:
>>
>>     (define-condition-type &emacs-batch-error &error
>>       emacs-batch-error?
>>       (expression emacs-batch-error-expression)
>>       (message emacs-batch-error-message))
>>     
>>     (define (emacs-batch-script expr)
>>       "Execute the Elisp code EXPR in Emacs batch mode and return output."
>>       (let* ((error-pipe (open-output-string))
>>              (pipe (with-error-to-port error-pipe
>>                      (lambda ()
>>                        (open-pipe*
>>                         OPEN_READ
>>                         (%emacs) "--quick" "--batch"
>>                         (string-append "--eval=" (expr->string expr))))))
>>              (output (read-string pipe))
>>              (error (get-output-string error-pipe))
>>              (status (close-pipe pipe)))
>>         (unless (zero? status)
>>           (raise (condition (&emacs-batch-error
>>                              (expression expr)
>>                              (message error)))))
>>         output))
>
> Unfortunately ‘open-pipe*’ is not smart enough to redirect stderr to a
> non-file port (a string port in this case).
>
> One way around it would be to merge stdout and stderr, like so:
>
>   (parameterize ((current-error-port (current-output-port)))
>     (open-pipe* …))
>
> but then you get both on the same stream, which could be a problem for
> instance if Emacs emits warnings and such.
>
> You could work around it by establishing a second pipe:
>
>   (match (pipe)
>     ((stderr-input . stderr-output)
>      (parameterize ((current-error-port stderr-output))
>        (open-pipe* …))))
>
> Here you should be able to read, in the parent process, from
> ‘stderr-input’.
>
> Another option is to not try to capture stderr: after all, that’ll get
> printed on the screen anyway.

I just sent in v2 of the patches. Changes are:

- emacs-batch-script will now raise an &emacs-batch-error if emacs batch
  script fails. I opted to capture the stderr and package that up in the
  condition. Thank you for the pointers! I removed the expression slot I
  had in my prototype. It felt redundant, emacs error message should be
  enough.

- tests/build-emacs-utils.scm: I added tests for the two new procedures.

It was good that I added the tests as I had missed to use (srfi srfi-34)
in build/emacs-utils.scm during my prototyping and that generated the
cryptic error:

   Wrong type (expecting exact integer): #<&emacs-batch-error…>

Took me a while to figure that one out. But now all is good. The tests
are passing.

Thanks again.

-- 
s/Fred[re]+i[ck]+/Fredrik/g




Information forwarded to guix-patches <at> gnu.org:
bug#55420; Package guix-patches. (Sun, 05 Jun 2022 09:53:02 GMT) Full text and rfc822 format available.

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

From: Maxime Devos <maximedevos <at> telenet.be>
To: Fredrik Salomonsson <plattfot <at> posteo.net>, 55420 <at> debbugs.gnu.org
Subject: Re: [bug#55420] [PATCH v2 1/2] guix: emacs-utils: Add
 emacs-batch-script.
Date: Sun, 05 Jun 2022 11:52:27 +0200
[Message part 1 (text/plain, inline)]
Fredrik Salomonsson schreef op zo 05-06-2022 om 00:19 [+0000]:
> +(test-equal "print foo from emacs"
> +  "foo"
> +  (emacs-batch-script '(princ "foo")))

IIUC, this can only be run if emacs is in $PATH when running the tests,
so sometimes the test needs to be skipped.  As an example on how to do
this, see the "pypi->guix-package, wheels" test in tests/pypi.scm.

Greetings,
Maxime.
[signature.asc (application/pgp-signature, inline)]

Information forwarded to guix-patches <at> gnu.org:
bug#55420; Package guix-patches. (Sun, 05 Jun 2022 19:53:02 GMT) Full text and rfc822 format available.

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

From: Fredrik Salomonsson <plattfot <at> posteo.net>
To: 55420 <at> debbugs.gnu.org
Cc: Fredrik Salomonsson <plattfot <at> posteo.net>
Subject: [PATCH v3 1/2] guix: emacs-utils: Add emacs-batch-script.
Date: Sun,  5 Jun 2022 19:51:42 +0000
* guix/build/emacs-utils.scm (emacs-batch-script): New procedure.

* tests/build-emacs-utils.scm: New file.

* Makefile.am (TESTS): Add `tests/build-emacs-utils.scm'.
---
 Makefile.am                 |  1 +
 guix/build/emacs-utils.scm  | 30 ++++++++++++++++++++++++++
 tests/build-emacs-utils.scm | 43 +++++++++++++++++++++++++++++++++++++
 3 files changed, 74 insertions(+)
 create mode 100644 tests/build-emacs-utils.scm

diff --git a/Makefile.am b/Makefile.am
index e8d4b7ef8a..4a8514ea3a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -469,6 +469,7 @@ SCM_TESTS =					\
   tests/boot-parameters.scm			\
   tests/bournish.scm				\
   tests/builders.scm				\
+  tests/build-emacs-utils.scm			\
   tests/build-utils.scm			\
   tests/cache.scm				\
   tests/challenge.scm				\
diff --git a/guix/build/emacs-utils.scm b/guix/build/emacs-utils.scm
index 60a754b9e9..1684bf3262 100644
--- a/guix/build/emacs-utils.scm
+++ b/guix/build/emacs-utils.scm
@@ -3,6 +3,7 @@
 ;;; Copyright © 2014 Alex Kost <alezost <at> gmail.com>
 ;;; Copyright © 2018, 2020, 2022 Maxim Cournoyer <maxim.cournoyer <at> gmail.com>
 ;;; Copyright © 2019 Liliana Marie Prikler <liliana.prikler <at> gmail.com>
+;;; Copyright © 2022 Fredrik Salomonsson <plattfot <at> posteo.net>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -22,10 +23,19 @@
 (define-module (guix build emacs-utils)
   #:use-module (guix build utils)
   #:use-module (ice-9 format)
+  #:use-module (ice-9 popen)
+  #:use-module (ice-9 rdelim)
+  #:use-module (srfi srfi-34)
+  #:use-module (srfi srfi-35)
   #:export (%emacs
             emacs-batch-eval
             emacs-batch-edit-file
             emacs-batch-disable-compilation
+            emacs-batch-script
+
+            emacs-batch-error?
+            emacs-batch-error-message
+
             emacs-generate-autoloads
             emacs-byte-compile-directory
 
@@ -69,6 +79,26 @@ (define (emacs-batch-disable-compilation file)
       (add-file-local-variable 'no-byte-compile t)
       (basic-save-buffer))))
 
+(define-condition-type &emacs-batch-error &error
+  emacs-batch-error?
+  (message emacs-batch-error-message))
+
+(define (emacs-batch-script expr)
+  "Execute the Elisp code EXPR in Emacs batch mode and return output."
+  (let* ((error-pipe (pipe))
+         (port (parameterize ((current-error-port (cdr error-pipe)))
+                 (open-pipe*
+                  OPEN_READ
+                  (%emacs) "--quick" "--batch"
+                  (string-append "--eval=" (expr->string expr)))))
+         (output (read-string port))
+         (status (close-pipe port)))
+    (close-port (cdr error-pipe))
+    (unless (zero? status)
+      (raise (condition (&emacs-batch-error
+                         (message (read-string (car error-pipe)))))))
+    output))
+
 (define (emacs-generate-autoloads name directory)
   "Generate autoloads for Emacs package NAME placed in DIRECTORY."
   (let* ((file (string-append directory "/" name "-autoloads.el"))
diff --git a/tests/build-emacs-utils.scm b/tests/build-emacs-utils.scm
new file mode 100644
index 0000000000..27cff46c38
--- /dev/null
+++ b/tests/build-emacs-utils.scm
@@ -0,0 +1,43 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2022 Fredrik Salomonsson <plattfot <at> posteo.net>
+;;;
+;;; This file is part of GNU Guix.
+;;;
+;;; GNU Guix is free software; you can redistribute it and/or modify it
+;;; under the terms of the GNU General Public License as published by
+;;; the Free Software Foundation; either version 3 of the License, or (at
+;;; your option) any later version.
+;;;
+;;; GNU Guix is distributed in the hope that it will be useful, but
+;;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;;; GNU General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
+
+
+(define-module (test build-emacs-utils)
+  #:use-module (guix tests)
+  #:use-module (guix build emacs-utils)
+  #:use-module (guix build utils)
+  #:use-module ((guix utils)
+                #:select (call-with-temporary-directory))
+  #:use-module (srfi srfi-34)
+  #:use-module (srfi srfi-64))
+
+(test-begin "build-emacs-utils")
+;; Only run the following tests if emacs is present.
+(test-skip (if (which "emacs") 0 2))
+
+(test-equal "emacs-batch-script: print foo from emacs"
+  "foo"
+  (emacs-batch-script '(princ "foo")))
+
+(test-assert "emacs-batch-script: raise &emacs-batch-error on failure"
+  (guard (c ((emacs-batch-error? c)
+             (string-contains (emacs-batch-error-message c)
+                              "Lisp error: (wrong-type-argument numberp \"three\")")))
+    (emacs-batch-script '(mapcar 'number-to-string (list 1 2 "three")))))
+
+(test-end "build-emacs-utils")

base-commit: 271736117e3f09b616a2dbd5d74c9595926c9297
-- 
2.36.1





Information forwarded to guix-patches <at> gnu.org:
bug#55420; Package guix-patches. (Sun, 05 Jun 2022 19:53:02 GMT) Full text and rfc822 format available.

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

From: Fredrik Salomonsson <plattfot <at> posteo.net>
To: 55420 <at> debbugs.gnu.org
Cc: Fredrik Salomonsson <plattfot <at> posteo.net>
Subject: [PATCH v3 2/2] guix: emacs-utils: Add emacs-header-parse.
Date: Sun,  5 Jun 2022 19:51:43 +0000
* guix/build/emacs-utils.scm (emacs-header-parse): New procedure.

* tests/build-emacs-utils.scm ("emacs-header-parse: fetch version",
  "emacs-header-parse: fetch keywords", "emacs-header-parse: fetch
  nonexistent author"): New tests.
---
 guix/build/emacs-utils.scm  |  9 +++++++++
 tests/build-emacs-utils.scm | 27 ++++++++++++++++++++++++++-
 2 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/guix/build/emacs-utils.scm b/guix/build/emacs-utils.scm
index 1684bf3262..8ee547f2b3 100644
--- a/guix/build/emacs-utils.scm
+++ b/guix/build/emacs-utils.scm
@@ -38,6 +38,7 @@ (define-module (guix build emacs-utils)
 
             emacs-generate-autoloads
             emacs-byte-compile-directory
+            emacs-header-parse
 
             as-display
             emacs-substitute-sexps
@@ -114,6 +115,14 @@ (define* (emacs-byte-compile-directory dir)
                 (byte-recompile-directory (file-name-as-directory ,dir) 0 1))))
     (emacs-batch-eval expr)))
 
+(define (emacs-header-parse section file)
+  "Parse the header SECTION in FILE and return it as a string."
+  (emacs-batch-script
+   `(progn
+     (require 'lisp-mnt)
+     (find-file ,file)
+     (princ (lm-header ,section)))))
+
 (define as-display         ;syntactic keyword for 'emacs-substitute-sexps'
   '(as display))
 
diff --git a/tests/build-emacs-utils.scm b/tests/build-emacs-utils.scm
index 27cff46c38..081032285a 100644
--- a/tests/build-emacs-utils.scm
+++ b/tests/build-emacs-utils.scm
@@ -28,7 +28,7 @@ (define-module (test build-emacs-utils)
 
 (test-begin "build-emacs-utils")
 ;; Only run the following tests if emacs is present.
-(test-skip (if (which "emacs") 0 2))
+(test-skip (if (which "emacs") 0 5))
 
 (test-equal "emacs-batch-script: print foo from emacs"
   "foo"
@@ -40,4 +40,29 @@ (define-module (test build-emacs-utils)
                               "Lisp error: (wrong-type-argument numberp \"three\")")))
     (emacs-batch-script '(mapcar 'number-to-string (list 1 2 "three")))))
 
+(call-with-temporary-directory
+ (lambda (directory)
+   (let ((mock-elisp-file (string-append directory "/foo.el")))
+     (call-with-output-file mock-elisp-file
+       (lambda (port)
+         (display ";;; foo --- mock emacs package -*- lexical-binding: t -*-
+
+;; Created: 4 Jun 2022
+;; Keywords: lisp test
+;; Version: 1.0.0
+;;; Commentary:
+;;; Code:
+;;; foo.el ends here
+"
+                  port)))
+     (test-equal "emacs-header-parse: fetch version"
+       "1.0.0"
+       (emacs-header-parse "version" mock-elisp-file))
+     (test-equal "emacs-header-parse: fetch keywords"
+       "lisp test"
+       (emacs-header-parse "keywords" mock-elisp-file))
+     (test-equal "emacs-header-parse: fetch nonexistent author"
+       "nil"
+       (emacs-header-parse "author" mock-elisp-file)))))
+
 (test-end "build-emacs-utils")
-- 
2.36.1





Information forwarded to guix-patches <at> gnu.org:
bug#55420; Package guix-patches. (Sun, 05 Jun 2022 20:03:01 GMT) Full text and rfc822 format available.

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

From: Fredrik Salomonsson <plattfot <at> posteo.net>
To: Maxime Devos <maximedevos <at> telenet.be>, 55420 <at> debbugs.gnu.org
Subject: Re: [bug#55420] [PATCH v2 1/2] guix: emacs-utils: Add
 emacs-batch-script.
Date: Sun, 05 Jun 2022 20:02:42 +0000
Hi Maxime,

Maxime Devos <maximedevos <at> telenet.be> writes:

> Fredrik Salomonsson schreef op zo 05-06-2022 om 00:19 [+0000]:
>> +(test-equal "print foo from emacs"
>> +  "foo"
>> +  (emacs-batch-script '(princ "foo")))
>
> IIUC, this can only be run if emacs is in $PATH when running the tests,
> so sometimes the test needs to be skipped.  As an example on how to do
> this, see the "pypi->guix-package, wheels" test in tests/pypi.scm.

Yes, you are correct. All my tests started to fail when I added `--pure`
to my test command.

I just sent in a v3 of the patches when I skip the tests if emacs is not
in the PATH.

I also changed the tests for the `emacs-header-parse` to be wrapped by
`call-with-temporary-directory`. It felt wasteful to create and destroy that
file for each test when the file is static.

I opted to just have one test-skip and skip all five of them. Although
that migth be too fragile. Would be great to have something like:

    (unless (which "emacs")
      (test-skip "emacs-batch-script:")
      (test-skip "emacs-header-parse:"))

But the docs just mention a counter or the full name of a test.

-- 
s/Fred[re]+i[ck]+/Fredrik/g




Reply sent to Ludovic Courtès <ludo <at> gnu.org>:
You have taken responsibility. (Fri, 17 Jun 2022 20:30:01 GMT) Full text and rfc822 format available.

Notification sent to Fredrik Salomonsson <plattfot <at> posteo.net>:
bug acknowledged by developer. (Fri, 17 Jun 2022 20:30:02 GMT) Full text and rfc822 format available.

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

From: Ludovic Courtès <ludo <at> gnu.org>
To: Fredrik Salomonsson <plattfot <at> posteo.net>
Cc: 55420-done <at> debbugs.gnu.org
Subject: Re: bug#55420: [PATCH 0/2] Add a function to parse emacs elisp's
 package header
Date: Fri, 17 Jun 2022 22:29:13 +0200
Hi Fredrik,

Fredrik Salomonsson <plattfot <at> posteo.net> skribis:

> * guix/build/emacs-utils.scm (emacs-batch-script): New procedure.
>
> * tests/build-emacs-utils.scm: New file.
>
> * Makefile.am (TESTS): Add `tests/build-emacs-utils.scm'.

[...]

> * guix/build/emacs-utils.scm (emacs-header-parse): New procedure.
>
> * tests/build-emacs-utils.scm ("emacs-header-parse: fetch version",
>   "emacs-header-parse: fetch keywords", "emacs-header-parse: fetch
>   nonexistent author"): New tests.

Thanks, applied.  Apologies for the delay!

Ludo’.




bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Sat, 16 Jul 2022 11:24:05 GMT) Full text and rfc822 format available.

This bug report was last modified 1 year and 299 days ago.

Previous Next


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