Subject: bug#76103: [PATCH] New function 'process-output'

From: Álvaro Ramírez <[email-masked]>
Date: Thu, 06 Feb 2025 19:06:25 +0000

Hi folks,

I find process-lines super convenient for glueing command line 
utilities.

Often wished I had a similar function that neither split into 
lines (process-lines) nor relied on shell 
(shell-command-to-string).

Proposing process-output as a close cousin to process-lines.

Happy to drop process-lines in favour of an existing function I 
may have missed.

Álvaro

In GNU Emacs 31.0.50 (build 1, aarch64-apple-darwin24.0.0, NS
 appkit-2566.00 Version 15.0.1 (Build 24A348)) of 2025-02-06 built 
 on
 MacBookPro
Repository revision: e333985b36e6efd06eb288256d82e0eaeb4d2bb4
Repository branch: master
Windowing system distributor 'Apple', version 10.3.2566
System Description:  macOS 15.0.1

Configured using:
 'configure --with-ns
 --prefix=/Users/alvaro/stuff/active/code/third_party/emacs/nextstep/Emacs.app/Contents/MacOS
 --enable-locallisppath=/Users/alvaro/stuff/active/code/third_party/emacs/nextstep/Emacs.app/Contents/MacOS'

>From 23a1937079922f4e19b5a2b47343d429b93e7f5e Mon Sep 17 00:00:00 2001
From: Álvaro Ramírez <[email-masked]>
Date: Thu, 6 Feb 2025 18:53:15 +0000
Subject: [PATCH] New function 'process-output'

* lisp/subr.el (process-output):
New convenience process function. Works like process-lines but
returns process output as string.

* test/lisp/subr-tests.el
(subr-test-process-output): New test.

* etc/NEWS: Announce the new feature.
---
 etc/NEWS                |  4 ++++
 lisp/subr.el            | 11 +++++++++++
 test/lisp/subr-tests.el |  4 ++++
 3 files changed, 19 insertions(+)

diff --git a/etc/NEWS b/etc/NEWS
index ade635aa924..eb1d23bd5a6 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1354,6 +1354,10 @@ provide instructions for finding the definition.
 New convenience function 'find-function-update-type-alist' offers a
 concise way to update a symbol's 'find-function-type-alist' property.
 
+---
+** New function 'process-output'
+Like existing 'process-lines' function, but returns output as a string.
+
 
 * Changes in Emacs 31.1 on Non-Free Operating Systems
 
diff --git a/lisp/subr.el b/lisp/subr.el
index 12f4ec38b78..4c859365af1 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -3241,6 +3241,17 @@ process-lines
   (declare (important-return-value t))
   (apply #'process-lines-handling-status program nil args))
 
+(defun process-output (program &rest args)
+  "Execute PROGRAM with ARGS, returning its output as a string.
+Signal an error if the program returns with a non-zero exit status.
+Also see `process-lines'."
+  (declare (important-return-value t))
+  (with-temp-buffer
+    (let ((status (apply #'call-process program nil (current-buffer) nil args)))
+      (unless (eq status 0)
+	(error "%s exited with status %s" program status))
+      (buffer-string))))
+
 (defun process-lines-ignore-status (program &rest args)
   "Execute PROGRAM with ARGS, returning its output as a list of lines.
 The exit status of the program is ignored.
diff --git a/test/lisp/subr-tests.el b/test/lisp/subr-tests.el
index 5b17c598efa..a4db8389a12 100644
--- a/test/lisp/subr-tests.el
+++ b/test/lisp/subr-tests.el
@@ -343,7 +343,10 @@ subr-test-global-key-binding
   (should (eq (global-key-binding "x") 'self-insert-command))
   (should-not (global-key-binding [f12])))
 
+(ert-deftest subr-test-process-output ()
+  (should (equal (process-output "echo" "Hello world") "Hello world\n"))
+  (should-error (process-output "__echo" "Hello world") :type 'error))
+
 
 ;;;; Mode hooks.
 
--
2.39.5 (Apple Git-154)