タグに基づいて LaTeX ビーマー フレームを動的に非表示にする

タグに基づいて LaTeX ビーマー フレームを動的に非表示にする

私は、多くの人にピンとくる構成になっていると思います。何年も実行されているプロジェクトの一環として、多数のスライドを含む非常に大規模な Beamer プレゼンテーションを開発しました。LaTeX ソースは多数のファイルに分割されており、プロジェクトのプレゼンテーションを頻繁にやり直す必要があるため、時間や対象者に応じてこれらのファイルをメイン ドキュメントに含めるか含めないかを決めています。

ここで、含めたいフレームを制御することで、プレゼンテーションの生成を何らかの方法で自動化したいと思います。<handout:0|beamer:0>フレーム定義のパラメータを使用して静的に実行できるようです。

\begin{frame}
Hello.
\end{frame}

% this frame won't be included
\begin{frame}<handout:0|beamer:0>
  Hidden
\end{frame}

私は、このアプローチをより一般的なものにしたいと考えていました。そこで、

  • フレーム定義にタグのセットを関連付ける
  • プレゼンテーションをコンパイルするときに使用するタグのセットを後で (何らかの方法で) 決定し、このタグを持つフレームのみが考慮され、他のフレームは非表示になるようにします。

誰かそれを実行する方法を知っていますか?

答え1

これは本当にいい質問ですね!

これは、ヴェルナーのコメント制限はほとんどありません。これらの制限は、ソリューションが Beamer の上にあるという事実によるものです。このような理由から、私はこれをコミュニティ wiki としてマークし、誰でも改善できるようにしました (そして、改善の余地はたくさんあります)。

シンプルなユーザーインターフェースを提供し、

  • 区別するバージョンのタグを作成する。
  • どのバージョンを出力するかを決定します。

最初のタスクはキーによって提供される

  1. create new version
  2. create multiple versions

名前は非常に明確です。どのフレームを出力するかを決定するには、以下を利用します。

  1. compile version
  2. compile frames1つのバージョン内のフレームのサブセットを選択する
  3. compile generic frames異なるバージョンからフレームを選択します。

すでに述べたように、メカニズムは Werner のコメントでほぼ説明されています。新しいバージョンを作成するということは、フレームがそのようにタグ付けされるたびに、新しいカウンター (またはそれ以上) がインスタンス化され、更新されることを意味します。バージョンのコンパイルは、 に渡されるリストの作成によって、舞台裏で実行されます\includeonlyframes。ここまでは順調です。

ここで、このアプローチの限界と弱点を見てみましょう。Beamerの真下を通らずに前述の方法でフレームにタグを付けるには、ちょっとしたトリック、つまり新しい環境が必要です。この目的のために、sebframe次の構文でオプションの引数を受け入れる環境が定義されています。

<tag>-<list of beamer options>

文字は、-タグを他の Beamer オプションから分離するために使用されます。ちなみに、これは と一致しませんfragile

mwe。これはコメントされており、概念実証として受け止めてください。コメントで指摘されているように、いくつかの点は改善できます。

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

私たちが選択したもの:

\SebCompileOptions{create new version=A, compile version=A}

出力は次のようになります。

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

選択することで

\SebCompileOptions{create new version=C, compile frames={1,3}}

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

オーバーレイ対応コマンドがまだ機能し、フレームC2が表示されていないことに注意してください。試してみましょう。

\SebCompileOptions{%
 create multiple versions={A,B}, 
 compile generic frames={A1,A3,B1,B2,C3}
}

これにより、次のようになります。

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

予想どおり、バージョン C が定義されていないため、フレーム C3 は表示されません。リストを提供する順序は、PDF での表示順序には影響しません。ページ番号のみがカウントされます。

答え2

プレゼンテーションの種類ごとに 1 つずつ、一連​​の条件文を作成します。これらのタイプを「バージョン」と呼びましょう。つまり、 、VersionAVersionBがある可能性がありますVersionC

各バージョンについて、次を使用して条件を作成します\newif(デフォルトでは false に設定されています)。

\newif\VersionA
\newif\VersionB
\newif\VersionC

次に、特定のバージョンに関連付けられたスライドをラップしますframe。たとえば、VersionAスライドは次のようになります。

\ifVersionA
\begin{frame}
  ...
\end{frame}
\fi

VersionB(例えば) ORに関連付けるスライドがある場合はVersionC、次のようにします。

\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

すべてのバージョンで表示されるスライドには、条件付きラッピングは必要ありません。以下に、最小限の設定例を示します。

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

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

同様のことをするには、commentパッケージただし、条件を組み合わせるのはそれほど簡単ではありません。もちろん、回避策としては、複数のバージョンの情報を含むスライドを複製することが考えられます。

もう一つの実現可能な選択肢は、labelfor eachframeを使用して

\begin{frame}[label=ConceptX]
  ...
\end{frame}

または\frameコマンドを使用します。そして、ConceptX興味のあるバージョンに以下を追加します。

\includeonlyframes{...,ConceptX,...}% Version A

frameただし、それぞれに概念的な(一意の)ラベルを付ける必要があります。

関連情報