Cuaderno de GNUtas

Inline tasks en Org Mode como secciones anónimas

Lo que en Org Mode se conoce con el poco atractivo y algo confuso término de inline tasks («tareas integradas», podríamos traducir de urgencia), es un elemento que depara muchas posibilidades de uso, si bien parece que no recibe la atención merecida por parte de los usuarios, incluso de aquellos más veteranos. Intentaremos contribuir desde aquí a invertir esa tendencia mostrando un aprovechamiento que nos resulta bastante feliz. Pero antes no está de más refrescar un poco la memoria sobre en qué consiste el elemento que nos ocupa.

Las inline tasks, en efecto, y por decirlo en dos palabras, no son otra cosa que nodos de Org desprendidos de la estructura en árbol del documento. O sea, carecen de un nivel determinado, pero sí pueden tener una marca de cierre, convirtiéndolas en una suerte de entorno. Comparten con los nodos normales, además, la posibilidad de añadir título, propiedades, estados «TODO», etc. Org reconoce de oficio una inline task cuando se alcanza cierta profundidad en los niveles de encabezados, cifra que viene definida por la variable org-inline-task-min-level, que por defecto es 15. Por supuesto, no hace falta degradar un encabezado quince veces para obtener una inline task en cualquier parte de nuestro documento. Bastaría con pulsar la secuencia C-c C-x t (org-inlinetask-insert-task). Y nuestra tarea integrada aparecería con un aspecto parecido a éste, dispuesta a recibir el contenido con que queramos dotarla:

***************
*************** END

Podemos introducir un título, un estado «TODO», un cajón de propiedades, una etiqueta y, claro está, el texto.

*************** TODO Título de mi tarea integrada      :etiqueta:
:PROPERTIES:
:propiedad: valor
:END:
Aquí un poco de contenido...
*************** END

Es decir, exactamente igual que en cualquier otro nodo, con la salvedad del cierre estilo entorno y de que nos hallamos fuera de los niveles de encabezado, de árboles y subárboles. Y es precisamente ese rasgo desprendido de la arborescencia de nuestro documento lo que propicia que podemos usar las tareas integradas para crear secciones anónimas, es decir, aquellos epígrafes que en un libro no llevan título y suelen separarse por algún carácter o juego de caracteres especiales, generalmente tres asteriscos. La ventaja que comporta hacerlo así frente a introducir un simple carácter de separación es evidente: de esta forma podemos tener esas secciones anónimas convenientemente parceladas, como verdaderas secciones que son.

Para obtener todo eso necesitaremos definir el código necesario para LATEX y un algo de código en Elisp. Partiremos, de momento, de dos posibles condiciones dependiendo de si la salida es a LATEX o a odt.

El código para LATEX

Necesitamos definir primero el carácter delimitador, cuidándonos de que no se produzcan cortes de página indeseados y asegurando de que nunca comience una página con esa marca. Posteriormente definiremos un simple entorno, que es a lo que queremos exportar nuestras inline tasks.

Como dijimos, la marca habitual para separar las secciones anónimas es una serie de tres asteriscos algo separados, lo que en la tradición tipográfica anglosajona se conoce como dinkus:

\newcommand\dinkus{\mbox{\textasteriskcentered\space\textasteriskcentered\space\textasteriskcentered}}

Podremos en un futuro definir más marcas, pero por comodidad ésta es la que asociaremos por defecto al siguiente comando que vamos a definir:

\newcommand\anonsectionmark{\dinkus}

Es el turno del comando que creará la separación para las secciones anónimas:

