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?

Drew
  • 75,699
  • 9
  • 109
  • 225
Murad
  • 13
  • 2
  • There are many duplicates of this question, e.g. https://emacs.stackexchange.com/questions/66621/passing-string-as-arg-to-apply-function (which itself is marked as a duplicate and points to additional questions of the same sort. – NickD Apr 06 '22 at 21:44
  • 2
    Does this answer your question? [How to evaluate the variables before adding them to a list?](https://emacs.stackexchange.com/questions/7481/how-to-evaluate-the-variables-before-adding-them-to-a-list) – NickD Apr 06 '22 at 21:45
  • https://emacs.stackexchange.com/tags/elisp/info – Drew Apr 06 '22 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 06 '22 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 07 '22 at 00:49
  • Please consider deleting your question, based on its being a duplicate. Thx. – Drew Apr 07 '22 at 01:49

1 Answers1

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)))
sds
  • 5,928
  • 20
  • 39