
Estou tentando entender como os comandos são compostos para uso na documentação do LaTeX. Esclarecer,nãousar LaTeX para criar documentação, em vez de escrever documentação em LaTeX sobre o uso do LaTeX (como nos manuais). Até onde eu sei, não existe nenhum termo para distinguir a documentação do LaTeX da criação de documentação com o LaTeX (infelizmente).
Linhas 1099-1121 do pgfmanual-en-macros.tex
https://www.ctan.org/pkg/pgf?lang=en
Este código "parece" que remove sinais de arroba para mim, mas não sei. Por que isso é necessário? 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}
}
Raciocínio
A razão pela qual eu gostaria de entender isso é porque parece que consigo digitar comandos com o código a seguir. Suspeito que há casos em que a minha ideia não funcionará.
Também existem limitações:
- incluir comandos com argumentos de modo que eu possa digitá-los (em
NewEnviron
with#1
) como exemplo na explicação (por exemplo, \hello{input1} e depois usar#1
noNewEnviron
não funcionaria)
\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 lateral para quem estiver interessado: Em vez de minipage
s também coloquei os comandos na margem usando o marginnote
pacote. Parece tudo bem.
\NewEnviron{command}[1]{%
\reversemarginpar\marginnote{\texttt{\string#1}}
\BODY
\par
}%
Saída
Responder1
A questão“por que é necessário?”exigiria a leitura de toda a fonte de documentação. Como funciona é fácil de ver.
A macro \getridofats
decide se o que vem a seguir no fluxo de entrada \relax
contém um código de categoria 12 @
.
No entanto, é melhor ver como \removeats
funciona para começar. Deve receber um nome de comando como seupreparadoargumento; primeiro de tudo, ele inicializa \strippedat
com uma lista de tokens vazia. Então acontece
\edef\strippedtext{\stripcommand#1}
que define \strippedtext
uma string contendo o nome do comando com a barra invertida removida, porque isso faz
\expandafter\mygobble\string#1
Por exemplo, \removeats{\abc@def}
isso \expandafter\mygobble\string\abc@def
primeiro se transforma \abc@def
em uma sequência de caracteres da categoria 12 (mas o código de categoria 11 para letras que aparecem depois de @
, se a macro for chamada em um \makeatother
contexto) e depois \mygobble
consome a barra invertida.
Após esta preparação, \expandafter\getridofats\strippedtext @\relax
é chamado, que produz os seguintes tokens no fluxo de entrada:
\getridofats abc@def@\relax
Olhando para a definição de \getridofats
, vemos que #1
é abc
, enquanto #2
é def@
. Se a chamada \removeats{\abcdef}
tivesse sido vista, o fluxo de entrada conteria
\getridofats abcdef@\relax
e #1
seria abcdef
, enquanto #2
estaria vazio.
A macro \getridtest
está definida para expandir para #2
; no primeiro caso não está vazio, no segundo caso está.
Depois disso, \ifx\getridtest\myempty
retorna verdadeiro no segundo caso, falso no primeiro caso.
Suponha que o teste retorne verdadeiro (segundo caso). Então
\expandafter\def\expandafter\strippedat\expandafter{\strippedat abcdef}
é executado, que anexa #1
(neste caso abcdef
) ao valor anterior de \strippedat
. Pode parecer inútil, porque \strippedat
foi inicializado vazio. Mas veremos mais tarde o que acontece no caso “falso”.
Suponha que o teste retorne falso (primeiro caso). Então
\expandafter\def\expandafter\strippedat\expandafter{\strippedat abc\protect\printanat}%
\getridofats def@\relax
está pronto: a primeira parte é anexada \strippedat
e \protect\printanat
a macro \getridofats
é chamada de volta para processar a parte final.
Não é uma macro particularmente bem escrita, na minha opinião. No entanto, as chamadas
\removeats\abcdef
\removeats\abc@def
\removeats\ab@cd@ef
resultar em \strippedat
conter, respectivamente,
abcdef
abc\protect\printanat def
ab\protect\printanat cd\protect\printanat ef
onde \printanat
é definido por
\def\printanat{\char`\@}
É claro \protect
que definitivamente não é necessário, desde que a macro seja definida com \def\printanat{\char64 }
, mas isso é uma escolha pessoal. Como a documentação é processada com LaTeX, provavelmente eu teria optado por
\DeclareRobustCommand{\printanat}{\char`\@ }
(observe o espaço à direita, é errado não tê-lo).
Aparentemente o mecanismo é utilizado para evitar a escrita @
de caracteres no .aux
arquivo evitando problemas com seu código de categoria (que é definido como 11 na leitura de arquivos auxiliares LaTeX).
expl3
versão, a ser emitida em contexto onde @
possua código de categoria 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