1

I'm trying to write a couple of new environments and commands to save short answers from a list with enumerate environment, the idea being to save the first and second level using references to lists stored in memory.

I am using the enumitem, multicol, pgffor, tcolorbox and xparse packages.

I explained, I created two new environments each with a defined command inside them to be able to save the short answers and I added a pair of keys to enumitem.

\NewDocumentEnvironment{saveanswer} whit \answi
\NewDocumentEnvironment{saveansweri} whit \answii
\SetEnumitemKey{columns}{before=\begin{multicols}{#1},after=\end{multicols}}%
\SetEnumitemKey{savekey}{before=\begin{saveanswer}{#1},after=\end{saveanswer}}%
\SetEnumitemKey{ansref}{before=\begin{saveansweri}{#1},after=\end{saveansweri}}%

Here begins my dilemma. If I use the enumitem keys, it loses the alignment of the lists in the last element and affects all enumerate environments (with or without the enabled key) using key from enumitem

If I comment the enumitem keys and encapsulate the enumerate environments within "saveanswer" the ones I have created partially solve the issue, but it still affects the other enumerate environments. enumerate in saveanswer

With both cases it fails, in addition, I can not run the foreach loop to keep the items correctly in the list. I would like it to look like this: IDEAL

I'm a little lost in this, i read Conflict between NewDocumentEnvironment and enumerate and maybe the way to get what I'm looking for is not the right one and it should be done differently. Regards: The MWE:

% !file: forum.tex
% arara: pdflatex
% arara: clean: { files:[forum.aux, forum.log] }
\documentclass{article}
\usepackage{enumitem}
\usepackage{multicol}
\usepackage{pgffor}
\usepackage{tcolorbox}
\tcbuselibrary{many}
\pagestyle{empty}

% Set key for multicols in enumitem
\SetEnumitemKey{columns}{before=\begin{multicols}{#1},after=\end{multicols}}%
\SetEnumitemKey{savekey}{before=\begin{saveanswer}{#1},after=\end{saveanswer}}%
\SetEnumitemKey{ansref}{before=\begin{saveansweri}{#1},after=\end{saveansweri}}%

% Some definition
\newtheorem{theorem}{Theorem}
\newtheorem{exercise}[theorem]{Exercise}

% Adapted from https://tex.stackexchange.com/a/364763/7832
\ExplSyntaxOn
% Reporter macro, is expandable
\cs_new:Npn \reportnumberofseqitems #1{%
 \seq_count:c {l_bcp_data_#1_seq}%
}
\NewDocumentCommand{\storedata}{mm}
  {
   \bcp_store_data:nn { #1 } { #2 }
  }

\NewDocumentCommand{\appenddata}{+m+m}
 {
  \bcp_append_data:nn { #1 } { #2 }
 }

\DeclareExpandableDocumentCommand{\getdata}{O{1}m}
 {
  \bcp_get_data:nn { #1 } { #2 }
 }

\cs_new_protected:Npn \bcp_store_data:nn #1 #2
 {
  % create the sequence if it doesn't exist or clear it if it exists
  \seq_if_exist:cTF { l_bcp_data_#1_seq }
   { \seq_new:c { l_bcp_data_#1_seq } }
   { \seq_gclear:c { l_bcp_data_#1_seq } }
  % append the items
  \__bcp_append_data:nn { #1 } { #2 }
 }

\cs_new_protected:Npn \bcp_append_data:nn #1 #2
 {
  % create the sequence if it doesn't exist, do nothing if it exists
  \seq_if_exist:cF { l_bcp_data_#1_seq }
   { \seq_new:c { l_bcp_data_#1_seq } }
  % append the items
  \__bcp_append_data:nn { #1 } { #2 }
 }

\cs_new_protected:Npn \__bcp_append_data:nn #1 #2
 {
  % append items one at a time
  \tl_map_inline:nn { #2 }
   {
    \seq_gput_right:cn { l_bcp_data_#1_seq } { ##1 }
   }
 }

\cs_new:Npn \bcp_get_data:nn #1 #2
 {
  % retrieve the requested item
  \seq_item:cn { l_bcp_data_#2_seq } { #1 }
 }
% Save answer in first level answi 
\NewDocumentEnvironment{saveanswer}{m}{%
\NewDocumentCommand\answi{m}{%,
    \appenddata{#1}{{##1}}%
    }% close \answi
}{%
}% close saveanswer

% Save answer in second level answii 
\newcounter{myNo}
\NewDocumentEnvironment{saveansweri}{m}{%
\stepcounter{myNo}
\NewDocumentCommand\answii{m}{%,
    \appenddata{#1:\themyNo}{{##1}}%
    }% close \answii
}{%
\appenddata{#1}{{\begin{enumerate}\space%
\foreach \x in {1,...,\reportnumberofseqitems{#1:\themyNo}}{%
    \item \space \getdata[\x]{#1:\themyNo} \space%
                } % close foreach
    \space \end{enumerate}}} % close appendata
}% close saveansweri

\ExplSyntaxOff

% [#1] : pass to tcolorbox
% {#2} : title
% {#3} : list ref
% [#4] : columns
\DeclareTotalTColorBox{\showans}{O{} m m O{4}}
{ colback=white,size=small,top=0mm,bottom=1.5mm, left=0mm,width=\columnwidth,title filled,%
  fontupper=\small,fonttitle=\small\sffamily,%
    adjusted title={#2},center title,#1}
  {% 
  \begin{enumerate}[columns=#4,leftmargin=15pt,labelsep=3pt,font=\footnotesize,nosep,widest=25,]%
  \small
  \setlength{\columnsep}{0pt} 
   \foreach \x in {1,...,\reportnumberofseqitems{#3}} {
    \item \getdata[\x]{#3}%
    }
  \end{enumerate}
  }%
\begin{document}

\section{It looks like this}
\subsection{Exercices}
\begin{enumerate}[savekey=test1]
\setenumerate{labelsep=5pt, leftmargin=1cm, itemsep=0pt,widest=80}%
\item True False
      \begin{enumerate}[ansref=test1] 
      \item $2\alpha+2\delta=90^{\circ}$ \answii{True}
      \item $\angle EDF=45^{\circ}$ \answii{False}
      \end{enumerate} 
\item Factor $x^{2}-2x+1$  \answi{$\left(x-1\right)^{2}$} 
\item Factor$3x+3y+3z$    \answi{$3(x+y+z)$}
\item True False
      \begin{enumerate}[ansref=test1]
      \item $2\alpha+2\delta=90^{\circ}$ \answii{False}
      \item $\alpha=\delta$ \answii{True}
      \item $\alpha=\delta$ \answii{True}
      \end{enumerate} 
\end{enumerate}
\subsection{answers}
\showans{Exercices 1}{test1}[2]
\end{document}
  • 1
    This looks very complex. And \setenumerate is deprecated. You should use \setlist[enumerate,1] , i.e. setting the keys for the individual enumerate levels here, which is most likely the cause for your problem -- they are mixed – user31729 Apr 17 '17 at 5:21
  • In my opinion, the issue is the usage of \themyNo -- it is not expanded and therefore the lists are mixed – user31729 Apr 17 '17 at 6:13
  • @ChristianHupfer: Thanks for the comment, it is quite complicated, try for several hours looking at the forum something that could adapt, I can not think of another way to address what I want. For the lists maybe I do not need a counter, only to run temporarily, maybe use \edef\tmp in \answii? – Pablo González L Apr 17 '17 at 10:15
  • No, I don't think that something like \edef\tmp would be sufficient (and not possible there because of the assignments with \seq_gput_right:Nnn, most likely) – user31729 Apr 17 '17 at 10:57
  • In your \keych macro change try to change \seq_gput_right:cn { l_bcp_data_ \retrievecurrentid _seq }{\item \Alph{enumii}} to \seq_gput_right:cx { l_bcp_data_ \retrievecurrentid _seq }{\protect\item \Alph{enumii}} – user31729 Apr 18 '17 at 16:47
1

I am applying a different strategy, by automatic stepping down and up of enumerate levels and storing the \begin{enumerate} and \end{enumerate} into one single list, retrieving the current list id with global \prop variable.

% !file: forum.tex
% arara: pdflatex
% arara: clean: { files:[forum.aux, forum.log] }
\documentclass{article}
\usepackage{enumitem}
\usepackage{multicol}
\usepackage{pgffor}
\usepackage[many]{tcolorbox}
\pagestyle{empty}

% Set key for multicols in enumitem
\SetEnumitemKey{columns}{before=\begin{multicols}{#1},after=\end{multicols}}%
\SetEnumitemKey{savekey}{before={\storecurrentid{#1}\begin{saveanswer}{#1}},after=\end{saveanswer}}%

% Some definition
\newtheorem{theorem}{Theorem}
\newtheorem{exercise}[theorem]{Exercise}

% Adapted from https://tex.stackexchange.com/a/364763/7832
\ExplSyntaxOn

\prop_new:N \g_bpc_admin_prop 

\cs_new:Npn \storecurrentid #1{%
  \prop_gput:Nnn \g_bpc_admin_prop {current-id} {#1}
}

\cs_new:Npn \retrievecurrentid {%
  \prop_item:Nn \g_bpc_admin_prop {current-id} 
}


\NewDocumentEnvironment{saveanswer}{m}{%
  \setlist[enumerate,1]{labelsep=5pt, leftmargin=1cm, itemsep=0pt,widest=80}%
  \setlist[enumerate,2]{before={\stepdownlevel},after={\stepuplevel},labelsep=5pt, leftmargin=0.6cm, itemsep=0pt,widest=80}
  \seq_if_exist:cF { l_bcp_data_#1_seq }{%
    \seq_new:c { l_bcp_data_#1_seq }
  }
  \leavevmode
}{%
%
}% close saveanswer

\NewDocumentCommand{\answeris}{+m}{%
  \seq_gput_right:cn { l_bcp_data_ \retrievecurrentid _seq }{\item  #1}
  \par
}

\newcommand{\stepdownlevel}{%
  % Must start a new item with \begin{enumerate} on answer ... 
  \seq_gput_right:cn {l_bcp_data_ \retrievecurrentid _seq} {\item \begin{enumerate}}
  }

\newcommand{\stepuplevel}{%
  % Close current enumerate level
  \seq_gput_right:cn {l_bcp_data_ \retrievecurrentid _seq} {\end{enumerate}}
}

\cs_new:Npn \displayseqcontent #1#2 {%
  \seq_if_empty:cF { l_bcp_data_#1_seq } {%
    \seq_log:c { l_bcp_data_#1_seq }
    \setlist[enumerate,2]{before={},after={},labelsep=5pt, leftmargin=0.6cm, itemsep=0pt,widest=80}
    \begin{enumerate}[#2]
      \small
      \setlength{\columnsep}{0pt} 
      \seq_map_inline:cn { l_bcp_data_#1_seq } {%
        ##1%
      }
    \end{enumerate}
  }
}

\ExplSyntaxOff

% [#1] : pass to tcolorbox
% {#2} : title
% {#3} : list ref
% [#4] : columns
\DeclareTotalTColorBox{\showans}{O{} m m O{4}}
{ colback=white,size=small,top=0mm,bottom=1.5mm, left=0mm,width=\columnwidth,title filled,%
  fontupper=\small,fonttitle=\small\sffamily,%
  adjusted title={#2},center title,#1}
{% 
  \displayseqcontent{#3}{columns=#4,leftmargin=15pt,labelsep=3pt,font=\footnotesize,nosep,widest=25}
}%


% Set the list properties for level 1 and 2
%\setlist[enumerate,1]{labelsep=5pt, leftmargin=1cm, itemsep=0pt,widest=80}%
%\setlist[enumerate,2]{before={\stepdownlevel},after={\typeout{stepping up for \retrievecurrentid}\stepuplevel},labelsep=5pt, leftmargin=0.6cm, itemsep=0pt,widest=80}%

\begin{document}
\section{It looks like this}
\subsection{Exercices}
\begin{enumerate}[savekey=test1]
\item True False
  \begin{enumerate}
  \item $2\alpha+2\delta=90^{\circ}$ \answeris{True}
  \item $\angle EDF=45^{\circ}$ \answeris{False}
  \end{enumerate} 
\item Factor $x^{2}-2x+1$  \answeris{$\left(x-1\right)^{2}$} 
\item Factor $3x+3y+3z$    \answeris{$3(x+y+z)$}
\item True False
  \begin{enumerate}
  \item $2\alpha+2\delta=90^{\circ}$ \answeris{False}
  \item $\alpha=\delta$ \answeris{True}
  \item $\alpha > \delta$ \answeris{False}
  \item \LaTeX2e\ is cool? \answeris{Very True!}
  \end{enumerate} 
\end{enumerate}


\begin{enumerate}[savekey=test2]
\item True False 
  \begin{enumerate}
  \item $2\alpha+2\delta=90^{\circ}$ \answeris{False}
  \item $\alpha=\delta$ \answeris{True}
  \item $\alpha > \delta$ \answeris{False}
  \item \LaTeX2e\ is cool? \answeris{Very True!}
  \end{enumerate} 

\item True False 

  \begin{enumerate}
  \item $2\alpha+2\delta=90^{\circ}$ \answeris{True}
  \item $\angle EDF=45^{\circ}$ \answeris{False}
  \end{enumerate} 

\item Factor $x^{2}-2x+1$  \answeris{$\left(x-1\right)^{2}$} 

\item Factor $3x+3y+3z$    \answeris{$3(x+y+z)$}
\end{enumerate}


\subsection{answers}

\showans[colback=yellow!30!white]{Exercices 1}{test1}[2]

\showans[colback=yellow!30!white]{Exercices 2}{test2}[2]


\showans[colback=yellow!70!blue]{Exercices 1 again}{test1}[2]
\end{document}

enter image description here

enter image description here

  • I don't guarantee this will work always – user31729 Apr 17 '17 at 13:04
  • Great, it's what I want, now I write from my cell phone, coming home I check it ... thank you very much – Pablo González L Apr 17 '17 at 14:31
  • @PabloGonzálezL: I've updated in the meantime. – user31729 Apr 17 '17 at 20:58
  • @ChristianHuper: Thank you very much for the time you have taken, it is just what I was looking for (with this I save a million hours of work). Now i know that \leavmode solves the interference with enumitem A query related to the same subject. With same strategy I want to save the "multiple choice" test keys, i have created an environment called "savechoice", a enumitem key "savecch" and command \keych, (copy of \answeris) whit optional argument, by deault \item \Alph{enumi} and \item # 1 with optional, how can expand the \Alph{enumi} of the second enumerate level?...Saludos – Pablo González L Apr 18 '17 at 2:09
  • @PabloGonzálezL: Do you mean something like \setenumerate[enumerate]{label={\Alph*}} and \setenumerate[enumerate,2]{label*={\arabic*}}? The label* means that the parent level (i.e. enumi) will be prepended – user31729 Apr 18 '17 at 6:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.