Ich glaube, ich bin in einer Situation, die vielen bekannt vorkommt: Im Rahmen eines mehrjährigen Projekts habe ich eine sehr große Beamer-Präsentation mit vielen Folien entwickelt. Die LaTeX-Quellen sind auf viele Dateien aufgeteilt und da ich die Präsentation des Projekts oft neu erstellen muss, füge ich diese Dateien je nach Zeit/Publikum in das Hauptdokument ein (oder auch nicht).
Nun möchte ich die Generierung der Präsentation irgendwie automatisieren, indem ich den Rahmen steuere, den ich einbinden möchte. Statisch scheint dies mit den <handout:0|beamer:0>
Parametern bei der Rahmendefinition möglich zu sein:
\begin{frame}
Hello.
\end{frame}
% this frame won't be included
\begin{frame}<handout:0|beamer:0>
Hidden
\end{frame}
Ich möchte den Ansatz allgemeiner gestalten. Daher dachte ich über die Möglichkeit nach,
- [einen Satz von] Tags bei der Frame-Definition zuordnen
- Entscheiden Sie später (auf irgendeine Weise) über den zu verwendenden Tag-Satz beim Kompilieren der Präsentation, sodass nur die Frames mit diesem Tag berücksichtigt werden (und die anderen somit ausgeblendet werden).
Kennt jemand eine Möglichkeit, das zu tun?
Antwort1
Das ist eine wirklich schöne Frage!
Dies ist der Beginn einer Lösung, die stark inspiriert ist vonKommentar von Wernerund mit wenigen Einschränkungen. Diese sind auf die Tatsache zurückzuführen, dass die Lösung auf Beamer basiert. Aus diesem Grund kennzeichne ich es als Community-Wiki und jeder kann es verbessern (und es gibt viel Raum dafür).
Es bietet eine einfache Benutzeroberfläche mit dem Ziel,
- Erstellen von Tags zur Unterscheidung der Version(en);
- Entscheiden, welche Version(en) ausgegeben werden.
Die erste Aufgabe übernehmen die Tasten
create new version
create multiple versions
und die Namen sind ziemlich klar. Um zu entscheiden, welche Frames ausgegeben werden, nutzen Sie:
compile version
compile frames
um eine Teilmenge von Frames innerhalb einer Version auszuwählencompile generic frames
um Frames aus verschiedenen Versionen auszuwählen.
Wie gesagt, der Mechanismus ist in Werners Kommentar ziemlich genau beschrieben: Das Erstellen einer neuen Version bedeutet einfach, dass ein neuer Zähler (oder mehrere) instanziiert und jedes Mal aktualisiert wird, wenn ein Frame auf diese Weise markiert wird. Das Kompilieren von Versionen wird im Hintergrund durch die Erstellung einer Liste durchgeführt, die an übergeben wird \includeonlyframes
. So weit, so gut.
Sehen wir uns nun die Grenzen und Schwachstellen des Ansatzes an. Frames auf die oben beschriebene Weise zu taggen, ohne wirklich unter Beamer zu gehen, erfordert einen kleinen Trick, nämlich eine neue Umgebung. Zu diesem Zweck sebframe
wurde eine Umgebung definiert, die ein optionales Argument mit der folgenden Syntax akzeptiert
<tag>-<list of beamer options>
Das Zeichen -
dient dazu, den Tag von anderen Beamer-Optionen abzugrenzen; hier geht es übrigens mit daneben fragile
.
Das mwe. Es ist kommentiert und wird als Proof of Concept betrachtet: Ein paar Dinge können verbessert werden, wie die Kommentare zeigen.
\documentclass{beamer}
\usepackage{lmodern} % https://tex.stackexchange.com/a/58088/13304
\usepackage{mwe} % for dummy image
\newcommand{\enlarge}{\centering\scalebox{13}}% Just for this example
% = = = = = = = = = = = = = = = = = = = = = = = =
% core of the solution
\usepackage{pgffor,pgfkeys,xstring}
\newcommand{\deflistframes}[1]{
\gdef\listframes{}% global list
\foreach \x[count=\xi] in {#1}{\global\let\maxitems\xi}% count the max number of items
\foreach \x[count=\xi] in {#1}{
\ifnum\xi=\maxitems
\xdef\listframes{\listframes \vers\x}
\else
\xdef\listframes{\listframes \vers\x,}
\fi
}
}
\newcommand{\defcustomlistframes}[1]{
\gdef\listframes{}% global list
\foreach \x[count=\xi] in {#1}{\global\let\maxitems\xi}% count the max number of items
\foreach \x[count=\xi] in {#1}{
\ifnum\xi=\maxitems
\xdef\listframes{\listframes \x}
\else
\xdef\listframes{\listframes \x,}
\fi
}
}
\makeatletter
% https://tex.stackexchange.com/a/74890/13304
\newcommand{\defversion}[1]{\@namedef{vers#1}{}}
\makeatother
% test for multiple versions compilation
\newif\ifmultipleversion
\multipleversionfalse
\pgfkeys{/seb-beamer/.cd,
create new version/.code={\gdef\vers{#1}\newcounter{#1}},
create multiple versions/.code={%
\gdef\listofversions{}
\foreach \v in {#1}{%
\defversion{\v}
\newcounter{\v}
\xdef\listofversions{\listofversions \v,}
}%
\multipleversiontrue
},
compile version/.code={% version-based: need to store in .aux a
% "total frame" counter per version (incremented in custom enviroment)
% and use it as final value (hard-coded here for simplicity)
\deflistframes{1,...,1000}
% list of frames in output
\expandafter\includeonlyframes\expandafter{\listframes}%
},
compile frames/.code={% this should be version-based -> second argument (TBA)
\deflistframes{#1}
% for the list
\expandafter\includeonlyframes\expandafter{\listframes}%
},
compile generic frames/.code={% generic for multi version compilations
\defcustomlistframes{#1}
% list of frames in output
\expandafter\includeonlyframes\expandafter{\listframes}%
},
}
\makeatletter
% see: https://tex.stackexchange.com/a/132411/13304
\newenvironment{sebframe}[1][]{
% cut the string to separate version from other options
\StrCut{#1}{-}\compvers\opt
\edef\seboptions{\opt}
\def\mylabel{}
\ifmultipleversion
\@ifundefined{c@\compvers}{}{% test if the counter is undefined
\stepcounter{\compvers}
% increment here the counter total frames per version
\edef\mylabel{label=\compvers\the\value{\compvers}}
}
\else
\IfStrEq{\vers}{\compvers}{% true
\stepcounter{\compvers}
% increment here the counter total frames per version
\edef\mylabel{label=\compvers\the\value{\compvers}}
}{% false
\edef\mylabel{}
}
\fi
\begingroup\edef\x{\endgroup\noexpand\begin{frame}[\mylabel,\seboptions]}\x}{\end{frame}}
\makeatother
\newcommand{\SebCompileOptions}[1]{%
\pgfkeys{/seb-beamer/.cd,#1}
}
% = = = = = = = = = = = = = = = = = = = = = = = =
% user interface
%\SebCompileOptions{create new version=A, compile version=A}
%\SebCompileOptions{%
% create multiple versions={A,B},
% compile generic frames={A1,A3,B1,B2,C3}
%}
\SebCompileOptions{create new version=C, compile frames={1,3}}
\begin{document}
\begin{sebframe}[A-t,allowframebreaks]
\frametitle{Version A}
\enlarge{A1}
\end{sebframe}
\begin{sebframe}[B]
\frametitle{Version B}
\enlarge{B1}
\end{sebframe}
\begin{sebframe}[C]
\frametitle{Version C}
\enlarge{C1}
\end{sebframe}
\begin{sebframe}[A]
\frametitle{Version A}
\enlarge{A2}
\end{sebframe}
\begin{sebframe}[B]
\frametitle{Version B}
\enlarge{B2}
\end{sebframe}
\begin{sebframe}[C]
\frametitle{Version C}
\enlarge{C2}
\end{sebframe}
\begin{frame}
\frametitle{Version B or C}
\enlarge{BC}
\end{frame}
\begin{sebframe}[A-t,b,containsverbatim]% just to point out that passing multiple beamer options works (unless fragile)
\frametitle{Version A}
\enlarge{A3}
\end{sebframe}
\begin{sebframe}[C]
\frametitle{Version C}
\enlarge{C3}
\vskip1ex
\includegraphics<2>[scale=0.5]{example-image}
\end{sebframe}
\begin{sebframe}[A]
\frametitle{Version A}
\enlarge{A4}
\end{sebframe}
\begin{frame}[fragile,label=A5]% add manually a label: displayed only in A version though
\frametitle{Version A \& B \& C}
\enlarge{ABC}
\end{frame}
\end{document}
Wie wir ausgewählt haben:
\SebCompileOptions{create new version=A, compile version=A}
die Ausgabe ist:
Durch die Auswahl
\SebCompileOptions{create new version=C, compile frames={1,3}}
Beachten Sie, dass Overlay-fähige Befehle weiterhin funktionieren und Frame C2 nicht angezeigt wird. Versuchen wir
\SebCompileOptions{%
create multiple versions={A,B},
compile generic frames={A1,A3,B1,B2,C3}
}
was ergibt:
Da Version C nicht definiert ist, wird der Rahmen C3 erwartungsgemäß nicht angezeigt. Die Reihenfolge, in der die Liste bereitgestellt wird, hat keinen Einfluss auf die Reihenfolge des Erscheinens im PDF: Dafür zählen nur die Seitenzahlen.
Antwort2
Ich würde eine Reihe von Konditionalen erstellen, eine für jede Art von Präsentation, die Sie halten möchten. Nennen wir diese Typen „Versionen“. Vielleicht gibt es also VersionA
, VersionB
und VersionC
.
Erstellen Sie für jede Version eine Bedingung mit \newif
(standardmäßig ist sie auf „false“ gesetzt):
\newif\VersionA
\newif\VersionB
\newif\VersionC
Dann packen Sie Ihre Folien, die mit einer bestimmten Version verknüpft sind. Eine Folie würde frame
beispielsweise aussehenVersionA
\ifVersionA
\begin{frame}
...
\end{frame}
\fi
VersionB
Wenn Sie eine Folie haben, die mit (sagen wir) OR verknüpft werden soll VersionC
, dann können Sie Folgendes tun:
\makeatletter
\let\ifCombined\ifVersionB
\ifVersionC
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{\let\ifCombined\iftrue}{}
\makeatother
\ifCombined% Version B or C
\begin{frame}
..
\end{frame}
\fi
Die Folien, die in allen Versionen sichtbar sind, benötigen keine bedingte Umbruchfunktion. Hier ist ein minimales Beispiel für die Einrichtung:
\documentclass{beamer}% http://ctan.org/pkg/beamer
\let\Tiny=\tiny% http://tex.stackexchange.com/q/58087/5764
\newcommand{\enlarge}{\centering\scalebox{13}}% Just for this example
\newif\ifVersionA
\newif\ifVersionB
\newif\ifVersionC
%\VersionAtrue% Show Version A
\VersionBtrue% Show Version B
%\VersionCtrue% Show Version C
\begin{document}
\ifVersionA
\begin{frame}
\frametitle{Version A}
\enlarge{A1}
\end{frame}
\fi
\ifVersionB
\begin{frame}
\frametitle{Version B}
\enlarge{B1}
\end{frame}
\fi
\ifVersionC
\begin{frame}
\frametitle{Version C}
\enlarge{C1}
\end{frame}
\fi
\ifVersionA
\begin{frame}
\frametitle{Version A}
\enlarge{A2}
\end{frame}
\fi
\ifVersionB
\begin{frame}
\frametitle{Version B}
\enlarge{B2}
\end{frame}
\fi
\makeatletter
\let\ifCombined\ifVersionB
\ifVersionC
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{\let\ifCombined\iftrue}{}
\makeatother
\ifCombined% Version B or C
\begin{frame}
\frametitle{Version B or C}
\enlarge{BC}
\end{frame}
\fi
\ifVersionA
\begin{frame}
\frametitle{Version A}
\enlarge{A3}
\end{frame}
\fi
\ifVersionC
\begin{frame}
\frametitle{Version C}
\enlarge{C3}
\end{frame}
\fi
\ifVersionA
\begin{frame}
\frametitle{Version A}
\enlarge{A4}
\end{frame}
\fi
\begin{frame}
\frametitle{Version A \& B \& C}
\enlarge{ABC}
\end{frame}
\end{document}
Ähnliches können Sie mit demcomment
Paket. Allerdings ist das Kombinieren von Bedingungen nicht so einfach. Eine Problemumgehung wäre natürlich, Folien mit Informationen für mehrere Versionen zu duplizieren.
Eine weitere praktikable Option wäre die Erstellung eines label
für jedes frame
mithilfe von
\begin{frame}[label=ConceptX]
...
\end{frame}
oder mit dem \frame
Befehl. Und fügen Sie dann ConceptX
die Versionen hinzu, die Sie interessieren, einschließlich der Verwendung
\includeonlyframes{...,ConceptX,...}% Version A
frame
Dies erfordert allerdings, dass Sie jedem eine konzeptionelle (eindeutige) Bezeichnung geben .