pgfmanual-en-macros.tex の 1099 行目から 1121 行目

pgfmanual-en-macros.tex の 1099 行目から 1121 行目

私は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#1NewEnviron

\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}

興味のある人のための補足: minipages の代わりに、パッケージを使用してコマンドを余白に配置しました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ことがわかります。呼び出しが行われていた場合、入力ストリームには次の内容が含まれます。#1abc#2def@\removeats{\abcdef}

\getridofats abcdef@\relax

およびは、 は空になり#1ます。abcdef#2

マクロは\getridtestに展開されるように定義されています#2。最初のケースでは空ではありませんが、2 番目のケースでは空です。

この後、\ifx\getridtest\myempty2 番目のケースでは 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

関連情報