Я пытаюсь реализовать пользовательскую версию команды \ref
. Я обнаружил, что для того, чтобы я мог переопределить эту команду, мне нужно сделать это через \AtBeginDocument
as, иначе мои изменения, похоже, будут перезаписаны чем-то другим.
Теперь он работает так, как и ожидалось, за исключением случая использования \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}%
}%
}%
может сделать его более читабельным, поскольку уровни более очевидны.