Revoltijo Elisp (IV)
Resaltar y/o plegar notas al pie en Org
Como ya he dicho más de una vez, uso Org Mode para escribir (entre otras cosas) y también para intentar poner un orden
(esa gran utopía) en lo que escribo. Sobre este último extremo, uno de los frentes que se me iba resistiendo algo más
era el de organizar las notas al pie. Veamos. Por un lado no soy muy dado a abusar de notas al pie, una de las grandes
plagas del academicismo. Creo que lo que se debe decir debe decirse en el texto, y no escribir dos textos que discurran
en paralelo, uno arriba y otro abajo. Pero alguna que otra no me queda más remedio que escribir, me temo1. Por otra
parte, Org Mode gestiona razonablemente bien todo lo referente a las notas, pero mi problema es que tiendo a usar muy a
menudo la opción fnlocal
, que sitúa las notas por grupos lo más cerca posible del párrafo que voy escribiendo, en
lugar de hacerlo todas juntas bajo un encabezado al final del documento. Me resulta mucho mantener las notas así, ya que
muevo mucho los encabezados y sub-árboles entre documentos, y si las notas no están «pegadas» al párrafo o rondando por
ahí cerca (ergo, dentro del sub-árbol que muevo), se me acaban quedando por el camino. Dicho lo cual, echaba de menos
una forma de resaltar los cuerpos de notas al igual que los bloques de código. Y, como éstos, también la posibilidad de
plegarlos para que no estorben. Así pues, me decidí a escribir una serie de funciones como apaño. Estas funciones hacen
uso de los overlays de Emacs, o capas temporales con propiedades de texto y gráficos. Los overlays vienen a ser,
mutatis mutandis como las máscaras de capa de los programas para editar imágenes.
Pasamos a explicar rápidamente las funciones, por si le fuesen de utilidad a alguien o las quisiese mejorar. Y, por contradecir el título de esta entrada, empezamos por las que pliegan / despliegan el texto de la nota.
Para plegar y desplegar el texto de las notas en un documento
Primero, la función que pliega las notas, donde nos viene de perlas la función nativa de Org org-narrow-to-element
.
Nuestro overlay para sustituir al texto de la nota, en este caso, es la palabra «nota», en rojo y encerrada en un
recuadro.
(defun pliega-notas-org () (interactive) (save-excursion (goto-char (point-min)) (while (re-search-forward "^\\[fn:[[:digit:]]" nil t) (save-restriction (org-narrow-to-element) (let ((ov (make-overlay (point-min) (point-max))) (nota-plegada (propertize "nota" 'font-lock-face '(:foreground "red" :weight bold :box t)))) (overlay-put ov 'overlay-nota-plegada t) (overlay-put ov 'display nota-plegada))))))
Y para volver a mostrar las notas, simplemente eliminamos el overlay:
(defun muestra-notas-org () (interactive) (remove-overlays nil nil 'overlay-nota-plegada t))
Para resaltar el texto de las notas de un documento
Aquí son necesarias algunas triquiñuelas. Primero definimos una función que aplica un par de propiedades de texto entre
los argumentos x
e y
. Los colores que he ecogido, por supuesto, son personales e intransferibles, pero al menos
cuadran bien con los dos temas que suelo usar en Emacs, el claro para el día y el oscuro para los trabajos nictálopes.
(defun propiedades-resaltado-nota (x y) (put-text-property x y 'font-lock-face '(:background "NavajoWhite" :foreground "DarkMagenta")) (put-text-property x y 'front-sticky t))
A continuación, la función que resalta las notas en todo el documento, aplicando las propiedades antes mencionadas como overlay:
(defun resaltado-notas-local () (interactive) (save-excursion (goto-char (point-min)) (while (re-search-forward "^\\[fn:[[:digit:]]" nil t) (save-restriction (org-narrow-to-element) (let ((ov (make-overlay (point-min) (point-max))) (resaltado-nota (propiedades-resaltado-nota (point-min) (point-max)))) (overlay-put ov 'overlay-nota-resaltada t) (overlay-put ov 'display resaltado-nota))))))
Ahora, lo complicamos algo más. Esta otra función añade la anterior como variable local al documento. Sólo si no está ya
añadida (expresión unless
). Así, cada vez que abramos el documento, se conservará nuestro resaltado, ya que los
overlays son siempre temporales.
(defun var-local-resaltado-nota () (save-excursion (goto-char (point-min)) (unless (re-search-forward "eval: (resaltado-notas-local)" nil t) (add-file-local-variable 'eval '(resaltado-notas-local)) (save-excursion (goto-char (point-max)) (re-search-backward "# Local Variables:" nil t) (newline 5)))))
Y, por último, una función que añade una nota ya resaltada. Por cierto, aquí he tenido que hacer una pequeña triquiñuela
no demasiado elegante. Una nota que vamos a escribir es una nota vacía, así que la función org-narrow-to-element
no
tiene ningún elemento que «aislar». Así que, de forma provisional, se inserta y se elimina un pequeño texto de «bulto»,
para que el resaltado tenga efecto desde el momento en que empezamos a escribir la nota.
(defun mi-notapie-org () (interactive) (org-footnote-action) (save-excursion (insert "nota")) (resaltado-notas-local) (var-local-resaltado-nota) (save-restriction (org-narrow-to-element) (goto-char (point-min)) (replace-regexp "nota" "" nil)))
Estrambotes
Uno. La última función tiene un pequeño problema. Si pegamos texto en nuestra nota resaltada (yank
), el texto pegado viene
con las propiedades de origen, que se sobreescribirán a las del overlay. Por tanto, no aparecerá resaltado hasta que
no recarguemos el búfer (revert-buffer
). Para prevenir ese comportamiento, podemos definir esta función:
(defun resaltado-yank-notas () (if (org-footnote-at-definition-p) (resaltado-notas-local)))
Y hacer que se ejecute justo después de llamar a la función yank
. Así:
(advice-add 'yank :after 'resaltado-yank-notas)
Dos. Con esto de los overlays, que da mucho juego, escribí también unas funciones para mostrar las imágenes dentro de un documento de LaTeX o el resultado compilado (y aproximado, ojo) de algunos entornos. El código está en este repo de GitLab.
∞
Publicado: 18/10/2019
Última actualización: 18/10/2019
Esta obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial 4.0 Internacional.
Notas al pie de página:
Un autor que abusa de este recurso, por cierto, recuerda mucho al que en el cine te está explicando la película y no te deja verla.