今天我花了比我願意承認的更多的時間來被程式碼中的註解打敗...
我試圖在簡報中逐字插入一些內容,但收到此錯誤:
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 指出的那樣,逐字處理器。
對於[fragile]
幀,beamer
使用其逐字處理器,位於beamerbaseverbatim.sty
. Beamer 有一個簡潔的逐字處理器:
\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
是 string \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!
這會讓事情變得瘋狂:)
長話短說
孩子請記住,使用[fragile]
框架時,\end{frame}
必須成為僅有的行中的事情。不允許前導空格和註釋(尾隨空格被 TeX 吞噬)。
正如 samcarter 在她的評論中指出的那樣,Beamer 的當前版本允許領先和尾隨空格和製表符。\beamer@strip@whitespace
在與 比較之前,巨集將吃掉空格和製表符\beamer@stopframe
。