1

In my init.el I have a series of programming language specific hooks that I use to add font-lock patterns (namely adding a header style font to some of my comments). Here is an example for c-like languages:

;; I'm only showing one pattern for simplicity
(add-hook 'c-mode-common-hook
          (lambda ()
            (font-lock-add-keywords
             nil
             '(("^/// \\(.*\\)" 1 'header-1-face prepend)
               ;; more patterns ...
               ))))

The pattern above will match if I have a C comment with 3 '/' at the start of the line. header-1-face is a font face defined earlier using defface. As I work in different languages I will add a language specific hook to my config, but since there is a lot of repeated code I though to write a function that takes two parameters: a comment string and a header string (eg for the above example it would be "//" and "/" respectively)

My naive attempt at this function essentially encapsulated the contents of the lambda and parameterized the variables.

(defun match-comment-headers (c h)
  (font-lock-add-keywords
   nil
   '(
     ;; ("^/// \\(.*\\)" 1 'header-1-face prepend) ;; This works
     ((format "^%s%s \\(.*\\)" c h) 1 'head-1-face prepend) ;; This does not
     )))
(add-hook 'c-mode-common-hook
          (lambda () (match-comment-headers "//" "/")))

When using this as a hook, emacs interprets the first element of ((format "^%s%s \\(.*\\)" c h) 1 'head-1-face prepend) as a function and yields an "invalid function" error. Using a hard coded string literal will work, however, so the overall format of the function and hook seem to be working properly. So the question is: In function such as font-lock-add-keywords that accepts these regex patterns, how can I use a string that is the result of an expression instead of a string literal?

6
  • There are many duplicates of this question, e.g. emacs.stackexchange.com/questions/66621/… (which itself is marked as a duplicate and points to additional questions of the same sort.
    – NickD
    Apr 6, 2022 at 21:44
  • 2
    Does this answer your question? How to evaluate the variables before adding them to a list?
    – NickD
    Apr 6, 2022 at 21:45
  • emacs.stackexchange.com/tags/elisp/info
    – Drew
    Apr 6, 2022 at 21:58
  • 1
    After seeing the accepted answer here and that other question, it does indeed solve my problem. Thanks! Although I will say that it wasn't initially obvious to me that this was the exact issue I was having.
    – Murad
    Apr 6, 2022 at 23:27
  • Agreed - the same issue appears under somewhat different guises that make it difficult to understand that it is the same issue. Hindsight is essential :-) That's why there are so many duplicates!
    – NickD
    Apr 7, 2022 at 0:49

1 Answer 1

1

Quoted code is not evaluated, so format is never called.

Use backquote:

  (font-lock-add-keywords
   nil
   `((,(format "^%s%s \\(.*\\)" c h) 1 'head-1-face prepend)))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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