unofficial mirror of guix-patches@gnu.org 
 help / color / mirror / code / Atom feed
* [bug#55420] [PATCH 0/2] Add a function to parse emacs elisp's package header
@ 2022-05-14 23:00 Fredrik Salomonsson
  2022-05-14 23:05 ` [bug#55420] [PATCH 1/2] guix: emacs-utils: Add emacs-batch-script Fredrik Salomonsson
                   ` (2 more replies)
  0 siblings, 3 replies; 15+ messages in thread
From: Fredrik Salomonsson @ 2022-05-14 23:00 UTC (permalink / raw)
  To: 55420; +Cc: Fredrik Salomonsson

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





^ permalink raw reply	[flat|nested] 15+ messages in thread

* [bug#55420] [PATCH 1/2] guix: emacs-utils: Add emacs-batch-script.
  2022-05-14 23:00 [bug#55420] [PATCH 0/2] Add a function to parse emacs elisp's package header Fredrik Salomonsson
@ 2022-05-14 23:05 ` Fredrik Salomonsson
  2022-05-14 23:05   ` [bug#55420] [PATCH 2/2] guix: emacs-utils: Add emacs-header-parse Fredrik Salomonsson
  2022-06-01 20:38   ` Ludovic Courtès
  2022-06-05  0:19 ` [bug#55420] [PATCH v2 1/2] guix: emacs-utils: Add emacs-batch-script Fredrik Salomonsson
  2022-06-05 19:51 ` [bug#55420] [PATCH v3 " Fredrik Salomonsson
  2 siblings, 2 replies; 15+ messages in thread
From: Fredrik Salomonsson @ 2022-05-14 23:05 UTC (permalink / raw)
  To: 55420; +Cc: Fredrik Salomonsson

* 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@gmail.com>
 ;;; Copyright © 2018, 2020, 2022 Maxim Cournoyer <maxim.cournoyer@gmail.com>
 ;;; Copyright © 2019 Liliana Marie Prikler <liliana.prikler@gmail.com>
+;;; Copyright © 2022 Fredrik Salomonsson <plattfot@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





^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [bug#55420] [PATCH 2/2] guix: emacs-utils: Add emacs-header-parse.
  2022-05-14 23:05 ` [bug#55420] [PATCH 1/2] guix: emacs-utils: Add emacs-batch-script Fredrik Salomonsson
@ 2022-05-14 23:05   ` Fredrik Salomonsson
  2022-06-01 20:39     ` [bug#55420] [PATCH 0/2] Add a function to parse emacs elisp's package header Ludovic Courtès
  2022-06-01 20:38   ` Ludovic Courtès
  1 sibling, 1 reply; 15+ messages in thread
From: Fredrik Salomonsson @ 2022-05-14 23:05 UTC (permalink / raw)
  To: 55420; +Cc: Fredrik Salomonsson

* 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





^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [bug#55420] [PATCH 0/2] Add a function to parse emacs elisp's package header
  2022-05-14 23:05 ` [bug#55420] [PATCH 1/2] guix: emacs-utils: Add emacs-batch-script Fredrik Salomonsson
  2022-05-14 23:05   ` [bug#55420] [PATCH 2/2] guix: emacs-utils: Add emacs-header-parse Fredrik Salomonsson
@ 2022-06-01 20:38   ` Ludovic Courtès
  2022-06-02  2:53     ` Fredrik Salomonsson
  1 sibling, 1 reply; 15+ messages in thread
From: Ludovic Courtès @ 2022-06-01 20:38 UTC (permalink / raw)
  To: Fredrik Salomonsson; +Cc: 55420

Hi Fredrik,

The patches LGTM modulo cosmetic issues:

Fredrik Salomonsson <plattfot@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’.
     




^ permalink raw reply	[flat|nested] 15+ messages in thread

* [bug#55420] [PATCH 0/2] Add a function to parse emacs elisp's package header
  2022-05-14 23:05   ` [bug#55420] [PATCH 2/2] guix: emacs-utils: Add emacs-header-parse Fredrik Salomonsson
@ 2022-06-01 20:39     ` Ludovic Courtès
  0 siblings, 0 replies; 15+ messages in thread
From: Ludovic Courtès @ 2022-06-01 20:39 UTC (permalink / raw)
  To: Fredrik Salomonsson; +Cc: 55420

Fredrik Salomonsson <plattfot@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’.




^ permalink raw reply	[flat|nested] 15+ messages in thread

* [bug#55420] [PATCH 0/2] Add a function to parse emacs elisp's package header
  2022-06-01 20:38   ` Ludovic Courtès
@ 2022-06-02  2:53     ` Fredrik Salomonsson
  2022-06-02 13:44       ` Ludovic Courtès
  0 siblings, 1 reply; 15+ messages in thread
From: Fredrik Salomonsson @ 2022-06-02  2:53 UTC (permalink / raw)
  To: Ludovic Courtès; +Cc: 55420

Hi Ludo,

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

> Hi Fredrik,
>
> The patches LGTM modulo cosmetic issues:
>
> Fredrik Salomonsson <plattfot@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




^ permalink raw reply	[flat|nested] 15+ messages in thread

* [bug#55420] [PATCH 0/2] Add a function to parse emacs elisp's package header
  2022-06-02  2:53     ` Fredrik Salomonsson
@ 2022-06-02 13:44       ` Ludovic Courtès
  2022-06-05  0:42         ` Fredrik Salomonsson
  0 siblings, 1 reply; 15+ messages in thread
From: Ludovic Courtès @ 2022-06-02 13:44 UTC (permalink / raw)
  To: Fredrik Salomonsson; +Cc: 55420

Hi,

Fredrik Salomonsson <plattfot@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’.




^ permalink raw reply	[flat|nested] 15+ messages in thread

* [bug#55420] [PATCH v2 1/2] guix: emacs-utils: Add emacs-batch-script.
  2022-05-14 23:00 [bug#55420] [PATCH 0/2] Add a function to parse emacs elisp's package header Fredrik Salomonsson
  2022-05-14 23:05 ` [bug#55420] [PATCH 1/2] guix: emacs-utils: Add emacs-batch-script Fredrik Salomonsson
@ 2022-06-05  0:19 ` Fredrik Salomonsson
  2022-06-05  0:19   ` [bug#55420] [PATCH v2 2/2] guix: emacs-utils: Add emacs-header-parse Fredrik Salomonsson
  2022-06-05  9:52   ` [bug#55420] [PATCH v2 1/2] guix: emacs-utils: Add emacs-batch-script Maxime Devos
  2022-06-05 19:51 ` [bug#55420] [PATCH v3 " Fredrik Salomonsson
  2 siblings, 2 replies; 15+ messages in thread
From: Fredrik Salomonsson @ 2022-06-05  0:19 UTC (permalink / raw)
  To: 55420; +Cc: Fredrik Salomonsson

* 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@gmail.com>
 ;;; Copyright © 2018, 2020, 2022 Maxim Cournoyer <maxim.cournoyer@gmail.com>
 ;;; Copyright © 2019 Liliana Marie Prikler <liliana.prikler@gmail.com>
+;;; Copyright © 2022 Fredrik Salomonsson <plattfot@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@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





^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [bug#55420] [PATCH v2 2/2] guix: emacs-utils: Add emacs-header-parse.
  2022-06-05  0:19 ` [bug#55420] [PATCH v2 1/2] guix: emacs-utils: Add emacs-batch-script Fredrik Salomonsson
@ 2022-06-05  0:19   ` Fredrik Salomonsson
  2022-06-05  9:52   ` [bug#55420] [PATCH v2 1/2] guix: emacs-utils: Add emacs-batch-script Maxime Devos
  1 sibling, 0 replies; 15+ messages in thread
From: Fredrik Salomonsson @ 2022-06-05  0:19 UTC (permalink / raw)
  To: 55420; +Cc: Fredrik Salomonsson

* 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





^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [bug#55420] [PATCH 0/2] Add a function to parse emacs elisp's package header
  2022-06-02 13:44       ` Ludovic Courtès
@ 2022-06-05  0:42         ` Fredrik Salomonsson
  0 siblings, 0 replies; 15+ messages in thread
From: Fredrik Salomonsson @ 2022-06-05  0:42 UTC (permalink / raw)
  To: Ludovic Courtès; +Cc: 55420


Hi Ludo,

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

> Hi,
>
> Fredrik Salomonsson <plattfot@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




^ permalink raw reply	[flat|nested] 15+ messages in thread

* [bug#55420] [PATCH v2 1/2] guix: emacs-utils: Add emacs-batch-script.
  2022-06-05  0:19 ` [bug#55420] [PATCH v2 1/2] guix: emacs-utils: Add emacs-batch-script Fredrik Salomonsson
  2022-06-05  0:19   ` [bug#55420] [PATCH v2 2/2] guix: emacs-utils: Add emacs-header-parse Fredrik Salomonsson
@ 2022-06-05  9:52   ` Maxime Devos
  2022-06-05 20:02     ` Fredrik Salomonsson
  1 sibling, 1 reply; 15+ messages in thread
From: Maxime Devos @ 2022-06-05  9:52 UTC (permalink / raw)
  To: Fredrik Salomonsson, 55420

[-- Attachment #1: Type: text/plain, Size: 398 bytes --]

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.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 260 bytes --]

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [bug#55420] [PATCH v3 1/2] guix: emacs-utils: Add emacs-batch-script.
  2022-05-14 23:00 [bug#55420] [PATCH 0/2] Add a function to parse emacs elisp's package header Fredrik Salomonsson
  2022-05-14 23:05 ` [bug#55420] [PATCH 1/2] guix: emacs-utils: Add emacs-batch-script Fredrik Salomonsson
  2022-06-05  0:19 ` [bug#55420] [PATCH v2 1/2] guix: emacs-utils: Add emacs-batch-script Fredrik Salomonsson
@ 2022-06-05 19:51 ` Fredrik Salomonsson
  2022-06-05 19:51   ` [bug#55420] [PATCH v3 2/2] guix: emacs-utils: Add emacs-header-parse Fredrik Salomonsson
  2022-06-17 20:29   ` bug#55420: [PATCH 0/2] Add a function to parse emacs elisp's package header Ludovic Courtès
  2 siblings, 2 replies; 15+ messages in thread
From: Fredrik Salomonsson @ 2022-06-05 19:51 UTC (permalink / raw)
  To: 55420; +Cc: Fredrik Salomonsson

* 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@gmail.com>
 ;;; Copyright © 2018, 2020, 2022 Maxim Cournoyer <maxim.cournoyer@gmail.com>
 ;;; Copyright © 2019 Liliana Marie Prikler <liliana.prikler@gmail.com>
+;;; Copyright © 2022 Fredrik Salomonsson <plattfot@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@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





^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [bug#55420] [PATCH v3 2/2] guix: emacs-utils: Add emacs-header-parse.
  2022-06-05 19:51 ` [bug#55420] [PATCH v3 " Fredrik Salomonsson
@ 2022-06-05 19:51   ` Fredrik Salomonsson
  2022-06-17 20:29   ` bug#55420: [PATCH 0/2] Add a function to parse emacs elisp's package header Ludovic Courtès
  1 sibling, 0 replies; 15+ messages in thread
From: Fredrik Salomonsson @ 2022-06-05 19:51 UTC (permalink / raw)
  To: 55420; +Cc: Fredrik Salomonsson

* 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





^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [bug#55420] [PATCH v2 1/2] guix: emacs-utils: Add emacs-batch-script.
  2022-06-05  9:52   ` [bug#55420] [PATCH v2 1/2] guix: emacs-utils: Add emacs-batch-script Maxime Devos
@ 2022-06-05 20:02     ` Fredrik Salomonsson
  0 siblings, 0 replies; 15+ messages in thread
From: Fredrik Salomonsson @ 2022-06-05 20:02 UTC (permalink / raw)
  To: Maxime Devos, 55420

Hi Maxime,

Maxime Devos <maximedevos@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




^ permalink raw reply	[flat|nested] 15+ messages in thread

* bug#55420: [PATCH 0/2] Add a function to parse emacs elisp's package header
  2022-06-05 19:51 ` [bug#55420] [PATCH v3 " Fredrik Salomonsson
  2022-06-05 19:51   ` [bug#55420] [PATCH v3 2/2] guix: emacs-utils: Add emacs-header-parse Fredrik Salomonsson
@ 2022-06-17 20:29   ` Ludovic Courtès
  1 sibling, 0 replies; 15+ messages in thread
From: Ludovic Courtès @ 2022-06-17 20:29 UTC (permalink / raw)
  To: Fredrik Salomonsson; +Cc: 55420-done

Hi Fredrik,

Fredrik Salomonsson <plattfot@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’.




^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2022-06-17 20:30 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-14 23:00 [bug#55420] [PATCH 0/2] Add a function to parse emacs elisp's package header Fredrik Salomonsson
2022-05-14 23:05 ` [bug#55420] [PATCH 1/2] guix: emacs-utils: Add emacs-batch-script Fredrik Salomonsson
2022-05-14 23:05   ` [bug#55420] [PATCH 2/2] guix: emacs-utils: Add emacs-header-parse Fredrik Salomonsson
2022-06-01 20:39     ` [bug#55420] [PATCH 0/2] Add a function to parse emacs elisp's package header Ludovic Courtès
2022-06-01 20:38   ` Ludovic Courtès
2022-06-02  2:53     ` Fredrik Salomonsson
2022-06-02 13:44       ` Ludovic Courtès
2022-06-05  0:42         ` Fredrik Salomonsson
2022-06-05  0:19 ` [bug#55420] [PATCH v2 1/2] guix: emacs-utils: Add emacs-batch-script Fredrik Salomonsson
2022-06-05  0:19   ` [bug#55420] [PATCH v2 2/2] guix: emacs-utils: Add emacs-header-parse Fredrik Salomonsson
2022-06-05  9:52   ` [bug#55420] [PATCH v2 1/2] guix: emacs-utils: Add emacs-batch-script Maxime Devos
2022-06-05 20:02     ` Fredrik Salomonsson
2022-06-05 19:51 ` [bug#55420] [PATCH v3 " Fredrik Salomonsson
2022-06-05 19:51   ` [bug#55420] [PATCH v3 2/2] guix: emacs-utils: Add emacs-header-parse Fredrik Salomonsson
2022-06-17 20:29   ` bug#55420: [PATCH 0/2] Add a function to parse emacs elisp's package header Ludovic Courtès

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/guix.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).