フレームとアイテムを一緒に作成する

フレームとアイテムを一緒に作成する

frameを として再定義したいと思いますframe + itemize。これまでこれを試してきました -

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

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

これのどこが間違っているのでしょうか。また、これを正しく再定義するにはどうすればよいでしょうか。

答え1

環境beamerframe、次の手法を使用して本体を収集します。\begin{frame}を検索した後、トークンを読み取り、1 つのケース (以下を参照) を除いて拡張せずに保存しますが、収集プロセス中にと同じ数の が見つかった場合にのみ、収集される環境本体の末尾として\end{frame}を受け入れます(一致させようとはしません)。これは、fromの で使用されているものです。\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}1 つをプッシュしますb(つまり、1 レベル開きます) \beamer@begin@stack。が読み取られるbと、これがポップされます。この時点で、は の後にだけ見たことを認識しています。 これは正しいですが誤解を招きます。が展開されると、2 つのポップが生成されるためです。 そのため、は、次はを提供する必要があると考えます (おそらくトークンを展開した後で、脚注 1 を参照)。 残念ながら、これは正しくありません。次は です。がこのように展開され、を探し続けますが、もちろん見つからず、ファイルの末尾に到達して、エラーが発生します。\end{myframe}\beamer@collect@@body\begin{...}\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 

つまり、基本的に、問題は がこれら 2 つ ( ) を隠しており、 が存在するにもかかわらず の展開によってこれらを発見できないため、 が を適切にカウントできないということです。これは、がこれ\beamer@collect@@bodyを見つけた時点でよりも多く見ているからです( によりスタックが空ではありません)。\end{...}\end{myframe}\end{itemize}\end{frame}\beamer@collect@@body\endmyframe\end{myframe}\begin{...}\end{...}\end{myframe}\begin{itemize}

解決策としては、展開されない\end{...}マクロに隠れないようにする必要があります。1つは、次のようにパッケージを使用することです。\beamer@collect@@bodyenvironferahfeza の回答、もう 1 つは\itemize\enditemizeを次のように使用しています (どちらもスタックには影響しないため、が を見た\beamer@begin@stackときにスタックは空であり、 が1 回展開され、環境本体のスキャン プロセスに対して が見えるようになります)。\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第一レベルの展開で置き換えます。これは展開によって生成されるものと似ていますが、後者ではさらにいくつかの処理が行われます ( p. 272 を参照)。\endfoobar\endgroup\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}

ここに画像の説明を入力してください

関連情報