summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Porter <jporterbugs@gmail.com>2022-06-25 20:05:57 -0700
committerLars Ingebrigtsen <larsi@gnus.org>2022-06-26 16:51:21 +0200
commit598d7c5d1c10bfb161cb53aa76d480864414487c (patch)
tree42d650e0476b281145c650dbe095e8e651b60a18
parentb637d9c0750fde8810058a153d964b6c70e0f577 (diff)
downloademacs-598d7c5d1c10bfb161cb53aa76d480864414487c.tar.gz
emacs-598d7c5d1c10bfb161cb53aa76d480864414487c.tar.bz2
emacs-598d7c5d1c10bfb161cb53aa76d480864414487c.zip
Optionally signal an error if an Eshell predicate fails to match anything
* lisp/eshell/em-pred.el (eshell-error-if-no-glob): Declare it. (eshell-apply-modifiers): Add STRING-DESC argument and signal an error if there are no matches and 'eshell-error-if-no-glob' is set. (eshell-parse-arg-modifier): Pass modifier string to 'eshell-apply-modifiers'. * test/lisp/eshell/em-pred-tests.el (eshell-eval-predicate): Simplify. (em-pred-test/no-matches): New test. * doc/misc/eshell.texi (Bugs and ideas): Remove todo entry about this change.
-rw-r--r--doc/misc/eshell.texi5
-rw-r--r--lisp/eshell/em-pred.el18
-rw-r--r--test/lisp/eshell/em-pred-tests.el26
3 files changed, 35 insertions, 14 deletions
diff --git a/doc/misc/eshell.texi b/doc/misc/eshell.texi
index 85e5a4933fd..2e3ba4c273b 100644
--- a/doc/misc/eshell.texi
+++ b/doc/misc/eshell.texi
@@ -1902,11 +1902,6 @@ glob match.
At the moment, this is not supported.
-@item Error if a glob doesn't expand due to a predicate
-
-An error should be generated only if @code{eshell-error-if-no-glob} is
-non-@code{nil}.
-
@item @samp{(+ @key{RET} @key{SPC} @key{TAB}} does not cause @code{indent-according-to-mode} to occur
@item Create @code{eshell-auto-accumulate-list}
diff --git a/lisp/eshell/em-pred.el b/lisp/eshell/em-pred.el
index d73976d3464..b4ef154f8c3 100644
--- a/lisp/eshell/em-pred.el
+++ b/lisp/eshell/em-pred.el
@@ -233,6 +233,8 @@ Each element is of the form (OPEN . CLOSE), where OPEN and CLOSE
are characters representing the opening and closing delimiter,
respectively.")
+(defvar eshell-error-if-no-glob) ; Defined in em-glob.el.
+
(defvar-keymap eshell-pred-mode-map
"C-c M-q" #'eshell-display-predicate-help
"C-c M-m" #'eshell-display-modifier-help)
@@ -263,14 +265,19 @@ respectively.")
#'eshell-parse-arg-modifier t t)
(eshell-pred-mode))
-(defun eshell-apply-modifiers (lst predicates modifiers)
- "Apply to list LST a series of PREDICATES and MODIFIERS."
+(defun eshell-apply-modifiers (lst predicates modifiers string-desc)
+ "Apply to list LST a series of PREDICATES and MODIFIERS.
+STRING-DESC is the original string defining these predicates and
+modifiers."
(let (stringified)
(if (stringp lst)
(setq lst (list lst)
stringified t))
(when (listp lst)
- (setq lst (eshell-winnow-list lst nil predicates))
+ (when lst
+ (setq lst (or (eshell-winnow-list lst nil predicates)
+ (when eshell-error-if-no-glob
+ (error "No matches found: (%s)" string-desc)))))
(while modifiers
(setq lst (funcall (car modifiers) lst)
modifiers (cdr modifiers)))
@@ -290,7 +297,8 @@ This function is specially for adding onto `eshell-parse-argument-hook'."
(when (eshell-arg-delimiter (1+ end))
(save-restriction
(narrow-to-region (point) end)
- (let* ((modifiers (eshell-parse-modifiers))
+ (let* ((modifier-string (buffer-string))
+ (modifiers (eshell-parse-modifiers))
(preds (car modifiers))
(mods (cdr modifiers)))
(if (or preds mods)
@@ -302,7 +310,7 @@ This function is specially for adding onto `eshell-parse-argument-hook'."
(list
(lambda (lst)
(eshell-apply-modifiers
- lst preds mods))))))))
+ lst preds mods modifier-string))))))))
(goto-char (1+ end))
(eshell-finish-arg))))))
diff --git a/test/lisp/eshell/em-pred-tests.el b/test/lisp/eshell/em-pred-tests.el
index 3b50543d69a..c8c1a6a9317 100644
--- a/test/lisp/eshell/em-pred-tests.el
+++ b/test/lisp/eshell/em-pred-tests.el
@@ -26,6 +26,7 @@
(require 'ert)
(require 'esh-mode)
(require 'eshell)
+(require 'em-glob)
(require 'em-pred)
(require 'eshell-tests-helpers
@@ -39,10 +40,9 @@
"Evaluate PREDICATE on INITIAL-VALUE, returning the result.
PREDICATE is an Eshell argument predicate/modifier."
(let ((eshell-test-value initial-value))
- (with-temp-eshell
- (eshell-insert-command
- (format "setq eshell-test-value $eshell-test-value(%s)" predicate)))
- eshell-test-value))
+ (ignore-errors
+ (eshell-test-command-result
+ (format "echo $eshell-test-value(%s)" predicate)))))
(defun eshell-parse-file-name-attributes (file)
"Parse a fake FILE name to determine its attributes.
@@ -545,4 +545,22 @@ PREDICATE is the predicate used to query that attribute."
(should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":j'\\\"'")
"foo\\\"bar\\\"baz")))
+(ert-deftest em-pred-test/no-matches ()
+ "Test behavior when a predicate fails to match any files."
+ (eshell-with-file-attributes-from-name
+ (let ((files '("/fake/modes=0666" "/fake/type=d,modes=0777"
+ "/fake/type=l,modes=0777")))
+ (should (equal (eshell-eval-predicate files "*") nil))
+ (let ((eshell-error-if-no-glob t))
+ ;; Don't signal an error if the original list is empty.
+ (should (equal (eshell-eval-predicate nil "*") nil))
+ ;; Ensure this signals an error. This test case is a bit
+ ;; clumsy, since `eshell-do-eval' makes it hard to catch
+ ;; errors otherwise.
+ (let ((modifiers (with-temp-eshell
+ (eshell-with-temp-command "*"
+ (eshell-parse-modifiers)))))
+ (should-error (eshell-apply-modifiers files (car modifiers)
+ (cdr modifiers) "*")))))))
+
;; em-pred-tests.el ends here