0

I'm trying to wrap my head around font-lock-keywords format, particularly MATCH-ANCHORED variant, but I don't see how would I re-use matches generated from one regexp. Below is my setup for illustration:

(defvar fmt-font-lock-keywords
  ;; no-args
  `(("~\\(@:?\\|:@?\\)?[]>()}aswvcp;_]"
     (0 font-lock-keyword-face))
    ;; numeric-arg
    ("~\\([0-9]*\\|#,?\\)\\(@:?\\|:@?\\)?[i*%&|~{[]"
     (0 font-lock-keyword-face))
    ;; decimal
    ("~\\([0-9]*\\|#\\(,[0-9]*\\|#\\)\\{0,3\\}\\)?\\(@:?\\|:@?\\)?[rdbox]"
     (0 font-lock-keyword-face))
    ;; floating-point f
    (,(concat
       "~\\(\\(\\([0-9]*\\|#\\)\\(,\\([0-9]*\\|#\\)\\)\\{3\\}\\(,'\\w\\)\\{1,2\\}\\)\\|"
       "\\(\\([0-9]*\\|#\\)\\(,\\([0-9]*\\|#\\)\\)\\{0,3\\}\\)\\)"
       "?\\(@:?\\|:@?\\)?f")
     (0 font-lock-keyword-face))
    ;; floating-point e, g
    (,(concat
       "~\\(\\(\\([0-9]*\\|#\\)\\(,\\([0-9]*\\|#\\)\\)\\{3\\}\\(,'\\w\\)\\{1,3\\}\\)\\|"
       "\\(\\([0-9]*\\|#\\)\\(,\\([0-9]*\\|#\\)\\)\\{0,3\\}\\)\\)"
       "?\\(@:?\\|:@?\\)?[eg]")
     (0 font-lock-keyword-face))
    ;; currency
    (,(concat
       "~\\(\\(\\([0-9]*\\|#\\)\\(,\\([0-9]*\\|#\\)\\)\\{2\\}\\(,'\\w\\)\\)\\|"
       "\\(\\([0-9]*\\|#\\)\\(,\\([0-9]*\\|#\\)\\)\\{0,2\\}\\)\\)"
       "?\\(@:?\\|:@?\\)?[$]")
     (0 font-lock-keyword-face))
    ;; tabulation
    ("~\\(\\([0-9]*\\|#\\)\\(,\\([0-9]*\\|#\\)\\)?\\)?\\(@:?\\|:@?\\)?t"
     (0 font-lock-keyword-face))
    ;; escape
    ("~\\(\\([0-9]*\\|#\\)\\(,\\([0-9]*\\|#\\)\\)\\{0,2\\}\\)?\\(@:?\\|:@?\\)?^"
     (0 font-lock-keyword-face))
    ;; logical block
    ("~\\(\\([0-9]*\\|#\\)\\(,\\([0-9]*\\|#\\)\\)\\{0,3\\}\\)?\\(@:?\\|:@?\\)?<"
     (0 font-lock-keyword-face))
    ;; custom function
    (,(concat
       "~\\(\\([0-9]+\\|'\\w\\|#\\)\\(,\\([0-9]+\\|'\\w\\|#\\)+\\)*\\)?"
       "\\(@:?\\|:@?\\)?\\/[^\\s\\n,#@]+\\/")
     (0 font-lock-keyword-face))))

And, when initializing this mode:

(define-derived-mode fmt-mode fundamental-mode
  . . .
  (set (make-local-variable 'font-lock-defaults)
      '(fmt-font-lock-keywords)) . . .)

Sorry, I know it looks like cuneiform, but what it does is actually very simple... it's parsing the Common Lisp format mini-language.

What it does now: it colors all special sub-strings using keyword face, but what I would like to do is to color certain parts differently (numerical arguments would be colored differently, the custom function call would be colored differently, at and colon - maybe differently, character data - maybe differently too).

I could, technically, duplicate these regexps to extract a different group, but it is very inelegant, besides, in cases where it is possible to pass variable number of arguments the writeup will near combinatorial explosion...


I do realize that parsing can be much more easily solved when not using regular expressions, but I don't know how to combine it with font-lock mode. But if you happen to know how to do it w/o regexps, while still using font-lock mechanics for coloring, that would be a great answer too!

1 Answer 1

1

A quick partial response without looking at your code (sorry) - so it might well miss the boat.

  1. If part of what you are asking is how to leave something highlighted by a f-l-k entry even if it also matches a later f-l-k entry, the answer to that is to use keep. (See also what t does, which is pretty much the opposite.)

  2. If part of what you are asking is how to font-lock without using regexps, or without using only regexps, the answer to that is to use a function.

If you haven't already, see the Elisp manual, node Search-based Fontification -- search for keep and FUNCTION.

2
  • Thanks for the answer, I found a partial answer too: using ("\\(group one\\)\\(group two\\)" (1 face-one) (2 face-two)) seems to do what I asked above, but it doesn't solve the original problem, because extracting repeating groups (such as if matching delimited lists) becomes very tedious with long fixed length lists and impossible with lists of arbitrary length. So, yes, I'm going to research the search-based fontification).
    – wvxvw
    Aug 3, 2014 at 5:43
  • @wvxvw You should write an answer with your partial solution. (That was exactly what I was looking for.)
    – Tobias
    Mar 10, 2020 at 11:57

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .