Testen auf aufeinanderfolgende Aufrufe einer Umgebung

Testen auf aufeinanderfolgende Aufrufe einer Umgebung

Ich verwende Beamer, um Folien für meinen Statistikkurs zu erstellen und habe jetzt ein sehr schönes Setup, das eine Ausgabe ähnlich der von Powerpoint erzeugt (siehe Frage:Verwenden Sie Beamer, um 3 Folien pro Seite mit Notizen daneben zu platzieren (wie bei Powerpoint)).

Damit dieses System funktioniert, benötige ich für jede Folie eine Definition der Notizen, die mit einer Folie verknüpft sind, da die Notizen sonst nicht mehr mit den Folien synchronisiert sind. Es gibt wahrscheinlich eine bessere Möglichkeit, eine „Standard“-Notizendefinition für eine Folie zu definieren, damit sie nie nicht mehr synchronisiert sind, aber das übersteigt meine Fähigkeiten in Latex bei weitem, und die Umgebung ist so kompliziert, dass es (für mich) schwierig wäre, ein MWE dafür zu veröffentlichen.

Stattdessen möchte ich zumindest den Fehler abfangen, dass für eine Folie keine Notizen definiert wurden. Der einfachste Weg, der mir dazu einfällt, lässt sich auf ein MWE reduzieren, das unten gezeigt wird:

\documentclass[10pt]{article}

\newcounter{mypagecount}
\setcounter{mypagecount}{1}

\newcommand\incpagecount{
  \stepcounter{mypagecount}
}
\newcommand\getpagecount{
  \themypagecount
}

