4

Is there a way to store the text between the \begin and \end commands of a generic environment in an array?

A code that obviously doesn't work but shows what I mean is the following

\documentclass{memoir}
\usepackage{arrayjobx}
\newarray\entry
\newnvironment{mycenter}{\begin{center}\entry{0}={}{}\end{center}} % \entry{0} should be the text between \begin{mycenter} and \end{mycenter}
\begin{document}
\begin{mycenter}
This line is centered.
\end{mycenter}
\entry{0} % \entry{0} should be 'This line is centered'
\end{document}

Here I used the environment mycenter based on center, but the specific environment doesn't really matter, I just used it as an example.

Edit: I tried using the environ package as suggested by David Carlisle but I think I'm missing something here.

The edited code is

\documentclass{memoir}
\usepackage{arrayjobx, environ}
\newarray\entry
\NewEnviron{mycenter}{\entry(0)={\BODY}\begin{center}\BODY\end{center}}
\begin{document}
\begin{mycenter}
This line is centered.
\end{mycenter}
\entry(0)
\end{document}

which still doesn't compile. What am I doing wrong?

7
  • you can use the environ (or newenviron) packages to grab the content of the environment as a macro. (tex doesn't really have arrays, so it's not clear if the array-like syntax of the arrayjobx package really helps here, it would be simpler and considerably more efficient to handle the macro storage direct;y) but it depends what you want to do with the stored values. Commented Feb 1, 2019 at 14:04
  • Indeed, it would be much better to know what you want to use the stored values for.
    – egreg
    Commented Feb 1, 2019 at 14:26
  • I'm making a list of theorems, I want to store the value of each theorem thesis, i.e. the text between \begin{thm} and \end{thm} in an array and use a forloop to build the list once I have all the theorems. So in short, the values of the array will be texts. I'm aware that thmtools offers a \listoftheorems command, but that's now what I'm looking for. @DavidCarlisle could you show me how to use the environ (or newenviron) packages to do that?
    – noibe
    Commented Feb 1, 2019 at 14:45
  • I don't see how the array syntax helps, unless you want random access, eg to refer to item 42 without accessing item 41 first, but also here you are defining a new environment mycenter so you could define it with \NewEnviron instead which would give you the content as \BODY but it's rather different if you want to do similar with theorems which you are presumably defining already with a custom \newtheorem declaration. Commented Feb 1, 2019 at 14:50
  • @DavidCarlisle that's true but the workaround is immediate: let's say I have something like \newtheorem{mythm}{some code}, then I can define a new environment \newenvironment{thm}{\begin{mythm}}{\end{mythm}}.
    – noibe
    Commented Feb 1, 2019 at 15:44

1 Answer 1

5

Definitely not a simple task.

