Pregunta

Im trying to setup font-locking for a major mode. Here is some example code:

USING: foo bar bar ;

IN: fuelcolors

TUPLE: font < super-class
    name
    size
    bold?
    italic?
    { foreground initial: COLOR: black }
    { background initial: COLOR: white } ;

TUPLE: rgb red green blue ;

: foobar ( seq -- seq )
  hello there { 1 2 3 } ;

The following symbols should be highlighted with some face (doesn't matter which, my problem is the matching part): name, size, bold?, italic?, foreground, background, red, green, blue. They represent names of slots in tuples.

I know a regexp wont do it because the matched region isn't continuous. italic? and foreground should be matched, but not the { character in between those symbols. So instead I thought I could author a font-lock matcher function, similar to the one Dmitri offered here: Context-sensitive font-locking in emacs for a very similar problem.

But afaict, his solution takes advantage of the fact that the "sequence" of items to highlight is inside paranthesises which is not the case here.

Font-lock has trouble with situations like these (Unknown number of matches in regex and font-lock), but I'm still hoping for some "good enough" solution even it if requires hacking font-lock internals.

¿Fue útil?

Solución 2

Here is the solution I ended up with:

(,"\\(TUPLE\\):[ \n]+\\(\\(?:\\sw\\|\\s_\\)+\\)\\(?:[ \n]+<[ \n]+\\(\\(?:\\sw\\|\\s_\\)+\\)\\)?"
     (1 'factor-font-lock-parsing-word)
     (2 'factor-font-lock-type-name)
     (3 'factor-font-lock-type-name nil t)
     ("\\(\\(?:\\sw\\|\\s_\\)+\\)\\|\\(?:{[ \n]+\\(\\(?:\\sw\\|\\s_\\)+\\)[^}]+\\)"
      ((lambda (&rest foo)
         (save-excursion
           (re-search-forward " ;" nil t)
           (1- (point)))))
      nil
      (1 'factor-font-lock-symbol nil t)
      (2 'factor-font-lock-symbol nil t)))

Otros consejos

A matcher function seems like a good match for this.

I would use two functions, one that you can use to match TUPLE and to set the limits of the search of the members, and an inner matcher to find each element. The inner function could be written to be aware of the { name ... } construct.

The trick is that the inner function is called once for each element, so there is never a situation where you have an unknown number of matches.

The rule would look something like:

'(my-match-a-tuple
  (1 'font-lock-keyword-name-face)    ;; Highlight the word TUPLE
  (my-match-tuple-member
   ;; Pre-match form (can be used move the point around and to set search limits)
   nil
   ;; Post-match form (can be used to move point around afterwords)
   nil
   (1 'font-lock-variable-face)))

You can look at my package for fontifying cmake scripts, it makes heavy use of matcher functions: https://github.com/Lindydancer/cmake-font-lock

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top