% \iffalse %% File: l3expan.dtx Copyright (C) 1990-2006 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/cgi-bin/cvsweb.cgi/ %% %% 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. %% %% ----------------------------------------------------------------------- % %\RequirePackage{l3names} %<*dtx> %\fi \def\GetIdInfo$Id: #1.dtx #2 #3-#4-#5 #6 #7$#8{% \def\fileversion{#2}% \def\filedate{#3/#4/#5}% \ProvidesFile{#1.dtx}[#3/#4/#5 v#2 #8]% } %\iffalse % %\fi \GetIdInfo$Id: l3expan.dtx 573 2006-08-21 20:59:37Z morten $ {L3 Experimental Argument Expansion module} % % \iffalse %<*driver> \documentclass{l3doc} \begin{document} \DocInput{l3expan.dtx} \end{document} % % \fi % % % \title{The \textsf{l3expan} package\thanks{This file % has version number \fileversion, last % revised \filedate.}\\ % Controlling Expansion of Command Arguments} % \author{\Team} % \date{\filedate} % \maketitle % % % \section{\LaTeX3 functions} % % All \LaTeX3 functions contain a colon in their % name. Characters following the colon are used to denote the number and % the ``type'' of arguments that the function takes. An uppercase "N" is % used to denote an argument that consists of a single token and a % lowercase "n" is used when the argument can consist of several tokens % surrounded by braces. In case of "n" arguments that consist of a % single token the surrounding braces can be omitted in nearly all % situations---functions that force the use of braces even for single % token arguments are explicitly mentioned. For example, "\seq_gpush:Nn" % is a function that takes two arguments, the first is a single token % (the sequence) and the second may consist of several tokens surrounded % by braces. % % This concept of argument specification makes it easy to read the code % and should be followed when defining new functions. % % \subsection{Expanding arguments of functions} % % Within code it is often necessary to expand or partially expand % arguments before passing it on to some function. For example, if the % token list pointer "\l_tmpa_tlp" contains the current file % that should be pushed onto some stack, we can not write % \begin{quote} % "\seq_gpush:Nn" \\ % " \g_file_name_stack" \\ % " \l_tmpa_tlp" % \end{quote} % since this would put the token "\l_tmpa_tlp" and not its % contents on the stack. Instead a suitable number of "\exp_after:NN" % would be necessary (together with extra braces) to change the order of % execution, i.e. % \begin{quote} % "\exp_after:NN" \\ % " \seq_gpush:Nn" \\ % "\exp_after:NN" \\ % " \g_file_name_stack" \\ % "\exp_after:NN" \\ % " {\l_tmpa_tlp}" % \end{quote} % % The above example is probably the simplest case but is already shows % how the code changes to something difficult to understand. Therefore % \LaTeX3 provides the programmer with a general scheme that keeps the % code compact and easy to understand. % To denote that some argument to a function needs special treatment one % just uses different letters in the argument part of the function to % mark the desired behavior. In the above example one would write % \begin{quote} % "\seq_gpush:No" \\ % " \g_file_name_stack" \\ % " \l_tmpa_tlp" % \end{quote} % to achieve the desired effect. Here the "o" stands for expand this % (the second) argument once before passing it to the function. % % The following letters can be used to denote special treatment of % arguments before passing it to the basic function: % \begin{description} % \item[o] One time expanded token or token-list. In the latter case, % effectively only the first token in the list gets expanded. Since % the expansion might result in more than one token, the result is % surrounded for further processing with braces. % % \item[x] Fully expanded token or token-list. Like "o" but the % argument is expanded using "\def:Npx" before it is passed on. This means % that expansion takes place until only unexpandable tokens are left. % % \item[f] Almost the same as the |x| type except here the token list % is expanded fully until the first unexpandable token is found and % the rest is left unchanged. Note that if this function finds a % space at the beginning of the argument it will gobble it and not % expand the next argument. % % \item[N,O,X] Like "n", "o", "x" but the argument must be a single % token without any braces around it. % % \item[c] A character string or a token-list that ultimately expands % to characters. This string (after expansion) is used to construct a % command name that is eventually passed on. % % \item[C] A character string or a token-list that ultimately expands % to characters. From this string (after expansion) a command name is % constructed and then this command name is expanded once (like "o"). % The result of this is eventually passed on. In other words % \begin{quote} % "\seq_gpush:NC" \\ % " \g_file_name_stack" \\ % " {l_tmpa_tlp}" % \end{quote} % Has the same effect as the example above. % % % \end{description} % % Here are three new expansion types that may be useful but I'm not % sure yet. Only time will tell\dots{} Proper documentation of these % functions is postponed until later. % \begin{description} % \item[d] This is pretty much like the |o| type except the token list % get's expanded twice before being passed on. (|d| is for double) % % \item[E] Sometimes you need to unpack a token list or something else % but you don't want it to add the braces that the |o| type % does. This is where you usually wind up with a lot of % |\exp_after:NN|s and we would like to avoid that. This type works % quite well with the other syntax but it won't work in certain % circumstances: Since the generic expansion functions read their % arguments when the expanded code is shuffled around, this type % will have a problem if the last token you want to expand once is % |\token_to_str:N| \emph{and} you're in an argument expansion % process involving arguments in braces such as the |n| and |o| type % arguments. If you stick to functions invloving only |N| and |E| % everything will work just fine. (|E| is for expanded, single % token.) % % \item[e] Same as above but the argument must be given in braces. % \end{description} % % Due to memory constraints not all possible variations are implemented % for every base function. Instead only those that are used within the % \LaTeX3 kernel or otherwise seem to be of general interest are % implemented. % Consult the module description to find out which functions are % actually defined. The next section explains how to define missing % variants. % % \subsection{Defining new variants} % % The definition of variant forms for base functions may be necessary % when writing new functions or when applying a kernel function in a % situation that we haven't thought of before. % % Internally preprocessing of arguments is done with functions from the % "\exp_" module. They all look alike, an example would be % "\exp_args:NNo". This function has three arguments, the first and the % second are a single tokens the third argument gets % expanded once. If "\seq_gpush:No" wouldn't be defined the example % above could be coded in the following way: % \begin{quote} % "\exp_args:NNo\seq_gpush:Nn" \\ % " \g_file_name_stack" \\ % " \l_tmpa_tlp" % \end{quote} % In other words, the first argument to "\exp_args:NNo" is the base % function and the other arguments are preprocessed and then passed to % this base function. In the example the first argument to the base % function should be a single token which is left unchanged while the % second argument is expanded once. From this example we can also see % how the variants are defined. They just expand into the appropriate % "\exp_" function followed by the desired base function, e.g. % \begin{quote} % "\def_new:Npn\seq_gpush:No{\exp_args:NNo\seq_gpush:Nn}" % \end{quote} % Providing variants in this way in style files is uncritical as the % "\def_new:Npn" function will silently accept definitions whenever the % new definition is identical to an already given one. Therefore adding % such definition to later releases of the kernel will not make such % style files obsolete. % % The |f| type is so special that it deserves an example. % Let's pretend we want to set "\aaa" equal to the control sequence % stemming from turning "b \l_tmpa_tlp b" into a control % sequence. Furthermore we want to store the execution of it in a % \m{toks} register. In this example we assume "\l_tmpa_tlp" contains % the text string "lur". The straight forward approach is % \begin{quote} % "\toks_set:No \l_tmpa_toks {\let:Nc \aaa {b \l_tmpa_tlp b}}" % \end{quote} % Unfortunately this only puts % "\exp_args:NNc \let:NN \aaa {b \l_tmpa_tlp b}" into "\l_tmpa_toks" % and not "\let:NwN \aaa = \blurb" as we probably wanted. Using % "\toks_set:Nx" is not an option as that will die horribly. Instead % we can do a % \begin{quote} % "\toks_set:Nf \l_tmpa_toks {\let:Nc \aaa {b \l_tmpa_tlp b}}" % \end{quote} % which puts the desired result in "\l_tmpa_toks". It requires % "\toks_set:Nf" to be defined as % \begin{quote} % "\def:Npn \toks_set:Nf {\exp_args:NNf \toks_set:Nn}" % \end{quote} % If you use this type of expansion in conditional processing then % you should stick to using "TF" type functions only as it does not % try to finish any "\if... \fi:" itself! % % % % % % The available internal functions for argument expansion come in to % flavours, some of them are faster then others. Therefore it is usually % best to follow the following guidelines when defining new functions % that are supposed to come with variant forms: % \begin{itemize} % \item % Arguments that might need expansion should come first in the list of % arguments to make processing faster. % \item % Arguments that should consist of single tokens should come first. % \item % Arguments that need full expansion (i.e., are denoted with "x") % should be avoided if possible as they can not be processed very fast. % \item % In general "n", "x", and "o" (if not in the last position) will % need special processing which is not fast and not expandable, % i.e., functions of this type may not work correctly in arguments % that are itself subject to "x" expansion. Therefore it is best to % use the ``expandable'' functions (i.e., those that contain only % "c", "N", "O", "o" or "f" in the last position) whenever possible. % \end{itemize} % % \subsection{Manipulating the first argument} % % \begin{function}{% % \exp_args:No % } % \begin{syntax} % " \exp_args:No" "..." % \end{syntax} % The first argument of (i.e., ) is expanded once, the % result is surrounded by braces and passed to . may have % more than one argument---all others are passed unchanged. % \end{function} % % \begin{function}{% % \exp_args:Nc % } % \begin{syntax} % " \exp_args:Nc" "..." % \end{syntax} % The first argument of (i.e., ) is expanded until only % characters remain. (An internal error occurs if something else is the % result of this expansion.) Then the result is turned into a control % sequence and passed to as the first argument. may have % more than one argument---all others are passed unchanged. % \end{function} % % \begin{function}{% % \exp_args:NC % } % \begin{syntax} % " \exp_args:Nc" "..." % \end{syntax} % The first argument of (i.e., ) is expanded until only % characters remain. (An internal error occurs if something else is the % result of this expansion.) Then the result is turned into a control % sequence which is then expanded once more. The result of this is then % passed to as the first argument. may have more than % one argument---all others are passed unchanged. % \end{function} % % \begin{function}{% % \exp_args:Nx % } % \begin{syntax} % " \exp_args:Nx" "..." % \end{syntax} % The first argument of (i.e., ) is fully expanded until % only unexpandable tokens remain, the result is surrounded by braces % and passed to . may have more than one argument---all % others are passed unchanged. % As mentioned before, this type of function is relatively slow. % \end{function} % % \begin{function}{% % \exp_args:Nf % } % \begin{syntax} % " \exp_args:Nf" "..." % \end{syntax} % The first argument of (i.e., ) undergoes full % expansion until the first unexpandable token is encountered, the % result is surrounded by braces and passed to . may % have more than one argument---all others are passed unchanged. % Beware of its special behavior as explained above. % \end{function} % % % \subsection{Manipulating two arguments} % % \begin{function}{% % \exp_args:NNx | % \exp_args:Nnx | % \exp_args:Ncx | % \exp_args:Nox | % \exp_args:Nxo | % \exp_args:Nxx | % } % \begin{syntax} % "\exp_args:Nnx" "..." % \end{syntax} % The above functions all manipulate the first two arguments of . % They are all slow and non-expandable. % \end{function} % % \begin{function}{% % \exp_args:NNo | % \exp_args:NNf | % \exp_args:Nno | % \exp_args:NNc | % \exp_args:Noo | % \exp_args:NOo | % \exp_args:NOc | % \exp_args:Nco | % \exp_args:Ncc | % \exp_args:NNC | % } % \begin{syntax} % "\exp_args:NNo" "..." % \end{syntax} % These are the fast and expandable functions for the first two arguments. % \end{function} % % \subsection{Manipulating three arguments} % % So far not all possible functions are provided and even the selection % below may be reduced in the future as far as the non-expandable % functions are concerned. % % \begin{function}{% % \exp_args:Nnnx | % \exp_args:Noox | % \exp_args:Nnox | % \exp_args:Ncnx | % } % \begin{syntax} % "\exp_args:Nnnx" "..." % \end{syntax} % All the above functions are non-expandable. % \end{function} % % \begin{function}{% % \exp_args:NnnN | % \exp_args:Nnno | % \exp_args:NNOo | % \exp_args:NOOo | % \exp_args:Nccc | % \exp_args:NcNc | % \exp_args:Nnnc | % \exp_args:NcNo | % \exp_args:Ncco | % } % \begin{syntax} % "\exp_args:NNOo" "..." % \end{syntax} % These are the fast and expandable functions for the first three % arguments. % \end{function} % % \subsection{Internal functions and variables} % % \begin{function}{\exp_after:NN} % \begin{syntax} % "\exp_after:NN" % \end{syntax} % This will expand once before processing . This is % similar to "\exp_args:No" except that no braces are put around the % result of expanding . % \begin{texnote} % This is the primitive \tn{expandafter} which was renamed to fit into % the naming conventions of \LaTeX3. % \end{texnote} % \end{function} % % \begin{function}{\exp_not:N | % \exp_not:c | % \exp_not:n } % \begin{syntax} % "\exp_not:N" % "\exp_not:n" "{" "}" % \end{syntax} % This function will prohibit the expansion of in situation % where would otherwise be replaced by it definition, e.g., % inside an argument that is handled by the "x" convention. % \begin{texnote} % "\exp_not:N" is the primitive \tn{noexpand} renamed and "\exp_not:n" % is the \eTeX{} primitive \tn{unexpanded}. % \end{texnote} % \end{function} % % % \begin{function}{\exp_not:o} % \begin{syntax} % "\exp_not:o" "{""}" % \end{syntax} % Same as "\exp_not:n" except is expanded once and the % result of this expansion is then prohibited from being expanded % further. % \end{function} % % \begin{function}{\exp_not:E} % \begin{syntax} % "\exp_not:E" % \end{syntax} % The name of this command is a lie. Perhaps it should be called % ``"exp_perhaps_once"''. What it actually does is, it expands % and then issues an "\exp_not:N" to prohibit further expansion of the % first token in the replacement text of . This means that if % the replacement text of consists of more than one token all % further tokens are still subject to full expansion. % \begin{texnote} % This command has no equivalent. % \end{texnote} % \end{function} % % % % % \begin{variable}{\l_exp_tlp | } % \begin{syntax}\end{syntax} % The "\exp_" module has its private variables to temporarily store % results of the argument expansion. This is done to avoid interference % with other functions using temporary variables. % \end{variable} % % \StopEventually{} % % \subsection {The Implementation} % % We start by ensuring that the required packages are loaded. % \begin{macrocode} %\RequirePackage{l3tlp} %<*initex|package> % \end{macrocode} % % \subsubsection{General expansion} % % In this section a general mechanism for defining functions to handle % argument handling is defined. These general expansion functions are % expandable unless |x| is used. (Any version of |x| is going to have % to use one of the \LaTeX3\ names for |\def:Npx| at some point, and % so is never going to be expandable.\footnote{However, some % primitives have certain characteristics that means that their % arguments undergo an \texttt{x} type expansion but the primitive % is in fact still expandable. We shall make it very clear when such % a function is expandable.}) % % In a later section some common cases are coded by a more direct % method, typically using calls to |\exp_after:NN|. % % \begin{macro}{\l_exp_tlp} % We need a scratch token list pointer. % \begin{macrocode} \tlp_new:Nn\l_exp_tlp{} % \end{macrocode} % \end{macro} % % This code uses internal functions with names that start with |\::| % to perform the expansions. % \begin{macro}{\exp_arg_next:nnn} % This is basically the same function as |\Dexp_arg_next:nnn|. % \begin{macrocode} \def_new:Npn\exp_arg_next:nnn#1#2#3{ #2\:::{#3#1} } % \end{macrocode} % \end{macro} % % \begin{macro}{\::n} % This function is used to skip an argument that doesn't need to % be expanded. % \begin{macrocode} \def_new:Npn\::n#1\:::#2#3{ #1\:::{#2{#3}} } % \end{macrocode} % \end{macro} % % \begin{macro}{\::N} % This function is used to skip an argument that consists of a % single token and doesn't need to be expanded. %^^A was \let_new:NN\::N\::n (changed to match \;N above. % \begin{macrocode} \def_new:Npn\::N#1\:::#2#3{ #1\:::{#2#3} } % \end{macrocode} % \end{macro} % % \begin{macro}{\::c} % This function is used to skip an argument that is turned into % as control sequence without expansion. % \begin{macrocode} \def_new:Npn\::c#1\:::#2#3{ \exp_after:NN\exp_arg_next:nnn\cs:w #3\cs_end:{#1}{#2} } % \end{macrocode} % \end{macro} % % \begin{macro}{\::o} % This function is used to expand an argument once. % \begin{macrocode} \def_new:Npn\::o#1\:::#2#3{ \exp_after:NN\exp_arg_next:nnn\exp_after:NN{\exp_after:NN{#3}}{#1}{#2} } % \end{macrocode} % \end{macro} % % % \begin{macro}{\::f} % This function is used to expand a token list until the first % unexpandable token is found. % The underlying "\int_to_roman:w -`0" expands everything in its % way to find something terminating the number and thereby expands the % function in front of it. This scanning procedure is terminated once % the expansion hits something non-expandable or a space; in case the % scanner hits a number, this number also terminates the scanning and % is left untouched. In the example shown earlier the scanning was % stopped once \TeX{} had fully expanded % "\let:Nc \aaa {b \l_tmpa_tlp b}" into "\let:NwN \aaa = \blurb" which % then turned out to contain the non-expandable token "\let:NwN". % Since the expansion of "\int_to_roman:w -`0" is \m{null}, we % wind up with a fully expanded list, only \TeX{} has not tried to % execute any of the non-expandable tokens. This is what % differentiates this function from the "x" argument type. % \begin{macrocode} \def_new:Npn\::f#1\:::#2#3{ \exp_after:NN\exp_arg_next:nnn \exp_after:NN{\exp_after:NN{\int_to_roman:w -`0 #3}} {#1}{#2} } % \end{macrocode} % \end{macro} % % \begin{macro}{\::x} % This function is used to expand an argument fully. % \begin{macrocode} \def_new:Npn\::x#1\:::#2#3{ \tlp_set:Nx\l_exp_tlp{{{#3}}} \exp_after:NN\exp_arg_next:nnn\l_exp_tlp{#1}{#2}} % \end{macrocode} % \end{macro} % % \begin{macro}{\:::} % Just another name for the identity function. % \begin{macrocode} \def_new:Npn\:::#1{#1} % \end{macrocode} % \end{macro} % % \begin{macro}{\::C} % This function creates a control sequence out of |#3| and expands % that once before passing it on to |\exp_arg_next:nnn|. % \begin{macrocode} \def_new:Npn\::C#1\:::#2#3{ \exp_after:NN\exp_C_aux:nnn\cs:w #3\cs_end:{#1}{#2}} % \end{macrocode} % \end{macro} % % \begin{macro}{\exp_C_aux:nnn} % A helper function for |\::C| wich expands its argument before % passing it on to |\exp_arg_next:nnn|. % \begin{macrocode} \def_new:Npn\exp_C_aux:nnn #1 { \exp_after:NN \exp_arg_next:nnn \exp_after:NN { \exp_after:NN {#1} } } % \end{macrocode} % \end{macro} % % Here are some that might not stay but let's see. % \begin{macro}{\::E} % This function is used to expand an argument once and return it % \emph{without} braces. Use this only when you feel pretty % comfortable about your input! Actually this is pretty much just % generic wrapper for |\exp_after:NN|. % \begin{macrocode} \def:Npn\::E#1\:::#2#3{ \exp_after:NN\exp_arg_next:nnn \exp_after:NN{#3}{#1}{#2} } % \end{macrocode} % \end{macro} % % \begin{macro}{\::e} % Same as |\::E| really but conceptually they are different. % \begin{macrocode} \def:Npn\::e#1\:::#2#3{ \exp_after:NN\exp_arg_next:nnn \exp_after:NN{#3}{#1}{#2} } % \end{macrocode} % \end{macro} % % \begin{macro}{\::d} % This function is used to expand an argument twice. Mostly useful % for |toks| type things. % \begin{macrocode} \def:Npn\::d#1\:::#2#3{ \exp_after:NN\exp_after:NN\exp_after:NN\exp_arg_next:nnn \exp_after:NN\exp_after:NN\exp_after:NN{ \exp_after:NN\exp_after:NN\exp_after:NN{#3}}{#1}{#2} } % \end{macrocode} % \end{macro} % % We do most of them by hand here. This also means that we get a name % for |\exp_after:NN| that fits with the rest of the code. % \begin{macrocode} \let:NN \exp_args:NE \exp_after:NN \def:Npn \exp_args:NNE #1{\exp_args:NE#1\exp_args:NE} \def:Npn \exp_args:NNNE #1#2{\exp_args:NE#1\exp_args:NE#2\exp_args:NE} \def:Npn \exp_args:NEE #1{\exp_args:NE\exp_args:NE\exp_args:NE#1\exp_args:NE} \def:Npn \exp_args:NcE #1#2{\exp_after:NN #1\cs:w #2\exp_after:NN\cs_end:} \def:Npn \exp_args:Nd {\::d\:::} \def:Npn \exp_args:NNd {\::N\::d\:::} % \end{macrocode} % % \begin{macro}{\exp_args:NC} % \begin{macro}{\exp_args:Ncx} % \begin{macro}{\exp_args:Ncco} % \begin{macro}{\exp_args:Nccx} % \begin{macro}{\exp_args:Ncnx} % \begin{macro}{\exp_args:NcNc} % \begin{macro}{\exp_args:Nf} % \begin{macro}{\exp_args:NNf} % \begin{macro}{\exp_args:Nfo} % \begin{macro}{\exp_args:Nnf} % \begin{macro}{\exp_args:NNno} % \begin{macro}{\exp_args:NnnN} % \begin{macro}{\exp_args:Nnno} % \begin{macro}{\exp_args:Nnnx} % \begin{macro}{\exp_args:Nno} % \begin{macro}{\exp_args:Nnox} % \begin{macro}{\exp_args:NNx} % \begin{macro}{\exp_args:Nnx} % \begin{macro}{\exp_args:Noo} % \begin{macro}{\exp_args:Noox} % \begin{macro}{\exp_args:Nox} % \begin{macro}{\exp_args:Nx} % \begin{macro}{\exp_args:Nxx} % \begin{macro}{\exp_args:Nxx} % \begin{macro}{\exp_args:NNC} % \begin{macro}{\exp_args:Nnnc} % Here are the actual function definitions, using the helper functions % above. % \begin{macrocode} \def:Npn \exp_args:NC {\::C\:::} %\def:Npn \exp_args:Nc {\::c\:::} %\def:Npn \exp_args:Ncc {\::c\::c\:::} %\def:Npn \exp_args:Nccc {\::c\::c\::c\:::} \def:Npn \exp_args:Ncx {\::c\::x\:::} \def:Npn \exp_args:Ncco {\::c\::c\::o\:::} \def:Npn \exp_args:Nccx {\::c\::c\::x\:::} \def:Npn \exp_args:Ncnx {\::c\::n\::x\:::} \def:Npn \exp_args:NcNc {\::c\::N\::c\:::} \def:Npn \exp_args:NcNo {\::c\::N\::o\:::} \def:Npn \exp_args:Ncco {\::c\::c\::o\:::} %\def:Npn \exp_args:Nco {\::c\::o\:::} %\def:Npn \exp_args:NNc {\::N\::c\:::} \def:Npn \exp_args:Nf {\::f\:::} \def:Npn \exp_args:NNf {\::N\::f\:::} \def:Npn \exp_args:Nfo{\::f\::o\:::} \def:Npn \exp_args:Nnf {\::n\::f\:::} %\def:Npn \exp_args:NNNo {\::N\::N\::o\:::} \def:Npn \exp_args:NNno {\::N\::n\::o\:::} %% Strange one this next one... \def:Npn \exp_args:NnnN {\::n\::n\::N\:::} \def:Npn \exp_args:Nnno {\::n\::n\::o\:::} \def:Npn \exp_args:Nnnx {\::n\::n\::x\:::} %\def:Npn \exp_args:NNo {\::N\::o\::\:::} \def:Npn \exp_args:Nno {\::n\::o\:::} %\def:Npn \exp_args:NNOo {\::N\::O\::o\:::} \def:Npn \exp_args:Nnox {\::n\::o\::x\:::} \def:Npn \exp_args:NNx {\::N\::x\:::} \def:Npn \exp_args:Nnx {\::n\::x\:::} %\def:Npn \exp_args:No {\::o\:::} %\def:Npn \exp_args:NOc {\::O\::c\:::} %\def:Npn \exp_args:NOo {\::O\::o\:::} \def:Npn \exp_args:Noo {\::o\::o\:::} %\def:Npn \exp_args:NOOo {\::O\::O\::o\:::} \def:Npn \exp_args:Noox {\::o\::o\::x\:::} \def:Npn \exp_args:Nox {\::o\::x\:::} \def:Npn \exp_args:Nx {\::x\:::} \def:Npn \exp_args:Nxo {\::x\::o\:::} \def:Npn \exp_args:Nxx {\::x\::x\:::} \def:Npn \exp_args:NNC {\::N\::C\:::} \def:Npn \exp_args:Nnnc {\::n\::n\::c\:::} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % % \subsubsection{Preventing expansion} % % % \begin{macro}{\exp_not:o} % \begin{macrocode} \def_new:Npn\exp_not:o#1{\exp_not:n\exp_after:NN{#1}} % \end{macrocode} % \end{macro} % % \begin{macro}{\exp_not:E} % \begin{macro}{\exp_not:c} % Two helper functions, which we can probably live without it. % \begin{macrocode} \def_new:Npn\exp_not:E{\exp_after:NN\exp_not:N} \def_new:Npn\exp_not:c#1{\exp_after:NN\exp_not:N\cs:w#1\cs_end:} % \end{macrocode} % \end{macro} % \end{macro} % % % \subsubsection{Single token expansion} % % Expansion for arguments that are single tokens is done with the % functions below. I first thought of using a different module name % but then I saw that this wouldn't do since I could then never % determine for, say, |\seq_put:no| whether this means single, or % general expansion. Therefore I decided to use uppercase `O' for % single expansion. % % One of the most important features of these functions is that they % are fully expandable and therefore allow to prefix them with % |\pref_global:D| for example. This together with the fact that the % above concept is much slower in general means that we should convert % whenever possible and perhaps remove all remaining occurences by % hand-encoding in the end. % % \begin{macro}{\exp_args:No} % \begin{macro}{\exp_args:NOo} % \begin{macro}{\exp_args:NNo} % \begin{macro}{\exp_args:NNO} % \begin{macro}{\exp_args:NOOo} % \begin{macro}{\exp_args:NNOo} % \begin{macro}{\exp_args:NNNo} % This looks somewhat horrible but it runs well with the other % syntax. It is important to see that these functions really need % single tokens as arguments whenever capital letters are used. % \begin{macrocode} \def_new:Npn \exp_args:No #1#2{\exp_after:NN#1\exp_after:NN{#2}} \def_new:Npn \exp_args:NOo #1#2#3{\exp_after:NN\exp_args:No \exp_after:NN#1 \exp_after:NN#2\exp_after:NN{#3}} \def_new:Npn \exp_args:NOOo #1#2#3#4{\exp_after:NN\exp_args:NOo \exp_after:NN#1\exp_after:NN#2\exp_after:NN#3\exp_after:NN{#4}} \def_new:Npn \exp_args:NNo #1#2#3{\exp_after:NN#1\exp_after:NN#2 \exp_after:NN{#3}} \def_new:Npn \exp_args:NNO #1#2#3 {\exp_after:NN#1 \exp_after:NN#2 #3} \def_new:Npn \exp_args:NNOo #1#2#3#4{\exp_after:NN\exp_args:NNo \exp_after:NN#1\exp_after:NN#2\exp_after:NN#3\exp_after:NN{#4}} \def_new:Npn \exp_args:NNNo #1#2#3#4{\exp_after:NN#1\exp_after:NN#2 \exp_after:NN#3\exp_after:NN{#4}} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % % \begin{macro}{\exp_args:Nc} % \begin{macro}{\exp_args:NNc} % \begin{macro}{\exp_args:NOc} % \begin{macro}{\exp_args:Ncc} % \begin{macro}{\exp_args:Nccc} % Here are the functions that turn their argument into csnames but % are expandable. % \begin{macrocode} \def_new:Npn \exp_args:Nc #1#2{\exp_after:NN#1\cs:w#2\cs_end:} \def_new:Npn \exp_args:NNc #1#2#3{\exp_after:NN#1\exp_after:NN#2 \cs:w#3\cs_end:} \def_new:Npn \exp_args:NOc#1#2#3{\exp_after:NN\exp_args:No\exp_after:NN #1\exp_after:NN#2\cs:w#3\cs_end:} \def_new:Npn \exp_args:Ncc #1#2#3{\exp_after:NN#1 \cs:w#2\exp_after:NN\cs_end:\cs:w#3\cs_end:} \def_new:Npn \exp_args:Nccc #1#2#3#4{\exp_after:NN#1 \cs:w#2\exp_after:NN\cs_end:\cs:w#3\exp_after:NN \cs_end:\cs:w #4\cs_end:} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % % \begin{macro}{\exp_args:Nco} % If we force that the third argument % always has braces, we could implement this function % with less tokens and only two arguments. % \begin{macrocode} \def_new:Npn \exp_args:Nco #1#2#3{\exp_after:NN#1\cs:w#2\exp_after:NN \cs_end:\exp_after:NN{#3}} % \end{macrocode} % \end{macro} % % % \begin{macro}{\exp_def_form:nnn} % This command is a recent addition which was actually added % when we wrote the article for TUGboat (while most of the other % code goes way back to 1993). % \begin{macrocode} \def:Npn\exp_def_form:nnn#1#2#3{ \exp_after:NN \def:Npn \cs:w #1:#3 \exp_after:NN \cs_end: \exp_after:NN { \cs:w exp_args:N#3 \exp_after:NN \cs_end: \cs:w #1:#2 \cs_end: } % \end{macrocode} % We also have to test if |exp_args:N#3| is already defined % and if not define it via the % |\::| commands using the chars in |#3| % \begin{macrocode} \cs_if_free:cT {exp_args:N#3} {\def:cpx {exp_args:N#3} {\exp_args_form_x:w #3 :} } } % \end{macrocode} % \end{macro} % % % \begin{macro}{\exp_args_form_x:w} % This command grabs char by char outputting |\::#1| (not expanded % further) until we see a |:|. That colon is in fact also turned into % |\:::| so that the required structure for |\exp_args...| commands % is correctly terminated. % \begin{macrocode} \def_new:Npn\exp_args_form_x:w #1 { \exp_not:c{::#1} \if_meaning:NN #1 : \else: \exp_after:NN\exp_args_form_x:w \fi:} % \end{macrocode} % \end{macro} % % Show token usage: % \begin{macrocode} % %<*showmemory> \showMemUsage % % \end{macrocode} % % \endinput % % $Log$ % Revision 1.29 2006/07/30 15:43:38 morten % Minor touch-up plus added functions needed by clist module % % Revision 1.28 2006/06/03 18:56:31 morten % A few more functions % % Revision 1.27 2006/03/20 18:26:35 braams % Updated the copyright notice (2006) and demoted all implementation % sections to subsections and so on to clean up the toc for source3.tex % % Revision 1.26 2006/02/17 23:01:47 braams % Imported \exp_args:NNO from l3messages % % Revision 1.25 2005/12/27 10:00:45 morten % Changed RCS information retrieval % % Revision 1.24 2005/12/22 13:56:03 morten % Fixed error in \exp_args:NNd % % Revision 1.23 2005/12/21 20:44:30 morten % Corrected typo. % % Revision 1.22 2005/12/06 15:34:46 morten % Made \exp_not:o do what you'd expect % % Revision 1.21 2005/11/23 07:37:29 morten % A few new expansion types, we shall see if they will be useful. % % Revision 1.20 2005/04/12 16:44:06 morten % Fix to make it run as a package % % Revision 1.19 2005/04/12 13:24:07 morten % Minor updates % % Revision 1.18 2005/04/09 21:06:46 morten % Added yet another function. % % Revision 1.17 2005/04/06 21:38:10 morten % Added more functions. % % Revision 1.16 2005/03/26 21:09:44 morten % Added f argument type for "force expansion" % % Revision 1.15 2005/03/22 23:24:40 morten % Fixed documentation error. % % Revision 1.14 2005/03/16 22:36:37 braams % Added the tweaks necessary to be able to load with initex % % Revision 1.13 2005/03/11 21:37:37 braams % Fixed the use of RCS information %