在这个问题我已经得到了一个复杂的方法来实现我所设定的目标。这个问题不是“我该怎么做”的问题——我已经有答案了——而是“请解释一下我尝试的方法有什么缺陷”的问题。
最初的问题是\crefname
cleveref 包提供的宏在 中没有任何效果\foreach
。jfbu(在答案中)和 egreg(在评论中)指出,问题在于\crefname
仅在本地产生影响,并且更改在每次循环迭代结束时都会被丢弃。在 egreg 发布提供解决方案的答案之前,我想到使用 来\foreach
构建一个命令来执行\crefname
更改,然后在循环结束后调用该命令。我使用\global
宏使更改成为全局的。不幸的是,\global
导致出现错误消息,我不知道为什么。这是我的尝试:
\documentclass[a4paper]{amsart}
\def\myTheoremEnvironments{%
theorem/theorems,%
cobblestone/cobblestones,%
toybox/toyboxes%
}
\usepackage{tikz, titlecaps, cleveref}
% Number all definition, theorem, etc. environments using the same counter.
% Start counting again at the start of each section.
% Style these environments using LaTeX's "definition" style.
\theoremstyle{definition}
\newtheorem{baseTheorem}{Base Theorem}[section]
\def\mycrefnamecommands{}
\foreach \x/\y in \myTheoremEnvironments {
\edef\tmp{\noexpand\newtheorem{\x}[baseTheorem]{\noexpand\titlecap{\x}}}\tmp
\global\edef\mycrefnamecommands{\mycrefnamecommands\noexpand\crefname{\x}{\x}{\y}}
}
\mycrefnamecommands
\begin{document}
\section{Hello, and welcome to my document.}
\begin{cobblestone}
\label{csref}
Hello. I am an ``cobblestone'' environment.
\end{cobblestone}
\begin{toybox}
\label{tbref}
I am a ``toybox'' environment. What a strange name that is for an environment.
\end{toybox}
\begin{theorem}
\label{thmref}
People trying to do strange things with ``foreach'' should expect trouble.
\end{theorem}
Here are some references to \cref{csref}, \cref{tbref} and \cref{thmref}.
I could have tried using just one call to ``cref'' here,
but it's best not to run before you can walk.
\end{document}
这是错误消息。我尝试用谷歌搜索,但没有看到任何特别有用的结果。
! Argument of \@ynthm has an extra }.
<inserted text>
\par
l.66 }
答案1
你必须记住\edef
,一路,但\noexpand
只抑制一次扩展。因此,在第一次循环之后,的替换文本\mycrefnamecommands
为
\crefname{theorem}{theorem}{theorems}
而在第二个周期\edef
就会试图扩张\crefname
,从而引发灾难。
你必须小心,只扩大一次 \mycrefnamecommands
在各个步骤中。这可以通过两种方式完成:
\toks0=\expandafter{\mycrefnamecommands}%
\xdef\mycrefnamecommands{\the\toks0 \noexpand\crefname{\x}{\x}{\y}%
\the\toks0
利用由 产生的标记列表不会进一步扩展这一事实\edef
(\xdef
与 相同\global\edef
)。
另一种利用 e-TeX 扩展(在 LaTeX 中可用)的方法是
\xdef\mycrefnamecommands{%
\unexpanded\expandafter{\mycrefnamecommands}%
\noexpand\crefname{\x}{\x}{\y}%
}%
其功能与上面的基本相同,但仅需一步。
另一种策略可能是
\def\mycrefnamecommands{}
\foreach \x/\y in \myTheoremEnvironments {
\let\crefname\relax
\edef\tmp{\noexpand\newtheorem{\x}[baseTheorem]{\noexpand\titlecap{\x}}}\tmp
\xdef\mycrefnamecommands{\mycrefnamecommands\crefname{\x}{\x}{\y}}
}
\mycrefnamecommands
在\foreach
循环中我们将其设置\crefname
为等于\relax
,因此它变得不可扩展,因此它不会以任何方式被解释\xdef
;然而,在的末尾\foreach
,\crefname
将恢复其原来的含义,因此在执行最终宏时\mycrefnamecommands
它将定期完成其工作。