KOMA scrbook に \chapter を追加すると、「! LaTeX エラー: \do undefined」が生成されます。

KOMA scrbook に \chapter を追加すると、「! LaTeX エラー: \do undefined」が生成されます。

コンテクスト:この質問は、マクロのカンマ区切りの引数リスト内の _ (アンダースコア) の処理\codecitepこの質問では、コンマ区切りのリストを引数として受け取り、リンクを生成するこれらのキーを出力するマクロを作成しますhyperref

問題:私の MWE はうまく動作しますが、実際のドキュメントに実装することはできませんでした。実際に次のエラーが発生します。

! LaTeX Error: \do undefined.

原因を突き止めました。それは...コマンドです\chapter\codecitep前に最初のものは\chapterうまくコンパイルされますが、しないでください。

解決:(そう、質問の前に解決策が来ます!)LaTeXエラーが見つかりません\doエラーの原因となったコマンドの後に定義をリセットすると、コンパイルが機能するようになります。

ただし、\def\do{}各コマンドの後に追加するのは非常に面倒であり、KOMA のコマンドをサフィックスで\chapter再定義/パッチすることは持続可能な解決策ではないと思います。\chapter\def\do{}

質問:\chapter定義の変更の原因は何ですか\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。つまり、 はLaTeX によれば未定義な\renewcommand\do{...}ので、は実行できません。\do

実際、\let\do\relaxそれを実行している 2 つの内部マクロを削除すると、問題は解消されます。

この\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

\dolatex.ltx多くの低レベルのLaTeX構造で使用されていますが、そこを見るだけで

 \global\let\do\noexpand

\begin{document}

  \let\do\@makeother 

そして

\let\do\do@noligs

verbatim\verb

\let\do\@makeother

filecontents

\doあなたのユースケースで何がリセットされるのか正確には追跡していませんが、基本的には、分離されたリストが実行される直前のローカル定義にのみ使用する必要があります。

関連情報