Notxor tiene un blog

Defenestrando la vida

Macros en org-mode

Notxor
2022-11-25

Gracias a las preguntas que me hacen algunos usuarios me doy cuenta de que no siempre me explico con toda claridad y que, muchas veces, doy por sentado que las cosas simples las conoce todo el mundo. No obstante, puesto que mi información proviene de leerme el manual, entiendo a quien prefiere remitir al preguntón a leérselo. Sin embargo, mi inclinación siempre es responder con algo más sustancial que un «lee el manual». También porque me sirve de excusa para escribir algo en el blog y tenerlo en barbecho el mínimo tiempo posible. En este artículo responderé a unas preguntas básicas que un nuevo usuario de Emacs me hace, sobre el uso de org-mode, específicamente la capacidad de utilizar macros para introducir texto repetitivo, también para explicar para qué pueden servir, o se pueden utilizar, las propiedades de los apartados y demás cosas relacionadas con las «macros».

Puesto que hablar en abstracto es complicado, me vais a permitir poner un ejemplo de buffer org-mode con una serie de macros, para luego explicarlos más detenidamente. El código del ejemplo sería el siguiente:

#+title: Expansión de macros
#+author: Notxor
#+etiquetas: emacs, org, macro
#+macro: autores yo, mí, me y conmigo
#+macro: hoy (eval (format-time-string (or $1 "%Y-%m-%d")))

* Hoy es {{{hoy}}}
:PROPERTIES:
:numero:   42
:END:

Los /macros de la página/:

1. *Título*: {{{title}}}
2. *Autor*: {{{author}}}
3. *Etiquetas*: {{{keyword(etiquetas)}}}
4. *Lista de autores*: {{{autores}}}
5. *Propiedad /numero/*: {{{property(numero)}}}
6. *Fecha de hoy*: {{{hoy(%A\, %d de %B de %Y)}}}
7. Llamamos al /contador/ {{{n(contador)}}} vez y {{{n(contador)}}}
   veces.
8. Y tener varios contadores con varios nombres: {{{n(otro)}}} vez,
   {{{n(otro)}}} veces, {{{n(otro)}}} veces y el otro contador también
   {{{n(contador)}}} veces.

* Otra cabecera
:PROPERTIES:
:numero:   37
:END:

Aquí el /número/ es {{{property(numero)}}}.

El resultado del código anterior al exportar a html será:

captura-expansion-macros.png

Viendo la imagen y el código que la genera, se puede explicar mejor cómo funcionan las macros:

Para empezar, se deben meter entre llaves triples, tal que {{{macro}}} se sustituye por el valor de #+macro: en algunos casos, como para title o author. Sin embargo, en los que definimos nosotros se debe emplear la sintaxis {{{keyword(macro)}}}. Se puede expresar la explicación también al revés, en las primeras se utiliza una forma abreviada que expresa {{{keyword(title)}}} o {{{keyword(author)}}}.

También podemos definir nuestros propios macros utilizando la sintaxis:

#+macro: nombre cuerpo

En el cuerpo los valores expresados coo $1, $2... $n son argumentos que puede recibir, finalmente se forma una cadena con la que sustituir la macro. Por otro lado, también se puede utilizar cualquier forma elisp cuya evaluación resulte en una cadena de texto. En el ejemplo anterior vemos que se ha definido una macro de la siguiente manera:

#+macro: hoy (eval (format-time-string (or $1 "%Y-%m-%d")))  

Dicho macro nos devuelve la fecha de hoy dándonos la oportunidad de especificar un formato, que se puede pasar en un parámetro o en su defecto se utilizar el formato ISO «año-mes-día». En el ejemplo de documento anterior se muestra que se utiliza con un simple {{{hoy}}} devolviendo la fecha en formato ISO, pero en el punto 6 de la lista inferior se utiliza un formato introduciendo el parámetro entre paréntesis. A propósito se ha introducido en éste una coma que debe estar escapada. Si no lo hacemos así nos lanzará un error al interpretar que hay dos parámetros, puesto que en la llamada, entre paréntesis se utiliza el caracter , como separador.

Es decir, tenemos que fijarnos en que la cadena no está encerrada entre comillas ni se utiliza delimitador alguno, si necesitamos varios parámetros debemos separarlos mediante comas. Es aconsejable juguetear un poco con esto para acostumbrarnos al modo de funcionamiento, similar a otros lenguajes, pero muy distinta a como funciona elisp.

También podemos apreciar que se pueden sustituir macros con los valores de las propiedades. En el punto 5 se sustituye {{{property(numero)}}} por el valor definido como propiedad en la primera cabecera. Con posterioridad, en el siguiente apartado, se ha modificado el valor de la propiedad del mismo nombre y por tanto también la sustitución. Por tanto, podemos utilizar las properties de los distintos encabezados para agrupar expresiones o datos de manera que al cambiar el valor de una propiedad, cambiará en texto en todas las apariciones de la macro al hacer la exportación.

Por último, mencionar que se pueden tener contadores, por ejemplo, para realizar enumeraciones más allá de lo que son las listas numeradas o las entradas de titulares. No es algo que haya utilizado mucho y por tanto sólo puedo remitir al lector a la documentación si necesita esta funcionalidad más que yo.

Conclusiones

No hay mucho más que explicar y el funcionamiento es muy sencillo. Si no lo has usado nunca, seguramente es porque no lo conocías. Después de conocerlo, seguro que se te ocurren varias formas de utilización que te ahorrarán trabajo.

Categoría: emacs org-mode

Comentarios

Debido a algunos ataques mailintencionados a través de la herramienta de comentarios, he decidido no proporcionar dicha opción en el Blog. Si alguien quiere comentar algo, me puede encontrar en Mastodon y en Diaspora con el nick de Notxor.

También se ha abierto un grupo en Telegram (enlace de invitación al grupo), para usuarios de esa red.

Disculpen las molestias.