コマンドのカスタム バージョンを実装しようとしています\ref
。このコマンドを再定義するには、 を介して行う必要があることがわかりました。\AtBeginDocument
そうしないと、変更が他の何かによって上書きされてしまうようです。
\ref
内部で使用する場合以外は期待どおりに動作しますが、内部で使用すると\caption
次のエラーが発生します。
Argument of \@caption has an extra }. \caption{Test here \ref{sec:Section}}
Paragraph ended before \@caption was complete. \caption{Test here \ref{sec:Section}}
問題を再現する MWE は次のとおりです。
\documentclass{article}
\usepackage{xstring}
\AtBeginDocument{%
\let\refCopy\ref
\renewcommand{\ref}[1]{%
\IfBeginWith{#1}{eq:}{
(\refCopy{#1})
}{
\refCopy{#1}
}
}
}
\setcounter{errorcontextlines}{999}
\begin{document}
\section{Section}
\label{sec:Section}
\begin{figure}
\caption{Test here \ref{sec:Section}}
\end{figure}
\end{document}
\ref
ドキュメント のカスタム実装を削除すると、正常にコンパイルされます。
この問題の原因は何ですか? また、どうすれば回避できますか?
答え1
の(再)定義により、\ref
これはいわゆる「脆弱な」コマンドになります。これは、\ref
が「移動コマンド」の引数で使用される場合に問題になります。たとえば、 です\caption
。変更する必要があります。
\caption{Test here \ref{sec:Section}}
に
\caption{Test here \protect\ref{sec:Section}}
さらに、相互参照の呼び出しの前後に不要な空白が挿入されないようにする必要があります。変更することをお勧めします。
\renewcommand{\ref}[1]{%
\IfBeginWith{#1}{eq:}{
(\refCopy{#1})
}{
\refCopy{#1}
}
}
に
\renewcommand{\ref}[1]{%
\IfBeginWith{#1}{eq:}{%
(\refCopy{#1})%
}{%
\refCopy{#1}%
}%
}%
の新しい 6 つのインスタンスを見つけることができますか%
?
補遺: @AlanMunn がコメントで指摘したように、パッケージをロードして に置き換える\protect
場合、ディレクティブは必要ありません。etoolbox
\renewcommand{\ref}...
\renewrobustcmd{\ref}...
コードのフォーマット
\renewcommand{\ref}[1]{%
\IfBeginWith{#1}{eq:}{%
(\refCopy{#1})%
}{%
\refCopy{#1}%
}%
}%
レベルがより明確になるため、読みやすくなる可能性があります。