> 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/nl/diepgaande-artikelen/09-an-introduction-to-luatex-part-2-understanding-directlua.md).

# Een introductie tot LuaTeX (deel 2): \directlua begrijpen

## Het doel van dit artikel

In het eerste deel van dit artikel, [Een introductie tot LuaTeX (deel 1): wat is het — en wat maakt het zo anders?](/latex/nl/diepgaande-artikelen/07-an-introduction-to-luatex-part-1-what-is-it-and-what-makes-it-so-different.md), hebben we LuaTeX kort besproken als een uiterst veelzijdige TeX-engine: een geavanceerd, programmeerbaar zetwerksysteem dat een breed scala aan hulpmiddelen biedt voor het opzetten van oplossingen voor documentengineering en productie.

In deze afsluitende aflevering bekijken we het belangrijkste onderdeel van de LuaTeX-gereedschapskist van dichtbij: de `\directlua` opdracht die de ‘toegangspoort’ biedt tot programmatische aansturing van LuaTeX’s zetwerk via de Lua-scripttaal.

Het volledig benutten van LuaTeX via `\directlua` vereist enige achtergrondkennis van verschillende TeX-onderwerpen: TeX-tokens, tokenlijsten en het expansiemechanisme. Het doel van dit artikel is deze fundamentele TeX-concepten te verkennen en uit te leggen: de TeX-gerelateerde processen achter `\directlua` om te begrijpen hoe het werkt en de basis te leggen waarop u uw eigen zetwerkoplossingen met LuaTeX kunt bouwen.

Dit artikel bevat talrijke korte voorbeelden om de belangrijkste aspecten van `\directlua`gedrag te demonstreren en uit te leggen, waarbij bewust al te complexe code wordt vermeden ten gunste van korte codefragmenten. Waar nodig gebruiken de voorbeelden basis-(ruwe/plain) TeX—hoewel de meeste mensen LaTeX (macro’s) gebruiken en verkiezen, hebben basis-TeX-opdrachten als voordeel dat ze eenvoudig zijn.

## Introductie tot Lua in LuaTeX

