Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

Introduction

I'm using a somewhat complex theorem-environment setup which, perhaps, is finally getting me into trouble. I use memoir, cleveref and ntheorem. There is a global thmcounter that all theorem-like environments share. In addition, all theorem-types have a counterpart for entries related to the main case study (which have a subtly different style). And therein lies my problem.

Problem

I want to convince cleveref that normal Definitions (Theorems, Lemmas, ...) and case study Definitions (Theorems, Lemmas, ...) are really the same thing. But I don't know how.

One of the ways this manifests itself is cleveref's cross-reference compression and sorting. It can say "Definitions 1 and 2" rather than "Definition 1 and Definition 2". But only when they have the same type.

Minimal Working Example

Here's a MWE. Some of the packages below may not be involved, but I thought I'd err on the side of completeness. In my real code I have macros to automate most of this, but that shouldn't affect anything.

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

enter image description here

As you can see, it doesn't do the right thing by default, which is understandable.

Things I tried

I tried using \crefalias{CaseStudyDefinition}{Definition}, but that seems to do nothing. I also tried using the aliascnt package, but that works on counters, of which I use only one. So no luck.

cleveref modifies the \label command so an author can supply an optional argument specifying a different theorem-type. And strangely... that works. If I do this:

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

then the second sentence is compressed just like the first. But that solution requires a manual fix for every use. I tried several ways of 'implicitly' supplying the optional argument. I tried redefining \label, for instance, but without success. I'm not sure where to insert my own hack.

I'd appreciate some assistance.

share|improve this question

2 Answers 2

up vote 4 down vote accepted

Actually \crefalias ought to work. The fact that it doesn't is a bug in cleveref. I'll fix it in the next release.

share|improve this answer
    
Great. Thanks! :-) –  mhelvens Nov 21 '13 at 19:00

After studying the cleveref code, I came up with a hack that works. Note that I'd rather not use a hack at all, so if anyone knows a cleaner solution, please let me know and I'll accept your answer!

The Hack

Put the following in the preamble after loading cleveref:

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

Then, after defining the 'base theorem type', a call to \CrefEnvAlias will do the trick:

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

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

This can take the place of any \crefname commands, which would now be redundant.

Extra Info

The hack redefines the internal cleveref macro \label@noarg, which handles the no-optional-argument behavior of \label. It uses etoolbox to insert this new definition just at the point where we know the theorem-type we want to alias, but just before the \label command is due to be used.

The end of the theorem-like environment closes a group, so the original behavior of \label is automatically restored afterwards. And I believe it's best that all additional \label occurrences inside the environment share the hack. See my comments below for my motivation.

share|improve this answer
    
You could add \let\label@noarg\CREFlabel@noarg at the end of the inner \def, after having set in advance \let\CREFlabel@noarg\label@noarg, so only the first occurrence of \label would be affected. –  egreg Sep 13 '13 at 22:39
    
Of course, that makes sense. Though after thinking about it, I'm not so sure we really need (or want) only the first occurrence to be affected. The only reason for additional \labels inside a thm-like environment I can think of would be to label something like an enumerate item. And they don't seem to be affected by the hack. Any package that wants to do something like "Definition 2.1.a" will either be unaffected by the hack, or actually benefit from it still being in place. –  mhelvens Sep 13 '13 at 22:55
    
Ah, in fact, I remember that I sometimes merge two definitions into one. When I do, I give it both original \labels —at least temporarily— so I don't break any references. All in all, I think it's better that the hack is in effect throughout the environment. --- Though as a direct solution to the problem I stated at the end, you were correct, of course. –  mhelvens Sep 13 '13 at 23:05

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.