Resaltar código Lua (con Emacs) en un documento LaTeX

Cuando en un búfer de Emacs está activo algún determinado modo mayor, el resaltado de sintaxis aplicado será, como es de esperar, el de ese modo mayor. Si nuestro modo es Emacs Lisp, por ejemplo, se resaltará todo (comentarios inclusive) como Emacs Lisp. Si es Python, como Python. Y si es LATEX, como LATEX. Pero el problema viene cuando queremos incluir algo de código Lua dentro de un documento LATEX, generalmente encerrado en el entorno luacode . ¿Qué ocurre? Pues que esas líneas en Lua serán interpretadas con el resaltado del LaTeX-mode , y el resultado será confuso e incómodo para leer. Pensemos, sin ir más lejos, en el signo que usa Lua para los comentarios ( -- ): las líneas comentadas aparecerán como meras líneas de texto. Y, por contra, el carácter que LATEX emplea para comentar líneas ( % ) es el que en Lua se aplica como carácter de escape. La inconsistencia en las fuentes queda servida, ya que cualquier pasaje en una función Lua que incluya un % el LaTeX-mode lo entenderá como línea comentada.

Para remediar estos y otros desaguisados, que afean y despistan bastante la lectura del código de nuestro documento, se me ocurrió hace poco escribir la función que paso de inmediato a comentar.

La idea, dicho con algo de trazo grueso, es que todo lo que tengamos encerrado en un entorno luacode sea enviado a un búfer temporal, se «fontifique» (valga el barbarismo por el emacsiano fontify) con el resaltado propio del lua-mode y, una vez adquiridas esas propiedades textuales, se añada en su lugar oportuno como un overlay, que recordemos es lo que en la jerga emacsiana se traduce como una capa temporal con ciertas propiedades de texto.

Empezamos por definir esta función que se encargará de la primera parte del proceso, y que nos devolverá una cadena del argumento ( texto ) con las propiedades del lua-mode :

( defun resaltado-temporal-lua (texto) ( with-temp-buffer (insert texto) ( delay-mode-hooks (lua-mode)) (font-lock-default-function 'lua-mode) (font-lock-default-fontify-region (point-min) (point-max) nil) (buffer-string)))

La siguiente función nos hará el resto del trabajo:

( defun entorno-lua-resalta () ( interactive ) ( let ((x (make-marker)) (y (make-marker))) ( save-excursion (goto-char (point-min)) ( while (re-search-forward "\\\\begin{luacode}" nil t) (forward-line 1) (beginning-of-line) (set-marker x (point)) ( save-excursion (re-search-forward "\\\\end{luacode}" nil t) (forward-line -1) (end-of-line) (set-marker y (point))) ( let* ((ov (make-overlay x y)) (pega (resaltado-temporal-lua ( save-restriction (narrow-to-region x y) (buffer-string))))) (overlay-put ov 'overlay-lua t) (overlay-put ov 'display (propertize (format "%s" pega) 'font-lock-face (get-text-property (point) 'face))))))))

Y para eliminar los overlays, bastará con definir:

( defun entorno-lua-quita-resaltado () ( interactive ) (remove-overlays nil nil 'overlay-lua t))

Figura 1: Antes y después de resaltar nuestro entorno Lua en un documento LaTeX

Ahora ya nuestras funciones en Lua no parecerán un injerto horrible en medio de los documentos *.tex . Podemos, además, crear sendos atajos de teclado para activar o desactivar el resaltado; o hacerlo permanente mediante una variable local, añadiendo por ejemplo en la primera línea del documento:

% -*- eval: (entorno-lua-resalta); -*-

Y como un gif vale más que mil palabras:

Figura : Resaltando código Lua en un documento LaTeX (click en la imagen para ampliar)