branch: elpa/clojure-mode
commit 876ef22dec877469695c5a262a81f59e4a1fdc33
Merge: d76f97cd66 93d8d15293
Author: Bozhidar Batsov <[email protected]>
Commit: GitHub <[email protected]>

    Merge pull request #696 from clojure-emacs/font-lock-letfn-names
    
    Font-lock function names in letfn bindings
---
 CHANGELOG.md                        |  1 +
 clojure-mode.el                     | 28 ++++++++++++++++++++++++++++
 test/clojure-mode-font-lock-test.el | 14 +++++++++++++-
 3 files changed, 42 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index d182b2b4ac..fcf83c31f0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -20,6 +20,7 @@
 * [#402](https://github.com/clojure-emacs/clojure-mode/issues/402): Font-lock 
protocol method docstrings with `font-lock-doc-face`.
 * [#649](https://github.com/clojure-emacs/clojure-mode/issues/649): Fix 
`clojure-add-arity` severing arglist metadata (`^String`, `^:keyword`, 
`^{...}`) when converting single-arity to multi-arity.
 * [#600](https://github.com/clojure-emacs/clojure-mode/issues/600): Fix 
`clojure--valid-put-clojure-indent-call-p` rejecting valid indent specs with 
nested lists (e.g. `letfn`'s `(1 ((:defn)) nil)`).
+* [#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 2e9adafc24..b04cb770b0 100644
--- a/clojure-mode.el
+++ b/clojure-mode.el
@@ -911,6 +911,31 @@ 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.  For each `(symbol' match, it checks
+whether the paren is a direct child of 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' is critical: the verification below uses
+      ;; `looking-back' which would overwrite the match data from
+      ;; `re-search-forward' that font-lock needs for the highlight.
+      (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 +1018,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 3b4eb1aa29..1f05aa3e0d 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))))
 
 (describe "docstring font-locking"
   (it "should font-lock defn docstrings"

Reply via email to