我正在尝试实现命令的自定义版本\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}%
}%
}%
您能发现这六个新的实例%
吗?
附录:正如@AlanMunn 在评论中指出的那样,如果加载包并用 替换,则不需要\protect
这些指令。etoolbox
\renewcommand{\ref}...
\renewrobustcmd{\ref}...
将代码格式化为
\renewcommand{\ref}[1]{%
\IfBeginWith{#1}{eq:}{%
(\refCopy{#1})%
}{%
\refCopy{#1}%
}%
}%
可能会使其更具可读性,因为级别更加明显。