> For the complete documentation index, see [llms.txt](https://overleaf-pro.ayaka.space/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://overleaf-pro.ayaka.space/latex/es/articulos-en-profundidad/09-an-introduction-to-luatex-part-2-understanding-directlua.md).

# Una introducción a LuaTeX (Parte 2): Entendiendo \directlua

## El objetivo de este artículo

En la primera parte de este artículo, [Introducción a LuaTeX (Parte 1): ¿Qué es y qué lo hace tan diferente?](/latex/es/articulos-en-profundidad/07-an-introduction-to-luatex-part-1-what-is-it-and-what-makes-it-so-different.md), revisamos brevemente LuaTeX como un motor TeX extremadamente versátil: un sistema de composición tipográfica sofisticado y programable que proporciona una amplia gama de herramientas para construir soluciones de ingeniería y producción documental.

En esta entrega final, examinamos de cerca el componente más vital del conjunto de herramientas de LuaTeX: el `\directlua` comando, que proporciona la “puerta de entrada” al control programático de la composición tipográfica de LuaTeX a través del lenguaje de programación Lua.

Sin embargo, aprovechar plenamente LuaTeX mediante `\directlua` requiere algunos conocimientos previos de varios temas de TeX: los tokens de TeX, las listas de tokens y el mecanismo de expansión. El objetivo de este artículo es explorar y explicar estos conceptos fundamentales de TeX: reconstruyendo los procesos relacionados con TeX detrás de `\directlua` para desarrollar una comprensión de cómo funciona y proporcionar las bases sobre las cuales construir tus propias soluciones de composición tipográfica usando LuaTeX.

Este artículo incluye numerosos ejemplos breves para demostrar y explicar aspectos clave de `\directlua`del comportamiento de, evitando deliberadamente código demasiado complejo en favor de fragmentos de código breves. Cuando es necesario, los ejemplos utilizan TeX básico (raw/plain)—aunque la mayoría de la gente usa y prefiere LaTeX (macros), los comandos básicos de TeX tienen la ventaja de la simplicidad.

## Introducción a Lua en LuaTeX

[Lua](https://www.lua.org/about.html) es un lenguaje de programación de scripts cuyo [código fuente](https://www.lua.org/download.html) es altamente portable y fácil de incrustar en aplicaciones de software, permitiendo a los desarrolladores incorporar capacidades de scripting en sus programas. Lua se ha integrado en [muchas aplicaciones](https://en.wikipedia.org/wiki/List_of_applications_using_Lua) y es una opción popular dentro de la industria del desarrollo de videojuegos—quizás el ejemplo más famoso sea [World of Warcraft](https://wowwiki.fandom.com/wiki/Lua_functions).

LuaTeX, como su nombre sugiere, es un motor TeX que incorpora el lenguaje de programación Lua, proporcionando a los usuarios la capacidad de controlar el comportamiento de composición tipográfica de LuaTeX incluyendo programas Lua (scripts) en sus documentos. Además del control directo de LuaTeX, los usuarios pueden aprovechar Lua puramente como un lenguaje de programación muy capaz para realizar tareas que podrían ser extremadamente difíciles de lograr usando el lenguaje TeX, que es, por cualquier medida justa, un desafío aprender y dominar. Mediante la adición e integración de Lua, LuaTeX se convierte en un motor TeX muy versátil y potente que admite directamente dos lenguajes de programación.

### Usando Lua y TeX en tu documento: introduce \directlua

Lua y TeX son dos *muy diferentes* lenguajes de programación: Lua se parece mucho más a lo que la mayoría de la gente considera un lenguaje de programación, pero TeX, con sus códigos de categoría, tokens, macros y mecanismo de expansión, está muy alejado de las experiencias/expectativas de la mayoría de las personas sobre un lenguaje en el que escribir programas. Sin embargo, como ha demostrado la historia, el lenguaje TeX ha perdurado porque es bueno en lo que fue diseñado para hacer: controlar la composición tipográfica, aunque su modo de funcionamiento sea algo arcano.

Para abordar el desafío de mezclar los lenguajes Lua y TeX en un único documento TeX, los desarrolladores de LuaTeX introdujeron un nuevo comando llamado `\directlua` que es la vía para usar Lua, tanto como lenguaje de programación independiente por derecho propio como para controlar el comportamiento de composición tipográfica de LuaTeX.

El `\directlua` comando permite a los usuarios incrustar código Lua en sus documentos TeX; ese código se pasa posteriormente al intérprete de Lua incorporado de LuaTeX. Sin embargo, `\directlua` también te permite *combinar* el código Lua y (La)TeX juntos, dentro del mismo `\directlua` comando—aunque eso introduce complejidades adicionales debido a las diferencias fundamentales entre Lua y los lenguajes de programación basados en TeX. El desafío clave al usar una combinación de (La)TeX y código Lua es garantizar que esos dos lenguajes coexistan pacíficamente y no se “estorben” mutuamente.

`\directlua` está mejor adaptado para usarlo con fragmentos más cortos de código Lua en el documento, pero puedes usarlo con programas Lua más extensos si lo deseas. En general, los programas Lua más sustanciales y las bibliotecas de código Lua se guardan en archivos externos que pueden cargarse usando la `dofile()` función dentro de un `\directlua` comando. Desde el punto de vista del procesamiento de TeX, una ventaja significativa de usar archivos externos de código Lua es evitar las complicaciones que surgen del mecanismo de códigos de categoría de TeX, un tema explorado en profundidad en este artículo.

### Descripción más formal de \directlua

El [Manual de referencia de LuaTeX](http://www.pragma-ade.com/general/manuals/luatex.pdf) describe `\directlua` de la siguiente manera (ligeramente modificado):

> Para fusionar código Lua con la entrada de TeX, se necesitan algunos nuevos primitivos. El primitivo `\directlua` se usa para ejecutar código Lua de inmediato. La sintaxis básica es `\directlua{⟨code⟩}`. El `⟨code⟩` se expande por completo y luego se introduce en el intérprete de Lua. Después de la lectura y de aplicar la expansión a la `⟨code⟩`, la lista de tokens resultante se convierte en una cadena como si se mostrara usando `\the\toks`.

Por supuesto, esto es técnicamente correcto, pero quizá no sea tan fácil de entender sin algunos conocimientos de procesos de TeX de nivel inferior, como los tokens y la expansión.

## Entendiendo \directlua: ¿Qué temas veremos?

En este artículo examinaremos con más detalle algunos temas clave de fondo y ofreceremos varios ejemplos diseñados para demostrar cómo `\directlua` funciona y dónde (o por qué) debes tener cuidado al combinar TeX y Lua en tu `⟨code⟩`.

Exploraremos los siguientes temas con suficiente detalle para proporcionar una base para entender `\directlua` y su “preprocesamiento” del código que usas dentro de él:

* códigos de categoría y tokens de TeX: convertir texto en tokens y tokens en texto;
* el proceso de expansión de TeX (y cómo impedir la expansión);
* secuencias/mecanismos de escape de Lua para caracteres y cadenas;
* usar comentarios al estilo de Lua;
* una breve introducción a la API de Lua de LuaTeX.

Si entiendes cómo los motores TeX crean y usan tokens y desarrollas una comprensión del mecanismo de expansión de TeX, entonces tendrás las bases necesarias para desbloquear la increíble versatilidad de LuaTeX’s `\directlua` comando.

## Los fundamentos: del texto a los tokens y de los tokens al texto

Overleaf ha publicado varios artículos que analizan en profundidad los tokens de TeX y conceptos relacionados, así que no repetiremos todo ese material aquí; en su lugar, describiremos esas áreas/temas relevantes para desarrollar una mejor comprensión de `\directlua`.

Aquí tienes una lista de artículos publicados anteriormente que pueden ser de interés:

* [¿Qué es un token de TeX?](/latex/es/articulos-en-profundidad/53-what-is-a-tex-token.md)
* [¿Qué es una lista de tokens de TeX?](/latex/es/articulos-en-profundidad/54-what-is-a-tex-token-list.md)
* [¿Cómo funciona \expandafter? Una introducción a los tokens de TeX](/latex/es/articulos-en-profundidad/19-how-does-expandafter-work-an-introduction-to-tex-tokens.md)
* [Una serie de seis partes: ¿Cómo funcionan realmente las macros de TeX?](/latex/es/mas-temas/01-a-six-part-series-how-do-tex-macros-actually-work.md)

### Entendiendo los tokens de caracteres

Cualquier carácter que un motor TeX pueda leer de un archivo de texto se representa mediante dos valores numéricos:

* su *código de carácter* (valor ASCII o, hoy en día, su punto de código Unicode);
* un segundo valor, centrado en TeX, llamado su *código de categoría*.

Los lectores que deseen saber más sobre los códigos de categoría pueden estar interesados en leer esta introducción publicada por Overleaf: [Entonces, ¿por dónde empezamos? Con los códigos de categoría](/latex/es/mas-temas/19-how-tex-macros-actually-work-part-1.md#so2c-where-do-we-start3f-with-category-codes).

Por ejemplo, si un motor TeX lee el carácter `A` tendría acceso a dos piezas de información: `A`su código de carácter (65) y su código de categoría (11, normalmente). Una vez que TeX ha introducido ese carácter `A`, su código de categoría no cambiará, pero las macros del usuario pueden hacer cambios en el código de categoría que podrían afectar a cualquier *subsecuente* carácter `A` que *aún no ha sido leído* por TeX. En consecuencia, TeX necesita registrar que *este* carácter `A`, *acabado de leer*, tiene código de categoría 11. Para ello, TeX usa el par de enteros (65,11) para calcular otro valor entero que llama *token de carácter*. Al calcular ese valor de token, que se pasa al procesamiento interno de TeX, ese particular `A` y su código de categoría quedan *vinculados entre sí*; en efecto, ese token de carácter *encapsula* los datos que TeX necesita conocer sobre ese carácter para usarlos en cualquier actividad de composición posterior más profunda dentro del motor TeX.

#### ¿Cómo se calculan los tokens de carácter?

En primer lugar, debemos recordar que los motores TeX usan el código de categoría 13 con el fin de crear los llamados *caracteres activos*: cualquier carácter con código de categoría 13 se comporta como una mini-macro; en consecuencia, y como veremos a continuación, los tokens para caracteres activos se calculan de forma distinta a los caracteres normales con otros códigos de categoría como 10, 11 o 12.

Para *no activos* caracteres:

* los motores antiguos de 8 bits (TeX de Knuth, e-TeX, pdfTeX) calculan tokens de carácter para *no activos* caracteres usando

$$\text{(non-active) character token} = (256 \times \text{category code}) + (\text{ASCII character code})$$

* para LuaTeX, que tiene que lidiar con valores de caracteres Unicode, el cálculo para *no activos* caracteres es similar, pero produce valores enteros mucho mayores:

$$\text{(non-active) character token} = (2^{21} \times \text{category code}) + (\text{Unicode value})$$

Volviendo a nuestro ejemplo anterior de la letra A con código de categoría 11, LuaTeX calcularía un valor de token de carácter de $$2^{21} \times 11 + 65 = 23068737$$. Una vez calculado, ese valor de token de carácter *vincula* ese carácter A en particular a un valor de código de categoría de 11. Las macros del usuario pueden cambiar el código de categoría de cualquier carácter A posterior, pero el código de categoría de este ha quedado fijado al convertirlo en un token para su uso a medida que pasa por los mecanismos internos de LuaTeX. LuaTeX ha preservado, o encapsulado, el significado previsto de ese carácter tal como se determinó en el momento en que se leyó.

Los motores TeX usan un total de [16 códigos de categoría diferentes](/latex/es/mas-temas/43-table-of-tex-category-codes.md) y *cualquiera* de esos códigos de categoría puede asignarse, mediante el `\catcode` comando, a *cualquiera* carácter que el motor TeX es capaz de leer. Los cambios en los códigos de categoría se usan para alterar la forma en que los motores TeX procesan caracteres particulares en la entrada, permitiendo a los usuarios de TeX escribir macros que producen resultados o comportamientos especiales de composición tipográfica.

**Caracteres activos**

Como se señaló, los motores TeX usan el código de categoría 13 para atribuir un “significado especial” a un carácter, convirtiéndolo en un llamado *carácter activo* que se comporta como una mini-macro: no se requiere `\` el carácter aislado, debido a su código de categoría, es suficiente para desencadenar su comportamiento similar al de una macro.

Como un carácter activo actúa como una mini-macro, no se convierte en un *token de carácter* sino en un segundo tipo de token (entero) llamado *token de comando*. Estos se calculan de la siguiente manera:

* para los motores antiguos de 8 bits (TeX de Knuth, e-TeX, pdfTeX), los tokens para caracteres activos se calculan mediante:

1. calcular un valor intermedio llamado $$\text{curcs}$$ (**cur**rent **c**ontrol **s**equencia) donde $$\text{curcs} = \text{character code} + 1$$3. calcula el valor del token donde $$\text{active character token} = \text{curcs} + \text{4095}$$

* para LuaTeX el cálculo es un poco más complejo porque tiene que tratar con toda la gama de caracteres Unicode, cualquiera de los cuales podría hacerse activo:

1. calcular el valor entero intermedio $$\text{curcs}$$ aplicando una llamada *función hash* al valor del punto de código Unicode del carácter activo expresado en UTF-8: $$\text{curcs}=\texttt{hashfunction}\text{(UTF-8 text for Unicode value of active character)}$$3. calcula el valor entero del token: $$\text{active character token} = \text{curcs} + 2^{29} - 1$$

**Ejemplos**

* Motores de 8 bits: el cálculo del token para el carácter activo `~` (código de carácter 126) da como resultado $$\text{curcs} = 126 + 1 = 127$$, dando un valor de token de $$4095 + 127 = 4222$$.
* LuaTeX: el cálculo del token para el carácter activo `~` da como resultado $$\text{curcs}=3186$$ dando un valor de token de $$3186 + 2^{29} - 1 = 536874097$$. ¡Los tokens de LuaTeX usan valores enteros mucho mayores!

### Entendiendo los tokens de comando

Además de procesar *individuales* caracteres, los motores TeX pueden, por supuesto, procesar *secuencias* de caracteres llamadas *comandos* (o, más correctamente, *secuencias de control*). Por tradición, el `\` carácter se usa para señalar el inicio de un comando, pero eso es solo una convención; de hecho, cualquier carácter con código de categoría 0 (el carácter de escape) podría usarse en su lugar.

Los motores TeX reconocen dos tipos de comando que se conocen como *palabras de control* y *símbolos de control*:

* **palabras de control**: comandos construidos a partir de uno o más caracteres que tienen código de categoría 11;
* **símbolos de control**: comandos de un solo carácter en los que el código de categoría de ese carácter *no se* 11: como `\$`, `\#` o `\\`.

**Nota**: Los primitivos de TeX `\chardef`, `\mathchardef`, `\countdef`, `\dimendef`, `\skipdef`, `\muskipdef` y `\toksdef` también se usan para definir secuencias de control, pero, a diferencia de las definiciones de macros normales, las secuencias de control resultantes (palabras de control o símbolos de control) *no son expansibles*—las exploraremos con más detalle a continuación.

#### ¿Cómo se calculan los tokens de comando?

Al igual que con los caracteres activos, los motores TeX usan el segundo tipo de valor entero de token para representar comandos: *tokens de comando*—recuerda que los caracteres activos también generan tokens de comando porque se comportan como mini-macros.

Los cálculos utilizados por los motores de 8 bits para crear enteros de token de comando pueden encontrarse en este [artículo de Overleaf](/latex/es/articulos-en-profundidad/19-how-does-expandafter-work-an-introduction-to-tex-tokens.md#how-tex-calculates-token-values). Aquí resumiremos los pasos clave en los cálculos de tokens de comando para LuaTeX, que son ligeramente diferentes porque LuaTeX tiene que procesar valores de código de caracteres Unicode, que pueden ser considerablemente mayores que los valores de 8 bits; sin embargo, los cálculos de LuaTeX siguen los mismos principios generales usados por los motores antiguos de 8 bits.

Después de detectar un comando entrante, los motores TeX, incluido LuaTeX, ignoran el carácter inicial `\` carácter: no se usa en los cálculos de los valores de token de comando, sino que simplemente actúa como un “interruptor” para informar a un motor TeX de que necesita procesar un comando. El valor del token de comando se calcula usando la secuencia de (uno o más) caracteres presentes en el nombre del comando: LuaTeX calcula tokens de comando para símbolos de control y palabras de control usando el mismo algoritmo:

1. calcular el valor entero intermedio $$\text{curcs}$$ aplicando una llamada [función hash](https://en.wikipedia.org/wiki/Hash_function) a la cadena Unicode UTF-8 de caracteres contenida en el nombre del comando: $$\text{curcs}=\texttt{hashfunction}\text{(Unicode UTF-8 string of characters in command name)}$$3. calcula el valor del token de comando donde $$\text{command token} = \text{curcs} + 2^{29} - 1$$

**Ejemplos**

* para el `\\` comando (un símbolo de control), LuaTeX calcula $$\text{curcs}=94$$, lo que da como resultado un valor de token para `\\` de $$94 + 2^{29} - 1 = 536871005$$.
* para el `\vskip` comando primitivo (una palabra de control), LuaTeX calcula $$\text{curcs}=3560$$, lo que da como resultado un valor de token para `\vskip` de $$3560 + 2^{29} -1 = 536874471$$.
* para la macro definida por el usuario `\mynewmacro` (una palabra de control) LuaTeX calcula $$\text{curcs} = 2971$$, lo que da como resultado un valor de token para `\mynewmacro` de $$2971 + 2^{29} -1 = 536873882$$.

Una vez creados, los tokens pueden almacenarse para su uso posterior mediante las llamadas *listas de tokens* o pueden pasarse de inmediato para su procesamiento posterior dentro del motor TeX. Usar valores enteros para representar tokens no solo funciona en todos los tipos de plataforma de computación/sistema operativo, sino que también es una forma muy eficiente para que TeX almacene/procese datos.

### Cómo identifica un motor TeX el tipo de token (comando o carácter)

Dado un valor entero de token en particular, $$T$$, un motor TeX puede determinar fácilmente si $$T$$ representa un comando o un carácter comprobando si $$T$$ supera un cierto $$\text{threshold value}$$—eso $$\text{threshold value}$$ depende del motor TeX. Si $$T \geq \text{threshold value}$$ entonces $$T$$ es un token de comando; de lo contrario $$T$$ es un token de carácter. El $$\text{threshold value}$$ es $$4095$$ para motores de 8 bits y $$2^{29}-1$$ (536.870.911) para LuaTeX. Knuth diseñó los métodos usados en las fórmulas de cálculo de tokens para que su motor TeX, y todos los motores posteriores basados en su código/arquitectura, pudieran comprobar los valores de token de forma rápida y sencilla.

## Los tokens pueden descomponerse (y convertirse de nuevo en texto)

Los tokens (enteros) son el mecanismo mediante el cual un motor TeX “encapsula” todo lo que necesita registrar sobre un elemento de entrada (carácter o comando). Sin embargo, hay ocasiones en las que un motor TeX necesita revertir el proceso de tokenización, para averiguar qué se leyó originalmente para producir ese valor de token: un carácter individual o una secuencia de uno o más caracteres que forman el nombre de un comando:

* **para los tokens de carácter**: cualquier token de carácter puede dividirse en sus dos partes constituyentes: el código de carácter y el código de categoría correspondiente asignado a ese carácter *en el momento en que fue leído originalmente*. Como todos los motores TeX, LuaTeX no cambiará esa asignación original del código de categoría, pero hará uso de ella durante actividades posteriores de procesamiento interno.
* **para los tokens de comando:** Estos son un poco más detallados, pero si observas el cálculo de tokens de comando de LuaTeX, incluidos los tokens para caracteres activos, verás que siguen un patrón: $$\text{command token} = \text{curcs} + 2^{29} -1$$

donde $$\text{curcs}$$ se calcula según el tipo de token de comando que se genera: carácter activo, símbolo de control o palabra de control. El $$\text{curcs}$$ variable es un *extremadamente* componente importante de las operaciones internas de un motor TeX: dado cualquier valor de token de comando (entero), LuaTeX puede extraer muy fácilmente el valor de $$\text{curcs}$$ de ese token de comando usando $$\text{curcs} = \text{token value} - (2^{29} -1)$$.

### ¿Por qué es $$\text{curcs}$$ tan importante?

La variable interna de TeX $$\text{curcs}$$ (**cur**rent **c**ontrol **s**ecuencia) es un componente vital de las operaciones internas “bajo el capó” de un motor TeX. Aunque no la usarás, y no puedes acceder a ella directamente, en tu código, $$\text{curcs}$$ desempeña un papel crucial porque los motores TeX usan el valor actual de $$\text{curcs}$$ como índice en tablas internas que almacenan datos sobre cada comando conocido actualmente por el motor. Esas tablas almacenan información sobre el significado actual de un comando: qué hace o qué representa y, además, registran la secuencia de caracteres usada originalmente para calcular ese $$\text{curcs}$$ valor. Al extraer el valor de $$\text{curcs}$$ de un token de comando, un motor TeX puede determinar el nombre, es decir, el texto legible por humanos, correspondiente a cualquier token (de comando), lo que le permite realizar las conversiones de token a texto que son un aspecto clave de `\directlua`la operación de

### Convertir tokens enteros de nuevo en caracteres o secuencias de caracteres (nombres de comandos)

Hemos visto que los motores TeX convierten caracteres de entrada, o secuencias de caracteres, en valores enteros de token, pero hay ocasiones en las que un motor TeX necesita *invertir* ese proceso, para producir el texto legible por humanos usado originalmente para crear esos valores enteros de token; por ejemplo:

* escribir mensajes de error o advertencia en la pantalla o `.log` archivo;
* sacar código TeX/LaTeX a un archivo de texto mediante el `\write` comando;
* al convertir una secuencia de tokens en texto dentro de `\directlua` (¡como veremos pronto!)

#### Convertir tokens de carácter en texto

Como se señaló, los tokens para caracteres no activos se calculan usando el código de categoría y el código de carácter (valor Unicode) de un carácter de entrada. LuaTeX usa la fórmula:

$$\text{character token} = (2^{21} \times \text{category code}) + (\text{Unicode value})$$

Es una tarea de programación sencilla dividir el número entero $$\text{character token}$$ valor para obtener su código de carácter constitutivo ($$\text{Unicode value}$$) y $$\text{category code}$$.

#### Convertir tokens de comando en texto

Todos los motores TeX almacenan el nombre (secuencia de caracteres) de cada comando que “conocen”: ya sea que ese comando sea una macro definida por el usuario o un primitivo incorporado: el almacenamiento de los nombres de comandos primitivos tiene lugar cuando el motor TeX se inicia, mucho antes de que empiece a procesar tu código. Para los comandos definidos por el usuario (macros), el nombre de esa macro (sin el `\`) se guarda como parte de los procesos de definición de macros dentro de los motores TeX.

Cuando un motor TeX necesita acceder o sacar el texto legible por humanos a partir del cual se calculó originalmente un token de comando entero, primero determinará el $$\text{curcs}$$ valor de ese token; en LuaTeX, $$\text{curcs} = \text{token} - (2^{29} -1$$). Usando el valor de $$\text{curcs}$$ extraído de un token de comando, un motor TeX puede acceder a una estructura de datos interna llamada *grupo de cadenas* para determinar la secuencia de caracteres legibles por humanos usada originalmente para calcular ese valor particular de $$\text{curcs}$$ y, en consecuencia, el token de comando correspondiente.

Como veremos, estas actividades de procesamiento de tokens—convertir secuencias de caracteres en valores enteros de token y convertir valores enteros de token de vuelta en secuencias de caracteres (“des-tokenización”)—son los *mecanismos fundamentales* usados dentro de `\directlua`.

## Listas de tokens

A medida que un motor TeX lee la entrada, genera tokens de carácter y de comando (y los procesa), podría encontrarse con ciertos comandos que instruyen al motor a (temporalmente) dejar de pasar tokens para su procesamiento posterior y, en su lugar, almacenarlos para uso futuro. El ejemplo más común es definir una macro usando uno de los comandos de definición de macros `\def`, `\edef`, `\gdef` o `\xdef`—comandos de LaTeX como `\newcommand` son macros que proporcionan funcionalidad adicional construida alrededor de primitivas de bajo nivel que, finalmente, realizan el proceso real de definición de macros. Una macro puede considerarse como el nombre dado a una lista particular de tokens almacenados: una lista de tokens.

Los motores TeX hacen *uso extensivo* de las listas de tokens, especialmente [listas internas temporales de uso exclusivo](/latex/es/articulos-en-profundidad/21-how-does-expandafter-work-tex-uses-temporary-token-lists.md) usadas con fines de procesamiento interno. Cada motor TeX también proporciona comandos de nivel de usuario para crear listas de tokens que se guardan para cuando el usuario, o el propio motor TeX, las necesite. El número de comandos de creación de listas de tokens (primitivas incorporadas) varía según el motor TeX, pero todos comparten un conjunto mínimo básico compatible con todos los motores, como el `\\toks` primitivo.

En la práctica, una lista de tokens no es más que una secuencia almacenada de valores enteros:

* la entrada se lee para generar (calcular) tokens individuales, que representan un carácter o un comando;
* cada token se almacena después, preservando la secuencia en la que los tokens se generaron a partir de la entrada.

Los motores TeX almacenan listas de tokens usando una estructura de datos llamada [lista enlazada](https://en.wikipedia.org/wiki/Linked_list) (de tipo enlazado simple). Los lectores que deseen saber más sobre las listas de tokens están invitados a leer el artículo de Overleaf [¿Qué es una lista de tokens de TeX?](/latex/es/articulos-en-profundidad/54-what-is-a-tex-token-list.md) que usa una analogía para construir los conceptos/ideas detrás de una lista de tokens. Una exploración en profundidad de las listas de tokens de TeX y de cómo se usan en el procesamiento de macros puede encontrarse en la serie de artículos de Overleaf [¿Cómo funcionan realmente las macros de TeX?](/latex/es/mas-temas/01-a-six-part-series-how-do-tex-macros-actually-work.md)

#### Una lista de tokens en forma gráfica

El siguiente gráfico muestra una lista de tokens generada por LuaTeX con los valores de token correspondientes producidos a partir de la siguiente entrada

`Hi, \TeX! \hskip 5bp`

Por ejemplo, si definimos `\mymacro` como `\def\mymacro{Hi, \TeX! \hskip 5bp}` la definición de `\mymacro` se almacenaría en memoria usando una lista de tokens como esta:

![](/files/94a286f584b04bf9ffa23c0f5cc7a1bd9f7a97be)

La lista de tokens es una secuencia de elementos enlazados llamados *nodos*, nombre dado a un pequeño bloque de memoria de LuaTeX asignado para contener cada elemento de la lista (como eslabones individuales de una cadena). Cada nodo contiene un valor entero de token y la dirección de memoria del *siguiente* nodo de la cadena, formando una estructura de datos llamada [lista enlazada](https://en.wikipedia.org/wiki/Linked_list). El último nodo indica el final de la lista usando un “valor nulo” especial para el siguiente nodo, porque no existe uno.

**Notas:**

* Por conveniencia, hemos incluido la dirección de cada nodo individual, pero, en la práctica, esos datos no se almacenan dentro de los nodos de la lista de tokens; solo la dirección del *nodo siguiente* se requiere para construir listas de tokens del motor TeX.
* La segunda columna del gráfico titulada “Lo que significa cada token” muestra una serie de cajas grises que contienen información sobre el token contenido en cada nodo: estas son puramente informativas y *no* forman parte de los datos reales almacenados en la lista de tokens.

Aquí hay una tabla de los valores de token contenidos en la lista de tokens mostrada arriba:

|                         |                     |                                                                                         |                    |
| ----------------------- | ------------------- | --------------------------------------------------------------------------------------- | ------------------ |
| **Elemento de entrada** | **Tipo de entrada** | <p><strong>Código de categoría</strong><br><br><strong>(si es un carácter)</strong></p> | **Valor de token** |
| H                       | carácter            | 11                                                                                      | 23068744           |
| i                       | carácter            | 11                                                                                      | 23068777           |
| ,                       | carácter            | 12                                                                                      | 25165868           |
|                         | carácter            | 10                                                                                      | 20971552           |
| \TeX                    | comando (macro)     |                                                                                         | 536871539          |
| !                       | carácter            | 12                                                                                      | 25165857           |
|                         | carácter            | 10                                                                                      | 20971552           |
| \hskip                  | comando (primitivo) |                                                                                         | 536874247          |
| 5                       | carácter            | 12                                                                                      | 25165877           |
| b                       | carácter            | 11                                                                                      | 23068770           |
| p                       | carácter            | 11                                                                                      | 23068784           |

**Nota:** Nuestro texto de entrada original tiene una después del `\hskip` comando, pero no hay ningún token que represente ese carácter en la lista de tokens. Ese carácter fue absorbido por el proceso de escaneo (lectura) de entrada de LuaTeX porque se usó para terminar la búsqueda de LuaTeX de los caracteres que componen el `\hskip` comando.

## Cómo funciona realmente \directlua

Ahora que hemos explorado los tokens, las listas de tokens y la conversión de tokens a texto, el siguiente desafío es entender el concepto del motor TeX de token *expansión*.

Como se señaló, `\directlua{⟨code⟩}` se le puede pedir que procese `⟨code⟩` que contiene tanto código Lua como TeX/LaTeX pero el intérprete de Lua incorporado de LuaTeX no entiende TeX ni LaTeX: entonces, ¿cómo puede funcionar esto? ¿Cómo es posible que el `⟨code⟩` contenga instrucciones de TeX/LaTeX sin confundir por completo al intérprete de Lua con comandos que no entiende? Por ejemplo, el siguiente `\directlua` comando solo usa macros de TeX, pero funciona:

```
\def\aa{tex}
\def\bb{.}
\def\cc{print}
\def\dd{(\"Hello\")}
\directlua{
   \aa\bb\cc\dd
}
```

Este `\directlua` comando da como resultado la composición tipográfica en LuaTeX `Hello` pero ¿por qué y cómo funciona esto si el lenguaje Lua no entiende las macros de TeX?

La respuesta se encuentra en la descripción anterior que tomamos prestada de la [Manual de referencia de LuaTeX](http://www.pragma-ade.com/general/manuals/luatex.pdf) pero podemos considerar que `\directlua{⟨code⟩}` funciona haciendo que LuaTeX inicialmente “preprocese” el `⟨code⟩` antes de que se pase nada al intérprete de Lua. La naturaleza de este “preprocesamiento”—es decir, lo que realmente significa y sus consecuencias para tu `⟨code⟩`—es el siguiente tema que abordaremos para ayudar a los lectores interesados en aprovechar la potencia y flexibilidad de `\directlua`.

### Cómo procesa LuaTeX \directlua: una primera mirada

Para ampliar nuestra comprensión de `\directlua`las actividades de “preprocesamiento” podemos comenzar con el siguiente diagrama simplificado, que da una visión general de lo que ocurre. El `⟨code⟩` proporcionado a `\directlua{⟨code⟩}` se convierte primero en tokens usando los procesos y cálculos discutidos anteriormente; esa secuencia de tokens se almacena en una lista de tokens. Una vez construida esa lista de tokens, cada token de esa lista se convierte de nuevo a su representación textual: el texto producido por cada token—token de carácter o token de comando—se combina (concatena) para crear una sola cadena de código que se pasa al intérprete de Lua para su ejecución.

![](/files/e44e60700aa4b4eac0e85db880c5925534b17676)

Pero espera, ¿qué sentido tendría pasar de texto a tokens y convertir esos tokens inmediatamente de nuevo en texto? Quizá no te sorprenda saber que, sí, hay un proceso adicional y vital que no hemos incluido en este gráfico: *expansión de tokens*. Cada token producido a partir del texto en tu `⟨code⟩` está sujeto a un tipo de “inspección” en la que LuaTeX aplica una prueba para ver si ese token representa un comando que pertenece al subconjunto conocido como *comandos expandibles*. Si lo hace, LuaTeX filtra ese comando *eliminar* de tu `⟨code⟩` y *reemplazándolo* con el/los resultado(s) de un proceso que los motores TeX llaman *expansión de tokens*.

### Cómo procesa LuaTeX \directlua: una segunda mirada (a la expansión)

El mecanismo de expansión de TeX es un componente central de todos los motores de composición tipográfica basados en TeX porque, en última instancia, cada uno se deriva de (o se basa en) el código fuente y el diseño originales de TeX de Knuth. Sin embargo, el concepto de expansión es difícil de explicar en un lenguaje conciso, pero accesible, porque en la práctica expansión es un término general usado para describir un solo proceso, pero uno que produce una variedad de resultados. Esos resultados variados son consecuencia del conjunto algo ecléctico de comandos a los que puede aplicarse la expansión, así que puedes considerar que cada comando expandible tiene cierto “comportamiento de expansión”.

Como una *primera aproximación* para entender la expansión podemos decir que la expansión de un token (comando) significa *eliminar* eliminar ese comando (token) del input actual de TeX y *reemplazar* sustituirlo por una secuencia de tokens que resultan de ejecutar ese comando expandible en particular—reemplazando el token original por los resultados/consecuencias de su expansión *comportamiento*. Sin embargo, esta “definición” inicial de expansión—en términos de generar nuevos tokens para que TeX los lea—no es totalmente exacta para todos los comandos expandibles, pero es suficiente como punto de partida.

Para dar un ejemplo sencillo: el primitivo de TeX `\\jobname` es un comando expandible y su *expansión* es una secuencia de tokens de carácter que representan el nombre del archivo principal de entrada de TeX. Si TeX decide expandir un `\\jobname` comando (token), este *eliminado* de la fuente de entrada actual de TeX y *reemplazado* por la secuencia de tokens de carácter que genera, que luego TeX procede a leer/procesar.

Dentro de `\directlua`, después de que se procesa (elimina) un token expandible y se reemplaza por nuevos tokens, LuaTeX seguirá leyendo esos nuevos tokens que acaba de colocar en su lugar, pero algunos de esos nuevos tokens también podrían ser expandibles. Debido a que `\directlua` realiza la llamada *expansión completa*, LuaTeX leerá esos nuevos tokens y, una vez más, pasará por el proceso de expansión para expandir (eliminar) cualquier token nuevo (expandible); este proceso de expansión continúa hasta que no queden tokens expandibles. Sin embargo, hay dos excepciones importantes a esta regla de “seguir expandiendo”, ambas de las cuales hablaremos a continuación:

* usando el constructo `\the\toks`;
* prevención deliberada (supresión) de la expansión de uno o más tokens seleccionados.

Como se señaló, nuestra definición de trabajo (primera aproximación) para entender la expansión no cubre el rango completo de comportamientos de expansión demostrados por el subconjunto de comandos expandibles. Por ejemplo, algunos comandos expandibles no generan tokens de la forma en que `\\jobname` lo hace, pero podrían:

* “filtrar” tokens de la entrada: los comandos condicionales de un motor TeX (`\if`, `\ifcat`, `\ifnum`, `\ifdim`, `\ifodd`, `\ifvmode`, …) son expandibles. Su comportamiento de expansión es un tipo de “filtrado de tokens”—los condicionales pueden usarse en `\directlua`.
* “hacer malabares” con tokens en la entrada: la [`\\expandafter` comando](/latex/es/articulos-en-profundidad/03-a-six-part-article-series-on-expandafter-tex-tokens-and-expansion.md) es expandible y cambia la secuencia en la que se expanden dos tokens.
* impedir la expansión: los comandos expandibles `\noexpand` y `\unexpanded` suprimen la expansión de los tokens de comando en la entrada.
* convertir secuencias de caracteres en la entrada en tokens de comando: `\csname … \endcsname.`
* convertir cantidades internas en una secuencia de tokens de carácter: `\number` y `\\the` son comandos expandibles que generan una secuencia de tokens de carácter que representa el valor de una cantidad interna.
* convertir tokens de comando en tokens de carácter: `\string` y `\detokenize` son comandos expandibles que convierten sus argumentos en una secuencia de tokens de carácter con código de categoría 12. Observa que `\detokenize` difiere de `\string`: `\detokenize` puede procesar múltiples tokens e introduce un carácter de espacio, con código de categoría 10, después de procesar los tokens de comando creados a partir de *palabras de control*. En efecto, `\detokenize` añade un carácter de espacio final después del nombre del comando—we’ll see some examples later in the article.

#### Afinando nuestra “definición” de expansión

Ahora podemos generalizar nuestra definición y decir que la expansión de un comando (token) implica *la eliminación* de ese comando (token) de la fuente de entrada actual de TeX y *reemplazándolo* sustitución por el resultado de la *operación(es) de tokens* realizada(s) por ese comando. En esencia, el proceso de expansión hace que un comando expandible realice algún tipo de “operación” sobre los tokens en la entrada actual de TeX que afecta al número o al comportamiento de los tokens que TeX leerá posteriormente; la naturaleza precisa de esa “operación” depende de qué comando se esté expandiendo. Todas las macros, y los caracteres activos, son expandibles, pero solo un pequeño número de los comandos integrados (primitivos) de un motor TeX se clasifican como expandibles; la lista de comandos expandibles depende del motor TeX que estés usando. LuaTeX tiene toda una colección de ellos.

Cada nuevo motor TeX hereda los comandos primitivos incorporados en sus antecesores, los motores TeX de generaciones anteriores de los que se derivó, y algunos de esos primitivos heredados serán expandibles. Por supuesto, un nuevo motor TeX puede optar por no implementar algunos de los comandos primitivos contenidos en los motores anteriores o por modificar su comportamiento para adaptarlo a las necesidades del nuevo motor. Además, los nuevos motores TeX suelen implementar primitivas adicionales para proporcionar soporte a su propia funcionalidad mejorada; algunas de esas también podrían ser expandibles. En consecuencia, el número de comandos expandibles disponibles para ti variará según el motor TeX que estés usando—LuaTeX tiene toda una colección de ellos.

Otra dificultad al explicar/entender la expansión, y quizás el verdadero desafío, es saber exactamente *cuándo* un motor TeX va a realizar, o no, realmente el proceso de expansión. Ese es un tema amplio y complejo porque la expansión está profundamente integrada en el funcionamiento interno de los motores TeX: no tenemos espacio para abordarlo en detalle más allá del uso de la expansión en `\directlua`.

### Cómo procesa LuaTeX \directlua: una mirada final

El siguiente diagrama resume las `\directlua` actividades de preprocesamiento que tienen lugar dentro del propio motor LuaTeX. En este diagrama también mostramos dos funciones internas de bajo nivel de LuaTeX que realmente hacen el trabajo: `scan_toks()` y `tokenlist_to_cstring()`. Esas funciones están escritas en lenguaje C y residen profundamente dentro del software ejecutable LuaTeX: forman parte de la maquinaria interna de LuaTeX y no *directamente* accesibles a tu código TeX/LaTeX.

![](/files/1553c5a9756329acd0adf456ff06de06f8074c99)

La siguiente descripción de `\directlua ⟨code⟩`resume la actividad de preprocesamiento anterior.

1. La secuencia de caracteres en tu ⟨code⟩ es procesada por `scan_toks()`. Su propósito es leer tu ⟨code⟩ carácter por carácter para generar tokens de carácter y tokens de comando. Como está creando tokens, el código de categoría asignado a cada carácter en ⟨code⟩, en el momento en que se lee, es extremadamente importante.
2. Durante `scan_toks()`el procesamiento de tokens (generación) cualquier comando (token) expandible se expande *a menos que* se haya impedido mediante comandos como `\protected` (definiciones de macros), `\noexpand`, `\unexpanded` etc. Los caracteres activos (código de categoría 13) también se expanden (a menos que se impida).
3. El flujo de tokens creado por `scan_toks()` se construye en una larga lista de tokens—los tokens presentes en esa lista incluyen los producidos a partir de la expansión aplicada a comandos expandibles (como macros) presentes en tu `⟨code⟩`. Ten en cuenta también que `scan_toks()` *no* no activan ni provocan la ejecución de ningún token que represente un comando no expandible: esos tokens no expandibles simplemente se pasan tal cual para incorporarse a la lista de tokens que se está construyendo.
4. Una vez que la lista de tokens está terminada y toda la actividad de expansión se ha completado, esa lista de tokens es procesada por otra función llamada `tokenlist_to_cstring()` que convierte cada token de la lista final de tokens de nuevo en su representación textual. Esto genera una cadena de texto que es el código Lua que se pasará al intérprete de Lua. Para una ejecución correcta, esa cadena debe contener código Lua sintácticamente correcto.
5. El procesamiento de ese código por Lua tiene lugar en dos pasos:
6. El intérprete de Lua incorporado en LuaTeX analiza y “compila” el código Lua generado en los pasos anteriores. Si ese análisis/compilación falla, el intérprete de Lua generará errores (como errores de sintaxis); esos errores pueden hacer que la ejecución de LuaTeX falle a menos que hayas elegido usar `--interaction=nonstopmode` en la línea de comandos.
7. Si el análisis/compilación tiene éxito, el intérprete de Lua ejecuta el código compilado en el paso (5a).

En esencia, la `scan_toks()` función es el núcleo de las actividades de preprocesamiento de LuaTeX: su tarea principal es expandir todos los comandos expandibles de TeX/LaTeX contenidos en el texto de tu `⟨code⟩` y construir una lista de tokens a partir de todo lo que ha procesado. Nuevamente, subrayamos que `scan_toks()` *no ejecuta comandos no expandibles* (tokens): simplemente *almacena* esos tokens en la lista de tokens que está construyendo. Una vez completada, esa lista de tokens se convierte posteriormente *de nuevo en una representación textual* por `tokenlist_to_cstring()`—una lista de tokens es un concepto exclusivo de TeX que es completamente ajeno a un intérprete de Lua, de ahí la necesidad de convertirla en texto, convirtiéndose en código Lua para pasarlo al intérprete de Lua.

## La expansión como “interfaz” de un lenguaje de programación

Puedes pensar en `\directlua`el proceso de expansión de LuaTeX se utiliza como un mecanismo, o interfaz, para pasar datos/información desde el “Mundo TeX” al “Mundo Lua”: proporcionando un método para que el lenguaje TeX comunique datos al lenguaje Lua. Por ejemplo, código TeX como `\number\count75` puede usarse para transferir un valor del “Mundo TeX” almacenado en el registro de conteo 75 al entero x del “Mundo Lua”:

```
\count75=1564 % Datos existentes en el "Mundo TeX"
\directlua{
   local x=\number\count75 \space % Transferir datos de TeX al "Mundo Lua"
   tex.print("x= "..x)
   local y = (2*x-65)/5
   tex.print(" y = "..y)
}
```

Esto genera el código Lua

```
 local x=1564 tex.print("x= "..x) local y = (2*x-65)/5 tex.print(" y = "..y)
```

**Nota**: Añadimos `<space>\space` después de `\number\count75` para asegurar que se preservara un carácter de espacio entre `1564` y `tex.print`—eso no es estrictamente necesario aquí porque Lua seguiría analizando correctamente el código si lo omitiéramos. El carácter de espacio que sigue inmediatamente después de `\count75` se absorbe durante el proceso que usan los motores TeX para buscar valores numéricos—aquí, el valor que se suministra a `\\count`. El carácter de espacio después de `75` se usa para terminar la búsqueda de LuaTeX de la secuencia de dígitos `75` y se absorbe del input. La `\space` macro se expande para proporcionar el carácter de espacio necesario para separar el texto `1564` y `tex.print`.

Usando el código anterior, LuaTeX compondrá

`x= 1564 and y = 612.6`

Aquí, el mecanismo de “paso de datos” se logra mediante `\number`: un comando expandible que, en este caso, instruye a TeX a recuperar el valor almacenado en `\\count` registro `75` y a partir de ese valor (`1546`) generar una serie de tokens de carácter, un token de carácter por cada dígito, dando como resultado una secuencia de tokens para los dígitos `1`, `5`, `6` y `4`. Esos 4 tokens de carácter se incorporan a la lista principal de tokens que está construyendo `\directlua` y posteriormente se convierten de nuevo a su representación textual cuando la lista de tokens se convierte en texto. Sin duda, es un camino muy indirecto ir desde el `\count75` valor de registro almacenado dentro de LuaTeX, hasta los dígitos destinados al código Lua, pero, en última instancia, funciona.

**CONSEJO:** Si quieres inspeccionar los resultados de las actividades de expansión de LuaTeX, puedes escribir código como este:

```
\directlua{
   local foo=[[local x=\number\count75
   tex.print("x= "..x)
   local y = (2*x-65)/5
   tex.print(" y = "..y)]]
   print(foo)
}
```

En este ejemplo usamos el método de corchetes largos para crear una variable de cadena `foo` cuyo propósito es contener la cadena de código Lua generada a partir de la expansión de todo lo que hay entre `[[` y `]]`. Esa cadena se imprime en la consola mediante la llamada a la función Lua `print(foo)`.

En Overleaf puedes ver resultados similares escribiendo el contenido de `foo` en el `.log` archivo usando la función Lua de LuaTeX `texio.write()`:

```
\directlua{
   local foo=[[local x=\number\count75
   tex.print("x= "..x)
   local y = (2*x-65)/5
   tex.print(" y = "..y)]]
   texio.write(foo)
}
```

## Tokens en la lista de tokens de \directlua: tokens no expandibles y tokens no expandidos

Hemos señalado que `\directlua{⟨code⟩}` realiza *expansión completa* de tu `⟨code⟩`: elimina y expande todos los comandos expandibles hasta que solo queden tokens no expandibles. La secuencia de tokens creada por `\directlua`’s processing (in the `scan_toks()` de procesamiento (en la

Sin embargo, todavía no hemos abordado la parte final de esta historia porque necesitamos considerar las dos “clases” de token de comando que pueden llegar a la lista de tokens que se está construyendo dentro de `\directlua`: nos referiremos a ellas como *tokens de comando abreviados* y *no expandidos* tokens:

* **tokens de comando abreviados**: Este tipo de token de comando surge de secuencias de control definidas usando uno de los primitivos de TeX `\chardef`, `\mathchardef`, `\countdef`, `\dimendef`, `\skipdef`, `\muskipdef` y `\toksdef`. Estos comandos primitivos se usan para definir secuencias de control que representan un valor numérico; las secuencias de control resultantes son *no* expandibles.
* **tokens no expandidos**: Este tipo de token surge de comandos que normalmente se expandirían, pero `\directlua` ha sido o bien:
* instruido explícitamente *no* a expandirlos; por ejemplo, la supresión de la expansión mediante los comandos `\noexpand` o `\unexpanded`—enseguida explicaremos cómo se hace esto;
* inyectado tokens procesando la secuencia `\the\toks` (más sobre esto abajo).

### Dos “grupos” de token en una lista de tokens de \directlua

Basándonos en nuestras discusiones, podemos decir que los tokens contenidos en la lista de tokens que se está construyendo durante la primera etapa de `\directlua`’s preprocesamiento (en la `scan_toks()` function) se dividen en dos grupos:

1. *intrínsecamente no expandibles* tokens

* cualquier token que represente un *carácter*;
* cualquier token que represente un comando *primitivo* *comando*;
* cualquier token que represente un *comando abreviado* (estos no son expandibles, véase abajo).

3. *no expandidos* tokens:

* cualquier token que represente un comando expandible cuya expansión fue *suprimida* (o evitada) durante `\directlua`’s preprocesamiento.

#### Tokens de comando abreviado: creación de comandos no expandibles

Como se señaló, los motores TeX proporcionan un conjunto de primitivas (comandos incorporados) que pueden usarse para construir *no expandibles* secuencias de control (indicadas aquí por `⟨command⟩`). Estas primitivas toman la forma:

* `\chardef ⟨command⟩ = ⟨numeric value⟩`
* `\mathchardef ⟨command⟩ = ⟨numeric value⟩`
* `\countdef ⟨command⟩ = ⟨numeric value⟩`
* `\dimendef ⟨command⟩ = ⟨numeric value⟩`
* `\skipdef ⟨command⟩ = ⟨numeric value⟩`
* `\muskipdef ⟨command⟩ = ⟨numeric value⟩`
* `\toksdef ⟨command⟩ = ⟨numeric value⟩`

donde `⟨numeric value⟩` es algún valor entero apropiado para cada comando.

Aquí, revisaremos brevemente el uso de `\chardef` para demostrar la característica clave de estas primitivas: producir una `⟨command⟩` que no es expandible. Puedes usar ``\chardef\mydollar=`\$`` para crear la secuencia de control `\mydollar` y usarla para componer tipográficamente un `$`:

`I paid \mydollar30.`

Esto compondrá tipográficamente `Pagué $30.` La secuencia de control `\mydollar` creada por `\chardef` no es expandible, como podemos ver en el siguiente ejemplo:

```
\chardef\mydollar=`\$
\directlua{
   local x =[[I paid \mydollar30.]]
   texio.write(x)
}
```

Lo que produce el siguiente texto en el `.log` editable

`I paid \mydollar 30.`

Esto muestra `\mydollar` fue *no* expandido durante `\directlua`’s preprocesamiento. El espacio que aparece después de `\mydollar` se añade cuando un token de comando se convierte a su representación como texto.

Cuando usas `\chardef` para crear una secuencia de control, la clasificación interna de TeX de esa secuencia de control (comando) hace que sea *no expandibles* no expandible, lo cual es un comportamiento muy diferente al de las secuencias de control definidas por uno de los comandos de definición de macros: \def, \edef, \gdef o \xdef. Como se señaló anteriormente, durante el proceso de construcción de su lista de tokens `\directlua` examina cada token de comando entrante para comprobar si es expandible. Si un token de comando no es expandible, pasa directamente a la lista de tokens y su representación textual reaparecerá más tarde en la cadena de código Lua resultante de convertir los tokens de la lista de tokens de vuelta a su forma textual.

**Breves notas sobre plain TeX frente a LaTeX**

Históricamente, el plain TeX original de Knuth definía los símbolos de control de uso común `\%`, `\&`, `\#` y `\$` usando `\chardef`—no usando uno de los comandos estándar de definición de macros `\def`, `\edef`, `\gdef` o `\xdef`. Por ejemplo:

```
   \chardef\#=`\#
   \chardef\$=`\$
   \chardef\%=`\%
   \chardef\&=`\&
```

La extraña `` `\ `` sintaxis es un método de TeX para obtener el valor numérico del código de carácter. En el antiguo régimen de plain TeX, estos símbolos de control no son expandibles (debido a `\chardef`) pero LaTeX (o los paquetes) puede redefinirlos como *macros* para proporcionar una funcionalidad mejorada, lo que los haría expandibles, así que quizá convenga tener esto en cuenta.

**¿Cómo afecta esto a \directlua?**

Comparemos el resultado del siguiente código ejecutado bajo plain TeX y LaTeX. Por simplicidad, escribiremos los resultados en el `.log` archivo usando la función de la API Lua de LuaTeX `texio.write()`.

```
\directlua{
   local x=[[\$150 for the "\#1" product---20\%! more than its competitor, Widget \& Co.]]
   texio.write(x)
}
```

Al ejecutar este código usando **plain TeX** produce la siguiente salida en el `.log` archivo, mostrando el resultado de cualquier expansión:

```
\$150 for the "\#1" product---20\%! more than its competitor, Widget \& Co.
```

Está claro que, bajo plain TeX, ninguno de los símbolos de control`\$`, `\#`, `\%` o `\&` fue expandido, porque todos se crean usando `\chardef`.

Ejecutar ese código usando el **LaTeX** documento:

```
\documentclass{article}
\begin{document}
   \directlua{local x=[[\$150 para el "\#1" producto---20\%! más que su competidor, Widget \& Co.]] texio.write(x)}
\end{document}
```

produce la siguiente salida en el `.log` editable

```
\protect \TU\textdollar 150 para el "\#1" producto---20\%! más que su competidor, Widget \& Co
```

Claramente, ejecutar LaTeX genera un resultado diferente al de TeX puro porque bajo LaTeX el comando `\$` ha sido expandido, lo que indica que es una macro.

**Nota:** Tanto en TeX puro como en LaTeX `\directlua` no procesó completamente ninguno de los símbolos de control `\%`, `\&`, `\#` y `\$` para generar el carácter correspondiente. Durante el proceso de expansión realizado por `\directlua` los tokens que representan estos símbolos de control —o, en LaTeX, su expansión— pasan directamente a la lista principal de tokens que se está construyendo.

**Nota:** Los símbolos de control se forman a partir de un solo carácter que no tiene código de categoría 11, como `\#`. Cuando un token que representa un símbolo de control se convierte de nuevo a su representación textual, los motores TeX no insertan un carácter de espacio después de ese texto. Este tratamiento especial de los símbolos de control es una regla incorporada sobre cómo operan los motores TeX.

### Tokens no expandidos: suprimir la expansión

`\directlua`el preprocesamiento de es un ejemplo en el que un motor TeX está realizando expansión, pero puede que quieras *impedir* que la expansión se aplique a uno o más tokens que, de otro modo, se expandirían. Como otro ejemplo, LuaTeX (y todos los motores TeX) realizan un proceso de expansión, similar al de `\directlua`, cuando procesan `\write` comando:

`\write file-number {⟨material⟩}`

\write instruye a un motor TeX a escribir `⟨material⟩`—a menudo con comandos TeX/LaTeX— en un archivo de texto (`número-de-archivo`'); cualquier comando expandible dentro de `⟨material⟩` se expandirá, salvo que se impida, antes de que `⟨material⟩` se escriba realmente en ese archivo.

Como cabría esperar, los motores TeX proporcionan comandos para suprimir o controlar la expansión:

* `\noexpand⟨token⟩`: impide la expansión del único `⟨token⟩`;
* `\unexpanded{⟨material⟩}`: impide la expansión de todos los comandos expandibles (tokens) en `⟨material⟩`. En efecto, es una versión de varios tokens de `\noexpand`;
* `\protected`: un prefijo añadido a las definiciones de macros que impide la expansión de esa macro en ciertas circunstancias (como durante `\directlua`, `\write` o `\edef`).

A pesar de los nombres que sugieren lo contrario, tanto `\noexpand` y `\unexpanded` puedes *comandos expandibles* y proporcionan buenos ejemplos de ver el proceso de expansión de un motor TeX como si realizara “operaciones sobre tokens”: la operación aquí es impedir la expansión de uno o más tokens subsiguientes (comandos). Porque `\noexpand` y `\unexpanded` son ambos comandos expandibles, se eliminan y procesan (ejecutan) durante `\directlua`el preprocesamiento de mientras construye la lista de tokens a partir de tu `⟨code⟩`.

#### \noexpand ⟨token⟩

`\noexpand ⟨token⟩` impide la expansión del único `⟨token⟩`. `\noexpand` dentro `\directlua` se expandirá (se eliminará de la entrada) y se reemplazará por los resultados de su “comportamiento de expansión”. El resultado de expandir `\noexpand` es crear un `⟨token marcador⟩` especial (oculto) `⟨token⟩` que se coloca delante del original `⟨token marcador⟩` cuya expansión se va a suprimir: ese `\directlua` actúa como una bandera que dice “no expandir el siguiente token”. Como `\noexpand ⟨token⟩` está realizando una expansión completa, volverá a procesar cualquier token que resulte del “comportamiento de expansión” de un comando expandible. En consecuencia, cuando la expansión de `⟨token marcador⟩⟨token⟩` está completa, LuaTeX vuelve a leer los resultados y ve la secuencia de dos tokens `⟨token⟩` que hace que el `\directlua`.

**Ejemplo**

original

```
\directlua{
   local x= "\TeX"
}
```

la `\TeX` macro se expanda en sus tokens constituyentes, lo que, en TeX puro, dará como resultado que el siguiente texto se pase a Lua (nota: Lua no puede procesar este código, solo es un ejemplo para demostrar el proceso):

`local x = "T\kern -.1667em\lower .5ex\hbox {E}\kern -.125emX"`

Si *suprimimos* la expansión de la `\TeX` macro usando `\noexpand`

`\directlua{local x= "\noexpand\TeX"}`

se produce el siguiente código Lua (de nuevo, Lua no puede ejecutar este código; es simplemente un ejemplo para demostrar `\noexpand`):

`local x= "\TeX "`

Debido a `\noexpand`, `\directlua` no se expandirá `\TeX` sino que simplemente permitirá que el valor de token que representa el `\TeX` comando pase intacto, sin daños, a la lista de tokens que se está construyendo durante la primera etapa de `\directlua`’s preprocesamiento.

**Nota:** El carácter de espacio que aparece después de `\TeX` es introducido por la conversión posterior de LuaTeX del `\TeX` valor de token entero de nuevo a su representación textual (dentro de la `tokenlist_to_cstring()` función).

#### \unexpanded{⟨material⟩}

`\unexpanded` es un comando expandible que suprime la expansión de todos los tokens formados a partir de `⟨material⟩`. Como hemos señalado, cuando un motor TeX realiza expansión cualquier comando expandible es *eliminado* de la entrada y *reemplazado* por los resultados de su “comportamiento de expansión”; entonces, ¿qué significa eso realmente para `\unexpanded`? Normalmente, durante *expansión completa*, una vez que el proceso de expansión para un comando particular se completa, el motor TeX pasa a leer/procesar cualquier token surgido del “comportamiento de expansión” de ese comando: necesita expandir aún más los tokens que se produjeron. Sin embargo, `\unexpanded` *elude* cualquier expansión adicional: así es como lo hace.

Dentro del motor TeX, el `\unexpanded` comando primero convierte los caracteres y comandos en `⟨material⟩` a una lista temporal de tokens compuesta por *no expandidos* tokens. Después de que se hayan creado y almacenado todos los tokens en esa lista temporal, el `\unexpanded` comando hace que `\directlua` a *se salten* volver a leerlos y procesarlos —aunque \directlua está realizando una expansión completa. En cambio, esos *no expandidos* tokens pasan directamente y se incorporan a la lista principal de tokens que está construyendo `\directlua` (en la `scan_toks()` función). De este modo, todo lo que hay en `⟨material⟩` se convierte en tokens y el proceso de expansión se omite para ese conjunto de tokens. La operación de `\unexpanded{⟨material⟩}` es similar al uso de `\the\toks`, que comentamos a continuación.

**Ejemplo**

`\unexpanded` produce resultados de una manera similar a `\noexpand` excepto que puede impedir la expansión de múltiples tokens; aquí hay un ejemplo:

```
\directlua{
   local x = "\unexpanded{\foo\bar\foobar}. ¡Pero Lua no puede procesar este código!"
}
```

que produce el siguiente texto como código para Lua:

`local x = "\foo \bar \foobar . ¡Pero Lua no puede procesar este código!"`

**Nota**: Hay caracteres de espacio después de cada nombre de comando. Estos son nuevamente consecuencia de la conversión posterior de LuaTeX de los tokens no expandidos `\\foo`, `\bar` y `\foobar` de vuelta a texto dentro de la `tokenlist_to_cstring()` función.

#### definiciones de macros \protected

El `\protected` comando es un prefijo aplicado a una definición de macro para evitar que esa macro se expanda cuando TeX está construyendo una lista de tokens expandida, como la lista de tokens construida por `\directlua`’s preprocesamiento.

**Ejemplo**

Supón que defines las siguientes macros con y sin usar el `\protected` prefijo:

```
\def\macroA{"Esta macro no protegida contiene una cadena"}
\protected\def\macroB{"Esta macro protegida también contiene una cadena"}
```

Si usas el operador de concatenación de cadenas de Lua (`..`) para escribir

```
\directlua{
   local x=\macroA..\macroB
}
```

`\directlua`el preprocesamiento de produciría el siguiente código para pasarlo a Lua:

`local x="Esta macro no protegida contiene una cadena"..\macroB`

`\macroA` no está definida usando `\protected` así que se expande, produciendo la primera parte de la cadena que se va a concatenar, pero `\macroB` está definida usando `\protected` así que no se ha expandido.

Durante el preprocesamiento, la `scan_toks()` función de LuaTeX creó un token para `\macroA`, reconoció que era un comando expandible normal y lo expandió: esa expansión produce una secuencia de tokens de caracteres, un token de carácter por cada carácter de `"Esta macro no protegida contiene una cadena"`. Cada token de carácter se pasa y se añade a la lista de tokens que se está construyendo.

Cuando `scan_toks()` crea el token para `\macroB` advierte que ese comando fue definido como `\protected` y no lo expande: el token que representa `\macroB` pasa intacto, sin tocar (sin expandir), a la lista de tokens que se está construyendo. Después de que se haya construido esa lista de tokens, la siguiente etapa del preprocesamiento, dentro de la `tokenlist_to_cstring()` función, consiste en convertir todos los tokens de la lista de tokens de nuevo a su representación textual. El token no expandido que representa `\macroB` se detecta y se convierte a su representación textual, dando como resultado el texto `\macroB` que aparece en el código destinado a Lua. Ten en cuenta que Lua en realidad no puede concatenar `"Esta macro no protegida contiene una cadena"..\macroB` para producir la cadena final porque `\macroB` no tiene significado en la sintaxis de Lua, lo que da lugar al error `símbolo inesperado cerca de '\'`.

**Curiosidades**: El `\protected` comando fue introducido por $$\varepsilon\text{-}\mathrm{\TeX}$$, la primera gran extensión del software TeX original de Knuth, y es compatible con todos los motores TeX cuya ascendencia de código incluye $$\varepsilon\text{-}\mathrm{\TeX}$$.

### Tokens no expandidos: Uso de \the\toks en \directlua

La vida en programación no sería la misma sin esos “casos especiales” que hay que tratar, y el uso de `\\the` en conjunto con `\\toks` en un `\directlua` comando es uno de esos casos especiales.

#### Breve introducción a \toks

La primitiva de TeX `\\toks` instruye a un motor TeX a guardar algunos tokens para usarlos más tarde: en lugar de ser enviados para un procesamiento adicional, esos tokens se apartan y se almacenan en una ubicación de memoria especificada usando un *registro de tokens*. Por ejemplo, podemos decirle a un motor TeX que cree algunos tokens y los almacene en la ubicación del registro de tokens `100` usando

`\toks100={¡Hola, \TeX! \hskip 5bp}`

Aquí, TeX usa el registro de tokens `100` para acceder a una ubicación conocida dentro de su memoria: un área de almacenamiento designada para contener listas de tokens.

Los tokens que representan todo lo que hay entre `{` y `}` se crean, *pero no se expanden*, y se encadenan en una lista de tokens —similar a la lista de tokens que exploramos antes en este artículo. Para reutilizar esos tokens escribiríamos `\the\toks100` en la que `\\the` (un comando expandible) instruye a TeX a recuperar los tokens almacenados e insertarlos en la ubicación donde escribiste `\the\toks100`. Otra forma de pensarlo es que `\the\toks` hace que TeX inserte algunos tokens en esa ubicación.

El `\\toks` comando *no expande* ninguno de los tokens que se le pide crear y guardar: simplemente convierte los caracteres y comandos entre `{` y `}` en tokens y los almacena.

#### De vuelta a \directlua

En la discusión sobre la expansión señalamos `\directlua{⟨code⟩}` realiza *expansión completa* de `⟨code⟩`: eliminar todos los comandos expandibles y reemplazarlos con el resultado de su comportamiento de expansión —continuando para *expandir aún más* cualquier token que surja de la expansión inicial de un comando expandible.

`\\the` es un comando expandible, así que `\directlua` lo expandirá; sin embargo, cuando `\\the` se usa en conjunto con `\\toks` dentro `\directlua`, como en `\the\toks⟨registro de tokens⟩`, los tokens insertados no se expanden más *. La expansión de*inyecta la secuencia de `\the\toks⟨registro de tokens⟩` tokens, almacenada en *no expandidos* tokens `⟨registro de tokens⟩`, directamente en la lista de tokens que está construyendo `\directlua`: este comportamiento elude el proceso habitual de expansión completa. En efecto, esos tokens pasan, *no expandidos*, para incorporarse a la lista principal de tokens que está construyendo `\directlua`—este proceso de paso de tokens no expandidos es similar en funcionamiento a `\unexpanded`, como se comentó anteriormente.

**Ejemplo**

Supongamos que definimos la macro `\mymacro` como `\def\mymacro{\TeX}`. Contiene solo un token para el `\TeX` comando (que es una macro): así que tenemos un comando expandible `\mymacro` que contiene otra macro `\TeX`, que también es expandible.

El siguiente código hará que Lua intente crear una variable de cadena `x`:

```
\def\mymacro{\TeX}
\directlua{
   local x="\mymacro"
}
```

Dentro de \\`directlua`, el token para `\mymacro` se expande, pero eso da lugar a otro token expandible, `\TeX`, que se expande aún más. En TeX puro, esas expansiones dan como resultado el siguiente texto pasado a Lua:

`local x = "T\kern -.1667em\lower .5ex\hbox {E}\kern -.125emX"`

Este código intenta definir una cadena que contiene texto que representa la versión expandida de la `\TeX` macro. Si intentas ejecutar este ejemplo, Lua intentará construir esa cadena pero fallará, generando un error:

`secuencia de escape no válida cerca de ' "T\k'.`

Más adelante en este artículo exploraremos el significado de “secuencia de escape no válida”.

Contrastemos ahora el uso de `\mymacro` con colocar el `\TeX` token dentro de una lista de tokens generada por un `\\toks` comando:

```
\toks100={\TeX}
\directlua{
   local x="\the\toks100"
}
```

el procesamiento de `\directlua` de LuaTeX generará esta cadena de texto para Lua:

`local x = "\TeX "`

El carácter de espacio después de `\TeX` es generado por el proceso de conversión de comando a cadena de LuaTeX.

**Pero ten en cuenta**: El `\TeX` macro tiene *no* ha sido expandida en sus tokens constituyentes. `\the\toks100` causó que los tokens almacenados en el registro 100 se insertaran, pero eso es todo: no se *no* expanden más y se incorporan a la lista principal de tokens que está siendo construida por `\directlua` (dentro de la función `scan_toks()`). Poner tokens en una lista de tokens creada por `\\toks` es otra forma de evitar que los tokens se expandan.

Si ejecutamos este ejemplo, también produce un error:

`secuencia de escape no válida cerca de ' "\T'.`

Exploraremos las secuencias de escape de Lua más adelante en el artículo.

## Otros comandos/técnicas usados en la expansión

En esta sección vemos algunos comandos/métodos adicionales de TeX que pueden ser útiles en situaciones en las que se aplica la expansión (como dentro de `\directlua`).

### \string ⟨token⟩

`\string` es un comando expandible que convierte el ⟨token⟩ en una serie de tokens de caracteres, cada uno con código de categoría 12.

Por ejemplo, `\string\TeX` produciría una serie de 4 tokens de caracteres `\`, `T`, `e` y `X` donde a cada carácter se le asigna código de categoría 12 (incluido el `\` carácter inicial).

original

```
\directlua{
   local x="Usaré \string\newcommand"
   print(x)
}
```

la `\string` se expandirá, dando como resultado una secuencia de tokens de caracteres con código de categoría 12. Después de que `\string` se expanda, los tokens de caracteres resultantes (que representan cada carácter en `\newcommand`) se incorporarán a la lista principal de tokens que está siendo construida por `\directlua`. Una vez que `\directlua` haya terminado de construir su lista principal de tokens, sus tokens constituyentes se convierten de nuevo a su representación textual, lo que produce el siguiente código para pasarlo al intérprete de Lua:

`local x="Usaré \newcommand" print(x)`

Cuando este código se pasa a Lua, `print(x)` mostrará la cadena `x` en la pantalla (consola). Sin embargo, hemos sido un poco astutos y hemos usado deliberadamente un ejemplo de comando que empieza con `\n`. Si puedes ejecutar este ejemplo en una instalación local de TeX, notarás que Lua imprime el siguiente texto en la pantalla:

```
   Usaré
   ewcommand
```

Para ejecutar este código en Overleaf puedes indicarle a LuaTeX que escriba directamente en el `.log` archivo usando la función de la API Lua de LuaTeX `texio.write(*cadena*)`:

```
\directlua{
   local x="Usaré \string\newcommand"
   texio.write(x)
}
```

Si inspeccionas el `.log` archivo resultante verás que también contiene

```
   Usaré
   ewcommand
```

Esta salida inesperada se debe a que Lua interpreta el `\n` al comienzo de `**\n**ewcommand` como la secuencia de escape para el carácter de salto de línea (código de carácter 10): asume que quieres comenzar una nueva línea de texto que empiece con `ewcommand`. Hablamos de las secuencias de escape de Lua más adelante en este artículo.

### \detokenize{⟨material⟩}

`\detokenize` es, en sus efectos, una versión de varios tokens de `\string` y también es un comando expandible que convierte todo lo que hay en `⟨material⟩` en una secuencia de tokens de caracteres con código de categoría 12 —*salvo* los caracteres de espacio (valor ASCII/Unicode 32) que obtienen código de categoría 10. `\detokenize` también inserta un carácter de espacio final después de los nombres de comando que son *palabras de control* (por ejemplo, `\\foo`) pero no se inserta un carácter de espacio después de *símbolos de control* (por ejemplo, `\#`, `\%` etc.).

### Ejemplo

Incluso si las macros `\foohoo`, `\\foo`, `\bar` y `\foobar` no están definidas, si escribes esto:

```
\directlua{
   local x = "\string\foohoo\detokenize{\foo\bar\foobar}"
}
```

produciría el siguiente texto como código para pasarlo al intérprete de Lua

`local x = "\foohoo\foo \bar \foobar "`

Si no usas `\string` y `\detokenize` y escribes:

`\directlua{local x = "\foohoo\foo\bar\foobar"}`

`\directlua` procesaría `\foohoo`, reconoce que es un comando e intenta expandirlo; pero como `\foohoo` no está definida, daría lugar a un error:

```
   ! Secuencia de control indefinida.
   l.1 \directlua{local x = "\foohoo
                      \foo\bar\foobar"}
         ?
```

Porque `\string` y `\detokenize` convierten sus argumentos en una serie de tokens de caracteres, `\directlua`el proceso de expansión de sí obtiene la oportunidad de detectar tokens de comandos expandibles `\foohoo`, `\\foo`, `\bar`, o `\foobar`: se transforman en secuencias de tokens de caracteres mucho antes de que puedan activar la expansión.

Como se señaló anteriormente, la expansión de un comando implica eliminarlo de la entrada y reemplazarlo con el resultado de su “comportamiento de expansión”. Los resultados de la expansión (normalmente tokens) son leídos posteriormente por el motor TeX. Aquí, el “comportamiento de expansión” de `\string` y `\detokenize` es absorber tokens de caracteres y comandos de la entrada y convertirlos en secuencias de tokens de caracteres, inicialmente almacenadas en una lista temporal de tokens, que `\directlua` lee posteriormente. Esos tokens de caracteres pasan a incorporarse a la lista principal de tokens que está construyendo `\directlua`.

La siguiente gráfica muestra cómo `\string` convierte el `\foohoo` comando en una secuencia de tokens de caracteres, produciendo una lista temporal de tokens que posteriormente lee `\directlua` para incorporar esos tokens de caracteres a la lista principal de tokens que se está construyendo.

![](/files/53f131b47b3eb689189dc0548aad9318f2064452)

Si `\string` o `\detokenize` encuentran caracteres en su argumento, por ejemplo, `\string a` o `\detokenize{abc}` esos caracteres (aquí, con código de categoría 11) producen tokens de caracteres pero con código de categoría 12.

Notas:

Si volvemos al ejemplo anterior:

`\directlua{local x = "\string\foohoo\detokenize{\foo\bar\foobar}"}`

que produce el siguiente texto como código para pasarlo al intérprete de Lua

`local x = "\foohoo\foo \bar \foobar "`

podemos observar lo siguiente:

* `\detokenize` ha insertado un carácter de espacio después de cada nombre de macro, pero `\string` no lo hizo.
* `\string` actúa sobre un único token.
* En la cadena `"\foohoo\foo \bar \foobar "` se usa para definir `x` volveremos a encontrar el mecanismo de caracteres de escape de Lua (analizado más abajo):

  * `\bar` empieza con `\b` que es la secuencia de escape de Lua utilizada para representar el [carácter de retroceso](https://en.wikipedia.org/wiki/Backspace) (código de carácter 8);
  * comandos `\foohoo`, `\\foo` y `\foobar` todo empieza con `\f`, la secuencia de escape de Lua utilizada para representar el [carácter de avance de página](https://en.wikipedia.org/wiki/Page_break#Form_feed) (código de carácter 12).

  Porque las secuencias de caracteres `\b` y `\f` se usan dentro de una cadena creada con comillas dobles `"..."` producirán resultados no deseados a menos que se tomen medidas para evitarlo usando el llamado *corchetes largos* método de cadenas: un tema que ahora podemos tratar junto con las secuencias de escape de Lua.

## ¿Qué son las «secuencias de escape de Lua»?

Los lenguajes de programación reservan ciertos caracteres para “uso especial” como parte de la sintaxis del lenguaje: en efecto, esos caracteres se definen para tener alguna forma de significado especial. Sin embargo, hay ocasiones en las que necesitas “desactivar” temporalmente el significado especial de un carácter si, por ejemplo, quieres que ese carácter esté incrustado como parte de una cadena más larga en la que su comportamiento estándar introduciría errores de sintaxis. En esencia, ese carácter necesita ser procesado *sin* haciendo que su interpretación estándar se active, es decir, que pase inadvertido. Para ello, los programadores usan una técnica llamada *escape* en la que un “carácter especial” se representa mediante su llamada *secuencia de escape*.

Un ejemplo habitual (también compatible con Lua) es usar comillas dobles dentro de una cadena, donde se escapan las comillas dobles internas usando la secuencia de escape `\"`:

`"Cuando les preguntaron sobre LuaTeX respondieron: \"¡Es un motor TeX asombroso!\" Estoy de acuerdo."`

El lenguaje Lua proporciona varios mecanismos para trabajar con secuencias de escape:

* secuencias estándar, entre ellas `\n` (salto de línea), `\r` (retorno de carro), `\\` (barra invertida), `\"` (comillas dobles), `\t` (tabulación horizontal), `\v` (tabulación vertical) y `\'` (comilla simple);
* `\xXX`, donde `XX` es una secuencia de exactamente dos dígitos hexadecimales;
* `\ddd`, donde `ddd` es una secuencia de hasta tres dígitos decimales;
* en el momento en que se escribió este artículo (agosto de 2019), la última versión de LuaTeX, aunque aún no estaba disponible en Overleaf, usa la versión 5.3 de Lua, que introdujo soporte para secuencias de escape UTF-8: `\u{XXX}`. Este mecanismo de escape es para caracteres Unicode codificados en UTF-8, donde `XXX` es una secuencia de uno o más dígitos hexadecimales que representan el punto de código del carácter. Ten en cuenta que los corchetes de cierre `{ }` son obligatorios.

### Control de las secuencias de escape

Tradicionalmente, las cadenas se definen usando comillas dobles, como en `"esto es una cadena"`; dentro de una cadena así puedes usar secuencias de escape: `"esto es una cadena.\nAhora empezaré en una nueva línea."`. Sin embargo, Lua tiene un segundo y *muy* cómodo mecanismo para definir cadenas: su llamado *corchetes largos* mecanismo en el que defines una cadena encerrando el texto entre `[[` y `]]`:

`[[Soy una cadena de corchetes largos]]`

Dentro de una cadena creada con el método de corchetes largos, el mecanismo de escape de caracteres de Lua está *desactivado*: las secuencias de escape se tratan como caracteres normales. Por ejemplo, en la cadena

`[[Soy una cadena de corchetes largos\n cadena]]`

la `\n` la secuencia de escape no se trata como el único carácter de retorno de carro (código ASCII 13), sino como dos caracteres normales: `\` seguido de `n`.

### ¿Por qué son tan útiles las cadenas de corchetes largos?

Como veremos más adelante, LuaTeX proporciona un conjunto de funciones Lua especializadas e integradas que puedes usar con `\directlua` para controlar el comportamiento de composición tipográfica de LuaTeX. Entre esas muchas funciones hay una llamada `tex.print(*string*)` que te permite pasar `*string*` material desde código Lua de vuelta a LuaTeX para su composición tipográfica. Un ejemplo muy simple es:

`\directlua{tex.print(\"¡Hola, mundo!\") }`

lo que hará que LuaTeX componga tipográficamente `¡Hola, mundo!`

El `*string*` utilizado en `tex.print(*string*)` también puede incluir texto que represente comandos de TeX y LaTeX para que LuaTeX lo procese. Sin embargo, los comandos de TeX/LaTeX empiezan con un `\` carácter, lo cual es problemático con las cadenas creadas usando comillas dobles porque Lua intentaría analizar la cadena, detectar el `\` carácter inicial e interpretarlo como el comienzo de una secuencia de escape. Cuando Lua intenta procesar la secuencia de escape, normalmente fallará porque el `\` combinado con la primera letra de muchos nombres de comandos de TeX/LaTeX no forma una secuencia de escape válida conocida por Lua. Por ejemplo, al procesar una cadena como `"Me gusta \LaTeX"` Lua vería `\L` y fallaría con el error “invalid escape sequence”, y esta es la causa de los errores mencionados arriba.

#### ¡Las cadenas de corchetes largos vienen al rescate!

El método de corchetes largos para crear (definir) cadenas es extremadamente útil porque, aunque los comandos de TeX/LaTeX empiezan con una `\` carácter, el método de cadenas de corchetes largos desactiva el mecanismo de secuencias de escape de Lua. Aquí tienes un breve ejemplo, recordando que necesitamos impedir que las macros se expandan usando, por ejemplo, `\protected` o `\noexpand`.

Supongamos que definimos una `\newtest` macro como esta

`**\protected**\def\newtest#1{El argumento: #1}`

y la usamos en `\directlua` con la función de la API Lua de LuaTeX `tex.print()`:

```
\directlua{
   tex.print("\newtest{Hola}")
}
```

Debido al uso de `\protected`, `\newtest` la macro

`no se expande, lo que da como resultado el siguiente texto pasado a Lua:`

El carácter de espacio añadido después de `\newtest` y antes de la llave de apertura (`{`) es un efecto secundario de `\directlua`la conversión de LuaTeX de los tokens de comando de vuelta a su representación textual.

Este código se pasa a Lua, que posteriormente ejecuta la función de LuaTeX `tex.print()` pero hay un problema que se manifiesta de formas que dependen de las fuentes que estés usando. En LaTeX en Overleaf verías una salida como esta:

![](/files/2bc06dc8480f281871f8347f7f3d7301aa62d20f)

junto con una advertencia en el archivo de registro:

```
   Carácter faltante: no hay
   (U+000A) en la fuente [lmroman10-regular]:+tlig;!
```

En plain TeX podrías ver una salida que se parece a esto:

![](/files/cc365426930961b288eec58b66509a175cabf17c)

En ambos casos, la `\newtest` macro no se llama y la salida no es la que pretendíamos. El error lo causa el mecanismo de caracteres de escape de Lua: en el texto `\newtest {Hola}` el nombre de la macro empieza con `\n` que Lua reconoce como la secuencia de escape de un carácter de salto de línea, por lo que lo reemplaza `\n` por el carácter ASCII 10, o en hexadecimal 0A. En el mensaje de error de LaTeX, `U+000A` es una forma de representar el valor Unicode usando 4 dígitos hexadecimales.

Debido a que el `\n` se convierte en el carácter de salto de línea, LuaTeX no ve una llamada a macro, sino que cree que se le pide componer tipográficamente un texto que empieza con el código de carácter ASCII 10:

`⟨ASCII 10⟩ewtest {Hola}`

Dependiendo de la fuente utilizada, LuaTeX puede, o no, ser capaz de componer tipográficamente el `⟨ASCII 10⟩` carácter, pero el texto restante se muestra tal cual con la `{` y `}` tratada como un grupo y no se imprime.

Plain TeX da un resultado distinto porque la fuente predeterminada es Computer Modern Roman, que tiene una codificación extraña que hace que, al ver el código de carácter 10, se componga tipográficamente una Omega mayúscula.

Para evitar estos problemas necesitamos usar cadenas de corchetes largos para impedir que se aplique el mecanismo de escape de Lua. El resultado correcto se obtiene con

`\directlua{tex.print([[\newtest{Hola}]])}`

lo que produce el resultado mostrado en la siguiente captura:

![](/files/f8e1fee29703a6e8b15cd0e6cede80ab4f117381)

### Expansión y no ejecución de comandos no expandibles

Al hablar de la expansión señalamos que es un proceso en el que un motor TeX *elimina* un comando expandible (token) de la entrada actual y *lo reemplaza* por el/los resultado(s) producido(s) por ese comando expandible. Como \directlua está realizando *solo expansión* actividades (para generar una lista de tokens), no *no* lleva el procesamiento de LuaTeX más allá de eso. Una vez que se ha leído y expandido por completo un comando expandible, los resultados de esa expansión —que con frecuencia incluyen comandos no expandibles (tokens)— se incorporarán a la lista de tokens que se está construyendo, lista que estará lista para convertirse de nuevo en texto y pasarse a Lua.

Aquí hay un principio importante en juego: durante *solo expansión* las actividades diseñadas para producir una lista de tokens, los motores TeX, incluido LuaTeX, *no ejecutan* ningún comando primitivo integrado de TeX que no sea expandible.

En el caso de `\directlua{⟨code⟩}`, `⟨code⟩` produce, o contiene comandos TeX/LaTeX no expandibles, estos *se pasarán a Lua* (representados como texto).

#### Ejemplo

Aquí tienes un ejemplo para demostrar que los primitivos no expandibles no se ejecutan durante el procesamiento de solo expansión (como dentro de `\directlua`). Supongamos que definimos una macro `\setcountreg` así:

`\def\setcountreg#1#2{\count#1=#2\relax}`

**Nota**: Usamos `\relax` después del parámetro `#2` para evitar que LuaTeX se pase de largo al escanear la entrada en busca del valor numérico (argumento) que coincida con el parámetro `#2`.

Si, fuera de `\directlua`, ejecutamos después la macro así

```
   \setcountreg{100}{50}
   El valor en el registro de conteo 100 es \the\count100.
```

generaría

`El valor en el registro de conteo 100 es 50.`

En este contexto, cualquier motor TeX procesaría la macro `\setcountreg`—expandir la macro, determinar los argumentos y continuar leyendo *y acción* (ejecutar) los comandos contenidos en el texto de reemplazo de la macro (definición). El resultado aquí es asignar `50` como valor almacenado en el registro `\count100`.

Sin embargo, cuando un motor TeX está realizando *solo expansión* actividades, como ocurre con `\directlua`, no *ejecutará* los comandos no expandibles contenidos en la definición de la macro.

original

```
\def\setcountreg#1#2{\count#1=#2\relax}
\directlua{
   local x = [[\setcountreg{100}{50}]]
}
```

produce el siguiente texto como código para Lua:

`local x = [[\count 100=50\relax ]]`

El código Lua producido arriba muestra que dentro de `\directlua` la `\setcountreg` se ha expandido, sus argumentos han sido identificados y sustituidos en el parámetro apropiado (`#1` y `#2`) pero no va más allá de eso: el comando primitivo de TeX no expandible `\\count` fue *no se ejecuta* durante `\directlua`el procesamiento de expansión de LuaTeX.

Sin embargo, LuaTeX ejecutará el código TeX si pasamos la cadena resultante `x` *de vuelta a LuaTeX* a través de `tex.print(x)` así

```
\count100=50 % establece \count100 en un valor inicial de 50
\def\setcountreg#1#2{\count#1=#2\relax}
\directlua{
   local x = [[\setcountreg{100}{250}]]
   tex.print(x)
}
El valor almacenado en el registro de conteo 100 es \the\count100.
```

Después de `\directlua` haber terminado, la salida sería

`El valor almacenado en el registro de conteo 100 es 250.`

lo que muestra que el registro de conteo `100` ahora contiene el valor `250`.

El código Lua producido a partir del ejemplo anterior es

`local x = [[\count 100=250\relax ]] tex.print(x)`

Este código define `x` como una cadena creada usando el método de corchetes largos, que se utiliza para evitar errores con secuencias de escape erróneas. Si usáramos comillas dobles `"..."` para definir x, la combinación de caracteres `\c` al comienzo de `\\count` provocaría un error: `secuencia de escape no válida cerca de ' "\c'`.

La llamada a la API Lua de LuaTeX `tex.print(x)` hace que LuaTeX ejecute la secuencia de código TeX `\count 100=250\relax` y `\count100` se le asigna un valor de `250` como se ve en la salida compuesta:

`El valor almacenado en el registro de conteo 100 es 250.`

#### Precaución: macros y la API Lua de LuaTeX

En el ejemplo anterior vimos que durante `\directlua`el preprocesamiento (expansión) de LuaTeX no se ejecutó el código `\count 100=250`, que contiene el `no expandibles` comando primitivo `\\count`: para ejecutar ese código tuvimos que *devolverlo a LuaTeX* a través de `tex.print()`.

`\directlua` es solo un caso en el que LuaTeX está realizando un procesamiento de solo expansión para construir una lista de tokens. Hay otros comandos que realizan actividades similares de procesamiento de expansión y generación de listas de tokens, como `\write` y `\edef`: esos comandos tampoco ejecutan primitivos no expandibles durante su procesamiento de expansión. Es un principio general que los motores TeX no ejecutan primitivos no expandibles al construir una lista de tokens durante actividades de procesamiento de solo expansión.

**Reescribiendo nuestra macro para usar la API Lua de LuaTeX**

Podemos reescribir la `\setcountreg` macro usando una función de la API Lua de LuaTeX llamada `tex.setcount()`, evitando así comandos TeX para cambiar el valor almacenado en el registro de conteo `100`:

```
   \def\setcount#1#2{\directlua{tex.setcount(#1,#2)}}
   \count100=50
   el registro de conteo 100 contiene \the\count100\par
   \setcount{100}{250}
   el registro de conteo 100 ahora contiene \the\count100\par
```

Este código compondrá tipográficamente:

```
el registro de conteo 100 contiene 50
el registro de conteo 100 ahora contiene 250
```

Aquí estamos usando `tex.setcount()`, una de las muchas funciones de la API Lua de LuaTeX, para *acceder directamente a* el área interna de almacenamiento de datos de LuaTeX para colocar el valor `250` en la ubicación de memoria que representa el registro de conteo `100`. En efecto, hemos *eludido* los métodos estándar de procesamiento de entrada del motor TeX de LuaTeX: leer la entrada, crear tokens y ejecutar comandos primitivos de TeX. Sin embargo, hay una advertencia: al usar las funciones de la API Lua de LuaTeX, la actividad de procesamiento de solo expansión *puede dar lugar a efectos secundarios*: cambios en valores almacenados dentro del motor TeX que de otro modo no serían posibles con comandos puramente TeX/LaTeX.

**Ejemplo: efectos secundarios inesperados**

Aquí tienes un ejemplo para demostrar *inesperados* efectos secundarios que pueden surgir con macros que usan `\directlua`. Supongamos que escribimos el siguiente código:

```
\def\dochange{\directlua{tex.setcount(999,12345)}}
\edef\careful{\dochange}
\the\count999
```

Al ejecutar este código se compone tipográficamente `12345`!

¿Cómo puede ser? No *explícitamente* llamamos a ningún código ni macro para poner ese valor en el registro de conteo `999`. ¿O sí?

Definimos `\dochange` con un `\directlua` comando que usa `tex.setcount()` para almacenar el valor `12345` en el registro de conteo `999`: en código TeX equivale a `\count999=12345`. Luego usamos el primitivo estándar de TeX `\edef` para definir la macro `\careful`—es el uso de `\edef` lo que desencadena el efecto secundario inesperado.

`\edef` expande completamente su argumento: aquí detecta una macro expandible `\dochange` y la expande. La `\dochange` macro usa el comando expandible `\directlua` que contiene una llamada a la API Lua; por tanto, la expansión de `\dochange` da como resultado la expansión de `\directlua` y eso hace que `tex.setcount()` se llame, lo que cambia el valor en el registro de conteo `999`.

Si redefinimos `\dochange` para usar comandos TeX:

```
   Antes: el registro de conteo 999 contiene \the\count999.\par
   \def\dochange{\count999=12345\relax}
   \edef\careful{\dochange}
   Después: el registro de conteo 999 contiene \the\count999.\par
```

al ejecutar este código se compone tipográficamente

```
Antes: el registro de conteo 999 contiene 0.
Después: el registro de conteo 999 contiene 0.
```

Claramente, no hubo ningún efecto sobre `\count999`. Cuando `\edef` define `\careful` lo expande `\dochange` pero esa expansión solo produce primitivos TeX no expandibles: estos *no se ejecuta* sino simplemente *almacenados* en la lista de tokens que compone la definición de `\careful`.

Por si fuera poco, el mismo principio explica por qué esto produce salida compuesta:

```
\def\dochange{\directlua{tex.print(\"Hola\")}}
\edef\careful{\dochange}
```

## Breve introducción a la API Lua de LuaTeX

Como hemos visto, `\directlua` no solo te permite escribir código Lua convencional, o una mezcla de código Lua y TeX/LaTeX, sino que también proporciona acceso a un conjunto de funciones Lua adicionales (específicas de LuaTeX) que puedes usar (invocar) para comunicarte con el funcionamiento interno del software de composición tipográfica de LuaTeX, o controlarlo directamente. Hemos usado varias funciones Lua en este artículo, `tex.print()`, `texio.write()`, `tex.setcount()` y estas, junto con *muchas* más, se documentan en [El Manual de referencia de LuaTeX](http://www.pragma-ade.com/general/manuals/luatex.pdf) en el que los grupos de funciones relacionadas se denominan *bibliotecas*.

Puedes considerar estas funciones de Lua como la API de Lua de LuaTeX (**A**plicación **P**rogramación **I**nterfaz), que proporcionan las herramientas para construir soluciones sofisticadas de composición tipográfica e ingeniería de documentos controlando el comportamiento de composición tipográfica de LuaTeX usando Lua como controlador.

Como se ha señalado, LuaTeX organiza su API en un conjunto de funciones que llama bibliotecas: grupos de funciones relacionadas por su propósito o sus acciones. Cada conjunto de funciones está diseñado para proporcionar acceso a un aspecto particular de los procesos internos, estructuras de datos, almacenamiento de datos y algoritmos de composición tipográfica de LuaTeX. Internamente, LuaTeX se construye a partir de múltiples componentes: bibliotecas/herramientas de software (escritas en su mayor parte en C) que no solo componen el propio motor de TeX sino también otros subsistemas, incluidos Lua, MetaPost, Kpathsea, FontForge, libpng y zlib. Estas bibliotecas se integran para construir las características y funciones del software ejecutable de LuaTeX, y es a través de la API de Lua que los usuarios obtienen acceso a la funcionalidad de LuaTeX derivada de la integración y coordinación de esos múltiples componentes de software.

## Algunos ejemplos y errores comunes

En esta sección presentamos algunos ejemplos adicionales que hacen uso de los temas, conceptos y explicaciones proporcionados en este artículo.

### Uso del carácter tilde (\~)

El lenguaje Lua usa el `~` carácter (llamado tilde) como parte de su sintaxis, incluida su sintaxis para realizar una comprobación de “distinto de”; por ejemplo, para comprobar si una variable `x` es distinto de `4` podríamos escribir:

```
   local x=3
   if x ~= 4 then
   print("x is not equal to 4")
   end
```

Si intentamos ejecutar este simple código Lua mediante `\directlua`:

```
\directlua{
   local x=3
   if x ~= 4 then
   print("x is not equal to 4")
   end
}
```

obtenemos un error:

`[\directlua]:1: 'then' expected near '\'.`

Es extraño porque nuestro código es correcto: hemos usado `'then'` y no hay ningún `\` carácter en nuestro código, así que ¿qué salió mal? Para entender esto, debemos recordar que, para TeX/LaTeX, `~` suele definirse como un “carácter especial” con código de categoría 13: los llamados caracteres activos, que son minimacros y por tanto están sujetos a expansión. Cuando `\directlua` detecta el `~` carácter, se expande mediante *eliminarlo* de la entrada y *reemplazándolo* y reemplazándolo por el resultado de su expansión. Usando plain TeX, el texto resultante (código) que LuaTeX produce y pasa al intérprete de Lua en realidad no contiene el `~` carácter, y es:

`local x=3 if x \penalty \@M \ = 4 then print("x is not equal to 4") end`

El `~` el carácter ha sido *eliminado* y *expandido* en sus comandos constituyentes: el código Lua anterior resulta de la definición, en plain TeX, del carácter activo `~`. Ahora podemos ver por qué Lua responde con el error `'then' expected near '\'`—empieza a analizar este código, pero se encuentra con la palabra `\penalty` que no significa nada para Lua y genera un error de sintaxis.

Para corregir esto, el `~` carácter debe tener un código de categoría seguro en el momento en que `\directlua` está procesando tu código; por ejemplo, podemos cambiar temporalmente el código de categoría de `~` a 11 (letra) encerrando el código en un grupo:

```
\begingroup
\catcode`\~=11
\directlua{
   local x=3
   if x ~= 4 then
   print("x is not equal to 4")
   end
}
\endgroup
```

Este código funciona como se espera y `x no es igual a 4` se imprime en la consola. Hay otras opciones: podemos usar los comandos expandibles `\noexpand` o `\string`.

#### Uso de \string⟨token⟩

Podemos aplicar `\string` al `⟨token⟩` `~` que tiene código de categoría 13 (carácter activo); `\string` convierte el `~` carácter para generar un token de carácter que tiene código de categoría 12. Si hacemos

```
\directlua{
   local x=3
   if x \string~= 4 then
   print("x is not equal to 4")
   end
}
```

produce el código Lua que necesitamos:

`local x=3 if x ~= 4 then tex.print("x no es igual a 4") end`

#### Uso de \noexpand⟨token⟩

Podemos usar `\noexpand~` para suprimir la expansión del carácter activo `~`

```
\directlua{
   local x=3
   if x \noexpand~= 4 then
   print("x is not equal to 4")
   end
}
```

El `~` token no expandido pasa a la lista de tokens que se está construyendo en `\directlua` y se volverá a convertir en texto, lo que producirá código Lua funcional.

### Uso del carácter \#

Dentro del lenguaje Lua, el `#` carácter se puede usar para obtener la longitud de una tabla. Sin embargo, si probamos el siguiente código

```
\directlua{
   local tbl = {}
   tbl[1] = "Hello"
   tbl[2] = "World"
   tex.print("Table length is 2")
}
```

podríamos esperar que LuaTeX compusiera

`La longitud de la tabla es 2`

pero genera un error:

`\directlua]:1: attempt to get length of a number value`

Este error se produce porque el `#` carácter suele tener el código de categoría 6 (parámetro de macro)—el `#` carácter tiene dos usos en TeX/LaTeX: indicar parámetros de macro (`#1`, `#2`… `#9`) y el texto de reemplazo en plantillas de alineación (para `\halign` y `\valign`).

Cuando `\directlua` está generando tokens para construir su lista de tokens, ve el `#` carácter con código de categoría 6 y crea un token de carácter adecuado para representarlo. Cuando llega el momento de convertir la lista final de tokens de nuevo a forma textual, el token de carácter para # (con código de categoría 6) recibe un tratamiento especial: se emite como *dos caracteres consecutivos*: `##`, lo que da lugar a que el siguiente código se pase a Lua:

`local tbl = {} tbl[1] = "Hello" tbl[2] = "World" print(##tbl)`

Al convertirlo a código Lua, el original `#` se ha duplicado y eso genera un error:

`\directlua]:1: attempt to get length of a number value`

Este problema surge debido a la sintaxis de TeX, que usa un símbolo de almohadilla doble `##` para representar o generar un solo `#` token; esta sintaxis se usa en macros que definen otras macros que toman parámetros, o en macros usadas para crear plantillas para los comandos de `\halign` o `\valign` construcción de tablas. Esto resulta bastante confuso, así que veamos un ejemplo.

#### Ejemplo

Supongamos que definimos una macro `\mymacro` que toma un solo parámetro, `#1`, pero también define una segunda macro `\\foo` que a su vez toma un solo parámetro. Para distinguir entre el parámetro `#1` usado con `\mymacro` y la necesidad de definir `\\foo` para usar su propio parámetro `#1` la sintaxis de TeX exige que uses `##1` dentro de `\mymacro` para representar el parámetro que se usará con `\\foo`:

`\def\mymacro#1{\def\foo##1{#1 Hello##1}}`

Si escribieras `\mymacro{Hey!}` definiría la macro `\\foo` como

`\def\foo#1{Hey! Hello#1}`

Obsérvese que el `\mymacro`el parámetro de `#1` (`Hey!`) se ha incorporado en la definición de `\\foo` y la secuencia `##1` se ha convertido en `#1` en la definición de `\\foo`. Así que podemos usar `\\foo` así:

`\foo{, World!}`

que compusiera `¡Hey! ¡Hola, mundo!`

Podemos resolver `\directlua`el tratamiento de `#` carácter cambiando temporalmente su código de categoría antes de que LuaTeX procese el código. Por ejemplo:

```
\begingroup
   \catcode`\#=11
   \directlua{
   local tbl = {}
   tbl[1] = "Hello"
   tbl[2] = "World"
   tex.print("Table length is 2")
}
\endgroup
```

Esto genera el código Lua

```
local tbl = {} tbl[1] = "Hello" tbl[2] = "World" tex.print("Table length is "..#tbl)
```

lo que compone el resultado que esperábamos:

`La longitud de la tabla es 2`

### Uso del carácter %

Dentro de TeX/LaTeX, el `%` carácter se usa normalmente para incluir comentarios de una sola línea en tu código: para indicar al motor TeX que debe ignorar todo desde ese punto hasta el final de la línea en la que se escribe el `%` Sin embargo, dentro del lenguaje Lua, el `%` carácter se usa en algunas funciones de procesamiento de cadenas muy útiles, como `string.format(...)`, `string.gmatch(...)`y `string.gsub(...)` en las que el `%` carácter desempeña un papel importante como parte de la sintaxis de esas funciones.

Cuando se usa con TeX/LaTeX, `%` actúa como carácter de comentario porque se le asigna el código de categoría 14. Para hacer que se comporte como un carácter normal y desactivar su comportamiento habitual en TeX/LaTeX, necesitamos cambiar su código de categoría a algo seguro, como 12. El `\directlua` ejemplo siguiente usa varias técnicas comentadas antes en el artículo, junto con una que todavía no hemos mencionado: ``\catcode`\^^M=12``, lo que nos permite usar comentarios de Lua en nuestro código; esto se analiza más abajo.

#### Ejemplo

Los siguientes ejemplos están tomados de [lua-users.org](http://lua-users.org/wiki/StringLibraryTutorial), modificados convenientemente para su uso dentro de `\directlua`.

```
\documentclass{article}
\begin{document}
\begingroup
\ttfamily
\let\\\relax
\catcode`\^^M=12 %<---we further explore this below!
\catcode`\%=12
\directlua{
   local str -- declara una variable local para contener el resultado

   tex.print("Using string.format():".."\\par")

   str=string.format("%s %q", "Hello", "Lua user!") -- string and quoted string
   tex.print(str.."\\par")
   str = string.format("%c%c%c", 76, 117, 97) -- char
   tex.print(str.."\\par")
   str=string.format("%e, %E", math.pi, math.pi) -- exponent
   tex.print(str.."\\par")
   str=string.format("%f", math.pi) -- float
   tex.print(str.."\\par")
   str=string.format("%g, %g", math.pi, 10^9) -- float or exponent
   tex.print(str.."\\par")
   str = string.format("%o, %x, %X", 99, 125, 125)  -- octal, hexadecimal, hexadecimal
   tex.print(str.."\\par")

   tex.print("\\vskip3mm".."Using string.gmatch():".."\\par")

   for word in string.gmatch("Hello TeX user", "%a+") do
      tex.print(word.."\\par")
   end

   tex.print("\\vskip3mm".."Using string.gsub():".."\\par")
   str=string.gsub("banana", "(an)", "%1-") -- capture any occurrences of "an" and replace
   tex.print(str.."\\par")
}
\endgroup
\end{document}
```

La siguiente captura de pantalla muestra el resultado compuesto del código anterior:

![Uso de funciones de cadena de Lua en \directlua](/files/d99bf27152107bac4dd042b63c0263620184d75e)

## ¿Por qué el código Lua se muestra en una sola línea?

Como habrás notado, todos los fragmentos de código Lua (generados) que se muestran en los ejemplos de este artículo se presentan como una sola línea de texto: los saltos de línea que originalmente estaban presentes en los `\directlua` fragmentos de código no se conservan. ¿Por qué? Porque los saltos de línea en el código Lua han sido *eliminados* durante el preprocesamiento de LuaTeX dentro de `\directlua`, haciendo que el código Lua se convierta en una larga línea de texto. Ese comportamiento se puede rastrear hasta la forma en que los motores TeX manejan los caracteres de fin de línea, denotados por `\r` (retorno de carro) y `\n` (avance de línea) en la literatura de programación. Por qué podríamos necesitar preocuparnos por estos detalles quedará claro cuando hablemos de usar los mecanismos de Lua para comentar secciones de código.

Cuando el software escribe (guarda) un archivo de texto, cada línea individual de texto termina con los llamados caracteres de “nueva línea”; el o los caracteres reales de nueva línea dependen de la aplicación y del sistema operativo que se esté usando para escribir ese archivo. Wikipedia tiene un [artículo interesante](https://en.wikipedia.org/wiki/Newline) que explora la historia/evolución de los caracteres de nueva línea que se usan hoy en día.

Dado cualquier archivo de texto, sus líneas individuales de texto podrían terminar con diversas combinaciones de caracteres, denominados retorno de carro (carácter ASCII/Unicode 13) y/o avance de línea (carácter ASCII/Unicode 10), que se denotan por `\r` y `\n` respectivamente. Como los motores TeX están diseñados para ser independientes de la plataforma, necesitan un método para sortear la naturaleza inherentemente dependiente de la plataforma de los finales de línea usados en los archivos de texto. Naturalmente, los motores TeX tienen un método integrado (pero configurable) para tratar los caracteres de terminación de línea.

### Cómo gestionan los motores TeX los finales de línea

Cuando LuaTeX procesa `\directlua{⟨code⟩}` lee el texto contenido en tu `⟨code⟩` y aplica los métodos estándar del motor TeX para procesar cualquier final de línea contenido en tu `⟨code⟩`. De forma predeterminada, esos métodos estándar de TeX hacen que todos los caracteres de terminación de línea (retornos de carro y avances de línea) se eliminen y se sustituyan por caracteres de espacio. Decimos “de forma predeterminada” porque el tratamiento de los caracteres de terminación de línea por parte de un motor TeX puede modificarse mediante un parámetro configurable por el usuario llamado `\endlinechar`. Aquí ofreceremos una breve visión general en dos pasos, pero pueden encontrarse más detalles en el artículo de Overleaf [Introducción a \endlinechar: cómo TeX lee líneas de archivos de texto](/latex/es/articulos-en-profundidad/05-an-introduction-to-endlinechar-how-tex-reads-lines-from-text-files.md).

#### Paso 1: TeX inserta su propio carácter de fin de línea

Después de leer una línea de texto de tu archivo de entrada, los motores TeX eliminan inmediatamente cualquier `\r` o `\n` carácter del final de esa línea. A continuación, los motores TeX *insertan* añaden de nuevo su propio carácter de terminación de línea al final de esa línea. Ese carácter está determinado por el valor de un parámetro de TeX configurable por el usuario llamado `\endlinechar` y es mediante este mecanismo que los motores TeX pueden procesar los caracteres de fin de línea de forma independiente de la plataforma: ellos eligen y establecen el carácter de fin de línea con independencia de lo que contuviera originalmente el archivo de texto de entrada.

Normalmente, los motores TeX usan el ajuste

`\endlinechar=13`

que es el carácter de retorno de carro (`\r`). Sin embargo, los usuarios siempre pueden asignar otro código de carácter como valor de `\endlinechar`—algo que veremos más adelante en este artículo.

En consecuencia, cualquier carácter o caracteres de terminación de línea contenidos en tu `⟨code⟩` que serán procesados por `\directlua{⟨code⟩}` se eliminan y se sustituyen por un único carácter determinado por el propio motor TeX. Ten en cuenta que los motores TeX realizan este procesamiento de fin de línea inmediatamente después de leer una nueva línea de texto de un archivo y *antes de que* procesar cualquier carácter de esa línea (para generar tokens). Sin embargo, esto no es todo: lo que el motor TeX *sí* con esos caracteres de fin de línea (que ha insertado) explica por qué el código Lua se convierte en una sola línea.

#### Paso 2: TeX convierte su carácter de fin de línea en un espacio

Además de insertar su propio carácter de terminación de línea, definido por el valor de `\endlinechar`, los motores TeX también usan el código de categoría 5 para los caracteres que deben ser *tratados como* un carácter de fin de línea. Como resultado, los motores TeX suelen trabajar con:

1. un carácter de fin de línea definido por `\endlinechar`;
2. ese mismo carácter *por lo general* al que se le asigna el código de categoría 5.

Es lo que TeX hace con ese carácter de fin de línea lo que explica nuestra duda respecto a las líneas únicas de código Lua. Cuando un motor TeX procesa una línea de entrada, acabará detectando el último carácter de esa línea: el carácter definido por `\endlinechar`. Normalmente, ese carácter tiene el código de categoría 5, lo que hace que TeX *lo sustituya* por un carácter de espacio: es decir, al final de línea TeX, en efecto, elimina su carácter de terminación de línea y lo reemplaza por un espacio. Como nota al margen, los motores TeX también usan caracteres con código de categoría 5 para detectar líneas en blanco e iniciar un nuevo párrafo, pero no abordaremos eso aquí.

Por supuesto, tratándose de TeX, puedes realizar todo tipo de trucos especiales de programación de macros reconfigurando el `\endlinechar` a otro carácter y/o asignando al carácter `\endlinechar` un valor de código de categoría de tu elección.

Si quieres evitar que el código Lua se convierta en una sola línea de texto, puedes cambiar (temporalmente) el valor asignado a `\endlinechar` o cambiar el código de categoría del terminador estándar de fin de línea `\r`.

### La extraña notación ^^ de TeX

En las siguientes secciones encontraremos la inusual `^^` notación, conocida como el “mecanismo de caracteres extendidos”. Fue diseñada por Knuth como una forma de facilitar la escritura de “caracteres de control” como terminadores de fin de línea, tabulaciones, etc. Por ejemplo:

* `^^J` representa el código de carácter 10 (`\n`, avance de línea);
* `^^M` representa el código de carácter 13 (`\r`, retorno de carro).

Secuencias de caracteres como `^^M` se convierten en sus códigos de carácter correspondientes en una fase temprana del proceso de escaneo de entrada de TeX, cuando TeX lee caracteres de entrada para generar los tokens de carácter correspondientes.

### Cambiar el carácter asignado a \endlinechar

Recordando que todavía necesitamos impedir la expansión del `~` carácter, podemos escribir

```
\begingroup
\endlinechar=10 % Change the end-of-line character to \n
\directlua{
   local x=3
   if x \noexpand~= 4 then
   print("x is not equal to 4")
   end
}% don’t want the \n appearing here
\endgroup% or a \n here
```

El ajuste anterior de `\endlinechar` hace que LuaTeX añada el código de carácter 10 (`\n`, avance de línea) al final de cada línea que lee. Hacemos esto porque `\n` (avance de línea) suele tener el código de categoría 12, lo cual puedes comprobar escribiendo ``\the\catcode`\^^J``. Como `\n` no tiene el código de categoría 5, LuaTeX no lo convertirá en un carácter de espacio, por lo que permanecerá al final de cada línea leída por LuaTeX. Esto da como resultado que un carácter con código 10 permanezca al final de cada línea, pasando así a la lista de tokens que se está construyendo por `\directlua` y reapareciendo posteriormente en el código Lua una vez que la lista de tokens se convierte en texto. Con el cambio anterior, el código Lua se envía al intérprete de Lua como la siguiente secuencia de caracteres:

**\n**local x=3\*\*\n**if x \~= 4 then**\n**print("x is not equal to 4")**\n**end**\n\*\*

donde la **\n** notación pretende representar el código de carácter 10 *no* alguna macro desconocida `\n`. Ahora, el intérprete de Lua verá saltos de línea en el código, exactamente como se escribió originalmente en el `\directlua` comando:

```
   local x=3
   if x ~= 4 then
   print("x is not equal to 4")
   end
```

Por cierto, observa que el primer carácter en la cadena de código Lua es `\n` (antes de la `local` palabra clave). `\n` Eso

`\directlua{`

proviene de la línea `{` porque hay un salto de línea inmediatamente después de la apertura

`\directlua{%`

### Cambiar el código de categoría de \r

Para mantener los saltos de línea en nuestro código Lua también podemos cambiar el código de categoría de `\r` a algo distinto de 5, de modo que `\r` ya no se reconozca (se trate como) un carácter de fin de línea. Con esta técnica, LuaTeX sigue usando `\endlinechar=13` y seguirá añadiendo un `\r` al final de cada línea; sin embargo, como `\r` ya no tiene el código de categoría 5, LuaTeX no reconocerá el `\r` carácter como un fin de línea: no lo convertirá en un espacio y lo pasará intacto para que aparezca en el código Lua.

Recordando que todavía necesitamos impedir la expansión del `~` carácter, podemos escribir

```
\begingroup
\catcode`\^^M=12 % change category code of \r to 12
\directlua{
   local x=3
   if x \noexpand~= 4 then
   print("x is not equal to 4")
   end
}
\endgroup
```

En este caso, el código Lua se envía al intérprete de Lua como:

**\r**local x=3\*\*\r**if x \~= 4 then**\r**print("x is not equal to 4")**\r**end**\r\*\*

donde la `\r` la notación pretende representar el código de carácter 13, no alguna macro desconocida de TeX `\r`. Al igual que con el `\endlinechar` ejemplo, el intérprete de Lua verá ahora saltos de línea en el código, exactamente como se escribió originalmente en el `\directlua` comando:

```
   local x=3
   if x ~= 4 then
   print("x is not equal to 4")
   end
```

Por cierto, observa de nuevo que el primer carácter en la cadena de código Lua es `\r` (antes de la palabra clave local): esto también proviene de la línea

`\directlua{`

#### ¿Por qué \r usó el código de categoría 12 y no el código de categoría 11?

La respuesta se debe al riesgo de introducir accidentalmente errores provocados por `\r` (de código de categoría 11) añadiéndose al final de los comandos de TeX/LaTeX leídos desde nuestro archivo de entrada. Toma este ejemplo:

```
\begingroup
\catcode`\^^M=11 % change category code of \r to 11
\directlua{
   local x=3
   if x \noexpand~= 4 then
   print("x is not equal to 4")
   end
}
\endgroup
```

que genera un error:

```
   ! Secuencia de control indefinida.
   l.9 \endgroup
```

¿Cómo puede ser eso cierto, si `\endgroup` es un comando primitivo estándar de TeX? `\endgroup`—también añadió el `\endlinechar` carácter `\r` al final de esa línea. Ahora, en su memoria, LuaTeX ve la secuencia de caracteres

`\endgroup\r`

donde usamos `\r` para indicar el carácter con código 13, no el nombre de alguna macro desconocida de TeX `\r`.

En el momento en que LuaTeX leyó esta línea de nuestro archivo de texto, el original `\begingroup` sigue operativo: estamos dentro de un grupo que aún no se ha cerrado al ejecutar el correspondiente `\endgroup` comando, lo que haría que `\r` volviera a su valor anterior de código de categoría 5.

Cuando LuaTeX comienza a procesar (crear tokens) a partir de la línea de texto `\endgroup\r` reconoce el primer carácter `\` como el carácter de escape, lo que hace que LuaTeX empiece a buscar el nombre de un comando. Para identificar un nombre de comando LuaTeX busca una secuencia de caracteres con código de categoría 11, pero como `\r` también tiene código de categoría 11, LuaTeX piensa que el `\r` carácter (todavía con código de categoría 11) forma *parte de un comando* llamado `\endgroup\r` que, por supuesto, no existe, así que LuaTeX informa de un `Secuencia de control indefinida` error. Por eso usamos el código de categoría 12 y no el 11.

Como el mensaje de error de LuaTeX se escribió en la consola, no pudimos ver/advertir fácilmente el `\r` carácter, así que no era obvio qué había causado el error.

### ¿Por qué nos preocupamos por los finales de línea?

La razón es permitir el uso del método de comentarios de Lua en tu código. Puedes usar el mecanismo estándar de LuaTeX de añadir `%` caracteres para comentar líneas individuales dentro de tu código; sin embargo, el lenguaje Lua tiene sus propios mecanismos de comentarios, muy útiles, *de varias líneas* que quizá quieras aprovechar.

Empecemos viendo qué ocurre si intentamos usar comentarios de una sola línea del lenguaje Lua sin abordar los problemas de saltos de línea. Mientras que TeX usa el `%` carácter para comentar líneas individuales de código, Lua usa un doble guion: `--`.

¿Qué ocurre si intentamos ejecutar esto:

```
\directlua{
   local x=3
   if x \noexpand~= 4 then
   -- Voy a mostrar el resultado de esta compleja prueba
   print("x is not equal to 4")
   end
}
```

Obtenemos un error:

`[\directlua]:1: se esperaba 'end' cerca de <eof>`

Este error se debe a la ausencia de saltos de línea en el código Lua pasado al intérprete, que solo ve una única cadena continua en la que el comentario comienza a mitad de camino dentro de esa cadena:

```

local x=3 if x ~= 4 then -- Voy a mostrar el resultado de esta compleja prueba print("x no es igual a 4") end
```

Todo lo que aparece después `**local x=3 if x ~= 4 then**` se trata como comentado, lo que hace que el intérprete vea un fragmento incompleto de código Lua, dando lugar al error

`'end' se esperaba cerca de <eof>`.

donde `<eof>` significa fin de archivo.

Como probablemente habrás adivinado, debemos remediarlo asegurándonos de que los saltos de línea se transmitan al código Lua resultante, lo que podemos conseguir, por ejemplo, cambiando el código de categoría de `\r` a 12:

```
\begingroup
\catcode`\^^M=12 % change category code of \r to 12
\directlua{
   local x=3
   if x \noexpand~= 4 then
   -- Voy a mostrar el resultado de esta compleja prueba
   print("x is not equal to 4")
   end
}
\endgroup
```

Ahora, el intérprete Lua ve una cadena, pero contiene `\r` saltos de línea tal como se escriben en el `\directlua` fragmento:

**\r**local x=3\*\*\r**if x \~= 4 then**\r\*\*-- Voy a mostrar el resultado de esta compleja prueba\*\*\r**tex.print("x no es igual a 4")**\r**end**\r\*\*

En efecto, esto equivale a escribir

```
   local x=3
   if x \noexpand~= 4 then
   -- Voy a mostrar el resultado de esta compleja prueba
   print("x is not equal to 4")
   end
```

lo que significa que Lua puede procesar este código correctamente e ignorar la línea que comentamos.

**Comentarios en bloque**

El lenguaje Lua también admite una sintaxis a la que llama [«comentario en bloque»](https://www.lua.org/pil/1.3.html) (o *comentario largo*): estos comienzan con `--[[` y están vigentes hasta el correspondiente `]]`. Podemos usar esta sintaxis cómoda para escribir comentarios de varias líneas, o comentar secciones de código que queremos eliminar temporalmente:

```
\begingroup
\catcode`\^^M=12 % change category code of \r to 12
\directlua{
   local x=3
   if x \noexpand~= 4 then
   --[[ Voy a mostrar el resultado de esta compleja prueba
   simplemente porque realmente es
   una conclusión tan asombrosa]]
   print("x is not equal to 4")
   end
}
\endgroup
```

## En conclusión

En primer lugar, ¡felicidades si has logrado leer este extenso artículo! Hemos intentado elaborar una guía razonablemente completa sobre conceptos y temas relacionados con TeX que proporcionan los antecedentes necesarios para sacar el máximo partido a LuaTeX mediante el `\directlua` comando. Esperamos haber producido un artículo que sea instructivo y contribuya con algo útil y valioso para la comunidad de usuarios de Overleaf, y más allá. Como siempre, nos complace recibir comentarios, así que no dudes en [contactarnos](https://www.overleaf.com/contact) con comentarios sobre este artículo o sugerencias sobre otros temas sobre los que te gustaría que escribiéramos.

Feliz $$\text{Lua}\mathrm{\TeX}\text{-ing!}$$ de Graham Douglas y el equipo de Overleaf.

### Y por último... simplemente usa el paquete luacode

Aunque TeX y Lua operan de maneras fundamentalmente diferentes, esos lenguajes comparten una serie de caracteres que tienen «significados especiales» dentro del contexto de cada lenguaje—como \\, %, \~, #, ^, &—; por supuesto, Lua y TeX asignan esos significados especiales para *muy* propósitos distintos. Nuestra exploración de los caracteres problemáticos muestra por qué pueden surgir dificultades y cómo puedes resolverlas; sin embargo, puede resultar bastante tedioso corregir manualmente muchos fragmentos pequeños de código Lua, así que la mayoría de los usuarios prefiere utilizar paquetes de LaTeX que eliminan esos desafíos. Uno de esos paquetes es [`luacode`](https://ctan.org/pkg/luacode?lang=en) que proporciona un conjunto de funciones diseñadas para simplificar el trabajo con `\directlua`, pero al menos ahora quizá tengas una mejor comprensión de los problemas `luacode` que resuelve por ti.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://overleaf-pro.ayaka.space/latex/es/articulos-en-profundidad/09-an-introduction-to-luatex-part-2-understanding-directlua.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