\newenvironment{mypage}[1]{%
Parameter: #1 Expected: \getpagecount Body :}{ \incpagecount \\ }

\begin{document}

\begin{mypage}{1} foo \end{mypage}
\begin{mypage}{2} foo \end{mypage}
\begin{mypage}{4} foo \end{mypage}
\begin{mypage}{5} foo \end{mypage}

\end{document}

FRAGE: Wie bringe ich Latex dazu, einen Fehler auszugeben, wenn es feststellt, dass es keinen Aufruf für mypage {3} gab? Für C-Programmierer wäre es toll, zu zeigen, wie man eine C-artige Behauptung verwendet, dass der Parameter nicht dem erwarteten Wert entspricht!

Danke an alle.

Antwort1

Keine Behauptung. Nicht einmal ein !=. Es gibt auch \if, \ifdim, \ifx, , \ifcase, \@ifundefined, \@ifl@aded, usw. Siehe das TeXbook (Knuth) und source2e.pdf (CTAN).

Beachten Sie, dass lokale Definitionen außerhalb einer Umgebung nicht verfügbar sind. Glücklicherweise verwenden die Zähleroperationen globale Versionen. \global\letund \xdefkönnen verwendet werden, und jedoch \setlengthnicht \renewcommand.

\documentclass[10pt]{article}

\newcounter{mypagecount}
\setcounter{mypagecount}{1}

\newcommand\incpagecount{%
  \stepcounter{mypagecount}%
}
\newcommand\getpagecount{% redundant
  \themypagecount
}

\newenvironment{mypage}[1]{%
\ifnum\value{mypagecount}=#1\relax
\else
  \errmessage{Parameter: #1 Expected: \getpagecount}%
  \setcounter{mypagecount}{#1}%
\fi
\noindent Body :}%
{ \incpagecount \\ }

\begin{document}

\begin{mypage}{1} foo \end{mypage}
\begin{mypage}{2} foo \end{mypage}
\begin{mypage}{4} foo \end{mypage}
\begin{mypage}{5} foo \end{mypage}

\end{document}

Antwort2

Ich schlage eine andere Lösung vor. Dies ist derzeit ein Proof-of-Concept. Insbesondere schlägt es fehl, wenn Sie andere Optionen als labeldie frameUmgebung übergeben. Dies kann meiner Meinung nach behoben werden, würde die Sache aber verkomplizieren.

Die Idee ist, die Folien auf andere Weise in das Handout einzubinden. Dabei werden das beamerarticlePaket von Beamer, die labelOption für frameUmgebungen und das \includeslideMakro verwendet. Außerdem werden (weil ich zu frustriert war, mit s und dergleichen xcoffinsherumzuspielen ) und verwendet .minipageenviron

Arbeitsablauf:

  • 3 Dateien, von denen 2 extrem einfache Wrapper sind, die die dritte eingeben.

  • Die dritte Datei enthält kein \documentclass, sondern sowohl Folien als auch Notizen. Angenommen, dies ist <main file name>.tex.

  • Die Folien kommen framewie gewohnt in Umgebungen. Diese werden mit der labelOption gekennzeichnet.

  • Die Notizen werden in annotUmgebungen eingefügt. Diese erfordern ein Argument, das die Bezeichnung für die entsprechende Folie angibt. (Wenn Sie sich normal auf die Folie beziehen würden, würden Sie dieses Argument angeben \ref{}.) Ein optionales Argument kann verwendet werden, um die beim Einfügen der Folie verwendeten Einstellungen zu überschreiben.

  • Der erste Wrapper wird kompiliert, um die Folien zu erstellen. Ich habe dies genannt <main file name>-beamer.tex. Der Inhalt dieser Datei sollte sein

    \pdfminorversion=7% comment this out if not using pdftex
    \documentclass[ignorenonframetext]{beamer}
    \input{<main file name>}% substitute appropriately here
    

    Dies sollte zusammengestellt werdenErste.

  • Der zweite Wrapper wird kompiliert, um die Handouts zu erstellen. Ich habe ihn aufgerufen, <main file name>-article.texweil ich die articleKlasse und den Beamer- articleModus verwendet habe. Der Inhalt dieser Datei sollte sein

    \pdfminorversion=7% comment this out if not using pdftex
    \documentclass{article}% adjust if you prefer a different class
    \usepackage{beamerarticle,graphicx}
    \setjobnamebeamerversion{<main file name>-beamer}% substitute appropriately here
    \input{<main file name>}% substitute appropriately here
    

    Dies sollte zusammengestellt werdenzweite.

Dann <main file name>.texfügen Sie den Rest Ihrer Präambel und den documentText ein. Ich habe die meisten benutzerdefinierten Dinge hier in die Präambel eingefügt und sie auf den Beamer- articleModus beschränkt, aber Sie könnten dies auch in den Handout-Wrapper verschieben, wenn Sie das bevorzugen.

% \jobname.tex = <main file name>.tex
\mode<article>
{

Dies wird nur im articleModus ausgeführt.

  \usepackage{xcoffins,environ,geometry,calc,pgf}

xcoffins, environ, pgfund calcsind erforderlich. geometryHabe gerade die defekten Kartons entsorgt.

Zunächst ein paar neue Längen, die wir später brauchen.

  \newlength\annotsep
  \setlength\annotsep{.5em}% set the horizontal separation of frames and annotations
  \newlength\frmwd
  \AtBeginDocument{%
    \setlength\frmwd{.5\linewidth-.5\annotsep-2\fboxsep-2\fboxrule}%
  }

Und ein paar Särge.

  \NewCoffin\AnnotCoffin
  \NewCoffin\FrameCoffin

Jetzt definieren wir die annotUmgebung, verwenden aber „ \NewEnvironeher“ als „ \newenvironment, weil wir den gesamten Inhalt in einen Sarg packen wollen und dies am einfachsten erschien. (Ich habe expl3hier versucht, „syntax“ zu vermeiden.)

  \NewEnviron{annot}[2][]{%
    \edef\tempa{\extractedref}\edef\tempb{#2}%
    \ifx\tempa\tempb\relax
    \else\outputempty\fi\xdef\extractedref{}%

Dadurch wird überprüft, ob es Frames gibt, für die wir außer dem für diese Anmerkung keine Folie eingefügt haben. Wenn es eine Beschriftung gibt, frameder dieser Satz von Notizen nicht entspricht, nehmen wir an, dass der Frame keine Notizen hat, und geben ihn stattdessen mit einem Leerzeichen auf der rechten Seite aus.

Nun stellen wir unseren ersten Sarg auf, \FrameCoffinmit einer gerahmten Kopie der entsprechenden Folie (also der Folie, auf die wir mit dem annotobligatorischen Argument der Umgebung verwiesen haben).

    \SetVerticalCoffin\FrameCoffin{.5\linewidth-.5\annotsep}{%
      \fbox{\includeslide[width=\frmwd,#1]{#2}}% depending on theme, remove frame if not required
    }%

Nun stellen wir unseren zweiten Sarg auf, \AnnotCoffinfür die Notizen.

    \SetVerticalCoffin\AnnotCoffin{.5\linewidth-.5\annotsep}{%
      \BODY
    }%

Wir verbinden die Särge oben, indem wir die Knoten etwas quer und nach unten schieben.

    \JoinCoffins\FrameCoffin[t,r]\AnnotCoffin[t,l](\annotsep,-.5\baselineskip)

Setzen Sie unsere Särge und lassen Sie etwas flexiblen vertikalen Raum, sodass unsere Folien gleichmäßig auf der Seite verteilt sind.

    \TypesetCoffin\FrameCoffin
    \medskip\vfill\par
  }
  \usepackage{kantlipsum}

Dieses Paket dient nur als Beispiel. Laden Sie es nicht in Ihr echtes Dokument, es sei denn, Sie setzen die relevanten Passagen von Kant und haben nichts gegen die wahrscheinlich veraltete Übersetzung.

Ein paar neue Befehle.

  \newcommand\extractref{}
  \newcommand\extractedref{}

Definieren Sie eines davon als Hilfsmakro.

  \def\extractref label=#1\null{#1}

Dies ändert die Definition des frameModus article. Normalerweise setzt Beamer den frameInhalt in allen Modi. Dies möchten wir hier jedoch nicht. Wir definieren es so, dass es ein einzelnes optionales Argument annimmt. Alles andere verschwindet. Wenn jedoch ein optionales erstes Argument vorhanden ist und es nicht leer ist, nehmen wir an, dass es ein ist, label=<key for label>und extrahieren diese Referenz.

  \RenewEnviron{frame}[1][]{%
    \edef\tempa{#1}\edef\tempb{}%
    \ifx\tempa\tempb\relax
    \else
      \outputempty

Wenn das Makro, das den Trace speichert, \extractedrefnicht leer ist, gab es eine Folie ohne einen entsprechenden Satz Notizen. In diesem Fall nehmen wir an, dass diese Folie keine Notizen enthält, und geben diese Folie mit einem leeren Satz Notizen auf der rechten Seite aus.

      \xdef\extractedref{\extractref #1\null}%

Für den aktuellen framesetzen wir nichts. Wir extrahieren und speichern lediglich die Referenz in \extractedref.

    \fi
  }

Nun zum Makro, das s ohne Annotationen ausgibt . Dies wird von den neu definierten und den Umgebungen frameverwendet .frameannot

  \newcommand\outputempty{%
    \edef\tempb{}%
    \edef\tempa{\extractedref}%
    \ifx\tempa\tempb\relax
    \else

Särge sind hier nicht erforderlich, aber wir geben die Folie mit der Standardkonfiguration aus und fügen den gleichen vertikalen Abstand ein, um die Folien gleichmäßig auf der Seite zu verteilen.

      \fbox{\includeslide[width=\frmwd]{\extractedref}}%
      \medskip\vfill\par
    \fi
  }
}

Ich vermute, Sie möchten hier keine Absatzeinrückung. Sie könnten die Verwendung des parskipPakets in Betracht ziehen, aber je nach Inhalt Ihrer Notizen ist das möglicherweise nicht wichtig.

  \setlength\parindent{0pt}

Wenn das letzte framebeschriftet, aber unbeschriftet ist, müssen wir sicherstellen, dass es in das Handout kommt. Ein weiteres \outputemptysollte genügen.

  \AtEndDocument{\outputempty}

Das ist die Konfiguration. Jetzt zum Dokument.

\begin{document}

hier ist ein Rahmen mit der Beschriftung frame-a.

\begin{frame}[label=frame-a]{A Frame}%
  \includegraphics[height=.75\textheight,width=\textwidth,keepaspectratio]{example-image-a}
\end{frame}

Hier sind die Hinweise für frame-a.

\begin{annot}{frame-a}
  Not much to say about image A.
\end{annot}

Gleiches gilt für frame-bund frame-c.

\begin{frame}[label=frame-b]{B Frame}%
  \includegraphics[height=.75\textheight,width=\textwidth,keepaspectratio]{example-image-b}
\end{frame}
\begin{annot}{frame-b}
  Not much to say about image b.
\end{annot}

\begin{frame}[label=frame-c]{C Frame}%
  \includegraphics[height=.75\textheight,width=\textwidth,keepaspectratio]{example-image-c}
\end{frame}
\begin{annot}{frame-c}
  Not much to say about image C.
\end{annot}

Dadurch wird eine Seite mit geometrydem Standardlayout erstellt.

Hier ist frame-another. Hier fehlen die Notizen, deshalb gibt es keine annotFortsetzung.

\begin{frame}[label=frame-another]{Another Frame}%
  \includegraphics[height=.75\textheight,width=\textwidth,keepaspectratio]{example-image}
\end{frame}

Im articleModus wird der nächste Frame frame-anotherausgegeben, da wir davon ausgehen frame, dass keine Notizen dafür vorhanden sind. Ich hatte keine Bilder von MWE mehr und war gelangweilt, also hier eine tolle Alternative.

\begin{frame}[label=frame-tiger]{Tiger Frame}%
  \includegraphics[height=.75\textheight,width=\textwidth,keepaspectratio]{tiger}
\end{frame}
\begin{annot}{frame-tiger}
  This frame shows a large, wild cat.
  Well, what it actually shows is a small picture of a wild cat, but you are meant to infer that it represents a larger reality.
\end{annot}

Der nächste framehat eine sehr lange Notiz und landet daher auf einer eigenen Seite. Hier ist das Gebrüll etwas weniger laut, aber vielleicht ist man in der Gruppe sicherer.

\begin{frame}[label=frame-cats]{Cats Frame}%
  \includegraphics[height=.75\textheight,width=\textwidth,keepaspectratio]{cathod}
\end{frame}
\begin{annot}{frame-cats}
  \kant[1-2]
\end{annot}

\begin{frame}[label=frame-which]{Which Frame?}%
 \includegraphics[height=.75\textheight,width=\textwidth,keepaspectratio]{cauldron}
\end{frame}
\begin{annot}{frame-which}
  This frame includes a pun, a cauldron and a question.
  More accurately, it includes a pun, a depiction of a cauldron and a question mark.
\end{annot}

Und ein letztes, nichtssagendes frame, um sicherzustellen, dass das Finale \outputemptyfunktioniert.

\begin{frame}[label=frame-gadael]
  \includegraphics[width=\textwidth]{cath-gadael-chartref}
\end{frame}

\end{document}

Folien:

Folien

Handout/Mitschriften:

Handout mit Notizen

Vollständiger Code (Dateinamen müssen bei Bedarf ersetzt werden):

\begin{filecontents}{\jobname-beamer.tex}
\documentclass[ignorenonframetext]{beamer}
\input{<main file name>}% substitute \jobname or whatever here
\end{filecontents}
\begin{filecontents}{\jobname-article.tex}
\documentclass{article}
\usepackage{beamerarticle,graphicx}
\setjobnamebeamerversion{<main file name>-beamer}% substitute \jobname or whatever here
\input{<main file name>}% substitute \jobname or whatever here
\end{filecontents}

% \jobname.tex = <main file name>.tex
\mode<article>
{
  \usepackage{xcoffins,environ,geometry,calc,pgf}
  \newlength\annotsep
  \setlength\annotsep{.5em}% set the horizontal separation of frames and annotations
  \newlength\frmwd
  \AtBeginDocument{%
    \setlength\frmwd{.5\linewidth-.5\annotsep-2\fboxsep-2\fboxrule}%
  }
  \NewCoffin\AnnotCoffin
  \NewCoffin\FrameCoffin
  \NewEnviron{annot}[2][]{%
    \edef\tempa{\extractedref}\edef\tempb{#2}%
    \ifx\tempa\tempb\relax
    \else\outputempty\fi\xdef\extractedref{}%
    \SetVerticalCoffin\FrameCoffin{.5\linewidth-.5\annotsep}{%
      \fbox{\includeslide[width=\frmwd,#1]{#2}}% depending on theme, remove frame if not required
    }%
    \SetVerticalCoffin\AnnotCoffin{.5\linewidth-.5\annotsep}{%
      \BODY
    }%
    \JoinCoffins\FrameCoffin[t,r]\AnnotCoffin[t,l](\annotsep,-.5\baselineskip)
    \TypesetCoffin\FrameCoffin
    \medskip\vfill\par
  }
  \usepackage{kantlipsum}
  \newcommand\extractref{}
  \newcommand\extractedref{}
  \def\extractref label=#1\null{#1}
  \RenewEnviron{frame}[1][]{%
    \edef\tempa{#1}\edef\tempb{}%
    \ifx\tempa\tempb\relax
    \else
      \outputempty
      \xdef\extractedref{\extractref #1\null}%
    \fi
  }
  \newcommand\outputempty{%
    \edef\tempb{}%
    \edef\tempa{\extractedref}%
    \ifx\tempa\tempb\relax
    \else
      \fbox{\includeslide[width=\frmwd]{\extractedref}}%
      \medskip\vfill\par
    \fi
  }
  \setlength\parindent{0pt}
  \AtEndDocument{\outputempty}
}
\begin{document}
\begin{frame}[label=frame-a]{A Frame}%
  \includegraphics[height=.75\textheight,width=\textwidth,keepaspectratio]{example-image-a}
\end{frame}
\begin{annot}{frame-a}
  Not much to say about image A.
\end{annot}

\begin{frame}[label=frame-b]{B Frame}%
  \includegraphics[height=.75\textheight,width=\textwidth,keepaspectratio]{example-image-b}
\end{frame}
\begin{annot}{frame-b}
  Not much to say about image b.
\end{annot}

\begin{frame}[label=frame-c]{C Frame}%
  \includegraphics[height=.75\textheight,width=\textwidth,keepaspectratio]{example-image-c}
\end{frame}
\begin{annot}{frame-c}
  Not much to say about image C.
\end{annot}

\begin{frame}[label=frame-another]{Another Frame}%
  \includegraphics[height=.75\textheight,width=\textwidth,keepaspectratio]{example-image}
\end{frame}

\begin{frame}[label=frame-tiger]{Tiger Frame}%
  \includegraphics[height=.75\textheight,width=\textwidth,keepaspectratio]{tiger}
\end{frame}
\begin{annot}{frame-tiger}
  This frame shows a large, wild cat.
  Well, what it actually shows is a small picture of a wild cat, but you are meant to infer that it represents a larger reality.
\end{annot}

\begin{frame}[label=frame-cats]{Cats Frame}%
  \includegraphics[height=.75\textheight,width=\textwidth,keepaspectratio]{cathod}
\end{frame}
\begin{annot}{frame-cats}
  \kant[1-2]
\end{annot}

\begin{frame}[label=frame-which]{Which Frame?}%
 \includegraphics[height=.75\textheight,width=\textwidth,keepaspectratio]{cauldron}
\end{frame}
\begin{annot}{frame-which}
  This frame includes a pun, a cauldron and a question.
  More accurately, it includes a pun, a depiction of a cauldron and a question mark.
\end{annot}

\begin{frame}[label=frame-gadael]
  \includegraphics[width=\textwidth]{cath-gadael-chartref}
\end{frame}

\end{document}

verwandte Informationen