如何让 cleveref 将不同的定理类型视为一个?

如何让 cleveref 将不同的定理类型视为一个?

介绍

我正在使用一个有点复杂的定理环境设置,也许最终会让我陷入麻烦。我使用和memoir。有一个全局变量是所有定理类环境共享的。此外,所有定理类型都有一个与主定理相关的条目的对应项cleverefntheoremthmcounter案例分析(风格略有不同)。这就是我的问题所在。

问题

我想cleveref说服普通的定义(定理、引理……)和案例分析定义(定理、引理……)其实是一回事。但我不知道如何理解。

其表现方式之一是cleveref交叉引用压缩和排序。可以说“定义 1 和 2”而不是“定义 1 和定义 2”。但只有当它们具有相同的类型时。

最小工作示例

这是 MWE。下面的一些包可能没有涉及,但我认为我会在完整性方面犯错。在我的实际代码中,我有宏来自动化大部分操作,但这不会影响任何事情。

\documentclass{memoir}

\usepackage                       {amsmath}  %| 1 (keep in this order)
\usepackage [ntheorem]            {empheq}   %| 2
\usepackage [amsmath,thmmarks]    {ntheorem} %| 3
\usepackage                       {hyperref} %| 4
\usepackage [capitalize,noabbrev] {cleveref} %| 5

\newtheorem{thmcounter}{}[chapter]

\newtheorem         {Definition}[thmcounter]{Definition}
\newtheorem{CaseStudyDefinition}[thmcounter]{Definition}
\crefname         {Definition}{Definition}{Definitions}
\Crefname         {Definition}{Definition}{Definitions}
\crefname{CaseStudyDefinition}{Definition}{Definitions}
\Crefname{CaseStudyDefinition}{Definition}{Definitions}
% same for Theorem, Lemma, Axiom, etc.

\begin{document}
    \begin{Definition}[A] \label{def:A}  Foo  \end{Definition}

    \begin{Definition}[B] \label{def:B}  Bar  \end{Definition}

    \begin{CaseStudyDefinition}[C] \label{def:C}  FooBar  \end{CaseStudyDefinition}

    Look at \cref{def:A,def:B}!

    Now look at \cref{def:A,def:C}!
\end{document}

在此处输入图片描述

如您所见,它默认情况下不会执行正确的事情,这是可以理解的。

我尝试过的事情

我尝试使用\crefalias{CaseStudyDefinition}{Definition},但似乎没有任何效果。我也尝试使用aliascnt包,但它在计数器上有效,而我只使用了一个计数器。所以没有运气。

cleveref修改\label命令,以便作者可以提供指定不同定理类型的可选参数。奇怪的是……这有效。如果我这样做:

\begin{CaseStudyDefinition}[C] \label[Definition]{def:C}  FooBar  \end{CaseStudyDefinition}

然后第二个句子就像第一个句子一样被压缩。但是该解决方案每次使用时都需要手动修复。我尝试了几种“隐式”提供可选参数的方法。\label例如,我尝试重新定义,但没有成功。我不确定在哪里插入我自己的黑客攻击。

我将非常感激您的帮助。

答案1

实际上\crefalias 應該无法工作。事实上,这是 中的一个错误cleveref。我将在下一个版本中修复它。

答案2

在研究了cleveref代码之后,我想到了一个可行的破解方法。请注意,我宁愿根本不使用破解方法,因此如果有人知道更简洁的解决方案,请告诉我,我会接受您的答案!

黑客攻击

加载后将以下内容放入序言中cleveref

\makeatletter
    \usepackage{etoolbox}
    \def\CrefEnvAlias#1#2{%
        \AtBeginEnvironment{#1}{%
            \def\label@noarg##1{\label@optarg[#2]{##1}}%
        }%
    }
\makeatother

然后,在定义“基本定理类型”之后,调用\CrefEnvAlias即可达到目的:

\newtheorem{Definition}[thmcounter]{Definition}
\crefname  {Definition}{Definition}{Definitions}
\Crefname  {Definition}{Definition}{Definitions}

\newtheorem{CaseStudyDefinition}[thmcounter]{Definition}
\CrefEnvAlias{CaseStudyDefinition}{Definition}

这可以代替任何\crefname现在已是多余的命令。

额外信息

该 hack 重新定义了内部cleveref\label@noarg,它处理 的无可选参数行为\label。它用于etoolbox在我们知道要别名的定理类型的位置插入此新定义,但就在命令\label即将使用之前。

定理类环境的结束会关闭一个组,因此 的原始行为\label随后会自动恢复。我认为最好让\label环境内的所有其他事件都共享 hack。请参阅下面的评论以了解我的动机。

相关内容