Skip to content

Commit f26379b

Browse files
committed
Add some font-locking documentation
1 parent 2744f63 commit f26379b

File tree

1 file changed

+59
-0
lines changed

1 file changed

+59
-0
lines changed

README.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ specific `clojure-mode` release.**
3030
- [Indentation of function forms](#indentation-of-function-forms)
3131
- [Indentation of macro forms](#indentation-of-macro-forms)
3232
- [Vertical alignment](#vertical-alignment)
33+
- [Font-locking](#font-locking)
3334
- [Refactoring support](#refactoring-support)
3435
- [Threading macros](#threading-macros-related-features)
3536
- [Cycling things](#cycling-things)
@@ -258,6 +259,64 @@ This can also be done automatically (as part of indentation) by
258259
turning on `clojure-align-forms-automatically`. This way it will
259260
happen whenever you select some code and hit `TAB`.
260261

262+
### Font-locking
263+
264+
`clojure-mode` features static font-locking (syntax highlighting) that you can extend yourself
265+
if needed. As typical for Emacs, it's based on regular expressions. You can find
266+
the default font-locking rules in `clojure-font-lock-keywords`. Here's how you can add font-locking for built-in Clojure functions and vars:
267+
268+
``` el
269+
(defvar clojure-built-in-vars
270+
'(;; clojure.core
271+
"accessor" "aclone"
272+
"agent" "agent-errors" "aget" "alength" "alias"
273+
"all-ns" "alter" "alter-meta!" "alter-var-root" "amap"
274+
;; omitted for brevity
275+
))
276+
277+
(defvar clojure-built-in-dynamic-vars
278+
'(;; clojure.test
279+
"*initial-report-counters*" "*load-tests*" "*report-counters*"
280+
"*stack-trace-depth*" "*test-out*" "*testing-contexts*" "*testing-vars*"
281+
;; clojure.xml
282+
"*current*" "*sb*" "*stack*" "*state*"
283+
))
284+
285+
(font-lock-add-keywords 'clojure-mode
286+
`((,(concat "(\\(?:\.*/\\)?"
287+
(regexp-opt clojure-built-in-vars t)
288+
"\\>")
289+
1 font-lock-builtin-face)))
290+
291+
(font-lock-add-keywords 'clojure-mode
292+
`((,(concat "\\<"
293+
(regexp-opt clojure-built-in-dynamic-vars t)
294+
"\\>")
295+
0 font-lock-builtin-face)))
296+
297+
```
298+
299+
**Note:** The package `clojure-mode-extra-font-locking` provides such additional
300+
font-locking for Clojure built-ins.
301+
302+
As you might imagine one problem with this font-locking approach is that because
303+
it's based on regular expressions you'll get some false positives here and there
304+
(there's no namespace information, and no way for `clojure-mode` to know what
305+
var a symbol resolves to). That's why `clojure-mode`'s font-locking defaults are
306+
conservative and minimalistic.
307+
308+
Precise font-locking requires additional data that can obtained from a running
309+
REPL (that's how CIDER's [dynamic font-locking](https://docs.cider.mx/cider/config/syntax_highlighting.html) works) or from static code analysis.
310+
311+
When it comes to definitions, `clojure-mode` employs a simple heuristic and will treat every symbol named `def`something as a built-in keyword. Still, you'll need to
312+
teach `clojure-mode` manually how to handle the docstrings of non built-in definition forms. Here's an example:
313+
314+
``` emacs-lisp
315+
(put '>defn 'clojure-doc-string-elt 2)
316+
```
317+
318+
**Note:** The `clojure-doc-string-elt` attribute is processed by the function `clojure-font-lock-syntactic-face-function`.
319+
261320
## Refactoring support
262321

263322
The available refactorings were originally created and maintained by the

0 commit comments

Comments
 (0)