Curso no convencional de LaTeX: nuestras propias macros

Hoy vamos a salir de mi zona de confort y hablar sobre la creación de macros, es decir, de nuevos comandos y entornos1. No soy ninguna experta en esto, pero hay un par de ideas que me parece que hay que tener claras a la hora de definir cosas en LaTeX. Básicamente voy a contar lo que me hubiera gustado que me contaran cuando empecé con esto, más que nada para no copiar de StackOverflow a ciegas.

Lo primero y más importante que tenemos que saber a la hora de jugar con las macros en LaTeX es que tenemos dos opciones2:

  • Crear un entorno o comando desde cero. Así conseguimos que LaTeX haga algo que no hacía o guardamos un conjunto de órdenes que usamos a menudo en una macro con el objetivo escribir menos. La palabra clave para esto es new.

  • Pisar un entorno o comando existente. En este caso la idea es modificar el comportamiento de cierto comando o entorno a nuestro gusto. Se conoce como renew.

El siguiente concepto en orden de importancia es que podemos (re)definir comandos en cualquier parte del documento, pero para tener todo perfectamente organizado es preferible hacerlo en el preámbulo.

Veamos entonces como crear comandos y entornos nuevos y modificar los existentes. Voy a intentar que todos los ejemplos resuelvan problemas reales, que no sean de juguete.

Escribir comandos

Han ido apareciendo comandos nuevos3 y trucados4 anteriormente, ¡hoy llega por fin la explicación que os debía! Primero vamos a fabricar comandos nuevecitos, luego modificaremos alguno que ya existe para que sea más divertido.

Comandos nuevos

Definir comandos nuevos en LaTeX es sencillo, solo debemos seguir la siguiente estructura:

\newcommand{COMANDO}[ARGUMENTOS]{DEFINICIÓN}

donde:

  • COMANDO será el nombre del comando que queramos definir. Empezará por \. Solo podemos usar letras para bautizarlo.

  • ARGUMENTOS será el número de argumentos entre 0 y 9 que le pasaremos al comando. Como veis, que un comando tenga argumentos es opcional.

  • DEFINICIÓN será donde escribiremos lo que hace el comando. Haremos referencia a los diferentes argumentos mediante # seguida del número correspondiente.

Veamos un ejemplo. Vamos a crear un comando que nos escriba Figura X en lugar de X cuando hagamos referencia a cierta figura:

