clojure-emacs/clojure-mode

All top-level def forms should have consistent font-lock

j-cr opened this issue · 4 comments

j-cr commented

Some thoughts on syntax highlighting.

(def foo 42) ; font-lock-variable-name-face
(defn bar [x] x) ; font-lock-function-name-face

I think variable-name-face should be used for foo in (let [foo 42] ...), but not for foo in (def foo 42). Top-level definitions should use the same face, whether its a function or a 'variable'. It seems more logical, since if I want to make both "foo" and "bar" use the same bold and highly visible face (since both are top-level defs), then e.g. in my c code I get local variables and function arguments highlighted with the same face.

I guess the correct hierarchy would be: top-level-definition-face -> (function-face, var-face[1]). It would be nice to have a separate space for def-like keywords as well (so a user could highlight "defn", but not "do" or "let").

[1]: technically defn also creates a var; what's the best short name for a top-level definition that is not a function? Do we actually need/want this distinction at all? I don't really see how it's useful.

I've tried to align the font-locking in clojure-mode to that in lisp-mode and elisp-mode. Obviously there are some differences between a Lisp-1 and Lisp-2, but I think we won't gain much by changing the fock-locking for definitions. None of the existing Lisp modes for Emacs try to font-lock locals, so I didn't bother to so as well.

j-cr commented

I don't care that much about highlighting locals too. My main point's that logically all top-level definitions are kinda on the same level of "importance", so should be highlighted similarly, whether it's defined with a def or defn (or other def-like forms).

But setting font-lock-variable-name-face (currently used for (def x ...) definitions) to be the same as function-name face (i.e. bold and bright) also makes local variables in other languages bold and bright (local variables in other lang modes use the same face: font-lock-variable-name-face).

Anyways, feel free to close as you see fit, as it's not a feature request per se but more of "what's your thoughts on this" type ticket; or maybe leave open to gather more opinions.

For what it's worth, I do exactly this special highlighting of all def... forms on my local fork of clojure-mode, and I find it helps greatly with visual parsing of code.
image

This was done with a custom clojure-definition-face that is applied equally to all def.. forms, without distinguishing between def / deftype / defn.
I do realise it's not for everyone and doesn't align well with other Emacs modes as pointed out above, just posting since there's interest.

(defface clojure-definition-face
  `((t :height 1.4 :bold t
       :inherit highlight))
  "Face used to font-lock Clojure definitions")

The font lock keyword:

      ;; Definitions (any form that starts with def except for "default")
      (,(concat "(\\(?:" clojure--sym-regexp "/\\)?"
                (rx (group "def"
                           (? (or (: (not (any "a ")) (* (not (any " "))))
                                  (: "a"
                                   (? (or (: (not (any "u ")) (* (not (any " "))))
                                          (: "u"
                                           (? (or (: (not (any "l ")) (* (not (any " "))))
                                                  (: "l"
                                                   (? (: (not (any "t ")) (* (not (any " "))))))))))))))
                           word-end))
                clojure--whitespace-regexp
                clojure--type-or-metadata-regexp
                "\\(:*" clojure--sym-regexp "\\)?")
       (1 font-lock-keyword-face)
       (2 'clojure-definition-face nil t))
jpe90 commented

@yuhan0 Would it be possible to share your local fork? That special highlighting looks great, but it looks you're using definitions of clojure--whitespace-regexp and clojure--type-or-metadata-regexp that aren't shown if I understand correctly