![在 beamer 中输入一行“foreach ...”(在文章中效果很好)](https://linux22.com/image/361936/%E5%9C%A8%20beamer%20%E4%B8%AD%E8%BE%93%E5%85%A5%E4%B8%80%E8%A1%8C%E2%80%9Cforeach%20...%E2%80%9D%EF%BC%88%E5%9C%A8%E6%96%87%E7%AB%A0%E4%B8%AD%E6%95%88%E6%9E%9C%E5%BE%88%E5%A5%BD%EF%BC%89.png)
我有一个问题,可以简单归结为以下几点。
首先,下面的代码可以正常工作:
\documentclass{beamer}
\usepackage{pgffor}
\begin{document}
\foreach \p in {first,second}
{
\begin{frame}
\p
\end{frame}
}
\end{document}
不过,如果我把这一行改一下
\foreach \p in {first,second}
和
\input{forEachToBeInput.tex}
其中forEachToBeInput.tex
是一个包含单行(即“ \foreach \p in {first,second}
”,显然)的文件并删除frame
环境,然后我开始收到一堆错误,如“ Paragraph ended before pgffor@next was complete
”......
请注意,有趣的是,如果我使用文档类 Article,那么一切都很好!
提前谢谢大家!!
答案1
问题在于\input
标记后面跟着其他东西,而不是直接跟着{\begin{frame}...\end{frame}}
部分。
您可以使用其他答案中建议的可扩展版本来解决问题\input
,但还有一种不太复杂的方法:
\begin{filecontents*}{forEachToBeInput.tex}
\foreach \p in {first,second}
\end{filecontents*}
\documentclass{beamer}
\usepackage{pgffor}
\usepackage{catchfile}
\newcommand{\foreachfromfile}[1]{%
\begingroup
% load the file contents in \temp
\CatchFileDef\temp{#1}{}
\expandafter\endgroup\temp
}
\begin{document}
\foreachfromfile{forEachToBeInput}
{
\begin{frame}
\p
\end{frame}
}
\end{document}
由于进行了分组,因此没有\temp
留下任何定义。
类似的方法只需要在文件中保存列表而不是\foreach
部分内容。
\begin{filecontents*}{forEach.tex}
first,second
\end{filecontents*}
\documentclass{beamer}
\usepackage{pgffor}
\usepackage{catchfile}
\newcommand\foreachfromfile[2]{
\CatchFileDef\foreachfromfilevariable{#2}{}%
\foreach #1 in \foreachfromfilevariable
}
\begin{document}
\foreachfromfile\p{forEach}
{
\begin{frame}
\p
\end{frame}
}
\end{document}
强制expl3
版本:
\begin{filecontents*}{forEach.tex}
first,second
\end{filecontents*}
\documentclass{beamer}
\usepackage{xparse}
\ExplSyntaxOn
\tl_new:N \l__giulio_foreach_tl
\clist_new:N \l__giulio_foreach_clist
\NewDocumentCommand{\foreachfromfile}{m +m}
{% #1 is the file name, #2 the actions to perform
\tl_set_from_file:Nnn \l__giulio_foreach_tl { } { #1 }
% normalize to a clist
\clist_set:NV \l__giulio_foreach_clist \l__giulio_foreach_tl
% map the clist
\clist_map_inline:Nn \l__giulio_foreach_tl { #2 }
}
\ExplSyntaxOff
\begin{document}
\foreachfromfile{forEach}
{
\begin{frame}
#1
\end{frame}
}
\end{document}
如您所见,不需要伪变量。列表中的当前项仅用 表示#1
。
答案2
尝试这个
\documentclass{beamer}
\usepackage{filecontents}
\begin{filecontents*}{forEachToBeInput.tex}
\foreach \p in {first,second}
\end{filecontents*}
\usepackage{pgffor}
\begin{document}
\csname @@input\endcsname forEachToBeInput.tex
{
\begin{frame}
\p
\end{frame}
}
\end{document}
(该filecontents
包仅用于使该答案独立)
(从评论中移出)
您可以通过添加来简化上述操作
\makeatletter\let\xxinput\@@input\makeatother
到序言部分然后使用
\xxinput forEachToBeInput.tex
{
<etc>
根据解释,宏扩展的踪迹表明,在某个阶段,TeX 将不得不扩展这个
\@addtofilelist {forEachToBeInput.tex}\filehook@atbegin {forEachToBeInput.tex}\@@input forEachToBeInput.tex<space token here>\filehook@atend {forEachToBeInput.tex}
这意味着在某个时候
\foreach \p in {first,second}\filehook@atend {forEachToBeInput.tex}
并且\foreach
不喜欢这样。
这\filehook@atend
不是 LaTeX 内核的一部分,也不是由标准类提供的。
我招募了 Sherlock Holmes,他发现这个宏是由包提供的,filehook
该包是由包加载的,sansmathaccent
该包是由包加载的beamerbasefont
。
\ifbeamer@sansmath
\IfFileExists{sansmathaccent.sty}
{\RequirePackage{sansmathaccent}}
{}
\fi
我们sansmathaccent.sty
发现:
% Check to see if we are a Beamer document
\@ifpackageloaded{beamerbasefont}{%
\def\sansmathaccent@warning{}
% Ensure proper placement of accents with bm
% but don't waste a mathgroup unless we will in fact use
% bm and pureletters
\IfFileExists{filehook.sty}{
\RequirePackage{filehook}
\AtBeginOfFile{bm.sty}{
\beamer@font@check \ifbeamer@suppressreplacements\else
\DeclareSymbolFont{pureletters}{OT1}{mathkerncmss}{m}{sl}
\SetSymbolFont{pureletters}{bold}{OT1}{mathkerncmss}{bx}{sl}
\fi
}
}{
\DeclareSymbolFont{pureletters}{OT1}{mathkerncmss}{m}{sl}
\SetSymbolFont{pureletters}{bold}{OT1}{mathkerncmss}{bx}{sl}
\PackageWarning{sansmathaccent}{Could not find 'filehooks' package: one mathgroup may be wasted}
}