Prueba de llamadas consecutivas a un entorno

Prueba de llamadas consecutivas a un entorno

Utilizo Beamer para hacer diapositivas para mi clase de estadística y ahora tengo una configuración muy buena que genera resultados similares a los de PowerPoint (consulte la pregunta:Utilice Beamer para colocar 3 diapositivas por página con notas al lado (como PowerPoint)).

Para que este sistema funcione, necesito una definición de las notas asociadas con una diapositiva para cada diapositiva o las notas no estarán sincronizadas con las diapositivas. Probablemente haya una mejor manera de definir una definición de nota "predeterminada" para una diapositiva para que nunca se desincronicen, pero esto está mucho más allá de mi capacidad en látex, y el entorno es lo suficientemente complicado como para publicar un MWE para eso. ser difícil (para mí).

En cambio, quiero al menos detectar el error de que no se han definido notas para una diapositiva. La forma más sencilla que se me ocurre de hacerlo se ha reducido a un MWE que se muestra a continuación:

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

PREGUNTA: ¿Cómo hago para que Latex arroje un error cuando detecta que no hubo ninguna llamada para mi página {3}? Para los programadores de C, sería fantástico mostrar cómo utilizar una afirmación de estilo C de que el parámetro no es igual al valor esperado.

Gracias a todos.

Respuesta1

No afirmar. Ni siquiera un !=. También hay \if, \ifdim, \ifx, \ifcase, \@ifundefined, \@ifl@adedetc. Consulte TeXbook (Knuth) y source2e.pdf (CTAN).

Tenga en cuenta que las definiciones locales no estarán disponibles fuera de un entorno. Afortunadamente, las contraoperaciones utilizan versiones globales. \global\lety \xdefse puede utilizar, pero \setlengthy \renewcommandno.

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

Respuesta2

Sugiero una solución diferente. Actualmente, esta es una prueba de concepto. En particular, fallará si pasa cualquier opción que no sea labella del frameentorno. Creo que esto se puede solucionar, pero complicaría las cosas.

La idea es incluir las diapositivas en el folleto de una manera diferente. Para ello se hace uso del paquete de Beamer beamerarticle, la labelopción de frameentornos y la \includeslidemacro. También usa xcoffins(porque me frustré demasiado jugando con minipagesy cosas similares) y environ.

Flujo de trabajo:

  • 3 archivos, 2 de los cuales son contenedores extremadamente simples que ingresan el tercero.

  • El tercer archivo no contiene archivos \documentclass, sino diapositivas y notas. Supongamos que esto es <main file name>.tex.

  • Los toboganes van en frameambientes, como es habitual. Estos están etiquetados usando la labelopción.

  • Las notas van en annotambientes. Estos requieren un argumento que proporcione la etiqueta de la diapositiva correspondiente. (Si normalmente te estuvieras refiriendo a la diapositiva, este es el argumento que darías \ref{}). Se puede usar un argumento opcional para anular la configuración utilizada al incluir la diapositiva.

  • El primer contenedor se compila para producir las diapositivas. Llamé a esto <main file name>-beamer.tex. El contenido de este archivo debe ser

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

    Esto debería ser compilado.primero.

  • El segundo envoltorio se compila para producir los folletos. Llamé a esto <main file name>-article.texporque usé la articleclase y el modo Beamer article. El contenido de este archivo debe ser

    \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
    

    Esto debería ser compilado.segundo.

Luego <main file name>.tex, colocas el resto del preámbulo y el documentcuerpo. Puse la mayoría de las cosas personalizadas en el preámbulo aquí, restringiéndolas al articlemodo Beamer, pero puedes mover esto al envoltorio del folleto si lo prefieres.

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

Esto sólo se ejecutará en articlemodo.

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

xcoffins, environ, pgfy calcson obligatorios. geometryAcabo de deshacerme de las cajas defectuosas.

Primero, un par de longitudes nuevas que necesitaremos más adelante.

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

Y un par de ataúdes.

  \NewCoffin\AnnotCoffin
  \NewCoffin\FrameCoffin

