基於標籤動態隱藏 LaTeX Beamer 框架

基於標籤動態隱藏 LaTeX Beamer 框架

我想我所處的配置會給很多人敲響警鐘:在一個運行多年的專案背景下,我開發了一個非常大的 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 之上。出於這樣的原因,我將其標記為社區維基,每個人都可以改進它(並且有很大的空間)。

它提供了一個簡單的使用者介面,目的是

  • 為區分版本建立標籤;
  • 決定輸出哪個版本。

第一個任務由按鍵提供

  1. create new version
  2. create multiple versions

而且名字也很清楚。要決定輸出哪些幀,請利用:

  1. compile version
  2. compile frames選擇一個版本中的幀子集
  3. compile generic frames從不同版本中選擇框架。

如前所述,Werner 的評論中對該機制進行了詳細描述:創建新版本僅意味著每次以這種方式標記幀時都會實例化並更新一個新計數器(或更多)。編譯版本是在幕後透過建立傳遞給 的清單來進行的\includeonlyframes。到目前為止,一切都很好。

現在讓我們來看看該方法的限制和周點。以上述方式標記幀而不真正在 Beamer 下進行,需要一些技巧,即新環境。為此,sebframe定義了一個環境,​​它接受具有以下語法的可選參數

<tag>-<list of beamer options>

該字元-用於將標籤與其他Beamer選項分開;順便說一句,這錯過了fragile.

姆韋。它被評論並將其作為概念證明:正如評論指出的那樣,有一些事情可以改進。

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

在此輸入影像描述

請注意,overleyed-aware 命令仍然有效,並且不會顯示幀 C2。讓我們嘗試一下

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

其產生:

在此輸入影像描述

如所料,由於版本 C 未定義,因此不顯示幀 C3。提供清單的順序不會影響 PDF 中的顯示順序:僅頁碼有效。

答案2

我會創建一堆條件,每個條件對應您想要提供的每種類型的演示。我們將這些類型稱為「版本」。所以,也許有VersionAVersionBVersionC

對於每個版本,使用以下命令建立一個條件\newif(預設情況下它們設定為 false):

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

frame然後,包裝與特定版本相關的幻燈片。例如,VersionA幻燈片類似於

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

如果您有一張投影片應該與(例如)VersionBOR相關聯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包裹。然而,組合條件卻不那麼容易。當然,解決方法是複製包含多個版本資訊的幻燈片。

另一個可行的選擇是label為每個frame使用創建一個

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

或使用\frame命令。然後添加ConceptX到您感興趣的版本,包括使用

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

但這需要您為每個標籤提供frame一個概念性(唯一的)標籤。

相關內容