Комментарий после того, как хрупкий \end{frame} ломает бимер

Комментарий после того, как хрупкий \end{frame} ломает бимер

Сегодня я потратил больше времени, чем мне хотелось бы, терпя поражение из-за комментария в коде...

Я пытался вставить дословный текст в презентацию и получил следующую ошибку:

Runaway argument?
! File ended while scanning use of \next.

Затем, сведя все это к MWE, я получил следующее:

\documentclass{beamer}

\begin{document}

\begin{frame}[fragile]
Hello :)
\end{frame}% NO :(

\end{document}

и ошибка сохранилась.

Затем, когда я удалил комментарий, \end{frame}все заработало.

Может ли кто-нибудь объяснить, что здесь происходит?


Отказ от ответственности: нет, мне не нужен комментарий :P

решение1

Немного покопавшись во beamerвнутренностях, я обнаружил, что ответ, как и указал egreg, — процессор verbatim.

Для [fragile]кадров beamerиспользует свой процессор verbatim, расположенный в beamerbaseverbatim.sty. У Beamer есть удобный процессор verbatim:

\protected\long\gdef\beamer@processframeline#1^^M{%
  \edef\beamer@test{\beamer@strip@whitespace#1\beamer@strip@stop}%
  \ifx\beamer@test\beamer@stopframe%
    \let\next=\beamer@framewritten%
  \else%
    \immediate\write\beamer@verbatimfileout{#1}%
    \let\next=\beamer@processframeline%
  \fi%
  \next%
}%

Процессор — это макрос с разделителями, который будет читать все до символа возврата каретки (новая строка). Прочитанное содержимое сохраняется \beamer@testи сравнивается с \beamer@stopframeтем, что в большинстве случаев определяется как:

\xdef\beamer@stopframe{\string\\end\string\{frame\string\}}

которая расширяется до точной строки \ e n d { f r a m e }.

Процессор сравнивает \beamer@testс \beamer@stopframeи если они различны, содержимое \beamer@testзаписывается в \beamer@verbatimfileout(файл .vrb), а \nextмакрос должен \letбыть процессором, и он рекурсивно вызывает себя для продолжения чтения. В противном случае, если \beamer@testэто строка \end{frame}, процессор завершает работу нормально.

Ошибка возникает из-за того, что процессор не игнорирует комментарии (они могут потребоваться в дословном контексте!), поэтому процессор сравнивает \end{frame}с \end{frame}% NO :(, что, очевидно, не удается, и продолжает чтение после \end{frame}.

Сейчас могут произойти две вещи:

Во-первых, это последний кадр, поэтому процессор никогда не найдет соответствие \end{frame}, ! File ended while scanning use of \next.возникнет ошибка и компиляция прекратится.

Во-вторых, и это более болезненно, есть еще один кадр, в котором будут дроиды, \end{frame} которых искал процессор. Но в этом случае \nextбудет \letto \beamer@framewritten, что по сути считывает содержимое файла .vrb обратно в кадр. Но содержимое будет примерно таким:

Hello :)
\end{frame}% NO :(
\begin{frame}
Hello again!

что заставит все пойти наперекосяк :)

TL;DR

Помните, дети, при использовании [fragile]рамок,\end{frame} долженбытьтольковещь в строке. Не допускаются начальные пробелы и комментарии (конечные пробелы поглощаются TeX).

Как отметила Сэмкартер в своем комментарии, текущая версия Beamer позволяет вестииконечные пробелы и табуляции. \beamer@strip@whitespaceМакрос съест пробелы и табуляции перед сравнением с \beamer@stopframe.

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