Macros en org-mode
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á:
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.
Comentarios