\newcommand{\figref}[1]{\figurename~\ref{#1}}

Analicémoslo:

  • El nombre del nuevo comando es \figref{} y tiene un único argumento, la etiqueta de la figura, a la que hacemos referencia gracias a nuestro viejo conocido \ref{}.

  • \figurename es el comando que guarda el nombre de las figuras5. Podríamos escribir Figura a mano, pero si cambiamos el idioma tendríamos que cambiar también la definición. De este modo LaTeX, sustituye \figurename por el nombre de la figura según le mande el paquete de idioma.

  • Usamos un espacio duro entre el nombre y el número para que LaTeX no meta en medio un salto de línea o de página.

Nuestra nueva macro se usa exactamente igual que cualquier otro comando:

\begin{figure}[H]
  \includegraphics[width=0.7\textwidth]{Figuras/esquema.eps}
  \caption{Esquema del proceso}
  \label{fig:esquema}
\end{figure}

Como vemos en la \figref{fig:esquema}...

% Equivalente a 
Como vemos en la Figura~\ref{fig:esquema}...

Un tema interesante a la hora de definir comandos es la inclusión de argumentos por defecto en la definición del mismo:

\newcommand{COMANDO}[ARGUMENTOS][DEFECTO]{DEFINICIÓN}

donde DEFECTO es el valor que tomará el argumento opcional si no se especifica. El argumento opcional siempre es el primero.

Un ejemplo de uso podría ser un texto matemático en el que hagamos referencia al plano real a menudo pero tal vez nos haga falta alguna vez hablar de un espacio de dimensión mayor. Para ello podemos definir un comando que nos escriba la R molona esa y que por defecto el espacio sea bidimensional, pero podamos cambiarlo opcionalmente:

\usepackage{amssymb}
\newcommand{\R}[1][2]{\mathbb{R}^{#1}}

A la hora de usarlo le pasamos el argumento opcional cuando lo necesitamos:

% Espacio bidimensional
$\R$

% Espacio tridimensional
$\R[3]$

Comandos trucados

Hemos dicho al principio que además de crear nuestros propios comandos podemos modificar el comportamiento de alguno existente. Para ello usamos \renewcommand en lugar de \newcommand con la misma sintaxis:

\renewcommand{COMANDO}[ARGUMENTOS]{DEFINICIÓN}

donde:

  • COMANDO será el nombre del comando que queramos modificar.

  • ARGUMENTOS será el número de argumentos, igual que antes.

  • DEFINICIÓN será la nueva definición del comando.

Como ejemplo de esta sección, vamos a usar \renewcommand para evitar tener que activar el modo matemático cuando escribamos fracciones. Con este fin vamos a echar mano de [\ensuremath{}], que nos permite usar comandos matemáticos dentro y fuera de las ecuaciones6.

Como vamos a crear la nueva definición a partir del propio comando, necesitamos guardarlo en otro sitio primero para que la definición no sea recursiva. En este menester nos ayuda el comando [\let], que sirve para copiar el contenido de un comando en uno nuevo:

\let\comandoNuevo=\comandoViejo

Juntando las piezas, tenemos lo siguiente:

% Guardamos la definición original
\let\oldfrac=\frac
% Modificamos \frac para que funcione fuera de ecuaciones
\renewcommand{\frac}[2]{\ensuremath{\oldfrac{#1}{#2}}}

Ahora podemos usar \frac directamente en el texto.

Escribir entornos

¡Ya sabemos crear y cambiar comandos! Vamos a dar un paso más y hacer los mismo para los entornos.

Entornos nuevos

La sintaxis para la definición de entornos nuevos es muy similar a la de los comandos, usando ahora \newenvironment:

\newenvironment{ENTORNO}[ARGUMENTOS]{ANTES}{DESPUÉS}

En ANTES escribiremos el grupo de comandos que hay que ejecutar al iniciar el entorno y, por tanto, los que le darán el formato al mismo, y DESPUÉS, los que se activarán tras el texto. El resto de elementos funciona como antes.

De esta manera, podemos definir un entorno para poner notas en el texto. Yo he creado uno que rodea el texto de la nota con dos rayas (\hrule), una por debajo y una por encima, y que nos permite darle un título, que aparecerá en negrita:

\newenvironment{nota}[1]
  {\vspace{1ex}\hrule\textbf{#1}}
  {\vspace{1ex}\hrule}

Este entorno nuevecito y reluciente se usa en el cuerpo del documento como cualquier otro:

\begin{nota}{¡Cuidado!}
  Hay que tener en cuenta que
\end{nota}

Un tema interesante son los contadores gracias a los cuales podremos fabricar entornos numerados. Los contadores tiene la estructura \theELEMENTO. Así, \thepage contiene el número de página, \thechapter7 el número de capítulo y \theNOMBRE el número del elemento numerado que hayamos creado.

Para crear un contador usamos el comando \newcounter, le damos un nombre y, opcionalmente, le decimos dónde debe reiniciar la cuenta:

\newcounter{NOMBRE}[REINICIO]

El tema del reinicio es interesante para los documentos largos, así podemos empezar a contar al iniciar un capítulo y hacer referencia al elemento mediante \thechapter.\theNOMBRE que nos escribirá el número del capítulo seguido del número del elemento. Con el ejemplo que viene a continuación se entenderá mejor, espero.

Luego, incrementamos el valor del contador cuando sea necesario con:

  • \stepcounter{CONTADOR}: incrementa en uno el valor de CONTADOR.

  • \refstepcounter{CONTADOR}: incrementa en uno el valor de CONTADOR y nos permite usarlo en las referencias cruzadas.

  • \addtocounter{CONTADOR}{NÚMERO}: incrementa CONTADOR en un valor que le pasemos.

Una idea que se me ocurre para hacer uso de esta funcionalidad es crear un entorno numerado para poner ejemplos en el texto cuya numeración se reinicie al cambiar de sección:

% Creamos un nuevo contador que se reinicie al cambiar de sección
\newcounter{ejemplo}[section]
% Incrementamos en uno el contador al iniciar el nuevo entorno
% Accedemos a su contenido con \theejemplo
\newenvironment{ejemplo}
  {\refstepcounter{ejemplo}\vspace{1ex}\hrule\textbf{Ejemplo~\thesection.\theejemplo}}
  {\vspace{1ex}\hrule}

Así, si escribimos algo de este estilo:

\section{Entorno numerado}
  \begin{ejemplo}
    Un primer ejemplo
  \end{ejemplo}

  \begin{ejemplo}
    Un segundo ejemplo
  \end{ejemplo}

Conseguiremos lo siguiente:

Entornos numerados

Entornos trucados

Al igual que modificábamos comandos existentes con \renewcommand, podemos cambiar entornos con \renewenvironment:

\renewenvironment{ENTORNO}[ARGUMENTOS]{ANTES}{DESPUÉS}

Lo que tenemos que tener en cuenta aquí es la implementación original del entorno que vamos a cambiar. A mí me ayuda pensar en un entorno como dos comandos, uno que da inicio al formato concreto y otro que lo finaliza. Es decir, esto:

\begin{equation}
  a^2 x + b x + c = 0
\end{equation}

es equivalente a:

\equation
  a^2 x + b x + c = 0
\endequation

De esta manera me resulta más sencillo saber qué hay que escribir en los argumentos ANTES y DESPUÉS de los que hablaba.

Para terminar con los entornos os dejo con un ejemplo complejo que monté juntando piezas de aquí y de allí para que las citas aparecieran en gris oscuro con una barrita gris clara a la izquierda. Es complicadillo y yo misma no sé si lo entiendo muy bien, pero es para que veáis un caso real:

\usepackage{framed}

% Redefinir leftbar
\renewenvironment{leftbar}[1][\hsize]
  {\color{gray}
    \def\FrameCommand
    {{\color{lightgray}\vrule width 3pt}}
    \MakeFramed{\hsize#1\advance\hsize-\width\FrameRestore}
  }
  {\endMakeFramed}

% Guardar entorno quote, lo forman dos comandos
\let\oldquote=\quote
\let\oldendquote=\endquote

% Barra vertical a la izquierda de la cita
\renewenvironment{quote}
  {\vspace{10pt}\leftbar\vspace*{-6pt}\oldquote}
  {\oldendquote\endleftbar\vspace{10pt}}

En fin, creo que la única manera de aprender a modificar entornos es modificar entornos así que no queda más remedio que practicar.

Una nota sobre TeX

En el principio de los tiempos dijimos que LaTeX es un conjunto de macros escritos en TeX (o Plain TeX) ¿recordáis? Esto provoca que LaTeX tenga algunas limitaciones a la hora de definir cosas, limitaciones que TeX, al ser de más bajo nivel, no tiene.

El comando \let que hemos usado para guardar la definición original de un comando que íbamos a modificar pertenece a TeX. También [\def] que aparece en ejemplo de las citas personalizadas es parte de TeX y sirve para definir comandos nuevos, al igual que \newcommand8. Os hablo de ellos porque los veréis a menudo cuando busquéis ejemplos por ahí.

En definitiva, ¿qué hay que saber?

Diría que lo más importante es saber la diferencia entre definir (\new) y pisar (\renew) un comando o entorno existente y cuándo hay que hacer lo uno o lo otro. Tampoco está de más recordar que escribimos tanto las definiciones como las modificaciones en el preámbulo. Igualmente, nos viene bien saber de la existencia de comandos de TeX como \let y \def que nos hacen la vida más fácil.

Para acabar, os dejo mi proceso para crear macros:

  1. Escribo mi combinación de comandos en el cuerpo del documento y verifico que funciona.

  2. Escribo cómo quiero que sea mi comando o entorno final y lo comparo con mi combinación de comandos.

  3. Traslado la combinación al preámbulo y le doy forma según la sintaxis correspondiente.

  4. Extraigo los argumentos y pienso si puedo darle un valor por defecto a alguno de ellos.

  5. Pruebo si funciona.

Lo dicho, a escribir macros se aprende escribiendo macros. ¡Dadle duro!

Referencias

LaTeX example: How to create your own commands with newcommand

LaTeX/Macros en Wikibooks

\newcommand with arguments in LaTeX

Plain TeX vs. LaTeX Macros en TeXExchange

LaTeX/Plain TeX en Wikibooks

List of higher-level LaTeX commands corresponding to TeX commands en TeXExchange

What is the difference between \def and \newcommand? en TeXExchange


Escribí esta entrada oyendo:


  1. ¡Líos de nomenclatura a la vista! Dijimos hace mucho que LaTeX es un conjunto de macros para TeX. Luego hemos separado estas macros en comandos y entornos, pero un entorno no deja de ser un conjunto de comandos que afecta de forma local. Llamaremos también macro a los comandos (y por extensión entornos) que definamos nosotros, tal y como se suele hacer en el mundillo. 
  2. Para ser sinceros también está \providecommand, que crea el comando si no existe y si no ignora la definición, pero no tiene un primo para los entornos
  3. Cuando aprendimos a escribir ecuaciones vimos un truco para no tener que escribir la palabra Ecuación a la hora de referenciar. 
  4. Cuando hablamos del idioma vimos cómo modificar el nombre de las tablas. 
  5. Del mismo modo, el nombre de los capítulos se guarda en \chaptername y el de las tablas en \tablename. Cuidado porque no todos los elementos siguen este patrón, de hecho, \sectionname no existe. 
  6. Ahora no nos vengamos arriba y nos pongamos usar \ensuremath{} a mansalva. Aquí hay algunos criterios. 
  7. Uniéndolo con lo que hemos dicho anteriormente, \thechapter contiene el número del capítulo, \chaptername su nombre y \chaptermark el título. 
  8. Se pueden declarar comandos nuevos dentro de entornos de manera similar a declararlos de manera independiente. Aquí tenéis más información. 
Anuncios

¡Opina sin miedo! (Puedes usar Markdown)

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s