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?