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}
3
  • 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, 2016 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, 2016 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, 2016 at 0:26

2 Answers 2

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.

2
  • The code in chat does compile, you had a misplaced \makeatother.
    – Manuel
    Apr 6, 2016 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, 2016 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.

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

You must log in to answer this question.

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