aboutsummaryrefslogtreecommitdiffstats
path: root/test/lisp/eshell
diff options
context:
space:
mode:
authorJim Porter2024-10-19 11:52:42 -0700
committerJim Porter2024-10-19 12:01:10 -0700
commit43d5b7a04c4b1a8a7d57f25824df2e8720d2c567 (patch)
tree189201134e9e92c6bbf156ebb772f573f65cf71f /test/lisp/eshell
parentc2a9f519f7e9a5cbb5dbe50ba7b4e4b2757bb3b6 (diff)
downloademacs-43d5b7a04c4b1a8a7d57f25824df2e8720d2c567.tar.gz
emacs-43d5b7a04c4b1a8a7d57f25824df2e8720d2c567.zip
Lazily convert numeric strings to Lisp numbers in Eshell
This should reduce the number of issues with Eshell converting strings to numbers too aggressively and losing information (e.g. "001" -> 1) while still allowing almost all of the beneficial uses, like summing a list of numeric strings with '+'. * lisp/eshell/esh-util.el (eshell--do-mark-numeric-string): New function. (eshell-convert-to-number): Make obsolete in favor of... (eshell-mark-numeric-string): ... this. Update callers. * lisp/eshell/esh-arg.el (eshell--numberlike-p): New function... (eshell-concat-1): ... use it. * test/lisp/eshell/esh-util-tests.el: Reimplement type conversion tests to use 'eshell-convertible-to-number-p' instead. * test/lisp/eshell/esh-var-tests.el (esh-var-test/interp-var-splice-concat, esh-var-test/interp-concat-cmd) (esh-var-test/interp-convert-var-split-indices) (esh-var-test/interp-convert-quoted-var-split-indices) (esh-var-test/interp-convert-cmd-multiline) (esh-var-test/interp-convert-cmd-split-indices): Adjust tests to check the new behavior. * doc/misc/eshell.texi (Type Conversion): New section. (Expansion): Clarify concatenation behavior.
Diffstat (limited to 'test/lisp/eshell')
-rw-r--r--test/lisp/eshell/esh-util-tests.el114
-rw-r--r--test/lisp/eshell/esh-var-tests.el29
2 files changed, 83 insertions, 60 deletions
diff --git a/test/lisp/eshell/esh-util-tests.el b/test/lisp/eshell/esh-util-tests.el
index 031de558d1f..4a0874bff39 100644
--- a/test/lisp/eshell/esh-util-tests.el
+++ b/test/lisp/eshell/esh-util-tests.el
@@ -66,70 +66,70 @@
66 "Test that `eshell-stringify' correctly stringifies complex objects." 66 "Test that `eshell-stringify' correctly stringifies complex objects."
67 (should (equal (eshell-stringify (list 'quote 'hello)) "'hello"))) 67 (should (equal (eshell-stringify (list 'quote 'hello)) "'hello")))
68 68
69(ert-deftest esh-util-test/eshell-convert-to-number/integer () 69(ert-deftest esh-util-test/eshell-convertible-to-number-p/integer ()
70 "Test that `eshell-convert-to-number' correctly converts integers." 70 "Test that `eshell-convertible-to-number-p' matches integers."
71 (should (equal (eshell-convert-to-number "123") 123)) 71 (should (eshell-convertible-to-number-p "123"))
72 (should (equal (eshell-convert-to-number "-123") -123)) 72 (should (eshell-convertible-to-number-p "-123"))
73 ;; These are technially integers, since Emacs Lisp requires at least 73 ;; These are technially integers, since Emacs Lisp requires at least
74 ;; one digit after the "." to be a float: 74 ;; one digit after the "." to be a float:
75 (should (equal (eshell-convert-to-number "123.") 123)) 75 (should (eshell-convertible-to-number-p "123."))
76 (should (equal (eshell-convert-to-number "-123.") -123))) 76 (should (eshell-convertible-to-number-p "-123.")))
77 77
78(ert-deftest esh-util-test/eshell-convert-to-number/floating-point () 78(ert-deftest esh-util-test/eshell-convertible-to-number-p/float ()
79 "Test that `eshell-convert-to-number' correctly converts floats." 79 "Test that `eshell-convertible-to-number-p' matches floats."
80 (should (equal (eshell-convert-to-number "1.23") 1.23)) 80 (should (eshell-convertible-to-number-p "1.23"))
81 (should (equal (eshell-convert-to-number "-1.23") -1.23)) 81 (should (eshell-convertible-to-number-p "-1.23"))
82 (should (equal (eshell-convert-to-number ".1") 0.1)) 82 (should (eshell-convertible-to-number-p ".1"))
83 (should (equal (eshell-convert-to-number "-.1") -0.1))) 83 (should (eshell-convertible-to-number-p "-.1")))
84 84
85(ert-deftest esh-util-test/eshell-convert-to-number/floating-point-exponent () 85(ert-deftest esh-util-test/eshell-convertible-to-number-p/float-exponent ()
86 "Test that `eshell-convert-to-number' correctly converts exponent notation." 86 "Test that `eshell-convertible-to-number-p' matches exponent notation."
87 ;; Positive exponent: 87 ;; Positive exponent:
88 (dolist (exp '("e2" "e+2" "E2" "E+2")) 88 (dolist (exp '("e2" "e+2" "E2" "E+2"))
89 (should (equal (eshell-convert-to-number (concat "123" exp)) 12300.0)) 89 (should (eshell-convertible-to-number-p (concat "123" exp)))
90 (should (equal (eshell-convert-to-number (concat "-123" exp)) -12300.0)) 90 (should (eshell-convertible-to-number-p (concat "-123" exp)))
91 (should (equal (eshell-convert-to-number (concat "1.23" exp)) 123.0)) 91 (should (eshell-convertible-to-number-p (concat "1.23" exp)))
92 (should (equal (eshell-convert-to-number (concat "-1.23" exp)) -123.0)) 92 (should (eshell-convertible-to-number-p (concat "-1.23" exp)))
93 (should (equal (eshell-convert-to-number (concat "1." exp)) 100.0)) 93 (should (eshell-convertible-to-number-p (concat "1." exp)))
94 (should (equal (eshell-convert-to-number (concat "-1." exp)) -100.0)) 94 (should (eshell-convertible-to-number-p (concat "-1." exp)))
95 (should (equal (eshell-convert-to-number (concat ".1" exp)) 10.0)) 95 (should (eshell-convertible-to-number-p (concat ".1" exp)))
96 (should (equal (eshell-convert-to-number (concat "-.1" exp)) -10.0))) 96 (should (eshell-convertible-to-number-p (concat "-.1" exp))))
97 ;; Negative exponent: 97 ;; Negative exponent:
98 (dolist (exp '("e-2" "E-2")) 98 (dolist (exp '("e-2" "E-2"))
99 (should (equal (eshell-convert-to-number (concat "123" exp)) 1.23)) 99 (should (eshell-convertible-to-number-p (concat "123" exp)))
100 (should (equal (eshell-convert-to-number (concat "-123" exp)) -1.23)) 100 (should (eshell-convertible-to-number-p (concat "-123" exp)))
101 (should (equal (eshell-convert-to-number (concat "1.23" exp)) 0.0123)) 101 (should (eshell-convertible-to-number-p (concat "1.23" exp)))
102 (should (equal (eshell-convert-to-number (concat "-1.23" exp)) -0.0123)) 102 (should (eshell-convertible-to-number-p (concat "-1.23" exp)))
103 (should (equal (eshell-convert-to-number (concat "1." exp)) 0.01)) 103 (should (eshell-convertible-to-number-p (concat "1." exp)))
104 (should (equal (eshell-convert-to-number (concat "-1." exp)) -0.01)) 104 (should (eshell-convertible-to-number-p (concat "-1." exp)))
105 (should (equal (eshell-convert-to-number (concat ".1" exp)) 0.001)) 105 (should (eshell-convertible-to-number-p (concat ".1" exp)))
106 (should (equal (eshell-convert-to-number (concat "-.1" exp)) -0.001)))) 106 (should (eshell-convertible-to-number-p (concat "-.1" exp)))))
107 107
108(ert-deftest esh-util-test/eshell-convert-to-number/floating-point/infinite () 108(ert-deftest esh-util-test/eshell-convertible-to-number-p/float/infinite ()
109 "Test that `eshell-convert-to-number' correctly converts infinite floats." 109 "Test that `eshell-convertible-to-number-p' matches infinite floats."
110 (should (equal (eshell-convert-to-number "1.0e+INF") 1.0e+INF)) 110 (should (eshell-convertible-to-number-p "1.0e+INF"))
111 (should (equal (eshell-convert-to-number "2.e+INF") 1.0e+INF)) 111 (should (eshell-convertible-to-number-p "2.e+INF"))
112 (should (equal (eshell-convert-to-number "-1.0e+INF") -1.0e+INF)) 112 (should (eshell-convertible-to-number-p "-1.0e+INF"))
113 (should (equal (eshell-convert-to-number "-2.e+INF") -1.0e+INF))) 113 (should (eshell-convertible-to-number-p "-2.e+INF")))
114 114
115(ert-deftest esh-util-test/eshell-convert-to-number/floating-point/nan () 115(ert-deftest esh-util-test/eshell-convertible-to-number-p/float/nan ()
116 "Test that `eshell-convert-to-number' correctly converts NaNs." 116 "Test that `eshell-convertible-to-number-p' matches NaNs."
117 (should (equal (eshell-convert-to-number "1.0e+NaN") 1.0e+NaN)) 117 (should (eshell-convertible-to-number-p "1.0e+NaN"))
118 (should (equal (eshell-convert-to-number "2.e+NaN") 2.0e+NaN)) 118 (should (eshell-convertible-to-number-p "2.e+NaN"))
119 (should (equal (eshell-convert-to-number "-1.0e+NaN") -1.0e+NaN)) 119 (should (eshell-convertible-to-number-p "-1.0e+NaN"))
120 (should (equal (eshell-convert-to-number "-2.e+NaN") -2.0e+NaN))) 120 (should (eshell-convertible-to-number-p "-2.e+NaN")))
121 121
122(ert-deftest esh-util-test/eshell-convert-to-number/non-numeric () 122(ert-deftest esh-util-test/eshell-convertible-to-number-p/non-numeric ()
123 "Test that `eshell-convert-to-number' does nothing to non-numeric values." 123 "Test that `eshell-convertible-to-number-p' returns nil for non-numerics."
124 (should (equal (eshell-convert-to-number "foo") "foo")) 124 (should-not (eshell-convertible-to-number-p "foo"))
125 (should (equal (eshell-convert-to-number "") "")) 125 (should-not (eshell-convertible-to-number-p ""))
126 (should (equal (eshell-convert-to-number "123foo") "123foo"))) 126 (should-not (eshell-convertible-to-number-p "123foo")))
127 127
128(ert-deftest esh-util-test/eshell-convert-to-number/no-convert () 128(ert-deftest esh-util-test/eshell-convertible-to-number-p/no-convert ()
129 "Test that `eshell-convert-to-number' does nothing when disabled." 129 "Test that `eshell-convertible-to-number-p' returns nil when disabled."
130 (let ((eshell-convert-numeric-arguments nil)) 130 (let ((eshell-convert-numeric-arguments nil))
131 (should (equal (eshell-convert-to-number "123") "123")) 131 (should-not (eshell-convertible-to-number-p "123"))
132 (should (equal (eshell-convert-to-number "1.23") "1.23")))) 132 (should-not (eshell-convertible-to-number-p "1.23"))))
133 133
134(ert-deftest esh-util-test/eshell-printable-size () 134(ert-deftest esh-util-test/eshell-printable-size ()
135 (should (equal (eshell-printable-size (expt 2 16)) "65536")) 135 (should (equal (eshell-printable-size (expt 2 16)) "65536"))
diff --git a/test/lisp/eshell/esh-var-tests.el b/test/lisp/eshell/esh-var-tests.el
index 7ac9807a1a7..70f6e9c7777 100644
--- a/test/lisp/eshell/esh-var-tests.el
+++ b/test/lisp/eshell/esh-var-tests.el
@@ -231,7 +231,7 @@ nil, use FUNCTION instead."
231 ;; into the first value of the non-spliced list. 231 ;; into the first value of the non-spliced list.
232 (eshell-command-result-equal 232 (eshell-command-result-equal
233 "echo it is $@'eshell-test-value'$eshell-test-value" 233 "echo it is $@'eshell-test-value'$eshell-test-value"
234 '("it" "is" 1 2 (31 2 3))))) 234 '("it" "is" 1 2 ("31" 2 3)))))
235 235
236(ert-deftest esh-var-test/interp-lisp () 236(ert-deftest esh-var-test/interp-lisp ()
237 "Interpolate Lisp form evaluation." 237 "Interpolate Lisp form evaluation."
@@ -280,12 +280,16 @@ nil, use FUNCTION instead."
280 (eshell-command-result-equal "+ ${+ 1 2}3 3" 36) 280 (eshell-command-result-equal "+ ${+ 1 2}3 3" 36)
281 (eshell-command-result-equal "echo ${*echo \"foo\nbar\"}-baz" 281 (eshell-command-result-equal "echo ${*echo \"foo\nbar\"}-baz"
282 '("foo" "bar-baz")) 282 '("foo" "bar-baz"))
283 ;; Concatenating to a number in a list should produce a number... 283 ;; Concatenating to a number in a list should produce a numeric value...
284 (eshell-command-result-equal "echo ${*echo \"1\n2\"}3" 284 (eshell-command-result-equal "echo ${*echo \"1\n2\"}3"
285 '("1" "23"))
286 (eshell-command-result-equal "echo $@{*echo \"1\n2\"}3"
285 '(1 23)) 287 '(1 23))
286 ;; ... but concatenating to a string that looks like a number in a list 288 ;; ... but concatenating to a string that looks like a number in a list
287 ;; should produce a string. 289 ;; should produce a string.
288 (eshell-command-result-equal "echo ${*echo \"hi\n2\"}3" 290 (eshell-command-result-equal "echo ${*echo \"hi\n2\"}3"
291 '("hi" "23"))
292 (eshell-command-result-equal "echo $@{*echo \"hi\n2\"}3"
289 '("hi" "23"))) 293 '("hi" "23")))
290 294
291(ert-deftest esh-var-test/interp-concat-cmd2 () 295(ert-deftest esh-var-test/interp-concat-cmd2 ()
@@ -491,11 +495,16 @@ nil, use FUNCTION instead."
491 495
492(ert-deftest esh-var-test/interp-convert-var-split-indices () 496(ert-deftest esh-var-test/interp-convert-var-split-indices ()
493 "Interpolate and convert string variable with indices." 497 "Interpolate and convert string variable with indices."
494 ;; Check that numeric forms are converted to numbers. 498 ;; Check that numeric forms are marked as numeric.
495 (let ((eshell-test-value "000 010 020 030 040")) 499 (let ((eshell-test-value "000 010 020 030 040"))
500 ;; `eshell/echo' converts numeric strings to Lisp numbers...
496 (eshell-command-result-equal "echo $eshell-test-value[0]" 501 (eshell-command-result-equal "echo $eshell-test-value[0]"
497 0) 502 0)
503 ;; ... but not lists of numeric strings...
498 (eshell-command-result-equal "echo $eshell-test-value[0 2]" 504 (eshell-command-result-equal "echo $eshell-test-value[0 2]"
505 '("000" "020"))
506 ;; ... unless each element is a separate argument to `eshell/echo'.
507 (eshell-command-result-equal "echo $@eshell-test-value[0 2]"
499 '(0 20))) 508 '(0 20)))
500 ;; Check that multiline forms are preserved as-is. 509 ;; Check that multiline forms are preserved as-is.
501 (let ((eshell-test-value "foo\nbar:baz\n")) 510 (let ((eshell-test-value "foo\nbar:baz\n"))
@@ -515,9 +524,14 @@ nil, use FUNCTION instead."
515(ert-deftest esh-var-test/interp-convert-quoted-var-split-indices () 524(ert-deftest esh-var-test/interp-convert-quoted-var-split-indices ()
516 "Interpolate and convert quoted string variable with indices." 525 "Interpolate and convert quoted string variable with indices."
517 (let ((eshell-test-value "000 010 020 030 040")) 526 (let ((eshell-test-value "000 010 020 030 040"))
527 ;; `eshell/echo' converts numeric strings to Lisp numbers...
518 (eshell-command-result-equal "echo $'eshell-test-value'[0]" 528 (eshell-command-result-equal "echo $'eshell-test-value'[0]"
519 0) 529 0)
530 ;; ... but not lists of numeric strings...
520 (eshell-command-result-equal "echo $'eshell-test-value'[0 2]" 531 (eshell-command-result-equal "echo $'eshell-test-value'[0 2]"
532 '("000" "020"))
533 ;; ... unless each element is a separate argument to `eshell/echo'.
534 (eshell-command-result-equal "echo $@'eshell-test-value'[0 2]"
521 '(0 20)))) 535 '(0 20))))
522 536
523(ert-deftest esh-var-test/interp-convert-cmd-string-newline () 537(ert-deftest esh-var-test/interp-convert-cmd-string-newline ()
@@ -530,9 +544,13 @@ nil, use FUNCTION instead."
530 '("foo" "bar")) 544 '("foo" "bar"))
531 ;; Numeric output should be converted to numbers... 545 ;; Numeric output should be converted to numbers...
532 (eshell-command-result-equal "echo ${echo \"01\n02\n03\"}" 546 (eshell-command-result-equal "echo ${echo \"01\n02\n03\"}"
547 '("01" "02" "03"))
548 (eshell-command-result-equal "echo $@{echo \"01\n02\n03\"}"
533 '(1 2 3)) 549 '(1 2 3))
534 ;; ... but only if every line is numeric. 550 ;; ... but only if every line is numeric.
535 (eshell-command-result-equal "echo ${echo \"01\n02\nhi\"}" 551 (eshell-command-result-equal "echo ${echo \"01\n02\nhi\"}"
552 '("01" "02" "hi"))
553 (eshell-command-result-equal "echo $@{echo \"01\n02\nhi\"}"
536 '("01" "02" "hi"))) 554 '("01" "02" "hi")))
537 555
538(ert-deftest esh-var-test/interp-convert-cmd-number () 556(ert-deftest esh-var-test/interp-convert-cmd-number ()
@@ -541,9 +559,14 @@ nil, use FUNCTION instead."
541 559
542(ert-deftest esh-var-test/interp-convert-cmd-split-indices () 560(ert-deftest esh-var-test/interp-convert-cmd-split-indices ()
543 "Interpolate command result with indices." 561 "Interpolate command result with indices."
562 ;; `eshell/echo' converts numeric strings to Lisp numbers...
544 (eshell-command-result-equal "echo ${echo \"000 010 020\"}[0]" 563 (eshell-command-result-equal "echo ${echo \"000 010 020\"}[0]"
545 0) 564 0)
565 ;; ... but not lists of numeric strings...
546 (eshell-command-result-equal "echo ${echo \"000 010 020\"}[0 2]" 566 (eshell-command-result-equal "echo ${echo \"000 010 020\"}[0 2]"
567 '("000" "020"))
568 ;; ... unless each element is a separate argument to `eshell/echo'.
569 (eshell-command-result-equal "echo $@{echo \"000 010 020\"}[0 2]"
547 '(0 20))) 570 '(0 20)))
548 571
549(ert-deftest esh-var-test/quoted-interp-convert-var-number () 572(ert-deftest esh-var-test/quoted-interp-convert-var-number ()