![更新部分命令以在环境中包装整个部分](https://linux22.com/image/240344/%E6%9B%B4%E6%96%B0%E9%83%A8%E5%88%86%E5%91%BD%E4%BB%A4%E4%BB%A5%E5%9C%A8%E7%8E%AF%E5%A2%83%E4%B8%AD%E5%8C%85%E8%A3%85%E6%95%B4%E4%B8%AA%E9%83%A8%E5%88%86.png)
我正在尝试编写一个 beamer 模板潘多克.为此我需要转换
\section{Text 1}
Some text.
到
\begin{frame}[fragile]{Text 1}
Some text.
\end{frame}
有没有办法在 LaTeX 中做到这一点,例如使用\renewcommand
?我不介意对生成的 LaTeX 文件进行多次解析。
这个问题似乎在寻找类似的解决方案,但我感兴趣的问题并没有真正得到解答。
编辑
对 like的重新定义\section
(伪代码)
def \section{$title}:
static has_preceeding_section = False
has_preceeding_section = True
if not has_preceeding_section:
return \begin{frame}[fragile]{$title}
else:
return \end{frame}\begin{frame}[fragile}{$title}
finally:
return \end{frame}
对我的用例来说就足够了。如何在 LaTeX 中实现上述伪代码?
答案1
我有一种解决方案,但我不确定它有多强大。在这种特殊情况下,这可能是可以的,因为 LaTeX 文件是从 创建的pandoc
,因此输出中不太可能有任何“偷偷摸摸的宏”。特别是,我预计不会有人试图在文档中间更改 catcodes。此外,诸如\section
命令和\end{document}
命令之类的东西将位于它们自己的行上。
这个想法是,当我们得到一个\section
时,我们就开始吞噬行。每次我们得到一个新行时,我们都会测试第一个标记以查看它是\section
命令还是一个\end
。如果它是\end
,我们会测试它是否是\end{document}
。如果其中一个(最终)测试为真,那么我们就会停止吞噬行并将我们迄今为止吞噬的内容放入框架中(以部分标题作为框架标题)。如果其中一个为假,那么我们就会返回到吞噬行。
请注意,我们可以通过将其放入脆弱框架中来处理 catcode 内容。
以下是代码,附带示例文档:
\documentclass{beamer}
\makeatletter
\long\def\ge@addto@macro#1#2{%
\begingroup
\toks@\expandafter\expandafter\expandafter{\expandafter#1#2}%
\xdef#1{\the\toks@}%
\endgroup}
\let\sec@this=\@empty
\def\sec@document{document}
\long\gdef\sec@line#1\par{%
\g@addto@macro\sec@this{#1\par}%
\futurelet\sec@next\sec@linestart}%
\def\sec@linestart{%
\let\sec@do@next=\sec@line
\ifx\sec@next\section
\let\sec@do@next=\sec@new
\else
\ifx\sec@next\end
\let\sec@do@next=\sec@test@end
\fi
\fi
\sec@do@next}
\def\sec@new{%
\def\sec@frame{}%
\ifx\sec@this\@empty
\else
\g@addto@macro\sec@frame{\begin{frame}}%
\ge@addto@macro\sec@frame\sec@title
\ge@addto@macro\sec@frame\sec@this
\g@addto@macro\sec@frame{\par\end{frame}}%
\fi
\let\sec@title=\@empty
\let\sec@this=\@empty
\sec@frame
}
\def\sec@test@end\end#1{%
\def\sec@test{#1}%
\ifx\sec@test\sec@document
\message{got here}%
\let\sec@do@next=\sec@new
\else
\let\sec@do@next=\sec@line
\fi
\sec@do@next\end{#1}}
\renewcommand{\section}[1]{\message{Called with #1}\def\sec@title{{#1}}\sec@line}
\makeatother
\usepackage{lipsum}
\begin{document}
\section{Introduction}
\lipsum[1]
\section{Main Part}
\lipsum[1]
\section{Main Theorem}
\begin{theorem}[Euclid]
There is no largest prime.
\end{theorem}
\begin{proof}
We start by noting that a number is prime if and only if no prime less than it divides it.
\begin{enumerate}[<+->]
\item Suppose that there were a largest prime.
\item Then the number of primes would be finite; label them (in order) as \(p_1, \dotsc, p_n\).
\item Consider \(q = p_1 \cdot p_2 \cdots p_n + 1\).
\item Then \(p_j \not| q\) so \(q\) is not divisible by any prime less than it.
\item Hence \(q\) is prime.
\item But \(q > p_n\) so \(q\) is not prime.
\end{enumerate}
\end{proof}
\section{Conclusion}
\lipsum[1]
\end{document}
我把theorem
和proof
放进去以表明它适用于非文档端。该lipsum
包用于为其他框架提供一些虚拟文本。
请注意,对技术细节感兴趣的人:我查看了和,environ
以beamer
了解如何收集大量“东西”,但两者都是通过收集到下一个 来工作的\end
。我们需要能够同时查找\end{document}
和\section{Section Title}
。我看不出有任何方法可以使用相同的机制来做到这一点,所以不得不逐行吞咽。如果有更好的方法,我很想知道。