El comando que crea la separación anónima. Utilizamos, para evitar los cortes de página indeseados, la función \Needspace* del paquete needspace (https://www.ctan.org/pkg/needspace).

\newcommand\anonsectionbreak{%
  \nopagebreak[4]
  \bigskip%
  {\centering
  \anonsectionmark\par}
  \Needspace*{2\bigskipamount}
  \bigskip}

Y, por último, el entorno para delimitar las secciones anónimas:

\newenvironment{anonsection}{%
\anonsectionbreak%
}
{%
\par}

El código Elisp para Org

Lo primero de todo, debemos activar nuestro elemento en Org, ya que no viene disponible de fábrica. Basta con añadir a nuestro ~/.emacs la línea:

(require 'org-inlinetask)

Las inline tasks se exportan por defecto a LATEX como un entorno minipage, y a odt y a html como marcos. Por suerte, Org dispone de una serie de variables para asociar nuestras funciones personalizadas de exportación para estos elementos. Como aquí lo que nos interesa la salida a LATEX y a odt, debemos fijarnos en las variables org-latex-format-inlinetask-function y org-odt-format-inlinetask-function, respectivamente.

Pero no queremos que todas nuestras inline tasks se exporten invariablemente como secciones anónimas; sólo aquellas que contengan en el título (que no se exportará) la cadena de texto «anonsec». Con esa condición definimos nuestra función de exportación a LATEX:

(defun my-org-latex-format-inlinetask-default-function
    (todo _todo-type priority title tags contents _info)
  (if (string-match-p "anonsec" title)
      (concat
       "\n\\begin{anonsection}\n"
       (org-string-nw-p contents)
       "\n\\end{anonsection}\n")
    (org-string-nw-p contents)))

Y configuramos la variable correspondiente con la función anterior.

(setq org-latex-format-inlinetask-function 'my-org-latex-format-inlinetask-default-function)

Lo mismo, pero para la exportación a odt:

(defun mi-org-odt-format-inlinetask-default-function
    (todo todo-type  priority name tags contents)
  (if (string-match-p "anonsec" name)
      (concat
       contents
       "<text:p text:style-name=\"OrgCenter\">* * *</text:p>")))

Y, de nuevo, asociamos la función a su variable para la salida a odt:

(setq org-odt-format-inlinetask-function 'mi-org-odt-format-inlinetask-default-function)

Probando el código

Ya sólo nos queda probar nustro código. Por ejemplo, usando el paquete lipsum para LATEX (el resultado de la exportación, en la fig. 1):

@@latex:\lipsum[1]@@

*************** anonsec

@@latex:\lipsum[1-2]@@

*************** END

*************** anonsec

@@latex:\lipsum[5-6]@@

*************** END

*************** anonsec

@@latex:\lipsum[7]@@

*************** END

dinkus.png

Figura 1: Seccinones anónimas en LATEX, separadas por un dinkus

Por supuesto, por el lado de LATEX podemos ingeniárnoslas para obtener caracteres de separación más vistosos. Gracias al paquete pgfornament (https://www.ctan.org/pkg/pgfornament), redefinimos nuestra marca con el ornamento que se muestra en la fig. 2).

\renewcommand{\anonsectionmark}{\pgfornament[scale=.122]{3}}

anonsec_pgfornament.png

Figura 2: Secciones anónimas separadas por una floritura del paquete pgfornament

A modo de conclusión

Este pequeño hacking, además de buscarle una ocupación más especializada a las poco ubicables —a veces— tareas integradas de Org, pone de manifiesto, una vez más, algo que nos parece esencial en nuestro querido modo del unicornio, tan difícil siempre de definir. Org Mode no es, en efecto, tanto un simple lenguaje de marcas ligeras al estilo de Markdown u otros similares, cuanto una casi infinita batería de recursos y triquiñuelas. Es extensible porque GNU Emacs es extensible. La magia, por tanto, está en Emacs. Como lenguaje de marcas ligeras Org no es ni mejor ni peor que Markdown. Y, por otra parte, con sólo un lenguaje de este tipo no se va demasiado lejos cuando se trata de documentos con la complejidad que aporta la «vida real». La pulpa está en el pre- y postproceso, algo que Org ofrece de una manera consistente e imbricada con asombrosa coherencia dentro del gran ecosistema de Emacs. Org es, en suma, una interfaz —más que un lenguaje— para Emacs. Y ELisp, siempre, tras bambalinas.

Publicado: 18/01/22

Última actualización: 07/08/22


Índice general

Acerca de...

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

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