Cuaderno de GNUtas

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:

#+MACRO: lab @@latex:\label{$1}@@

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:

canto-verso1.png

Figura 1: Enlace personalizado en Org y referencia cruzada en LATEX con el paquete varioref

Publicado: 14/10/21

Última actualización: 21/01/22


Índice general

Acerca de...

Esta obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial 4.0 Internacional.

Notas:

1

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.

© Juan Manuel Macías
Creado con esmero en
GNU Emacs