1

I have a small problem when trying to keep a key=val locally defining using xparse to pass multicols to enumerate (enumitem package). I have redefined the environment enumerate to accept the columns=number and created commands \keyans[...], \answer{...} and \showanskey[...]{...}{...}[...] to save the multiple choice keys and answers for worksheet exercise , all well except that when activate the columns in the first level of enumerate, affects all the levels nested in it.

When using columns=2 in the first level it looks like this:

current result

all nested environments are in two columns.

I hope is that the output is something like this:

expected result

I tried to put \group_begin: and \group_end: in different places but I only get errors. The code is adapted from Defining a list environment with multiple optional arguments and MWE:

% arara: pdflatex
% arara: clean: { extensions: [ aux, log] }
\documentclass{article}
\usepackage{letltxmacro,enumitem,multicol,xparse}
\usepackage[most]{tcolorbox}
\usepackage[margin=0.6in,noheadfoot,papersize={8.5in,13in}]{geometry} % for mwe
\setlength{\parindent}{0pt}
\pagestyle{empty}

% Set keys for save-ans and save-key in enumitem
\SetEnumitemKey{save-ans}{before={\storecurrentid{#1}\begin{saveanswer}{#1}},after=\end{saveanswer}}%
\SetEnumitemKey{save-key}{before={\storecurrentid{#1}\begin{savekeyans}{#1}},after=\end{savekeyans}}%

% Save a copy enumerate
\LetLtxMacro\oldenum\enumerate
\LetLtxMacro\oldendenum\endenumerate

% Redefine enumerate for multicols
\ExplSyntaxOn
\RenewDocumentEnvironment{enumerate}{ O{} }
 {
  \tl_clear:N \l_keyanswer_enumitem_tl
  \keys_set:nn { keyanswer } { #1 } 
  \int_compare:nT { \l_keyanswer_columns_tl > 1 } 
   { 
   \setlength{\multicolsep}{5.0pt plus 2.0pt minus 1.5pt}
   \begin{multicols}{ \l_keyanswer_columns_tl } 
   }
  \keyanswer_beginenum:V \l_keyanswer_enumitem_tl 
 }
 {
  \oldendenum
  \int_compare:nT { \l_keyanswer_columns_tl > 1 }
   { \end{multicols} }
 }
\cs_new_protected:Npn \keyanswer_beginenum:n #1
 { \oldenum[#1] }

\cs_generate_variant:Nn \keyanswer_beginenum:n {V}

\tl_new:N \l_keyanswer_columns_tl
\tl_new:N \l_keyanswer_enumitem_tl

\keys_define:nn { keyanswer }
 {
  columns .tl_set:N  = \l_keyanswer_columns_tl,
  columns .initial:n = 1,
  unknown .code:n    = \tl_put_right:Nx \l_keyanswer_enumitem_tl 
                        { \l_keys_key_tl \tl_if_empty:nF { #1 } { = \exp_not:n { #1 } } , },
 }

% Implementation to save \answer{...} and \keyans[...] in lists
\prop_new:N \g_keyanswer_admin_prop

\cs_new:Npn \storecurrentid #1{%
  \prop_gput:Nnn \g_keyanswer_admin_prop {current-id} {#1}
 }
\cs_new:Npn \retrievecurrentid {%
  \prop_item:Nn \g_keyanswer_admin_prop {current-id}
 }

% environments for save \answer{...} and \keyans[...]
\NewDocumentEnvironment{saveanswer}{ m }{%
  \setlist[enumerate,2]{leftmargin=16pt,nosep,itemsep=0pt,label=(\alph*),before={\stepdownlevel},after={\stepuplevel}}%
  \setlist[enumerate,3]{leftmargin=20pt,nosep,itemsep=0pt,label=\Roman*.,before={\stepdownlevel},after={\stepuplevel}}%
  \seq_if_exist:cF { l_keyanswer_data_#1_seq }{ \seq_new:c { l_keyanswer_data_#1_seq }}
  }{ \leavevmode }

\NewDocumentEnvironment{savekeyans}{ m }{%
  \setlist[enumerate,1]{left=0pt,labelsep=5pt,itemsep=1pt,label=\arabic*.}%
  \setlist[enumerate,2]{leftmargin=16pt,nosep,label=\Alph*)}%
  \seq_if_exist:cF { l_keyanswer_data_#1_seq }{%
    \seq_new:c { l_keyanswer_data_#1_seq }}}{ \leavevmode }

% commands \answer{...} and \keyans[...]
\NewDocumentCommand{\answer}{ +m }{%
  \seq_gput_right:cn { l_keyanswer_data_ \retrievecurrentid _seq }{\item  #1}
  \par%
 }

\NewDocumentCommand\keyans{ !o }{%
 \IfNoValueTF{#1}{%
  \tl_set:Nn \l_tmpa_tl {\protect\item}%
  \tl_put_right:Nx \l_tmpa_tl {\protect\space \Alph{enumii}}% 
  \seq_gput_right:cV { l_keyanswer_data_ \retrievecurrentid _seq }{ \l_tmpa_tl}%
  \par%
    }{%
  \seq_gput_right:cn { l_keyanswer_data_ \retrievecurrentid _seq }{\item #1}%
  \par%
    }%
 }%

% \stepdownlevel and \stepuplevel for save in nested enumerate
\newcommand{\stepdownlevel}{%
  \seq_gput_right:cn {l_keyanswer_data_ \retrievecurrentid _seq} {\item \begin{enumerate}}
 }
\newcommand{\stepuplevel}{%
  \seq_gput_right:cn {l_keyanswer_data_ \retrievecurrentid _seq} {\end{enumerate}}
 }

% Display \answer{...} and \keyans[...] in list by id
\cs_new:Npn \displayseqcontent #1#2 {%
  \seq_if_empty:cF { l_keyanswer_data_#1_seq } {%
    \seq_log:c { l_keyanswer_data_#1_seq }
    \setlist[enumerate,1]{labelsep=5pt,label=\arabic*.,leftmargin=15pt,labelsep=3pt,font=\footnotesize,nosep,widest=80}%
    \setlist[enumerate,2]{font=\footnotesize,labelsep=5pt,leftmargin=0.6cm,nosep,label=(\alph*)}%
    \setlist[enumerate,3]{font=\footnotesize,labelsep=5pt,leftmargin=0.3cm,nosep,label=\Roman*.}%
    \begin{enumerate}[#2] \small\setlength{\columnsep}{0pt}
      \seq_map_inline:cn { l_keyanswer_data_#1_seq } { ##1 }
    \end{enumerate}
  }
 }
\ExplSyntaxOff

% \showanskey[tcolorbox]{title}{list ref}[columns]
\DeclareTotalTColorBox{\showanskey}{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} }%

\begin{document}

\section{Multiple Choice}

\begin{enumerate}[save-key=mchoice,left=0pt,columns=2]
\item First type of questions
    \begin{enumerate}
        \item value 
        \item value 
        \item value
        \item correct \keyans
        \item value 
    \end{enumerate}
\item Second type of questions
        \begin{enumerate}[leftmargin=2pc,label=\Roman*.]
            \item $2\alpha+2\delta=90^{\circ}$
            \item $\alpha=\delta$ 
            \item $\angle EDF=45^{\circ}$
        \end{enumerate}
\begin{enumerate}[columns=2]% 
        \item I only 
        \item II only \keyans
        \item I and II only
        \item I and III only 
        \item I, II, and III
\end{enumerate}
%\columnbreak % 
\item Third type of questions
        \begin{enumerate}[leftmargin=2pc,label=(\arabic*)]
            \item $2\alpha+2\delta=90^{\circ}$
            \item $\angle EDF=45^{\circ}$
        \end{enumerate}
    \begin{enumerate}
        \item Altenativa A 
        \item Altenativa B 
        \item Altenativa C \keyans
        \item Altenativa D
        \item Altenativa E 
    \end{enumerate}
\item Fourth type of question, a problem with numerical response \keyans[$\sqrt{2}$]

\end{enumerate}

\section{Worksheet}

\begin{enumerate}[save-ans=Worksheet,left=0pt,labelsep=5pt,nosep,label=\arabic*.,columns=2]
\item Factor $x^{2}-2x+1$  \answer{$\left(x-1\right)^{2}$} 
\item Factor $3x+3y+3z$    \answer{$3(x+y+z)$}
\item True False
  \begin{enumerate}
  \item $\alpha > \delta$ \answer{False}
  \item \LaTeX2e\ is cool? \answer{Very True!}
  \end{enumerate} 
\item Related to Linux
  \begin{enumerate}
  \item You use linux? \answer{Yes}
  \item Usually uses the package manager? \answer{Yes}
  \item Rate the following package managers
        \begin{enumerate}
        \item dnf \answer{good}
        \item apt \answer{very good}
        \item yum \answer{obsolete}
        \end{enumerate}
  \end{enumerate} 
\end{enumerate}

\section{Answers}
\showanskey[colback=yellow!30!white]{Multiple Choice Keys}{mchoice}[5]
\showanskey[colback=yellow!30!white]{Solution Worksheet}{Worksheet}[2]

\section{Normal enumerate}
\begin{enumerate}
\item First level
    \begin{enumerate}
        \item Second level 
        \item value 
        \item \begin{enumerate}
                \item Third level
                \item value
               \end{enumerate}
    \end{enumerate}
\end{enumerate}

\end{document}

If put in all sublevels columns=1 skip the problem, but, can't do this with \showanskey. If instead of using \RenewDocumentEnvironment{enumerate} I use directly

\SetEnumitemKey{columns}{before=\begin{multicols}{#1},after=\end{multicols}}%

I get the following error:

! LaTeX3 Error: Variable \l_keyanswer_data_mchoice_seq undefined.

How can i fix this?

Grateful

2

Once you set the keys, the values remain as stated.

You can simply restore a value by specifying the relevant key, before setting the specified ones:

\keys_set:nn { keyanswer } { #1 } 

should become

\keys_set:nn { keyanswer } { columns=1, #1 } 

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.