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}
ebosi
  • 11,692

2 Answers2

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.

David Carlisle
  • 757,742
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}
egreg
  • 1,121,712