% \iffalse
%% File: l3candidates.dtx Copyright (C) 2005-2011 LaTeX3 project
%%
%% It may be distributed and/or modified under the conditions of the
%% LaTeX Project Public License (LPPL), either version 1.3c of this
%% license or (at your option) any later version.  The latest version
%% of this license is in the file
%%
%%    http://www.latex-project.org/lppl.txt
%%
%% This file is part of the ``expl3 bundle'' (The Work in LPPL)
%% and all files in that bundle must be distributed together.
%%
%% The released version of this bundle is available from CTAN.
%%
%% -----------------------------------------------------------------------
%%
%% The development version of the bundle can be found at
%%
%%    http://www.latex-project.org/svnroot/experimental/trunk/
%%
%% for those people who are interested.
%%
%%%%%%%%%%%
%% NOTE: %%
%%%%%%%%%%%
%%
%%   Snapshots taken from the repository represent work in progress and may
%%   not work or may contain conflicting material!  We therefore ask
%%   people _not_ to put them into distributions, archives, etc. without
%%   prior consultation with the LaTeX Project Team.
%%
%% -----------------------------------------------------------------------
%
%<*driver|package>
\RequirePackage{expl3}
%</driver|package>
%\fi
\errorcontextlines=999
\GetIdInfo$Id: l3candidates.dtx 2179 2011-03-06 09:06:18Z mittelba $
          {L3 Experimental 'extras' module}
%\iffalse
%<*driver>
%\fi
\ProvidesFile{\filename.\filenameext}
  [\filedate\space v\fileversion\space\filedescription]
