1

Background: I'm attempting to use some exercises from an open text that are distributed across many files. I've rewritten the input mechanism and have it working fine. I can use multicols and enumerate to print exercise sets vertically across two columns, but would like to print them horizontally, thus the tasks package. The problem is as follows:

Problem: When changing from enumerate to tasks, I'm getting a missing \item error. I assume that this is due to a \par introduced somewhere in the I/O operations being included in a \task (the tasks package documentation lists this as one way that the environment differs from enumerate, no \par's allowed). If this is the case, then I can't find where it's introduced. If not, then I have no idea what's going on.

MWE:

\documentclass{article}
\usepackage{xparse}
\usepackage{tasks}
\usepackage{filecontents}

\begin{filecontents*}{numbers_20.tex}
{$5 - (2+3)$}
{$0$}
\end{filecontents*}

\begin{filecontents*}{numbers_21.tex}
{$5 - (2-3)$}
{$6$}
\end{filecontents*}

\begin{filecontents*}{numbersset.tex}
\exinput{numbers_20.tex}
\exinput{numbers_21.tex}
\end{filecontents*}

\ExplSyntaxOn
\ior_new:N \l__exread_ior % read exercise
\ior_new:N \l__exsetread_ior % read exercise set
\ior_new:N \l__allread_ior % read all

%Relevant code below
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\NewDocumentCommand{\exinput}{m}{
    \ior_open:Nn \l__exread_ior {#1} % open exercise file
    \ior_get:NN \l__exread_ior \l_tmpb_tl % get line
    \task\l_tmpb_tl % add task
    \ior_close:N \l__exread_ior
}

\NewDocumentCommand{\exsetinput}{m}{
    \ior_open:Nn \l__exsetread_ior {#1} % open set file
    \ior_map_inline:Nn \l__exsetread_ior {\seq_put_right:Nn \l_tmpb_seq {##1}} % put exercises in a sequence
    % if following changed to enumerate, and line 31 to item then works as expected.
    \begin{tasks}(2) % start tasks
        % seq items are "exinput" (above) and should print \task\blah
        \seq_use:Nn \l_tmpb_seq {}
    \end{tasks}

    \ior_close:N \l__exsetread_ior 
    \seq_clear:N \l_tmpb_seq
}


\ExplSyntaxOff
\begin{document}

\exsetinput{numbersset}

\end{document}

1 Answer 1

2

The problem is that the tasks environment does not work quite like enumerate. enumerate is a "traditional" environment, in the sense that it executes the code line by line until finding its end. tasks works more like a command, grabbing the contents of the environment and then doing its thing.

The environment grabs its body and then splits it at each occurrence of the token \task. However in your code there is no such token; all there is is \seq_use:Nn \l_tmpb_seq {}.

To make it work with tasks you need to first read everything in and put it with explicit \task tokens in the body of the environment and then start the tasks environment.

I changed your code to do so. It uses a temporary sequence \l__exread_tmp_seq (avoid using \l_tmpa_seq and other such variables; they are meant for really short term usage, like quick tests) to store the read exercises. It then reads in the file (numbersset.tex) without any special treatment. This file should contain the file names to be read, one per line.

The code iterates at each line of the file and uses \__exread_input_one:Nn (I made it a private function; you don't need to use it in every line of the file, the code does it for you :-) in each line. This inner function also iterates on each line of each file and appends that line to a sequence variable. Once all of that is done, the sequence should contain all the lines in all the files listed in numbersset.tex, each of them preceded by a \task token.

Once that is done, the function x-expands \seq_use:Nn \l__exread_tmp_seq { } before starting the tasks environment. Once the environment starts, everything is in its due place and tasks does its thing:

enter image description here

Here's the code:

\documentclass{article}
\usepackage{xparse}
\usepackage{tasks}
\usepackage{filecontents}
\begin{filecontents*}{numbers_20.tex}
{$5 - (2+3)$}
{$0$}
\end{filecontents*}
\begin{filecontents*}{numbers_21.tex}
{$5 - (2-3)$}
{$6$}
\end{filecontents*}
\begin{filecontents*}{numbersset.tex}
numbers_20.tex
numbers_21.tex
\end{filecontents*}
\ExplSyntaxOn
\ior_new:N \l__exread_all_ior
\ior_new:N \l__exread_one_ior
\seq_new:N \l__exread_tmp_seq
\cs_new_protected:Npn \__exread_input_one:Nn #1 #2
  {
    \ior_open:Nn \l__exread_one_ior {#2}
    \ior_map_inline:Nn \l__exread_one_ior
      { \seq_put_right:Nn #1 { \task ##1 } }
    \ior_close:N \l__exread_one_ior
  }
\NewDocumentCommand { \exsetinput } { m }
  {
    \seq_clear:N \l__exread_tmp_seq
    \file_if_exist:nTF {#1}
      {
        \ior_open:Nn \l__exread_all_ior {#1}
        \ior_map_inline:Nn \l__exread_all_ior
          { \__exread_input_one:Nn \l__exread_tmp_seq {##1} }
        \ior_close:N \l__exread_all_ior
      }
      { \msg_error:nnn { exread } { file-not-found } {#1} }
    \use:x
      {
        \exp_not:N \begin{tasks}(2)
          \seq_use:Nn \l__exread_tmp_seq { }
        \exp_not:N \end{tasks}
      }
  }
\msg_new:nnn { exread } { file-not-found }
  { File~`#1'~not~found. }
\ExplSyntaxOff
\begin{document}

\exsetinput{numbersset}

\end{document}
1
  • 1
    Many thanks Phelype!
    – Scott H.
    Sep 25, 2019 at 4:13

You must log in to answer this question.

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