5

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)))))
  • 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 Mar 20 '15 at 6:44
  • @lawlist that syntax works when it's in a major mode - why would it stop working for a minor mode? – Brian Hicks Mar 20 '15 at 13:35
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.

  • Is there a closing parenthesis missing? – ceving Dec 9 '16 at 16:07
  • Yes, there was. Thanks for spotting this. – Lindydancer Dec 10 '16 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 Jun 7 '18 at 16:50
3

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:

  • 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.) – Brian Hicks Mar 20 '15 at 13:49

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.