Il file clsguide
contiene “LaTeX2e for class and package writers”. È piuttosto corto, 33 pagine, ed è scritto principalmente per spiegare LaTeX2e (anni ’90) a chi arriva dalla versione 2.09 (che sarebbe la prima versione di LaTeX, quella degli anni ’80), quindi mi è stato meno utile del previsto. Comunque qualcosa ho imparato.
- Negli ultimi tempi dopo aver letto il TeXbook ho usato tendenzialmente i comandi di TeX per fare le cose perché sono più sbrigativi di quelli di LaTeX. Tanto cosa cambia?
The simplest way to ensure ‘colour safety’ is to always use LaTeX box commands rather than TeX primitives, that is use
\sbox
rather than\setbox
,\mbox
rather than\hbox
and\parbox
or theminipage
environmentrather
than\vbox
.
Ah ecco cosa cambia. Spiegazione:
As an example of what can go wrong, consider that in
{\ttfamily ⟨text⟩}
the font is restored just before the}
, whereas in the similar looking construction{\color{green} ⟨text⟩}
the colour is restored just after the final}
.
E perché diavolo \color
riimposta il colore dopo la graffa anziché prima, incasinando tutte le circostanze in cui le graffe delimitano qualcosa che viene spostato e quindi il comando di reset del colore rimane lì mentre il comando di set del colore se ne va a giro? Non potevano farlo come i comandi dei font \ttfamily
etc.?
La spiegazione che ipotizzo è: l’impostazione del font è un’operazione primitiva di TeX che in qualche modo \ttfamily
evoca. Quindi vengono assegnati dei valori a delle variabili che TeX legge per decidere che font usare al prossimo carattere. Come tutti gli assegnamenti, se non dichiarati globali vengono annullati alla chiusura del gruppo corrente. Invece i colori TeX non sa cosa siano, quindi avranno dovuto implementarli con dei whatsit (le estensioni/plugin in TeX si chiamano whatsit, non so perché). Quindi ci vorra un whatsit iniziale che imposta il colore, e un whatsit finale che lo annulla quando il gruppo finisce. L’unica funzione di TeX per far succedere qualcosa quando chiudi le graffe è \aftergroup
che però come suggerisce il nome piazza le cose dopo la chiusura.
Visto che i comandi predefiniti di LaTeX hanno un “maglione” in più sugli argomenti, come ho scoperto leggendo il manuale, anche nei comandi tipo \mbox
ci avranno messo questo gruppo in più (che in TeX con le scatole non servirebbe perché le scatole formano gruppi) cosicché \aftergroup
non riesce a sparare i whatsit fuori dalla scatola.
We consider it good practice, when writing packages and classes, to use LaTeX commands as much as possible.
Ok, ok, mi avete convinto.
- Le opzioni delle classi e dei pacchetti di LaTeX sono implementate con una famigliola di macro tra cui
\ProcessOptions
. Negli esempi viene sempre usata così:\ProcessOptions\relax
. Perché\relax
? Perché c’è anche la versione\ProcessOptions*
con l’asterisco. Visto che gli asterischi non sono caratteri validi per costruire una\
-sequenza, tutte le macro con l’asterisco sono implementate con un parser che guarda il carattere successivo e controlla se è un asterisco. Se non fai errori fila tutto liscio. Se fai errori il parser viene evocato nel posto sbagliato al momento sbagliato e mangia qualcosa che non doveva mangiare e gli errori non sono più comprensibili (o meglio, sono ancora più incomprensibili). Nel documento non te la spiegano proprio così, ma non ho ancora trovato nessuna esplicita ammissione di inferno nella documentazione ufficiale. - I comandi
\documentclass
e\usepackage
supportano un argomento opzionale dopo il nome del pacchetto per specificare la data minima richiesta. C’è anche\NeedsTeXFormat
per chiedere una data minima di release di LaTeX. - C’è una classe
minimal
che definisce il minimo necessario ma Enrico Gregorio su tex.stackexchange diceva di non usarla. Boh. - Il comando
\DeclareOption
si mangia il codice da eseguire nel caso una
certa opzione venga specificata dall’utente. In tale codice si può usare il cancelletto#
. COME DIAVOLO È POSSIBILE? Ok, idea: usano un token register. \DeclareRobustCommand
, che già conoscevo, definisce una nuova macro stile\newcommand
ma non fragile. Come funzionerà? Forse mette la macro in un nome interno del tipo\rob@macro
e poi definisce\macro
come\noexpand\rob@macro
. O forse ormai usa\protected
di eTeX? Per fortuna questi importanti quesiti si possono risolvere eseguendolatexdef \DeclareRobustCommand
, che mi porta a eseguirelatexdef \declare@robustcommand
, che sputa fuori:
\declare@robustcommand:
macro:#1->\ifx #1\@undefined \else \ifx #1\relax \else \@latex@info {Redefining \string #1}\fi \fi \edef \reserved@a {\string #1}\def \reserved@b {#1}\edef \reserved@b {\expandafter \strip@prefix \meaning \reserved@b }\edef #1{\ifx \reserved@a \reserved@b \noexpand \x@protect \noexpand #1\fi \noexpand \protect \expandafter \noexpand \csname \expandafter \@gobble \string #1 \endcsname }\let \@ifdefinable \@rc@ifdefinable \expandafter \new@command \csname \expandafter \@gobble \string #1 \endcsname
Uhm… ci sono sicuramente un po’ di cose in più, però il succo è quello. Inoltre non usa un nome interno per salvare la macro, ma la definisce come \protect\macro
, se sto capendo. Ma se tanto poi \new@command
ridefinisce \macro
, come fa a funzionare?? Ma non ha un Cristo di senso!!! Eseguendo latexdef \protect
viene fuori:
\relax
.