我使用 beamer 为我的统计课制作幻灯片,现在有一个非常好的设置,可以生成类似于 powerpoint 的输出(参见问题:使用 Beamer 每页放置 3 张幻灯片,并在旁边添加注释(类似 powerpoint))。
要使该系统正常工作,我需要为每张幻灯片定义与幻灯片相关的注释,否则注释将与幻灯片不同步。可能有更好的方法来为幻灯片定义“默认”注释定义,以便它们永远不会不同步,但这远远超出了我在 latex 中的能力,而且环境非常复杂,因此发布 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}
问题:当检测到没有调用 mypage {3} 时,如何让 latex 抛出错误?对于 c 程序员来说,展示如何使用 c 风格的断言参数不等于预期值会很棒!
谢谢大家。
答案1
没有断言。甚至没有!=
。还有\if
,,,,,,等等。请参阅 TeXbook (Knuth) 和 source2e.pdf (CTAN \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
东西感到太沮丧了)和。minipage
environ
工作流程:
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}
xcoffins
、、environ
和pgf
是calc
必需的。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
这改变了模式下的定义article
。通常,Beamer 会frame
在所有模式下排版内容。但是,我们在这里不希望这样。我们将其定义为接受单个可选参数。其他所有内容都会消失。但是,如果有一个可选的第一个参数并且它不为空,我们将假定它是,label=<key for label>
并且我们将提取此引用。
\RenewEnviron{frame}[1][]{%
\edef\tempa{#1}\edef\tempb{}%
\ifx\tempa\tempb\relax
\else
\outputempty
如果保持跟踪的宏\extractedref
不为空,则说明存在一张没有相应注释的幻灯片,因此我们假设该幻灯片没有注释,并在右侧输出带有一组空白注释的幻灯片。
\xdef\extractedref{\extractref #1\null}%
对于当前的frame
,我们不排版任何内容。我们只是提取并存储 中的引用\extractedref
。
\fi
}
现在来看看输出不带注释的 s 的宏。这由重新定义和环境frame
使用。frame
annot
\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-b
和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}
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}