\documentclass{article}
\usepackage{amsmath}
\usepackage{amsthm}
\usepackage{environ}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\newtheoremx}{momo}
 {
  % * Let's duplicate the working of \newtheorem; \newtheoremx should
  %   be used for theorems that need to be listed
  % * \newtheoremx{theorem}{Theorem} will actually do
  %   \newtheorem{theorem@inner}{Theorem} (honoring the usual optional arguments)
  % * We also need a property list to store along with the theorem
  %   the one which it is subordinate to
  \IfValueTF{#2}
   {
    \newtheorem{#1@inner}[#2@inner]{#3}
    % #1 is subordinate to #2
    \prop_gput:Nnn \g_riccardo_theorems_prop { #1 } { #2 }
   }
   {
    \IfValueTF{#4}
     {
      \newtheorem{#1@inner}{#3}[#4]
     }
     {
      \newtheorem{#1@inner}{#3}
     }
    % #1 is not subordinate, store the name itself
    \prop_gput:Nnn \g_riccardo_theorems_prop { #1 } { #1 }
   }
  % define a "grabbing" environment #1 with the usual features 
  \NewEnviron{#1}[1][]
   {
    % start the inner environment (without or with optional argument)
    \tl_if_empty:nTF { ##1 }
     { \begin{#1@inner} }
     { \begin{#1@inner}[##1] }
    % save the statement number
    \tl_gset:Nx \g__riccardo_theorems_number_tl { \use:c {@currentlabel} }
    % typeset the statement
    \BODY
    % end the inner environment
    \end{#1@inner}
   % store the statement in a sequence variable, actually as
   % four arguments as shown
   \seq_gput_right:Nx \g_riccardo_theorems_seq
     {
      { #1 } % name
      { \g__riccardo_theorems_number_tl } % number
      { \exp_not:n { ##1 } } % attribution
      { \exp_not:V \BODY } } % body
    }
 }

% allocate the needed variables
\prop_new:N \g_riccardo_theorems_prop
\seq_new:N \g_riccardo_theorems_seq
\tl_new:N \g__riccardo_theorems_number_tl

% print the stored theorems
\NewDocumentCommand{\printtheorems}{}
 {
  % we need a group where nullifying the action of \label
  \group_begin:
  \cs_set_eq:NN \label \use_none:n
  % map the sequence, passing each item to the function that prints a theorem
  \seq_map_function:NN \g_riccardo_theorems_seq \riccardo_printtheorems:n
  % end the group
  \group_end:
 }

\cs_new_protected:Nn \riccardo_printtheorems:n
 {
  % just pass the argument in the form {name}{number}{attribution}{text}
  % to a four argument function
  \__riccardo_printtheorems:nnnn #1
 }
\cs_new_protected:Nn \__riccardo_printtheorems:nnnn
 {
  % redefine \the<statement>@inner to yield the stored number
  % we use the property list to use the correct counter
  % (for instance, in case of "lemma", <statement> will be "theorem"
  \cs_set:cpn { the \prop_item:Nn \g_riccardo_theorems_prop {#1} @inner } { #2 }
  \tl_if_empty:nTF { #3 }
   {
    % no attribution
    \begin{#1@inner} #4 \end{#1@inner}
   }
   {
    % attribution
    \begin{#1@inner}[#3] #4 \end{#1@inner}
   }
 }

\ExplSyntaxOff

\newtheoremx{theorem}{Theorem}[section]
\newtheoremx{lemma}[theorem]{Lemma}

\begin{document}

\section{First test}

\begin{theorem}[Important]\label{thm:important}
This is a theorem about $\log_a x$.
\end{theorem}

\begin{lemma}\label{lem:whatever}
This is a lemma.
\end{lemma}

\begin{theorem}\label{thm:unimportant}
This is another theorem
\end{theorem}

\section{Second test}

\begin{theorem}\label{thm:soandso}
Again a theorem.
\end{theorem}

\section{Theorems}

\printtheorems

\end{document}

enter image description here

7
  • 1
    Wow! This is brilliant, thank you! I still have a couple of questions: 1) is it possible to use printtheorems at the beginning of each chapter? I was thinking a possible way to do it would be to compile the .tex twice, the first time to get the theorems's thesis and the second one to display them; 2) is it possible to divide printtheorems into chapters? e.g. calling it after every \chapter{chapter x} and displaying only the theorems relative to that specific chapter.
    – noibe
    Commented Feb 1, 2019 at 17:58
  • 1
    @RiccardoMazzarini That's quite a job! Are you sure you want to have a list of theorems at the beginning of each chapter? Have you ever seen something like that?
    – egreg
    Commented Feb 1, 2019 at 18:23
  • 1
    I'm sure but I don't want to abuse of your time. If that implementation requires a lot of coding time then don't feel forced to help me. With that said, there's one thing I'd like to ask you: do you know any introductory guides to expl3 and xparse? The documentations of both packages aren't exactly beginner-friendly but they seem (as shown by the code you posted) extremely useful and versatile.
    – noibe
    Commented Feb 1, 2019 at 18:31
  • A few quick questions. Is there a way to: 1) get a \newpage before each theorem and before \printtheorems 2) in the printtheorems list, making Theorem x (optional theorem name) clickable links to the theorem relative theorem using hyperref 3) this isn't really a question but using \counterwithin{equation}{thm} gives an error, (Class memoir Error: thm is not a counter).
    – noibe
    Commented Feb 2, 2019 at 12:03
  • 1
    @RiccardoMazzarini 1 is easy, add \newpage where you need it. 2 is more difficult. 3 use \counterwithin{equation}{thm@inner}, if your base theorems are called thm.
    – egreg
    Commented Feb 2, 2019 at 13:02

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .