I am working on a minor mode that will use Slime to highlight defined symbols when editing Lisp code. The code is here. It is based on the code for Highlight-Defined which registers a matcher function for font lock. The function attempts to parse the next symbol (hackily) and then uses swank to test if it is defined. Currently this process is extremely slow. I'm wondering if there are best practices for font locking that will increase performance. For instance, is there some standard way to parse symbols (right now the same symbol gets parsed multiple times sometimes)? Is this just a bad approach and instead should I try to get a list of defined symbols and then add regexs explicitly for them?

Specifically I have registered the following font-lock matcher and I am wondering if there is some way to make this run at a reasonable speed or should I give up and try a different approach.

(defun shigh-highlight (_limit)
  "Highlight Lisp functions and/or variables that are currently defined.
Use as a font-lock MATCHER function for `slime-highlight-mode'."
  ;; If your code uses any of these variable names too then bad - they will be highlighted:
  ;; `shigh-found', `shigh-highlight-type', `shigh-obj', and `shigh-opoint'.
  (let ((shigh-opoint  (point))
        (shigh-epoint nil)
        (shigh-found   nil)
        (move-error nil))
    (with-syntax-table lisp-mode-syntax-table 
      (skip-chars-forward "()#` []")
      (while (and (not shigh-found) (not (eobp)) (< (point) _limit))
        (condition-case () 
              (setq shigh-opoint  (point))
              (forward-sexp 1)
              (setq shigh-epoint (point)))
          (error (progn (setf move-error t) (setq shigh-epoint (point)))))
        (let ((shigh-str (trim-string
                          (upcase (buffer-substring-no-properties shigh-opoint 
          (if (and (not move-error) 
                   (> (length shigh-str) 0)
                   (symbolp (read shigh-str)))
            (let ((bndp (slime-boundp shigh-str))
                  (fbndp (slime-fboundp shigh-str))
                  (lclp (slime-local-symbolp shigh-str)))
             (if (and 
                  (not (member shigh-str '("NIL" "T")))
                                        ;(not (keywordp hdefd-obj))
                  (or (and (memq shigh-highlight-type '(fns-and-vars functions))
                           (or (and (not shigh-highlight-cl) lclp)
                      (and (memq shigh-highlight-type '(fns-and-vars variables))
                           (or (and (not shigh-highlight-cl) lclp)
                      (and (eq shigh-highlight-type 'undefined)
                           (not fbndp)
                           (not bndp))))
                   (setq shigh-face
                         (if (and (memq shigh-highlight-type 
                                        '(fns-and-vars functions))
                             (if lclp
                           (if (eq shigh-highlight-type 'undefined)
                             (if lclp
                   (forward-sexp 1)
                   (setq shigh-found t))
                 (if (looking-at "\\(\\sw\\|\\s_\\)")
                     (forward-sexp 1)
                   (forward-char 1))
                 (skip-chars-forward "()#`")
                 (setf move-error nil))))
                 (if (looking-at "\\(\\sw\\|\\s_\\)")
                     (forward-sexp 1)
                   (forward-char 1))
                 (skip-chars-forward "()#`")
                 (setf move-error nil)))))
      (when shigh-found
       (set-match-data (list shigh-opoint shigh-epoint)))
  • The question is too broad and unclear. Who knows what you are really doing? Please show your code and ask a specific question.
    – Drew
    May 3 '17 at 2:53
  • Your question should make sense even when the link to your code disappears.
    – Stefan
    May 3 '17 at 3:30
  • CIDER registers a new keyword for every defined macro once you've compiled it, so hooking into the REPL could be a better approach.
    – wasamasa
    May 3 '17 at 6:28
  • I edited the question to include the relevant code. I'm sorry that the question is vague but it is hard to make it more specific since I'm asking about a general approach.
    – qazmonk
    May 3 '17 at 20:57

As I understand your question the main problem is that the function

swank:eval-and-grab-output works slowly, and you call it around 3 times for each symbol in region you need to "font-lock".

It may be better to first parse all the region needed to font-lock and extract substrings witch may be symbols (maybe with information about their place), and then, pass that list of symbols to Common Lisp to find the true symbols that need to be fontified.

I don't no how exactly font-lock mode work (it seems to me it depends on a lot of variables) but, For example, if the variable font-lock-support-mode is eq to jit-lock-mode, you can use (jit-lock-register #'fun t) where fun is a function "will be called with two arguments START and END indicating the region that needs to be (re)fontified" (c) to extract data you need from region going to be font-lock.

For example, it seems to me, it can be written like this (just to explane what I meen).


  • This looks like exactly what I am looking for
    – qazmonk
    May 7 '17 at 17:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.