\apptocmd en condicional: ¿por qué no funciona?

\apptocmd en condicional: ¿por qué no funciona?

¿Por qué el siguiente MWE no funciona mientras que si comento el condicional funciona?

\documentclass{beamer}

\makeatletter

\@ifclassloaded{beamer}{

\usepackage{bookmark}
\usepackage{etoolbox}

\apptocmd{\beamer@@frametitle}{\only<1>{\bookmark[page=\the\c@page,level=3]{#1}}}%
{\message{** patching of \string\beamer@@frametitle succeeded **}}%
{\message{** patching of \string\beamer@@frametitle failed **}}%

}{}

\makeatother


\begin{document}

\begin{frame}{Title}
Hello \pause world
\end{frame}
\end{document}

Respuesta1

respuesta principal

En general, parchear comandos cuando #está involucrado no puede ocurrir en el argumento de otro comando. Se pueden hacer algunos trucos con códigos de categoría, pero otro enfoque puede ser más sencillo:

\documentclass{beamer}

\makeatletter
\@ifclassloaded{beamer}{\@tempswatrue}{\@tempswafalse}
\if@tempswa
  \usepackage{bookmark}
  \usepackage{etoolbox}
  \apptocmd{\beamer@@frametitle}
    {\only<1>{\bookmark[page=\the\c@page,level=3]{#1}}}%
    {\message{** patching of \noexpand\beamer@@frametitle succeeded **}}%
    {\message{** patching of \noexpand\beamer@@frametitle failed **}}%
\fi
\makeatother


\begin{document}

\begin{frame}{Title}
Hello \pause world
\end{frame}
\end{document}

El \if@tempswacondicional es un condicional temporal proporcionado por el kernel.

Esto es lo que está escrito en el .logarchivo:

** patching of \beamer@@frametitle succeeded **

Respuesta generalizada

Un enfoque similar sin usar \@tempsway que puede usarse para otros pseudocondicionales de LaTeX como \@ifpackageloadedo \@ifundefined:

\makeatletter
\newcommand{\latex@conditional}[1]{#1{11}{01}}

\if\latex@conditional{\@ifclassloaded{beamer}}
  \usepackage{bookmark}
  \usepackage{etoolbox}
  \apptocmd{\beamer@@frametitle}
    {\only<1>{\bookmark[page=\the\c@page,level=3]{#1}}}%
    {\message{** patching of \noexpand\beamer@@frametitle succeeded **}}%
    {\message{** patching of \noexpand\beamer@@frametitle failed **}}%
%\else
% code for the false branch
\fi
\makeatother

Esto se basa en el hecho de que \iflos tokens se expanden y que los pseudocondicionales de LaTeX son completamente expandibles; así que al final \ifencuentra 11si la condición es verdadera, de 01lo contrario sigue las ramas verdadera y falsa en consecuencia. Tenga en cuenta que dichas construcciones se pueden anidar en otros condicionales de estilo TeX. También se puede especificar el código para la rama falsa.

Método alternativo

Alternativamente, use el regexpatchpaquete:

\documentclass{beamer}

\makeatletter
\@ifclassloaded{beamer}{
  \usepackage{bookmark}
  \usepackage{regexpatch}
  \xapptocmd{\beamer@@frametitle}
    {\only<1>{\bookmark[page=\the\c@page,level=3]{#1}}}%
    {\message{** patching of \noexpand\beamer@@frametitle succeeded **}}%
    {\message{** patching of \noexpand\beamer@@frametitle failed **}}%
}{}
\makeatother


\begin{document}

\begin{frame}{Title}
Hello \pause world
\end{frame}
\end{document}

información relacionada