From eb45cc9521e25dc685bdfb4a6b7926c244fbf259 Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Fri, 26 Jul 2019 09:58:23 +0200 Subject: [PATCH] Add new macro `ignore-error' * doc/lispref/control.texi (Handling Errors): Document `ignore-error'. * lisp/subr.el (ignore-error): New macro. * lisp/progmodes/elisp-mode.el (elisp-completion-at-point): Provide completion for `ignore-error'. --- doc/lispref/control.texi | 12 ++++++++++++ etc/NEWS | 5 +++++ lisp/progmodes/elisp-mode.el | 26 +++++++++++++++++++++----- lisp/subr.el | 8 ++++++++ test/lisp/subr-tests.el | 10 ++++++++++ 5 files changed, 56 insertions(+), 5 deletions(-) diff --git a/doc/lispref/control.texi b/doc/lispref/control.texi index de6cd9301ff..e98daf66e98 100644 --- a/doc/lispref/control.texi +++ b/doc/lispref/control.texi @@ -2154,6 +2154,18 @@ Here's the example at the beginning of this subsection rewritten using @end example @end defmac +@defmac ignore-error condition body@dots{} +This macro is like @code{ignore-errors}, but will only ignore the +specific error condition specified. + +@example + (ignore-error end-of-file + (read "")) +@end example + +@var{condition} can also be a list of error conditions. +@end defmac + @defmac with-demoted-errors format body@dots{} This macro is like a milder version of @code{ignore-errors}. Rather than suppressing errors altogether, it converts them into messages. diff --git a/etc/NEWS b/etc/NEWS index 44a69213899..5673fc1b42d 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1937,6 +1937,11 @@ buffer-local. `permanent' also sets the variable's ** The new macro `with-suppressed-warnings' can be used to suppress specific byte-compile warnings. ++++ +** The new macro `ignore-error' is like `ignore-errors', but takes a +specific error condition, and will only ignore that condition. (This +can also be a list of conditions.) + --- ** The new function `byte-compile-info-message' can be used to output informational messages that look pleasing during the Emacs build. diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index da7a731ec22..1babb2f9094 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el @@ -500,16 +500,27 @@ functions are annotated with \"\" via the (scan-error pos)))) ;; t if in function position. (funpos (eq (char-before beg) ?\()) - (quoted (elisp--form-quoted-p beg))) + (quoted (elisp--form-quoted-p beg)) + (fun-sym (condition-case nil + (save-excursion + (up-list -1) + (forward-char 1) + (and (memq (char-syntax (char-after)) '(?w ?_)) + (read (current-buffer)))) + (error nil)))) + (message "sym: %s %s %s %s" fun-sym funpos beg end) (when (and end (or (not (nth 8 (syntax-ppss))) (memq (char-before beg) '(?` ?‘)))) (let ((table-etc (if (or (not funpos) quoted) - ;; FIXME: We could look at the first element of the list and - ;; use it to provide a more specific completion table in some - ;; cases. E.g. filter out keywords that are not understood by - ;; the macro/function being called. (cond + ;; FIXME: We could look at the first element of + ;; the current form and use it to provide a more + ;; specific completion table in more cases. + ((eq fun-sym 'ignore-error) + (list t obarray + :predicate (lambda (sym) + (get sym 'error-conditions)))) ((elisp--expect-function-p beg) (list nil obarray :predicate #'fboundp @@ -568,6 +579,11 @@ functions are annotated with \"\" via the (< (point) beg))))) (list t obarray :predicate (lambda (sym) (get sym 'error-conditions)))) + ;; `ignore-error' with a list CONDITION parameter. + ('ignore-error + (list t obarray + :predicate (lambda (sym) + (get sym 'error-conditions)))) ((and (or ?\( 'let 'let*) (guard (save-excursion (goto-char (1- beg)) diff --git a/lisp/subr.el b/lisp/subr.el index f1a4e8bb292..eea4e045dde 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -302,6 +302,14 @@ See also `with-demoted-errors' that does something similar without silencing all errors." (declare (debug t) (indent 0)) `(condition-case nil (progn ,@body) (error nil))) + +(defmacro ignore-error (condition &rest body) + "Execute BODY; if the error CONDITION occurs, return nil. +Otherwise, return result of last form in BODY. + +CONDITION can also be a list of error conditions." + (declare (debug t) (indent 1)) + `(condition-case nil (progn ,@body) (,condition nil))) ;;;; Basic Lisp functions. diff --git a/test/lisp/subr-tests.el b/test/lisp/subr-tests.el index 06db8f5c902..0023680738d 100644 --- a/test/lisp/subr-tests.el +++ b/test/lisp/subr-tests.el @@ -400,5 +400,15 @@ See https://debbugs.gnu.org/cgi/bugreport.cgi?bug=19350." (should (equal subr-tests--hook '(f5 f10 f9 f6 f2 f1 f4 f3 f7 f8))) ) +(ert-deftest ignore-error-tests () + (should (equal (ignore-error (end-of-file) + (read "")) + nil)) + (should (equal (ignore-error end-of-file + (read "")) + nil)) + (should-error (ignore-error foo + (read "")))) + (provide 'subr-tests) ;;; subr-tests.el ends here -- 2.39.2