
Estoy tratando de entender cómo se componen los comandos para su uso en la documentación de LaTeX. Para aclarar,nousar LaTeX para crear documentación, en lugar de escribir documentación en LaTeX sobre el uso de LaTeX (como en los manuales). Hasta donde yo sé, no existe ningún término para distinguir la documentación de LaTeX de la creación de documentación con LaTeX (desafortunadamente).
Líneas 1099-1121 del pgfmanual-en-macros.tex
https://www.ctan.org/pkg/pgf?lang=en
Este código "parece" que me elimina las señales, pero no lo sé. ¿Por qué es esto necesario? ¿Como funciona?
{
\makeatletter
\global\let\myempty=\@empty
\global\let\mygobble=\@gobble
\catcode`\@=12
\gdef\getridofats#1@#2\relax{%
\def\getridtest{#2}%
\ifx\getridtest\myempty%
\expandafter\def\expandafter\strippedat\expandafter{\strippedat#1}
\else%
\expandafter\def\expandafter\strippedat\expandafter{\strippedat#1\protect\printanat}
\getridofats#2\relax%
\fi%
}
\gdef\removeats#1{%
\let\strippedat\myempty%
\edef\strippedtext{\stripcommand#1}%
\expandafter\getridofats\strippedtext @\relax%
}
\gdef\stripcommand#1{\expandafter\mygobble\string#1}
}
Razonamiento
La razón por la que me gustaría entender esto es porque parece que puedo escribir comandos con el siguiente código. Sospecho que hay casos en los que mi idea no funcionará.
También existen limitaciones:
- incluir comandos con argumentos de modo que pueda escribirlos (con
NewEnviron
)#1
como ejemplo bajo la explicación (por ejemplo, \hello{input1} y luego usarlos#1
enNewEnviron
no funcionaría)
\documentclass{article}
\usepackage{fontspec}
\usepackage{environ}
\NewEnviron{command}[1]{%
\begin{minipage}[t]{.3\textwidth}
\texttt{\string#1}
\end{minipage}
\hfill
\begin{minipage}[t]{.7\textwidth}
\BODY
\end{minipage}
\xdef\putcommandexample{\BODY}% Set BODY to variable http://tex.stackexchange.com/a/14392/13552
}%
\begin{document}
\section{Friendly Commands}
\begin{command}{\hello}
This command greets the reader in a friendly manner.
\end{command}
\begin{command}{\goodbye}
This command greets the reader in a friendly manner.
\end{command}
\end{document}
Nota al margen para cualquiera interesado: en lugar de minipage
s, también pongo los comandos en el margen usando el marginnote
paquete. Se ve bien.
\NewEnviron{command}[1]{%
\reversemarginpar\marginnote{\texttt{\string#1}}
\BODY
\par
}%
Producción
Respuesta1
La pregunta"¿Por qué es necesario?"Requeriría leer toda la fuente de documentación. Cómo funciona es fácil de ver.
La macro \getridofats
decide si lo que le sigue en el flujo de entrada hasta \relax
contiene un código de categoría 12 @
.
Sin embargo, es mejor ver cómo \removeats
funciona para empezar. Debería recibir un nombre de comando como suapuntaladoargumento; En primer lugar, se inicializa \strippedat
en una lista de tokens vacía. entonces lo hace
\edef\strippedtext{\stripcommand#1}
que se establece \strippedtext
en una cadena que contiene el nombre del comando sin la barra invertida, porque no
\expandafter\mygobble\string#1
Por ejemplo, \removeats{\abc@def}
eso \expandafter\mygobble\string\abc@def
primero se transforma \abc@def
en una cadena de categoría 12 caracteres (pero código de categoría 11 para las letras que aparecen después de @
, si la macro se llama en un \makeatother
contexto) y luego \mygobble
se come la barra invertida.
Después de esta preparación, \expandafter\getridofats\strippedtext @\relax
se llama, lo que produce los siguientes tokens en el flujo de entrada:
\getridofats abc@def@\relax
Mirando la definición de \getridofats
, vemos que #1
es abc
, mientras que #2
es def@
. Si \removeats{\abcdef}
se hubiera visto la llamada, el flujo de entrada contendría
\getridofats abcdef@\relax
y #1
sería abcdef
, mientras #2
estaría vacío.
La macro \getridtest
está definida para expandirse a #2
; en el primer caso no está vacío, en el segundo caso sí.
Después de esto, \ifx\getridtest\myempty
devuelve verdadero en el segundo caso y falso en el primero.
Supongamos que la prueba es verdadera (segundo caso). Entonces
\expandafter\def\expandafter\strippedat\expandafter{\strippedat abcdef}
se realiza, que se suma #1
(en este caso abcdef
) al valor anterior de \strippedat
. Podría parecer inútil porque \strippedat
se había inicializado para que estuviera vacío. Pero veremos más adelante qué sucede en el caso “falso”.
Supongamos que la prueba arroja falso (primer caso). Entonces
\expandafter\def\expandafter\strippedat\expandafter{\strippedat abc\protect\printanat}%
\getridofats def@\relax
Está hecho: se agrega la primera parte y \strippedat
luego se vuelve a llamar \protect\printanat
a la macro \getridofats
para procesar el fragmento final.
En mi opinión, no es una macro particularmente bien escrita. Sin embargo, las llamadas
\removeats\abcdef
\removeats\abc@def
\removeats\ab@cd@ef
resultan en \strippedat
contener, respectivamente,
abcdef
abc\protect\printanat def
ab\protect\printanat cd\protect\printanat ef
donde \printanat
está definido por
\def\printanat{\char`\@}
Por supuesto, \protect
definitivamente no es necesario siempre que la macro esté definida con \def\printanat{\char64 }
, pero es una elección personal. Como la documentación se procesa con LaTeX, probablemente habría optado por
\DeclareRobustCommand{\printanat}{\char`\@ }
(tenga en cuenta el espacio final, está mal no tenerlo).
Aparentemente el mecanismo se utiliza para evitar escribir @
caracteres en el .aux
archivo y así evitar problemas con su código de categoría (que se establece en 11 al leer archivos auxiliares de LaTeX).
expl3
versión, que se emitirá en un contexto donde @
tenga el código de categoría 12.
\ExplSyntaxOn
\cs_new_protected:Npn \removeats #1
{
\tl_set:Nx \strippedat { \cs_to_str:N #1 }
\tl_replace_all:Nnn \strippedat { @ } { \protect\printanat }
}
\ExplSyntaxOff