为什么 cleveref 的 \crefname 命令出现在 \foreach 中时不起作用?

为什么 cleveref 的 \crefname 命令出现在 \foreach 中时不起作用?

这个问题源于这个,这是我几周前问的。后来我发现了 cleveref 包,我想用它来方便地引用类似定理的环境,而不必记住给定的语句是定理、引理还是命题等。

这是一个小示例文档。当我编译此文档时,文本的最后一行以“以下是一些对 ?? 1.1、?? 1.2 和定理 1.3 的引用”开头。尝试使用\crefname为不同环境设置引用名称(我不熟悉术语)不起作用。但是,如果% (*)取消注释标有 的行,第二个“??”将变为“toybox”。所以这与 中有关\foreach。但我找不到让它工作的方法。就好像 中的调用\crefname被完全忽略了\foreach。为什么会发生这种情况?

\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]
\foreach \x/\y in \myTheoremEnvironments {
    \edef\tmp{\noexpand\newtheorem{\x}[baseTheorem]{\noexpand\titlecap{\x}}}\tmp
    \crefname{\x}{\x}{\y}
}

%\crefname{toybox}{toybox}{toyboxes} % (*)

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

答案1

最大的问题是\foreach每个循环都在一个组内进行;虽然\newtheorem定义是全局的,但\crefname定义不是。

我建议采用一个可能更加用户友好的界面。

\documentclass[a4paper]{amsart}

\usepackage{titlecaps, cleveref}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\foreachpair}{smm}
 {
  \IfBooleanTF{#1}
   {
    \hammerite_foreachpair:on { #2 } { #3 }
   }
   {
    \hammerite_foreachpair:nn { #2 } { #3 }
   }
 }

\cs_new_protected:Npn \hammerite_foreachpair:nn #1 #2
 {
  \cs_set:Npn \__hammerite_temp:nn ##1 ##2 { #2 }
  \clist_map_inline:nn { #1 } { \__hammerite_dopair:n { ##1 } }
 }
\cs_new:Npn \__hammerite_dopair:n #1
 {
  \__hammerite_dopair:wn #1 \q_stop
 }
\cs_new:Npn \__hammerite_dopair:wn #1/#2 \q_stop
 {
  \__hammerite_temp:nn { #1 } { #2 }
 }
\cs_generate_variant:Nn \hammerite_foreachpair:nn { o }
\ExplSyntaxOff

% 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]

\foreachpair
 {
  theorem/theorems,
  cobblestone/cobblestones,
  toybox/toyboxes,
 }
 {
  \newtheorem{#1}[baseTheorem]{\titlecap{#1}}
  \crefname{#1}{#1}{#2}
 }

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

如您所见,的第二个参数\foreachpair是一个以逗号分隔的形式的项目列表<item-a>/<item-b>;第二个参数就像一个命令定义,在每个循环中<item-a>替换#1<item-b>替换#2

还有另一种调用方式

\newcommand\myTheoremEnvironments{
  theorem/theorems,
  cobblestone/cobblestones,
  toybox/toyboxes
}

\foreachpair* \myTheoremEnvironments
 {
  \newtheorem{#1}[baseTheorem]{\titlecap{#1}}
  \crefname{#1}{#1}{#2}
 }

在此处输入图片描述

答案2

\foreach每次迭代都进行一组,而且\crefname不扩展其第二个参数。

可以使用\xintForpairfrom 包来规避这些问题新工具

\documentclass[a4paper]{amsart}


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

% Does not work: 
% \def\myTheoremEnvironments{%
%     theorem/theorems,%
%     cobblestone/cobblestones,%
%     toybox/toyboxes%
% }
% \foreach \x/\y in \myTheoremEnvironments {
%     \edef\tmp{\noexpand\newtheorem{\x}[baseTheorem]{\noexpand\titlecap{\x}}}\tmp
%     \crefname{\x}{\x}{\y}
% }

% alternative using \xintForpair:

\usepackage{xinttools}% http://ctan.org/pkg/xint

\xintForpair #1#2 in 
{% spaces around commas or like the end of lines here, 
 % or around parentheses are removed automatically
   (theorem,theorems),
   (cobblestone,cobblestones),
   (toybox,toyboxes)
}
\do
{%  (spaces significant but do not matter)
    \newtheorem{#1}[baseTheorem]{\titlecap{#1}}
    \crefname{#1}{#1}{#2}
}

\begin{document}\thispagestyle{empty}

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

带有 crefname 的循环

答案3

[Y]你可以使用内部.list使用的处理程序,但是\foreach

  • 不对其内容进行分组[…]并且
  • 可以与已经扩展的内容一起使用#1(而不是作为宏序列)。

使用

\pgfkeys{/utils/my Foreach/.code args={#1/#2}{\newtheorem{#1}[baseTheorem]{\titlecap{#1}}%
                                              \crefname{#1}{#1}{#2}},
         /utils/my Foreach/.list/.expand once=\myTheoremEnvironments}

给出

在此处输入图片描述

相关内容