6

I'm trying to understand minor modes with the goal of adding a minor mode for Jinja2 syntax highlighting (from jinja2-mode) to stuff like YAML. I'm running into problems though. When following a tutorial on adding new syntax highlighting, I translate the "simple" example to a minor mode:

(setq kwds
      '(("Sin\\|Cos\\|Sum" . font-lock-function-name-face)
        ("Pi\\|Infinity" . font-lock-constant-face)))

(define-minor-mode blah-mode
  :lighter "blah"
  (setq font-lock-defaults '(kwds)))

and that doesn't work. Neither does the approach taken by the major mode in jinja2-mode. I'm at a bit of a loss here... is adding highlighting in a minor mode possible? It seems to be, but I can't find any examples online, and I don't see anything in the conventions for the minor modes about how to define this correctly.

Edit

(setq kwds
      '(("Sin\\|Cos\\|Sum" . font-lock-function-name-face)
        ("Pi\\|Infinity" . font-lock-constant-face)))

(define-minor-mode blah-mode
  :lighter "blah"

  (font-lock-add-keywords nil kwds)

  (if (fboundp 'font-lock-flush)
      (font-lock-flush)
    (when font-lock-mode
      (with-no-warnings (font-lock-fontify-buffer)))))
2
  • It's late at night and I'm almost off to bed -- without fully understanding the issue, I can tell you that the single quote prevents evaluating variables inside the list. To obtain the value of a variable of what is inside a list, you need to use a backtick instead of a single quote, and the variable needs a comma in front of it -- e.g., `(,kwds)
    – lawlist
    Commented Mar 20, 2015 at 6:44
  • @lawlist that syntax works when it's in a major mode - why would it stop working for a minor mode? Commented Mar 20, 2015 at 13:35

3 Answers 3

5

You've got the arguments to define-minor-mode wrong. The following adds a doc string and supplies the three optional arguments:

(define-minor-mode blah-mode
  "Doc string."
  nil "blah" nil
  (font-lock-add-keywords nil kwds)

  (if (fboundp 'font-lock-flush)
      (font-lock-flush)
    (when font-lock-mode
      (with-no-warnings (font-lock-fontify-buffer)))))

Of course, you will will need to ensure that your keywords are removed when you disable the mode.

Another thing, your regexp:s will patch, say, Pi inside works like PaPiPo. Use "\\_<\\(Pi\\|Infinity\\)\\_>" to fix this.

3
  • Is there a closing parenthesis missing?
    – ceving
    Commented Dec 9, 2016 at 16:07
  • Yes, there was. Thanks for spotting this. Commented Dec 10, 2016 at 7:20
  • For some reason, this doesn't work when the major-mode is AucTeX's latex-mode. I am using the awkward work-around of executing font-lock-add-keywords delayed with a run-with-timer.
    – kdb
    Commented Jun 7, 2018 at 16:50
4

The easiest way is to call font-lock-add-keywords when the mode is started and font-lock-remove-keywords when it's disabled. To ensure that the new keywords take effect you can call font-lock-flush (in newer Emacs versions) or font-lock-fontify-buffer. For example:

  (if (fboundp 'font-lock-flush)
      (font-lock-flush)
    (when font-lock-mode
      (with-no-warnings
        (font-lock-fontify-buffer)))))

One example of such mode is cwarn (a mode that highlights assignment in expressions and semicolons after if and for etc. in C-like languages), it is part of the Emacs distribution.

Other examples are:

1
  • I've tried this now, it still doesn't seem to work. I've updated the question, do you see anything I'm doing wrong? (other than not checking if the mode is enabled or not, which I'll obviously change once I get it working.) Commented Mar 20, 2015 at 13:49
0

Instead of adding code within the definition, you may consider using the mode hook, as explained in How to automatically remove a hook provided by a minor mode after disabling that mode?

This would cover both activation and inhibition. Here, you can write:

(define-minor-mode blah-mode :lighter "blah")

(defun blah-mode-apply-keywords ()
  (if blah-mode
       (progn
         (font-lock-add-keywords nil kwds)
         (font-lock-mode))
     (font-lock-remove-keywords nil kwds)
    )
  (font-lock-fontify-buffer) ;; or whatever to refresh decoration
)

(add-hook 'blah-mode-hook 'blah-mode-apply-keywords)

Your Answer

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

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