
私はLaTeXドキュメントで使用するコマンドがどのようにタイプセットされるかを理解しようとしています。明確にするために、ないLaTeX を使用してドキュメントを作成するのではなく、LaTeX の使用に関するドキュメントを LaTeX で記述します (マニュアルなど)。私の知る限り、LaTeX ドキュメントと LaTeX を使用したドキュメントの作成を区別する用語はありません (残念ながら)。
pgfmanual-en-macros.tex の 1099 行目から 1121 行目
https://www.ctan.org/pkg/pgf?lang=en
このコードはアットマークを削除する「ように見えます」が、よく分かりません。なぜこれが必要なのでしょうか? どのように動作するのでしょうか?
{
\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}
}
推論
私がこれを理解したい理由は、次のコードでコマンドをタイプセットできるようだからです。私のアイデアが機能しない場合があるのではないかと思います。
制限事項もあります:
- 説明の下に例として、引数付きのコマンド( )をタイプセットできるように含めます(例: \hello{input1} と入力してから を使用すると
NewEnviron
機能しません)#1
#1
NewEnviron
\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}
興味のある人のための補足: minipage
s の代わりに、パッケージを使用してコマンドを余白に配置しましたmarginnote
。見た目は問題ありません。
\NewEnviron{command}[1]{%
\reversemarginpar\marginnote{\texttt{\string#1}}
\BODY
\par
}%
出力
答え1
質問「なぜそれが必要なのか?」すべてのドキュメントソースを読む必要があります。どのように動作するかは簡単にわかります。
マクロは\getridofats
、入力ストリーム内のその後に続く部分に\relax
カテゴリ コード 12 が含まれているかどうかを判断します@
。
\removeats
しかし、まずは動作を確認した方が良いでしょう。補強された引数; まず最初に\strippedat
空のトークンリストに初期化します。次に
\edef\strippedtext{\stripcommand#1}
これは\strippedtext
コマンド名からバックスラッシュを取り除いた文字列に設定されます。
\expandafter\mygobble\string#1
たとえば、\removeats{\abc@def}
は、\expandafter\mygobble\string\abc@def
最初に\abc@def
カテゴリ 12 文字の文字列に変換され (ただし、@
マクロがコンテキスト内で呼び出される場合は、の後に表示される文字のカテゴリ コードは 11 に\makeatother
なります)、次に\mygobble
バックスラッシュが消費されます。
この準備の後、\expandafter\getridofats\strippedtext @\relax
が呼び出され、入力ストリームに次のトークンが生成されます。
\getridofats abc@def@\relax
の定義を見ると、 は であり、 は である\getridofats
ことがわかります。呼び出しが行われていた場合、入力ストリームには次の内容が含まれます。#1
abc
#2
def@
\removeats{\abcdef}
\getridofats abcdef@\relax
およびは、 は空になり#1
ます。abcdef
#2
マクロは\getridtest
に展開されるように定義されています#2
。最初のケースでは空ではありませんが、2 番目のケースでは空です。
この後、\ifx\getridtest\myempty
2 番目のケースでは true を返し、最初のケースでは false を返します。
テストがtrueを返すと仮定します(2番目のケース)。
\expandafter\def\expandafter\strippedat\expandafter{\strippedat abcdef}
が実行され、の前の値に#1
(この場合は) が追加されます。 は空に初期化されていたため、これは役に立たないように見えるかもしれません。しかし、後で「偽」の場合に何が起こるかを見ていきます。abcdef
\strippedat
\strippedat
テストがfalseを返すと仮定します(最初のケース)。
\expandafter\def\expandafter\strippedat\expandafter{\strippedat abc\protect\printanat}%
\getridofats def@\relax
が完了します。最初の部分が に追加され\strippedat
、その後\protect\printanat
、マクロ\getridofats
が呼び出されて最後のチャンクが処理されます。
私の意見では、特にうまく書かれたマクロではありません。しかし、呼び出し
\removeats\abcdef
\removeats\abc@def
\removeats\ab@cd@ef
\strippedat
それぞれ、
abcdef
abc\protect\printanat def
ab\protect\printanat cd\protect\printanat ef
ここで、は次\printanat
のように定義されます。
\def\printanat{\char`\@}
もちろん\protect
マクロが で定義されている場合は は絶対に必要ありませんが\def\printanat{\char64 }
、それは個人的な選択です。ドキュメントはLaTeXで処理されるため、私はおそらく を選択したでしょう。
\DeclareRobustCommand{\printanat}{\char`\@ }
(末尾のスペースに注意してください。スペースがないのは間違いです)。
@
どうやら、このメカニズムは、ファイル内に文字を書き込むことを回避して.aux
、カテゴリ コード (LaTeX 補助ファイルを読み取るときに 11 に設定される) の問題を回避するために使用されているようです。
expl3
@
カテゴリ コード 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