2

I tried to compile the following code, which I collect and modify from: Label an item of a 'randomized enumerate' written by @egreg.

\documentclass[12pt,a4paper]{article}
\usepackage{amsmath, mathptmx, amssymb}
\usepackage[left=1.5cm,right=1.5cm,top=1.5cm,bottom=1.5cm]{geometry}

%Shuffle Questions
\usepackage{xparse,environ}

\ExplSyntaxOn
\NewEnviron{randomlist}[1][]
 {
  \keys_set:nn { lucas/randomlist } { #1 }
  \lucas_randomlist:V \BODY
 }
\NewDocumentCommand{\answerkey}{}
 {
  \subsubsection*{Answer ~ key}
  \begin{tasks}[label = \arabic*.](10)
  \seq_map_inline:Nn \g_lucas_randomlist_answers_seq { \task ##1 }
  \end{tasks}
 }
\NewDocumentCommand{\ans}{}
 {
  \seq_gput_right:Nx \g_lucas_randomlist_answers_seq { \use:c { @currentlabel } }
 }

\keys_define:nn { lucas/randomlist }
 {
  environment .tl_set:N = \l__lucas_randomlist_env_tl,
  seed .code:n = \sys_gset_rand_seed:n { #1 },
 }

\seq_new:N \g_lucas_randomlist_answers_seq
\cs_new_protected:Nn \lucas_randomlist:n
 {
  \seq_set_split:Nnn \l__lucas_randomlist_items_seq { \item } { #1 }
  % discard the empty first item
  \seq_pop_left:NN \l__lucas_randomlist_items_seq \l_tmpa_tl
  \seq_shuffle:N \l__lucas_randomlist_items_seq
  \begin{\l__lucas_randomlist_env_tl}
  \item \seq_use:Nn \l__lucas_randomlist_items_seq { \item }
  \end{\l__lucas_randomlist_env_tl}
 }
\cs_generate_variant:Nn \lucas_randomlist:n { V }

\ExplSyntaxOff

\usepackage[inline]{enumitem}
\setlist[enumerate]{
    label = \textbf{Q \arabic*.},
    align = left,
    labelwidth = \parindent, 
    leftmargin = \parindent,
    style = standard
}

\usepackage{tasks}[newest]
\newcommand*\tasklabelformat[1]{\textbf{#1.}}
\settasks{
    item-indent = 2em,
    label-width = 1.5em,
    label-offset = 0.25em,
    label = \Alph*,
    label-format = \tasklabelformat
}

%=========================================================
\begin{document}
\begin{randomlist}[environment=enumerate, seed=1]
\item How many letters in the word ``Tea'' ?
    \begin{tasks}(4)
        \task $1$
        \task $3$ \ans
        \task $2$
        \task $4$.
   \end{tasks}

\item How many letters in the word ``Hi'' ?
    \begin{tasks}(4)
        \task $1$
        \task $3$ 
        \task $2$ \ans
        \task $4$.
   \end{tasks}

\item How many letters in the word ``Cake'' ?
    \begin{tasks}(4)
        \task $1$
        \task $3$ 
        \task $2$
        \task $4$. \ans
   \end{tasks}

\item How many letters in the word ``Tree'' ?
    \begin{tasks}(4)
        \task $1$
        \task $3$ 
        \task $2$
        \task $4$. \ans
   \end{tasks}

\item How many letters in the word ``Dog'' ?
    \begin{tasks}(4)
        \task $1$
        \task $3$ \ans
        \task $2$ 
        \task $4$.
   \end{tasks}

\item How many letters in the word ``House'' ?
    \begin{tasks}(4)
        \task $2$
        \task $3$ 
        \task $5$ \ans
        \task $4$.
   \end{tasks}

\item How many letters in the word ``Tea'' ?
    \begin{tasks}(4)
        \task $1$
        \task $3$ \ans
        \task $2$
        \task $4$.
   \end{tasks}

\item How many letters in the word ``Hi'' ?
    \begin{tasks}(4)
        \task $1$
        \task $3$ 
        \task $2$ \ans
        \task $4$.
   \end{tasks}

\item How many letters in the word ``Cake'' ?
    \begin{tasks}(4)
        \task $1$
        \task $3$ 
        \task $2$
        \task $4$. \ans
   \end{tasks}

\item How many letters in the word ``Tree'' ?
    \begin{tasks}(4)
        \task $1$
        \task $3$ 
        \task $2$
        \task $4$. \ans
   \end{tasks}

\item How many letters in the word ``Dog'' ?
    \begin{tasks}(4)
        \task $1$
        \task $3$ \ans
        \task $2$ 
        \task $4$.
   \end{tasks}

\item How many letters in the word ``House'' ?
    \begin{tasks}(4)
        \task $2$
        \task $3$ 
        \task $5$ \ans
        \task $4$.
   \end{tasks}
\end{randomlist}
\answerkey
\end{document}

It pops the below structure and answer keys are not generated.

You've placed (tasks)(tasks) \seq_map_inline:Nn \g_lucas_randomlist_answers_seq
(tasks) {\task ##1} (tasks)(tasks) before the first \task

When I replace a corresponding part of the code by:

\NewDocumentCommand{\answerkey}{}
 {
  \subsubsection*{Answer ~ key}
  \begin{enumerate*}[nosep, label = \arabic*., mode = unboxed]
  \seq_map_inline:Nn \g_lucas_randomlist_answers_seq {\item \makebox[2cm][l]{##1}}
  \end{enumerate*}
 }

It works fine, but two lines of answer keys are not aligned as shown below: enter image description here

How to solve that? Any solution is welcomed and I'll be very appreciated.

1 Answers1

1

Environments from the tasks package need to see their body in order to be able to split the contents at each occurrence of \task and build the list according the chosen setup. This means you cannot build it on the fly within \begin{tasks} ... \end{tasks}. You need to build the environment body beforehand and then use it.

I suggest to modify the definition of \answerkey like this:

\cs_generate_variant:Nn \use:nn {nV}

\NewDocumentCommand \answerkey {}
  {
    \subsubsection* {Answer~ key}
    \tl_clear:N \l_tmpa_tl
    \seq_map_inline:Nn \g_lucas_randomlist_answers_seq
      { \tl_put_right:Nn \l_tmpa_tl { \task ##1 } }
    \use:nV
      { \begin{tasks}[label = \arabic*](10)}
      \l_tmpa_tl
    \end {tasks}
 }

\use:nn reads two arguments and puts them in the input stream. The variant \use:nV reads the contents of a variable as second argument and uses its contents as argument. Before we only need to build up the body of the tasks environment as contents of the variable.

BTW: with a sufficiently up to date xparse you can read the body of an environment using the argument type b which means you don't need environ. I modified the code accordingly:

\documentclass[12pt,a4paper]{article}
\usepackage{amsmath, mathptmx, amssymb}
\usepackage[left=1.5cm,right=1.5cm,top=1.5cm,bottom=1.5cm]{geometry}

%Shuffle Questions
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentEnvironment {randomlist} {o+b}
  {
    \IfNoValueF {#1} { \keys_set:nn { lucas/randomlist } {#1} }
    \lucas_randomlist:n {#2}
  }
  {}

\cs_generate_variant:Nn \use:nn {nV}

\NewDocumentCommand \answerkey {}
  {
    \subsubsection* {Answer~ key}
    \tl_clear:N \l_tmpa_tl
    \seq_map_inline:Nn \g_lucas_randomlist_answers_seq
      { \tl_put_right:Nn \l_tmpa_tl { \task ##1 } }
    \use:nV
      { \begin{tasks}[label = \arabic*](10)}
      \l_tmpa_tl
    \end {tasks}
 }

\NewDocumentCommand \ans {}
  {
    \seq_gput_right:Nx \g_lucas_randomlist_answers_seq
      { \use:c { @currentlabel } }
  }

\keys_define:nn { lucas/randomlist }
  {
    environment .tl_set:N = \l__lucas_randomlist_env_tl,
    seed .code:n = \sys_gset_rand_seed:n { #1 },
  }

\seq_new:N \g_lucas_randomlist_answers_seq
\cs_new_protected:Nn \lucas_randomlist:n
  {
    \seq_set_split:Nnn \l__lucas_randomlist_items_seq { \item } {#1}
    % discard the empty first item
    \seq_pop_left:NN \l__lucas_randomlist_items_seq \l_tmpa_tl
    \seq_shuffle:N \l__lucas_randomlist_items_seq
    \begin {\l__lucas_randomlist_env_tl}
      \item \seq_use:Nn \l__lucas_randomlist_items_seq { \item }
    \end {\l__lucas_randomlist_env_tl}
  }

\ExplSyntaxOff

\usepackage[inline]{enumitem}
\setlist[enumerate]{
    label = \textbf{Q \arabic*.},
    align = left,
    labelwidth = \parindent, 
    leftmargin = \parindent,
    style = standard
}

\usepackage{tasks}[newest]
\newcommand*\tasklabelformat[1]{\textbf{#1.}}
\settasks{
    item-indent = 2em,
    label-width = 1.5em,
    label-offset = 0.25em,
    label = \Alph*,
    label-format = \tasklabelformat
}

%=========================================================
\begin{document}
\begin{randomlist}[environment=enumerate, seed=1]
\item How many letters in the word ``Tea'' ?
    \begin{tasks}(4)
        \task $1$
        \task $3$ \ans
        \task $2$
        \task $4$.
   \end{tasks}

\item How many letters in the word ``Hi'' ?
    \begin{tasks}(4)
        \task $1$
        \task $3$ 
        \task $2$ \ans
        \task $4$.
   \end{tasks}

\item How many letters in the word ``Cake'' ?
    \begin{tasks}(4)
        \task $1$
        \task $3$ 
        \task $2$
        \task $4$. \ans
   \end{tasks}

\item How many letters in the word ``Tree'' ?
    \begin{tasks}(4)
        \task $1$
        \task $3$ 
        \task $2$
        \task $4$. \ans
   \end{tasks}

\item How many letters in the word ``Dog'' ?
    \begin{tasks}(4)
        \task $1$
        \task $3$ \ans
        \task $2$ 
        \task $4$.
   \end{tasks}

\item How many letters in the word ``House'' ?
    \begin{tasks}(4)
        \task $2$
        \task $3$ 
        \task $5$ \ans
        \task $4$.
   \end{tasks}

\item How many letters in the word ``Tea'' ?
    \begin{tasks}(4)
        \task $1$
        \task $3$ \ans
        \task $2$
        \task $4$.
   \end{tasks}

\item How many letters in the word ``Hi'' ?
    \begin{tasks}(4)
        \task $1$
        \task $3$ 
        \task $2$ \ans
        \task $4$.
   \end{tasks}

\item How many letters in the word ``Cake'' ?
    \begin{tasks}(4)
        \task $1$
        \task $3$ 
        \task $2$
        \task $4$. \ans
   \end{tasks}

\item How many letters in the word ``Tree'' ?
    \begin{tasks}(4)
        \task $1$
        \task $3$ 
        \task $2$
        \task $4$. \ans
   \end{tasks}

\item How many letters in the word ``Dog'' ?
    \begin{tasks}(4)
        \task $1$
        \task $3$ \ans
        \task $2$ 
        \task $4$.
   \end{tasks}

\item How many letters in the word ``House'' ?
    \begin{tasks}(4)
        \task $2$
        \task $3$ 
        \task $5$ \ans
        \task $4$.
   \end{tasks}
\end{randomlist}
\answerkey
\end{document}

enter image description here

cgnieder
  • 66,645