4

I'm trying to write a derived mode from fundamental-mode. Assuming that I have this regexp : A ((foo)bar)? B, how can I tell emacs to use the following faces ?

  • font-lock-keyword-face on A
  • font-lock-warning-face on foo (but not bar)
  • font-lock-constant-face on B

I have tried to use this following code :

(defvar myregexp
  "\\(A\\) \\(?:\\(foo\\)bar \\)?\\(B\\)")

(setq mylang-font-lock-keywords `(
  (, myregex 1 font-lock-keyword-face)
  (, myregex 2 font-lock-warning-face)
  (, myregex 3 font-lock-constant-face)
))

But it does not work with the string A B (emacs report a missing capture).

Drew
  • 29,895
  • 7
  • 74
  • 104
Maël Nison
  • 7,055
  • 7
  • 46
  • 77

2 Answers2

4

Use subexp highlighters with laxmatch enabled to have font-lock-mode ignore missing groups in matches:

(setq mylang-font-lock-keywords
      `((,myregexp (1 font-lock-keyword-face)
              (2 font-lock-warning-face nil t)
              (3 font-lock-constant-face))))

The forth element of each subexp highlighter is the laxmatch argument. If t font-lock-mode ignores this highlighter if the corresponding group in the first element is not found in the match result of myregexp.

See Search-based Fontification in the Emacs Lisp manual for more information.

  • That's only needed for the 2nd match, but it's OK to use it everywhere (I actually think it was a mistake for font-lock to be non-lax by default). Also, you have wisely changed the rule to use `myregex` only once, which will speed up the code by about 3. But you need to wrap the keywords into one more pair of parentheses. – Stefan Nov 07 '12 at 15:28
  • @Stefan Thank you for your corrections. I have updated the code accordingly. –  Nov 07 '12 at 15:50
0

The way your regexp is specified, you'd need two spaces between A and B. Either pull the second space inside the optional foobar part or use * or ? after it.

scottfrazer
  • 17,079
  • 4
  • 51
  • 49
  • Typo, it's fixed. The missing capture error is still there (`Error during redisplay: (error "No match 3 in highlight (1 font-lock-constant-face)")`) – Maël Nison Nov 04 '12 at 15:30
  • The error you cite ("No match 3 in highlight (1 font-lock-constant-face)") doesn't mak much sense and doesn't match your code either (your code has 3 associated to font-lock-constant-face, not 1). – Stefan Nov 07 '12 at 15:25