% \iffalse meta-comment
%
% getitems.dtx
% Copyright 2016 by Anders O.F. Hendrickson (anders.hendrickson@snc.edu)
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3
% of this license or (at your option) any later version.
% The latest version of this license is in
%   http://www.latex-project.org/lppl.txt
% and version 1.3 or later is part of all distributions of LaTeX
% version 2005/12/01 or later.
%
% This work has the LPPL maintenance status `maintained'.
% 
% The Current Maintainer of this work is Anders O.F. Hendrickson.
%
% This work consists of the files moodle.dtx and moodle.ins
% and the derived files moodle.sty and getitems.sty.
%
% \fi
%
% \iffalse
%<*driver>
\ProvidesFile{getitems.dtx}
%</driver>
%<package>\NeedsTeXFormat{LaTeX2e}[1999/12/01]
%<package>\ProvidesPackage{getitems}
%<*package>
    [2016/01/11 v1.0 gather items from a list]
%</package>
%
%<*driver>
\documentclass{ltxdoc}
\usepackage{getitems}
\usepackage{fancyvrb}
\usepackage{amssymb}
\usepackage{xcolor}
\EnableCrossrefs         
\CodelineIndex
\RecordChanges
\begin{document}
  \DocInput{getitems.dtx}
  \PrintChanges
  %\PrintIndex
\end{document}
%</driver>
% \fi
%
% \CheckSum{212}
%
% \CharacterTable
%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
%   Digits        \0\1\2\3\4\5\6\7\8\9
%   Exclamation   \!     Double quote  \"     Hash (number) \#
%   Dollar        \$     Percent       \%     Ampersand     \&
%   Acute accent  \'     Left paren    \(     Right paren   \)
%   Asterisk      \*     Plus          \+     Comma         \,
%   Minus         \-     Point         \.     Solidus       \/
%   Colon         \:     Semicolon     \;     Less than     \<
%   Equals        \=     Greater than  \>     Question mark \?
%   Commercial at \@     Left bracket  \[     Backslash     \\
%   Right bracket \]     Circumflex    \^     Underscore    \_
%   Grave accent  \`     Left brace    \{     Vertical bar  \|
%   Right brace   \}     Tilde         \~}
%
%
% \changes{v1.0}{2016/01/11}{Initial version}
%
% \GetFileInfo{getitems.sty}
%
% \DoNotIndex{\newcommand,\newenvironment,\def}
% 
%
% \title{The \textsf{getitems} package: \\
%        gathering {\tt\string\item}'s from a list-like environment\thanks{This document
%                corresponds to \textsf{getitems.sty}~\fileversion, dated \filedate.}}
% \author{Anders Hendrickson\\ St.~Norbert College, De~Pere, WI, USA \\ \texttt{anders.hendrickson@snc.edu}}
%
% 
% \maketitle
%
% \section{Overview}
%
% The |enumerate| and |itemize| environments of \LaTeX\ organize their contents
% through the use of the |\item| command.  Each entry in these lists is prefaced
% with the command |\item|, making for very compact and easily readable source 
% code.  Package designers may find it useful to use the same syntax for
% their custom environments.  The \textsf{getitems} package makes
% it easy to code such environments by parsing a string of tokens, separating them
% by the occurrence of |\item|'s, and saving the contents as macros.  
% Nested environments are handled correctly.
% 
% Moreover, some typesetting tasks naturally consist of a ``header'' followed by 
% several related items; one example would be a multiple-choice question on a 
% school examination.  This package saves any \TeX\ tokens appearing before the
% first |\item| as the zeroth item for special handling.
% 
% \section{Usage}
% 
% \DescribeMacro{\gatheritems}
% To parse a string of text, such as the body of an environment,
% call 
% \begin{center}
%   |\gatheritems|\marg{text to parse}.
% \end{center}
% This will scan through the \meta{text to parse}, dividing it at each |\item|
% while respecting \TeX\ groupings and nested environments, 
% and store the divided portions of text into memory.
% 
% \DescribeMacro{numgathereditems}
% The total number of items in the parsed text is stored in the \LaTeX\ counter
% |numgathereditems|.
% 
% \DescribeMacro{\gathereditem}
% To retrieve a stored item, you may call |\gathereditem|\marg{item number};
% the \meta{item number} should expand to an arabic representation of a nonnegative integer.
% Any tokens occurring before the first |\item| may be retrieved with
% |\gathereditem{0}|.
% 
% \DescribeMacro{\loopthroughitemswithcommand}
% Once the items are gathered, it will probably be necessary to loop through
% all of them.  
% Of course a package author can do so manually, but |getitems| provides a 
% built-in way to do so by calling |\loopthroughitemswithcommand|\marg{macro}.
% The \meta{macro} must be a control sequence taking exactly one argument;
% it will be called successively with the item text.
% For example,
% \begin{quote}
% \begin{tabular}{p{3in}p{1.5in}}
% \begin{minipage}{3in}
%   \begin{Verbatim}[gobble=6]
%     \gatheritems{%
%       Zero
%       \item One
%       \item Two
%       \item Three
%     }
%     \loopthroughitemswithcommand{\fbox}
%   \end{Verbatim}
% \end{minipage}
% &
% \begin{minipage}{1.5in}
%     \gatheritems{%
%       Zero
%       \item One
%       \item Two
%       \item Three
%     }
%     \loopthroughitemswithcommand{\fbox}
% \end{minipage} 
% \end{tabular}
% \end{quote}
% The result is the same as processing |\fbox{One}|, then |\fbox{Two}|, and finally |\fbox{Three}|.
% Note that |\loopthroughitemswithcommand| deliberately ignores the zeroth entry, which occurs
% before the first |\item|.
% 
% \DescribeMacro{currentitemnumber}
% Typically the package author will create a custom macro to process each item.
% This macro may make use of the index of the loop, which is stored in the 
% \LaTeX\ counter |currentitemnumber|.
% \DescribeMacro{\ifgatherbeginningofloop}
% A conditional |\ifgatherbeginningofloop| is also available,
% which only evaluates as true when
% processing the first item; it is thus functionally equivalent to
% |\ifnum1=\c@currentitemnumber|.
% The custom macro may take advantage of this to run special code for the first item only.
% 
% 
% \section{Example}
% An example using |getitems| to create a custom environment may be informative.
% We use the |\NewEnviron| command from the |environ| package 
% (automatically loaded by |getitems|) to define a |question| environment;
% the body between the |\begin{question}| and |\end{question}| is available as |\BODY|.
% \medskip
% 
% \par \noindent
% \begin{tabular}{p{3in}p{1.5in}}
% \begin{minipage}{3in}
%   \small
%   \begin{Verbatim}[gobble=6]
%     \def\doitem#1{\item #1\hfill $\Box$}%
%     \NewEnviron{question}{%
%       \expandafter\gatheritems\expandafter{\BODY}%
%       \gathereditem{0}%
%       \begin{itemize}
%         \loopthroughitemswithcommand{\doitem}
%       \end{itemize}
%     }
%     \begin{question}
%       Who proved the unsolvability of the quintic?
%       \item Abel
%       \item Galois
%       \item Lie
%     \end{question}
%   \end{Verbatim}
% \end{minipage}
% &
% \begin{minipage}{1.5in}
%     \def\doitem#1{\item #1\hfill $\Box$}%
%     \NewEnviron{question}{%
%       \expandafter\gatheritems\expandafter{\BODY}%
%       \gathereditem{0}%
%       \begin{itemize}
%         \loopthroughitemswithcommand{\doitem}
%       \end{itemize}
%     }
%     \begin{question}
%       Who proved the unsolvability of the quintic?
%       Check the appropriate box.
%       \item Abel
%       \item Galois
%       \item Lie
%     \end{question}
% \end{minipage} 
% \end{tabular}
% \medskip
% 
% 
% This second example shows that nested environments are handled as expected.
% \medskip
% 
% \par \noindent
% \begin{tabular}{p{3in}p{2in}}
% \begin{minipage}{3in}
%   \small
%   \begin{Verbatim}[gobble=6]
%     \def\doitem#1{\item[$\Box$] 
%                   \fbox{\parbox[t]{1.75in}{#1}}}%
%     \NewEnviron{question}{%
%       \expandafter\gatheritems\expandafter{\BODY}%
%       \gathereditem{0}%
%       \begin{itemize}
%         \loopthroughitemswithcommand{\doitem}
%       \end{itemize}
%     }
%     \begin{question}
%       Who proved the unsolvability of the quintic?
%       Check the appropriate box.
%       \item Abel
%             \begin{itemize}
%               \item Born August 5, 1802
%               \item Died April 6, 1829
%             \end{itemize}
%       \item Galois
%             \begin{itemize}
%               \item Born October 25, 1811
%               \item Died May 31, 1832
%             \end{itemize}
%       \item Lie
%             \begin{itemize}
%               \item Born December 17, 1842
%               \item Died February 18, 1899
%             \end{itemize}
%     \end{question}
%   \end{Verbatim}
% \end{minipage}
% &
% \begin{minipage}{2.5in}
%     \def\doitem#1{\item[$\Box$] \fbox{\parbox[t]{1.75in}{#1}}}%
%     \NewEnviron{question}{%
%       \expandafter\gatheritems\expandafter{\BODY}%
%       \gathereditem{0}%
%       \begin{itemize}
%         \loopthroughitemswithcommand{\doitem}
%       \end{itemize}
%     }
%     \begin{question}
%       Who proved the unsolvability of the quintic?
%       Check the appropriate box.
%       \item Abel
%             \begin{itemize}
%               \item Born August 5, 1802
%               \item Died April 6, 1829
%             \end{itemize}
%       \item Galois
%             \begin{itemize}
%               \item Born October 25, 1811
%               \item Died May 31, 1832
%             \end{itemize}
%       \item Lie
%             \begin{itemize}
%               \item Born December 17, 1842
%               \item Died February 18, 1899
%             \end{itemize}
%     \end{question}
% \end{minipage} 
% \end{tabular}
% 
% 
% \StopEventually{}
%
% \section{Implementation}
% 
% We need the |trimspaces| package to remove excess spaces
% from the items we find.
% Although the |environ| package is not used by |getitems| itself,
% it will almost certainly be needed.
%    \begin{macrocode}
\RequirePackage{environ}
\RequirePackage{trimspaces}
\let\xa=\expandafter
%    \end{macrocode}
%  \begin{macro}{\gathereditem}
%    The $k$th item found will be stored in the macro |\getitems@item@|\meta{k};
%    the user can access it through the |\gathereditem| macro.
%    \begin{macrocode}
\def\gathereditem#1{\csname getitems@item@#1\endcsname}
%    \end{macrocode}
%  \end{macro}
%  
%  \begin{macro}{numgathereditems}
%    We define the \LaTeX\ counter |numgathereditems|.
%    \begin{macrocode}
\newcounter{numgathereditems}
%    \end{macrocode}
%  \end{macro}
%  
%  \begin{macro}{\gatheritems}
%    The main control sequence of this package is |\gatheritems|.
%    The na\"ive strategy is to use the delimiter mechanism of \TeX\ to
%    split the text at the first occurrence of the token ``|\item|.''
%    We add |\getitems@relax| before, 
%    and ``|\item\getitems@terminalitem|'' after, the text to help us
%    detect empty items and prevent
%    errors after we have found all the genuine |\item|'s.
%    \begin{macrocode}
\long\def\gatheritems#1{%
  \setcounter{getitems@begindepth}{0}%
  \setcounter{numgathereditems}{0}%
  \xa\long\xa\gdef\csname getitems@item@0\endcsname{}%
  \gatheritems@int\getitems@relax#1\item\getitems@terminalitem\getitems@endgatheritems
  \xa\let\xa\gatheredheader\xa=\csname getitems@item@0\endcsname
}
%    \end{macrocode}
%  \end{macro}
%  The trouble with the na\"ive strategy is that it won't handle nested
%  environments correctly.  To do that, we need to keep track of how deeply
%  nested we are with the macro |\getitems@trackbegindepth|, defined below.
%  That macro stores its results in the \LaTeX\ counter |getitems@begindepth|;
%  a value of 0 indicates the top-level within the argument of |\gatheritems|.
%    \begin{macrocode}
\def\@getitems@terminalitem{\getitems@terminalitem}%
\def\@dummy@relax{\getitems@relax}%
\long\def\gatheritems@int#1\item#2\getitems@endgatheritems{%
  \getitems@trackbegindepth{#1}%
  \ifnum\c@getitems@begindepth=0\relax
%    \end{macrocode}
% At this point we have gathered a complete |\item|; we have not stopped 
% accidentally at a sub|\item|.  The original |\item| might have had no content,
% in which case |#1| will be simply ``|\getitems@relax|'', and we do nothing;
% otherwise we strip off the |\getitems@relax| and store those tokens in 
% |\getitems@item@|\meta{numgathereditems}.
%    \begin{macrocode}
    \def\getitems@test@i{#1}%
    \ifx\getitems@test@i\@dummy@relax
      \relax
    \else
      \xa\xa\xa\g@addto@macro
         \xa\xa\csname getitems@item@\the\c@numgathereditems\endcsname
            \xa{\getitems@stripfirsttokenfrom#1\getitems@endstrip}%
    \fi
%    \end{macrocode}
% Now we test whether we have reached the end of the text to be parsed.
% This is the case if |#2| is simply |\getitems@terminalitem|,
% and we stop the recursion.
% Otherwise there is at least one more |\item| to process, so we increment |numgathereditems|,
% prepare |\getitems@item@|\meta{k+1},
% and prepare to recurse.
%    \begin{macrocode}
    \def\getitems@test@ii{#2}%
    \ifx\getitems@test@ii\@getitems@terminalitem
      \let\getitems@next=\relax
    \else
      \stepcounter{numgathereditems}%
      \xa\gdef\csname getitems@item@\the\c@numgathereditems\endcsname{}%
      \def\getitems@next{\gatheritems@int\getitems@relax#2\getitems@endgatheritems}%
    \fi
  \else
%    \end{macrocode}
% We are now in the case where |getitems@begindepth|${}\neq 0$.
% This essentially means that the text in |#1| has more |\begin|'s than |\end|'s,
% so we have not read a complete |\item|; we stopped at an ``|\item|'' token
% within a sub-environment.
% We save the text gathered so far to |\getitems@item@|\meta{k},
% including the |\item| we parsed by mistake,
% and then call |\gatheritems@int| again to sweep up more tokens.
%    \begin{macrocode}
    \xa\xa\xa\g@addto@macro
       \xa\xa\csname getitems@item@\the\c@numgathereditems\endcsname
          \xa{\getitems@stripfirsttokenfrom#1\getitems@endstrip}%
    \xa\g@addto@macro\csname getitems@item@\the\c@numgathereditems\endcsname{\item}%
    \def\getitems@next{\gatheritems@int\getitems@relax#2\getitems@endgatheritems}%
  \fi
  \getitems@next
}
%    \end{macrocode}
% This next macro is used by |\gatheritems@int| to strip off a 
% dummy |\getitems@relax| token from the beginning of its first parameter.
%    \begin{macrocode}
\long\def\getitems@stripfirsttokenfrom#1#2\getitems@endstrip{#2}
%    \end{macrocode}
% Here is the code used to track the depth of nesting of |\begin|'s in a text.
%    \begin{macrocode}
\newcounter{getitems@begindepth}
\long\def\getitems@trackbegindepth#1{%
  \getitems@trackbegindepth@int#1\getitems@terminalbegindepth\getitems@endtrackbegindepth
}
\def\@getitems@begin{\begin}%
\def\@getitems@end{\end}%
\def\@getitems@terminalbegindepth{\getitems@terminalbegindepth}%
\long\def\getitems@trackbegindepth@int#1#2\getitems@endtrackbegindepth{%
  \def\getitems@test@i{#1}%
  \ifx\getitems@test@i\@getitems@begin
    \advance\c@getitems@begindepth by 1\relax
  \else
    \ifx\getitems@test@i\@getitems@end
      \advance\c@getitems@begindepth by -1\relax
    \fi
  \fi
  \def\getitems@test@ii{#2}%
  \trim@spaces@in\getitems@test@ii
  \ifx\getitems@test@ii\@getitems@terminalbegindepth
    \let\getitems@trackbegindepth@next=\relax
  \else
    \def\getitems@trackbegindepth@next{%
      \getitems@trackbegindepth@int#2\getitems@endtrackbegindepth}%
  \fi
  \getitems@trackbegindepth@next
}
%    \end{macrocode}
% \begin{macro}{\loopthroughitemswithcommand}
%   Finally, we define the user-level command to loop through
%   the gathered items from 1 through |numgathereditems|.
%    \begin{macrocode}
\newif\ifgatherbeginningofloop
\newcounter{currentitemnumber}
\def\loopthroughitemswithcommand#1{%
  \setcounter{currentitemnumber}{1}%
  \gatherbeginningoflooptrue
  \loopthroughitemswithcommand@int{#1}%
}

\def\loopthroughitemswithcommand@int#1{%
  \ifnum\c@currentitemnumber>\c@numgathereditems\relax
    \let\getitems@loop@next=\relax%
  \else
    \xa\xa\xa#1\xa\xa\xa{\csname getitems@item@\the\c@currentitemnumber\endcsname}%
    \def\getitems@loop@next{\loopthroughitemswithcommand@int{#1}}%
    \stepcounter{currentitemnumber}%
  \fi
  \gatherbeginningofloopfalse
  \getitems@loop@next
}
%    \end{macrocode}
% \end{macro}
%
% \Finale
\endinput
