5

Context: This question is a follow-up of Handling _ (underscores) in a macro's comma-separated list of arguments. In this question I create the macro \codecitep that takes a comma-separated list as argument, and prints these keys generating hyperref links.

Problem: My MWE works great, however, I did not succeed in implementing it in my real document. I indeed get the following error:

! LaTeX Error: \do undefined.

I have tracked down the cause, which is... the \chapter command: \codecitep commands positioned before the first \chapter compile well, but those after don't.

Solution: (Yep, the solution comes before the question!) As suggesting in Cannot find LaTeX Error, reseting \do definition after the error-causing command makes compilation work.

However, adding \def\do{} after each \chapter command is way to dirty, and I don't think redefining/patching KOMA's \chapter command with \def\do{} as suffix is a sustainable solution.

Question: What makes \chapter change \do's definition, and how to avoid it impacts my own \codecitep macro?


\documentclass{scrbook}
    \usepackage{etoolbox}
    \usepackage{hyperref}
    \usepackage{lipsum}

    \newcommand{\codecitep}[1]{% cf. https://tex.stackexchange.com/a/87423/64454
        [%
        \def\nextitem{\def\nextitem{, }}% Separator
        \renewcommand*{\do}[1]{\nextitem{\hyperref[code:##1]{##1}}}% How to process each item
        \docsvlist{#1}% Process list
        ]%
    }   
\begin{document}

    \section{Body before chapter}
        A sentence with one code-citation only \codecitep{key1}.
        Another sentence with two code-citations and followed by dummy text \codecitep{key1, key2}.

\chapter{Chapter title}
%\def\do{}% <----- uncomment to make the error disappear
    \section{Body after chapter}
        A sentence with one code-citation only \codecitep{key1}.
        Another sentence with two code-citations and followed by dummy text \codecitep{key1, key2}.
        \lipsum[1-2]

    \section{Appendix}
        \lipsum[3]

        \subsection{key1}
        \label{code:key1}
        \label{code:a_123}
        \lipsum[4]

        \subsection{key2}
        \label{code:key2}
        \label{code:bb_456}
        \lipsum[5]
\end{document}
  • 1
    Use \def\do in your command. – Ulrike Fischer Apr 30 '17 at 6:40
4

The package tocbasic.sty used by scrbook does

\let\do\relax

as part of \doforeachtocfile, which is executed by \chapter. This means you cannot do \renewcommand\do{...}, because \do is undefined according to LaTeX.

Indeed, if I remove \let\do\relax from the two internal macros doing it, the problem disappears.

The \renewcommand{\do}{...} issue has appeared in other situations. The best, in my opinion, is to use your own list processor.

\documentclass{scrbook}

\usepackage{etoolbox}
\usepackage{hyperref}
\usepackage{lipsum}

\newcommand{\codecitep}[1]{% cf. https://tex.stackexchange.com/a/87423/64454
  [%
  \def\nextitem{\def\nextitem{, }}% Separator
  \forcsvlist\codecitepitem{#1}% Process list
  ]%
}
\newcommand{\codecitepitem}[1]{%
  \nextitem
  \hyperref[code:#1]{\detokenize{#1}}%
}

\begin{document}

\section{Body before chapter}

A sentence with one code-citation only \codecitep{key1}.
Another sentence with two code-citations and followed by 
dummy text \codecitep{key1, key2}.

\chapter{Chapter title}

\section{Body after chapter}

A sentence with one code-citation only \codecitep{key1}.
Another sentence with two code-citations and followed by 
dummy text \codecitep{key1, key2}.
\lipsum[1-2]

\section{Appendix}

\lipsum[3]

\subsection{key1}

\label{code:key1}
\label{code:a_123}
\lipsum[4]

\subsection{key2}
\label{code:key2}
\label{code:bb_456}
\lipsum[5]

\end{document}
  • Is there any advantage of doing this vs. using \def instead of \renewcommand (apart from avoiding TeX constructs)? – Alan Munn Apr 30 '17 at 13:20
  • @AlanMunn It's much cleaner, besides avoiding the issue. ;-) – egreg Apr 30 '17 at 13:38
4

\do is used in many low level latex constructs, just looking through latex.ltx there is

 \global\let\do\noexpand

in \begin{document}

  \let\do\@makeother 

and

\let\do\do@noligs

in verbatim and \verb

\let\do\@makeother

in filecontents

I didn't trace exactly what is resetting it in your use case but basically it should only ever be used for a local definition immediately before the \do separated list is executed.

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.