Ardides de la Odisea: referencias automáticas a número de canto y verso
A lo largo de mi traducción de la Odisea (work in progress) voy dejando muchas anotaciones, en Org Mode por supuesto, que remiten a ciertos números de canto y verso en mi traducción (ésta conserva el mismo número de versos del original). Para navegar con cierta soltura y marearme lo menos posible por todo ese (cada vez más) vasto oleaje de versos, va surgiendo un catálogo variopinto de apaños en Elisp. Detallaremos aquí algunos, por si pudiesen resultar útiles y adaptables a algún amable lector1.
Para empezar, una muy simple función que me devuelve en un mensaje el número de canto y
verso donde tengo el cursor, teniendo en cuenta que el número de canto lo extrae de la
propiedad :Canto:
. Para la función numero-verso-actual
, véase esta otra GNUta, aquí.
(defun donde-odisea () (interactive) (let ((canto (org-entry-get nil "Canto")) (verso (numero-verso-actual))) (message "Od. %s.%s" canto verso) (kill-new (format "%s.%s" canto verso))))
Cada vez que llamo a la función, me devuelve en la echo area el mensaje con la cadena «Od.núm-canto.num-verso» (por ejemplo, «Od. 3.121») y copia en el portapapeles (kill-ring) de Emacs la cadena «num-canto.num-verso» (por ejemplo, «3.21»).
Pero hay más. Para saltar automágicamente a un determinado número de canto-verso desde mis
anotaciones de consumo personal o desde los textos colaterales del prólogo y las notas
encontré, una vez más, utilísimo el potente sistema de enlaces de Org. Así que definí un
nuevo tipo de enlace con la etiqueta «od» que admitiera la estructura núm-canto punto
núm-verso
. Y con escribir en cualquier parte, simplemente, algo así como od:3.121
, ya
el propio Org se encargaría de reconocer el enlace y resaltarlo. El enlace tendría una
acción asociada (saltar al número de canto y verso correspondiente) y una regla de
exportación a LATEX, para que pasara como una referencia cruzada a la página, usando
el paquete varioref
. O sea, que un enlace od:3.21
daría en LATEX la cadena 3.21
(\vpageref{3.21})
(como se aprecia en la fig. 1).
Mi nuevo tipo de enlace quedó, finalmente, así:
(org-link-set-parameters "od" :follow (lambda (ruta) (let ((canto (if (string-match "\\([[:digit:]]+\\)\\." ruta) (substring ruta (match-beginning 1) (match-end 1)) (error "no se ha indicado número de canto"))) (verso (if (string-match "\\.\\([[:digit:]]+\\)" ruta) (string-to-number (substring ruta (match-beginning 1) (match-end 1))) (error "no se ha indicado número de verso")))) (find-file "~/Git/Traduccion_Odisea/CANTOS/Odisea.org") (org-show-all) (goto-char (point-min)) ;; buscamos por la propiedad (when (re-search-forward (concat ":Canto:\s+" canto) nil t) (re-search-forward "#\\+begin_verse\\|#\\+BEGIN_VERSE") (save-restriction (org-narrow-to-block) (goto-char (point-min)) (end-of-line) (dotimes (x verso) (re-search-forward "^." nil t)))))) :face '(:foreground "violet" :weight bold :underline t) :export (lambda (ruta desc format) (cond ((eq format 'latex) (let ((canto (if (string-match "\\([[:digit:]]+\\)\\." ruta) (substring ruta (match-beginning 1) (match-end 1)) (error "no se ha indicado número de canto"))) (verso (if (string-match "\\.\\([[:digit:]]+\\)" ruta) (string-to-number (substring ruta (match-beginning 1) (match-end 1))) (error "no se ha indicado número de verso")))) (format "%s.%s (\\vpageref{%s.%s})" canto verso canto verso))))))
Pero, claro, es necesario añadir las etiquetas necesarias en cada verso para que acceda a
ellas varioref
. A tal efecto, escribí otra función que se evalúa, mediante una
variable local, cada vez que guardo el documento con mi traducción. La función busca todos
los enlaces del tipo «od», accede a cada número de canto-verso y añade al final del verso
la etiqueta para varioref
, por ejemplo, \label{3.21}
. Pero, para simplificar, defino
antes una macro de sustitución en mi documento:
La función, entonces, quedaría así:
(defun inserta-label-canto-verso () (save-excursion (goto-char (point-min)) (while (re-search-forward org-any-link-re nil t) (when (string-match-p "od:[[:digit:]]+\\.[[:digit:]]+" (match-string 0)) (let* ((link (org-element-context)) (ruta (org-element-property :path link)) (canto (when (string-match "\\([[:digit:]]+\\)\\." ruta) (substring ruta (match-beginning 1) (match-end 1)))) (verso (when (string-match "\\.\\([[:digit:]]+\\)" ruta) (string-to-number (substring ruta (match-beginning 1) (match-end 1)))))) (save-excursion (org-show-all) (goto-char (point-min)) ;; buscamos por la propiedad (when (re-search-forward (concat ":Canto:\s+" canto) nil t) (re-search-forward "#\\+begin_verse\\|#\\+BEGIN_VERSE") (save-restriction (org-narrow-to-block) (goto-char (point-min)) (end-of-line) (dotimes (x verso) (re-search-forward "\\(^.+$\\)")) (unless (looking-back "{{{lab([[:digit:]]+\\.[[:digit:]]+)}}}") (replace-match (concat "\\1 " "{{{lab(" canto "." (number-to-string verso) ")}}}")))))))))))
Y acto seguido añado como variable local un add-hook
en su modalidad local, para que
sólo tenga efectos en ese documento y no se evalúe la función cada vez que salvo cualquier
otro archivo:
# Local Variables: # eval: (add-hook 'after-save-hook #'inserta-label-canto-verso nil t) # End:
∞
Publicado: 14/10/21
Última actualización: 21/01/22
Esta obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial 4.0 Internacional.
Notas:
A la sombra de esta traducción, por cierto, también escribí este modo menor para
poder desplegar al margen una secuencia de numeración de versos en un bloque verse
de Org.