diff --git a/CHANGELOG.md b/CHANGELOG.md index 24cb6fcf..e538b946 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ ### Bugs fixed +* [#365](https://github.com/clojure-emacs/clojure-mode/issues/365): Font-lock function names in `letfn` bindings with `font-lock-function-name-face`. * Fix typos in `clojure-mode-extra-font-locking`: `halt-when?` -> `halt-when`, `simple-indent?` -> `simple-ident?`. * Fix `doc` and `find-doc` misplaced under `clojure.core` instead of `clojure.repl` in extra font-locking. diff --git a/clojure-mode.el b/clojure-mode.el index 27347286..58ee2a1d 100644 --- a/clojure-mode.el +++ b/clojure-mode.el @@ -911,6 +911,27 @@ any number of matches of `clojure--sym-forbidden-rest-chars'.") Matches the rule `clojure--keyword-sym-forbidden-1st-chars' followed by any number of matches of `clojure--sym-forbidden-rest-chars'.")) +(defun clojure--search-letfn-name (limit) + "Search for function names in letfn bindings up to LIMIT. +This is a font-lock MATCHER function that finds each binding name +in a `letfn' binding vector." + (let ((binding-re (concat "(\\(" clojure--sym-regexp "\\)")) + found) + (while (and (not found) + (re-search-forward binding-re limit t)) + (save-match-data + (let ((paren-pos (match-beginning 0))) + (save-excursion + (goto-char paren-pos) + (when (ignore-errors (backward-up-list) t) + (when (eq (char-after) ?\[) + (skip-chars-backward " \t\n\r") + (when (looking-back + "(\\(?:clojure\\.core/\\)?letfn" + (- (point) 25)) + (setq found t)))))))) + found)) + (defconst clojure-font-lock-keywords (eval-when-compile `(;; Any def form @@ -993,6 +1014,9 @@ any number of matches of `clojure--sym-forbidden-rest-chars'.")) ;; Possibly name "\\(\\sw+\\)?" ) (2 font-lock-function-name-face nil t)) + ;; Function names in letfn bindings + (clojure--search-letfn-name + (1 font-lock-function-name-face)) ;; Special forms (,(concat "(" diff --git a/test/clojure-mode-font-lock-test.el b/test/clojure-mode-font-lock-test.el index b7eab44a..93132828 100644 --- a/test/clojure-mode-font-lock-test.el +++ b/test/clojure-mode-font-lock-test.el @@ -1041,7 +1041,19 @@ DESCRIPTION is the description of the spec." (9 13 font-lock-variable-name-face)) ("*some-var?*" - (1 11 font-lock-variable-name-face)))) + (1 11 font-lock-variable-name-face))) + + (when-fontifying-it "should handle letfn binding names" + ("(letfn [(twice [x] (* x 2))])" + (2 6 font-lock-keyword-face) + (10 14 font-lock-function-name-face)) + + ("(letfn [(twice [x] (* x 2)) (six-times [y] (* (twice y) 3))])" + (10 14 font-lock-function-name-face) + (30 38 font-lock-function-name-face)) + + ("(clojure.core/letfn [(twice [x] (* x 2))])" + (23 27 font-lock-function-name-face)))) (provide 'clojure-mode-font-lock-test)