2

I try to produce a document containing an exam and the associated correction. I want automatic hyperlinks from the question to the associated answer and vice-versa.

Using the solution given by Gonzalo Medina to the question Automatic labeling of enumeration items, I am able to label automatically the different item, and using setlist I can produce the necessary hyperlinks.

However, I need my questions to be label qu:1 or q:2.a ant the associated answers to be labeled rep:1 or rep:2.a

Gonzalo Medina's solution is to use something like that :

\makeatletter
\apptocmd{\@item}{
  \ifnum\@enumdepth=1\relax
   \label{qu:\arabic{enumi}}
  \else 
  \ifnum\@enumdepth=2\relax
    \label{qu:\arabic{enumi}.\alph{enumii}}
 \fi\fi}{}{}
\makeatother

It works fine, but apptocmd definitely changes the definition of \@item. Unfortunately, when writing the solutions to the question, I will need to redefine \@item so that the solutions will be label with rep and not qu.

Something that seems to work but does not really satifies me is the following MWE :

\documentclass{book}
\usepackage{enumitem}
\usepackage{etoolbox}
\usepackage[colorlinks]{hyperref}

\setlist[enumerate,1]{label=\hyperref[rep:\arabic{enumi}]{\arabic*.}}
\setlist[enumerate,2]{label=\hyperref[rep:\arabic{enumi}.\alph{enumii}]{\arabic{enumi}.\alph*.},ref=\alph*}


\begin{document}

Questions : 

\begin{enumerate}
\makeatletter
\apptocmd{\@item}{
  \ifnum\@enumdepth=1\relax
    \label{qu:\arabic{enumi}}
  \else 
  \ifnum\@enumdepth=2\relax
    \label{qu:\arabic{enumi}.\alph{enumii}}
\fi\fi}{}{}
\makeatother 
\item A question
\begin{enumerate}
\item A subquestion
\item Another subquestion
\end{enumerate}
\item An other question
\end{enumerate}
\newpage
Solutions : 

\setlist[enumerate,1]{label=\hyperref[qu:\arabic{enumi}]{\arabic*.}}
\setlist[enumerate,2]{label=\hyperref[qu:\arabic{enumi}.\alph{enumii}]{\arabic{enumi}.\alph*.},ref=\alph*}

\begin{enumerate}
\makeatletter
\apptocmd{\@item}{
  \ifnum\@enumdepth=1\relax
    \label{rep:\arabic{enumi}}
  \else 
  \ifnum\@enumdepth=2\relax
    \label{rep:\arabic{enumi}.\alph{enumii}}
\fi\fi}{}{}
\makeatother 

\item An answer
\begin{enumerate}
\item A sub-answer
\item Another sub-answer
\end{enumerate}
\item Another answer
\end{enumerate}

\end{document}

The main inconvenient is that a the begin of the questions and the beginning of the answers, I need to manually redefine the effect of \item (and use \setlist).

I'd like to create two different environment, named subject and solutions (moreover, this seems compatible with the local effect of apptocmd).

So I tried the following :

\documentclass{book}
\usepackage{enumitem}
\usepackage{etoolbox}
\usepackage[colorlinks]{hyperref}

\newenvironment{subject}{
  \setlist[enumerate,1]{label=\hyperref[rep:\arabic{enumi}]{\arabic*.}}
  \setlist[enumerate,2]{label=\hyperref[rep:\arabic{enumi}.\alph{enumii}]{\arabic{enumi}.\alph*.},ref=\alph*}
  \makeatletter
  \apptocmd{\@item}{
    \ifnum\@enumdepth=1\relax
      \label{qu:\arabic{enumi}}
    \else 
    \ifnum\@enumdepth=2\relax
      \label{qu:\arabic{enumi}.\alph{enumii}}
  \fi\fi}{}{}
  \makeatother
}{}

