
Контекст:Этот вопрос является продолжениемОбработка _ (подчеркиваний) в списке аргументов макроса, разделенных запятыми. В этом вопросе я создаю макрос \codecitep
, который принимает в качестве аргумента список, разделенный запятыми, и печатает эти ключи, генерируя hyperref
ссылки.
Проблема:Мой MWE работает отлично, однако мне не удалось реализовать его в моем реальном документе. Я действительно получаю следующую ошибку:
! LaTeX Error: \do undefined.
Я выяснил причину, которая заключается в... \chapter
команде:
\codecitep
команды, расположенныедопервые \chapter
компилируются хорошо, но тепослене.
Решение:(Да, решение появляется раньше вопроса!) Как следует изНевозможно найти ошибку LaTeX, сброс \do
определения после команды, вызвавшей ошибку, позволяет компиляции работать.
Однако добавление \def\do{}
после каждой \chapter
команды — это слишком грязно, и я не думаю, что переопределение/исправление \chapter
команды KOMA с помощью \def\do{}
суффикса as является устойчивым решением.
Вопрос:Что влияет на определение \chapter
change \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
выполнением разделенного списка.