добавление \chapter в KOMA scrbook приводит к появлению сообщения "! LaTeX Error: \do undefined."

добавление \chapter в KOMA scrbook приводит к появлению сообщения "! LaTeX Error: \do undefined."

Контекст:Этот вопрос является продолжениемОбработка _ (подчеркиваний) в списке аргументов макроса, разделенных запятыми. В этом вопросе я создаю макрос \codecitep, который принимает в качестве аргумента список, разделенный запятыми, и печатает эти ключи, генерируя hyperrefссылки.

Проблема:Мой MWE работает отлично, однако мне не удалось реализовать его в моем реальном документе. Я действительно получаю следующую ошибку:

! LaTeX Error: \do undefined.

Я выяснил причину, которая заключается в... \chapterкоманде: \codecitepкоманды, расположенныедопервые \chapterкомпилируются хорошо, но тепослене.

Решение:(Да, решение появляется раньше вопроса!) Как следует изНевозможно найти ошибку LaTeX, сброс \doопределения после команды, вызвавшей ошибку, позволяет компиляции работать.

Однако добавление \def\do{}после каждой \chapterкоманды — это слишком грязно, и я не думаю, что переопределение/исправление \chapterкоманды KOMA с помощью \def\do{}суффикса as является устойчивым решением.

Вопрос:Что влияет на определение \chapterchange \doи как избежать его влияния на мой собственный \codecitepмакрос?


\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

Пакет tocbasic.sty, используемый scrbookделает

\let\do\relax

как часть \doforeachtocfile, который выполняется \chapter. Это означает, что вы не можете сделать \renewcommand\do{...}, поскольку \doне определено согласно LaTeX.

Действительно, если я уберу \let\do\relaxиз него два внутренних макроса, выполняющих это, проблема исчезнет.

Проблема \renewcommand{\do}{...}возникала и в других ситуациях. Лучше всего, по моему мнению, использовать собственный процессор списков.

\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}

решение2

\doиспользуется во многих низкоуровневых латексных конструкциях, просто просматривая latex.ltxих, можно увидеть

 \global\let\do\noexpand

в\begin{document}

  \let\do\@makeother 

и

\let\do\do@noligs

в verbatimи\verb

\let\do\@makeother

вfilecontents

Я не проследил точно, что именно сбрасывает его в вашем случае использования, но по сути его следует использовать только для локального определения непосредственно перед \doвыполнением разделенного списка.

Связанный контент