%\iffalse
% xfor.dtx generated using makedtx version 0.94b (c) Nicola Talbot
% Command line args:
%   -src "xfor.sty\Z=>xfor.sty"
%   -src "sample.tex\Z=>sample.tex"
%   -doc "xfor-manual.tex"
%   -author "Nicola Talbot"
%   -dir "source"
%   xfor
% Created on 2009/2/5 16:02
%\fi
%\iffalse
%<*package>
%% \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         \~}
%</package>
%\fi
% \iffalse
% Doc-Source file to use with LaTeX2e
% Copyright (C) 2009 Nicola Talbot, all rights reserved.
% \fi
% \iffalse
%<*driver>
\documentclass[a4paper]{ltxdoc}
\usepackage{xfor}
\usepackage{ifthen}
\usepackage{alltt}
\usepackage[colorlinks,
            bookmarks,
            hyperindex=false,
            pdfauthor={Nicola L.C. Talbot},
            pdftitle={xfor: redefinition of \string\@for},
            pdfkeywords={LaTeX,package development}]{hyperref}

\CheckSum{197}
\PageIndex
\RecordChanges
\newcommand*{\sty}[1]{\textsf{#1}}

\begin{document}
\DocInput{xfor.dtx}
\end{document}
%</driver>
%\fi
%\MakeShortVerb{"}
%
% \title{xfor v1.05: Reimplementation of \cs{@for} to allow
%premature termination of the loop}
% \author{Nicola L.C. Talbot\\[10pt]
%School of Computing Sciences\\
%University of East Anglia\\
%Norwich. Norfolk\\
%NR4 7TJ. United Kingdom.\\
%\url{http://theoval.cmp.uea.ac.uk/~nlct/}}
%
%\date{5th February 2009}
%\maketitle
%\tableofcontents
%
%\section{Introduction}
%\changes{1.0}{2007 June 27}{Initial version}
%The \sty{xfor} package redefines \cs{@for} so that the loop can
%be prematurely terminated, akin to C/Java's \texttt{break} statement
%except that the loop will terminate at the \emph{end} of the
%current iteration. The syntax for \DescribeMacro{\@for}\cs{@for} 
%remains the same:
%\begin{quote}
%\cs{@for}\meta{cmd}":="\meta{list}"\do"\marg{body}
%\end{quote}
%where \meta{cmd} is a command name that is assigned to the current
%element of the list given by \meta{list} at each iteration.
%
%To terminate the loop at the end of the current
%iteration, use the command \DescribeMacro{\@endfortrue}\cs{@endfortrue}. 
%This command may be used anywhere in \meta{body}, but will only
%take effect at the end of the current iteration.
%The remainder of the list is stored in 
%\DescribeMacro{\@forremainder}\cs{@forremainder}. You can test 
%whether the loop was prematurely terminated using the conditional
%\DescribeMacro{\if@endfor}\cs{if@endfor}.
%
%As from version 1.02, there is also provision for looking ahead.
%At each iteration in the loop, the next element is stored in
%\cs{@xfor@nextelement}\DescribeMacro{\@xfor@nextelement}. 
%On the last iteration, this value
%will be \cs{@nil}, and so can be checked using
%\begin{verbatim}
% \ifx\@xfor@nextelement\@nnil
% % last iteration
% \else
% % not last iteration
% \fi
%\end{verbatim}
%
%\subsection{Example (ordered insertion)}
%
%Suppose you have list of sorted numbers stored in the command 
%\cs{mylist}, e.g.:
%\begin{verbatim}
%\def\mylist{1,3,5,7,8,12,15,20}
%\end{verbatim}
%and you want to insert a new value given by the command 
%\cs{newval}, e.g.
%\begin{verbatim}
%\def\newval{11}
%\end{verbatim}
%in the correct order. You can use \cs{@for} to iterate through
%each element in the sorted list, testing the value against the
%new value to be inserted. Once the new value has been inserted,
%the loop can be terminated, and any remaining elements can be
%appended to the new list. The following 
%defines the command \cs{insertinto}\marg{new val}\marg{list}
%which uses this method:
%\begin{verbatim}
% \newcommand{\insertinto}[2]{%
% \def\nlst{}% new list initially empty
% \@for\n:=#2\do{%
% % store new list in \toks@
% \expandafter\toks@\expandafter{\nlst}%
% % test current value against new value
% \ifnum\n>#1\relax
%   % new value needs to be inserted before current value
%   \edef\newstuff{\number#1,\n}%
%   % end for loop at the end of this iteration
%   \@endfortrue
% \else
%   \edef\newstuff{\n}%
% \fi
% % append new stuff to new list
% \ifx\nlst\@empty
%   \edef\nlst{\newstuff}%
% \else
%   \edef\nlst{\the\toks@,\newstuff}%
% \fi
% }%
% % check to see if for loop was prematurely terminated
% \if@endfor
%  % loop may have been terminated during final iteration, in
%  % which case \@forremainder is empty.
%  \ifx\@forremainder\@empty
%    % do nothing
%  \else
%    % loop prematurely ended, append remainder of original list
%    % to new list
%    \expandafter\toks@\expandafter{\nlst}%
%    \edef\nlst{\the\toks@,\@forremainder}%
%  \fi
% \else
%  % wasn't prematurely terminated, so new value hasn't been added
%  % so add now.
%   \expandafter\toks@\expandafter{\nlst}%
%   \ifx\nlst\@empty
%     \edef\nlst{\number#1}%
%   \else
%     \edef\nlst{\the\toks@,\number#1}%
%   \fi
% \fi
% \let#2=\nlst
% }
%\end{verbatim}
%The \cs{insertinto} macro can then be used as follows:
%\begin{verbatim}
%\def\mylist{1,2,5,9,12,15,18,20}%
%\def\newval{11}%
%Original list: \mylist. New value: \newval.
%
%\insertinto{\newval}{\mylist}
%New list: \mylist.
%\end{verbatim}
%
%\subsection{Example (numerical insertion sort)}
%
%Care needs to be taken when nesting \cs{@for}-loops.
%Suppose you have a list of unsorted numbers, say
%\begin{verbatim}
%\def\mylist{4,2,7,1,10,11,20,15}
%\end{verbatim}
%and you want to sort the list in numerical order using an insertion
%sort method. To do this, a macro needs to be defined which iterates
%through each element in the unordered list, and the element 
%is then inserted into an ordered list. The previous example
%described the macro \cs{insertinto} which does this, but this results
%in nested \cs{@for} commands. The \cs{insertinto} command will need
%to be grouped to avoid errors:
%\begin{verbatim}
%\newcommand*{\insertionsort}[1]{%
%\def\sortedlist{}%
%\@for\val:=#1\do{{\insertinto{\val}{\sortedlist}}}%
%\let#1=\sortedlist
%}
%\end{verbatim}
%This won't work with the definition of \cs{insertinto} as
%given in the previous section, as the grouping causes the
%definition of the sorted list to be localised to that group.
%Replacing
%\begin{verbatim}
%\let#2=\nlst
%\end{verbatim}
%with
%\begin{verbatim}
%\global\let#2=\nlst
%\end{verbatim}
%at the end of the definition of \cs{insertinto} will fix that.
%
%\subsection{Example (looking ahead)}
%
%This example checks the next value to determine if the loop
%is on the last iteration, if it is, it does nothing, otherwise
%it does a semi-colon:
%\begin{verbatim}
%\makeatletter
%\def\mylist{1,2,3,4,5}%
%\@for\val:=\mylist\do{\val
%\ifx\@xfor@nextelement\@nnil \else ;\fi}
%\makeatother
%\end{verbatim}
%which produces:
%\makeatletter
%\def\mylist{1,2,3,4,5}\relax
%\@for\val:=\mylist\do{\val
%\ifx\@xfor@nextelement\@nnil \else ;\fi}
%\makeatother
%
%\section{Acknowledgements}
%
%Many thanks to Morten~H\o gholm for providing code to improve
%efficiency.
%
% \StopEventually{\phantomsection
%\addcontentsline{toc}{section}{Change History}
%\PrintChanges\phantomsection
%\addcontentsline{toc}{section}{Index}
%\PrintIndex}
%
%
%
%\section{The Code}
%\iffalse
%    \begin{macrocode}
%<*xfor.sty>
%    \end{macrocode}
%\fi
% Note that the internal macros used by \cs{@for} have changed
% in version 1.04.
%
%    \begin{macrocode}
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{xfor}[2009/02/05 v1.05 (NLCT)]
%    \end{macrocode}
%\begin{macro}{\if@endfor}
% Define a switch to determine if the for loop should be 
% stopped prematurely.
%    \begin{macrocode}
\newif\if@endfor
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@gobbleseven}
%\changes{1.04}{2009 January 25}{added by Morten H\o gholm}
% Ignore seven arguments.
%    \begin{macrocode}
\long\def\@gobbleseven#1#2#3#4#5#6#7{}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@for}
% \cs{@for}\meta{cmd}":="\meta{list}\cs{do}\marg{body}
% test if the list is empty and then re-arrange
%\changes{1.04}{2009 January 25}{Modified by Morten H\o gholm to
% improve efficiency}
%    \begin{macrocode}
\long\def\@for#1:=#2\do{%
%    \end{macrocode}
% Initialise
%    \begin{macrocode}
	\@endforfalse
	\def\@forremainder{}%
	\expandafter\def\expandafter\@fortmp\expandafter{#2}%
%    \end{macrocode}
% If list is empty do nothing
%    \begin{macrocode}
	\ifx\@fortmp\@empty
		\expandafter\@gobbleseven
	\fi
	\expandafter\@@for\expandafter#1\expandafter{#2}%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@@for}
% Initialise for loop
%\changes{1.04}{2009 January 25}{Added by Morten H\o gholm}
%    \begin{macrocode}
\long\def\@@for#1#2#3{%
	\@xforloop#1{#3}#2,\@nil,\@nil,%
        \@xfor@endmarker% magic end marker
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@xfornoop}
%\changes{1.04}{2009 January 25}{second and third arguments dropped (MH)}
%\changes{1.04}{2009 January 25}{\cs{@fornoop} replaced by
% \cs{@xfornoop} to prevent conflict with \cs{@tfor}}
% Read up until magic end marker.
%    \begin{macrocode}
\long\def\@xfornoop#1\@xfor@endmarker{}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@xforloop}
%\cs{@forloop}\marg{var}\marg{action}
%\changes{1.04}{2009 January 25}{Modified by Morten H\o gholm to
% improve efficiency}
%\changes{1.05}{2009 February 5}{\cs{@forloop} replaced by
% \cs{@xforloop} to prevent conflict with other packages that
% use \cs{@forloop}}
%    \begin{macrocode}
\long\def\@xforloop#1#2#3,#4,{%
	\def#1{#3}%
	\ifx#1\@nnil
%    \end{macrocode}
% Grab the \cs{@xfor@endmarker} at the very end
%    \begin{macrocode}
		\expandafter\@xfornoop 
	\fi
%    \end{macrocode}
% Removed |\@xfor@storenext#4,\@nil|. Instead store next element
% in \cs{@xfor@nextelement}.
%    \begin{macrocode}
	\def\@xfor@nextelement{#4}%
	#2%
	\if@endfor
		\expandafter\@iforgatherrest
	\fi
	\@xforloop#1{#2}{#4},%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@iforgatherrest}
% Gather the remainder (and store in \cs{@forremainder})
%\changes{1.01}{2007 July 11}{made long}%
%\changes{1.04}{2009 January 25}{argument syntax changed (MH)}
%    \begin{macrocode}
\long\def\@iforgatherrest \@xforloop#1#2#3,#4\@xfor@endmarker{%
	\def\@fortmp{#3}%
	\ifx\@fortmp\@nnil
		\def\@forremainder{}%
	\else
		\@forgatherrest{#3},#4\@xfor@endmarker%
	\fi
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@forgatherrest}
% Get remainder of list (stored in \cs{@forremainder}):
%\changes{1.01}{2007 July 11}{made long}%
%\changes{1.04}{2009 January 25}{argument syntax changed (MH)}
%    \begin{macrocode}
\long\def\@forgatherrest#1,\@nil,\@nil,\@xfor@endmarker{%
	\def\@forremainder{#1}%
}
%    \end{macrocode}
%\end{macro}
%
%\changes{1.02}{2007 August 16}{Added \cs{@xfor@storenext}}%
%\changes{1.04}{2009 January 25}{Removed \cs{\@xfor@storenext}}%
%\changes{1.04}{2009 January 25}{removed \cs{@iforloop}}

%\iffalse
%    \begin{macrocode}
%</xfor.sty>
%    \end{macrocode}
%\fi
%\iffalse
%    \begin{macrocode}
%<*sample.tex>
%    \end{macrocode}
%\fi
%\section{Sample Document (sample.tex)}
%    \begin{macrocode}
\listfiles
\documentclass{article}

\usepackage{xfor}

\makeatletter

% \insertinto{new value}{list}

\newtoks\tmptok

\newcommand{\insertinto}[2]{%
\def\nlst{}%
\@for\n:=#2\do{%
% store new list in \tmptok
\expandafter\tmptok\expandafter{\nlst}%
% test current value against new value
\ifnum\n>#1\relax
  \edef\newstuff{\number#1,\n}%
  % end for loop at the end of this iteration
  \@endfortrue
\else
  \edef\newstuff{\n}%
\fi
% append new stuff to new list
\ifx\nlst\@empty
  \edef\nlst{\newstuff}%
\else
  \edef\nlst{\the\tmptok,\newstuff}%
\fi
}%
% check to see if for loop was prematurely terminated
\if@endfor
 % loop may have been terminated during final iteration, in
 % which case \@forremainder is empty.
 \ifx\@forremainder\@empty
   % do nothing
 \else
   % loop prematurely ended, append remainder of original list
   % to new list
   \expandafter\tmptok\expandafter{\nlst}%
   \edef\nlst{\the\tmptok,\@forremainder}%
 \fi
\else
 % wasn't prematurely terminated, so new value hasn't been added.
 % Add now.
  \expandafter\tmptok\expandafter{\nlst}%
  \ifx\nlst\@empty
    \edef\nlst{\number#1}%
  \else
    \edef\nlst{\the\tmptok,\number#1}%
  \fi
\fi
\global\let#2=\nlst
}

% \insertionsort{list}
% replaces list with sorted list

\newcommand{\insertionsort}[1]{%
\def\sortedlist{}%
\@for\val:=#1\do{{\insertinto{\val}{\sortedlist}}}%
\let#1=\sortedlist}

\makeatother

\begin{document}
Unsorted list:
\def\mylist{4,2,7,1,10,11,20,15}\mylist.

\insertionsort{\mylist}%
Sorted list: \mylist.

Iterate through the list (next element in parentheses):
\makeatletter
\@for\n:=\mylist\do{%
\n
\ifx\@xfor@nextelement\@nnil
 % last iteration
\else
 (\@xfor@nextelement);
\fi
}.
\end{document}
%    \end{macrocode}
%\iffalse
%    \begin{macrocode}
%</sample.tex>
%    \end{macrocode}
%\fi
%\Finale
\endinput
