Skip to content

Commit e898a94

Browse files
Malabarbabbatsov
authored andcommitted
[Fix #518] Ignore ns forms inside strings in clojure-find-ns (#519)
1 parent 4387cb8 commit e898a94

File tree

3 files changed

+52
-23
lines changed

3 files changed

+52
-23
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
* [#508](https://github.com/clojure-emacs/clojure-mode/issues/508): Fix font lock for namespaces with metadata
1010
* [#506](https://github.com/clojure-emacs/clojure-mode/issues/506): `clojure-mode-display-version` correctly displays the package's version
1111
* [#445](https://github.com/clojure-emacs/clojure-mode/issues/445), [#405](https://github.com/clojure-emacs/clojure-mode/issues/405), [#469](https://github.com/clojure-emacs/clojure-mode/issues/469): Correct font-lock on string definitions with docstrings, e.g: `(def foo "doc" "value")`. Correct indentation as well.
12+
* [#518](https://github.com/clojure-emacs/clojure-mode/issues/518): Fix clojure-find-ns when there's an `ns` form inside a string
1213

1314
## 5.10.0 (2019-01-05)
1415

clojure-mode.el

+19-6
Original file line numberDiff line numberDiff line change
@@ -1886,6 +1886,19 @@ the cached value will be updated automatically."
18861886
(defvar-local clojure-cached-ns nil
18871887
"A buffer ns cache used to speed up ns-related operations.")
18881888

1889+
(defun clojure--find-ns-in-direction (direction)
1890+
"Return the nearest namespace in a specific DIRECTION.
1891+
DIRECTION is `forward' or `backward'."
1892+
(let ((candidate)
1893+
(fn (if (eq direction 'forward)
1894+
#'search-forward-regexp
1895+
#'search-backward-regexp)))
1896+
(while (and (not candidate)
1897+
(funcall fn clojure-namespace-name-regex nil t))
1898+
(unless (or (clojure--in-string-p) (clojure--in-comment-p))
1899+
(setq candidate (match-string-no-properties 4))))
1900+
candidate))
1901+
18891902
(defun clojure-find-ns ()
18901903
"Return the namespace of the current Clojure buffer.
18911904
Return the namespace closest to point and above it. If there are
@@ -1901,12 +1914,8 @@ The results will be cached if `clojure-cache-ns' is set to t."
19011914
;; Move to top-level to avoid searching from inside ns
19021915
(ignore-errors (while t (up-list nil t t)))
19031916

1904-
;; The closest ns form above point.
1905-
(when (or (re-search-backward clojure-namespace-name-regex nil t)
1906-
;; Or any form at all.
1907-
(and (goto-char (point-min))
1908-
(re-search-forward clojure-namespace-name-regex nil t)))
1909-
(match-string-no-properties 4))))))
1917+
(or (clojure--find-ns-in-direction 'backward)
1918+
(clojure--find-ns-in-direction 'forward))))))
19101919
(setq clojure-cached-ns ns)
19111920
ns)))
19121921

@@ -2384,6 +2393,10 @@ See: https://github.com/clojure-emacs/clj-refactor.el/wiki/cljr-cycle-privacy"
23842393
"Check whether the point is currently in a string."
23852394
(nth 3 (syntax-ppss)))
23862395

2396+
(defun clojure--in-comment-p ()
2397+
"Check whether the point is currently in a comment."
2398+
(nth 4 (syntax-ppss)))
2399+
23872400
(defun clojure--goto-if ()
23882401
"Find the first surrounding if or if-not expression."
23892402
(when (clojure--in-string-p)

test/clojure-mode-sexp-test.el

+32-17
Original file line numberDiff line numberDiff line change
@@ -146,23 +146,38 @@ and point left there."
146146
;; we should not cache the results of `clojure-find-ns' here
147147
(let ((clojure-cache-ns nil))
148148
(with-temp-buffer
149-
(insert "(ns ^{:doc \"Some docs\"}\nfoo-bar)")
150-
(newline)
151-
(newline)
152-
(insert "(in-ns 'baz-quux)")
153-
(clojure-mode)
154-
155-
;; From inside docstring of first ns
156-
(goto-char 18)
157-
(should (equal "foo-bar" (clojure-find-ns)))
158-
159-
;; From inside first ns's name, on its own line
160-
(goto-char 29)
161-
(should (equal "foo-bar" (clojure-find-ns)))
162-
163-
;; From inside second ns's name
164-
(goto-char 42)
165-
(should (equal "baz-quux" (clojure-find-ns))))))
149+
(insert "(ns ^{:doc \"Some docs\"}\nfoo-bar)")
150+
(newline)
151+
(newline)
152+
(insert "(in-ns 'baz-quux)")
153+
(clojure-mode)
154+
155+
;; From inside docstring of first ns
156+
(goto-char 18)
157+
(should (equal "foo-bar" (clojure-find-ns)))
158+
159+
;; From inside first ns's name, on its own line
160+
(goto-char 29)
161+
(should (equal "foo-bar" (clojure-find-ns)))
162+
163+
;; From inside second ns's name
164+
(goto-char 42)
165+
(should (equal "baz-quux" (clojure-find-ns))))
166+
(let ((data
167+
'(("\"\n(ns foo-bar)\"\n" "(in-ns 'baz-quux)" "baz-quux")
168+
(";(ns foo-bar)\n" "(in-ns 'baz-quux)" "baz-quux")
169+
("(ns foo-bar)\n" "\"\n(in-ns 'baz-quux)\"" "foo-bar")
170+
("(ns foo-bar)\n" ";(in-ns 'baz-quux)" "foo-bar"))))
171+
(pcase-dolist (`(,form1 ,form2 ,expected) data)
172+
(with-temp-buffer
173+
(insert form1)
174+
(save-excursion (insert form2))
175+
(clojure-mode)
176+
;; Between the two namespaces
177+
(should (equal expected (clojure-find-ns)))
178+
;; After both namespaces
179+
(goto-char (point-max))
180+
(should (equal expected (clojure-find-ns))))))))
166181

167182
(provide 'clojure-mode-sexp-test)
168183

0 commit comments

Comments
 (0)