summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/getitems
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/getitems
Initial commit
Diffstat (limited to 'macros/latex/contrib/getitems')
-rw-r--r--macros/latex/contrib/getitems/README.md49
-rw-r--r--macros/latex/contrib/getitems/getitems.dtx460
-rw-r--r--macros/latex/contrib/getitems/getitems.ins57
-rw-r--r--macros/latex/contrib/getitems/getitems.pdfbin0 -> 213889 bytes
4 files changed, 566 insertions, 0 deletions
diff --git a/macros/latex/contrib/getitems/README.md b/macros/latex/contrib/getitems/README.md
new file mode 100644
index 0000000000..b7d43e9e80
--- /dev/null
+++ b/macros/latex/contrib/getitems/README.md
@@ -0,0 +1,49 @@
+==============================================================================
+
+The `getitems' package v1.0
+Copyright (C) 2016 Anders Hendrickson (anders.hendrickson@snc.edu)
+
+This package provides a \gatheritems command to parse a list of data separated
+by \item tokens. This makes it easier to define custom environments which
+structure their data in the same way that itemize or enumerate do.
+
+Changes:
+- 2016/01/11 Initial version
+
+==============================================================================
+
+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 consists of the files:
+README (this file)
+getitems.dtx
+getitems.ins
+ and the derived file:
+getitems.sty
+
+ The distribution consists of the files:
+README (this file)
+getitems.dtx
+getitems.ins
+getitems.pdf (the user manual)
+
+-----------------------------------------------------------------
+
+ To install the package:
+- run: latex getitems.ins (which will generate getitems.sty)
+- Move getitems.sty to a location where LaTeX will find it (typically
+ in a local texmf tree at tex/latex/getitems) and refresh the
+ file database. See the FAQ on CTAN at help/uk-tex-faq or
+ http://www.tug.ac.uk/faq for more information on this.
+ To process the user manual
+- run: pdflatex getitems.dtx
+- run: pdflatex getitems.dtx
diff --git a/macros/latex/contrib/getitems/getitems.dtx b/macros/latex/contrib/getitems/getitems.dtx
new file mode 100644
index 0000000000..f5dc7c12ba
--- /dev/null
+++ b/macros/latex/contrib/getitems/getitems.dtx
@@ -0,0 +1,460 @@
+% \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
diff --git a/macros/latex/contrib/getitems/getitems.ins b/macros/latex/contrib/getitems/getitems.ins
new file mode 100644
index 0000000000..a6e527bf3f
--- /dev/null
+++ b/macros/latex/contrib/getitems/getitems.ins
@@ -0,0 +1,57 @@
+%% getitems.ins
+%% Copyright 2016 by Anders O.F. Hendrickson
+%%
+%% 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 getitems.dtx and getitems.ins
+%% and the derived file getitems.sty.
+
+\input docstrip.tex
+\keepsilent
+
+\usedir{tex/latex/getitems}
+
+\preamble
+
+This is a generated file.
+
+Copyright (C) 2016 by Anders 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.
+
+\endpreamble
+
+\generate{\file{getitems.sty}{\from{getitems.dtx}{package}}}
+
+\obeyspaces
+\Msg{*************************************************************}
+\Msg{* *}
+\Msg{* To finish the installation you have to move the following *}
+\Msg{* file into a directory searched by TeX: *}
+\Msg{* *}
+\Msg{* getitems.sty *}
+\Msg{* *}
+\Msg{* To produce the documentation run the file getitems.dtx *}
+\Msg{* through LaTeX. *}
+\Msg{* *}
+\Msg{* Happy TeXing! *}
+\Msg{* *}
+\Msg{*************************************************************}
+
+\endbatchfile
diff --git a/macros/latex/contrib/getitems/getitems.pdf b/macros/latex/contrib/getitems/getitems.pdf
new file mode 100644
index 0000000000..09a8dd833e
--- /dev/null
+++ b/macros/latex/contrib/getitems/getitems.pdf
Binary files differ