Cleveref - Conditional label formats

I am trying to define a new reference style with cleveref:

\crefname{prop}{property}{properties}
\creflabelformat{prop}{#2#1.\@#3}


This is meant to be used in a list of numbered properties in an enumerate environment. Labels should render as "property 1.", and "properties 1. to 4." for a range.

It works as intended, but I want to deal with cases where a certain punctuation mark (in normal text) follows the \cref command. For example, \cref{my:label}, should render as "property 1," and not as "property 1.,".

I tried to use @ifnextchar in the label definition but (I guess due to how cleveref parses the command) the token following \cref is not the one that gets fed into @ifnextchar.

Is it possible to define a label format conditioned by which character follows the \cref command?

EDIT: Added MWE (slightly different example)

\documentclass{article}
\usepackage{cleveref}

\makeatletter
\crefname{prop}{property}{properties}
\creflabelformat{prop}{#2#1#3\@ifnextchar.{}{.\@}}
\makeatother

\begin{document}
\begin{enumerate}
\item \label[prop]{my:firstlabel}
First property of the list

\item \label[prop]{my:secondlabel}
Second property of the list
\end{enumerate}

We will discuss the implications of \cref{my:firstlabel} and we will
\end{document}


The intended result would be "We will discuss the implications of property 1. and we will follow with property 2.", but the last period is actually printed twice (\@ifnextchar is not triggered).

I get the same behavior if I modify the standard enumi label format instead of specifying a new one, or if I use another environment (e.g. equation)

• Welcome to TeX SX! I think this is more of a configuration problem of the  enumerate environment. Could you post a minimal compilable code? – Bernard Jul 23 '19 at 12:41
• Thanks! I added a MWE, I hope it's clearer. – Andrea Olivo Jul 23 '19 at 13:11

With that code, \@ifnextchar will never see a period. If I change the definition to

\creflabelformat{prop}{#2#1#3\@ifnextchar.{}{\show\@let@token.\@}}


TeX will show in both cases

> \@let@token=\fi.
\reserved@c ->\show \@let@token
.\@


When the replacement text deriving from \creflabelformat is used, LaTeX is in the middle of a long processing. However you're lucky! Everything is performed in a single group, so we can solve the problem with \aftergroup that pushes a token to be executed when the current group ends.

In order to avoid \@ifnextchar gobbling spaces, a lower level technique has to be used.

\documentclass{article}
\usepackage{cleveref}

\makeatletter
\crefname{prop}{property}{properties}
\creflabelformat{prop}{#2#1#3\aftergroup\possible@period}
\makeatother

\begin{document}

\begin{enumerate}
\item \label[prop]{my:firstlabel}
First property of the list

\item \label[prop]{my:secondlabel}
Second property of the list
\end{enumerate}

We will discuss the implications of \cref{my:firstlabel}
and we will follow with \cref{my:secondlabel}. Some text.

\end{document}


It's shorter with expl3, but the technique is the same.

\documentclass{article}
\usepackage{cleveref,expl3}

\crefname{prop}{property}{properties}

\ExplSyntaxOn
\cs_new_protected:Npn \olivo_period:w
{
\peek_charcode:NF { . } { .\@ }
}
\creflabelformat{prop}{#2#1#3\group_insert_after:N \olivo_period:w}
\ExplSyntaxOff

\begin{document}

\begin{enumerate}
\item \label[prop]{my:firstlabel}
First property of the list

\item \label[prop]{my:secondlabel}
Second property of the list
\end{enumerate}

We will discuss the implications of \cref{my:firstlabel}
and we will follow with \cref{my:secondlabel}. Some text.

\end{document}

• Thanks! the first solution works perfectly, and I can even chain more \ifx for catching multiple punctuation symbols. – Andrea Olivo Jul 25 '19 at 10:40
• unfortunately it breaks with ranges and multiple references. \cref{my:firstlabel,my:secondlabel}. is rendered as property 1 and 2.. instead of properties 1. and 2. (and analogously for ranges). I can fix the range behavior overriding it with \crefrangelabelformat but it seems there is no equivalent \crefmultilabelformat. – Andrea Olivo Jul 25 '19 at 13:40
• @AndreaOlivo That was something I feared. As I said, the command \cref does many things after processing the replacement text in \creflabelformat, so when the \@ifnextchar will happen to be evaluated is quite unpredictable. – egreg Jul 25 '19 at 13:44
• It's OK, I'm starting to think that my style is not even typographically clear. I'll use a combination of normal refs and manual punctuation. Thank you for your time! – Andrea Olivo Jul 25 '19 at 13:49
• @AndreaOlivo Actually I hate those styles such as “1)”, “a)” or “1.” I know they're used, but can't stand them: a period means period and an closed parenthesis requires an open one. – egreg Jul 25 '19 at 14:02

Here is a solution with enumitem, which defines the ref=... key. I added the possibility to define a new list type, based on enumerate, which you can completely customise:

\documentclass{article}
\usepackage{cleveref}
\usepackage{enumitem}

\crefname{prop}{property}{properties}
\newlist{Prop}{enumerate}{1}
\setlist[Prop]{label=\arabic*., ref=\arabic*}
\crefname{Prop}{property}{properties}

\begin{document}

\begin{enumerate}[ref=\arabic*]
\item \label[prop]{my:firstlabel}
First property of the list

\item \label[prop]{my:secondlabel}
Second property of the list
\end{enumerate}

We will discuss the implications of \cref{my:firstlabel} and we will

\begin{Prop}[start=3]
\item \label[Prop]{My:firstlabel}
First property of this list

\item \label[Prop]{My:secondlabel}
Second property of this list
\end{Prop}
We will now discuss the implications of \cref{My:firstlabel} and we will