Esbozaré un modo principal simple para resaltar los bloques <style>
(CSS) y <script>
(JavaScript, etc.). Para obtener el bloqueo de fuente de varias líneas trabajando razonablemente bien, tendrá que primero habilitarla estableciendo font-lock-multiline
-t
y escribir una función para añadir a font-lock-extend-region-functions
que se extenderá la región búsqueda relevante para contener grandes bloques de texto. Luego, necesitará escribir emparejamientos multilínea, ya sean expresiones o funciones regulares, y agregarlos al font-lock-defaults
.
Aquí es una definición básica modo mayor que los nombres de la fuente bloqueo lista de palabras clave (en este caso, test-font-lock-keywords
), permite bloqueo de fuente de múltiples líneas, y agrega la función de extensión región test-font-lock-extend-region
.
función de extensión
(define-derived-mode test-mode html-mode "Test"
"Major mode for highlighting JavaScript and CSS blocks."
;; Basic font lock
(set (make-local-variable 'font-lock-defaults)
'(test-font-lock-keywords))
;; Multiline font lock
(set (make-local-variable 'font-lock-multiline) t)
(add-hook 'font-lock-extend-region-functions
'test-font-lock-extend-region))
La región debe ser algo como esto:
(defun test-font-lock-extend-region()
"Extend the search region to include an entire block of text."
;; Avoid compiler warnings about these global variables from font-lock.el.
;; See the documentation for variable `font-lock-extend-region-functions'.
(eval-when-compile (defvar font-lock-beg) (defvar font-lock-end))
(save-excursion
(goto-char font-lock-beg)
(let ((found (or (re-search-backward "\n\n" nil t) (point-min))))
(goto-char font-lock-end)
(when (re-search-forward "\n\n" nil t)
(beginning-of-line)
(setq font-lock-end (point)))
(setq font-lock-beg found))))
Esta función analiza las variables globales font-lock-beg
y font-lock-end
, que contienen la posiciones inicial y final de la región de búsqueda y extiende la región para contener un bloque completo de texto (separados por líneas en blanco, o "\n\n"
).
Ahora que Emacs buscará coincidencias en regiones más grandes, debemos configurar la lista test-font-lock-keywords
. Hay dos formas razonables de hacer coincidir construcciones multilínea: , una expresión regular que coincidirá entre líneas y una función correspondiente. Daré ejemplos de ambos. Esta lista de palabras clave contiene una expresión regular para hacer coincidir <style>
bloques y una función para hacer coincidir <script>
bloques:
(defvar test-font-lock-keywords
(list
(cons test-style-block-regexp 'font-lock-string-face)
(cons 'test-match-script-blocks '((0 font-lock-keyword-face)))
)
"Font lock keywords for inline JavaScript and CSS blocks.")
El primer elemento de la lista es sencillo: una expresión regular y una cara para poner de relieve partidos de que el uso regular expresión. El segundo parece un poco más complicado, pero se puede generalizar para especificar diferentes caras para diferentes grupos definidos en los datos de coincidencia especificados por la función. Aquí, simplemente resaltamos grupo cero (la coincidencia completa) usando font-lock-keyword-face
. (La documentación pertinente para estos comparadores se encuentra en la sección de Search-based fontification de el manual de Emacs.)
con una expresión regular para hacer coincidir <style>
bloques serían:
(defconst test-style-block-regexp
"<style>\\(.\\|\n\\)*</style>"
"Regular expression for matching inline CSS blocks.")
Tenga en cuenta que tenemos que poner \n
en el grupo interno porque .
no coincide con líneas nuevas.
La función de emparejamiento, por el contrario, tiene que buscar la primera <script>
bloque en la región desde el punto de la única argumento dado, last
:
(defun test-match-script-blocks (last)
"Match JavaScript blocks from the point to LAST."
(cond ((search-forward "<script" last t)
(let ((beg (match-beginning 0)))
(cond ((search-forward-regexp "</script>" last t)
(set-match-data (list beg (point)))
t)
(t nil))))
(t nil)))
Esta función establece los datos de partido , que es una lista del formulario begin-0 end-0 begin-1 end-1 ...
que indica el comienzo y el final del grupo zeroth, primer grupo, y así sucesivamente. Aquí, solo damos límites en el bloque completo que coincidió, pero podría hacer algo más sofisticado, como establecer diferentes caras para las etiquetas y el contenido .
Si se combinan todos este código en un solo archivo y ejecutar M-x test-mode
, debería funcionar para poner de relieve estos dos tipos de bloques . Aunque creo que esto hace el trabajo, si hay una forma más eficiente o apropiada de hacerlo, también me gustaría saber .
En este [hilo] (http://lists.gnu.org/archive/html/help-gnu-emacs/2004-09/msg00534.html), Stefan Monnier dice que font-lock-multi-line es apropiado para cosas que generalmente son de una sola línea, pero ocasionalmente de varias líneas. ¿Comentarios? –
Bueno, Stefan Monnier es la referencia definitiva cuando se trata de algo relacionado con font-lock, por lo que cualquier consejo de él vale la pena seguirlo. Usar el sistema sintáctico, como él sugiere, es una forma de hacerlo. Otra es utilizar una "función de coincidencia" en lugar de una expresión regular, que podría coincidir con todo el bloque. Debería ver mis respuestas como una respuesta directa a la pregunta (proporcione un ejemplo de la función de bloqueo de fuentes de varias líneas) y tal vez no una respuesta sobre la mejor manera de lograr lo que sea que el cartel original le pregunte. – Lindydancer