
私は、演習パッケージに似たパッケージを自分で作成して、生徒用の問題セットを準備しようとしています。問題や解答の出力を、ドキュメント内の適切な場所に到達するまで遅らせたいと考えています。ある程度機能するものはありますが、少し扱いにくいです。たとえば、これはかなりうまく機能します。
\usepackage{environ}
\NewEnviron{testb}{\global\expandafter\let\csname bar\endcsname\BODY}
\csname
名前は動的に生成されるため、を使用します。 コマンドが 以外の場合、これはあまりうまく機能しません\BODY
。 たとえば、 を使用すると\let\bar{\BODY}
、latex には aneurysm があります ( \bar
{ にのみバインドされます)。
これを行う別の方法は次のとおりです。
\NewEnviron{testc}{\global\expandafter\edef\csname foo\endcsname{\BODY}}
これは、ある程度は機能します。次のものは機能します:
\begin{testc}hi\end{testc}
、しかしこれは LaTeX に動脈瘤を引き起こします: \begin{testc}\bf hi\end{testc}
。(エラー メッセージは です\incomplete
)。私は自分でデバッグしようとしましたが、理解できないパッケージに絶望的に絡まってしまいました。\tiny
の代わりにを使用すると、\bf
まったく異なる LaTeX エラー メッセージが表示されます:! TeX capacity exceeded, sorry [input stack size=5000].
開始から終了までの間にあるものに対して堅牢性を保ちながら、 だけでなく\BODY
、 とその他のものの洗練された組み合わせを後で使用するために保存するにはどうすればよいでしょうか。\BODY
編集: 以下に複数の解決策があります
答え1
を使用すると、\unexpanded
について心配する必要がなくなります\protected@xdef
。
\documentclass{article}
\usepackage{environ}
\NewEnviron{exercise}{%
\xdef\savedexercises{%
\unexpanded\expandafter{\savedexercises}%
\noexpand\begin{printedexercise}%
\unexpanded\expandafter{\BODY}%
\noexpand\end{printedexercise}%
}%
}
\newcommand{\printexercises}{%
\savedexercises
\gdef\savedexercises{}%
}
\newcommand{\savedexercises}{}
\newtheorem{printedexercise}{Exercise}
\begin{document}
Here we talk about addition and show that $1+1=2$.
\begin{exercise}
Compute $1+2$
\end{exercise}
Here we talk about integrals.
\begin{exercise}
Compute the following integrals:
\begin{itemize}
\item $\displaystyle\int_0^x e^{-t^2}\,dt$
\item $\displaystyle\int_1^x \frac{e^t}{t}\,dt$, for $t>0$.
\end{itemize}
\end{exercise}
Now we can print the exercises.
\printexercises
\end{document}
\newtheorem
例としてのみ使用しました。
2019-03-05 以降にリリースされた場合xparse
:
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentEnvironment{exercise}{+b}
{
\tl_gput_right:Nn \g_loisel_exercises_tl
{
\begin{printedexercise}
#1
\end{printedexercise}
}
}{}
\NewDocumentCommand{\printexercises}{}
{
\tl_use:N \g_loisel_exercises_tl
\tl_gclear:N \g_loisel_exercises_tl
}
\tl_new:N \g_loisel_exercises_tl
\ExplSyntaxOff
\newtheorem{printedexercise}{Exercise}
\begin{document}
Here we talk about addition and show that $1+1=2$.
\begin{exercise}
Compute $1+2$
\end{exercise}
Here we talk about integrals.
\begin{exercise}
Compute the following integrals:
\begin{itemize}
\item $\displaystyle\int_0^x e^{-t^2}\,dt$
\item $\displaystyle\int_1^x \frac{e^t}{t}\,dt$, for $t>0$.
\end{itemize}
\end{exercise}
Now we can print the exercises.
\printexercises
\end{document}
答え2
保存して動的に追加したい場合はBODY
、次の 2 つのマクロを使用するのが最適です。
\documentclass{article}
\usepackage{environ}
\NewEnviron{testb}{%
\global\expandafter\let\csname bar\endcsname\BODY
\expandafter\xdef\csname barplus\endcsname{%
\expandafter\noexpand\csname bar\endcsname
\noexpand\bf Hi
}%
}
\begin{document}
\begin{testb}
\bfseries
Hi
\end{testb}
\show\barplus
\end{document}
\BODY
使用を避けたい場合は、xparse
\documentclass{article}
\usepackage{xparse}
\NewDocumentEnvironment{testb}{+b}{\expandafter\gdef\csname bar\endcsname{#1}}{}
\begin{document}
\begin{testb}
\bfseries
Hi
\end{testb}
\show\bar
\end{document}
答え3
拡張をトリガーするためのトリックは、以下を使用することです\romannumeral
。
\romannumeral
(La)TeX が、スペースで終わる数字のシーケンスを変換する必要がある数値としてまとめると、拡張可能なトークンが拡張されます。
最終的に正でない数字が集められると、変換の結果として (La)TeX はトークンをまったく出力しません。
したがって、最終的に正の数が見つからない\romannumeral
ことを保証している限り、多くの拡張作業と引数の反転作業をトリガーするためにうまく(悪用?)使用できます。\romannumeral
これはegregの回答これは、およびの代わりに\romannumeral
およびを使用します。\exchange
\xdef
\unexpanded
\documentclass{article}
\usepackage{environ}
\newcommand\exchange[2]{#2#1}
\NewEnviron{exercise}{%
\expandafter\gdef\expandafter\savedexercises\expandafter{%
\romannumeral0\expandafter\exchange\expandafter{\BODY}{%
\exchange{ }{\expandafter}\savedexercises
\begin{printedexercise}%
}%
\end{printedexercise}%
}%
}
\newcommand{\printexercises}{%
\savedexercises
\gdef\savedexercises{}%
}
\newcommand{\savedexercises}{}
\newtheorem{printedexercise}{Exercise}
\begin{document}
Here we talk about addition and show that $1+1=2$.
\begin{exercise}
Compute $1+2$
\end{exercise}
Here we talk about integrals.
\begin{exercise}
Compute the following integrals:
\begin{itemize}
\item $\displaystyle\int_0^x e^{-t^2}\,dt$
\item $\displaystyle\int_1^x \frac{e^t}{t}\,dt$, for $t>0$.
\end{itemize}
\end{exercise}
Now we can print the exercises.
\printexercises
\end{document}
定義するマクロの名前を\csname
..で囲む場合、つまり ではなく\endcsname
を使用する場合は、(La)TeX が制御シーケンス トークンの名前を収集し、一致する を検索することによって、展開可能なトークンを展開するという事実を利用できます。\csname savedexercises\endcsname
\savedexercises
\csname
\endcsname
\documentclass{article}
\usepackage{environ}
\newcommand\exchange[2]{#2#1}
\NewEnviron{exercise}{%
\expandafter\gdef\csname savedexercises\expandafter\endcsname\expandafter{%
\romannumeral0\expandafter\exchange\expandafter{\BODY}{%
\exchange{ }{\expandafter\expandafter\expandafter}\csname savedexercises\endcsname
\begin{printedexercise}%
}%
\end{printedexercise}%
}%
}
\newcommand{\printexercises}{%
\csname savedexercises\endcsname
\expandafter\gdef\csname savedexercises\endcsname{}%
}
\expandafter\newcommand\expandafter{\csname savedexercises\endcsname}{}
\newtheorem{printedexercise}{Exercise}
\begin{document}
Here we talk about addition and show that $1+1=2$.
\begin{exercise}
Compute $1+2$
\end{exercise}
Here we talk about integrals.
\begin{exercise}
Compute the following integrals:
\begin{itemize}
\item $\displaystyle\int_0^x e^{-t^2}\,dt$
\item $\displaystyle\int_1^x \frac{e^t}{t}\,dt$, for $t>0$.
\end{itemize}
\end{exercise}
Now we can print the exercises.
\printexercises
\end{document}
これまで紹介したアプローチでは、\printexercises
任意の場所で演習を行うことはできないことに注意してください。演習は、ソース内で演習環境の背後にある場所に対応するドキュメントの場所でのみ行うことができます。
おそらく、verbatim-catcode-régime でその内容を読み取り、それを .aux ファイルに展開せずに書き込む環境、そして .aux ファイルから verbatim-catcode-régime で読み戻して、適用されるマクロを定義する環境、そして、 verbatimized の内容に対する-メカニズムまたは - メカニズムの\scantokens
何らかの再実装によって、ドキュメント全体にわたって演習を印刷可能にすることが可能になるかもしれません。\label
\ref
\tableofcontents
このようなメカニズムを実装するのは、なかなかのチャレンジかもしれません。しかし、それを考慮する前に、意図した使用法と望ましい「ユーザー インターフェイス」、つまり、どのような追加事項をどのような方法で指定できるようにしたいかなど、正確な情報が必要です。
答え4
別のバリエーションとして、 を使用するとfilecontentsdef v1.4
、verbatim
コンテンツがサポートされます (必要な場合)。
\documentclass{article}
\usepackage{filecontentsdef,pgffor}
\setlength{\parindent}{0pt}
\pagestyle{empty}
\newtheorem{exercise}{Exercise}
% savedexercise
\newcounter{exeNr}
\newenvironment{savedexercise}
{\stepcounter{exeNr}%
\begingroup
\filecontentsdefmacro{exercise-\the\value{exeNr}}}%
{\endfilecontentsdefmacro\endgroup}
\newcommand{\printexercise}[1]{\filecontentsexec{exercise-\the\numexpr#1\relax}}
\newcommand{\printsrcexercise}[1]{\filecontentsprint{exercise-\the\numexpr#1\relax}}
\begin{document}
\section{Talk about math}
Here we talk about addition and show that $1+1=2$.
\begin{savedexercise}
Compute $1+2$
\end{savedexercise}
Here we talk about integrals.
\begin{savedexercise}
Compute the following integrals:
\begin{itemize}
\item $\displaystyle\int_0^x e^{-t^2}\,dt$
\item $\displaystyle\int_1^x \frac{e^t}{t}\,dt$, for $t>0$.
\end{itemize}
\end{savedexercise}
\section{The exercises}
Now we can print the exercises.
\foreach \i in {1,...,2} {
\begin{exercise}
\printexercise{\i}
\end{exercise}
}
\section{The src exercises}
Now we can print the src of exercises.
\foreach \i in {1,...,2} {
\printsrcexercise{\i}
}
\section{Back to first exercises}
Remember the first exercise
\setcounter{exercise}{0}
\begin{exercise}
\printexercise{1}
\end{exercise}
\end{document}