16

I think this MWE says it all. \cite can ignore spaces in its argument, while \cref cannot. I wonder if \cref could be improved that way.

\documentclass{article}
\usepackage{cleveref}
\usepackage{filecontents}
\begin{filecontents}{\jobname.bib}
    @misc{1, author="One Author", year=2000}
    @misc{2, author="Another Writer", year=2010}
\end{filecontents}
\begin{document}
    We can use \cite{1,2} AND \cite{1, 2}!

    Yet, we can use \cref{1,2}, but not \cref{1, 2}!

    \section{Section 1}
    \label{1}

    \section{Section 2}
    \label{2}

    \bibliographystyle{apalike}
    \bibliography{\jobname}

\end{document}

Why is this important? Because some text editors, TeXstudio being one of them, have trouble implementing line wraps at commas without a subsequent space.

2
  • Is using LuaLaTeX an option for you?
    – Mico
    Commented Nov 22, 2016 at 20:36
  • Related topic spaces in lists. Commented Nov 22, 2016 at 20:47

3 Answers 3

15

Normalization with removal of spaces before and after label names and removing of empty entries.

The following example uses the comma parser of package kvsetkeys for parsing the label name list of the referencing commands of package cleveref. The internal \@cref with the list in its second argument is redefined for this:

\documentclass{article}
\usepackage{cleveref}
\usepackage{kvsetkeys}

\makeatletter
\let\org@@cref\@cref
\renewcommand*{\@cref}[2]{%
  \begingroup
    \toks@={}%
    \comma@parse{#2}\add@cref@item
  \edef\process@me{\endgroup
    \noexpand\org@@cref{#1}{\the\toks@}%
  }\process@me
}
\newcommand*{\add@cref@item}[1]{%
  \expandafter\ifx\expandafter\\\the\toks@\\%
    \toks@{#1}%
  \else
    \toks@\expandafter{\the\toks@,#1}%
  \fi
}
\makeatother

\begin{document}
    \noindent
    We can use \cref{1,2}, and now  \cref{1, 2},\\
    and even with a leading or trailing comma: \Cref{ , 1 , 2 ,}.

    \section{Section 1}
    \label{1}

    \section{Section 2}
    \label{2}
\end{document}

Result

Removal of open spaces and retaining commas

Solution that zaps all open spaces. If a label contains spaces, the label must be put in curly braces.:

\documentclass{article}
\usepackage{cleveref}
\usepackage{kvsetkeys}

\makeatletter
\let\org@@cref\@cref
\renewcommand*{\@cref}[2]{%
  \edef\process@me{%
    \noexpand\org@@cref{#1}{\zap@space#2 \@empty}%
  }\process@me
}
\makeatother

\begin{document}
    \noindent
    We can use \cref{1,2}, and now  \cref{1, 2}.

    \section{Section 1}
    \label{1}

    \section{Section 2}
    \label{2}
\end{document}

Result

\zap@space is defined in the LaTeX kernel and is used to normalize options list for classes and packages, for example.

3
  • 1
    This answer has one drawback: \cref{1,2,3,,4} (sections 1-3 and 4) shall behave differently from \cref{1,2,3,4} (sections 1-4). This behavior is documented in cleveref, yet lost with this solution.
    – bers
    Commented Nov 22, 2016 at 20:54
  • 1
    @bers See updated answer. Commented Nov 22, 2016 at 21:01
  • Thanks. Your second example does not even need \usepackage{kvsetkeys}.
    – bers
    Commented Nov 25, 2016 at 4:19
8

Almost self-explaining code:

\begin{filecontents}{\jobname.bib}
    @misc{1, author="One Author", year=2000}
    @misc{2, author="Another Writer", year=2010}
\end{filecontents}

\documentclass{article}
\usepackage{xparse}
\usepackage{cleveref}

\ExplSyntaxOn
\cs_set_eq:Nc \bers_cref:nn { @cref }
\cs_generate_variant:Nn \bers_cref:nn { nx }
\cs_set_protected:cpn { @cref } #1 #2
 {
  \seq_set_split:Nnn \l_bers_cref_seq { , } { #2 }
  \bers_cref:nx { #1 } { \seq_use:Nn \l_bers_cref_seq { , } }
 }
\seq_new:N \l_bers_cref_seq
\ExplSyntaxOff

\begin{document}

We can use \cite{1,2} AND \cite{1, 2}!

Yet, we can use \cref{1 space,2}, but also \cref{1 space, 2}!

Also \cref{1 space,2 , 3,, 4}

Also \Cref{1 space, 2, 3 , , 4}

\section{Section 1}
\label{1 space}

\section{Section 2}
\label{2}

\section{Section 3}
\label{3}

\section{Section 4}
\label{4}

\bibliographystyle{apalike}
\bibliography{\jobname}

\end{document}

I redefine the internal command \@cref to first split its second argument at commas, which removes leading and trailing spaces, but preserves inner ones. The original \@cref is saved in \bers_cref:nn, and then \@cref is redefined to use \bers_cref:nx, a variant that fully expands its second argument where we do \seq_use:Nn with a comma between entries.

Note that also \Cref is modified automatically. Empty entries are honored.

enter image description here

4

Here's a LuaLaTeX-based solution. It allows whitespace (spaces, tab characters, line breaks) in the arguments of \cref, \Cref, and \labelcref. Note that the approach pursued in this solution doesn't modify the cleveref macros in any way.

enter image description here

\documentclass{article}
\usepackage{cleveref}

\usepackage{luacode}
\begin{luacode}
function nospace ( t ) -- remove all whitespace characters from string "t"
  return ( t:gsub ( "%s", "" ) )
end
function crefnospace ( s ) 
  return ( s:gsub ( "\\.-[cC]ref%s-%b{}" , nospace ) )
end 
\end{luacode}
\AtBeginDocument{\directlua{luatexbase.add_to_callback ( 
   "process_input_buffer", crefnospace, "crefnospace" )}}

\begin{document}
We may use \cref{a,b}, \Cref{a, b}, \cref{a ,b}, and \Cref{{ a }, b }.
``\labelcref{ b , {a }}'' works too.

\section{Section 1}\label{a}
\section{Section 2}\label{b}
\end{document}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .