補助ファイルでグローバルコマンドを定義する

補助ファイルでグローバルコマンドを定義する

私は長い文書を書いていますが、作業を簡単にするために、使用する量をマクロとして定義して、変更があったときに 1 か所で更新するだけで済むようにしています。私にとっては、作業を進めるにつれて、最も関連のある文書のセクションでこれらを定義するのが理にかなっています。ただし、これらのコマンドを他の章で使用したい場合や、場合によっては前の章で使用したい場合もあります。

.auxそこで、コマンドの定義を LaTeXファイルに吐き出すマクロを追加して、一度定義したコマンドをどこでも使えるようにしたいと思います。今のところ、次のようになっています。

% Make a command which defines a macro with \providecommand but in the aux file,
% so it's accessible to all other chapters
\makeatletter
\newcommand{\doccommand}[2]{%
\protected@write\@auxout{}{\protect\providecommand\protect#1{#2}}%
}
\makeatother

これにより、次の内容がauxファイルに書き込まれます。

\providecommand \tester {123}

このような章の場合:

\chapter{Test chapter}

This is a test chapter!

Tester is \tester{}.

\doccommand{\tester}{123}

残念ながら、動作しません。テスト チャプター内でコマンドを使用しても、「未定義の制御シーケンス」が表示され、他のチャプターでも同様です。

当初、これはファイル内にあるスペースと関係があるのではないかと考えましたが.aux、手動でスペースを削除し、 でコンパイルしましたが、\includeonly{a_different_chapter}それでも同じエラーが発生します。

何が起こったのですか?

アップデート:

ここでの皆さんの助けのおかげで、私はこれを動作させ、小さなパッケージに書き込むことができました。興味があれば、CTANで見つけることができます。https://ctan.org/pkg/globalvals

答え1

私は別の戦略を使用します。マクロを直接定義するのではなく、ラッパー コマンドを使用します。

\documentclass{article}

\makeatletter
\newcommand{\usevalue}[1]{%
  \ifcsname usevalue@#1\endcsname
    \csname usevalue@#1\endcsname
  \else
    ??%
  \fi
}
\newcommand{\definevalue}[2]{%
  \write\@auxout{%
    \unexpanded{\global\@namedef{usevalue@#1}{#2}}%
  }
}
\makeatother

\begin{document}

Something with \usevalue{tester}.

Something else.

Now we can define \texttt{tester} and use again it: \usevalue{tester}.

\definevalue{tester}{42}

\end{document}

最初の実行の出力

ここに画像の説明を入力してください

2回目の実行の出力

ここに画像の説明を入力してください

答え2

次のように書くこともできる

\makeatletter
\newcommand{\doccommand}[2]{%
  \immediate\write\@auxout{\gdef\noexpand#1{\unexpanded{#2}}}%
  \gdef#1{#2}%
}
\makeatother

これにより、置換テキストを展開せずにグローバル定義が実行されます。TeX を\gdef再実行せずにコマンドを使用できるように、追加の direct を追加しました。

しかし、これは良い考えではありません。コマンドが定義されているポイントより前にコマンドを使用しない場合、aux ファイルでコマンドを定義しても意味がありません。コマンドを定義する前に使用すると、LaTeX は aux ファイルのエントリを書き込むポイントに到達しません。

したがって、コマンドは、定義済みだが使用されていない状態で TeX を 1 回実行した後にのみ使用できます。aux ファイルを削除すると、ドキュメントが壊れます。別の章のみを含めると、aux ファイルのエントリは書き込まれないため、ドキュメントが壊れます。

代わりに、プリアンブルに含める定義を含む別のファイルを作成することもできます。作業は増えますが、より安定したドキュメントが得られます。

答え3

賢いアプローチをしてくれた @egreg に感謝します。彼のコードを少し変更して、同じドキュメントに 2 つの定義がある場合にエラー メッセージを追加しました。

\documentclass{article}    

\usepackage{siunitx}

\makeatletter
\newcommand{\useVal}[1]{%
  \ifcsname useVal@#1\endcsname
    \csname useVal@#1\endcsname
  \else
    ??%
  \fi
}
\newcommand{\defVal}[2]{%
\ifcsname useVal@#1@defined\endcsname
    \PackageError{useVal}{Value "#1" already defined}{}
\else
  \write\@auxout{%
    \unexpanded{\global\@namedef{useVal@#1}{#2}}%
  }
  \global\@namedef{useVal@#1@defined}{}
\fi
}
\makeatother

\begin{document}

Testval is \useVal{testVal}.

Now defining testval...

\defVal{testVal}{\SI{123}{\meter}}

Now it's \useVal{testVal}. 

% This would throw an error:
% \defVal{testVal}{Not this please!}

\end{document}

関連情報