框架和条目一起

框架和条目一起

我想重新定义frameframe + itemize。到目前为止,我已经尝试过这个 -

\documentclass{beamer}
\newenvironment{myframe}{\begin{frame}\begin{itemize}}{\end{itemize}\end{frame}}

\begin{document}
\begin{myframe}
\item
\end{myframe}
\end{document}

这到底是什么问题?如何正确地重新定义它?

答案1

环境使用以下技术收集其主体:它读取并存储查找后的标记beamer,除了一种情况(见下文)外,不会扩展它们,但只有当它在此收集过程中看到相同数量的as时,它才会接受作为正在收集的环境主体的末尾(它不会尝试匹配它们)。这就是from中 for 的使用。frame\begin{frame}\end{frame}\end{frame}\begin{...}\end{...}\beamer@begin@stack\beamer@collect@@bodybeamerbaseframe.sty

如果堆栈为空(即,它已经看到了之后的\end{...}),并且后面不是,它会扩展这个,希望这会出现。1但是这个\begin{...}\begin{frame}\end{...}\end{frame}\end\end{frame}仅有的发生在我给出的条件下(初始之后的\end{...}次数必须被看到)。\begin{...}\begin{frame}

在您的示例中,\begin{itemize}将一个b(即打开一个级别)推送到堆栈\beamer@begin@stack。读取b时弹出\end{myframe}。此时,\beamer@collect@@body知道在之后已经看到了\begin{...}与。这是正确的,但具有误导性,因为如果展开,它会产生两次弹出。因此,认为下一个必须提供,可能在展开标记之后(参见脚注 1)。唉,这是不正确的;下一个是。因此展开,然后继续寻找但当然永远找不到它,到达文件末尾,从而触发错误:\end{...}\begin{frame}\end{myframe}\beamer@begin@stack\end{...}\end{frame}\end...\end{...}\end{document}\enddocument\beamer@collect@@body\end{frame}

Runaway argument?
\let \AtEndDocument \@firstofone \@enddocumenthook \@checkend {docume\ETC.
! File ended while scanning use of \beamer@collect@@body.
<inserted text> 
                \par 

因此,基本上,问题在于\beamer@collect@@body无法保持对的正确计数,\end{...}因为您的\end{myframe}隐藏了其中两个(\end{itemize}\end{frame})并且尽管存在,\beamer@collect@@body也不会通过扩展发现它们,因为在看到这个时它已经看到了超过(由于非空堆栈)。\endmyframe\end{myframe}\begin{...}\end{...}\end{myframe}\begin{itemize}

解决方案要求你不要隐藏在不会扩展的\end{...}宏中。一种方法是使用如下包\beamer@collect@@bodyenvironFerahfeza 的回答,另一种是使用\itemize\enditemize如下(它们都不影响堆栈\beamer@begin@stack,因此当\beamer@collect@@body看到时\end{myframe},堆栈是空的,从而\endmyframe被扩展一次,这使得\end{frame}对环境主体扫描过程可见):

\documentclass{beamer}

\newenvironment*{myframe}[1]
  {\begin{frame}{#1}%
   \begingroup\itemize}
  {\enditemize\endgroup
   \end{frame}}

\begin{document}

\begin{myframe}{Frame title}
\item An item
\item Another item
\end{myframe}

\end{document}

截屏


脚注

  1. 更准确地说,会发生以下情况(在beamer 2018/12/02 v3.55)。如果:

    • 堆栈\beamer@begin@stack为空(在收集其主体之后已看到的\end{...}一样多),并且\begin{...}\begin{frame}
    • 下一个\end{...}不是\end{frame}——假设它是一个\end{foobar}

    然后用\beamer@collect@@body的第一级扩展替换收集到的材料中的\endfoobar\endgroupthis 。这与扩展产生的效果类似,尽管后者会做更多的事情(参见第 272 页):\end{foobar}\end{foobar}source2e.pdf

    • 检查 的替换文本\@currenvir是否为foobar(这会在beamer frame我们正在讨论的正文收集过程中失败,因为\@currenvirframe);
    • 遵守前一条\@endparenv命令(用于在某些段落制作环境之后抑制文本开头的段落缩进,除非所述文本前面有一个空行或\par);
    • 遵守前一个\ignorespacesafterend命令(用于使下一个命令\end{...}忽略可能跟在其后的空格)。

答案2

使用包environ

\documentclass{beamer}
\usepackage{environ}

\NewEnviron{myframe}[1][]{%
\begin{frame}{#1}
\begin{itemize}
\BODY
\end{itemize}
\end{frame}
}

\begin{document}
\begin{myframe}
\item First
\item Second
\end{myframe}
\end{document}

在此处输入图片描述

相关内容