3

Aesthetic caveat: I am actually using small-caps with hanging figures and not lining. However, in creating a minimal example, I have succumbed to the defaults and created a typographical monstrosity.


I am trying to create an environment with something like the following syntax:

\begin{<environment name>}{<single letter>}[<options>}
  \item <stuff>
\end{<environment name>}

I want the list to be enumerated and I want each item to be labelled with \textsc{<single letter>}\arabic{<number of item>}.

This is straightforward with enumitem. For example, I can do this:

\NewDocumentEnvironment{letters}{ O {} m }{%
  \begin{enumerate}[label=\textsc{#2}\arabic*., ref=\textsc{#2}\arabic*, #1]
}{%
  \end{enumerate}%
}

and then

\begin{letters}{a}
  \item first
  \item second
\end{letters}

will produce

sample 1

However, when I reference an item, I would like the format of the reference to be \textsc{<letter>}\arabic{<value>} (without a dot). Again, this is fine and the ref in enumitem above takes care of this nicely.

But I would also like to be able to capitalise the letter when the reference occurs at the start of a sentence, for example. Both fancyref and cleveref offer this kind of facility, but the use of small-caps for lower case makes this problematic.

So I started to investigate enumitem and started messing around with the \AddEnumerateCounter(*). As far as I can tell, this command does nothing of the sort. Instead, it seems to add a counter format so it is for adding an analogue to \arabic rather than analogue to c@page, for example. That said, I'm not at all sure I understand it in any way.

I did manage to reproduce my existing result with the following code

\makeatletter
\def\csimplelettered#1{\expandafter\@csimplelettered\csname c@#1\endcsname}
\def\@csimplelettered#1{\@arabic#1}
\makeatother
\AddEnumerateCounter{\csimplelettered}{\@csimplelettered}{2}
\NewDocumentEnvironment{simplelettered}{ O {} m }{%
  \begin{enumerate}[label=\textsc{#2}\csimplelettered*., ref=\textsc{#2}\csimplelettered*, #1]
}{%
  \end{enumerate}%
}

which lets me write

\begin{simplelettered}{b}
  \item first
  \item second
\end{simplelettered}

to produce

second sample

So then I tried to create a new counter format on-the-fly within the environment definition. Here's one (surely laughable) attempt

\makeatletter
\NewDocumentEnvironment{lettered}{ O {} m }{%
  \expandafter\def\csname clettered#2\endcsname ##1{\expandafter\expandafter\expandafter\csname @clettered#2\endcsname\csname c@##1\endcsname}%
  \expandafter\def\csname @clettered#2\endcsname ##1{\@arabic##1}%
  \AddEnumerateCounter*{\expandafter\csname clettered#2\endcsname}{\expandafter\csname @clettered#2\endcsname}{2}%
  \begin{enumerate}[label=\textsc{#2}\arabic*., ref=\textsc{#2}\arabic*, #1]
}{%
  \end{enumerate}%
}
\makeatother

Clearly my default strategy of throwing \expandafters randomly in arbitrary places is not proving especially fruitful in this particular case.

And now I'm more interested in this problem than I am in the original one (which I can solve in another way). How can I make the lettered environment work so that it creates a new counter format and uses it in the enumeration?

Complete NMWE:

\documentclass{article}
\usepackage{xparse,enumitem}
\NewDocumentEnvironment{letters}{ O {} m }{%
  \begin{enumerate}[label=\textsc{#2}\arabic*., ref=\textsc{#2}\arabic*, #1]
}{%
  \end{enumerate}%
}
\makeatletter
\def\csimplelettered#1{\expandafter\@csimplelettered\csname c@#1\endcsname}
\def\@csimplelettered#1{\@arabic#1}
\makeatother
\AddEnumerateCounter{\csimplelettered}{\@csimplelettered}{2}
\NewDocumentEnvironment{simplelettered}{ O {} m }{%
  \begin{enumerate}[label=\textsc{#2}\csimplelettered*., ref=\textsc{#2}\csimplelettered*, #1]
}{%
  \end{enumerate}%
}
\makeatletter
\NewDocumentEnvironment{lettered}{ O {} m }{%
  \expandafter\def\csname clettered#2\endcsname ##1{\expandafter\expandafter\expandafter\csname @clettered#2\endcsname\csname c@##1\endcsname}%
  \expandafter\def\csname @clettered#2\endcsname ##1{\@arabic##1}%
  \AddEnumerateCounter*{\expandafter\csname clettered#2\endcsname}{\expandafter\csname @clettered#2\endcsname}{2}%
  \begin{enumerate}[label=\textsc{#2}\arabic*., ref=\textsc{#2}\arabic*, #1]      
  % want to use something like:
  %\begin{enumerate}[label=\textsc{\csname clettered#2\endcsname*}., ref=\csname clettered#2\endcsname*, #1]
}{%
  \end{enumerate}%
}
\makeatother
\begin{document}
\begin{letters}{a}
  \item first
  \item second
\end{letters}
\begin{simplelettered}{b}
  \item first
  \item second
\end{simplelettered}
\begin{lettered}{c}
  \item first
  \item second
\end{lettered}
\end{document}
  • 2
    May I suggest that a small cap letter followed by a lining number is horrible? Either you use smallcaps +oldstyle numbers or capital letters+lining numbers… – Bernard Apr 5 '16 at 23:57
  • @Bernard I agree. I'm using oldstyle numbers. But that didn't seem relevant to the technical side of the question. – cfr Apr 6 '16 at 0:00
  • 1
    Two things: the \expandafter in \expandafter\csname foo\endcsname does nothing; and you can put \expandafters at the end of csnames, like \csname @clettered#2\expandafter\endcsname\csname c@##1\endcsname. Not necessarily relevant, just information. – Manuel Apr 6 '16 at 0:26
3

I don't understand the question, so don't expect this to answer it. But in any case, if you substitute this

\expandafter\def\csname clettered#2\endcsname ##1{\expandafter\expandafter\expandafter\csname @clettered#2\endcsname\csname c@##1\endcsname}%
\expandafter\def\csname @clettered#2\endcsname ##1{\@arabic##1}%
\AddEnumerateCounter*{\expandafter\csname clettered#2\endcsname}{\expandafter\csname @clettered#2\endcsname}{2}%

with

\def\clettered##1{\expandafter\@clettered\csname c@##1\endcsname}%
\def\@clettered{\@arabic}%
\AddEnumerateCounter*{\clettered}{\@clettered}{2}%

it does compile. Apart from the fact that you don't need to define any variants with \csname..\endcsname since you are inside an environment (if this has nothing to do with the question, ignore it).


In any case, this is your solution with correct use of \expandafters

\expandafter\def\csname clettered#2\endcsname##1{\csname @clettered#2\expandafter\endcsname\csname c@##1\endcsname}%
\expandafter\def\csname @clettered#2\endcsname##1{\@arabic{##1}}%
\expandafter\AddEnumerateCounter\expandafter*\csname clettered#2\expandafter\endcsname\csname @clettered#2\endcsname{2}%

To explain this, you only need one \expandafter before the \endcsname to create a token from the next \csname so

\csname a\expandafter\endcsname\csname b\endcsname

would first create \b and then \a, leaving \a\b.

  • The code in chat does compile, you had a misplaced \makeatother. – Manuel Apr 6 '16 at 1:21
  • Sorry. I screwed up as you pointed out. Yes, both versions work fine. Thank you again. (I probably may still want the second, but the first works here as you say.) – cfr Apr 6 '16 at 1:39
2

I'm not sure I've understood the question, but I think the best approach is to save the label unformatted:

\documentclass{article}

\usepackage{enumitem}

\makeatletter
\newcommand\mylabel[2]{\mylabelfont{#1}\@arabic{#2}}
\makeatother
\let\mylabelfont\textsc % Default
\newcommand\ucref[1]{%
  {\let\mylabelfont\MakeUppercase\ref{#1}}}

\begin{document}

\begin{enumerate}[label=\textsc{a}\arabic*,ref=\protect\mylabel{a}{\arabic*}]
\item \label{1st} First
\item \label{2nd} Second
\end{enumerate}

First is \ref{1st} and second is \ref{2nd}. But compare with \ucref{1st} and \ucref{2nd}.

\end{document}

Here \mylabel just saves the letter and the item number. The format is decided when the label is actually used. This is a general way to delay how the label is formatted when it depends on the context.

  • Thanks. This isn't exactly how I'm doing it but, yes, saving the unformatted label is part of it. – cfr Apr 6 '16 at 12:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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