Fork me on GitHub
Lucas Barbosa02:12:10

Anybody had issues with font lock on big clojure files before? My emacs is hanging when I open a 6k lines cljs file (an edn i18n dictionary). I profiled it and looks like font-lock is the culprit :thinking_face:

āœ‹ 4

Lucas, I recently introduced the following into my config for large files, whilst it won't address the initial loading issue, it may help for general navigation with any large file (not just Clojure code)

(use-package fast-scroll
  :ensure t
  (add-hook 'fast-scroll-start (lambda () (flycheck-mode -1)))
  (add-hook 'fast-scroll-end   (lambda () (flycheck-mode 1)))
  (fast-scroll-mode 1))

Lucas Barbosa14:12:36

I'll give it a try! Thanks


I think is a general emacs issue unfortunately


You can see it happen with any large file and font-lock, or if the file is large enough emacs just grinds to a halt


but I also would be interested in a solution


waiting for tree sitter support šŸ™‚


turning off the highlighting at least allows one to get things done, iirc


Yep. The current font-locking engine is based on regular expressions, which results in pretty poor performance in certain cases.


Iā€™m pretty sure we can improve the existing regular expressions, but I never found the time to profile and tweak them.

Lucas Barbosa11:12:43

Yeah, if I open the file literally, it is very fast @royalaid

Lucas Barbosa12:12:59

Well, it actually opens the file and I am able to navigate (slowly, but doable)

Lucas Barbosa12:12:22

But it hangs for a while when I ask it to open the file :thinking_face: not a deal breaker, definitely


I noticed major slowdowns too when the file is basically a single huge sexp, in the case of edn data


made a lightweight edn-mode based on text-mode to get around this - not sure if that would be something generally useful to people?

(defvar edn-font-lock-keywords
  `((,(rx (group (repeat 1 2 ":"))
          (group (+ (or (syntax word) (syntax symbol))))
          (group "/")
          (group (+ (or (syntax word) (syntax symbol)))))
     (1 'clojure-keyword-face)
     (2 font-lock-type-face)
     (3 'default)
     (4 'clojure-keyword-face))
    (,(rx (group (repeat 1 2 ":"))
          (group (+ (or (syntax word) (syntax symbol)))))
     (1 'clojure-keyword-face)
     (2 'clojure-keyword-face))))

(define-derived-mode edn-mode text-mode "EDN"
  "Major mode for editing Extensible Data Notation files"
  (set-syntax-table clojure-mode-syntax-table)
  (setq-local tab-width 2)
  (setq-local comment-start ";")
  (setq-local comment-start-skip ";+ *")
  (setq-local comment-add 1)
  (setq-local font-lock-defaults '(edn-font-lock-keywords nil)))

(add-hook 'edn-mode-hook 'rainbow-delimiters-mode)

(with-eval-after-load 'clojure-mode
  (add-to-list 'auto-mode-alist '("\\.edn\\'" . edn-mode))
  (add-to-list 'auto-mode-alist '("deps.edn\\'" . clojure-mode))
  (add-to-list 'auto-mode-alist '("shadow-cljs.edn\\'" . clojure-mode))
  (add-to-list 'auto-mode-alist '("config.edn" . clojure-mode)))


the last part is basically a whitelist of edn config files like "deps.edn" where you still want prog-mode commands like structural editing


i use the joe editor for huge edn :)


still cumbersome, but can at least search without terrible responsiveness


What is the emacs command for indenting the contents of a string like:

(deftest redefine-var-test
  (eval* "(def ^:redef x 10)
        (defn foo [] x)
     (def x 11)
   (println (foo))


I found indent-relative works, but not for multiple lines at once


i select the region and use indent-region


that doesn't work for a string


ah, just the string part...


no idea -- though you could indent the string when it's a form first and then paste?


may be narrow-to-region first?


that also doesn't work very well


i guess ending the line with the eval on it at the double quote and then starting the form on the next line is not to your taste?


yeah, that works šŸ™‚