Ahora definimos el annotentorno, pero lo usamos \NewEnvironen lugar de \newenvironmentporque queremos poner todo el contenido en un ataúd y esto nos pareció más fácil. (Estaba tratando de evitar expl3la sintaxis` aquí).

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

Esto verifica si hay algún marco para el cual no hayamos incluido una diapositiva, aparte del de esta anotación. Si ha habido una etiqueta framea la que este conjunto de notas no corresponde, asumimos que ese marco no tiene notas y en su lugar lo generamos con un espacio en blanco a la derecha.

Ahora configuramos nuestro primer ataúd, \FrameCoffincon una copia enmarcada de la diapositiva relevante (es decir, a la que hicimos referencia usando el annotargumento obligatorio del entorno).

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

Ahora preparamos nuestro segundo ataúd, \AnnotCoffinpara las notas.

    \SetVerticalCoffin\AnnotCoffin{.5\linewidth-.5\annotsep}{%
      \BODY
    }%

Unimos los ataúdes en la parte superior, empujando los nodos un poco hacia arriba y hacia abajo.

    \JoinCoffins\FrameCoffin[t,r]\AnnotCoffin[t,l](\annotsep,-.5\baselineskip)

Componga nuestros ataúdes y deje un espacio vertical flexible para que nuestras diapositivas queden espaciadas uniformemente en la página.

    \TypesetCoffin\FrameCoffin
    \medskip\vfill\par
  }
  \usepackage{kantlipsum}

Este paquete es sólo para el ejemplo. No cargue esto en su documento real a menos que esté escribiendo los extractos relevantes de Kant y no le importe la traducción probablemente desactualizada.

Un par de comandos nuevos.

  \newcommand\extractref{}
  \newcommand\extractedref{}

Defina uno de ellos como macro auxiliar.

  \def\extractref label=#1\null{#1}

Esto cambia la definición de modo frameen article. Normalmente, Beamer compone el framecontenido en todos los modos. Sin embargo, aquí no queremos eso. Lo definimos para que tome un único argumento opcional. Todo lo demás desaparecerá. Pero, si hay un primer argumento opcional y no está vacío, asumiremos que es a label=<key for label>y extraeremos esta referencia.

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

Si la macro que mantiene el seguimiento \extractedrefno está vacía, entonces ha habido una diapositiva sin un conjunto de notas correspondiente, por lo que asumimos que la diapositiva no tiene notas y generamos esa diapositiva con un conjunto de notas en blanco a la derecha.

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

Por el momento frame, no escribimos nada. Simplemente extraemos y almacenamos la referencia en formato \extractedref.

    \fi
  }

Ahora para la macro que genera frames sin anotaciones. Esto es utilizado por los redefinidos framey los annotentornos.

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

Aquí no se necesitan ataúdes, pero generamos la diapositiva usando la configuración predeterminada y colocamos el mismo espacio vertical para mantener las diapositivas distribuidas uniformemente en la página.

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

Supongo que no quieres sangría de párrafo aquí. Podrías considerar usar el parskippaquete, pero puede que esto no importe, dependiendo del contenido de tus notas.

  \setlength\parindent{0pt}

Si lo último frameestá etiquetado pero sin notas, debemos asegurarnos de que se incluya en el folleto. Uno más \outputemptydebería hacerlo.

  \AtEndDocument{\outputempty}

Esa es la configuración. Ahora el documento.

\begin{document}

Aquí hay un marco, etiquetado frame-a.

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

Aquí están las notas para frame-a.

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

De manera similar, para frame-by 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}

Esto crea una página con geometryel diseño predeterminado.

Aquí está frame-another. Este carece de notas, por lo que no hay annotseguidores.

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

En articlemodo, se generará el siguiente cuadro frame-another, porque asumiremos que no existen notas para ese frame. Se me acabaron las imágenes de MWE y me aburrí, así que aquí tengo una excelente alternativa.

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

El siguiente frametiene una nota muy larga, por lo que terminará en su propia página. Un poco menos de rugido aquí, pero quizás haya seguridad en los números.

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

Y un último, sin mencionar frame, para asegurarnos de que el final \outputemptyfuncione.

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

\end{document}

Diapositivas:

diapositivas

Folleto/notas:

folleto con notas

Código completo (necesita sustitución de nombres de archivos donde se indique):

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

información relacionada