\apptocmd в условный оператор — почему это не работает?

\apptocmd в условный оператор — почему это не работает?

Почему следующее выражение MWE не работает, хотя если я прокомментирую условие, оно работает?

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

решение1

Основной ответ

В общем, исправление команд, когда #задействовано, не может произойти в аргументе другой команды. Можно сделать некоторые трюки с кодами категорий, но другой подход может быть проще:

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

Условие \if@tempswaпредставляет собой чистое условие, предоставляемое ядром.

Вот что написано в .logфайле:

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

Обобщенный ответ

Похожий подход без использования \@tempswaand можно использовать для других псевдоусловий LaTeX, таких как \@ifpackageloadedor \@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

Это основано на фактах, которые \ifрасширяют токены и что псевдоусловия LaTeX полностью расширяемы; поэтому в конце \ifнаходит либо 11если условие истинно, либо в противном случае 01и поэтому следует ветвям true и false соответственно. Обратите внимание, что такие конструкции могут быть вложены в другие условные выражения в стиле TeX. Также можно указать код для ветви false.

Альтернативный метод

В качестве альтернативы используйте regexpatchпакет:

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

Связанный контент