測試對環境的連續調用

測試對環境的連續調用

我使用投影機為我的統計課程製作幻燈片,並且現在有一個非常好的設置,可以產生類似於 powerpoint 的輸出(請參閱問題:使用 Beamer 每頁放置 3 張投影片,並在旁邊加入註解(如 powerpoint))。

為了使該系統正常運作,我需要為每張投影片與投影片關聯的註解進行定義,否則註解將與投影片不同步。可能有更好的方法來定義幻燈片的「預設」註釋定義,以便它們永遠不會不同步,但這遠遠超出了我在乳膠中的能力,而且環境足夠複雜,為此發布 MWE 會很難(對我來說)。

相反,我至少想捕獲沒有為幻燈片定義註釋的錯誤。我能想到的最簡單的方法已簡化為如下所示的 MWE:

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

問題:當 Latex 偵測到沒有呼叫 mypage {3} 時,如何讓 Latex 拋出錯誤?對於 C 程式設計師來說,展示如何使用 C 風格的斷言來判斷參數不等於預期值會很棒!

謝謝大家。

答案1

沒有斷言。甚至沒有!=。還有\if\ifdim\ifx\ifcase\@ifundefined\@ifl@aded等。

請注意,本地定義在環境外部不可用。幸運的是,計數器操作使用全域版本。 \global\let\xdef可以使用,但是\setlength\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}

答案2

我建議一個不同的解決方案。目前這是一個概念驗證。特別是,如果您將任何選項傳遞label給環境以外的選項,它將失敗frame。我認為這個問題可以解決,但這會使事情變得複雜。

我們的想法是以不同的方式將幻燈片納入講義中。這利用了 Beamer 的beamerarticle套件、環境label選項frame\includeslide巨集。它也使用(因為我對s 之類的xcoffins事情感到太沮喪)和.minipageenviron

工作流程:

  • 3 個文件,其中 2 個是非常簡單的包裝器,輸入第三個文件。

  • 第三個文件不包含\documentclass,但包含投影片和註釋。假設這是<main file name>.tex.

  • 像往常一樣,幻燈片進入frame環境。這些是使用選項標記的label

  • 筆記放在annot環境中。這些需要一個參數來給出相應幻燈片的標籤。 (如果您通常會引用投影片,這就是您給的參數\ref{}。)可選參數可用於覆寫包含投影片時使用的設定。

  • 第一個包裝器被編譯以產生幻燈片。我叫這個<main file name>-beamer.tex。該文件的內容應該是

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

    這應該編譯第一的

  • 第二個包裝器被編譯以產生講義。我這樣稱呼是<main file name>-article.tex因為我使用了article類別和Beamer的article模式。該文件的內容應該是

    \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
    

    這應該編譯第二

然後<main file name>.tex,您將其餘的序言和正文放入其中document。我將大部分自訂內容放在此處的序言中,將其限制為 Beamerarticle模式,但如果您願意,可以將其移至講義包裝中。

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

這只會在article模式下執行。

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

xcoffinsenvironpgfcalc為必填項。geometry剛剛擺脫了壞盒子。

首先,我們稍後需要幾個新的長度。

  \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

現在我們定義annot環境,但我們使用\NewEnviron而不是\newenvironment因為我們想將整個內容放入棺材中,這似乎是最簡單的。 (我試圖expl3在這裡避免語法。)

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

這會檢查除了此註釋的幀之外是否還有我們未為其放入投影片的幀。如果有一個標籤frame與這組註釋不對應,我們假設該框架沒有註釋,並在右側輸出一個空格。

現在,我們設定了我們的第一個棺材,帶有相關幻燈片的裱框副本(即我們使用環境的強制參數\FrameCoffin引用的那個)。annot

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

現在我們安置第二口棺材,\AnnotCoffin用來存放筆記。

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

frame這改變了in模式的定義article。通常,Beamer 會frame在所有模式下排版內容。然而,在這裡我們不希望這樣。我們將其定義為採用單一可選參數。其他一切都會消失。但是,如果有一個可選的第一個參數並且它不為空,我們將假設它是 alabel=<key for label>並且我們將提取此引用。

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

如果巨集 keep trac\extractedref不為空,則表示存在一張沒有相應註釋集的投影片,因此我們假設該投影片沒有註釋,並在右側輸出帶有一組空白註釋的投影片。

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

目前frame,我們沒有排版任何內容。我們只需提取引用並將其存儲在\extractedref.

    \fi
  }

現在是輸出沒有註解的 s 的巨集frame。這是由重新定義frameannot環境使用的。

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

這裡不需要棺材,但我們使用預設配置輸出幻燈片,並放入相同的垂直空間,以保持幻燈片均勻地分佈在頁面上。

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

我猜你不希望這裡有段落縮排。您可能會考慮使用該parskip包,但這可能並不重要,具體取決於您的筆記內容。

  \setlength\parindent{0pt}

如果最後一個frame有標籤但沒有註釋,我們需要確保它進入講義。還\outputempty應該再做一個。

  \AtEndDocument{\outputempty}

這就是配置。現在來看文檔。

\begin{document}

這是一個框架,標記為frame-a

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

以下是 的註解frame-a

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

同樣,對於frame-bframe-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}

geometry這將創建一個具有預設佈局的頁面。

這裡是frame-another.這個沒有註釋,所以沒有annot後續。

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

article模式下,下一幀將被frame-another輸出,因為我們假設該幀不存在註釋frame。我已經用完了 MWE 的圖像,並且對此感到厭倦,所以這裡有一個很棒的替代方案。

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

下一個frame有一個很長的註釋,因此將在其自己的頁面上結束。這裡少了一點咆哮,但人數眾多也許是安全的。

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

最後一點,值得注意的是frame,確保決賽\outputempty能發揮作用。

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

\end{document}

幻燈片:

幻燈片

講義/註釋:

帶筆記的講義

完整程式碼(需要替換指定的檔案名稱):

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

相關內容