Cómo almacenar de forma sólida fragmentos de texto para su uso posterior

Cómo almacenar de forma sólida fragmentos de texto para su uso posterior

Estoy intentando escribir un paquete, similar al paquete de ejercicios, para poder preparar conjuntos de problemas para mis alumnos. Deseo retrasar la publicación de los problemas y/o soluciones hasta que se haya alcanzado un lugar adecuado en el documento. Tengo algo que funciona pero es un poco torpe. Por ejemplo, esto funciona bastante bien:

\usepackage{environ}
\NewEnviron{testb}{\global\expandafter\let\csname bar\endcsname\BODY}

Lo uso \csnameporque los nombres se generan dinámicamente. Esto no funciona tan bien si el comando no es \BODY. Por ejemplo, si lo hago \let\bar{\BODY}, el látex tiene un aneurisma (se une \barsolo a {).

Existe una forma alternativa de hacer esto, que es:

\NewEnviron{testc}{\global\expandafter\edef\csname foo\endcsname{\BODY}}

Este tipo de obras. Lo siguiente funciona: \begin{testc}hi\end{testc}, pero esto le da a LaTeX un aneurisma: \begin{testc}\bf hi\end{testc}. (El mensaje de error es \incomplete). Intenté depurarlo yo mismo pero me enredo irremediablemente en paquetes que no entiendo. Si lo hace en \tinylugar de, \bfobtendrá el mensaje de error de LaTeX tremendamente diferente:! TeX capacity exceeded, sorry [input stack size=5000].

¿Cómo puedo guardarlo para más adelante, no solo \BODY, sino también para alguna combinación sofisticada de \BODYy otras cosas, y al mismo tiempo tenerlo sólido para lo que hay entre el principio y el final?

Editar: ok, varias soluciones a continuación

Respuesta1

Con \unexpandedpodrás evitar preocuparte \protected@xdef.

\documentclass{article}
\usepackage{environ}

\NewEnviron{exercise}{%
  \xdef\savedexercises{%
    \unexpanded\expandafter{\savedexercises}%
    \noexpand\begin{printedexercise}%
    \unexpanded\expandafter{\BODY}%
    \noexpand\end{printedexercise}%
  }%
}
\newcommand{\printexercises}{%
  \savedexercises
  \gdef\savedexercises{}%
}
\newcommand{\savedexercises}{}

\newtheorem{printedexercise}{Exercise}

\begin{document}

Here we talk about addition and show that $1+1=2$.

\begin{exercise}
Compute $1+2$
\end{exercise}

Here we talk about integrals.

\begin{exercise}
Compute the following integrals:
\begin{itemize}
\item $\displaystyle\int_0^x e^{-t^2}\,dt$

\item $\displaystyle\int_1^x \frac{e^t}{t}\,dt$, for $t>0$.
\end{itemize}
\end{exercise}

Now we can print the exercises.

\printexercises

\end{document}

Lo usé \newtheoremsolo para el ejemplo.

ingrese la descripción de la imagen aquí

Con xparselanzamiento el 2019-03-05 o posterior:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentEnvironment{exercise}{+b}
 {
  \tl_gput_right:Nn \g_loisel_exercises_tl
   {
    \begin{printedexercise}
    #1
    \end{printedexercise}
   }
 }{}

\NewDocumentCommand{\printexercises}{}
 {
  \tl_use:N \g_loisel_exercises_tl
  \tl_gclear:N \g_loisel_exercises_tl
 }

\tl_new:N \g_loisel_exercises_tl

\ExplSyntaxOff

\newtheorem{printedexercise}{Exercise}

\begin{document}

Here we talk about addition and show that $1+1=2$.

\begin{exercise}
Compute $1+2$
\end{exercise}

Here we talk about integrals.

\begin{exercise}
Compute the following integrals:
\begin{itemize}
\item $\displaystyle\int_0^x e^{-t^2}\,dt$

\item $\displaystyle\int_1^x \frac{e^t}{t}\,dt$, for $t>0$.
\end{itemize}
\end{exercise}

Now we can print the exercises.

\printexercises

\end{document}

Respuesta2

Si desea BODYguardarlo, agregue cosas dinámicamente; probablemente sea mejor usar dos macros:

\documentclass{article}
\usepackage{environ}
\NewEnviron{testb}{%
  \global\expandafter\let\csname bar\endcsname\BODY
  \expandafter\xdef\csname barplus\endcsname{%
    \expandafter\noexpand\csname bar\endcsname
    \noexpand\bf Hi
  }%
}
\begin{document}

\begin{testb}
  \bfseries
  Hi
\end{testb}
\show\barplus
\end{document}

Si quieres evitar el uso, \BODYpuedes usarxparse

\documentclass{article}
\usepackage{xparse}
\NewDocumentEnvironment{testb}{+b}{\expandafter\gdef\csname bar\endcsname{#1}}{}
\begin{document}

\begin{testb}
  \bfseries
  Hi
\end{testb}
\show\bar
\end{document}

Respuesta3

Un truco para activar la expansión es usar \romannumeral:

Cuando debido a \romannumeral(La)TeX reúne una secuencia de dígitos seguidos por un espacio como el número que tiene que convertir, los tokens expandibles se expanden.

Cuando al final se reúne un número que no es positivo, como resultado de la conversión (La)TeX no entregará ningún token.

Por lo tanto, uno puede usar muy bien (¿ab?) \romannumeralpara desencadenar una gran cantidad de trabajo de expansión y cambiar argumentos, siempre y cuando se asegure de que al final \romannumeralno encontrará un número positivo.

He aquí una variante dela respuesta de egregque hace con \romannumeraly \exchangeen lugar de \xdefy \unexpanded.

\documentclass{article}
\usepackage{environ}

\newcommand\exchange[2]{#2#1}

\NewEnviron{exercise}{%
  \expandafter\gdef\expandafter\savedexercises\expandafter{%
    \romannumeral0\expandafter\exchange\expandafter{\BODY}{%
      \exchange{ }{\expandafter}\savedexercises
      \begin{printedexercise}%
    }%
    \end{printedexercise}%
  }%
}
\newcommand{\printexercises}{%
  \savedexercises
  \gdef\savedexercises{}%
}
\newcommand{\savedexercises}{}

\newtheorem{printedexercise}{Exercise}

\begin{document}

Here we talk about addition and show that $1+1=2$.

\begin{exercise}
Compute $1+2$
\end{exercise}

Here we talk about integrals.

\begin{exercise}
Compute the following integrals:
\begin{itemize}
\item $\displaystyle\int_0^x e^{-t^2}\,dt$

\item $\displaystyle\int_1^x \frac{e^t}{t}\,dt$, for $t>0$.
\end{itemize}
\end{exercise}

Now we can print the exercises.

\printexercises

\end{document}

ingrese la descripción de la imagen aquí

Si desea envolver el nombre de la macro que se va a definir en \csname.. \endcsname, es decir, si desea utilizarlo \csname savedexercises\endcsnameen lugar de \savedexercises, puede aprovechar el hecho de que (La)TeX expande los tokens expandibles mientras reúne \csnameel nombre de un token de secuencia de control y buscando la coincidencia \endcsname:

\documentclass{article}
\usepackage{environ}

\newcommand\exchange[2]{#2#1}

\NewEnviron{exercise}{%
  \expandafter\gdef\csname savedexercises\expandafter\endcsname\expandafter{%
    \romannumeral0\expandafter\exchange\expandafter{\BODY}{%
      \exchange{ }{\expandafter\expandafter\expandafter}\csname savedexercises\endcsname
      \begin{printedexercise}%
    }%
    \end{printedexercise}%
  }%
}
\newcommand{\printexercises}{%
  \csname savedexercises\endcsname
  \expandafter\gdef\csname savedexercises\endcsname{}%
}
\expandafter\newcommand\expandafter{\csname savedexercises\endcsname}{}

\newtheorem{printedexercise}{Exercise}

\begin{document}

Here we talk about addition and show that $1+1=2$.

\begin{exercise}
Compute $1+2$
\end{exercise}

Here we talk about integrals.

\begin{exercise}
Compute the following integrals:
\begin{itemize}
\item $\displaystyle\int_0^x e^{-t^2}\,dt$

\item $\displaystyle\int_1^x \frac{e^t}{t}\,dt$, for $t>0$.
\end{itemize}
\end{exercise}

Now we can print the exercises.

\printexercises

\end{document}

ingrese la descripción de la imagen aquí

Tenga en cuenta que con los enfoques presentados hasta ahora no puede utilizarlos \printexercisespara que los ejercicios se realicen en lugares arbitrarios. Puede hacer que los ejercicios se realicen sólo en lugares del documento que en la fuente corresponden a lugares detrás de los entornos de ejercicio.

Quizás un entorno que lea su contenido bajo el régimen verbatim-catcode-régime para escribirlo sin expandir en un archivo .aux de manera que desde el archivo .aux se vuelva a leer bajo el régimen verbatim-catcode también para definir una macro donde \scantokensse aplicará y, por lo tanto, algún tipo de reimplementación del \label- \ref-mecanismo o del \tableofcontents-mecanismo para material textual podría hacer posible hacer ejercicios imprimibles en todo el documento.

Implementar un mecanismo de este tipo podría ser un gran desafío. Pero antes de tomar eso en consideración, se necesita información exacta sobre el uso previsto y la "interfaz de usuario" deseada, es decir, qué cosas adicionales desea poder especificar, de qué manera, etc.

Respuesta4

Otra variante, usando filecontentsdef v1.4, admite verbatimcontenido (si es necesario).

\documentclass{article}
\usepackage{filecontentsdef,pgffor}
\setlength{\parindent}{0pt}
\pagestyle{empty}
\newtheorem{exercise}{Exercise}
% savedexercise
\newcounter{exeNr}
\newenvironment{savedexercise}
{\stepcounter{exeNr}%
\begingroup
\filecontentsdefmacro{exercise-\the\value{exeNr}}}%
{\endfilecontentsdefmacro\endgroup}
\newcommand{\printexercise}[1]{\filecontentsexec{exercise-\the\numexpr#1\relax}}
\newcommand{\printsrcexercise}[1]{\filecontentsprint{exercise-\the\numexpr#1\relax}}

\begin{document}
\section{Talk about math}
Here we talk about addition and show that $1+1=2$.

\begin{savedexercise}
Compute $1+2$
\end{savedexercise}

Here we talk about integrals.

\begin{savedexercise}
Compute the following integrals:
\begin{itemize}
\item $\displaystyle\int_0^x e^{-t^2}\,dt$

\item $\displaystyle\int_1^x \frac{e^t}{t}\,dt$, for $t>0$.
\end{itemize}
\end{savedexercise}

\section{The exercises}
Now we can print the exercises.

\foreach \i in {1,...,2} {
\begin{exercise}
\printexercise{\i}
\end{exercise}
}

\section{The src exercises}
Now we can print the src of exercises.

\foreach \i in {1,...,2} {
\printsrcexercise{\i}
}

\section{Back to first exercises}
Remember the first exercise

\setcounter{exercise}{0}
\begin{exercise}
\printexercise{1}
\end{exercise}
\end{document}

Ejemplo del resultado obtenido

información relacionada