¿Cómo agregar resaltado de sintaxis compleja en un modo menor?

10

Me gustaría resaltar el código con varias caras en un modo menor.

Aquí hay una captura de pantalla cercana a lo que quiero:

Python-sintaxis-resaltado

Una cosa que me falta es tener los caracteres de comentario #en font-lock-comment-face. La idea es tener comentarios que "pertenezcan" a un esquema resaltado como texto sin formato, para que sea más fácil de leer. Si bien tiene comentarios regulares con su habitual cara menos prominente.

Aquí está el código que usé:

(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)))

La cuestión es que no tengo idea de la interfaz en la que font-lock-syntactic-face-functionopera, aparte de que recibe una estructura de datos compleja state, tiene un estado de punto diferente y devuelve una cara.

¿Alguien podría explicar esta interfaz? ¿Hay uno mejor tal vez?

abo-abo
fuente

Respuestas:

6

font-lock-syntactic-face-functiones una variable regular de Font Lock, más específicamente de la fase Syntactic Font Lock (énfasis mío):

Si esta variable no es nula, debería ser una función para determinar qué cara usar para un elemento sintáctico dado (una cadena o un comentario). El valor normalmente se establece a través de un elemento other-vars en font-lock-defaults.

La función se llama con un argumento, el estado de análisis en el punto devuelto por parse-partial-sexp, y debe devolver una cara . El valor predeterminado devuelve font-lock-comment-face para comentarios y font-lock-string-face para cadenas (consulte Caras para Font Lock).

parse-partial-sexpa su vez, devuelve una lista que describe el estado sintáctico actual de Emacs, que es esencialmente el resultado de la aplicación de la tabla de sintaxis al búfer actual. La lista es bastante compleja, por lo tanto, la ahorraré aquí; puede ver la referencia completa en la cadena de documentos de parse-partial-sexp. El propósito de esta función es cambiar la cara aplicada a un elemento sintáctico bajo ciertas reglas. El comienzo de su función demuestra esto: si la cadena actual es una cadena de documentos, use una cara diferente para ella.

Sin embargo, la cara siempre se aplica a todo el elemento sintáctico, es decir, a toda la cadena o comentario. No puede resaltar partes individuales con esta función, y solo debe mirar lo dado statepara este propósito, como lo (python-info-docstring-p state)hace en su código. No , no utilizar el punto en este lugar; Ni siquiera estoy seguro de si el valor de pointestá correctamente definido en esta etapa de bloqueo de fuentes.


Al juntar las piezas, está utilizando la función incorrecta para su propósito, por lo que no puede hacer que funcione.

No he tratado de implementar el resaltado deseado, pero creo que cavaste demasiado, demasiado profundo para tu propósito. Si entiendo bien las cosas, solo desea resaltar los contornos en un comentario.

Si tengo razón, entonces solo necesitas font-lock-keywordsde una manera especial, a saber:

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

dónde outline-faceestá la cara que le gustaría aplicar al título, tsignifica anular cualquier bloqueo de fuente anterior en este lugar, y my/find-outline-in-commentes una función de coincidencia (vea la cadena de documentos de font-lock-defaults) que toma una posición y busca el primer contorno en un comentario entre (point)y esa posición, devolviendo las extensiones del contorno para resaltarlas en los datos del partido.

Para encontrar el esquema, debe buscar comentarios (usando font-lock-comment-faceo el estado sintáctico) y luego usa looking-atpara verificar si el comentario tiene un esquema.

Lunaryorn
fuente
1

Considere definir font-lock-syntactic-face-functionasí:

(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))))

Esto se probó con python-mode.el, dejando una sección que comienza con "# *" sin comentario:

(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))))

Mientras se administra con el modo:

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

En lugar de nil, cualquier cara válida debería funcionar.

Andreas Röhler
fuente