%\iffalse
\documentclass[full]{l3doc}
\begin{document}
\DocInput{l3candidates.dtx}
\end{document}
%</driver>
% \fi
%
%
% \title{The \textsf{l3candidates} package\thanks{This file
%         has version number \fileversion, last
%         revised \filedate.}}
% \author{\Team}
% \date{\filedate}
% \maketitle
%
% \begin{documentation}
%
% \section{Intro}
%
% This \emph{experimental} package contains additions to the \pkg{expl3}
% programming language before they're added to the `official' packages.
% The functions defined within will fall into three categories:
% \begin{itemize}
% \item Will be added directly to a corresponding \pkg{expl3} module at some stage.
% \item Will be re-worked and added to a module with slightly different name or behaviour.
% \item Will eventually vanish.
% \end{itemize}
% Beware, then, that loading this package and using its contents may cause your
% code to break down the track.
%
% \section{Functions for characters}
%
%
% \begin{function}{\char_active_set:Npn|\char_active_gset:Npn}
% \begin{syntax}
% |\char_active_set:Npn|~<char>~<param>~<definition>
% \end{syntax}
% Makes <char> active and gives it the definition specified as if it were
% a function.
% \end{function}
%
% \begin{function}{\char_active_set_eq:NN|\char_active_gset_eq:NN}
% \begin{syntax}
% |\char_active_set:Npn|~<char>~<function>
% \end{syntax}
% Makes <char> active and makes it equal to <function>.
% (Or another active char, etc.)
% \end{function}
%
%
%
% \section{Functions for token lists}
%
% \begin{function}{\tl_trim_spaces:n|\tl_trim_spaces:N}
% \begin{syntax}
% |\tl_trim_spaces:n|~|{|<token list>|}|
% |\tl_trim_spaces:n|~|{|\verb*| |<token list>\verb*| ||}|
% |\tl_trim_spaces:N| <tl var.>
% \end{syntax}
% After a full expansion, |\tl_trim_space:n| returns <token list> stripped
% of any preceeding and trailing spaces.
% For example, to set a token list variable to a trim-spaced argument,
% use something like this:
% \begin{verbatim}
% \tl_set:Nx \l_tmpa_tl { \tl_trim_spaces:n {#1} }
% \end{verbatim}
% |\tl_trim_spaces:N| removes preceeding and trailing spaces from the
% contents of its token list variable argument.
% \end{function}
%
%
% \section{Functions for sequences}
%
%
% \begin{function}{\seq_mapthread_function:NNN}
% \begin{syntax}
% "\seq_mapthread_function:NNN" <seq1> <seq2> <function>
% \end{syntax}
% Applies to <function> as arguments each pair of
% corresponding elements within <seq1> and <seq2> (which must have the same
% number of elements).
%
% For example, if "\l_mya_seq" contains "a", "b", "c" and
% "\l_myb_seq" contains "x", "y", "z", then
% \begin{verbatim}
% \seq_mapthread_function:NNN \l_mya_seq \l_myb_seq \my_func:nn
% \end{verbatim}
% is the same as executing
% \begin{verbatim}
% \my_func:nn {a} {x}
% \my_func:nn {b} {y}
% \my_func:nn {c} {z}
% \end{verbatim}
% \end{function}
%
%
% \begin{function}{\seq_get_length:NN}
% \begin{syntax}
% |\seq_get_length:NN| <seq> <int>
% \end{syntax}
% Sets <int> to the number of elements in <seq>.
% \end{function}
%
%
% \begin{function}{\seq_set_from_clist:NN|\seq_set_from_clist:Nn|
%                  \seq_gset_from_clist:NN|\seq_gset_from_clist:Nn}
% \begin{syntax}
% "\seq_set_from_clist:Nn" <seq> \Arg{clist}
% "\seq_set_from_clist:NN" <seq> <clist variable>
% \end{syntax}
% Transforms comma-list <clist> into sequence <seq>.
% \end{function}
%
%
% \section{Functions for comma-lists}
%
% \begin{function}{\clist_set_from_seq:NN|\clist_gset_from_seq:NN}
% \begin{syntax}
% "\clist_set_from_seq:NN" <clist> <seq>
% \end{syntax}
% Transforms sequence <seq> into comma-list variable <clist>.
% \end{function}
%
%
% \begin{function}{\clist_if_in_numrange:nn / (TF)}
% \begin{syntax}
% "\clist_if_in_numrange:nnTF" \Arg{intexpr} \Arg{numrange}
%                              \Arg{true} \Arg{false}
% \end{syntax}
% When parsing user input to specify whether numerical elements
% should be displayed/operated upon, it is common to use input such as
% `|-4,7-11,17-|' to indicate ranged but sometimes discontiguous sets.
% (In this particular example, we'd be specifying
%  $x\le4 \wedge 7\le x\le 11 \wedge x\ge 17$.)
% This function can be used to test whether the input number
% (actually <intexpr>) exists within the specified <numrange>.
%
% <numrange> need not be sorted and may contain overlapping ranges.
% Numbers inside ranges may consist of integer expressions or anything
% considered by \TeX\ to be a number
% (such as `|`\A|', which is decimal number 65).
%
% This function could probably be made expandable with sufficient effort.
% \end{function}
%
%
%
%\begin{function}{ 
%  \clist_length:N / (EXP) |
%  \clist_length:c / (EXP) |
%  \clist_length:n / (EXP) |
%}
%  \begin{syntax}
%    \cs{clist_length:N} \Arg{comma-list}
%  \end{syntax}
%  Counts the number of \meta{elements} in the \Arg{comma-list} and
%  leaves this information in the input stream. The number of 
%  \meta{elements} will be one more than the number of unbraced 
%  \verb"," tokens of category code \( 12 \) (other) within the
%  \meta{comma-list}. This function requires two expansions, 
%  giving an \meta{integer denotation}.
%\end{function}
%
%\begin{function}{ 
%  \clist_item:Nn / (EXP) |
%  \clist_item:cn / (EXP) |
%  \clist_item:nn / (EXP) |
%}
%  \begin{syntax}
%    \cs{clist_item:Nn} \Arg{comma-list} \Arg{offset}
%  \end{syntax}
%  Locates the \meta{element} in the \meta{comma-list} with the 
%  \meta{offset} specified, and leaves the result in the input stream.
%  The \meta{offset} should be an integer expression, and is the number
%  of places from the start of the list at which the \meta{element} is
%  located. The there is no \meta{element} with the \meta{offset} 
%  specified then the full expansion of the function will be empty.
%  Negative \meta{offset} values work from the end of the
%  \meta{comma-list}, such that and \meta{meta} of \( -1 \) will 
%  leave the last item of the \meta{comma-list} in the input stream.
%\end{function}
%
%
%
% \end{documentation}
%
% \begin{implementation}
%
% \section{Implementation}
%
%
%    \begin{macrocode}
%<*package>
\ProvidesExplPackage
  {\filename}{\filedate}{\fileversion}{\filedescription}
\package_check_loaded_expl:
%</package>
%<*initex|package>
%    \end{macrocode}
%
%
% \begin{macro}{\char_active_set:Npn,\char_active_set:Npx,\char_active_gset:Npn,\char_active_gset:Npx}
% \begin{macro}{\char_active_set_eq:NN,\char_active_gset_eq:NN}
%    \begin{macrocode}
\group_begin:
\char_make_active:N \^^@
\cs_set:Npn \char_tmp:NN {
  \cs_gnew:Npn #1 ##1 {
    \char_make_active:n {`##1}
    \group_begin:
      \tex_lccode:D `\^^@ `##1
      \tex_lowercase:D{\group_end: #2 ^^@}
  }
}
\char_tmp:NN \char_active_set:Npn    \cs_set:Npn
\char_tmp:NN \char_active_set:Npx    \cs_set:Npx
\char_tmp:NN \char_active_gset:Npn   \cs_gset:Npn
\char_tmp:NN \char_active_gset:Npx   \cs_gset:Npx
\char_tmp:NN \char_active_set_eq:NN  \cs_set_eq:NN
\char_tmp:NN \char_active_gset_eq:NN \cs_gset_eq:NN
\group_end:
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
%
%
% \begin{macro}{\tl_trim_spaces:n,\tl_trim_spaces:N}
%    \begin{macrocode}
\cs_new:Npn \tl_trim_spaces:n #1 {
  \exp_not:n \exp_after:wN \exp_after:wN \exp_after:wN
    { \tl_trim_spaces_exp:n {#1} }
}
\cs_new:Npn \tl_trim_spaces:N #1 {
  \tl_set:Nx #1 { \exp_after:wN \tl_trim_spaces:n \exp_after:wN {#1} }
}
%    \end{macrocode}
%
%    \begin{macrocode}
\char_make_math_shift:N \Q
\cs_new:Npn \tl_trim_spaces_exp:n #1 {
  \tex_romannumeral:D -`\q \tl_trim_spaces_aux_i:w \exp_not:N #1 Q~Q
}
\cs_new:Npn \tl_trim_spaces_aux_i:w #1~Q { \tl_trim_spaces_aux_ii:w #1 Q }
\cs_new:Npn \tl_trim_spaces_aux_ii:w #1 Q #2 {#1}
\char_make_letter:N \Q
%    \end{macrocode}
% \end{macro}
%
%
%
%
% \begin{macro}{\seq_mapthread_function:NNN}
%    \begin{macrocode}
\seq_new:N \l_tmpb_seq
%    \end{macrocode}
%
%
% \begin{macro}{\seq_get_length:NN}
%    \begin{macrocode}
\cs_new:Nn \seq_get_length:NN {
  \int_zero:N #1
  \seq_map_inline:Nn #2 { \int_incr:N #1}
}
%    \end{macrocode}
% \end{macro}
%
%    \begin{macrocode}
\cs_new:Nn \seq_mapthread_function:NNN {
  \seq_get_length:NN \l_tmpa_int #1
  \seq_get_length:NN \l_tmpb_int #2
  \int_compare:nTF { \l_tmpa_int == \l_tmpb_int }{
    \seq_set_eq:NN \l_tmpa_seq #1
    \seq_set_eq:NN \l_tmpb_seq #2
    \prg_stepwise_inline:nnnn{1}{1}{\l_tmpa_int}{
      \seq_pop:NN \l_tmpa_seq \l_kernel_tmpa_tl
      \seq_pop:NN \l_tmpb_seq \l_kernel_tmpb_tl
      \exp_args:NVV #3 \l_kernel_tmpa_tl \l_kernel_tmpb_tl
    }
  }{\ERROR}
}
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\seq_set_from_clist:Nn,\seq_set_from_clist:NN}
% \begin{macro}{\seq_gset_from_clist:Nn,\seq_gset_from_clist:NN}
%    \begin{macrocode}
\cs_set:Npn  \seq_set_from_clist:Nn #1#2 {
  \seq_clear:N #1
  \clist_map_inline:nn {#2} { \seq_put_right:Nn #1 {##1} }
}
\cs_set:Npn  \seq_set_from_clist:NN #1#2 {
  \seq_clear:N #1
  \clist_map_inline:Nn #2 { \seq_put_right:Nn #1 {##1} }
}
\cs_set:Npn  \seq_gset_from_clist:Nn #1#2 {
  \seq_gclear:N #1
  \clist_map_inline:nn {#2} { \seq_gput_right:Nn #1 {##1} }
}
\cs_set:Npn  \seq_gset_from_clist:NN #1#2 {
  \seq_gclear:N #1
  \clist_map_inline:Nn #2 { \seq_gput_right:Nn #1 {##1} }
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
%
%
% \begin{macro}{\clist_set_from_seq:NN,\clist_gset_from_seq:NN}
% I assume this technique is more efficient than looping through each element
% and using "\clist_put_right:Nn" (Will).
%    \begin{macrocode}
\cs_new:Npn \clist_set_from_seq_aux:NNN #1#2#3 {
  \cs_set:Npn \seq_elt:w ##1 \seq_elt_end: ##2 {
    \exp_not:n {##1}
    \quark_if_nil:NF ##2 { , ##2 }
  }
  #1 #2 { #3 \q_nil }
}
\cs_new:Npn \clist_set_from_seq:NN  { \clist_set_from_seq_aux:NNN \tl_set:Nx  }
\cs_new:Npn \clist_gset_from_seq:NN { \clist_set_from_seq_aux:NNN \tl_gset:Nx }
%    \end{macrocode}
% \end{macro}
%
%
%
% \begin{macro}[TF]{\clist_if_in_numrange:nn}
% A `numrange' is like |-2,5-8,17-| (can be unsorted).
%    \begin{macrocode}
\prg_new_conditional:Nnn \clist_if_in_numrange:nn {TF,T,F} {
  \bool_set_false:N \l_clist_numrange_bool
  \clist_map_inline:nn {#2} {
    \_clist_numrange_parse:nw {#1} ##1 - \q_nil - \q_stop
  }
  \bool_if:NTF \l_clist_numrange_bool \prg_return_true: \prg_return_false:
}
\cs_set:Npn \_clist_numrange_success: {
  \bool_set_true:N \l_clist_numrange_bool
  \clist_map_break:
}
\cs_set:Npn \_clist_numrange_parse:nw #1 #2 - #3 - #4 \q_stop {
  \tl_if_empty:nTF {#4}{
    \int_compare:nT {#1=#2} {\_clist_numrange_success:}
  }{
    \tl_if_empty:nTF {#3}{
      \int_compare:nT {#1>=#2} {\_clist_numrange_success:}
    }{
      \tl_if_empty:nTF {#2}{
        \int_compare:nT {#1<=#3} {\_clist_numrange_success:}
      }{
        \int_compare:nT {#1>=#2} {
          \int_compare:nT {#1<=#3}
            {\_clist_numrange_success:}
        }
      }
    }
  }
}
\bool_new:N \l_clist_numrange_bool
%    \end{macrocode}
% \end{macro}
%
%\begin{macro}{\clist_length:N}
%\begin{macro}{\clist_length:c}
%\begin{macro}{\clist_length:n}
% Counting the elements in a comma-list is straight-forward, using the
% same approach as for other lists of tokens.
%    \begin{macrocode}
\cs_new_nopar:Npn \clist_length:N #1 {
  \tex_number:D \etex_numexpr:D
    0
    \clist_map_function:NN #1 \tl_elt_count_aux:n
  \scan_stop:
}
\cs_generate_variant:Nn \clist_length:N { c }
\cs_new_nopar:Npn \clist_length:n #1 {
  \tex_number:D \etex_numexpr:D
    0
    \clist_map_function:nN {#1} \tl_elt_count_aux:n
  \scan_stop:
}
%    \end{macrocode}
%\end{macro}
%\end{macro}
%\end{macro}
%
%\begin{macro}{\clist_item:Nn}
%\begin{macro}{\clist_item:cn}
%\begin{macro}{\clist_item:nn}
%\begin{macro}[aux]{\clist_element_aux:nw}
% Recovering an item from a list is indexed from \( 0 \), with negative
% numbers meaning ``from the end of the list''. So the first test
% discriminates the two cases. For negative numbers, there is therefore
% a need to know the number of items in the list before doing the
% second phase, a recursion which will give an empty result if the
% number is too big.
%    \begin{macrocode}
\cs_new_nopar:Npn \clist_item:Nn #1#2 {
  \exp_args:No \clist_item:nn {#1} {#2}
}
\cs_generate_variant:Nn \clist_item:Nn { c }
\cs_new:Npn \clist_item:nn #1#2 {
  \int_compare:nNnTF {#2} < { 0 }
    {
      \exp_args:Nf \clist_item_aux:nw
        { \clist_length:n {#1} + #2 }
        #1 , \q_recursion_tail \q_recursion_stop
    }
    {
      \clist_item_aux:nw {#2} #1
        , \q_recursion_tail \q_recursion_stop
    }
}
\cs_new:Npn \clist_item_aux:nw #1#2 , #3 {
  \int_compare:nNnTF {#1} = { 0 }
    { \use_i_delimit_by_q_recursion_stop:nw {#2} }
    {
      \quark_if_recursion_tail_stop:n {#3}
      \clist_item_aux:nw { #1 - 1 } #3
    }
}
%    \end{macrocode}
%\end{macro}
%\end{macro}
%\end{macro}
%\end{macro}
%
%
%    \begin{macrocode}
%</initex|package>
%    \end{macrocode}
%
%    \begin{macrocode}
%<*showmemory>
\showMemUsage
%</showmemory>
%    \end{macrocode}
%
% \end{implementation}
%
% \PrintIndex
%
% \endinput