[Lua](https://www.lua.org/about.html) is een scripttaal waarvan de [broncode](https://www.lua.org/download.html) zeer draagbaar is en eenvoudig in softwaretoepassingen kan worden ingebed, waardoor ontwikkelaars scriptmogelijkheden in hun programma’s kunnen opnemen. Lua is ingebed in [veel toepassingen](https://en.wikipedia.org/wiki/List_of_applications_using_Lua) en is een populaire keuze binnen de softwaregame-industrie—misschien is het bekendste voorbeeld [World of Warcraft](https://wowwiki.fandom.com/wiki/Lua_functions).

LuaTeX is, zoals de naam al aangeeft, een TeX-engine die de Lua-scripttaal insluit en gebruikers de mogelijkheid biedt om het zetgedrag van LuaTeX te sturen door Lua-programma’s (scripts) in hun documenten op te nemen. Naast directe aansturing van LuaTeX kunnen gebruikers Lua ook puur benutten als een zeer krachtige programmeertaal om taken uit te voeren die met de TeX-taal uiterst moeilijk te realiseren zouden kunnen zijn—een taal die, objectief gezien, lastig te leren en te beheersen is. Door de toevoeging en integratie van Lua wordt LuaTeX een zeer veelzijdige en krachtige TeX-engine die rechtstreeks twee programmeertalen ondersteunt.

### Lua en TeX in uw document gebruiken: voer \directlua in

Lua en TeX zijn twee *zeer verschillende* programmeertalen: Lua staat veel dichter bij wat de meeste mensen als een programmeertaal beschouwen, maar TeX, met zijn categoriecodes, tokens, macro’s en expansiemechanisme, staat ver af van de ervaringen/verwachtingen van de meeste mensen van een taal waarin programma’s worden geschreven. Zoals de geschiedenis heeft aangetoond, heeft de TeX-taal echter standgehouden omdat zij goed is in waar zij voor ontworpen is: het sturen van zetwerk, ook al is de werkwijze enigszins raadselachtig.

Om de uitdaging aan te pakken van het mengen van de Lua- en TeX-talen in één TeX-document, introduceerden de ontwikkelaars van LuaTeX een nieuwe opdracht genaamd `\directlua` die de route vormt naar het gebruik van Lua—zowel als zelfstandige programmeertaal op zichzelf als voor het sturen van het zetgedrag van LuaTeX.

De `\directlua` opdracht stelt gebruikers in staat Lua-code in hun TeX-documenten in te voegen; die code wordt vervolgens doorgegeven aan LuaTeX’s ingebouwde Lua-taalinterpreter. Echter, `\directlua` stelt u ook in staat om *combineren* Lua- en (La)TeX-code samen te `\directlua` opdracht—al brengt dat extra complexiteit met zich mee door fundamentele verschillen tussen op Lua en TeX gebaseerde programmeertalen. De belangrijkste uitdaging bij het gebruik van een combinatie van (La)TeX- en Lua-code is ervoor te zorgen dat die twee talen vreedzaam naast elkaar bestaan en elkaar niet ‘in de weg zitten’.

`\directlua` is het meest geschikt voor gebruik met kortere Lua-codefragmenten in het document, maar u kunt het ook gebruiken met uitgebreidere Lua-programma’s, als u dat wilt. Over het algemeen worden omvangrijkere Lua-programma’s en Lua-codelibraries opgeslagen in externe bestanden die kunnen worden geladen met behulp van Lua’s `dofile()` functie binnen een `\directlua` opdracht. Vanuit het perspectief van TeX-verwerking is een belangrijk voordeel van het gebruik van externe Lua-codebestanden dat complicaties worden vermeden die voortkomen uit TeX’s categoriecodemechanisme—een onderwerp dat in dit artikel volledig wordt onderzocht.

### Meer formele beschrijving van \directlua

De [LuaTeX Reference Manual](http://www.pragma-ade.com/general/manuals/luatex.pdf) beschrijft `\directlua` als volgt (iets aangepast):

> Om Lua-code met TeX-invoer samen te voegen, zijn enkele nieuwe primitieve nodig. De primitieve `\directlua` wordt gebruikt om Lua-code onmiddellijk uit te voeren. De basis-syntaxis is `\directlua{⟨code⟩}`zijn gegenereerd. Het `⟨code⟩` wordt volledig uitgebreid en vervolgens aan de Lua-interpreter doorgegeven. Nadat het lezen en de expansie zijn toegepast op de `⟨code⟩`, wordt de resulterende tokenlijst omgezet naar een string alsof deze werd weergegeven met `\the\toks`.

Natuurlijk is dit technisch gezien correct, maar misschien niet zo gemakkelijk te begrijpen zonder enige kennis van lagere TeX-processen—zoals tokens en expansie.

## De werking van \directlua begrijpen: welke onderwerpen behandelen we?

In dit artikel bekijken we enkele belangrijke achtergrondonderwerpen van dichtbij en bieden we een aantal voorbeelden die laten zien hoe `\directlua` werkt en waar (of waarom) u voorzichtig moet zijn bij het combineren van TeX en Lua in uw `⟨code⟩`.

We zullen de volgende onderwerpen voldoende gedetailleerd verkennen om een basis te bieden voor het begrijpen van `\directlua` en de ‘voorverwerking’ van de code die u erin gebruikt:

* categoriecodes en TeX-tokens: tekst omzetten naar tokens en tokens naar tekst;
* TeX’s expansieproces (en het voorkomen van expansie);
* Lua-escapesequenties/-mechanismen voor tekens en strings;
* gebruik van Lua-stijl opmerkingen;
* een korte introductie tot LuaTeX’s Lua-API.

Als u begrijpt hoe TeX-engines tokens maken en gebruiken en u zich bewust wordt van TeX’s expansiemechanisme, dan hebt u de noodzakelijke basis om de ongelooflijke veelzijdigheid van LuaTeX’s te ontsluiten `\directlua` commando.

## De basis: van tekst naar tokens en van tokens naar tekst

Overleaf heeft verschillende artikelen gepubliceerd die een diepgaande blik werpen op TeX-tokens en gerelateerde concepten, dus we zullen al dat materiaal hier niet herhalen; in plaats daarvan schetsen we de gebieden/onderwerpen die relevant zijn voor een beter begrip van `\directlua`.

Hier is een lijst met eerder gepubliceerde artikelen die mogelijk interessant zijn:

* [Wat is een TeX-token?](/latex/nl/diepgaande-artikelen/53-what-is-a-tex-token.md)
* [Wat is een TeX-tokenlijst?](/latex/nl/diepgaande-artikelen/54-what-is-a-tex-token-list.md)
* [Hoe werkt \expandafter: een introductie tot TeX-tokens](/latex/nl/diepgaande-artikelen/19-how-does-expandafter-work-an-introduction-to-tex-tokens.md)
* [Een serie van zes delen: hoe werken TeX-macro’s eigenlijk?](/latex/nl/meer-onderwerpen/01-a-six-part-series-how-do-tex-macros-actually-work.md)

### Karaktertokens begrijpen

Elk teken dat een TeX-engine uit een tekstbestand kan lezen, wordt weergegeven door twee numerieke waarden:

* zijn *tekencode* (ASCII-waarde of tegenwoordig het Unicode-codepunt);
* een tweede, op TeX gerichte waarde, genaamd zijn *categoriecode*.

Lezers die meer over categoriecodes willen weten, kunnen geïnteresseerd zijn in deze introductie van Overleaf: [Dus waar beginnen we? Met categoriecodes](/latex/nl/meer-onderwerpen/19-how-tex-macros-actually-work-part-1.md#so2c-where-do-we-start3f-with-category-codes).

Als een TeX-engine bijvoorbeeld een teken inleest `A` heeft die toegang tot twee informatie-eenheden: `A`’s tekencode (65) en zijn categoriecode (meestal 11). Zodra TeX dat teken heeft ingelezen `A`, wordt zijn categoriecode niet gewijzigd, maar gebruikermacro’s kunnen categoriecodewijzigingen aanbrengen die van invloed kunnen zijn op elk *volgend* teken `A` dat *nog niet is gelezen* door TeX. Daarom moet TeX vastleggen dat *dit* teken `A`, *zojuist ingelezen*, categoriecode 11 heeft. Om dat te doen gebruikt TeX het getallenpaar (65,11) om een andere gehele waarde te berekenen die het een *tekentoken*. Door die tokenwaarde te berekenen, die wordt doorgegeven aan TeX’s interne verwerking, wordt dat specifieke `A` en zijn categoriecode *samengebonden*; in feite *verpakt* de gegevens die TeX over dat teken moet kennen voor gebruik in eventuele latere zetwerkactiviteiten dieper in de TeX-engine.

#### Hoe worden tekentokens berekend?

Allereerst moeten we ons herinneren dat TeX-engines categoriecode 13 gebruiken om zogenaamde *actieve tekens*: elk teken met categoriecode 13 gedraagt zich als een mini-macro; daarom, en zoals we hieronder zullen zien, worden tokens voor actieve tekens anders berekend dan gewone tekens met andere categoriecodes zoals 10, 11 of 12.

Voor *niet-actieve* tekens:

* oudere 8-bit-engines (Knuths TeX, e-TeX, pdfTeX) berekenen tekentokens voor *niet-actieve* tekens met behulp van

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

* voor LuaTeX, dat met Unicode-tekenwaarden moet omgaan, is de berekening voor *niet-actieve* tekens vergelijkbaar maar levert veel grotere gehele waarden op:

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

Terugkomend op ons eerdere voorbeeld van de letter A met categoriecode 11, zou LuaTeX een tekentokenwaarde van $$2^{21} \times 11 + 65 = 23068737$$. Zodra die tekentokenwaarde is berekend *verbindt* dat specifieke teken A aan een categoriecodewaarde van 11. Gebruikermacro’s kunnen de categoriecode voor elk volgend teken A wijzigen, maar de categoriecode van dit exemplaar is vastgelegd door het om te zetten in een token voor gebruik terwijl het door LuaTeX’s innerlijke werking passeert. LuaTeX heeft de bedoelde betekenis van dat teken behouden, of ingekapseld, zoals bepaald op het moment dat het werd ingelezen.

TeX-engines gebruiken in totaal [16 verschillende categoriecodes](/latex/nl/meer-onderwerpen/43-table-of-tex-category-codes.md) en *elke* van die categoriecodes kan via de `\catcode` opdracht, worden toegekend aan elk *elke* teken dat de TeX-engine kan lezen. Wijzigingen in categoriecodes worden gebruikt om de manier waarop TeX-engines bepaalde tekens in de invoer verwerken te veranderen, waardoor TeX-gebruikers macro’s kunnen schrijven die speciale zetwerkresultaten of -gedrag produceren.

**Actieve tekens**

Zoals opgemerkt gebruiken TeX-engines categoriecode 13 om aan een teken een ‘speciale betekenis’ toe te kennen, waardoor het een zogenaamd *actief teken* dat zich gedraagt als een mini-macro: geen voorloop `\` is vereist; het geïsoleerde teken is, dankzij zijn categoriecode, voldoende om zijn macro-achtige gedrag te activeren.

Omdat een actief teken als een mini-macro werkt, wordt het niet omgezet in een *tekentoken* maar in een tweede (geheel getal-)tokentype genaamd een *commandotoken*. Deze worden als volgt berekend:

* voor oudere 8-bit-engines (Knuths TeX, e-TeX, pdfTeX) worden tokens voor actieve tekens berekend via:

1. bereken een tussenwaarde genaamd $$\text{curcs}$$ (**cur**rent **c**ontrol **s**equence) where $$\text{curcs} = \text{character code} + 1$$3. bereken de tokenwaarde waarbij $$\text{active character token} = \text{curcs} + \text{4095}$$

* voor LuaTeX is de berekening iets complexer omdat het met het volledige bereik van Unicode-tekens moet omgaan, waarvan elk actief kan worden gemaakt:

1. bereken de tussengelegen gehele waarde $$\text{curcs}$$ door een zogenaamde *hashfunctie* toe te passen op de Unicode-codepuntwaarde van het actieve teken, uitgedrukt in UTF-8: $$\text{curcs}=\texttt{hashfunction}\text{(UTF-8 text for Unicode value of active character)}$$3. bereken de gehele tokenwaarde: $$\text{active character token} = \text{curcs} + 2^{29} - 1$$

**Voorbeelden**

* 8-bit-engines: de tokenberekening voor het actieve teken `~` (tekencode 126) resulteert in $$\text{curcs} = 126 + 1 = 127$$, wat een tokenwaarde oplevert van $$4095 + 127 = 4222$$.
* LuaTeX: de tokenberekening voor het actieve teken `~` resulteert in $$\text{curcs}=3186$$ wat een tokenwaarde oplevert van $$3186 + 2^{29} - 1 = 536874097$$. LuaTeX-tokens gebruiken veel grotere gehele waarden!

### Commandotokens begrijpen

Naast het verwerken van *afzonderlijke* tekens kunnen TeX-engines natuurlijk ook *reeksen* van tekens verwerken, genaamd *commando's* (of, juister gezegd, *commandoreeksen*). Volgens de traditie wordt het `\` teken gebruikt om het begin van een opdracht aan te geven, maar dat is slechts een conventie—in feite zou elk teken met categoriecode 0 (het escape-teken) daarvoor gebruikt kunnen worden.

TeX-engines herkennen twee typen opdrachten die bekendstaan als *control words* en *controlsymbolen*:

* **control words**: opdrachten die bestaan uit één of meer tekens met categoriecode 11;
* **controlsymbolen**: opdrachten van één teken waarbij de categoriecode van dat teken *niet* 11 is: zoals `\$`, `\#` of `\\`.

**Opmerking**: De TeX-primitieven `\chardef`, `\mathchardef`, `\countdef`, `\dimendef`, `\skipdef`, `\muskipdef` en `\toksdef` worden ook gebruikt om commandoreeksen te definiëren, maar anders dan gewone macrodefinities zijn de resulterende commandoreeksen (control words of controlsymbolen) *niet uitbreidbaar*—we zullen deze hieronder nader bekijken.

#### Hoe worden commandotokens berekend?

Net als actieve tekens gebruiken TeX-engines het tweede type tokenwaarde als geheel getal om opdrachten weer te geven: *commandotokens*—vergeet niet dat actieve tekens ook commandotokens genereren omdat ze zich als mini-macro’s gedragen.

De berekeningen die 8-bit-engines gebruiken om commandotokenwaarden te maken, zijn te vinden in dit [Overleaf-artikel](/latex/nl/diepgaande-artikelen/19-how-does-expandafter-work-an-introduction-to-tex-tokens.md#how-tex-calculates-token-values). Hier zullen we de belangrijkste stappen in commandotokenberekeningen voor LuaTeX samenvatten—die enigszins verschillen omdat LuaTeX Unicode-tekencodewaarden moet verwerken die aanzienlijk groter kunnen zijn dan 8-bitwaarden; LuaTeX’s berekeningen volgen echter dezelfde algemene principes als oudere 8-bit-engines.

Nadat een binnenkomende opdracht is gedetecteerd, negeren TeX-engines, inclusief LuaTeX, het voorloop `\` teken: het wordt niet gebruikt in berekeningen van commandotokenwaarden maar fungeert slechts als een ‘schakelaar’ om een TeX-engine te informeren dat deze een opdracht moet verwerken. De commandotokenwaarde wordt berekend met behulp van de reeks van (één of meer) tekens in de naam van de opdracht—LuaTeX berekent commandotokens voor controlsymbolen en control words met hetzelfde algoritme:

1. bereken de tussengelegen gehele waarde $$\text{curcs}$$ door een zogenaamde [hashfunctie](https://en.wikipedia.org/wiki/Hash_function) op de Unicode UTF-8-tekenreeks die in de opdrachtnaam voorkomt: $$\text{curcs}=\texttt{hashfunction}\text{(Unicode UTF-8 string of characters in command name)}$$3. bereken de commandotokenwaarde waarbij $$\text{command token} = \text{curcs} + 2^{29} - 1$$

**Voorbeelden**

* voor de `\\` opdracht (een controlsymbool), berekent LuaTeX $$\text{curcs}=94$$, wat resulteert in een tokenwaarde voor `\\` van $$94 + 2^{29} - 1 = 536871005$$.
* voor de `\vskip` primitieve opdracht (een control word) berekent LuaTeX $$\text{curcs}=3560$$, wat resulteert in een tokenwaarde voor `\vskip` van $$3560 + 2^{29} -1 = 536874471$$.
* voor de door de gebruiker gedefinieerde macro `\mynewmacro` (een control word) berekent LuaTeX $$\text{curcs} = 2971$$, wat resulteert in een tokenwaarde voor `\mynewmacro` van $$2971 + 2^{29} -1 = 536873882$$.

Zodra tokens zijn aangemaakt, kunnen ze voor later gebruik worden opgeslagen via zogenaamde *tokenlijsten* of ze kunnen onmiddellijk worden doorgegeven voor verdere verwerking binnen de TeX-engine. Het gebruik van gehele waarden om tokens weer te geven werkt niet alleen op alle soorten computerplatformen/besturingssystemen, maar is voor TeX ook een zeer efficiënte manier om gegevens op te slaan/verwerken.

### Hoe een TeX-engine het type token (opdracht of teken) identificeert

Gegeven een bepaalde gehele tokenwaarde, $$T$$, kan een TeX-engine gemakkelijk bepalen of $$T$$ een opdracht of een teken vertegenwoordigt door te testen of $$T$$ een bepaalde $$\text{threshold value}$$—dat $$\text{threshold value}$$ afhankelijk is van de TeX-engine. Als $$T \geq \text{threshold value}$$ vervolgens $$T$$ een commandotoken is, is het anders $$T$$ een tekentoken. De $$\text{threshold value}$$ is $$4095$$ voor 8-bit-engines en $$2^{29}-1$$ (536.870.911) voor LuaTeX. Knuth ontwierp de methoden die in tokenberekeningsformules worden gebruikt zo dat zijn TeX-engine, en alle daaropvolgende engines die op zijn code/architectuur zijn gebaseerd, tokenwaarden snel en gemakkelijk kunnen testen.

## Tokens kunnen worden opgesplitst (en terug omgezet naar tekst)

Tokens (gehele getallen) zijn het mechanisme waarmee een TeX-engine alles ‘inkapselt’ wat het moet vastleggen over een invoerelement (teken of opdracht). Er zijn echter momenten waarop een TeX-engine het tokenisatieproces moet omkeren—om te achterhalen wat oorspronkelijk werd ingelezen om die tokenwaarde te produceren—een afzonderlijk teken of een reeks van één of meer tekens die de naam van een opdracht vormen:

* **voor tekentokens**: Elk tekentoken kan worden opgesplitst in zijn twee samenstellende delen: de tekencode en de overeenkomstige categoriecode die aan dat teken *werd toegekend op het moment dat het oorspronkelijk werd ingelezen*. Net als alle TeX-engines zal LuaTeX die oorspronkelijke toewijzing van de categoriecode niet wijzigen, maar er wel gebruik van maken tijdens verdere interne verwerkingsactiviteiten.
* **voor commandotokens:** Deze zijn iets gedetailleerder, maar als u naar LuaTeX’s berekening van commandotokens kijkt, inclusief tokens voor actieve tekens, ziet u dat ze een patroon volgen: $$\text{command token} = \text{curcs} + 2^{29} -1$$

waar $$\text{curcs}$$ wordt berekend volgens het type commandotoken dat wordt gegenereerd: actief teken, controlsymbool of control word. De $$\text{curcs}$$ variabele is een *extreem* belangrijk onderdeel van de interne werking van een TeX-engine: gegeven elke commandotoken(gehele) waarde kan LuaTeX heel gemakkelijk de waarde van $$\text{curcs}$$ uit dat commandotoken extraheren met behulp van $$\text{curcs} = \text{token value} - (2^{29} -1)$$.

### Waarom is $$\text{curcs}$$ dit zo belangrijk?

De interne TeX-variabele $$\text{curcs}$$ (**cur**rent **c**ontrol **s**reeks) is een uiterst belangrijk onderdeel van de ‘onder de motorkap’-operaties van een TeX-engine. Hoewel u het niet direct in uw code zult en kunt gebruiken of benaderen, $$\text{curcs}$$ speelt een cruciale rol omdat TeX-engines de huidige waarde van $$\text{curcs}$$ als index gebruiken in interne tabellen die gegevens opslaan over elke opdracht die de engine momenteel kent. Die tabellen bewaren informatie over de huidige betekenis van een opdracht: wat doet of vertegenwoordigt deze, en daarnaast leggen ze de reeks tekens vast die oorspronkelijk werd gebruikt om die $$\text{curcs}$$ waarde te berekenen. Door de waarde van $$\text{curcs}$$ uit een commandotoken te extraheren, kan een TeX-engine de naam, d.w\.z. menselijk leesbare tekst, bepalen die overeenkomt met elk (opdracht)token, zodat hij de token-naar-tekstconversies kan uitvoeren die een belangrijk aspect zijn van `\directlua`’s werking.

### Gehele-tokens terug omzetten naar tekens of tekenreeksen (opdrachtnamen)

We hebben gezien dat TeX-engines invoertekens of tekenreeksen omzetten naar gehele tokenwaarden, maar er zijn gevallen waarin een TeX-engine moet *omkeren* dat proces—om de voor mensen leesbare tekst uit te voeren die oorspronkelijk werd gebruikt om die gehele tokenwaarden te creëren; bijvoorbeeld:

* het schrijven van fout- of waarschuwingsberichten naar het scherm of `.log` bestand;
* het uitvoeren van TeX/LaTeX-code naar een tekstbestand via de `\write` commando;
* bij het omzetten van een reeks tokens naar tekst binnen `\directlua` (zoals we zo meteen zullen zien!)

#### Tekentokens omzetten naar tekst

Zoals opgemerkt worden tokens voor niet-actieve tekens berekend met behulp van de categoriecode en tekencode (Unicodewaarde) van een invoerteken. LuaTeX gebruikt de formule:

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

Het is een eenvoudige programmeertaak om de gehele $$\text{character token}$$ waarde op te splitsen om de samenstellende tekencode ($$\text{Unicode value}$$) en $$\text{category code}$$.

#### Commandotokens omzetten naar tekst

Alle TeX-engines bewaren de naam (reeks tekens) van elke opdracht die zij ‘kennen’: of die opdracht nu een door de gebruiker gedefinieerde macro is of een ingebouwde primitief—de opslag van primitiefopdrachtnamen vindt plaats wanneer de TeX-engine opstart, lang voordat zij uw code begint te verwerken. Voor door de gebruiker gedefinieerde opdrachten (macro’s) wordt de naam van die macro (zonder de voorloop `\`) opgeslagen als onderdeel van de macrodefinitieprocessen binnen TeX-engines.

Wanneer een TeX-engine de voor mensen leesbare tekst wil benaderen of uitvoeren waaruit oorspronkelijk een gehele commandotoken werd berekend, bepaalt hij eerst de $$\text{curcs}$$ waarde voor die token; in LuaTeX, $$\text{curcs} = \text{token} - (2^{29} -1$$). Met behulp van de waarde van $$\text{curcs}$$ die uit een commandotoken is gehaald, kan een TeX-engine een interne datastructuur benaderen die de *stringpool* om de reeks voor mensen leesbare tekens te bepalen die oorspronkelijk werd gebruikt om die specifieke waarde voor $$\text{curcs}$$ en dus de bijbehorende commandotoken te berekenen.

Zoals we zullen zien, zijn deze tokenverwerkingsactiviteiten—het omzetten van tekenreeksen naar gehele tokenwaarden en het omzetten van gehele tokenwaarden terug naar tekenreeksen (‘de-tokenisatie’)—de *fundamentele mechanismen* die worden gebruikt binnen `\directlua`.

## Tokenlijsten

Terwijl een TeX-engine invoer leest, karakter- en commandotokens genereert (en verwerkt), kan hij bepaalde opdrachten tegenkomen die de engine instrueren om tijdelijk te stoppen met het doorgeven van tokens voor verdere verwerking en ze in plaats daarvan op te slaan voor later gebruik. Het meest voorkomende voorbeeld is het definiëren van een macro met behulp van een van de macrodefinitie-opdrachten `\def`, `\edef`, `\gdef` of `\xdef`—LaTeX-opdrachten zoals `\newcommand` zijn macro’s die extra functionaliteit bieden, opgebouwd rond laag-niveauprimitieven die uiteindelijk het eigenlijke macrodefinitieproces uitvoeren. Een macro kan worden beschouwd als de naam die aan een bepaalde lijst opgeslagen tokens is gegeven: een tokenlijst.

TeX-engines maken *uitgebreid* gebruik van tokenlijsten, vooral [tijdelijke, alleen-intern gebruikte lijsten](/latex/nl/diepgaande-artikelen/21-how-does-expandafter-work-tex-uses-temporary-token-lists.md) die voor interne verwerkingsdoeleinden worden gebruikt. Elke TeX-engine biedt ook gebruikersopdrachten om tokenlijsten te creëren die worden opgeslagen voor wanneer de gebruiker, of de TeX-engine zelf, ze nodig heeft. Het aantal opdrachten voor het creëren van tokenlijsten (ingebouwde primitieve opdrachten) varieert per TeX-engine, maar ze delen allemaal een kernminimumset die door elke engine wordt ondersteund, zoals de `\toks` primitief.

In de praktijk is een tokenlijst gewoon een opgeslagen reeks gehele waarden:

* de invoer wordt gelezen om afzonderlijke tokens te genereren (berekenen), die een teken of opdracht vertegenwoordigen;
* elk token wordt vervolgens opgeslagen, waarbij de volgorde waarin tokens uit de invoer werden gegenereerd behouden blijft.

TeX-engines slaan tokenlijsten op met behulp van een datastructuur genaamd een [gekoppelde lijst](https://en.wikipedia.org/wiki/Linked_list) (de enkelvoudig gelinkte variant). Lezers die meer over tokenlijsten willen weten, worden uitgenodigd het Overleaf-artikel te lezen [Wat is een TeX-tokenlijst?](/latex/nl/diepgaande-artikelen/54-what-is-a-tex-token-list.md) dat een analogie gebruikt om de concepten/ideeën achter een tokenlijst op te bouwen. Een diepgaande verkenning van TeX’s tokenlijsten, en hoe ze worden gebruikt in macroverwerking, is te vinden in de Overleaf-artikelreeks [Hoe werken TeX-macro’s eigenlijk?](/latex/nl/meer-onderwerpen/01-a-six-part-series-how-do-tex-macros-actually-work.md)

#### Een tokenlijst in grafische vorm

De volgende afbeelding toont een door LuaTeX gegenereerde tokenlijst met bijbehorende tokenwaarden, geproduceerd uit de volgende invoer

`Hoi, \TeX! \hskip 5bp`

Als we bijvoorbeeld definiëren `\mymacro` als `\def\mymacro{Hoi, \TeX! \hskip 5bp}` de definitie van `\mymacro` zou in het geheugen worden opgeslagen met behulp van een tokenlijst zoals deze:

![](/files/29d5e8353184be536d2e213eaf8415224e5a9cff)

De tokenlijst is een reeks gekoppelde items genaamd *nodes*, de naam die wordt gegeven aan een klein pakketje van LuaTeX-geheugen dat is toegewezen om elk item in de lijst te bevatten (zoals afzonderlijke schakels in een ketting). Elke knoop bevat een gehele tokenwaarde en geheugenadres van de *volgende* knoop in de ketting, waardoor een datastructuur ontstaat die een [gekoppelde lijst](https://en.wikipedia.org/wiki/Linked_list). De laatste knoop geeft het einde van de lijst aan met een speciale ‘nulwaarde’ voor de volgende knoop—omdat die er niet is.

**Opmerkingen:**

* Voor het gemak hebben we het adres van elke afzonderlijke knoop opgenomen, maar in de praktijk wordt die gegevens niet opgeslagen in tokenlijstknopen; alleen het adres van de *volgende node* is nodig om tokenlijsten van de TeX-engine op te bouwen.
* De tweede kolom in de afbeelding met de titel ‘Wat elk token betekent’ toont een reeks grijze vakken met informatie over het token in elke knoop: deze dienen uitsluitend ter informatie en *worden niet* maken geen deel uit van de feitelijke gegevens die in de tokenlijst zijn opgeslagen.

Hier is een tabel met de tokenwaarden die in de hierboven afgebeelde tokenlijst zijn opgenomen:

|                   |                      |                                                                           |                 |
| ----------------- | -------------------- | ------------------------------------------------------------------------- | --------------- |
| **Invoerelement** | **Type invoer**      | <p><strong>Categoriecode</strong><br><br><strong>(als teken)</strong></p> | **Tokenwaarde** |
| H                 | teken                | 11                                                                        | 23068744        |
| i                 | teken                | 11                                                                        | 23068777        |
| ,                 | teken                | 12                                                                        | 25165868        |
|                   | teken                | 10                                                                        | 20971552        |
| \TeX              | commando (macro)     |                                                                           | 536871539       |
| !                 | teken                | 12                                                                        | 25165857        |
|                   | teken                | 10                                                                        | 20971552        |
| \hskip            | commando (primitief) |                                                                           | 536874247       |
| 5                 | teken                | 12                                                                        | 25165877        |
| b                 | teken                | 11                                                                        | 23068770        |
| p                 | teken                | 11                                                                        | 23068784        |

**Opmerking:** Onze oorspronkelijke invoertekst heeft een a na de `\hskip` commando, maar er is geen token dat dat teken in de tokenlijst vertegenwoordigt. Dat teken werd geabsorbeerd door LuaTeX’ invoerscanproces (leesproces) omdat het werd gebruikt om LuaTeX’ zoektocht naar tekens waaruit de `\hskip` commando.

## Hoe \directlua echt werkt

Nu we tokens, tokenlijsten en het omzetten van tokens naar tekst hebben verkend, is de volgende uitdaging het TeX-engineconcept van token *expansie*.

Zoals opgemerkt, `\directlua{⟨code⟩}` kan worden gevraagd om te verwerken `⟨code⟩` dat zowel Lua- als TeX/LaTeX-code bevat, maar de ingebouwde Lua-taalinterpreter van LuaTeX begrijpt geen TeX of LaTeX: dus hoe kan dit werken? Hoe is het mogelijk voor de `⟨code⟩` om TeX/LaTeX-instructies te bevatten zonder de Lua-interpreter grondig in de war te brengen met commando’s die hij niet begrijpt? Bijvoorbeeld, het volgende `\directlua` commando gebruikt alleen TeX-macro’s, maar het werkt:

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

Dit `\directlua` commando resulteert in dat LuaTeX `Hello` maar waarom en hoe werkt dit, omdat de Lua-taal geen TeX-macro’s begrijpt?

Het antwoord zit in de eerdere beschrijving die we hebben overgenomen van de [LuaTeX Reference Manual](http://www.pragma-ade.com/general/manuals/luatex.pdf) maar we kunnen aannemen dat `\directlua{⟨code⟩}` werkt doordat LuaTeX in eerste instantie de `⟨code⟩` “voorbewerkt” voordat er iets aan de Lua-interpreter wordt doorgegeven. De aard van deze “voorbewerking”—oftewel wat dit echt betekent en de gevolgen ervan voor je `⟨code⟩`—is het volgende onderwerp dat we zullen behandelen om lezers te helpen die willen profiteren van de kracht en flexibiliteit van `\directlua`.

### Hoe LuaTeX \directlua verwerkt: een eerste blik

Om ons begrip van `\directlua`’s “voorbewerkings”-activiteiten verder uit te bouwen kunnen we beginnen met het volgende vereenvoudigde diagram, dat een overzicht geeft van wat er gebeurt. De `⟨code⟩` verstrekt aan `\directlua{⟨code⟩}` wordt eerst met behulp van de hierboven besproken processen en berekeningen omgezet in tokens; die reeks tokens wordt opgeslagen in een tokenlijst. Zodra die tokenlijst is opgebouwd, wordt elk token in die lijst terug omgezet naar zijn tekstuele representatie: de tekst die door elk token—karaktertoken of commandotoken—is geproduceerd, wordt gecombineerd (aaneengeschakeld) om één enkele tekenreeks met code te vormen die aan de Lua-interpreter wordt doorgegeven voor uitvoering.

![](/files/03b20c6a49f9a69ecd6795404d6582b2eecd569d)

Maar wacht, wat is dan het nut van van tekst naar tokens gaan en die tokens direct weer naar tekst omzetten? Het zal je misschien niet verbazen dat er inderdaad een extra en essentieel proces is dat we niet in deze afbeelding hebben opgenomen: *tokenexpansie*. Elk token dat uit de tekst in je `⟨code⟩` onderworpen wordt aan een soort “inspectie” waarbij LuaTeX een test toepast om te zien of dat token een commando vertegenwoordigt dat behoort tot de subset die bekendstaat als *uitbreidbare commando’s*. Als dat zo is, filtert LuaTeX dat commando eruit door *het te verwijderen* uit je `⟨code⟩` en *het te vervangen* door het/de resultaat/resultaten van een proces dat TeX-engines noemen *tokenexpansie*.

### Hoe LuaTeX \directlua verwerkt: een tweede blik (op expansie)

TeX’ expansiemechanisme is een kernonderdeel van alle op TeX gebaseerde zetsystemen, omdat elk ervan uiteindelijk is afgeleid van (of gebaseerd op) Knuths oorspronkelijke broncode en ontwerp van TeX. Het concept expansie is echter moeilijk beknopt én toegankelijk uit te leggen, omdat expansie in de praktijk een overkoepelende term is die wordt gebruikt om één enkel proces te beschrijven—maar wel een proces dat een reeks uitkomsten produceert. Die uiteenlopende uitkomsten zijn een gevolg van de enigszins eclectische verzameling commando’s waarop expansie kan worden toegepast, dus je kunt ervan uitgaan dat elk uitbreidbaar commando een bepaald “expansiegedrag” heeft.

Als een *eerste benadering* om expansie te begrijpen kunnen we zeggen dat expansie van een token (commando) betekent *het te verwijderen* dat commando (token) uit TeX’ huidige invoer en *vervangen* door een reeks tokens die het resultaat zijn van het uitvoeren van dat specifieke uitbreidbare commando—het oorspronkelijke token vervangen door de resultaten/gevolgen van zijn expansie *gedrag*. Deze eerste “definitie” van expansie—in termen van het genereren van nieuwe tokens die TeX moet lezen—is echter niet helemaal nauwkeurig voor alle uitbreidbare commando’s, maar het is goed genoeg als beginpunt.

Om een eenvoudig voorbeeld te geven: de TeX-primitief `\jobname` is een uitbreidbaar commando en zijn *expansie* is een reeks karaktertokens die de naam van het hoofd-TeX-invoerbestand voorstellen. Als TeX besluit een `\jobname` commando (token) uit te breiden, wordt het *verwijderd* uit TeX’ huidige invoerbron en *vervangen* door de reeks karaktertokens die het genereert—waarna TeX die vervolgens gaat lezen/verwerken.

Binnen `\directlua`komt LuaTeX, nadat een uitbreidbaar token is verwerkt (verwijderd) en vervangen door nieuwe tokens, toe aan het lezen van die nieuwe tokens die het net heeft geplaatst—maar sommige van die nieuwe tokens kunnen ook uitbreidbaar zijn. Omdat `\directlua` zogenoemde *volledige expansie*toepast, zal LuaTeX die nieuwe tokens lezen en opnieuw door het expansieproces gaan om eventuele nieuwe (uitbreidbare) tokens uit te breiden (te verwijderen)—dit expansieproces gaat door totdat er geen uitbreidbare tokens meer over zijn. Er zijn echter twee belangrijke uitzonderingen op deze regel van “maar doorgaan met uitbreiden”, die we hieronder allebei zullen bespreken:

* met behulp van de constructie `\the\toks`;
* opzettelijke verhindering (onderdrukking) van expansie voor één of meer geselecteerde tokens.

Zoals opgemerkt dekt onze werkdefinitie (eerste benadering) van het begrijpen van expansie niet het volledige scala aan expansiegedragingen dat door de subset van uitbreidbare commando’s wordt gedemonstreerd. Sommige uitbreidbare commando’s genereren bijvoorbeeld geen tokens op de manier waarop `\jobname` dat doet, maar ze kunnen:

* tokens uit de invoer “filteren”: conditionele commando’s van een TeX-engine (`\if`, `\ifcat`, `\ifnum`, `\ifdim`, `\ifodd`, `\ifvmode`, …) zijn uitbreidbaar. Hun expansiegedrag is een soort “tokenfiltering”—conditionals kunnen worden gebruikt in `\directlua`.
* “jongleren” met tokens in de invoer: de [`\expandafter` commando](/latex/nl/diepgaande-artikelen/03-a-six-part-article-series-on-expandafter-tex-tokens-and-expansion.md) is uitbreidbaar en verandert de volgorde waarin twee tokens worden uitgebreid.
* expansie voorkomen: de uitbreidbare commando’s `\noexpand` en `\unexpanded` onderdrukken de expansie van commandotokens in de invoer.
* tekenreeksen in de invoer omzetten naar commandotokens: `\csname … \endcsname.`
* interne grootheden omzetten naar een reeks karaktertokens: `\number` en `\the` zijn uitbreidbare commando’s die een reeks karaktertokens genereren die de waarde van een interne grootheid voorstellen.
* commandotokens omzetten naar karaktertokens: `\string` en `\detokenize` zijn uitbreidbare commando’s die hun argumenten omzetten naar een reeks karaktertokens met categoricode 12. Merk op dat `\detokenize` verschilt van `\string`: `\detokenize` meerdere tokens kan verwerken en er, na het verwerken van commandotokens die zijn gemaakt uit *control words*een spatiekarakter met categoricode 10 invoegt. In feite `\detokenize` voegt een afsluitend spatiekarakter toe na de commandonaam—we zullen later in het artikel enkele voorbeelden zien.

#### Onze “definitie” van expansie verfijnen

We kunnen onze definitie nu veralgemeniseren door te zeggen dat expansie van een commando (token) inhoudt *verwijdering* van dat commando (token) uit TeX’ huidige invoerbron en *het te vervangen* met het resultaat van de *tokenbewerkingen* uitgevoerd door dat commando. In wezen zorgt het expansieproces ervoor dat een uitbreidbaar commando een soort “bewerking” uitvoert op tokens in TeX’ huidige invoer, wat invloed heeft op het aantal, of het gedrag, van tokens die TeX vervolgens zal lezen—de precieze aard van die “bewerking” hangt af van welk commando wordt uitgebreid. Alle macro’s en actieve tekens zijn uitbreidbaar, maar slechts een klein aantal ingebouwde commando’s (primitieven) van een TeX-engine worden als uitbreidbaar geclassificeerd—de lijst met uitbreidbare commando’s hangt af van de TeX-engine die je gebruikt.

Elke nieuwe TeX-engine erft de primitieve commando’s die in zijn voorouder(s) zijn ingebouwd—de TeX-engine(s) van een eerdere generatie waarvan hij is afgeleid—en sommige van die geërfde primitiven zullen uitbreidbaar zijn. Natuurlijk kan een nieuwe TeX-engine ervoor kiezen om sommige van de primitieve commando’s uit de eerdere engines niet te implementeren of hun gedrag aan te passen aan de behoeften van de nieuwe engine. Bovendien implementeren nieuwe TeX-engines doorgaans extra primitiven om ondersteuning te bieden voor hun eigen verbeterde functionaliteit—sommige daarvan kunnen ook uitbreidbaar zijn. Daardoor zal het aantal beschikbare uitbreidbare commando’s variëren naargelang de TeX-engine die je gebruikt—LuaTeX heeft er nogal wat.

Een andere moeilijkheid bij het uitleggen/begrijpen van expansie, en misschien wel de echte uitdaging, is precies weten *wanneer* een TeX-engine het expansieproces werkelijk wel of niet gaat uitvoeren. Dat is een groot en complex onderwerp, omdat expansie diep verweven is met het innerlijke functioneren van TeX-engines: we hebben hier geen ruimte om dit in detail te behandelen, behalve het gebruik van expansie in `\directlua`.

### Hoe LuaTeX \directlua verwerkt: een laatste blik

De volgende afbeelding vat de `\directlua` voorbewerkingsactiviteiten samen die plaatsvinden binnen de LuaTeX-engine zelf. In deze afbeelding tonen we ook twee laag-niveau (interne) LuaTeX-functies die het werk daadwerkelijk uitvoeren: `scan_toks()` en `tokenlist_to_cstring()`. Die functies zijn geschreven in de programmeertaal C en bevinden zich diep in de uitvoerbare LuaTeX-software: ze maken deel uit van LuaTeX’ interne mechaniek en zijn niet *rechtstreeks* toegankelijk voor je TeX/LaTeX-code.

![](/files/78e977e8af3210f4b126b4f6e92fb91f76aadd90)

De volgende beschrijving van `\directlua ⟨code⟩`’s voorbewerkingsactiviteit vat de bovenstaande afbeelding samen.

1. De reeks tekens in je ⟨code⟩ wordt verwerkt door `scan_toks()`. Het doel is om je ⟨code⟩ teken voor teken te lezen om karaktertokens en commandotokens te genereren. Omdat het tokens creëert, is de categoricode die aan elk teken in ⟨code⟩ wordt toegewezen, op het moment dat het wordt ingelezen, uiterst belangrijk.
2. Tijdens `scan_toks()`’s tokenverwerking (generatie) wordt elk uitbreidbaar commando (token) uitgebreid *tenzij* voorkomen via commando’s zoals `\protected` (macrodefinities), `\noexpand`, `\unexpanded` enz. Actieve tekens (categoricode 13) worden ook uitgebreid (tenzij dit wordt voorkomen).
3. De stroom tokens die door `scan_toks()` wordt gemaakt, wordt samengevoegd tot één lange tokenlijst—tokens in die lijst omvatten ook tokens die ontstaan zijn doordat expansie is toegepast op uitbreidbare commando’s (zoals macro’s) die in je `⟨code⟩`aanwezig zijn. Merk ook op dat `scan_toks()` *doet niet* de uitvoering van tokens die een niet-uitbreidbaar commando vertegenwoordigen niet triggeren of veroorzaken: zulke niet-uitbreidbare tokens worden gewoon doorgegeven om te worden opgenomen in de tokenlijst die wordt opgebouwd.
4. Zodra de tokenlijst klaar is en alle expansieactiviteit voltooid is, wordt die tokenlijst verwerkt door een andere functie genaamd `tokenlist_to_cstring()` die elke token in de uiteindelijke tokenlijst terug omzet naar zijn tekstuele representatie. Dit genereert een tekenreeks die de Lua-code is die aan de Lua-interpreter wordt doorgegeven. Voor een succesvolle uitvoering moet die tekenreeks syntactisch correcte Lua-code bevatten.
5. De verwerking van die code door Lua vindt in twee stappen plaats:
6. De ingebouwde Lua-interpreter van LuaTeX ontleedt en “compileert” de Lua-code die in de vorige stappen is gegenereerd. Als dat ontleden/compileren mislukt, zal de Lua-interpreter fouten genereren (zoals syntaxisfouten)—die fouten kunnen ervoor zorgen dat de LuaTeX-run mislukt, tenzij je ervoor hebt gekozen om `--interaction=nonstopmode` op de commandoregel te gebruiken.
7. Als het ontleden/compileren slaagt, voert de Lua-interpreter de code uit die in stap (5a) is gecompileerd.

In wezen is de `scan_toks()` functie de kern van LuaTeX’ voorbewerkingsactiviteiten: de belangrijkste taak is om alle uitbreidbare TeX/LaTeX-commando’s uit te breiden die in de tekst van je `⟨code⟩` staan en van alles wat het heeft verwerkt een tokenlijst op te bouwen. Nogmaals benadrukken we dat `scan_toks()` *niet-uitbreidbare commando’s niet uitvoert* (tokens): het *slaat op* die tokens in de tokenlijst die het aan het opbouwen is. Zodra die klaar is, wordt die tokenlijst vervolgens geconverteerd *terug naar een tekstuele representatie* door `tokenlist_to_cstring()`—een tokenlijst is een puur TeX-concept dat totaal vreemd is voor een Lua-interpreter; daarom moet het naar tekst worden omgezet, zodat het Lua-code wordt om door te geven aan de Lua-interpreter.

## Expansie als een “interface” van een programmeertaal

Je kunt `\directlua`’s expansieproces zien als een mechanisme, of interface, om gegevens/informatie van de “TeX-wereld” naar de “Lua-wereld” door te geven: als een methode voor de TeX-taal om gegevens aan de Lua-taal door te geven. Bijvoorbeeld, TeX-code zoals `\number\count75` kan worden gebruikt om een waarde uit de “TeX-wereld” die is opgeslagen in tellerregister 75 over te dragen naar de gehele variabele x in de “Lua-wereld”:

```
\count75=1564 % Gegevens die bestaan in de "TeX-wereld"
\directlua{
   local x=\number\count75 \space % TeX-gegevens overdragen naar de "Lua-wereld"
   tex.print("x= "..x)
   local y = (2*x-65)/5
   tex.print(" and y = "..y)
}
```

Hieruit ontstaat de Lua-code

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

**Opmerking**: We hebben `<space>\space` na `\number\count75` om ervoor te zorgen dat een spatiekarakter behouden bleef tussen `1564` en `tex.print`—dat is hier niet strikt noodzakelijk, omdat Lua de code nog steeds correct zou ontleden als we het weglieten. Het spatiekarakter dat direct volgt op `\count75` wordt geabsorbeerd tijdens het proces dat TeX-engines gebruiken om naar numerieke waarden te zoeken—hier is de waarde die wordt doorgegeven aan `\count`. Het spatiekarakter na `75` wordt gebruikt om LuaTeX’ zoekactie naar de cijferreeks `75` te beëindigen en wordt uit de invoer geabsorbeerd. De `\space` macro breidt uit om het spatiekarakter te leveren dat nodig is om de tekst `1564` en `tex.print`.

Met de bovenstaande code zal LuaTeX zetten

`x= 1564 and y = 612.6`

Hier wordt het mechanisme van “gegevensoverdracht” bereikt door `\number`: een uitbreidbaar commando dat in dit geval TeX opdraagt de waarde op te halen die is opgeslagen in `\count` register `75` en uit die waarde (`1546`) een reeks karaktertokens te genereren, één karaktertoken voor elk cijfer, wat resulteert in een tokenreeks voor de cijfers `1`, `5`, `6` en `4`. Die 4 karaktertokens worden opgenomen in de hoofd-tokenlijst die wordt opgebouwd door `\directlua` en vervolgens terug geconverteerd naar hun tekstuele representatie wanneer de tokenlijst naar tekst wordt omgezet. Het is zonder twijfel een zeer omwegachtige route van de `\count75` registerwaarde die in LuaTeX is opgeslagen, naar cijfers bestemd voor Lua-code, maar uiteindelijk werkt het.

**TIP:** Als je de resultaten van LuaTeX’ expansieactiviteiten wilt inspecteren, kun je code als volgt schrijven:

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

In dit voorbeeld gebruiken we de lange-haakjesmethode om een stringvariabele te maken `foo` waarvan het doel is de tekenreeks met Lua-code vast te houden die wordt gegenereerd uit de expansie van alles tussen `[[` en `]]`. Die tekenreeks wordt via de Lua-functieaanroep naar de console afgedrukt `print(foo)`.

Op Overleaf kun je vergelijkbare resultaten bekijken door de inhoud van `foo` naar het `.log` bestand te schrijven met behulp van de LuaTeX-Lua-functie `texio.write()`:

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

## Tokens in de \directlua-tokenlijst: niet-uitbreidbare tokens en niet-uitgebreide tokens

We hebben opgemerkt dat `\directlua{⟨code⟩}` voert *volledige expansie* van je `⟨code⟩`uit: het verwijdert en breidt alle uitbreidbare commando’s uit totdat alleen niet-uitbreidbare tokens overblijven. De reeks tokens die door `\directlua`’s verwerking (in de `scan_toks()` functie) wordt gegenereerd, wordt aan elkaar geregen om een tokenlijst te vormen waarvan de afzonderlijke tokens terug naar tekst zullen worden omgezet om aan Lua te worden doorgegeven.

We hebben echter het laatste deel van dit verhaal nog niet behandeld, omdat we de twee “klassen” van commandotoken moeten bekijken die de tokenlijst kunnen bereiken die binnen `\directlua`wordt opgebouwd: we zullen naar hen verwijzen als *verkorte commandotokens* en *niet-uitgebreid* tokens:

* **verkorte commandotokens**: Dit type commandotoken ontstaat uit control sequences die zijn gedefinieerd met een van de TeX-primitieven `\chardef`, `\mathchardef`, `\countdef`, `\dimendef`, `\skipdef`, `\muskipdef` en `\toksdef`. Deze primitieve commando’s worden gebruikt om control sequences te definiëren die een numerieke waarde voorstellen—de resulterende control sequences zijn *niet* uitbreidbaar.
* **niet-uitgebreide tokens**: Dit tokentype ontstaat uit commando’s die normaal gesproken zouden worden uitgebreid maar `\directlua` heeft ofwel:
* expliciet opgedragen *niet* om ze uit te breiden; bijvoorbeeld onderdrukking van expansie door de commando’s `\noexpand` of `\unexpanded`—we leggen straks uit hoe dit gebeurt;
* ingesloten tokens door de reeks te verwerken `\the\toks` (meer daarover hieronder).

### Twee “groepen” tokens in een \directlua-tokenlijst

Op basis van onze discussies kunnen we zeggen dat tokens in de tokenlijst die wordt opgebouwd tijdens de eerste fase van `\directlua`’s voorbewerking (in de `scan_toks()` functie) in twee groepen vallen:

1. *van nature niet-uitbreidbaar* tokens

* elk token dat een niet-actief *teken*;
* elk token dat een niet-uitbreidbaar *primitief* *commando*;
* elk token dat een *verkort commando* (deze zijn niet-uitbreidbaar, zie hieronder).

3. *niet-uitgebreid* tokens:

* elk token dat een uitbreidbaar commando vertegenwoordigt waarvan de expansie *onderdrukt* (of vermeden) tijdens `\directlua`’s voorbewerking.

#### Verkorte commandotokens: niet-uitbreidbare commando’s creëren

Zoals opgemerkt bieden TeX-engines een reeks primitiven (ingebouwde commando’s) die kunnen worden gebruikt om *niet-uitbreidbare* control sequences te construeren (hier aangegeven met `⟨command⟩`). Deze primitiven hebben de vorm:

* `\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⟩`

waar `⟨numeric value⟩` is een gehele waarde die geschikt is voor elk commando.

Hier bekijken we kort het gebruik van `\chardef` om de belangrijkste eigenschap van deze primitiven te demonstreren—namelijk het produceren van een `⟨command⟩` dat niet-uitbreidbaar is. Je kunt ``\chardef\mydollar=`\$`` gebruiken om de control sequence `\mydollar` te creëren en die te gebruiken om een `$`:

`I paid \mydollar30.`

Hiermee wordt gezet `I paid $30.` De control sequence `\mydollar` gecreëerd door `\chardef` is niet-uitbreidbaar, zoals we kunnen zien in het volgende voorbeeld:

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

Wat de volgende tekst oplevert in het `.log` bestand

`I paid \mydollar 30.`

Dit laat zien `\mydollar` werd *niet* uitgebreid tijdens `\directlua`’s voorbewerking. De spatie die na `\mydollar` verschijnt, wordt toegevoegd wanneer een commandotoken naar zijn representatie als tekst wordt omgezet.

Wanneer je `\chardef` gebruikt om een control sequence te creëren, resulteert de interne classificatie van die control sequence (commando) erin dat deze *niet-uitbreidbare* wordt, wat heel ander gedrag is vergeleken met control sequences die zijn gedefinieerd door een van de macrodefinitiecommando’s: \def, \edef, \gdef of \xdef. Zoals hierboven opgemerkt, tijdens het proces van het opbouwen van zijn tokenlijst `\directlua` onderzoekt elk binnenkomend commandotoken om te controleren op uitbreidbaarheid. Als een commandotoken niet-uitbreidbaar is, gaat het rechtstreeks door naar de tokenlijst en zal zijn tekstuele representatie later opnieuw verschijnen in de tekenreeks Lua-code die ontstaat uit het terug omzetten van tokens in de tokenlijst naar hun tekstvorm.

**Korte notities over plain TeX versus LaTeX**

Historisch gezien definieerde Knuths oorspronkelijke plain TeX de veelgebruikte controlesymbolen `\%`, `\&`, `\#` en `\$` met behulp van `\chardef`—niet met een van de standaard macrodefinitiecommando’s `\def`, `\edef`, `\gdef` of `\xdef`. Bijvoorbeeld:

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

De vreemde `` `\\ `` syntax is een TeX-methode om de numerieke tekencodewaarde te krijgen. In het oude plain-TeX-regime zijn deze controlesymbolen niet-uitbreidbaar (vanwege `\chardef`) maar LaTeX (of pakketten) kan ze herdefiniëren als *macro’s* om verbeterde functionaliteit te bieden—waardoor ze uitbreidbaar zouden worden, dus je moet je hiervan bewust zijn.

**Hoe heeft dit invloed op \directlua?**

Laten we het resultaat van de volgende code vergelijken wanneer deze onder plain TeX en LaTeX wordt uitgevoerd. Voor de eenvoud schrijven we de resultaten naar het `.log` bestand met behulp van de LuaTeX-Lua-API-functie `texio.write()`.

```
\directlua{
   local x=[[\$150 voor het "\#1" product---20\%! meer dan zijn concurrent, Widget \& Co.]]
   texio.write(x)
}
```

Als deze code wordt uitgevoerd met **plain TeX** produceert de volgende uitvoer in het `.log` bestand, waarin het resultaat van eventuele uitbreidingen wordt getoond:

```
\$150 voor het "\#1" product---20\%! meer dan zijn concurrent, Widget \& Co.
```

Duidelijk is dat onder plain TeX geen van de controlesymbolen`\$`, `\#`, `\%` of `\&` werd uitgebreid—omdat ze allemaal zijn gemaakt met `\chardef`.

Als die code wordt uitgevoerd met de **LaTeX** document:

```
\documentclass{article}
\begin{document}
   \directlua{local x=[[\$150 voor het "\#1" product---20\%! meer dan zijn concurrent, Widget \& Co.]] texio.write(x)}
\end{document}
```

produceert de volgende uitvoer in het `.log` bestand

```
\protect \TU\textdollar 150 voor het "\#1" product---20\%! meer dan zijn concurrent, Widget \& Co.
```

Duidelijk is dat het uitvoeren van LaTeX een ander resultaat oplevert dan plain TeX, omdat onder LaTeX het commando `\$` is uitgebreid, wat aangeeft dat het een macro is.

**Opmerking:** In zowel plain TeX als LaTeX `\directlua` heeft geen van de controlesymbolen volledig verwerkt `\%`, `\&`, `\#` en `\$` om het overeenkomstige teken te genereren. Tijdens het uitbreidingsproces dat wordt uitgevoerd door `\directlua` gaan de tokens die deze controlesymbolen vertegenwoordigen—of, voor LaTeX, hun uitbreiding—rechtstreeks door naar de hoofdtokenlijst die wordt opgebouwd.

**Opmerking:** Controlesymbolen worden gevormd uit één teken dat geen categoriecode 11 heeft, zoals `\#`. Wanneer een token dat een controlesymbool vertegenwoordigt terug wordt omgezet naar zijn tekstuele representatie, voegen TeX-engines geen spatie toe na die tekst. Deze speciale behandeling van controlesymbolen is een ingebouwde regel voor hoe TeX-engines werken.

### Niet-uitgebreide tokens: uitbreiding onderdrukken

`\directlua`’s voorbewerking is een voorbeeld waarbij een TeX-engine uitbreiding uitvoert, maar je misschien wilt *voorkomen* dat uitbreiding wordt toegepast op één of meer tokens die anders zouden worden uitgebreid. Als nog een voorbeeld voeren LuaTeX (en alle TeX-engines) een uitbreidingsproces uit, vergelijkbaar met dat van `\directlua`, wanneer ze het `\write` commando:

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

\write instrueert een TeX-engine om `⟨material⟩`—vaak met TeX/LaTeX-commando's—naar een tekstbestand (`file-number`); alle uitbreidbare commando's binnen `⟨material⟩` zullen, tenzij verhinderd, worden uitgebreid voordat `⟨material⟩` daadwerkelijk naar dat bestand worden weggeschreven.

Zoals je zou verwachten, bieden TeX-engines commando's om uitbreiding te onderdrukken of te regelen:

* `\noexpand⟨token⟩`: voorkomt uitbreiding van het enkele `⟨token⟩`;
* `\unexpanded{⟨material⟩}`: voorkomt uitbreiding van alle uitbreidbare commando's (tokens) in `⟨material⟩`. Het is in feite een versie met meerdere tokens van `\noexpand`;
* `\protected`: een prefix die aan macrodefinities wordt toegevoegd en uitbreiding van die macro in bepaalde omstandigheden voorkomt (zoals tijdens `\directlua`, `\write` of `\edef`).

Ondanks namen die anders doen vermoeden, zijn zowel `\noexpand` en `\unexpanded` bent *uitbreidbare commando’s* en bieden goede voorbeelden van het zien van het uitbreidingsproces van een TeX-engine als het uitvoeren van “tokenbewerkingen”: de bewerking hier is het voorkomen van uitbreiding van één of meer daaropvolgende tokens (commando's). Omdat `\noexpand` en `\unexpanded` beide uitbreidbare commando's zijn, worden ze verwijderd en verwerkt (uitgevoerd) tijdens `\directlua`’s voorbewerking terwijl deze de tokenlijst uit je `⟨code⟩`.

#### \noexpand ⟨token⟩

`\noexpand ⟨token⟩` voorkomt uitbreiding van het enkele `⟨token⟩`. `\noexpand` binnen `\directlua` zal worden uitgebreid (uit de invoer verwijderd) en vervangen door de resultaten van zijn “uitbreidingsgedrag”. Het resultaat van het uitbreiden van `\noexpand` is het aanmaken van een speciaal (verborgen) `⟨marker token⟩` dat vóór het oorspronkelijke wordt geplaatst `⟨token⟩` waarvan de uitbreiding moet worden onderdrukt: dat `⟨marker token⟩` fungeert als een vlag die zegt “breid het volgende token niet uit”. Omdat `\directlua` volledige uitbreiding uitvoert, zal het alle tokens die voortkomen uit het “uitbreidingsgedrag” van een uitbreidbaar commando opnieuw verwerken. Daardoor, wanneer de uitbreiding van `\noexpand ⟨token⟩` is voltooid, gaat LuaTeX terug om de resultaten te lezen en ziet het de tweetokenreeks `⟨marker token⟩⟨token⟩` wat ervoor zorgt dat het oorspronkelijke `⟨token⟩` onuitgebreid doorlaat naar de tokenlijst die wordt opgebouwd door `\directlua`.

**Voorbeeld**

Als we schrijven

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

het `\TeX` macro wordt uitgebreid tot zijn samenstellende tokens, wat in plain TeX resulteert in de volgende tekst die aan Lua wordt doorgegeven (let op: Lua kan deze code niet verwerken, het is alleen een voorbeeld om het proces te demonstreren):

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

Als we *onderdrukken* uitbreiding van de `\TeX` macro met behulp van `\noexpand`

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

de volgende Lua-code wordt geproduceerd (opnieuw kan Lua deze code niet uitvoeren; het is eenvoudigweg een voorbeeld om te demonstreren `\noexpand`):

`local x= "\TeX "`

Vanwege `\noexpand`, `\directlua` zal niet uitbreiden `\TeX` maar simpelweg de tokenwaarde die het `\TeX` commando vertegenwoordigt ongeschonden doorlaten naar de tokenlijst die wordt opgebouwd tijdens de eerste fase van `\directlua`’s voorbewerking.

**Opmerking:** Het spatieteken dat na `\TeX` verschijnt, wordt geïntroduceerd door LuaTeX’s daaropvolgende omzetting van de `\TeX` integer tokewaarde terug naar zijn tekstuele representatie (binnen de `tokenlist_to_cstring()` functie).

#### \unexpanded{⟨material⟩}

`\unexpanded` is een uitbreidbaar commando dat uitbreiding onderdrukt van alle tokens gevormd uit `⟨material⟩`. Zoals we hebben opgemerkt, wanneer een TeX-engine uitbreiding uitvoert, wordt elk uitbreidbaar commando *verwijderd* uit de invoer verwijderd en *vervangen* vervangen door de resultaten van zijn “uitbreidingsgedrag”; wat betekent dat nu eigenlijk voor `\unexpanded`? Gewoonlijk, tijdens *volledige expansie*, zodra het uitbreidingsproces voor een bepaald commando is voltooid, gaat de TeX-engine verder met het lezen/verwerken van alle tokens die uit dat commando’s “uitbreidingsgedrag” voortkomen—hij moet alle geproduceerde tokens verder uitbreiden. Echter, `\unexpanded` *omzeilt* elke verdere uitbreiding: zo doet het dat.

Binnen de TeX-engine, het `\unexpanded` commando zet eerst de tekens en commando's in `⟨material⟩` om naar een tijdelijke tokenlijst bestaande uit *niet-uitgebreid* tokens. Nadat alle tokens zijn aangemaakt en in die tijdelijke tokenlijst zijn opgeslagen, zorgt het `\unexpanded` commando ervoor dat `\directlua` om *overslaat* door terug te gaan om ze te lezen en te verwerken—ook al voert \directlua volledige uitbreiding uit. In plaats daarvan, die *niet-uitgebreid* tokens gaan er rechtstreeks doorheen en worden opgenomen in de hoofdtokenlijst die wordt opgebouwd door `\directlua` (in de `scan_toks()` functie). Op deze manier wordt alles in `⟨material⟩` omgezet naar tokens en wordt het uitbreidingsproces overgeslagen voor die reeks tokens. De werking van `\unexpanded{⟨material⟩}` is vergelijkbaar met het gebruik van `\the\toks`, die we hieronder bespreken.

**Voorbeeld**

`\unexpanded` produceert resultaten op een manier die vergelijkbaar is met `\noexpand` behalve dat het uitbreiding van meerdere tokens kan voorkomen; hier is een voorbeeld:

```
\directlua{
   local x = "\unexpanded{\foo\bar\foobar}. Maar Lua kan deze code niet verwerken!"
}
```

wat de volgende tekst als code voor Lua oplevert:

`local x = "\foo \bar \foobar . Maar Lua kan deze code niet verwerken!"`

**Opmerking**: Er staan spatietekens na elke commando-naam. Dit is opnieuw een gevolg van LuaTeX’s daaropvolgende omzetting van de onuitgebreide tokens `\foo`, `\bar` en `\foobar` terug naar tekst binnen de `tokenlist_to_cstring()` functie.

#### \protected macrodefinities

De `\protected` commando is een prefix die wordt toegepast op een macrodefinitie om te voorkomen dat die macro wordt uitgebreid wanneer TeX een uitgebreide tokenlijst opbouwt, zoals de tokenlijst die wordt opgebouwd door `\directlua`’s voorbewerking.

**Voorbeeld**

Stel dat je de volgende macro's definieert met en zonder gebruik te maken van het `\protected` prefix:

```
\def\macroA{"Deze onbeschermde macro bevat een string"}
\protected\def\macroB{"Deze beschermde macro bevat ook een string"}
```

Als je Lua’s tekenreeksconcateneringsoperator gebruikt (`..`) om te schrijven

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

`\directlua`’s voorbewerking zou de volgende code produceren om aan Lua door te geven:

`local x="Deze onbeschermde macro bevat een string"..\macroB`

`\macroA` is niet gedefinieerd met `\protected` dus wordt het uitgebreid, waardoor het eerste deel van de samen te voegen tekenreeks ontstaat, maar `\macroB` is gedefinieerd met `\protected` dus is het niet uitgebreid.

Tijdens de voorbewerking heeft LuaTeX’s `scan_toks()` functie een token gemaakt voor `\macroA`, herkende dat het een gewoon uitbreidbaar commando was en breidde het uit: die uitbreiding produceert een reeks tekentokens, één tekentoken voor elk teken in `"Deze onbeschermde macro bevat een string"`. Elk tekentoken wordt doorgegeven en toegevoegd aan de tokenlijst die wordt opgebouwd.

Wanneer `scan_toks()` het token voor `\macroB` maakt, merkt het dat dat commando was gedefinieerd als `\protected` en het breidt het niet uit: het token dat `\macroB` voorstelt, gaat ongewijzigd (niet uitgebreid) door naar de tokenlijst die wordt opgebouwd. Nadat die tokenlijst is opgebouwd, is de volgende fase van de voorbewerking, binnen de `tokenlist_to_cstring()` functie, om alle tokens in de tokenlijst terug om te zetten naar hun tekstuele representatie. Het onuitgebreide token dat `\macroB` vertegenwoordigt wordt gedetecteerd en omgezet naar zijn tekstuele representatie, wat resulteert in de tekst `\macroB` die in de code verschijnt die voor Lua bestemd is. Merk op dat Lua eigenlijk niet kan samenvoegen `"Deze onbeschermde macro bevat een string"..\macroB` om de uiteindelijke tekenreeks te produceren, omdat `\macroB` geen betekenis heeft in Lua’s syntaxis, wat resulteert in de fout `onverwacht symbool nabij '\'`.

**Trivia**: De `\protected` commando werd geïntroduceerd door $$\varepsilon\text{-}\mathrm{\TeX}$$, de eerste grote uitbreiding van Knuths oorspronkelijke TeX-software, en wordt ondersteund door alle TeX-engines waarvan de codeafstamming $$\varepsilon\text{-}\mathrm{\TeX}$$.

### Niet-uitgebreide tokens: \the\toks gebruiken in \directlua

Het leven in programmeren zou niet hetzelfde zijn zonder die “speciale gevallen” om mee om te gaan en het gebruik van `\the` in combinatie met `\toks` in een `\directlua` commando is zo'n speciaal geval.

#### Korte achtergrond over \toks

De TeX-primitive `\toks` instrueert een TeX-engine om enkele tokens op te slaan voor later gebruik: in plaats van te worden doorgegeven voor verdere verwerking, worden die tokens terzijde gelegd en opgeslagen in een geheugenlocatie die wordt gespecificeerd met een *tokenregister*. We kunnen een TeX-engine bijvoorbeeld opdragen om enkele tokens aan te maken en ze op te slaan in tokenregisterlocatie `100` met behulp van

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

Hier gebruikt TeX tokenregister `100` om toegang te krijgen tot een bekende locatie in zijn geheugen: een opslagruimte die is bestemd voor het bewaren van lijsten met tokens.

Tokens die alles tussen de `{` en `}` worden aangemaakt, *maar niet uitgebreid*, en aan elkaar geregen in een tokenlijst—vergelijkbaar met de tokenlijst die we eerder in dit artikel hebben bekeken. Om die tokens opnieuw te gebruiken zouden we schrijven `\the\toks100` waarin `\the` (een uitbreidbaar commando) TeX instrueert om de opgeslagen tokens op te halen en ze in te voegen op de locatie waar je schreef `\the\toks100`. `\the\toks` zorgt ervoor dat TeX enkele tokens op die locatie invoegt.

De `\toks` commando *breidt niet uit* geen van de tokens die het moet aanmaken en opslaan: het zet simpelweg de tekens en commando's tussen `{` en `}` om in tokens en slaat ze op.

#### Terug naar \directlua

In de bespreking van uitbreiding merkten we op `\directlua{⟨code⟩}` voert *volledige expansie* van `⟨code⟩`: alle uitbreidbare commando's verwijderen en ze vervangen door het resultaat van hun uitbreidingsgedrag—vervolgens doorgaan met *verder uitbreiden* alle tokens die voortkomen uit de eerste uitbreiding van een uitbreidbaar commando.

`\the` is een uitbreidbaar commando, dus `\directlua` zal het uitbreiden; echter, wanneer `\the` in combinatie met `\toks` binnen `\directlua`, zoals in `\the\toks⟨token register⟩`, worden de ingevoegde tokens *niet verder uitgebreid*. Uitbreiding van `\the\toks⟨token register⟩` injecteert de reeks *niet-uitgebreid* tokens, opgeslagen in `⟨token register⟩`, rechtstreeks in de tokenlijst die wordt opgebouwd door `\directlua`: dit gedrag omzeilt het gebruikelijke proces van volledige uitbreiding. In feite gaan die tokens door, *niet-uitgebreid*, om opgenomen te worden in de hoofdtokenlijst die wordt opgebouwd door `\directlua`—dit doorgeefproces voor onuitgebreide tokens lijkt qua werking op `\unexpanded`, zoals eerder besproken.

**Voorbeeld**

Stel dat we de macro definiëren `\mymacro` als `\def\mymacro{\TeX}`. Het bevat slechts één token voor het `\TeX` commando (dat een macro is): dus hebben we een uitbreidbaar commando `\mymacro` dat een andere macro bevat `\TeX`, die ook uitbreidbaar is.

De volgende code zal ertoe leiden dat Lua probeert een tekenreeksvariabele aan te maken `x`:

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

Binnen \\`directlua`, wordt het token voor `\mymacro` uitgebreid, maar dat resulteert in een ander uitbreidbaar token, `\TeX`, dat verder wordt uitgebreid. In plain TeX resulteren die uitbreidingen in de volgende tekst die aan Lua wordt doorgegeven:

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

Deze code probeert een tekenreeks te definiëren die tekst bevat die de uitgebreide versie van de `\TeX` macro voorstelt. Als je dit voorbeeld probeert uit te voeren, zal Lua die tekenreeks proberen samen te stellen, maar het zal mislukken en een fout genereren:

`ongeldige escape-reeks nabij ' "T\k'.`

Later in dit artikel zullen we de betekenis van “ongeldige escape-reeks” verkennen.

Laten we nu het gebruik van `\mymacro` afzetten tegen het plaatsen van het `\TeX` token binnen een tokenlijst die is gegenereerd door een `\toks` commando:

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

LuaTeX’s `\directlua` verwerking zal deze tekenreeks voor Lua genereren:

`local x = "\TeX "`

Het spatieteken na `\TeX` wordt gegenereerd door LuaTeX’s conversieproces van commando-token naar tekenreeks.

**Maar merk op**: De `\TeX` macro is *niet* uitgebreid tot zijn samenstellende tokens. `\the\toks100` heeft ervoor gezorgd dat de tokens in register 100 werden ingevoegd, maar dat is alles: ze worden *niet* niet verder uitgebreid en worden opgenomen in de hoofdtokenlijst die wordt opgebouwd door `\directlua` (binnen de functie `scan_toks()`). Tokens in een tokenlijst plaatsen die is aangemaakt door `\toks` is weer een andere manier om te voorkomen dat tokens worden uitgebreid.

Als we dit voorbeeld uitvoeren, produceert het ook een fout:

`ongeldige escape-reeks nabij ' "\T'.`

We verkennen Lua-escape-reeksen later in het artikel.

## Andere commando's/technieken die bij uitbreiding worden gebruikt

In deze sectie bekijken we enkele aanvullende TeX-commando's/methoden die nuttig kunnen zijn in situaties waarin uitbreiding wordt toegepast (zoals binnen `\directlua`).

### \string ⟨token⟩

`\string` is een uitbreidbaar commando dat het ⟨token⟩ omzet in een reeks tekentokens, elk met categoriecode 12.

Bijvoorbeeld, `\string\TeX` zou een reeks van 4 tekentokens opleveren `\`, `T`, `e` en `X` waarbij elk teken categoriecode 12 krijgt toegewezen (inclusief het voorloop `\` teken).

Als we schrijven

```
\directlua{
   local x="Ik zal \string\newcommand gebruiken"
   print(x)
}
```

het `\string` commando wordt uitgebreid, wat resulteert in een reeks tekentokens met categoriecode 12. Nadat `\string` is uitgebreid, worden de resulterende tekentokens (die elk teken in `\newcommand`) vertegenwoordigen, opgenomen in de hoofdtokenlijst die wordt opgebouwd door `\directlua`. Zodra `\directlua` klaar is met het opbouwen van zijn hoofdtokenlijst, worden de samenstellende tokens terug omgezet naar hun tekstuele representatie, wat de volgende code oplevert om door te geven aan de Lua-interpreter:

`local x="Ik zal \newcommand gebruiken" print(x)`

Wanneer deze code aan Lua wordt doorgegeven, `print(x)` zal de tekenreeks `x` naar het scherm (console) uitvoeren. We zijn echter een beetje sluw geweest en hebben expres een voorbeeldcommando gebruikt dat begint met `\n`. Als je dit voorbeeld kunt uitvoeren op een lokale TeX-installatie, zul je merken dat Lua de volgende tekst op het scherm afdrukt:

```
   Ik zal gebruiken
   ewcommand
```

Om deze code op Overleaf uit te voeren, kun je LuaTeX instrueren om rechtstreeks te schrijven naar de `.log` bestand met behulp van de LuaTeX-Lua-API-functie `texio.write(*string*)`:

```
\directlua{
   local x="Ik zal \string\newcommand gebruiken"
   texio.write(x)
}
```

Als je het resulterende `.log` bestand bekijkt, zie je dat het ook bevat

```
   Ik zal gebruiken
   ewcommand
```

Deze onverwachte uitvoer is te wijten aan Lua’s interpretatie van de `\n` aan het begin van `**\n**ewcommand` als de escape-reeks voor het linefeed-teken (tekencode 10): het gaat ervan uit dat je een nieuwe regel tekst wilt beginnen die begint met `ewcommand`. We bespreken Lua-escape-reeksen later in dit artikel.

### \detokenize{⟨material⟩}

`\detokenize` is in zijn effect een versie met meerdere tokens van `\string` en het is ook een uitbreidbaar commando dat alles in `⟨material⟩` omzet in een reeks tekentokens met categoriecode 12—*behalve* spatietekens (ASCII/Unicode-waarde 32) die categoriecode 10 krijgen. `\detokenize` voegt ook een afsluitend spatieteken toe na commando-namen die *control words* (bijv., `\foo`) maar er wordt geen spatieteken toegevoegd na *controlsymbolen* (bijv., `\#`, `\%` enz.).

### Voorbeeld

Zelfs als de macro's `\foohoo`, `\foo`, `\bar` en `\foobar` niet gedefinieerd zijn, als je dit schrijft:

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

zou het de volgende tekst als code opleveren om door te geven aan de Lua-interpreter

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

Als je `\string` en `\detokenize` niet gebruikt en schrijft:

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

`\directlua` zou verwerken `\foohoo`, herkennen dat het een commando is en proberen het uit te breiden; maar omdat `\foohoo` niet gedefinieerd is, zou dat resulteren in een fout:

```
   ! Ongedefinieerde controlesequentie.
   l.1 \directlua{local x = "\foohoo
                      \foo\bar\foobar"}
         ?
```

Omdat `\string` en `\detokenize` zetten hun argumenten om in een reeks tekentokens, `\directlua`’s uitbreidingsproces krijgt wel de gelegenheid om uitbreidbare commando-tokens te detecteren `\foohoo`, `\foo`, `\bar`, of `\foobar`: ze worden al lang voordat ze uitbreiding kunnen activeren omgezet in reeksen tekentokens.

Zoals eerder opgemerkt, houdt uitbreiding van een commando in dat het uit de invoer wordt verwijderd en vervangen door het resultaat van zijn “uitbreidingsgedrag”. De resultaten van de uitbreiding (meestal tokens) worden vervolgens door de TeX-engine gelezen. Hier is het “uitbreidingsgedrag” voor `\string` en `\detokenize` om tekens en commando-tokens uit de invoer op te nemen en ze om te zetten in reeksen tekentokens, aanvankelijk opgeslagen in een tijdelijke tokenlijst, die `\directlua` vervolgens wordt gelezen. Die tekentokens worden opgenomen in de hoofdtokenlijst die wordt opgebouwd door `\directlua`.

De volgende afbeelding toont hoe `\string` het `\foohoo` commando omzet in een reeks tekentokens, waarbij een tijdelijke tokenlijst wordt geproduceerd die vervolgens wordt gelezen door `\directlua` om die tekentokens op te nemen in de hoofdtokenlijst die wordt opgebouwd.

![](/files/a1c3a4f2c12161a1b8dc62480411692880cc1669)

Als `\string` of `\detokenize` tekens tegenkomen in hun argument, bijvoorbeeld, `\string a` of `\detokenize{abc}` die tekens (hier, met categorische code 11) produceren karaktertokens maar met categorische code 12.

Opmerkingen:

Als we teruggaan naar het bovenstaande voorbeeld:

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

dat de volgende tekst oplevert als code om door te geven aan de Lua-interpreter

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

kunnen we het volgende waarnemen:

* `\detokenize` heeft na elke macronaam een spatie ingevoegd, maar `\string` deed dat niet.
* `\string` werkt op één token.
* In de string `"\foohoo\foo \bar \foobar "` gebruikt om te definiëren `x` zullen we opnieuw het mechanisme voor escape-tekens van Lua tegenkomen (hieronder besproken):

  * `\bar` begint met `\b` wat de Lua-escapesequentie is die wordt gebruikt om het [backspace-teken](https://en.wikipedia.org/wiki/Backspace) (tekencode 8);
  * commando's `\foohoo`, `\foo` en `\foobar` begint allemaal met `\f`, de Lua-escapesequentie die wordt gebruikt om het [formfeed-teken](https://en.wikipedia.org/wiki/Page_break#Form_feed) (tekencode 12).

  Omdat de tekenreeksen `\b` en `\f` worden gebruikt binnen een string die met dubbele aanhalingstekens is gemaakt `"..."` zullen ze ongewenste resultaten opleveren, tenzij maatregelen worden genomen om dat te voorkomen met Lua’s zogenoemde *lange haken* stringmethode: een onderwerp dat we nu kunnen bespreken samen met Lua-escapesequenties.

## Wat zijn “Lua-escapesequenties”?

Programmeertalen reserveren bepaalde tekens voor “speciaal gebruik” als onderdeel van de syntaxis van de taal: in feite krijgen die tekens een speciale betekenis toegewezen. Er zijn echter momenten waarop je tijdelijk de speciale betekenis van zo’n teken moet “uitschakelen” als je bijvoorbeeld wilt dat dat teken ingebed wordt als onderdeel van een langere string waarin het standaardgedrag syntaxisfouten zou veroorzaken. In wezen moet dat teken worden verwerkt *zonder* zijn standaardinterpretatie te activeren—erdoorheen glippen zonder opgemerkt te worden. Om dit te doen gebruiken programmeurs een techniek genaamd *escapen* escapesequentie *Een standaardvoorbeeld (ook ondersteund door Lua) is het gebruik van dubbele aanhalingstekens binnen een string, waarbij je de dubbele aanhalingstekens binnenin escapt met de escapesequentie*.

\\" `"Wanneer hen naar LuaTeX werd gevraagd, antwoordden ze: \"Het is een geweldige TeX-engine!\" Ik was het daarmee eens."`:

`De Lua-taal biedt een aantal mechanismen om met escapesequenties te werken:`

standaardsequenties waaronder

* (nieuwe regel), `\n` \n `\r` (carriage return), `\\` (backslash), `"Wanneer hen naar LuaTeX werd gevraagd, antwoordden ze: \"Het is een geweldige TeX-engine!\" Ik was het daarmee eens."` (dubbel aanhalingsteken), `\t` (horizontale tab), `\v` (verticale tab) en `\'` (enkel aanhalingsteken);
* `\xXX`, waarbij `XX` een reeks van precies twee hexadecimale cijfers is;
* `\ddd`, waarbij `ddd` een reeks van maximaal drie decimale cijfers is;
* Ten tijde van het schrijven van dit artikel (augustus 2019) gebruikt de nieuwste versie van LuaTeX, hoewel nog niet beschikbaar op Overleaf, versie 5.3 van Lua, die ondersteuning voor UTF-8-escapesequenties introduceerde: `\u{XXX}`. Dit escape-mechanisme is voor UTF-8-gecodeerde Unicode-tekens waarbij `XXX` een reeks van één of meer hexadecimale cijfers is die het karaktercodepunt weergeven. Merk op dat de omsluitende haakjes `{ }` verplicht zijn.

### Escape-sequenties beheren

Traditioneel worden strings gedefinieerd met dubbele aanhalingstekens, zoals in `"dit is een string"`; binnen zo’n string kun je escapesequenties gebruiken: `"dit is een string.\nIk begin nu op een nieuwe regel."`. Lua heeft echter nog een tweede en *zeer* handig mechanisme om strings te definiëren: het zogenoemde *lange haken* mechanisme, waarbij je een string definieert door de tekst in te sluiten tussen `[[` en `]]`:

`[[Ik ben een string met lange haken]]`

Binnen een string die met de lange-hakenmethode is gemaakt, is Lua’s teken-escape-mechanisme *uitgeschakeld*: escapesequenties worden als gewone tekens behandeld. Bijvoorbeeld, in de string

`[[Ik ben een string met lange haken\n string]]`

het `\n` escapesequentie niet behandeld als het enkele carriage-returnteken (ASCII-code 13), maar als twee gewone tekens: `\` gevolgd door `n`.

### Waarom zijn strings met lange haken zo nuttig?

Zoals we later zullen onderzoeken, biedt LuaTeX een reeks gespecialiseerde, ingebouwde Lua-functies die je kunt gebruiken met `\directlua` om het zetgedrag van LuaTeX te regelen. Onder die vele functies bevindt zich er één genaamd `tex.print(*string*)` waarmee je `*string*` materiaal uit Lua-code terug naar LuaTeX kunt doorgeven om te zetten. Een heel eenvoudig voorbeeld is:

`\directlua{tex.print("Hallo, wereld!")}`

waardoor LuaTeX het volgende zal zetten `Hallo, wereld!`

De `*string*` gebruikt in `tex.print(*string*)` kan ook tekst bevatten die TeX- en LaTeX-opdrachten voorstelt die LuaTeX moet verwerken. TeX/LaTeX-opdrachten beginnen echter met een `\` teken, wat problematisch is bij strings die met dubbele aanhalingstekens zijn gemaakt, omdat Lua de string zou proberen te parsen, het eerste `\` teken zou detecteren en het als het begin van een escapesequentie zou interpreteren. Wanneer Lua de escapesequentie probeert te verwerken, mislukt dit meestal omdat het eerste `\` samen met de eerste letter van veel TeX/LaTeX-opdrachtnamen geen geldige escapesequentie vormt die Lua kent. Bijvoorbeeld, bij het verwerken van een string zoals `"Ik hou van \LaTeX"` zou Lua `\L` zien en falen met de fout “ongeldige escapesequentie”, en dat is de oorzaak van de hierboven genoemde fouten.

#### Strings met lange haken bieden uitkomst!

De methode met lange haken om strings te maken (te definiëren) is uiterst nuttig omdat, ook al beginnen TeX/LaTeX-opdrachten met een `\` teken, de stringmethode met lange haken het escapesequentiemechanisme van Lua uitschakelt. Hier is een kort voorbeeld, waarbij we eraan denken dat we moeten voorkomen dat macro's worden uitgebreid met bijvoorbeeld `\protected` of `\noexpand`.

Stel dat we een `\newtest` macro als volgt definiëren

`**\protected**\def\newtest#1{Het argument: #1}`

en deze gebruiken in `\directlua` met de LuaTeX Lua-API-functie `tex.print()`:

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

Door het gebruik van `\protected`, wordt de macro `\newtest` niet uitgebreid, wat resulteert in de volgende tekst die aan Lua wordt doorgegeven:

`tex.print("\newtest {Hello}")`

Het spatiekarakter dat na `\newtest` en vóór de opening accolades (`{`) is een neveneffect van `\directlua`’s conversie van commandotokens terug naar hun tekstuele weergave.

Deze code wordt aan Lua doorgegeven, waarna Lua vervolgens de LuaTeX-functie uitvoert `tex.print()` maar er is een probleem dat zich op manieren manifesteert die afhangen van de lettertypen die je gebruikt. In LaTeX op Overleaf zou je uitvoer zoals deze zien:

![](/files/1f58af818d5fdade1b8c9e60627305d7814055a8)

samen met een waarschuwing in het logbestand:

```
   Ontbrekend teken: er is geen
   (U+000A) in lettertype [lmroman10-regular]:+tlig;!
```

In plain TeX kun je uitvoer zien die er ongeveer zo uitziet:

![](/files/37014e06dabf38fa9f4785014b56e43185ce018c)

In beide gevallen wordt de `\newtest` macro wordt niet aangeroepen en de uitvoer is niet wat we bedoeld hadden. De fout wordt veroorzaakt door Lua’s mechanisme voor escape-tekens: in de `\newtest {Hello}` begint de macronaam met `\n` dat Lua herkent als de escapesequentie voor een linefeed-teken, dus vervangt het `\n` door ASCII-teken 10, of in hex 0A. In de LaTeX-foutmelding, `U+000A` een manier is om de Unicodewaarde weer te geven met 4 hexadecimale cijfers.

Omdat de `\n` wordt omgezet naar het linefeed-teken, ziet LuaTeX geen macro-aanroep maar denkt het in plaats daarvan dat het de opdracht krijgt om tekst te zetten die begint met ASCII-tekencode 10:

`⟨ASCII 10⟩ewtest {Hello}`

Afhankelijk van het gebruikte lettertype kan LuaTeX het `⟨ASCII 10⟩` teken mogelijk wel of niet zetten, maar de resterende tekst wordt ongewijzigd uitgevoerd met de `{` en `}` behandeld als een groep en niet afgedrukt.

Plain TeX geeft een ander resultaat omdat het standaardlettertype Computer Modern Roman een vreemde codering heeft, waardoor er een hoofdletter Omega wordt gezet wanneer tekencode 10 wordt gezien.

Om deze problemen te voorkomen moeten we strings met lange haken gebruiken om te voorkomen dat Lua’s escape-mechanisme wordt toegepast. Het juiste resultaat wordt verkregen met

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

wat het resultaat oplevert dat in de volgende schermafbeelding wordt getoond:

![](/files/1f2e652a93be8344d29de2318f82099d2b58705a)

### Uitbreiding en niet-uitvoering van niet-uitbreidbare opdrachten

Bij de bespreking van uitbreiding merkten we op dat dit een proces is waarbij een TeX-engine *verwijdert* een uitbreidbare opdracht (token) uit de huidige invoer haalt en *vervangt* door het resultaat/de resultaten die door die uitbreidbare opdracht worden geproduceerd. Omdat \directlua *alleen-uitbreiding* activiteiten uitvoert (om een tokenlijst te genereren), gaat het *doet niet* de verwerking van LuaTeX niet verder dan dat. Zodra een uitbreidbare opdracht is gelezen en volledig is uitgebreid, worden de resultaten van die uitbreiding — die vaak niet-uitbreidbare opdrachten (tokens) bevatten — opgenomen in de tokenlijst die wordt opgebouwd, klaar om terug te worden omgezet naar tekst en doorgegeven aan Lua.

Hier geldt een belangrijk principe: tijdens *alleen-uitbreiding* activiteiten die bedoeld zijn om een tokenlijst te produceren, voeren TeX-engines, inclusief LuaTeX, *voeren* geen enkele niet-uitbreidbare primitieve, ingebouwde TeX-opdrachten.

In het geval van `\directlua{⟨code⟩}`, als de volledig uitgebreide versie van je `⟨code⟩` niet-uitbreidbare TeX/LaTeX-opdrachten produceert of bevat, dan *worden ze doorgegeven aan Lua* (als tekst weergegeven).

#### Voorbeeld

Hier is een voorbeeld om te laten zien dat niet-uitbreidbare primitieve opdrachten niet worden uitgevoerd tijdens alleen-uitbreidingsverwerking (zoals binnen `\directlua`). Stel dat we een macro definiëren `\setcountreg` als volgt:

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

**Opmerking**: We gebruiken `\relax` na parameter `#2` om te voorkomen dat LuaTeX doorschiet tijdens het scannen van de invoer bij het zoeken naar de numerieke waarde (het argument) die overeenkomt met parameter `#2`.

Als, buiten `\directlua`, we later de macro als volgt uitvoeren

```
   \setcountreg{100}{50}
   De waarde in telregister 100 is \the\count100.
```

zou dit opleveren

`De waarde in telregister 100 is 50.`

In deze context zou elke TeX-engine de macro verwerken `\setcountreg`—de macro uitbreiden, de argumenten bepalen en verder lezen *en uitvoeren* (uitvoeren) van opdrachten die in de vervangende tekst (definitie) van de macro staan. Het resultaat hier is het toewijzen van `50` als de waarde opgeslagen in register `\count100`.

Wanneer een TeX-engine echter *alleen-uitbreiding* activiteiten uitvoert, zoals bij `\directlua`, zal hij *zal niet uitvoeren* de niet-uitbreidbare opdrachten die in de definitie van de macro staan.

Als we schrijven

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

produceert het de volgende tekst als code voor Lua:

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

De hierboven geproduceerde Lua-code laat zien dat binnen `\directlua` het `\setcountreg` is uitgebreid, zijn argumenten geïdentificeerd en ingevuld in de juiste parameter (`#1` en `#2`) maar het gaat niet verder dan dat: de niet-uitbreidbare primitieve TeX-opdracht `\count` werd *niet uitgevoerd* tijdens `\directlua`’s uitbreidingsverwerking.

LuaTeX zal de TeX-code echter uitvoeren als we de resulterende string `x` *terug naar LuaTeX doorgeven* via `tex.print(x)` als volgt

```
\count100=50 % stel \count100 in op een beginwaarde van 50
\def\setcountreg#1#2{\count#1=#2\relax}
\directlua{
   local x = [[\setcountreg{100}{250}]]
   tex.print(x)
}
De waarde opgeslagen in telregister 100 is \the\count100.
```

Na `\directlua` zou de uitvoer zijn

`De waarde opgeslagen in telregister 100 is 250.`

wat laat zien dat telregister `100` nu de waarde bevat `250`.

De uit het bovenstaande voorbeeld geproduceerde Lua-code is

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

Deze code definieert `x` als een string die met de lange-hakenmethode is gemaakt, die wordt gebruikt om fouten met onjuiste escapesequenties te voorkomen. Als we dubbele aanhalingstekens zouden gebruiken `"..."` om x te definiëren, zou de tekencombinatie `\c` aan het begin van `\count` een fout veroorzaken: `ongeldige escapesequentie nabij ' "\c'`.

De LuaTeX Lua-API-aanroep `tex.print(x)` zorgt ervoor dat LuaTeX de TeX-codereeks uitvoert `\count 100=250\relax` en `\count100` krijgt een waarde van `250` zoals te zien is aan de gezette uitvoer:

`De waarde opgeslagen in telregister 100 is 250.`

#### Waarschuwing: macro's en de LuaTeX Lua-API

In het bovenstaande voorbeeld zagen we dat tijdens `\directlua`’s voorverwerking (uitbreiding) LuaTeX de code niet uitvoerde `\count 100=250`, die de `niet-uitbreidbare` primitieve opdracht `\count`: om die code uit te voeren moesten we *deze terug doorgeven aan LuaTeX* via `tex.print()`.

`\directlua` is slechts één geval waarin LuaTeX alleen-uitbreidingsverwerking uitvoert om een tokenlijst samen te stellen. Er zijn andere opdrachten die vergelijkbare uitbreidingsverwerking en tokenlijstgeneratie uitvoeren, zoals `\write` en `\edef`: die opdrachten voeren ook geen niet-uitbreidbare primitieve opdrachten uit tijdens hun uitbreidingsverwerking. Het is een algemeen principe dat TeX-engines geen niet-uitbreidbare primitieve opdrachten uitvoeren bij het samenstellen van een tokenlijst tijdens alleen-uitbreidingsverwerking.

**Onze macro herschrijven om de LuaTeX Lua-API te gebruiken**

We kunnen de `\setcountreg` macro herschrijven met een LuaTeX Lua-API-functie genaamd `tex.setcount()`, waardoor TeX-opdrachten om de waarde opgeslagen in telregister `100`:

```
   \def\setcount#1#2{\directlua{tex.setcount(#1,#2)}}
   \count100=50
   telregister 100 bevat \the\count100\par
   \setcount{100}{250}
   telregister 100 bevat nu \the\count100\par
```

Deze code zal het volgende zetten:

```
telregister 100 bevat 50
telregister 100 bevat nu 250
```

Hier gebruiken we `tex.setcount()`, een van de vele Lua-API-functies van LuaTeX, om *rechtstreeks toegang te krijgen tot* het interne gegevensopslaggebied van LuaTeX om de waarde te plaatsen `250` in de geheugenlocatie die telregister voorstelt `100`. We hebben in feite *omzeild* de standaard invoerverwerkingsmethoden van de TeX-engine van LuaTeX: invoer lezen, tokens maken en TeX-primitieve opdrachten uitvoeren. Er is echter een waarschuwing: door de Lua-API-functies van LuaTeX te gebruiken, kan alleen-uitbreidingsverwerking *leiden tot neveneffecten*: wijzigingen in waarden die binnen de TeX-engine zijn opgeslagen, die anders met zuivere TeX/LaTeX-opdrachten niet mogelijk zouden zijn.

**Voorbeeld: onverwachte neveneffecten**

Hier is een voorbeeld om te demonstreren *onverwachte* neveneffecten die kunnen ontstaan bij macro's die `\directlua`. Stel dat we de volgende code schrijven:

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

Bij het uitvoeren van deze code wordt gezet `12345`!

Hoe kan dat? We hebben niet *expliciet* een code of macro aangeroepen om die waarde in telregister te plaatsen `999`. Of wel?

We definieerden `\dochange` met een `\directlua` opdracht die `tex.setcount()` gebruikt om de waarde op te slaan `12345` in telregister `999`: in TeX-code is dit gelijk aan `\count999=12345`. Vervolgens gebruikten we de standaard TeX-primitief `\edef` om de macro te definiëren `\careful`—het is het gebruik van `\edef` dat het onverwachte neveneffect veroorzaakt.

`\edef` breidt zijn argument volledig uit: hier detecteert het een uitbreidbare macro `\dochange` en breidt die uit. De `\dochange` macro gebruikt de uitbreidbare opdracht `\directlua` die een Lua-API-aanroep bevat; dus de uitbreiding van `\dochange` leidt tot de uitbreiding van `\directlua` en dat zorgt ervoor dat `tex.setcount()` wordt aangeroepen, waardoor de waarde in telregister `999`.

Als we `\dochange` herdefiniëren om TeX-opdrachten te gebruiken:

```
   Vooraf: telregister 999 bevat \the\count999.\par
   \def\dochange{\count999=12345\relax}
   \edef\careful{\dochange}
   Na afloop: telregister 999 bevat \the\count999.\par
```

wordt bij het uitvoeren van deze code gezet

```
Vooraf: telregister 999 bevat 0.
Achteraf: telregister 999 bevat 0.
```

Duidelijk was er geen effect op `\count999`. Wanneer `\edef` definieert `\careful` het breidt uit `\dochange` maar die uitbreiding produceert alleen TeX-primitieven die niet uitbreidbaar zijn: die zijn *niet uitgevoerd* maar gewoon *opgeslagen* in de tokenlijst die de definitie van `\careful`.

Gewoon ter volledigheid verklaart hetzelfde principe waarom dit zetwerk als uitvoer produceert:

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

## Korte introductie tot de Lua-API van LuaTeX

Zoals we hebben gezien, `\directlua` biedt niet alleen de mogelijkheid om conventionele Lua-code te schrijven, of een mengsel van Lua- en TeX/LaTeX-code, maar geeft ook toegang tot een reeks extra Lua-functies (specifiek voor LuaTeX) die je kunt gebruiken (aanroepen) om te communiceren met, of rechtstreeks controle uit te oefenen over, de interne werking van de zetsoftware LuaTeX. We hebben in dit artikel verschillende Lua-functies gebruikt, `tex.print()`, `texio.write()`, `tex.setcount()` en deze, samen met *veel* meer, zijn gedocumenteerd in [De LuaTeX-referentiehandleiding](http://www.pragma-ade.com/general/manuals/luatex.pdf) waarin groepen verwante functies worden aangeduid als *bibliotheken*.

Je kunt deze Lua-functies zien als LuaTeX' Lua-API (**A**applicatie **P**rogrammeer **I**interface) die de hulpmiddelen bieden om geavanceerde zet- en documentengineeringoplossingen te construeren door het zetgedrag van LuaTeX te sturen met Lua als aansturing.

Zoals opgemerkt organiseert LuaTeX zijn API in een set functies die het bibliotheken noemt: groepen functies die verwant zijn door hun doel of werking. Elke set functies is ontworpen om toegang te bieden tot een bepaald aspect van LuaTeX' interne processen, datastructuren, gegevensopslag en zetalgoritmen. Intern is LuaTeX opgebouwd uit meerdere componenten: softwarebibliotheken/hulpmiddelen (grotendeels geschreven in C) die niet alleen de TeX-engine zelf omvatten, maar ook andere subsysteemdelen waaronder Lua, MetaPost, Kpathsea, FontForge, libpng en zlib. Deze bibliotheken zijn geïntegreerd om de functies van de uitvoerbare LuaTeX-software op te bouwen en via de Lua-API krijgen gebruikers toegang tot de functionaliteit van LuaTeX die voortkomt uit de integratie en coördinatie van die meerdere softwarecomponenten.

## Enkele voorbeelden en valkuilen

In deze sectie presenteren we enkele verdere voorbeelden die gebruikmaken van de onderwerpen, concepten en uitleg die in dit artikel zijn gegeven.

### De tildekarakter (\~) gebruiken

De Lua-taal gebruikt het `~` teken (tilde genoemd) als onderdeel van zijn syntax, inclusief de syntax om een “niet gelijk aan”-test uit te voeren; om bijvoorbeeld te testen of een variabele `x` niet gelijk is aan `4` kunnen we schrijven:

```
   local x=3
   if x ~= 4 then
   print("x is niet gelijk aan 4")
   end
```

Als we dit eenvoudige Lua-codefragment via `\directlua`:

```
\directlua{
   local x=3
   if x ~= 4 then
   print("x is niet gelijk aan 4")
   end
}
```

proberen uit te voeren, krijgen we een fout:

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

Dat is vreemd, want onze code is correct: we hebben `'then'` gebruikt en er is geen `\` teken in onze code, dus wat ging er mis? Om dit te begrijpen moeten we ons herinneren dat, voor TeX/LaTeX, `~` meestal is gedefinieerd als een “speciaal teken” met categoriecijfer 13: zogenaamde actieve tekens, die mini-macro's zijn en dus onderhevig aan expansie. Wanneer `\directlua` de `~` teken detecteert, wordt het uitgebreid door *het te verwijderen* uit de invoer verwijderd en *het te vervangen* en te vervangen door het resultaat van zijn expansie. Bij gebruik van plain TeX bevat de resulterende tekst (code) die LuaTeX produceert en doorgeeft aan de Lua-interpreter in feite niet het `~` teken, en is:

`local x=3 if x \penalty \@M \ = 4 then print("x is niet gelijk aan 4") end`

De `~` teken is *verwijderd* en *uitgebreid* tot zijn samenstellende commando's—de Lua-code hierboven is het resultaat van plain TeX' definitie van het actieve teken `~`. Nu kunnen we zien waarom Lua met de fout reageert `'then' expected near '\'`—het begint deze code te ontleden, maar treft het woord `\penalty` aan, wat voor Lua niets betekent en een syntaxisfout genereert.

Om dit te verhelpen, moet het `~` teken een veilige categoriecijferwaarde hebben op het moment dat `\directlua` je code verwerkt; bijvoorbeeld kunnen we de categoriecijferwaarde van `~` tijdelijk wijzigen in 11 (letter) door de code in een groep te omsluiten:

```
\begingroup
\catcode`\~=11
\directlua{
   local x=3
   if x ~= 4 then
   print("x is niet gelijk aan 4")
   end
}
\endgroup
```

Deze code werkt zoals verwacht en `x is niet gelijk aan 4` wordt naar de console afgedrukt. Er zijn andere opties: we kunnen de uitbreidbare commando's gebruiken `\noexpand` of `\string`.

#### Gebruik van \string⟨token⟩

We kunnen `\string` toepassen op het enkelteken- `⟨token⟩` `~` dat categoriecijfer 13 heeft (actief teken); `\string` het `~` teken om een tekentoken te genereren dat categoriecijfer 12 heeft. Als we

```
\directlua{
   local x=3
   if x \string~= 4 then
   print("x is niet gelijk aan 4")
   end
}
```

dan produceert het de Lua-code die we nodig hebben:

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

#### Gebruik van \noexpand⟨token⟩

We kunnen `\noexpand~` gebruiken om expansie van het actieve teken te onderdrukken `~`

```
\directlua{
   local x=3
   if x \noexpand~= 4 then
   print("x is niet gelijk aan 4")
   end
}
```

Het niet-uitgebreide `~` token gaat door naar de tokenlijst die wordt opgebouwd in `\directlua` en zal worden omgezet terug naar tekst, wat werkende Lua-code oplevert.

### Gebruik van het #-teken

Binnen de Lua-taal kan het `#` teken worden gebruikt om de lengte van een tabel te bepalen. Als we echter de volgende code proberen

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

zouden we verwachten dat LuaTeX zetwerk produceert

`De tabelgrootte is 2`

maar het genereert een fout:

`\directlua]:1: poging om de lengte van een numerieke waarde op te vragen`

Deze fout wordt veroorzaakt doordat het `#` teken gewoonlijk categoriecijfer 6 heeft (macroparameter)—het `#` teken heeft twee toepassingen in TeX/LaTeX: om macroparameters aan te geven (`#1`, `#2`… `#9`) en de vervangende tekst in uitlijntemplates (voor `\halign` en `\valign`).

Wanneer `\directlua` t tokens genereert om zijn tokenlijst op te bouwen, ziet het het `#` teken met categoriecijfer 6 en creëert een passend tekentoken om het weer te geven. Wanneer het moment komt om de uiteindelijke tokenlijst terug te zetten naar tekstvorm, krijgt het tekentoken voor # (met categoriecijfer 6) een speciale behandeling: het wordt uitgevoerd als *twee opeenvolgende tekens*: `##`, wat resulteert in de volgende code die aan Lua wordt doorgegeven:

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

Bij omzetting naar Lua-code is de oorspronkelijke `#` verdubbeld en dat genereert een fout:

`\directlua]:1: poging om de lengte van een numerieke waarde op te vragen`

Dit probleem ontstaat door TeX' syntax die een dubbel hekje `##` gebruikt om een enkel `#` token voor te stellen of te genereren; deze syntax wordt gebruikt in macro's die andere macro's definiëren die parameters nemen, of in macro's die worden gebruikt om sjablonen te maken voor de `\halign` of `\valign` tabelconstructiecommando's. Dit is nogal verwarrend, dus laten we naar een voorbeeld kijken.

#### Voorbeeld

Stel dat we een macro definiëren `\mymacro` die één parameter neemt, `#1`, maar die ook een tweede macro definieert `\foo` die zelf één parameter neemt. Om onderscheid te maken tussen de parameter `#1` die met `\mymacro` wordt gebruikt en de noodzaak om `\foo` te definiëren om zijn eigen parameter te gebruiken `#1` vereist TeX-syntax dat je `##1` binnen `\mymacro` moet gebruiken om de parameter weer te geven die met `\foo`:

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

Als je zou schrijven `\mymacro{Hey!}` zou het de macro definiëren `\foo` als

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

Merk op dat de `\mymacro`van de parameter `#1` (`Hey!`) is opgenomen in de definitie van `\foo` en de reeks `##1` is omgezet naar `#1` in de definitie van `\foo`. Dus kunnen we `\foo` als volgt:

`\foo{, World!}`

zetten voor `Hey! Hallo, Wereld!`

We kunnen `\directlua`’s behandeling van het `#` teken oplossen door tijdelijk zijn categoriecijfer te wijzigen voordat LuaTeX de code verwerkt. Bijvoorbeeld:

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

Hieruit ontstaat de Lua-code

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

wat het resultaat zet dat we verwachtten:

`De tabelgrootte is 2`

### Gebruik van het %-teken

Binnen TeX/LaTeX wordt het `%` teken meestal gebruikt om enkelregelige opmerkingen in je code op te nemen: om de TeX-engine te laten weten dat hij alles vanaf dat punt tot het einde van de regel waarop het `%` is geschreven moet negeren. Echter, binnen de Lua-taal wordt het `%` teken gebruikt binnen enkele zeer nuttige tekenreeksverwerkingsfuncties, zoals `string.format(...)`, `string.gmatch(...)` en `string.gsub(...)` waarin het `%` teken een belangrijke rol speelt als onderdeel van de syntax van die functie.

Wanneer het wordt gebruikt met TeX/LaTeX, `%` fungeert als het commentaartken omdat het categoriecijfer 14 heeft. Om het als een normaal teken te laten gedragen en zijn gebruikelijke TeX/LaTeX-gedrag uit te schakelen, moeten we zijn categoriecijfer wijzigen naar iets veiligs, zoals 12. Het `\directlua` voorbeeld hieronder gebruikt een aantal technieken die eerder in het artikel zijn besproken, samen met één die we nog niet hebben genoemd: ``\catcode`\^^M=12``, waarmee we Lua-opmerkingen in onze code kunnen gebruiken; dit wordt hieronder besproken.

#### Voorbeeld

De volgende voorbeelden zijn ontleend aan [lua-users.org](http://lua-users.org/wiki/StringLibraryTutorial), met passende aanpassingen voor gebruik binnen `\directlua`.

```
\documentclass{article}
\begin{document}
\begingroup
\ttfamily
\let\\\relax
\catcode`\^^M=12 %<---we verkennen dit hieronder verder!
\catcode`\%=12
\directlua{
   local str -- declareer een lokale variabele om het resultaat op te slaan

   tex.print("Gebruik van string.format():".."\\par")

   str=string.format("%s %q", "Hallo", "Lua-gebruiker!") -- string en geciteerde string
   tex.print(str.."\\par")
   str = string.format("%c%c%c", 76, 117, 97) -- teken
   tex.print(str.."\\par")
   str=string.format("%e, %E", math.pi, math.pi) -- exponent
   tex.print(str.."\\par")
   str=string.format("%f", math.pi) -- zwevendekommagetal
   tex.print(str.."\\par")
   str=string.format("%g, %g", math.pi, 10^9) -- zwevendekommagetal of exponent
   tex.print(str.."\\par")
   str = string.format("%o, %x, %X", 99, 125, 125)  -- octaal, hexadecimaal, hexadecimaal
   tex.print(str.."\\par")

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

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

   tex.print("\\vskip3mm".."Gebruik van string.gsub():".."\\par")
   str=string.gsub("banana", "(an)", "%1-") -- vang eventuele voorkomens van "an" en vervang
   tex.print(str.."\\par")
}
\endgroup
\end{document}
```

De volgende schermafbeelding toont het zetresultaat van de bovenstaande code:

![Gebruik van Lua-tekenreeksfuncties in \directlua](/files/cb3f75bbb8810ef84bc1f31b9ff99190ed6fe2c8)

## Waarom wordt Lua-code op één regel weergegeven?

Zoals je misschien hebt opgemerkt, worden alle (gegenereerde) Lua-codefragmenten die in de voorbeelden van dit artikel worden getoond, als één enkele tekstregel gepresenteerd: oorspronkelijk aanwezige regeleinden in de `\directlua` codefragmenten worden niet gevolgd. Waarom is dat? Dat komt doordat regeleinden in de Lua-code zijn *verwijderd* tijdens de voorverwerking door LuaTeX binnen `\directlua`, waardoor de Lua-code één lange tekstregel wordt. Dat gedrag is terug te voeren op de manier waarop TeX-engines met regeleindetekens omgaan—aangeduid door `\r` (carriage return) en `\n` (line feed) in programmeerliteratuur. Waarom we ons precies druk zouden moeten maken om deze fijne details wordt duidelijk wanneer we het gebruik van Lua's mechanismen voor het uitcommentariëren van codegedeelten bespreken.

Wanneer software een tekstbestand schrijft (opslaat), wordt elke afzonderlijke tekstregel beëindigd door zogenaamde “newline”-tekens — de daadwerkelijke newline-teken(s) hangen af van de toepassing en het besturingssysteem dat wordt gebruikt om dat bestand weg te schrijven. Wikipedia heeft een [interessant artikel](https://en.wikipedia.org/wiki/Newline) waarin de geschiedenis/evolutie van de huidige newline-tekens wordt verkend.

Voor elk tekstbestand kunnen de afzonderlijke tekstregels worden beëindigd door verschillende combinaties van tekens, aangeduid als carriage return (ASCII/Unicode-teken 13) en/of line feed (ASCII/Unicode-teken 10), die respectievelijk worden aangeduid door `\r` en `\n` respectievelijk. Omdat TeX-engines zijn ontworpen om platformonafhankelijk te zijn, hebben ze een methode nodig om de inherent platformafhankelijke aard van regeleinden in tekstbestanden te omzeilen. Natuurlijk hebben TeX-engines een ingebouwde (maar configureerbare) methode om met regeleindetekens om te gaan.

### Hoe TeX-engines omgaan met regeleinden

Wanneer LuaTeX `\directlua{⟨code⟩}` verwerkt, leest het de tekst in je `⟨code⟩` en past standaardmethoden van de TeX-engine toe voor het verwerken van regeleinden in je `⟨code⟩`. Standaard zorgen die standaardmethoden van TeX ervoor dat alle regeleindetekens (carriage returns en line feeds) worden verwijderd en vervangen door spaties. We zeggen “standaard” omdat de verwerking van regeleindetekens door een TeX-engine kan worden aangepast via een door de gebruiker configureerbare parameter genaamd `\endlinechar`. Hier geven we een kort tweestappenoverzicht, maar verdere details zijn te vinden in het Overleaf-artikel [Een introductie tot \endlinechar: hoe TeX regels uit tekstbestanden leest](/latex/nl/diepgaande-artikelen/05-an-introduction-to-endlinechar-how-tex-reads-lines-from-text-files.md).

#### Stap 1: TeX voegt zijn eigen regeleindeteken in

Nadat TeX-engines een regel tekst uit je invoerbestand hebben gelezen, verwijderen ze onmiddellijk eventuele `\r` of `\n` tekens van het einde van die regel. Vervolgens *voegen* (weer toe) hun eigen regeleindeteken toe aan het einde van die regel. Dat teken wordt bepaald door de waarde van een door de gebruiker configureerbare TeX-parameter genaamd `\endlinechar` en via dit mechanisme kunnen TeX-engines regeleindetekens op platformonafhankelijke wijze verwerken: ze kiezen en zetten het regeleindeteken, ongeacht wat oorspronkelijk in het invoertekstbestand stond.

Meestal gebruiken TeX-engines de instelling

`\endlinechar=13`

wat het carriage-returnteken (`\r`). is. Gebruikers kunnen echter altijd een andere tekencode toekennen als de waarde van `\endlinechar`—zoals we later in dit artikel zullen zien.

Bijgevolg worden alle regeleindeteken(s) in je `⟨code⟩` om te worden verwerkt door `\directlua{⟨code⟩}` weggehaald en vervangen door een enkel teken dat door de TeX-engine zelf wordt bepaald. Merk op dat TeX-engines deze regeleindeverwerking onmiddellijk uitvoeren nadat ze een nieuwe tekstregel uit een bestand hebben gelezen en *voordat* verwerken van eventuele tekens in die regel (om tokens te genereren). Maar daarmee is het verhaal niet afgelopen: wat de TeX-engine *doet* met die regeleindetekens (die hij heeft ingevoegd) verklaart waarom de Lua-code één enkele regel wordt.

#### Stap 2: TeX zet zijn regeleindeteken om naar een spatie

Naast het invoegen van hun eigen regeleindeteken, gedefinieerd door de waarde van `\endlinechar`, gebruiken TeX-engines ook categoriecijfer 5 voor tekens die moeten worden *behandeld als* een regeleindeteken. Dit resulteert erin dat TeX-engines doorgaans werken met:

1. een regeleindeteken gedefinieerd door `\endlinechar`;
2. datzelfde teken *gewoonlijk* dat categoriecijfer 5 heeft gekregen.

Het is wat TeX met dat regeleindeteken doet dat onze puzzel met enkele regels Lua-code verklaart. Wanneer een TeX-engine een invoerregel verwerkt, zal hij uiteindelijk het laatste teken in die regel detecteren: het teken gedefinieerd door `\endlinechar`. Gewoonlijk heeft dat teken categoriecijfer 5, waardoor TeX *het vervangt* door een spatie: d.w\.z. aan het einde van regels haalt TeX in feite zijn regeleindeteken weg en vervangt het door een spatie. Tussen haakjes: TeX-engines gebruiken tekens met categoriecijfer 5 ook om blanco regels te detecteren en een nieuwe alinea te beginnen, maar daar gaan we hier niet op in.

Natuurlijk kun je, aangezien het TeX is, allerlei speciale macroprogrammeringstrucs uitvoeren door de `\endlinechar` opnieuw in te stellen op een ander teken, en/of door het teken dat aan `\endlinechar` is toegekend een categoriecijferwaarde naar keuze te geven.

Als je wilt voorkomen dat Lua-code één enkele tekstregel wordt, kun je de aan `\endlinechar` toegekende waarde (tijdelijk) wijzigen of het categoriecijfer van de standaard regeleindebeëindiger wijzigen `\r`.

### TeX' bizarre ^^-notatie

In de volgende secties zullen we TeX' ongewone `^^` notatie tegenkomen, die bekendstaat als het "uitgebreide tekenmechanisme". Het werd door Knuth ontworpen als een manier om het typen van "controletekens" zoals regeleindebeëindigers, tabs en dergelijke te vergemakkelijken. Bijvoorbeeld:

* `^^J` vertegenwoordigt tekencode 10 (`\n`, line feed);
* `^^M` vertegenwoordigt tekencode 13 (`\r`, carriage return).

Tekensequenties zoals `^^M` worden vroeg in TeX' invoerscanproces omgezet naar hun overeenkomstige tekencodes, wanneer TeX invoertekens leest om de overeenkomstige tekentokens te genereren.

### Het toewijzen van een ander teken aan \endlinechar

Onthoudend dat we nog steeds moeten voorkomen dat het `~` teken wordt uitgebreid, kunnen we schrijven

```
\begingroup
\endlinechar=10 % Wijzig het regeleindeteken in \n
\directlua{
   local x=3
   if x \noexpand~= 4 then
   print("x is niet gelijk aan 4")
   end
}% we willen niet dat \n hier verschijnt
\endgroup% of hier een \n
```

De bovenstaande instelling voor `\endlinechar` zorgt ervoor dat LuaTeX tekencode 10 (`\n`, line feed) aan het einde toevoegt van elke regel die het inleest. Dit doen we omdat `\n` (line feed) gewoonlijk categoriecijfer 12 heeft, wat je kunt testen door te schrijven ``\the\catcode`\^^J``. Omdat `\n` niet categoriecijfer 5 heeft, zal LuaTeX het niet omzetten naar een spatie, zodat het aan het einde van elke regel blijft staan die door LuaTeX wordt ingelezen. Daardoor blijft een teken met code 10 aan het einde van elke regel staan, en komt het dus terecht in de tokenlijst die wordt opgebouwd door `\directlua` en verschijnt het vervolgens opnieuw in de Lua-code zodra de tokenlijst wordt omgezet naar tekst. Met de bovenstaande wijziging wordt de Lua-code als de volgende tekenreeks naar de Lua-interpreter gestuurd:

**\n**local x=3\*\*\n**if x \~= 4 then**\n**print("x is niet gelijk aan 4")**\n**end**\n\*\*

waarbij de **\n** notatie bedoeld is om tekencode 10 weer te geven *niet* een onbekende macro `\n`. Nu zal de Lua-interpreter regeleinden in de code zien, precies zoals het oorspronkelijk in de `\directlua` commando:

```
   local x=3
   if x ~= 4 then
   print("x is niet gelijk aan 4")
   end
```

Terloops: merk op dat het allereerste teken in de Lua-codeketen `\n` (vóór het `local` sleutelwoord). Dat `\n` ontstaat uit de regel

`\directlua{`

omdat er onmiddellijk na de openings `{` een regeleinde staat en ook dat wordt bewaard. Om dat te voorkomen kun je schrijven

`\directlua{%`

### Het categoriecijfer van \r wijzigen

Om regeleinden in onze Lua-code te behouden kunnen we ook het categoriecijfer van `\r` wijzigen in iets anders dan 5, zodat `\r` niet langer wordt herkend (behandeld als) een regeleindeteken. Met deze techniek gebruikt LuaTeX nog steeds `\endlinechar=13` en zal het blijven toevoegen van een `\r` aan het einde van elke regel; echter, omdat `\r` niet langer categoriecijfer 5 heeft, zal LuaTeX de `\r` teken niet herkennen als een regeleinde: het zal het niet omzetten in een spatie en het ongeschonden doorgeven zodat het in de Lua-code verschijnt.

Onthoudend dat we nog steeds moeten voorkomen dat het `~` teken wordt uitgebreid, kunnen we schrijven

```
\begingroup
\catcode`\^^M=12 % wijzig categoriecijfer van \r naar 12
\directlua{
   local x=3
   if x \noexpand~= 4 then
   print("x is niet gelijk aan 4")
   end
}
\endgroup
```

In dit geval wordt de Lua-code als volgt naar de Lua-interpreter gestuurd:

**\r**local x=3\*\*\r**if x \~= 4 then**\r**print("x is niet gelijk aan 4")**\r**end**\r\*\*

waarbij de `\r` notatie is bedoeld om tekencode 13 weer te geven en niet een onbekende macro `\r`. Net als bij het `\endlinechar` voorbeeld zal de Lua-interpreter nu regeleinden in de code zien, precies zoals het oorspronkelijk in de `\directlua` commando:

```
   local x=3
   if x ~= 4 then
   print("x is niet gelijk aan 4")
   end
```

Terloops: merk nogmaals op dat het allereerste teken in de Lua-codeketen `\r` (vóór het local-sleutelwoord): dit ontstaat ook uit de regel

`\directlua{`

#### Waarom kreeg \r categoriecijfer 12 maar niet categoriecijfer 11?

Het antwoord is vanwege het risico om per ongeluk fouten in te voeren die worden getriggerd door `\r` (van categoriecijfer 11) die aan het einde worden toegevoegd van TeX/LaTeX-opdrachten die uit ons invoerbestand worden gelezen. Neem dit voorbeeld:

```
\begingroup
\catcode`\^^M=11 % wijzig categoriecijfer van \r naar 11
\directlua{
   local x=3
   if x \noexpand~= 4 then
   print("x is niet gelijk aan 4")
   end
}
\endgroup
```

wat een fout genereert:

```
   ! Ongedefinieerde controlesequentie.
   l.9 \endgroup
```

Hoe kan dat waar zijn, aangezien `\endgroup` een standaard TeX-primitief commando is? De oorzaak van de fout is behoorlijk subtiel: toen LuaTeX de laatste regel tekst las—die met `\endgroup`—voegde het ook de `\endlinechar` teken `\r` toe aan het einde van die regel. Nu ziet LuaTeX in zijn geheugen de tekenreeks

`\endgroup\r`

waar we `\r` gebruiken om het teken met code 13 aan te duiden—niet de naam van een onbekende TeX-macro `\r`.

Op het moment dat LuaTeX deze regel uit ons tekstbestand las, is het oorspronkelijke `\begingroup` nog steeds actief: we bevinden ons binnen een groep die nog niet is afgesloten door het uitvoeren van het overeenkomstige `\endgroup` opdracht—waardoor `\r` zou terugkeren naar de vorige categoriecodewaarde van 5.

Wanneer LuaTeX begint met het verwerken (tokens aanmaken) van de regel tekst `\endgroup\r` herkent het het eerste teken `\` als het escapeteken, waardoor LuaTeX begint te zoeken naar de naam van een opdracht. Om een opdrachtnaam te identificeren zoekt LuaTeX naar een reeks tekens met categoriecode 11, maar omdat `\r` ook categoriecode 11 heeft, denkt LuaTeX dat het `\r` teken (nog steeds met categoriecode 11) vormt *deel van een opdracht* genaamd `\endgroup\r` dat natuurlijk niet bestaat, dus meldt LuaTeX een `Ongedefinieerde besturingsreeks` fout. Daarom hebben we categoriecode 12 gebruikt en niet 11.

Omdat de foutmelding van LuaTeX naar de console was geschreven, konden we het `\r` teken niet gemakkelijk zien/opmerken, zodat niet duidelijk was wat de fout had veroorzaakt.

### Waarom maken we ons zorgen over regeleindes?

De reden is om het gebruik van Lua's commentaarmethode in je code mogelijk te maken! Je kunt het standaardmechanisme van LuaTeX gebruiken om `%` tekens toe te voegen om afzonderlijke regels binnen je code te becommentariëren; de Lua-taal heeft echter ook zijn eigen, zeer nuttige, *meerregelige* commentaarmechanismen waarvan je misschien gebruik wilt maken.

Laten we beginnen met te bekijken wat er gebeurt als we proberen enkelregelige Lua-taalcommentaren te gebruiken zonder de problemen met regeleinden aan te pakken. Waar TeX het `%` teken gebruikt om afzonderlijke regels code te becommentariëren, gebruikt Lua een dubbel koppelteken: `--`.

Wat gebeurt er als we proberen dit uit te voeren:

```
\directlua{
   local x=3
   if x \noexpand~= 4 then
   -- Ik ga het resultaat van deze complexe test afdrukken
   print("x is niet gelijk aan 4")
   end
}
```

We krijgen een foutmelding:

`[\directlua]:1: 'end' expected near <eof>`

Deze fout wordt veroorzaakt door het ontbreken van regeleinden in de Lua-code die aan de interpreter wordt doorgegeven, die slechts één doorlopende tekenreeks ziet waarin het commentaar halverwege die reeks begint:

```

local x=3 if x ~= 4 then -- Ik ga het resultaat van deze complexe test afdrukken print("x is niet gelijk aan 4") end
```

Alles na `**local x=3 if x ~= 4 then**` wordt beschouwd als becommentarieerd, waardoor de interpreter een onvolledig deel van Lua-code ziet, wat resulteert in de fout

`'end' verwacht bij <eof>`.

waar `<eof>` betekent einde van bestand.

Zoals je waarschijnlijk al hebt geraden, moeten we dit verhelpen door ervoor te zorgen dat regeleinden worden doorgegeven aan de resulterende Lua-code, wat we bijvoorbeeld kunnen doen door de categoriecode van `\r` naar 12 te wijzigen:

```
\begingroup
\catcode`\^^M=12 % wijzig categoriecijfer van \r naar 12
\directlua{
   local x=3
   if x \noexpand~= 4 then
   -- Ik ga het resultaat van deze complexe test afdrukken
   print("x is niet gelijk aan 4")
   end
}
\endgroup
```

Nu ziet de Lua-interpreter een tekenreeks, maar deze bevat `\r` regeleinden zoals geschreven in het `\directlua` fragment:

**\r**local x=3\*\*\r**if x \~= 4 then**\r\*\*-- Ik ga het resultaat van deze complexe test afdrukken\*\*\r**tex.print("x is niet gelijk aan 4")**\r**end**\r\*\*

Dit komt in feite neer op het schrijven van

```
   local x=3
   if x \noexpand~= 4 then
   -- Ik ga het resultaat van deze complexe test afdrukken
   print("x is niet gelijk aan 4")
   end
```

wat betekent dat Lua deze code correct kan verwerken en de regel die we hebben becommentarieerd kan negeren.

**Blokcommentaren**

De Lua-taal ondersteunt ook een syntaxis die zij [‘blokcommentaar’](https://www.lua.org/pil/1.3.html) (of *lange commentaar*): deze beginnen met `--[[` en blijven van kracht tot de bijbehorende `]]`. We kunnen deze handige syntaxis gebruiken om meerregelige commentaren te schrijven, of delen van code te becommentariëren die we tijdelijk willen verwijderen:

```
\begingroup
\catcode`\^^M=12 % wijzig categoriecijfer van \r naar 12
\directlua{
   local x=3
   if x \noexpand~= 4 then
   --[[ Ik ga het resultaat van deze complexe test afdrukken
   simpelweg omdat het echt
   zo'n geweldige conclusie is]]
   print("x is niet gelijk aan 4")
   end
}
\endgroup
```

## Tot slot

Allereerst gefeliciteerd als je erin geslaagd bent dit omvangrijke artikel door te lezen! We hebben geprobeerd een redelijk uitgebreide gids te maken over TeX-gerelateerde concepten en onderwerpen die de achtergrond bieden die nodig is om het meeste uit LuaTeX te halen via de `\directlua` opdracht. We hopen een artikel te hebben geproduceerd dat instructief is en iets nuttigs en waardevols bijdraagt aan de Overleaf-gebruikersgemeenschap, en daarbuiten. Zoals altijd ontvangen we graag feedback, dus voel je vooral vrij om [contact met ons op](https://www.overleaf.com/contact) te reageren met opmerkingen over dit artikel of suggesties voor verdere onderwerpen waarover je ons zou willen laten schrijven.

Fijne $$\text{Lua}\mathrm{\TeX}\text{-ing!}$$ van Graham Douglas en het Overleaf-team.

### En ten slotte... gebruik gewoon het luacode-pakket

Hoewel TeX en Lua op fundamenteel verschillende manieren werken, delen die talen een aantal tekens die binnen de context van elke taal een ‘speciale betekenis’ hebben—zoals \\, %, \~, #, ^, &—natuurlijk geven Lua en TeX die speciale betekenissen voor *zeer* verschillende doeleinden. Onze verkenning van problematische tekens laat zien waarom er moeilijkheden kunnen ontstaan en hoe je die kunt oplossen; het kan echter nogal omslachtig zijn om veel kleine Lua-codefragmenten handmatig te repareren, dus geven de meeste gebruikers de voorkeur aan LaTeX-pakketten die die uitdagingen wegnemen. Een dergelijk pakket is [`luacode`](https://ctan.org/pkg/luacode?lang=en) dat een reeks functies biedt die zijn ontworpen om het werken met `\directlua`, maar je hebt nu in ieder geval wellicht een beter begrip van de problemen `luacode` die het voor je oplost.


---

# 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/nl/diepgaande-artikelen/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.
