cider

2026-06-26T09:46:39.620329Z

I went down a bit of a rabbit hole wondering why I was getting incomplete font-locking (highlighting) when evaluating in the REPL something like (zipmap (range 100) (repeat :foo)). My LLM managed to fix it by overriding cider-repl-handler but surely that is not the correct way to do this. Details and reproduction in 🧵 .

2026-06-26T09:53:35.862799Z

Here's the LLM generated fix that causes everything to be highlighted correctly. Maybe it breaks other stuff, not sure. Definitely feels like there must be a better way given how long CIDER has been around and how many people have put such great work into it.

2026-06-26T09:53:38.687019Z

(defun kl/cider-repl-handler-fontify-complete-values (buffer)
    "Make a CIDER REPL handler that fontifies complete streamed values."
    (let ((show-prompt t)
          value-chunks)
      (cider-make-eval-handler
       :buffer buffer
       :on-value (lambda (value)
                   (push value value-chunks))
       :on-stdout (lambda (out)
                    (dolist (f cider--repl-stdout-functions)
                      (funcall f buffer out))
                    (cider-repl-emit-stdout buffer out))
       :on-stderr (lambda (err)
                    (dolist (f cider--repl-stderr-functions)
                      (funcall f buffer err))
                    (cider-repl-emit-stderr buffer err))
       :on-done (lambda ()
                  (when value-chunks
                    (cider-repl-emit-result
                     buffer
                     (apply #'concat (nreverse value-chunks))
                     t))
                  (when show-prompt
                    (cider-repl-emit-prompt buffer))
                  (when cider-repl-buffer-size-limit
                    (cider-repl-maybe-trim-buffer buffer))
                  (cider-repl--auto-inspect-last-result buffer)
                  (dolist (f cider--repl-done-functions)
                    (funcall f buffer)))
       :on-content-type (lambda (value content-type)
                          (if-let* ((content-type* (car content-type))
                                    (handler (cdr (assoc content-type*
                                                         cider-repl-content-type-handler-alist))))
                              (setq show-prompt (funcall handler content-type buffer value nil t))
                            (cider-repl-emit-result buffer value t t)))
       :on-truncated (lambda ()
                       (cider-repl-emit-stderr buffer nil)))))

  (advice-add 'cider-repl-handler
              :override
              #'kl/cider-repl-handler-fontify-complete-values)

2026-06-26T09:54:15.570469Z

Some other LLM suggestions I tried (but which didn't fix the issue) were:

(setq font-lock-maximum-size nil)
  (setq jit-lock-chunk-size 4500)

2026-06-26T12:07:57.556899Z

Dug a bit deeper after lunch. Seems like the issue is related to how nrepl streams the output in chunks. If everything is on one line then it streams out as one chunk and gets highlighted correctly. However when using the default cider-print-fn set to 'pprint, the output is streamed out as three chunks. only the middle chunk is syntactically valid Clojure, which is why it gets highlighted properly. The first and last chunks have the (unmatched within the chunk) brace of the map, so they don't get highlighted properly. An alternative "fix" is to add some advice to disable the nrepl streaming entirely:

(define-advice cider--repl-request-plist
      (:filter-return (request) disable-repl-print-streaming)
    (cl-loop for (key value) on request by #'cddr
             append (list key
                          (if (equal key "nrepl.middleware.print/stream?")
                              nil
                            value))))
Still want a cleaner solution though...

Harold 2026-06-26T12:39:32.694489Z

Investigation from when I encountered this in 2019: https://github.com/clojure-emacs/cider/issues/2628 Report of similar from as early as 2014: https://github.com/clojure-emacs/cider/issues/670 Smart to revisit this with coding assistant help. If I were you I'd add a new issue to the cider repo. 🙂

2026-06-26T12:47:30.976969Z

thanks for the background. Yeah, I can dig around and add to an existing or create new issue so it's more discoverable. I'm just sorta shocked that this is the "out of the box" default behavior. Then again, I've been using cider/emacs for 10+ years now myself, so I'm partly responsible for not noticing and trying to fix until now =P

2026-06-26T12:51:23.909359Z

Perhaps here has been a regression since the final comment in that first issue: > I've also introduced cider-print-buffer-size which is set to 4k by default. I'm wary of using bigger buffer sizes by default, but everyone can bump them if they want to. I'm wondering whether to allow pretty-printing without streaming, but I probably won't do it as I don't see many benefits of this. since increasing this value doesn't resolve the issue today.

bozhidar 2026-06-28T08:46:55.578989Z

Well, the problem is still the same - it's just hard to font-lock properly incomplete forms. That's why workaround was essentially to just font-lock one chuck forms and ignore the rest. I'm thinking that potentially we can just re-fontify everything once the streaming is over and perhaps that would be fine for most people.

âž• 1
2026-06-27T10:08:31.670969Z

I tracked the root cause down to nREPL and opened an issue there: https://github.com/nrepl/nrepl/issues/445

bozhidar 2026-06-27T19:33:12.356039Z

I’ll take a closer look, but I haven’t seem any reports of this in quite a while, so I’m not sure it’s really a recent regression.

Harold 2026-06-27T22:06:54.587099Z

Behavior is unchanged for me since our original investigation in 2019/ 2020 (https://github.com/clojure-emacs/cider/issues/2628).

2026-06-26T09:48:13.372509Z

Here's a zip file with two emacs configs you can use to reproduce the original behavior and fix. Run with

emacs -Q -l large-print-buffer/init.el
emacs -Q -l handler-rewrite/init.el
I don't think the cider versions matter, but I wanted a repro just to make debugging easier in case.