Función en Emacs para trabajar con el paquete verse
de LaTeX
El paquete verse
de Peter Wilson para LaTeX es muy útil a la hora de trabajar con páginas de poesía o, por ser más
precisos, con versos, sean o no poesía: dilucidar eso último ya es otro cantar que no compete a TeX ni a la tipografía.
Mientras lo dilucidamos, el paquete incluye, entre otras muchas opciones, la posibilidad de alinear automáticamente el
poema entre los dos márgenes verticales de la página, tomando como referencia la anchura del verso más largo. Se trata
de una norma tipográfica que debe emplearse al menos en la versificación «clásica», y que comento también
en esta entrada de mi blog de
Apuntes tipográficos. Pero aquí nos ceñiremos a cuestiones de código.
Si seguimos la documentación del paquete, para que un poema quede perfectamente alineado respecto al verso más largo
centrado en la página, debemos establecer literalmente ese verso como valor de la longitud \versewidth
, a través del
comando \settowidth
. A continuación encerramos el poema dentro de un entorno verse
, que tendrá como argumento
opcional el valor \versewidth
, que se sobre-escribirá con cada poema1. Así, partiendo de las dos primeras estrofas
de la Sonatina de Darío, el esquema sería:
\settowidth{\versewidth}{La princesa está triste... ¿Qué tendrá la princesa?} \begin{verse}[\versewidth] La princesa está triste... ¿Qué tendrá la princesa?\\ Los suspiros se escapan de su boca de fresa,\\ que ha perdido la risa, que ha perdido el color.\\ La princesa está pálida en su silla de oro,\\ está mudo el teclado de su clave sonoro,\\ y en un vaso, olvidada, se desmaya una flor. El jardín puebla el triunfo de los pavos reales.\\ Parlanchina, la dueña dice cosas banales,\\ y vestido de rojo piruetea el bufón.\\ La princesa no ríe, la princesa no siente;\\ la princesa persigue por el cielo de Oriente\\ la libélula vaga de una vaga ilusión. \end{verse}
Nótese que, dentro del entorno verse
cada final de verso ha de marcarse con \\
, salvo el último verso de cada
estrofa.
Función para Emacs
A pesar de que estos comandos simplifican mucho el proceso, si estamos en Emacs siempre podremos ir un poco más lejos. A la larga puede resultar un poco latoso, sobre todo cuando tenemos que componer un libro con muchos poemas, el ir buscando los versos más largos de cada uno. Nada inasumible, por otra parte; lo que ocurre es que Emacs nos vuelve un poco comodones, pero en lugar de quejarnos nos da por pensar si no se podrá escribir una función. En este caso, que realice lo siguiente:
- En un poema señalado (marcado, en la jerga emacsiana) nos busque y copie el verso más largo;
- Nos encierre ese poema dentro del entorno antes descrito, con el valor de ese verso añadido a
\versewidth
.
Pero antes de ponernos a inventar la rueda desde cero, lo recomendable siempre será mirar si no estará ya —como sucede tan a menudo– inventada. Es la salsa del software libre, donde constantemente se reciclan ideas brillantes y no es necesario inventar mil ruedas a un tiempo, pues con una sola que funcione ya basta. Para el caso que nos ocupa, nuestra ansiada rueda era conseguir localizar y —al menos— marcar el verso más largo. Y la teníamos de forma simple y elegante en esta función para buscar y marcar la siguiente línea más larga desde la posición del cursor, que un usuario compartió en la lista de correo de gnu:
(defun goto-longest-line () (interactive) (let ((max-line-start 0) (max-line-length 0)) (goto-char (point-min)) (while (< (point) (point-max)) (let ((start (point))) (forward-line) (let ((length (- (point) start))) (if (< max-line-length length) (setf max-line-length length max-line-start start))))) (goto-char max-line-start) (set-mark (+ max-line-start max-line-length))))
Ya teníamos la rueda. Lo que yo he añadido no es más que la decoración de la rueda, es decir, adaptar esta función para
usarla en el entorno verse
de LaTeX. Y ésta es mi función resultante (más bien dos funciones, una para generar el
entorno verse
y otra para encerrar el poema dentro, con los valores del verso más largo:
1: (defun verso-latex () 2: "Envuelve una región marcada en un entorno verse y añade marcas 3: de verso y separación de 1.2em entre estrofas" 4: (interactive) 5: (if (region-active-p) 6: (progn 7: (save-excursion 8: (goto-char (region-end)) 9: (newline 2) 10: (insert "\\end{verse}")) 11: (save-excursion 12: (replace-regexp "$" "\\\\\\\\" nil (region-beginning) (region-end))) 13: (save-excursion 14: (replace-regexp "\\\\\\\\\n\\\\\\\\" "\n" nil (region-beginning) (region-end))) 15: (save-excursion 16: (goto-char (region-beginning)) 17: (insert "\\begin{verse}") 18: (newline 2))) 19: (nil))) 20: 21: ;; Definir el verso más largo en LaTeX 22: 23: (defun verso-largo-latex () 24: "Envuelve una región marcada en un entorno verse y añade marcas 25: de verso y separación entre estrofas. Extrae el verso más largo 26: de un entorno verse y lo coloca antes de \begin{verse}. Por 27: último, añade el argumento opcional [\versewidth] con el valor 28: del verso más largo" 29: (interactive) 30: (narrow-to-region (region-beginning) (region-end)) 31: (deactivate-mark) 32: (whitespace-cleanup) 33: (goto-longest-line) 34: (copy-region-as-kill (region-beginning) (region-end)) 35: (beginning-of-buffer) 36: (set-mark-command nil) 37: (end-of-buffer) 38: (verso-latex) 39: (deactivate-mark) 40: (widen) 41: (LaTeX-find-matching-begin) 42: (previous-line) 43: (save-excursion 44: (insert "\\settowidth{\\versewidth}{") 45: (yank)) 46: (set-mark-command nil) 47: (end-of-line) 48: (insert "}") 49: (save-excursion 50: (next-line 3) 51: (LaTeX-mark-environment) 52: (replace-string "begin{verse}" "begin{verse}[\\versewidth]" nil (region-beginning) (region-end))))
Naturalmente, debemos incluir antes la función que mencionamos goto-longest-line
, así como requerir AUCTeX, ya que
echamos mano de algunas funciones de este paquete. Para que la función goto-longest-line
actúe sólo en el poema y no
en todo el documento desde el cursor hasta el final (algo que no deseamos que suceda), aislamos nuestro poema marcado,
temporalmente, con un narrow-to-region
. Por otra parte, whitespace-cleanup
(lín. 32) nos resultará muy útil por si
se nos va la mano marcando el poema y nos pasamos algunas líneas blancas. No afecta al resultado final, pero le añade
desaliño. En este vídeo se muestra un poco cómo funciona nuestra nueva y flamante rueda:
Cómo colocar correctamente un poema en la página from Juan Manuel Macías Chaín on Vimeo.
Un bonus para Org Mode
¿Y si queremos exportar un bloque VERSE
desde Org Mode a LaTeX? Pues da la casualidad de que aquí también teníamos
nuestra rueda (o parte de ella) inventada, con una función que sitúa el cursor al principio de un bloque. En el caso de
la función original se trata de un bloque de código. Para que sea un bloque VERSE
, nos basta con modificarla en la
línea 9:
1: ;; Ir a inicio bloque (fuente: 2: ;; https://github.com/kshenoy/dotfiles/blob/master/emacs.org#jump-to-headtail-of-any-block-not-just-src-blocks) 3: 4: (defun my-org-babel-goto-block-corner (p) 5: "Go to the beginning of the current block. 6: If called with a prefix, go to the end of the block" 7: (interactive "P") 8: (let* ((element (org-element-at-point))) 9: (when (or (eq (org-element-type element) 'verse-block) ;; añadimos el bloque verse 10: (eq (org-element-type element) 'src-block) ) 11: (let ((begin (org-element-property :begin element)) 12: (end (org-element-property :end element))) 13: ;; Ensure point is not on a blank line after the block. 14: (beginning-of-line) 15: (skip-chars-forward " \r\t\n" end) 16: (when (< (point) end) 17: (goto-char (if p end begin)) 18: (when p 19: (skip-chars-backward " \r\t\n") 20: (beginning-of-line)))))))
Entonces, partiendo de esa función, no nos es difícil escribir esta otra para exportar desde Org:
(defun verso-largo-org () "extrae el verso más largo de un bloque VERSE y lo coloca para exportar a LaTeX" (interactive) (my-org-babel-goto-block-corner nil) (org-narrow-to-block) (goto-longest-line) (region-active-p) (copy-region-as-kill (region-beginning) (region-end)) (widen) (my-org-babel-goto-block-corner nil) (previous-line) (insert "#+begin_export latex") (newline) (save-excursion (insert "\\settowidth{\\versewidth}{") (yank)) (save-excursion (end-of-line) (insert "}") (newline) (insert "#+end_export")))
Nuestro bloque VERSE
acabaría luciendo entonces tal que así:
#+begin_export latex \settowidth{\versewidth}{La princesa está triste... ¿Qué tendrá la princesa?} #+end_export #+begin_verse La princesa está triste... ¿Qué tendrá la princesa? Los suspiros se escapan de su boca de fresa, que ha perdido la risa, que ha perdido el color. La princesa está pálida en su silla de oro, está mudo el teclado de su clave sonoro, y en un vaso, olvidada, se desmaya una flor. El jardín puebla el triunfo de los pavos reales. Parlanchina, la dueña dice cosas banales, y vestido de rojo piruetea el bufón. La princesa no ríe, la princesa no siente; la princesa persigue por el cielo de Oriente la libélula vaga de una vaga ilusión. #+end_verse
Estrambote: una consideración final
Téngase en cuenta, dicho todo lo anterior, que estamos en Emacs y que (muy probablemente) usaremos allí una fuente mono-espaciada, en mi caso la DejaVu Sans Mono, de la que soy devoto. Esto quiere decir que, en unos (por fortuna) pocos casos), el verso más largo en la fuente de Emacs no será el mismo que el verso más largo en la fuente de anchura variable de nuestra salida tipográfica tras la compilación con LaTeX. Habrá que estar al tanto y, si es necesario, hacer una enmienda manual de versos.
∞
Publicado: 22/05/2019
Última actualización: 16/08/23
Esta obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial 4.0 Internacional.
Notas:
En este argumento opcional podemos incluir otras longitudes que se nos antojen, no sólamente \versewidth
. Si el
poema, por ejemplo, contiene versos que ocupan varias líneas, no tendría sentido declarar el valor del verso más largo,
ya que éste equivaldría al ancho de la caja de texto. En tal caso, la longitud elegida ha de ser \textwidth
. El
paquete verse
compondrá esos versos como un párrafo normal y corriente, sólo que dejará sangrada la última línea.