quotes or as part of a string.
Normally, the output is split line-by-line, returning a list (or the
-first element if there's only one line of output). However, when this
-expansion is surrounded by double quotes, it returns the output as a
-single string instead.
+first element if there's only one line of output); if
+@code{eshell-convert-numeric-arguments} is non-@code{nil} and every
+line of output looks like a number, convert each line to a number.
+However, when this expansion is surrounded by double quotes, it
+returns the output as a single string instead.
@item $<@var{command}>
As with @samp{$@{@var{command}@}}, evaluates the Eshell command invocation
result will always be a single string, no matter the type that would
otherwise be returned.
++++
+*** Eshell subcommands with multiline numeric output return lists of numbers.
+If every line of the output of an Eshell subcommand like '${COMMAND}'
+is numeric, the result will be a list of numbers (or a single number
+if only one line of output). Previously, this only converted numbers
+when there was a single line of output.
+
---
*** Built-in Eshell commands now follow POSIX/GNU argument syntax conventions.
Built-in commands in Eshell now accept command-line options with
(when (= depth 0)
(if reverse-p (point) (1- (point)))))))
+(defun eshell-convertible-to-number-p (string)
+ "Return non-nil if STRING can be converted to a number.
+If `eshell-convert-numeric-aguments', always return nil."
+ (and eshell-convert-numeric-arguments
+ (string-match
+ (concat "\\`\\s-*" eshell-number-regexp "\\s-*\\'")
+ string)))
+
+(defun eshell-convert-to-number (string)
+ "Try to convert STRING to a number.
+If STRING doesn't look like a number (or
+`eshell-convert-numeric-aguments' is nil), just return STRING
+unchanged."
+ (if (eshell-convertible-to-number-p string)
+ (string-to-number string)
+ string))
+
(defun eshell-convert (string &optional to-string)
"Convert STRING into a more-native Lisp object.
If TO-STRING is non-nil, always return a single string with
* Split multiline strings by line.
-* If `eshell-convert-numeric-aguments' is non-nil, convert
- numeric strings to numbers."
+* If `eshell-convert-numeric-aguments' is non-nil and every line
+ of output looks like a number, convert them to numbers."
(cond
((not (stringp string))
(if to-string
string
(when (eq (aref string (1- len)) ?\n)
(setq string (substring string 0 (1- len))))
- (cond
- ((string-search "\n" string)
- (split-string string "\n"))
- ((and eshell-convert-numeric-arguments
- (string-match
- (concat "\\`\\s-*" eshell-number-regexp "\\s-*\\'")
- string))
- (string-to-number string))
- (t string)))))))
+ (if (string-search "\n" string)
+ (let ((lines (split-string string "\n")))
+ (if (seq-every-p #'eshell-convertible-to-number-p lines)
+ (mapcar #'string-to-number lines)
+ lines))
+ (eshell-convert-to-number string)))))))
(defvar-local eshell-path-env (getenv "PATH")
"Content of $PATH.
(ert-deftest esh-var-test/interp-convert-cmd-multiline ()
"Interpolate multi-line command result"
(should (equal (eshell-test-command-result "echo ${echo \"foo\nbar\"}")
- '("foo" "bar"))))
+ '("foo" "bar")))
+ ;; Numeric output should be converted to numbers...
+ (should (equal (eshell-test-command-result "echo ${echo \"01\n02\n03\"}")
+ '(1 2 3)))
+ ;; ... but only if every line is numeric.
+ (should (equal (eshell-test-command-result "echo ${echo \"01\n02\nhi\"}")
+ '("01" "02" "hi"))))
(ert-deftest esh-var-test/interp-convert-cmd-number ()
"Interpolate numeric command result"