\newenvironment{solution}{
  \setlist[enumerate,1]{label=\hyperref[qu:\arabic{enumi}]{\arabic*.}}
  \setlist[enumerate,2]{label=\hyperref[qu:\arabic{enumi}.\alph{enumii}]{\arabic{enumi}.\alph*.},ref=\alph*}
  \makeatletter
  \apptocmd{\@item}{
    \ifnum\@enumdepth=1\relax
      \label{rep:\arabic{enumi}}
    \else 
    \ifnum\@enumdepth=2\relax
      \label{rep:\arabic{enumi}.\alph{enumii}}
  \fi\fi}{}{}
  \makeatother
}{}

\begin{document}

Questions : 
\begin{subject}
\begin{enumerate}
\item A question
\begin{enumerate}
\item A subquestion
\item Another subquestion
\end{enumerate}
\item An other question
\end{enumerate}
\end{subject}

\newpage
Solutions : 

\begin{solution}
\begin{enumerate}    
\item An answer
\begin{enumerate}
\item A sub-answer
\item Another sub-answer
\end{enumerate}
\item Another answer
\end{enumerate}
\end{solution}
\end{document}

However, this is not working at all : the labels are not created at all, and it automatically prints itemitem at each use of one of the two newly created environments. Why having \apptocmd inside \newenvironment is a problem ? (and is that THE problem ?).

  • 1
    \makeatletter...\makeatother outside of the environments ;-) – user31729 Jul 7 '15 at 16:06
  • 2
    @MathieuVienney \makeatletter must precede code that mentions commands with @ in their name, not be inside code that uses them. SInce your \newenvironment definition mentions \@item, \makeatletter must be before \newenvironment. See tex.stackexchange.com/questions/8351/… – egreg Jul 7 '15 at 16:17
  • By the way, why my (non) solution was printing itemitem at each call of the environment subject ? – mvienney Jul 7 '15 at 17:02
4

I do not know many cases (in fact none) where \makeatletter...\makeatother inside of macro is useful. In this case, it would prevent the correct expansion of the \@item etc. macros, and \apptocmd is applied to \item etc.

\documentclass{book}
\usepackage{enumitem}
\usepackage{etoolbox}
\usepackage[colorlinks]{hyperref}

\makeatletter

\newenvironment{subject}{%
  \setlist[enumerate,1]{label=\hyperref[rep:\arabic{enumi}]{\arabic*.}}
  \setlist[enumerate,2]{label=\hyperref[rep:\arabic{enumi}.\alph{enumii}]{\arabic{enumi}.\alph*.},ref=\alph*}
  \apptocmd{\@item}{%
    \ifnum\@enumdepth=1\relax
      \label{qu:\arabic{enumi}}
    \else 
    \ifnum\@enumdepth=2\relax
      \label{qu:\arabic{enumi}.\alph{enumii}}
  \fi\fi}{}{}
}{}

\newenvironment{solution}{%
  \setlist[enumerate,1]{label=\hyperref[qu:\arabic{enumi}]{\arabic*.}}
  \setlist[enumerate,2]{label=\hyperref[qu:\arabic{enumi}.\alph{enumii}]{\arabic{enumi}.\alph*.},ref=\alph*}
  \apptocmd{\@item}{%
    \ifnum\@enumdepth=1\relax
      \label{rep:\arabic{enumi}}
    \else 
    \ifnum\@enumdepth=2\relax
      \label{rep:\arabic{enumi}.\alph{enumii}}
  \fi\fi}{}{}
}{}

\makeatother


\begin{document}

Questions : 
\begin{subject}
\begin{enumerate}
\item A question
\begin{enumerate}
\item A subquestion
\item Another subquestion
\end{enumerate}
\item An other question
\end{enumerate}
\end{subject}

\newpage
Solutions : 

\begin{solution}
\begin{enumerate}    
\item An answer
\begin{enumerate}
\item A sub-answer
\item Another sub-answer
\end{enumerate}
\item Another answer
\end{enumerate}
\end{solution}
\end{document}
  • Thanks a lot, I definitely need to read more about \makeatletter ... \makeatother to avoid these mistakes. Anyway, I learned something thanks to you ! – mvienney Jul 7 '15 at 16:14
  • @MathieuVienney: You're welcome ;-) – user31729 Jul 7 '15 at 16:16

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.