Gemeinsam einrahmen und auflisten

Gemeinsam einrahmen und auflisten

Ich möchte es neu definieren frameals frame + itemize. Ich habe bisher Folgendes versucht -

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

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

Was genau ist daran falsch und wie kann man dies dann richtig neu definieren?

Antwort1

Die beamerUmgebung framesammelt ihren Körper mithilfe der folgenden Technik: Sie liest und speichert Token, die auf \begin{frame}die Suche nach folgen \end{frame}, ohne sie zu erweitern, außer in einem Fall (siehe unten), aber sie akzeptiert ein als Ende des zu sammelnden Umgebungskörpers nur, wenn sie während dieses Sammlungsprozesses \end{frame}dieselbe Anzahl von \begin{...}wie gesehen hat (sie versucht nicht, sie abzugleichen). Dies wird für in von verwendet .\end{...}\beamer@begin@stack\beamer@collect@@bodybeamerbaseframe.sty

Falls der Stapel leer ist (d. h. er hat so viele gesehen \end{...}wie \begin{...}nach \begin{frame}) und das Folgende \end{...}kein ist \end{frame}, erweitert er dies \endin der Hoffnung, dass dies erscheinen wird \end{frame}. 1 Aber diesnurgeschieht unter der von mir angegebenen Bedingung (so viele \end{...}wie \begin{...}nach dem Initial \begin{frame}gesehen worden sein müssen).

In Ihrem Beispiel schiebt (d. h. öffnet eine Ebene) der \begin{itemize}eine auf den Stapel. Dieser wird beim Lesen von herausgeholt. An diesem Punkt weiß , dass er genauso viele gesehen hat wie nach dem . Das ist richtig, aber irreführend, denn wenn erweitert würde, würde es zwei Herausholvorgänge ergeben. Also denkt , dass der nächste liefern muss , möglicherweise nach dem Erweitern des Tokens (siehe Fußnote 1). Leider ist das falsch; der nächste ist . wird also erweitert, sucht dann weiter nach , findet es aber natürlich nie, erreicht das Ende der Datei, was den Fehler auslöst:b\beamer@begin@stackb\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 

Das Problem besteht also grundsätzlich darin, dass \beamer@collect@@bodySie die nicht richtig zählen können, \end{...}da Ihr \end{myframe}zwei davon ( \end{itemize}\end{frame}) verbirgt und \beamer@collect@@bodysie \endmyframetrotz des Vorhandenseins von nicht durch die Erweiterung von entdecken wird, da es an dem Punkt, an dem es dies sieht, \end{myframe}mehr gesehen hat \begin{...}als (nicht leerer Stapel aufgrund von ).\end{...}\end{myframe}\begin{itemize}

\end{...}Die Lösungen erfordern, dass Sie sich nicht in Makros verstecken , die \beamer@collect@@bodynicht erweitert werden. Eine davon ist die Verwendung des environPakets wie inferahfezas Antwort, ein anderer verwendet \itemizeund \enditemizewie folgt (keiner von beiden beeinflusst den \beamer@begin@stackStapel, daher ist der Stapel leer, wenn \beamer@collect@@bodygesehen wird \end{myframe}, und \endmyframewird daher einmal erweitert, wodurch der \end{frame}Körperscanvorgang für die Umgebung sichtbar wird):

\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}

Bildschirmfoto


Fußnote

  1. Genauer gesagt passiert Folgendes (in beamer 2018/12/02 v3.55). Wenn:

    • der \beamer@begin@stackStapel leer ist (so viele, \end{...}wie nach dem Einsammeln der Leiche \begin{...}gesehen wurden ) und\begin{frame}
    • das nächste \end{...}ist kein \end{frame}– sagen wir, es ist ein \end{foobar},

    ersetzt dann \beamer@collect@@bodydie Erweiterung der ersten Ebene von \endfoobar\endgroupdurch this \end{foobar}im gesammelten Material. Dies ist ähnlich dem, was die Erweiterung \end{foobar}erzeugen würde, obwohl letzteres noch ein paar weitere Dinge bewirken würde (siehe source2e.pdfS. 272):

    • Überprüfen Sie, ob der Ersetzungstext von \@currenvirlautet foobar(dies würde im beamer frameTextkörper-Sammelprozess, von dem wir sprechen, fehlschlagen, da \@currenvirlautet frame);
    • einen vorherigen \@endparenvBefehl berücksichtigen (wird verwendet, um die Absatzeinrückung am Anfang von Text nach einigen Umgebungen zur Absatzerstellung zu unterdrücken, es sei denn, dem Text geht eine Leerzeile oder ein \par) voraus;
    • einen vorherigen \ignorespacesafterendBefehl berücksichtigen (wird verwendet, um den nächsten dazu zu bringen \end{...}, die möglicherweise folgenden Leerzeichen zu ignorieren).

Antwort2

Paket verwenden 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}

Bildbeschreibung hier eingeben

verwandte Informationen