How can I get cleveref to compress multiple references to the same section?

Assuming I understand your approach, here is a wrapper for \cref which removes duplicate labels on the basis of the "type" (i.e., the counter to which they refer) and the "label" (i.e., the value of the counter for the label). If multiple labels in a list refer to the same "type" and "label" combination, only the first is retained.

The guts:

The comma separated list is parsed with \forcsvlist from etoolbox. The "type" and "label" for each entry are retrieved using the \cref@gettype and \cref@getlabel from cleveref. A unique global command (comprised of the "type" and "label") is used to indicate if the combination has been used before. If the unique command is not defined or it is equal to \relax, then the unique command is redefined to be equal to the label and the label is appended to \compressed@list which contains the compressed list. If the unique command exists and it is not equal to \relax, the label is skipped and a warning is raised (this may be commented out if you so desire).

The compressed list is then passed to the old version of \cref. Finally, each of the unique commands are reinitialized to \relax with \forcsvlist\@clear@list{\compressed@list} in preparation for subsequent \cref calls. \DeclareRobustCommand was used to retain the native functionality of \cref in headings.

Edit: As pointed out by the OP in the comments below, the original version of this answer did not pass undefined labels through to \cref; this version has been corrected.

\documentclass{book}

\usepackage{cleveref}

%%pre-compress labels to remove duplicates
\usepackage{etoolbox}    

\makeatletter
    %Robust, allowing \cref to be used in headings (may or may not be desired)
    \DeclareRobustCommand\@create@list[1]{%
            \ifcsname r@#1@cref\endcsname%only process if the label is defined
                \cref@gettype{#1}{\@temptype}%cleveref command, set \@temptype to type associated with label (i.e., the counter name)
                \cref@getlabel{#1}{\@templbl}%cleveref command, set \@templbl to the label (i.e., number) associated with the label
                \ifcsname Addval\@temptype\@templbl\endcsname%already defined
                    \expandafter\if\csname  Addval\@temptype\@templbl\endcsname\relax%equal to relax
                        \expandafter\gdef\csname Addval\@temptype\@templbl\endcsname{#1}%save the label
                        \if\compressed@list\relax%
                            \gdef\compressed@list{#1}\else
                            \g@addto@macro\compressed@list{,#1}\fi
                    \else%already defined and not equal to \relax
                        \@latex@warning{Label #1 is a duplicate of \@temptype\space\@templbl}%
                    \fi
                \else%not defined yet
                    \expandafter\gdef\csname Addval\@temptype\@templbl\endcsname{#1}%save the label
                    \if\compressed@list\relax%
                        \gdef\compressed@list{#1}\else
                        \g@addto@macro\compressed@list{,#1}\fi
                \fi
            \else%Added in edit: label not defined...add to the list anyway for "standard" handling
                \if\compressed@list\relax%
                    \gdef\compressed@list{#1}\else
                    \g@addto@macro\compressed@list{,#1}\fi
            \fi}
    %Robust, allowing \cref to be used in headings (may or may not be desired)
    \DeclareRobustCommand\@clear@list[1]{%command to set the addval\@temptype\@templbl commands to relax
        \ifcsname r@#1@cref\endcsname%only process if the label is defined
            \cref@gettype{#1}{\@temptype}%cleveref command, set \@temptype to type associated with label (i.e., the counter name)
            \cref@getlabel{#1}{\@templbl}%cleveref command, set \@templbl to the label (i.e., number) associated with the label
            \expandafter\gdef\csname Addval\@temptype\@templbl\endcsname{\relax}\fi}

    \def\compressed@list{\relax}%initialize
    \let\old@cref=\cref
    \def\cref#1{%Now, cref will compress duplicate labels and provide a warning if found
        \gdef\compressed@list{\relax}%ensure \relax
        \expandafter\forcsvlist\expandafter\@create@list\expandafter{#1}%create compressed list
        \if\relax\compressed@list\relax\else
        \old@cref{\compressed@list}%pass compresed list to cref
        \expandafter\forcsvlist\expandafter\@clear@list\expandafter{\compressed@list}%clear compressed list
        \fi}
\makeatother

\begin{document}

\chapter{This chapter}

\section{A section}

Expressions\label{exp.int}

Definitions\label{def.int}

\section{Another section}

Expressions and definitions occur in 
\cref{exp.int,def.int} on
\cpageref{exp.int,def.int}. 

\end{document}

compressed


I could see no reason not to compress away multiple references to the same label (just as cleveref already did for page references). "Sections 1 and 1" is surely never what's desired.

So I've implemented this in the latest pre-release version (0.21) of cleveref, available from my web site: http://www.dr-qubit.org/latex.html

It should now do what you want.


I doubt that you can with the way the OP is doing it. It seems the intent is to be able to refer to the section and the page number, and to do this some thought and planning on where the labels go will help.

Ideally, you should put your label right after the section or paragraph you want to refer to. So it should look something like this:

\documentclass{book}
\usepackage{cleveref}
\begin{document}

\chapter{This chapter}

\section{A section}
\label{sec:section}

Expressions\label{exp.int}

Definitions\label{def.int}

\section{Another section}

This should take care of labeling both the sections and the relevant paragraphs. Now we need to think about what we are referring to when we write our text

Expressions and definitions occur in \cref{sec:section} on \cpageref{exp.int,def.int}. 

\end{document}

Here we are making specific references to both the section and the paragraphs in the right areas. As the pages are the same for paragraphs, cleveref will compress it.

Hope that helps.

Tags:

Cleveref