Benutzerdefinierte Definition von \ref verursacht Probleme im Argument von \caption

Benutzerdefinierte Definition von \ref verursacht Probleme im Argument von \caption

Ich versuche, eine benutzerdefinierte Version des \refBefehls zu implementieren. Ich habe herausgefunden, dass ich diesen Befehl über neu definieren muss, \AtBeginDocumentda meine Änderung sonst anscheinend durch etwas anderes überschrieben wird.

Es funktioniert jetzt wie erwartet, außer bei der Verwendung \refinnerhalb eines \caption, wodurch der folgende Fehler auftritt:

Argument of \@caption has an extra }. \caption{Test here \ref{sec:Section}}
Paragraph ended before \@caption was complete. \caption{Test here \ref{sec:Section}}

Hier ist ein MWE, das das Problem reproduziert:

\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}

Wenn ich meine benutzerdefinierte Implementierung entferne, \refwird das Dokument einwandfrei kompiliert.

Was verursacht dieses Problem und wie kann ich es vermeiden?

Antwort1

Ihre (Neu-)Definition von \refmacht es zu einem sogenannten „fragilen“ Befehl. Dies ist wichtig, wenn \refes im Argument eines „beweglichen Befehls“ verwendet wird – wie etwa \caption. Sie müssen ändern

\caption{Test here \ref{sec:Section}}

Zu

\caption{Test here \protect\ref{sec:Section}}

Darüber hinaus müssen Sie sicherstellen, dass vor oder nach dem Querverweisaufruf keine unerwünschten Leerzeichen eingefügt werden. Ich schlage vor, Sie ändern

    \renewcommand{\ref}[1]{%
        \IfBeginWith{#1}{eq:}{
            (\refCopy{#1})
        }{
        \refCopy{#1}
    }
}

Zu

    \renewcommand{\ref}[1]{%
        \IfBeginWith{#1}{eq:}{%
            (\refCopy{#1})%
        }{%
        \refCopy{#1}%
    }%
}%

Können Sie die sechs neuen Fälle von entdecken %?


Nachtrag: Wie @AlanMunn in einem Kommentar angemerkt hat, \protectwerden die Anweisungen nicht benötigt, wenn das etoolboxPaket geladen und \renewcommand{\ref}...durch ersetzt wird \renewrobustcmd{\ref}....

Formatieren des Codes als

\renewcommand{\ref}[1]{%
  \IfBeginWith{#1}{eq:}{%
    (\refCopy{#1})%
  }{%
    \refCopy{#1}%
  }%
}%

kann die Lesbarkeit verbessern, da die Ebenen deutlicher erkennbar sind.

verwandte Informationen