Hoe complexe syntax highlighting toevoegen in een minor mode?

Ik wil graag code met verschillende gezichten benadrukken in een minder belangrijke modus.

Hier is een screenshot die dicht in de buurt komt van wat ik wil:

python-syntax-highlight

Een ding dat ik mis is het plaatsen van de commentaartekens # font-lock-commentaar-face . Het idee is om opmerkingen te hebben die "horen" om een ​​omtrek gemarkeerd als platte tekst, dus het is gemakkelijker om te lezen. Terwijl regelmatige opmerkingen hebben met hun gebruikelijke minder prominente gezicht.

Dit is de code die ik heb gebruikt:

(setq-local font-lock-defaults
            '(python-font-lock-keywords
              nil nil nil nil
              (font-lock-syntactic-face-function
               . lpy-font-lock-syntactic-face-function)))

(defun lpy-font-lock-syntactic-face-function (state)
  "Return syntactic face given STATE.
Returns 'defalt face for comments that belong to an outline."
  (cond ((nth 3 state)
         (if (python-info-docstring-p state)
             font-lock-doc-face
           font-lock-string-face))
        ((save-excursion
           (while (and (> (point) (point-min))
                       (progn (move-beginning-of-line 0)
                              (eq (char-after) ?\#))))
           (forward-line 1)
           (looking-at "#\\*+ "))
         'default)
        (t
         font-lock-comment-face)))

Het punt is, ik heb geen idee over de interface waarop font-lock-syntactic-face-function werkt, anders ontvangt het een complexe datastructuur staat , heeft een verschillende puntstatus en retourneert een gezicht.

Kan iemand deze interface uitleggen? Is er misschien een betere?

9

2 antwoord

font-lock-syntactic-face-function is a regular variable from Font Lock, more specifically from the Syntactic Font Lock phase (emphasis mine):

Als deze variabele niet-nul is, zou het een functie moeten zijn om te bepalen welk vlak gebruikt moet worden voor een bepaald syntactisch element (een string of een opmerking). De waarde wordt normaal ingesteld door een element van een andere-vars in lettertype-vergrendeling-standaardinstellingen.

     

De functie wordt aangeroepen met één argument, de parse-status op het punt geretourneerd door parse-partial-sexp en moet een gezicht retourneren . De standaardwaarde retourneert font-lock-comment-face voor opmerkingen en font-lock-string-face voor tekenreeksen (zie Faces voor lettertypevergrendeling).

parse-partial-sexp in turn returns a list which describes Emacs' current syntactic state, which is essentially the result of the application of the syntax table to the current buffer. The list is rather complex, hence I'll spare it here; you can see the complete reference in the docstring of parse-partial-sexp. The purpose of this function is to change the face applied to a syntactic element under certain rules. The beginning of your function demonstrates this: If the current string is a docstring, use a different face for it.

Het gezicht is echter altijd van toepassing op het gehele syntactische element, d.w.z. de hele tekenreeks of opmerking. U kunt afzonderlijke onderdelen niet markeren met deze functie, en u moet alleen de opgegeven status bekijken voor dit doel-achtige (python-info-docstring-p staat) doet in uw code. Gebruik niet punt op deze plaats gebruiken; Ik weet niet eens zeker of de waarde van point in deze fase van het vergrendelen van lettertypen correct is gedefinieerd.


Als u de stukjes bij elkaar zet, gebruikt u de verkeerde functie voor uw doel, daarom kunt u het niet laten werken.

Ik heb niet geprobeerd je gewenste accentuering te implementeren, maar ik denk dat je de weg hebt ingegraven, veel te diep voor je doel. Als ik de dingen goed begrijp, zou je graag de contouren in een opmerking willen benadrukken.

Als ik gelijk heb, dan heb je alleen font-lock-keywords op een speciale manier nodig, namelijk:

(my/find-outline-in-comment-p 0 'outline-face t)

waar outline-face het gezicht is dat u op de kop wilt toepassen, betekent t dat elke eerdere lettertype-vergrendeling op deze plaats wordt overschreven, en mijn/find-outline-in-comment is een matchfunctie (zie de docstring van font-lock-defaults ) die een positie inneemt en zoekt naar de eerste contour in een opmerking tussen (punt) en die positie, waarbij de uitgestrekte contouren van de te benadrukken contour in de wedstrijdgegevens worden teruggegeven.

Om de omtrek te vinden, scant u vooruit voor opmerkingen (met behulp van font-lock-comment-face of de syntactische staat) en gebruikt u vervolgens kijken om te controleren of de opmerking heeft een schets.

6
toegevoegd

Overweeg om font-lock-syntactic-face-function als volgt te definiëren:

(setq font-lock-syntactic-face-function
      (lambda (state)
    (cond ((nth 3 state)
           font-lock-string-face)
          ((and (nth 4 state)(nth 8 state))
            MY-COMMENT-FACE
          (t  font-lock-comment-face))))

Dit getest met python-mode.el, waarbij een sectie die begint met "# *" zonder commentaar-gezicht blijft:

(setq py--font-lock-syntactic-face-function
      (lambda (state)
    (cond ((nth 3 state)
           font-lock-string-face)
          ((and (nth 4 state)(nth 8 state)
            (progn (save-excursion
                 (goto-char (nth 8 state))
                 (looking-at (concat comment-start (regexp-quote "*"))))))
           nil)
          (t font-lock-comment-face))))

Hoewel het wordt beheerd met de modus:

(font-lock-syntactic-face-function
                    . py--font-lock-syntactic-face-function)

In plaats van nul zou elk geldig gezicht moeten werken.

0
toegevoegd