% \iffalse
%% File: l3extra.dtx Copyright (C) 2005-2009 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$
          {L3 Experimental 'extras' module}
%\iffalse
%<*driver>
%\fi
\ProvidesFile{\filename.\filenameext}
  [\filedate\space v\fileversion\space\filedescription]
%\iffalse
\documentclass[full]{l3doc}
\begin{document}
\DocInput{l3extra.dtx}
\end{document}
%</driver>
% \fi
%
%
% \title{The \textsf{l3extra} 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 functions}
%
%
% \begin{function}{\exp_arg:x}
% \begin{syntax}
% "\exp_arg:x" \Arg{text}
% \end{syntax}
% Fully expands <text> before passing it to the input stream.
% Not expandable.
% \begin{texnote}
% In pdf\TeX\ 1.5 and Lua\TeX, this can be done expandably with "\expanded".
% \end{texnote}
% \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}
%
%
% \begin{function}{\tl_transform:nn|\char_transform:NN}
% \begin{syntax}
% |\tl_transform:nn| \Arg{tranformation rules} \Arg{token list}
% "\char_transform:NN" <char.\ token1> <char.\ token2>
% \end{syntax}
% Tokenises and evaluates <token list> according to the transformation rules
% given in the first argument.
% These transformation rules may be function/variable
% redefinitions, catcode changes (see "\char_make_other:N" and so on), or
% token transformations given by "\char_transform:NN".
%
% "\char_transform:NN" declares that within the <token list> argument,
% any occurences of <token1> are interpreted as if they were <token2> albeit
% with the same catcode as <token1>.
%
% Note 1: Everything evaluated by this function occurs within a group;
% global definitions will be necessary to make changes outside of it.
%
% Note 2: Because this function must be invoked before its arguments are
% tokenised, it cannot be evaluated within another macro (unless clever use
% of "\tl_rescan:nn" is employed).
% \begin{texnote}
% This is a wrapper around \TeX's "\lowercase" primitive and only the ASCII
% uppercase letters are protected from being transformed themselves.
% If you are using Xe\TeX\ or Lua\TeX, be careful of unicode letters that will
% be affected by this process.
% \end{texnote}
% \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_seq:Nn" <seq> \Arg{clist}
% "\seq_set_from_seq: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}
%
%
%
% \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}{\exp_arg:x}
%    \begin{macrocode}
\cs_new:Npn \exp_arg:x #1
  {
    \group_begin:
      \cs_set:Npx \cs_tmp: {#1}
      \exp_args:wN
    \group_end:
    \cs_tmp:
  }
%    \end{macrocode}
% \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}{\tl_transform:nn,\char_transform:NN}
%    \begin{macrocode}
\cs_new:Npn \tl_transform:nn #1
  {
    \group_begin:
    \tl_map_function:nN
      { \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 }
      \char_protect_uppercase:N
    \cs_set_eq:NN \char_transform:NN \char_transform_hidden:NN
    #1
    \tl_transform_aux:n
  }
%    \end{macrocode}
% Allow for catcode changes:
%    \begin{macrocode}
\cs_new:Npn \tl_transform_aux:n #1
  {
    \tl_to_lowercase:n { \group_end: #1 }
  }
\cs_set:Npn \char_protect_uppercase:N #1
  {
    \char_set_lccode:nn {`#1} {`#1}
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Npn \char_transform_hidden:NN #1#2
  {
    \char_set_lccode:nn {`#1} {`#2}
  }
\cs_new:Npn \char_transform:NN
  {
    \msg_error:nn {l3extra} {naked-char-transform}
  }
\msg_new:nnn {l3extra} {naked-char-transform}
  {
    This command can only appear within the first\\
    argument of \string\tl_transform:nn.
  }
%    \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
  \intexpr_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_tmpa_tl
      \seq_pop:NN \l_tmpb_seq \l_tmpb_tl
      \exp_args:NVV #3 \l_tmpa_tl \l_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{macrocode}
%</initex|package>
%    \end{macrocode}
%
%    \begin{macrocode}
%<*showmemory>
\showMemUsage
%</showmemory>
%    \end{macrocode}
%
% \end{implementation}
%
% \PrintIndex
%
% \endinput
