
Ich versuche zu verstehen, wie Befehle für die Verwendung in LaTeX-Dokumentationen gesetzt werden. Zur Verdeutlichung:nichtLaTeX zum Erstellen von Dokumentation verwenden, anstatt Dokumentation in LaTeX über die Verwendung von LaTeX zu schreiben (wie in den Handbüchern). Soweit mir bekannt ist, gibt es dafür (leider) keinen Begriff, der LaTeX-Dokumentation vom Erstellen von Dokumentation mit LaTeX unterscheidet.
Zeilen 1099-1121 der Datei pgfmanual-en-macros.tex
https://www.ctan.org/pkg/pgf?lang=en
Dieser Code „sieht für mich so aus“, als würde er AT-Zeichen entfernen, aber ich weiß es nicht. Warum ist das notwendig? Wie funktioniert es?
{
\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}
}
Argumentation
Der Grund, warum ich das verstehen möchte, ist, dass ich anscheinend Befehle mit dem folgenden Code setzen kann. Ich vermute, es gibt Fälle, in denen meine Idee nicht funktioniert.
Es gibt auch Einschränkungen:
- Füge Befehle mit Argumenten ein, sodass ich sie (in
NewEnviron
mit#1
) als Beispiel unter der Erklärung setzen kann (z. B. würde \hello{input1} und dann die Verwendung#1
inNewEnviron
nicht funktionieren)
\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}
Randbemerkung für Interessierte: Statt minipage
s habe ich die Befehle auch mit dem Paket in den Rand gesetzt marginnote
. Sieht ganz gut aus.
\NewEnviron{command}[1]{%
\reversemarginpar\marginnote{\texttt{\string#1}}
\BODY
\par
}%
Ausgabe
Antwort1
Die Frage„Warum ist es notwendig?“Dazu müsste man die gesamte Dokumentation lesen. Wie es funktioniert, ist leicht zu erkennen.
Das Makro \getridofats
entscheidet, ob das, was im Eingabestrom bis darauf folgt, \relax
einen Kategoriecode 12 enthält @
.
Es ist jedoch besser, zunächst einmal zu sehen, wie \removeats
es funktioniert. Es sollte einen Befehlsnamen alsverspanntArgument; zunächst wird \strippedat
eine leere Tokenliste initialisiert. Dann
\edef\strippedtext{\stripcommand#1}
Dies setzt \strippedtext
eine Zeichenfolge, die den Befehlsnamen ohne Backslash enthält, da dies nicht der Fall ist.
\expandafter\mygobble\string#1
Beispielsweise \removeats{\abc@def}
wird \expandafter\mygobble\string\abc@def
dies zunächst \abc@def
in eine Zeichenfolge mit Zeichen der Kategorie 12 umgewandelt (aber mit Kategoriecode 11 für Buchstaben, die nach erscheinen @
, wenn das Makro in einem \makeatother
Kontext aufgerufen wird) und dann \mygobble
der Backslash verbraucht.
Nach dieser Vorbereitung \expandafter\getridofats\strippedtext @\relax
wird aufgerufen, was die folgenden Token im Eingabestrom erzeugt:
\getridofats abc@def@\relax
Wenn wir uns die Definition von ansehen \getridofats
, sehen wir, dass #1
ist abc
, während #2
ist def@
. Wenn der Aufruf \removeats{\abcdef}
gesehen worden wäre, würde der Eingabestrom enthalten
\getridofats abcdef@\relax
und #1
wäre abcdef
, während #2
leer wäre.
Das Makro \getridtest
ist so definiert, dass es auf erweitert wird #2
; im ersten Fall ist es nicht leer, im zweiten Fall ist es das.
Danach \ifx\getridtest\myempty
wird im zweiten Fall „true“ und im ersten Fall „false“ zurückgegeben.
Angenommen, der Test gibt true zurück (zweiter Fall). Dann
\expandafter\def\expandafter\strippedat\expandafter{\strippedat abcdef}
ausgeführt, was #1
(in diesem Fall abcdef
) an den vorherigen Wert von anhängt \strippedat
. Dies mag nutzlos erscheinen, da \strippedat
es auf leer initialisiert wurde. Aber wir werden später sehen, was im „falschen“ Fall passiert.
Angenommen, der Test gibt false zurück (erster Fall). Dann
\expandafter\def\expandafter\strippedat\expandafter{\strippedat abc\protect\printanat}%
\getridofats def@\relax
ist erledigt: Das erste Stück wird an angehängt \strippedat
, dann wird \protect\printanat
das Makro \getridofats
erneut aufgerufen, um den letzten Block zu verarbeiten.
Meiner Meinung nach kein besonders gut geschriebenes Makro. Die Aufrufe
\removeats\abcdef
\removeats\abc@def
\removeats\ab@cd@ef
führen \strippedat
zu enthalten, bzw.
abcdef
abc\protect\printanat def
ab\protect\printanat cd\protect\printanat ef
wobei \printanat
definiert ist durch
\def\printanat{\char`\@}
Natürlich \protect
ist es definitiv nicht erforderlich, sofern das Makro mit definiert ist \def\printanat{\char64 }
, aber das ist eine persönliche Entscheidung. Da die Dokumentation mit LaTeX verarbeitet wird, hätte ich mich wahrscheinlich für entschieden
\DeclareRobustCommand{\printanat}{\char`\@ }
(Beachten Sie das Leerzeichen am Ende. Es ist falsch, es nicht zu haben.)
Offenbar dient der Mechanismus dazu, das Schreiben @
von Zeichen in die .aux
Datei zu vermeiden und so Probleme mit ihrem Kategoriencode (der beim Lesen von LaTeX-Hilfsdateien auf 11 gesetzt wird) zu vermeiden.
expl3
Version, die in einem Kontext ausgegeben werden soll, in dem @
der Kategoriecode 12 vorliegt.
\ExplSyntaxOn
\cs_new_protected:Npn \removeats #1
{
\tl_set:Nx \strippedat { \cs_to_str:N #1 }
\tl_replace_all:Nnn \strippedat { @ } { \protect\printanat }
}
\ExplSyntaxOff