3

I am trying to build functionality similar to the exercise package, but exercise does not quite do what I want.

MWE:

\documentclass[10pt]{article}

\newwrite\myfile
\immediate\openout\myfile=\jobname.keys

\newcommand{\answerkey}[1]{\write\myfile{#1}}

\begin{document}

\begin{enumerate}
\item $1 + 1 = $ \answerkey{ XXXX 2}
\begin{enumerate}
\item $1 + 2 = $ \answerkey{ XXXX 3}
\begin{enumerate}
\item $1 + 3 = $ \answerkey{ XXXX 4}
\end{enumerate}
\end{enumerate}
\end{enumerate}

\end{document}

What I want is something to replace the XXXX so that what gets written to the file is something along the lines of:

1. 2
1.a. 3
1.a.i 4

I need an automated way to access the current label for an enumerant when I don't know how many levels deep I am, and don't want to type a unique label/tag for each one by hand (if someone has a nice way to automate the label/tag generation, that could work).

Suggestions appreciated.

1
  • In the best possible answer, the code identified as XXXX actually exists only in the \answerkey code at the beginning so that throughout the document, it simply says "\answerkey{2}" or "\answerkey{3}", etc. A still workable runner-up answer would have the same code for the XXXX in each of the instances in my example. (I don't know enough latex to understand if this is a meaningful difference). Commented May 11, 2016 at 1:47

2 Answers 2

1

Note you need \immediate\write and just write the current label

\documentclass[10pt]{article}

\newwrite\myfile
\immediate\openout\myfile=\jobname.keys

\makeatletter
\newcommand{\answerkey}[1]{\immediate\write\myfile{\@currentlabel #1}}
\makeatother

\begin{document}

\begin{enumerate}
\item $1 + 1 = $ \answerkey{ XXXX 2}
\begin{enumerate}
\item $1 + 2 = $ \answerkey{ XXXX 3}
\begin{enumerate}
\item $1 + 3 = $ \answerkey{ XXXX 4}
\end{enumerate}
\end{enumerate}
\end{enumerate}

\end{document}

produces

1 XXXX 2
1a XXXX 3
1(a)i XXXX 4

1(a)i is the same format \ref would use if you \label any of those items, so you can customise both in the same way.

0
3

EDITED to actually give an answer.

As I explained to Christopher in the comments, the counter for the first level of enumeration is enumi, for the second is enumii, for the third is enumiii in a roman numeral fashion. If the level is not yet invoked, the counter value is 0. Once invoked, it gets stepped to 1 and higher with each new \item. Thus, the \ifnum check is determining if each successive level is active or not. If it is active, it appends \theenum<romannumeral-level>. to \tmplabel, since \theenum<romannumeral-level> contains the actual enumeration label, regardless of whether it is arabic, alphabetic, or roman. If a level is active, it also recursively checks to see if the next deeper level is active.

\documentclass[10pt]{article}

\newwrite\myfile
\immediate\openout\myfile=\jobname.keys

\newcommand{\answerkey}[1]{\answerlabel\immediate\write\myfile{\tmplabel #1}}
\newcounter{enumlevel}
\newcommand\answerlabel{\setcounter{enumlevel}{0}\xdef\tmplabel{}\answerlabelhelp%
  \xdef\tmplabel{\tmplabel\space}}
\newcommand\answerlabelhelp{%
  \stepcounter{enumlevel}%
  \ifnum\value{enum\romannumeral\value{enumlevel}}>0\relax
    \xdef\tmplabel{\tmplabel\csname theenum\romannumeral\value{enumlevel}\endcsname.}%
      \answerlabelhelp%
  \fi
}
\begin{document}
\begin{enumerate}
\item $1 + 1 = $ \answerkey{2}
\begin{enumerate}
\item $1 + 2 = $ \answerkey{3}
\begin{enumerate}
\item $1 + 3 = $ \answerkey{4}
\end{enumerate}
\end{enumerate}
\end{enumerate}
\end{document}

The .keys file reads

1. 2
1.a. 3
1.a.i. 4

as requested.

9
  • The problem with this solution is that it requires me to both know how the enumerant is formatted (see your use of \alpha and \roman), and it requires me to know how deep I am in the enumerants (see your use of enumi, enumii, and enumiii). Both of these seem redundant and LATEX should both know at the point of \answerkey how deep I am, and how the enumerant is being formatted. Thanks for the thoughts, though. Commented May 11, 2016 at 1:41
  • @ChristopherDonham I believe I have provided a working answer. Commented May 11, 2016 at 2:28
  • This looks really close. Looking at it, I don't understand "\ifnum\value{enum\romannumeral\value{enumlevel}}>0\relax" Is this detecting whether or not roman numerals are being used, or is it baking the format into the solution? Thank you very much for your help with this. Commented May 11, 2016 at 2:37
  • @ChristopherDonham No. the counter for the first level of enumeration is enumi, for the second is enumii, for the third is enumiii in a roman numeral fashion. If the level is not yet invoked, the counter value is 0. Once invoked, it gets stepped to 1 and more with each new \item. Thus, the \ifnum check is determining if each successive level is active or not. Commented May 11, 2016 at 2:39
  • 1
    I don't think you want \refstepcounter{enumlevel} just \stepcounter or you will remove the ability to label/ref any of these items. Commented May 11, 2016 at 7:01

You must log in to answer this question.

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