Сегодня я потратил больше времени, чем мне хотелось бы, терпя поражение из-за комментария в коде...
Я пытался вставить дословный текст в презентацию и получил следующую ошибку:
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
будет \let
to \beamer@framewritten
, что по сути считывает содержимое файла .vrb обратно в кадр. Но содержимое будет примерно таким:
Hello :)
\end{frame}% NO :(
\begin{frame}
Hello again!
что заставит все пойти наперекосяк :)
TL;DR
Помните, дети, при использовании [fragile]
рамок,\end{frame}
долженбытьтольковещь в строке. Не допускаются начальные пробелы и комментарии (конечные пробелы поглощаются TeX).
Как отметила Сэмкартер в своем комментарии, текущая версия Beamer позволяет вестииконечные пробелы и табуляции. \beamer@strip@whitespace
Макрос съест пробелы и табуляции перед сравнением с \beamer@stopframe
.