From fd6c420b0cc553aac14696e3219b1d3ffaeaa3d1 Mon Sep 17 00:00:00 2001 From: vemv Date: Tue, 22 Aug 2023 18:00:16 +0200 Subject: [PATCH 1/3] `clojure-find-ns`: never raise errors --- CHANGELOG.md | 4 ++++ clojure-mode.el | 29 +++++++++++++++-------------- test/clojure-mode-sexp-test.el | 8 +++++++- 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9194d24c..6de9149c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## master (unreleased) +### Changes + +* `clojure-find-ns`: never raise errors, returning nil instead on unparseable ns forms. + ## 5.16.1 (2023-06-26) ### Changes diff --git a/clojure-mode.el b/clojure-mode.el index 67ae3f59..4b8c7f57 100644 --- a/clojure-mode.el +++ b/clojure-mode.el @@ -2127,20 +2127,21 @@ the cached value will be updated automatically." (defun clojure--find-ns-in-direction (direction) "Return the nearest namespace in a specific DIRECTION. DIRECTION is `forward' or `backward'." - (let ((candidate) - (fn (if (eq direction 'forward) - #'search-forward-regexp - #'search-backward-regexp))) - (while (and (not candidate) - (funcall fn clojure-namespace-regexp nil t)) - (let ((end (match-end 0))) - (save-excursion - (save-match-data - (goto-char end) - (clojure-forward-logical-sexp) - (unless (or (clojure--in-string-p) (clojure--in-comment-p)) - (setq candidate (string-remove-prefix "'" (thing-at-point 'symbol)))))))) - candidate)) + (ignore-errors + (let ((candidate) + (fn (if (eq direction 'forward) + #'search-forward-regexp + #'search-backward-regexp))) + (while (and (not candidate) + (funcall fn clojure-namespace-regexp nil t)) + (let ((end (match-end 0))) + (save-excursion + (save-match-data + (goto-char end) + (clojure-forward-logical-sexp) + (unless (or (clojure--in-string-p) (clojure--in-comment-p)) + (setq candidate (string-remove-prefix "'" (thing-at-point 'symbol)))))))) + candidate))) (defun clojure-find-ns () "Return the namespace of the current Clojure buffer. diff --git a/test/clojure-mode-sexp-test.el b/test/clojure-mode-sexp-test.el index f82552a0..cfd24cde 100644 --- a/test/clojure-mode-sexp-test.el +++ b/test/clojure-mode-sexp-test.el @@ -167,7 +167,13 @@ (expect (clojure-find-ns) :to-equal expected) ;; After both namespaces (goto-char (point-max)) - (expect (clojure-find-ns) :to-equal expected))))))) + (expect (clojure-find-ns) :to-equal expected)))))) + + (it "should return nil for an invalid ns form" + ;; we should not cache the results of `clojure-find-ns' here + (let ((clojure-cache-ns nil)) + (with-clojure-buffer "(ns )" + (expect (equal nil (clojure-find-ns))))))) (describe "clojure-sexp-starts-until-position" (it "should return starting points for forms after POINT until POSITION" From b89e37865407bfc1d890a45a897c1203300e27d3 Mon Sep 17 00:00:00 2001 From: vemv Date: Tue, 22 Aug 2023 23:01:13 +0200 Subject: [PATCH 2/3] Accept an argument instead --- CHANGELOG.md | 2 +- clojure-mode.el | 60 +++++++++++++++++++--------------- test/clojure-mode-sexp-test.el | 19 ++++++++--- 3 files changed, 48 insertions(+), 33 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6de9149c..b55893f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ ### Changes -* `clojure-find-ns`: never raise errors, returning nil instead on unparseable ns forms. +* `clojure-find-ns`: add an option to never raise errors, returning nil instead on unparseable ns forms. ## 5.16.1 (2023-06-26) diff --git a/clojure-mode.el b/clojure-mode.el index 4b8c7f57..93d5c3c0 100644 --- a/clojure-mode.el +++ b/clojure-mode.el @@ -2127,39 +2127,45 @@ the cached value will be updated automatically." (defun clojure--find-ns-in-direction (direction) "Return the nearest namespace in a specific DIRECTION. DIRECTION is `forward' or `backward'." - (ignore-errors - (let ((candidate) - (fn (if (eq direction 'forward) - #'search-forward-regexp - #'search-backward-regexp))) - (while (and (not candidate) - (funcall fn clojure-namespace-regexp nil t)) - (let ((end (match-end 0))) - (save-excursion - (save-match-data - (goto-char end) - (clojure-forward-logical-sexp) - (unless (or (clojure--in-string-p) (clojure--in-comment-p)) - (setq candidate (string-remove-prefix "'" (thing-at-point 'symbol)))))))) - candidate))) - -(defun clojure-find-ns () - "Return the namespace of the current Clojure buffer. + (let ((candidate) + (fn (if (eq direction 'forward) + #'search-forward-regexp + #'search-backward-regexp))) + (while (and (not candidate) + (funcall fn clojure-namespace-regexp nil t)) + (let ((end (match-end 0))) + (save-excursion + (save-match-data + (goto-char end) + (clojure-forward-logical-sexp) + (unless (or (clojure--in-string-p) (clojure--in-comment-p)) + (setq candidate (string-remove-prefix "'" (thing-at-point 'symbol)))))))) + candidate)) + +(defun clojure-find-ns (&optional favor-nil) + "Return the namespace of the current Clojure buffer, honor `FAVOR-NIL'. Return the namespace closest to point and above it. If there are no namespaces above point, return the first one in the buffer. +If `FAVOR-NIL' is t, errors during ns form parsing will be swallowed, +and nil will be returned instead of letting this function fail. + The results will be cached if `clojure-cache-ns' is set to t." (if (and clojure-cache-ns clojure-cached-ns) clojure-cached-ns - (let ((ns (save-excursion - (save-restriction - (widen) - - ;; Move to top-level to avoid searching from inside ns - (ignore-errors (while t (up-list nil t t))) - - (or (clojure--find-ns-in-direction 'backward) - (clojure--find-ns-in-direction 'forward)))))) + (let* ((f (lambda (direction) + (if favor-nil + (ignore-errors (clojure--find-ns-in-direction direction)) + (clojure--find-ns-in-direction direction)))) + (ns (save-excursion + (save-restriction + (widen) + + ;; Move to top-level to avoid searching from inside ns + (ignore-errors (while t (up-list nil t t))) + + (or (funcall f 'backward) + (funcall f 'forward)))))) (setq clojure-cached-ns ns) ns))) diff --git a/test/clojure-mode-sexp-test.el b/test/clojure-mode-sexp-test.el index cfd24cde..bb2c1808 100644 --- a/test/clojure-mode-sexp-test.el +++ b/test/clojure-mode-sexp-test.el @@ -169,11 +169,20 @@ (goto-char (point-max)) (expect (clojure-find-ns) :to-equal expected)))))) - (it "should return nil for an invalid ns form" - ;; we should not cache the results of `clojure-find-ns' here - (let ((clojure-cache-ns nil)) - (with-clojure-buffer "(ns )" - (expect (equal nil (clojure-find-ns))))))) + (describe "`favor-nil' argument" + (let ((clojure-cache-ns nil)) + (describe "given a faulty ns form" + (let ((ns-form "(ns )")) + (describe "when the argument is `t'" + (it "causes `clojure-find-ns' to return nil" + (with-clojure-buffer ns-form + (expect (equal nil (clojure-find-ns t)))))) + + (describe "when the argument is `nil'" + (it "causes `clojure-find-ns' to return raise an error" + (with-clojure-buffer ns-form + (expect (clojure-find-ns nil) + :to-throw 'error))))))))) (describe "clojure-sexp-starts-until-position" (it "should return starting points for forms after POINT until POSITION" From 0d79a6f8bfca22775e7d4df84cec437b0dd9776d Mon Sep 17 00:00:00 2001 From: vemv Date: Wed, 23 Aug 2023 12:27:24 +0200 Subject: [PATCH 3/3] Rename argument --- clojure-mode.el | 8 ++++---- test/clojure-mode-sexp-test.el | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/clojure-mode.el b/clojure-mode.el index 93d5c3c0..42552992 100644 --- a/clojure-mode.el +++ b/clojure-mode.el @@ -2142,19 +2142,19 @@ DIRECTION is `forward' or `backward'." (setq candidate (string-remove-prefix "'" (thing-at-point 'symbol)))))))) candidate)) -(defun clojure-find-ns (&optional favor-nil) - "Return the namespace of the current Clojure buffer, honor `FAVOR-NIL'. +(defun clojure-find-ns (&optional suppress-errors) + "Return the namespace of the current Clojure buffer, honor `SUPPRESS-ERRORS'. Return the namespace closest to point and above it. If there are no namespaces above point, return the first one in the buffer. -If `FAVOR-NIL' is t, errors during ns form parsing will be swallowed, +If `SUPPRESS-ERRORS' is t, errors during ns form parsing will be swallowed, and nil will be returned instead of letting this function fail. The results will be cached if `clojure-cache-ns' is set to t." (if (and clojure-cache-ns clojure-cached-ns) clojure-cached-ns (let* ((f (lambda (direction) - (if favor-nil + (if suppress-errors (ignore-errors (clojure--find-ns-in-direction direction)) (clojure--find-ns-in-direction direction)))) (ns (save-excursion diff --git a/test/clojure-mode-sexp-test.el b/test/clojure-mode-sexp-test.el index bb2c1808..edec5803 100644 --- a/test/clojure-mode-sexp-test.el +++ b/test/clojure-mode-sexp-test.el @@ -169,7 +169,7 @@ (goto-char (point-max)) (expect (clojure-find-ns) :to-equal expected)))))) - (describe "`favor-nil' argument" + (describe "`suppress-errors' argument" (let ((clojure-cache-ns nil)) (describe "given a faulty ns form" (let ((ns-form "(ns )"))