From 924603d09aeb9e8af080c2ff3b1b88aea7225cfc Mon Sep 17 00:00:00 2001 From: Jim Porter Date: Thu, 26 Jan 2023 13:11:15 -0800 Subject: [PATCH 2/2] Make 'eshell-number-regexp' into a regular defvar This isn't a very useful thing to customize, since it needs to detect numbers that can successfully be parsed by 'string-to-number'. Changes to this variable would therefore likely requiring adjusting 'eshell-convert-to-number' as well. * lisp/eshell/esh-util.el (eshell-number-regexp): Make into a defvar and improve the regexp to support more numbers (including infinity and NaN). * test/lisp/eshell/esh-util-tests.el (esh-util-test/eshell-convert-to-number/floating-point) (esh-util-test/eshell-convert-to-number/floating-point-exponent) (esh-util-test/eshell-convert-to-number/non-numeric) (esh-util-test/eshell-convert-to-number/no-convert): New tests. --- lisp/eshell/esh-util.el | 20 +++++---- test/lisp/eshell/esh-util-tests.el | 65 ++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 7 deletions(-) diff --git a/lisp/eshell/esh-util.el b/lisp/eshell/esh-util.el index 8b522449762..9549e7f1a10 100644 --- a/lisp/eshell/esh-util.el +++ b/lisp/eshell/esh-util.el @@ -94,13 +94,6 @@ eshell-convert-numeric-arguments argument matches `eshell-number-regexp'." :type 'boolean) -(defcustom eshell-number-regexp "-?\\([0-9]*\\.\\)?[0-9]+\\(e[-0-9.]+\\)?" - "Regular expression used to match numeric arguments. -If `eshell-convert-numeric-arguments' is non-nil, and an argument -matches this regexp, it will be converted to a Lisp number, using the -function `string-to-number'." - :type 'regexp) - (defcustom eshell-ange-ls-uids nil "List of user/host/id strings, used to determine remote ownership." :type '(repeat (cons :tag "Host for User/UID map" @@ -111,6 +104,19 @@ eshell-ange-ls-uids ;;; Internal Variables: +(defvar eshell-number-regexp + (rx (? "-") + (or (seq (+ digit) (? "." (* digit))) + (seq (* digit) "." (+ digit))) + ;; Optional exponent + (? (or "e" "E") + (or "+INF" "+NaN" + (seq (? (or "+" "-")) (+ digit))))) + "Regular expression used to match numeric arguments. +If `eshell-convert-numeric-arguments' is non-nil, and an argument +matches this regexp, it will be converted to a Lisp number, using the +function `string-to-number'.") + (defvar eshell-integer-regexp (rx (? "-") (+ digit)) "Regular expression used to match integer arguments.") diff --git a/test/lisp/eshell/esh-util-tests.el b/test/lisp/eshell/esh-util-tests.el index afaf1b77f2b..ed841e96c7e 100644 --- a/test/lisp/eshell/esh-util-tests.el +++ b/test/lisp/eshell/esh-util-tests.el @@ -54,4 +54,69 @@ esh-util-test/eshell-stringify/complex "Test that `eshell-stringify' correctly stringifies complex objects." (should (equal (eshell-stringify (list 'quote 'hello)) "'hello"))) +(ert-deftest esh-util-test/eshell-convert-to-number/integer () + "Test that `eshell-convert-to-number' correctly converts integers." + (should (equal (eshell-convert-to-number "123") 123)) + (should (equal (eshell-convert-to-number "-123") -123)) + ;; These are technially integers, since Emacs Lisp requires at least + ;; one digit after the "." to be a float: + (should (equal (eshell-convert-to-number "123.") 123)) + (should (equal (eshell-convert-to-number "-123.") -123))) + +(ert-deftest esh-util-test/eshell-convert-to-number/floating-point () + "Test that `eshell-convert-to-number' correctly converts floats." + (should (equal (eshell-convert-to-number "1.23") 1.23)) + (should (equal (eshell-convert-to-number "-1.23") -1.23)) + (should (equal (eshell-convert-to-number ".1") 0.1)) + (should (equal (eshell-convert-to-number "-.1") -0.1))) + +(ert-deftest esh-util-test/eshell-convert-to-number/floating-point-exponent () + "Test that `eshell-convert-to-number' correctly converts exponent notation." + ;; Positive exponent: + (dolist (exp '("e2" "e+2" "E2" "E+2")) + (should (equal (eshell-convert-to-number (concat "123" exp)) 12300.0)) + (should (equal (eshell-convert-to-number (concat "-123" exp)) -12300.0)) + (should (equal (eshell-convert-to-number (concat "1.23" exp)) 123.0)) + (should (equal (eshell-convert-to-number (concat "-1.23" exp)) -123.0)) + (should (equal (eshell-convert-to-number (concat "1." exp)) 100.0)) + (should (equal (eshell-convert-to-number (concat "-1." exp)) -100.0)) + (should (equal (eshell-convert-to-number (concat ".1" exp)) 10.0)) + (should (equal (eshell-convert-to-number (concat "-.1" exp)) -10.0))) + ;; Negative exponent: + (dolist (exp '("e-2" "E-2")) + (should (equal (eshell-convert-to-number (concat "123" exp)) 1.23)) + (should (equal (eshell-convert-to-number (concat "-123" exp)) -1.23)) + (should (equal (eshell-convert-to-number (concat "1.23" exp)) 0.0123)) + (should (equal (eshell-convert-to-number (concat "-1.23" exp)) -0.0123)) + (should (equal (eshell-convert-to-number (concat "1." exp)) 0.01)) + (should (equal (eshell-convert-to-number (concat "-1." exp)) -0.01)) + (should (equal (eshell-convert-to-number (concat ".1" exp)) 0.001)) + (should (equal (eshell-convert-to-number (concat "-.1" exp)) -0.001)))) + +(ert-deftest esh-util-test/eshell-convert-to-number/floating-point/infinite () + "Test that `eshell-convert-to-number' correctly converts infinite floats." + (should (equal (eshell-convert-to-number "1.0e+INF") 1.0e+INF)) + (should (equal (eshell-convert-to-number "2.e+INF") 1.0e+INF)) + (should (equal (eshell-convert-to-number "-1.0e+INF") -1.0e+INF)) + (should (equal (eshell-convert-to-number "-2.e+INF") -1.0e+INF))) + +(ert-deftest esh-util-test/eshell-convert-to-number/floating-point/nan () + "Test that `eshell-convert-to-number' correctly converts NaNs." + (should (equal (eshell-convert-to-number "1.0e+NaN") 1.0e+NaN)) + (should (equal (eshell-convert-to-number "2.e+NaN") 2.0e+NaN)) + (should (equal (eshell-convert-to-number "-1.0e+NaN") -1.0e+NaN)) + (should (equal (eshell-convert-to-number "-2.e+NaN") -2.0e+NaN))) + +(ert-deftest esh-util-test/eshell-convert-to-number/non-numeric () + "Test that `eshell-convert-to-number' does nothing to non-numeric values." + (should (equal (eshell-convert-to-number "foo") "foo")) + (should (equal (eshell-convert-to-number "") "")) + (should (equal (eshell-convert-to-number "123foo") "123foo"))) + +(ert-deftest esh-util-test/eshell-convert-to-number/no-convert () + "Test that `eshell-convert-to-number' does nothing when disabled." + (let ((eshell-convert-numeric-arguments nil)) + (should (equal (eshell-convert-to-number "123") "123")) + (should (equal (eshell-convert-to-number "1.23") "1.23")))) + ;;; esh-util-tests.el ends here -- 2.25.1