diff options
author | Karl Berry <karl@freefriends.org> | 2011-07-31 18:27:40 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2011-07-31 18:27:40 +0000 |
commit | 1b26357f303f48ae0b233a5fee9c2e5b8c3d8647 (patch) | |
tree | 7fc300fb4b7a180433559b69e8f2362d1cfe5ac7 /Master/texmf-dist/source/latex/l3packages/xparse | |
parent | dac945b204407dae96f70ec228206516093156d7 (diff) |
l3packages (5jun11)
git-svn-id: svn://tug.org/texlive/trunk@23283 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/l3packages/xparse')
-rw-r--r-- | Master/texmf-dist/source/latex/l3packages/xparse/xparse.dtx | 2650 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/l3packages/xparse/xparse.ins | 40 |
2 files changed, 2690 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/l3packages/xparse/xparse.dtx b/Master/texmf-dist/source/latex/l3packages/xparse/xparse.dtx new file mode 100644 index 00000000000..79a996d4fc8 --- /dev/null +++ b/Master/texmf-dist/source/latex/l3packages/xparse/xparse.dtx @@ -0,0 +1,2650 @@ +% \iffalse meta-comment +% +%% File: xparse.dtx (C) Copyright 1999 Frank Mittelbach, Chris Rowley, +%% David Carlisle +%% (C) Copyright 2004-2008 Frank Mittelbach, +%% The LaTeX3 Project +%% (C) Copyright 2009-2011 The 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 "l3packages 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} +\GetIdInfo$Id: xparse.dtx 2492 2011-07-02 13:40:38Z joseph $ + {L3 Experimental document command parser} +%</driver|package> +%<*driver> +\documentclass[full]{l3doc} +\usepackage{amstext} +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \providecommand\acro[1]{\textsc{\MakeLowercase{#1}}} +% \newenvironment{arg-description}{% +% \begin{itemize}\def\makelabel##1{\hss\llap{\bfseries##1}}}{\end{itemize}} +% +% \title{^^A +% The \textsf{xparse} package\\ Document command parser^^A +% \thanks{This file describes v\ExplFileVersion, +% last revised \ExplFileDate.}^^A +% } +% +% \author{^^A +% The \LaTeX3 Project\thanks +% {^^A +% E-mail: +% \href{mailto:latex-team@latex-project.org} +% {latex-team@latex-project.org}^^A +% }^^A +% } +% +% \date{Released \ExplFileDate} +% +% \maketitle +% +% \begin{documentation} +% +% The \pkg{xparse} package provides a high-level interface for +% producing document-level commands. In that way, it is intended as +% a replacement for the \LaTeXe{} \cs{newcommand} macro. However, +% \pkg{xparse} works so that the interface to a function (optional +% arguments, stars and mandatory arguments, for example) is separate +% from the internal implementation. \pkg{xparse} provides a normalised +% input for the internal form of a function, independent of the +% document-level argument arrangement. +% +% At present, the functions in \pkg{xparse} which are regarded as +% \enquote{stable} are: +% \begin{itemize} +% \item \cs{DeclareDocumentCommand} +% \item \cs{NewDocumentCommand} +% \item \cs{RenewDocumentCommand} +% \item \cs{ProvideDocumentCommand} +% \item \cs{DeclareDocumentEnvironment} +% \item \cs{NewDocumentEnvironment} +% \item \cs{RenewDocumentEnvironment} +% \item \cs{ProvideDocumentEnvironment} +% \item \cs{IfNoValue(TF)} (the need for \cs{IfValue(TF)} is currently +% an item of active discussion) +% \item \cs{IfBoolean(TF)} +% \end{itemize} +% with the other functions currently regarded as \enquote{experimental}. Please +% try all of the commands provided here, but be aware that the +% experimental ones may change or disappear. +% +% \subsection{Specifying arguments} +% +% Before introducing the functions used to create document commands, +% the method for specifying arguments with \pkg{xparse} will be +% illustrated. In order to allow each argument to be defined +% independently, \pkg{xparse} does not simply need to know the +% number of arguments for a function, but also the nature of each +% one. This is done by constructing an \emph{argument specification}, +% which defines the number of arguments, the type of each argument +% and any additional information needed for \pkg{xparse} to read the +% user input and properly pass it through to internal functions. +% +% The basic form of the argument specifier is a list of letters, where +% each letter defines a type of argument. As will be described below, +% some of the types need additional information, such as default values. +% The argument types can be divided into two, those which define +% arguments that are mandatory (potentially raising an error if not +% found) and those which define optional arguments. The mandatory types +% are: +% \begin{itemize}[font=\ttfamily] +% \item[m] A standard mandatory argument, which can either be a single +% token alone or multiple tokens surrounded by curly braces. +% Regardless of the input, the argument will be passed to the +% internal code surrounded by a brace pair. This is the \pkg{xparse} +% type specifier for a normal \TeX\ argument. +% \item[l] An argument which reads everything up to the first +% open group token: in standard \LaTeX\ this is a left brace. +% \item[u] Reads an argument `until' \meta{tokens} are encountered, +% where the desired \meta{tokens} are given as an argument to the +% specifier: \texttt{u}\marg{tokens}. +% \end{itemize} +% The types which define optional arguments are: +% \begin{itemize}[font=\ttfamily] +% \item[o] A standard \LaTeX\ optional argument, surrounded with square +% brackets, which will supply +% the special \cs{NoValue} token if not given (as described later). +% \item[d] An optional argument which is delimited by \meta{token1} +% and \meta{token2}, which are given as arguments: +% \texttt{d}\meta{token1}\meta{token2}. As with \texttt{o}, if no +% value is given the special token \cs{NoValue} is returned. +% \item[O] As for \texttt{o}, but returns \meta{default} if no +% value is given. Should be given as \texttt{O}\marg{default}. +% \item[D] As for \texttt{d}, but returns \meta{default} if no +% value is given: \texttt{D}\meta{token1}\meta{token2}\marg{default}. +% Internally, the \texttt{o}, \texttt{d} and \texttt{O} types are +% short-cuts to an appropriated-constructed \texttt{D} type argument. +% \item[s] An optional star, which will result in a value +% \cs{BooleanTrue} if a star is present and \cs{BooleanFalse} +% otherwise (as described later). +% \item[t] An optional \meta{token}, which will result in a value +% \cs{BooleanTrue} if \meta{token} is present and \cs{BooleanFalse} +% otherwise. Given as \texttt{t}\meta{token}. +% \item[g] An optional argument given inside a pair of \TeX\ group +% tokens (in standard \LaTeX, |{| \ldots |}|), which returns +% \cs{NoValue} if not present. +% \item[G] As for \texttt{g} but returns \meta{default} if no value +% is given: \texttt{G}\marg{default}. +% \end{itemize} +% +% Using these specifiers, it is possible to create complex input syntax +% very easily. For example, given the argument definition +% `|s o o m O{default}|', the input `|*[Foo]{Bar}|' would be parsed as: +% \begin{itemize}[nolistsep] +% \item |#1| = |\BooleanTrue| +% \item |#2| = |{Foo}| +% \item |#3| = |\NoValue| +% \item |#4| = |{Bar}| +% \item |#5| = |{default}| +% \end{itemize} +% whereas `|[One][Two]{}[Three]|' would be parsed as: +% \begin{itemize}[nolistsep] +% \item |#1| = |\BooleanFalse| +% \item |#2| = |{One}| +% \item |#3| = |{Two}| +% \item |#4| = |{}| +% \item |#5| = |{Three}| +% \end{itemize} +% Note that after parsing the input there will be always exactly the +% same number of \meta{balanced text} arguments as the number of letters +% in the argument specifier. The \cs{BooleanTrue} and \cs{BooleanFalse} +% tokens are passed without braces; all other arguments are passed as +% brace groups. +% +% Two more tokens have a special meaning when creating an argument +% specifier. First, \texttt{+} is used to make an argument long (to +% accept paragraph tokens). In contrast to \LaTeXe's \cs{newcommand}, +% this applies on an argument-by-argument basis. So modifying the +% example to `|s o o +m O{default}|' means that the mandatory argument +% is now \cs{long}, whereas the optional arguments are not. +% +% Secondly, the token \texttt{>} is used to declare so-called +% \enquote{argument processors}, which can be used to modify the contents of an +% argument before it is passed to the macro definition. The use of +% argument processors is a somewhat advanced topic, (or at least a less +% commonly used feature) and is covered in Section~\ref{sec:processors}. +% +% \subsection{Spacing and optional arguments} +% +% \TeX{} will find the first argument after a function name irrespective +% of any intervening spaces. This is true for both mandatory and +% optional arguments. So |\foo[arg]| and \verb*|\foo [arg]| are +% equivalent. Spaces are also ignored when collecting arguments up +% to the last mandatory argument to be collected (as it must exist). +% So after +% \begin{verbatim} +% \DeclareDocumentCommand \foo { m o m } { ... } +% \end{verbatim} +% the user input |\foo{arg1}[arg2]{arg3}| and +% \verb*|\foo{arg1} [arg2] {arg3}| will both be parsed in the same +% way. However, spaces are \emph{not} ignored when parsing optional +% arguments after the last mandatory argument. Thus with +% \begin{verbatim} +% \DeclareDocumentCommand \foo { m o } { ... } +% \end{verbatim} +% |\foo{arg1}[arg2]| will find an optional argument but +% \verb*|\foo{arg1} [arg2]| will not. This is so that trailing optional +% arguments are not picked up \enquote{by accident} in input. +% +% \subsection{Declaring commands and environments} +% +% With the concept of an argument specifier defined, it is now +% possible to describe the methods available for creating both +% functions and environments using \pkg{xparse}. +% +% The interface-building commands are the preferred method for +% creating document-level functions in \LaTeX3. All of the functions +% generated in this way are naturally robust (using the \eTeX{} +% \cs{protected} mechanism). +% +% \begin{function} +% { +% \DeclareDocumentCommand , +% \NewDocumentCommand , +% \RenewDocumentCommand , +% \ProvideDocumentCommand +% } +% \begin{syntax} +% \cs{DeclareDocumentCommand} \meta{Function} \Arg{arg spec} \Arg{code} +% \end{syntax} +% This family of commands are used to create a document-level +% \meta{function}. The argument specification for the function is +% given by \meta{arg spec}, and expanding +% to be replaced by the \meta{code}. +% +% As an example: +% \begin{verbatim} +% \DeclareDocumentCommand \chapter { s o m } +% { +% \IfBooleanTF {#1} +% { \typesetnormalchapter {#2} {#3} } +% { \typesetstarchapter {#3} } +% } +% \end{verbatim} +% would be a way to define a \cs{chapter} command which would +% essentially behave like the current \LaTeXe{} command (except that it +% would accept an optional argument even when a \texttt{*} was parsed). +% The \cs{typesetnormalchapter} could test its first argument for being +% \cs{NoValue} to see if an optional argument was present. +% +% The difference between the \cs{Declare\ldots}, \cs{New\ldots} +% \cs{Renew\ldots} and \cs{Provide\ldots} versions is the behaviour +% if \meta{function} is already defined. +% \begin{itemize} +% \item \cs{DeclareDocumentCommand} will always create the new +% definition, irrespective of any existing \meta{function} with the +% same name. +% \item \cs{NewDocumentCommand} will issue an error if \meta{function} +% has already been defined. +% \item \cs{RenewDocumentCommand} will issue an error if \meta{function} +% has not previously been defined. +% \item \cs{ProvideDocumentCommand} creates a new definition for +% \meta{function} only if one has not already been given. +% \end{itemize} +% +% \begin{texnote} +% Unlike \LaTeXe{}'s \cs{newcommand} and relatives, the +% \cs{DeclareDocumentCommand} function do not prevent creation of +% functions with names starting \cs{end\ldots}. +% \end{texnote} +% \end{function} +% +% \begin{function} +% { +% \DeclareDocumentEnvironment , +% \NewDocumentEnvironment , +% \RenewDocumentEnvironment , +% \ProvideDocumentEnvironment +% } +% \begin{syntax} +% \cs{DeclareDocumentEnvironment} \Arg{environment} \Arg{arg spec} +% ~~\Arg{start code} \Arg{end code} +% \end{syntax} +% These commands work in the same way as \cs{DeclareDocumentCommand}, +% etc., but create environments (\cs{begin}|{|\meta{function}|}| \ldots +% \cs{end}|{|\meta{function}|}|). Both the \meta{start code} and +% \meta{end code} +% may access the arguments as defined by \meta{arg spec}. +% \end{function} +% +% \subsection{Testing special values} +% +% Optional arguments created using \pkg{xparse} make use of dedicated +% variables to return information about the nature of the argument +% received. +% +% \begin{variable}{\NoValue} +% \cs{NoValue} is a special marker returned by \pkg{xparse} if no +% value is given for an optional argument. If typeset (which should +% not happen), it will print the value \texttt{-NoValue-}. +% \end{variable} +% +% \begin{function}[EXP,TF]{\IfNoValue} +% \begin{syntax} +% \cs{IfNoValueTF} \Arg{argument} \Arg{true code} \Arg{false code} +% \end{syntax} +% The \cs{IfNoValue} tests are used to check if <argument> (|#1|, +% |#2|, \emph{etc.}) is the special \cs{NoValue} token. For example +% \begin{verbatim} +% \DeclareDocumentCommand \foo { o m } +% { +% \IfNoValueTF {#1} +% { \DoSomethingJustWithMandatoryArgument {#2} } +% { \DoSomethingWithBothArguments {#1} {#2} } +% } +% \end{verbatim} +% will use a different internal function if the optional argument +% is given than if it is not present. +% +% As the \cs{IfNoValue(TF)} tests are expandable, it is possible to +% test these values later, for example at the point of typesetting or +% in an expansion context. +% \end{function} +% +% \begin{function}[EXP,TF]{\IfValue} +% \begin{syntax} +% \cs{IfValueTF} \Arg{argument} \Arg{true code} \Arg{false code} +% \end{syntax} +% The reverse form of the \cs{IfNoValue(TF)} tests are also available +% as \cs{IfValue(TF)}. The context will determine which logical +% form makes the most sense for a given code scenario. +% \end{function} +% +% \begin{variable}{\BooleanFalse, \BooleanTrue} +% The \texttt{true} and \texttt{false} flags set when searching for +% an optional token (using \texttt{s} or \texttt{t\meta{token}}) have +% names which are accessible outside of code blocks. +% \end{variable} +% +% \begin{function}[EXP,TF]{\IfBoolean} +% \begin{syntax} +% \cs{IfBooleanTF} \meta{argument} \Arg{true code} \Arg{false code} +% \end{syntax} +% Used to test if \meta{argument} (|#1|, |#2|, \emph{etc.}) is +% \cs{BooleanTrue} or \cs{BooleanFalse}. For example +% \begin{verbatim} +% \DeclareDocumentCommand \foo { s m } +% { +% \IfBooleanTF #1 +% { \DoSomethingWithStar {#2} } +% { \DoSomethingWithoutStar {#2} } +% } +% \end{verbatim} +% checks for a star as the first argument, then chooses the action to +% take based on this information. +% \end{function} +% +% \subsection{Argument processors} +% \label{sec:processors} +% +% \pkg{xparse} introduces the idea of an argument processor, which is +% applied to an argument \emph{after} it has been grabbed by the +% underlying system but before it is passed to \meta{code}. An argument +% processor can therefore be used to regularise input at an early stage, +% allowing the internal functions to be completely independent of input +% form. Processors are applied to user input and to default values for +% optional arguments, but \emph{not} to the special \cs{NoValue} marker. +% +% Each argument processor is specified by the syntax +% \texttt{>}\marg{processor} in the argument specification. Processors +% are applied from right to left, so that +% \begin{verbatim} +% >{\ProcessorB} >{\ProcessorA} m +% \end{verbatim} +% would apply \cs{ProcessorA} +% followed by \cs{ProcessorB} to the tokens grabbed by the \texttt{m} +% argument. +% +% \begin{variable}{\ProcessedArgument} +% \pkg{xparse} defines a very small set of processor functions. In the +% main, it is anticipated that code writers will want to create their +% own processors. These need to accept one argument, which is the +% tokens as grabbed (or as returned by a previous processor function). +% Processor functions should return the processed argument as the +% variable \cs{ProcessedArgument}. +% \end{variable} +% +% \begin{function}{\ReverseBoolean} +% \begin{syntax} +% \cs{ReverseBoolean} +% \end{syntax} +% This processor reverses the logic of \cs{BooleanTrue} and +% \cs{BooleanFalse}, so that the the example from earlier would become +% \begin{verbatim} +% \DeclareDocumentCommand \foo { > { \ReverseBoolean } s m } +% { +% \IfBooleanTF #1 +% { \DoSomethingWithoutStar {#2} } +% { \DoSomethingWithStar {#2} } +% } +% \end{verbatim} +% \end{function} +% +% \begin{function}{\SplitArgument} +% \begin{syntax} +% \cs{SplitArgument} \Arg{number} \Arg{token} +% \end{syntax} +% This processor splits the argument given at each occurrence of the +% \meta{token} up to a maximum of \meta{number} tokens (thus +% dividing the input into $\text{\meta{number}} + 1$ parts). +% An error is given if too many \meta{tokens} are present in the +% input. The processed input is places inside +% $\text{\meta{number}} + 1$ sets of braces for further use. +% If there are less than \Arg{number} of \Arg{tokens} in the argument +% then empty brace groups are added at the end of the processed +% argument. +% \begin{verbatim} +% \DeclareDocumentCommand \foo +% { > { \SplitArgument { 2 } { ; } } m } +% { \InternalFunctionOfThreeArguments #1 } +% \end{verbatim} +% Any category code $13$ (active) \meta{tokens} will be replaced +% before the split takes place. +% \end{function} +% +% \begin{function}{\SplitList} +% \begin{syntax} +% \cs{SplitList} \Arg{token} +% \end{syntax} +% This processor splits the argument given at each occurrence of the +% \meta{token} where the number of items is not fixed. Each item is +% then wrapped in braces within |#1|. The result is that the +% processed argument can be further processed using a mapping function. +% \begin{verbatim} +% \DeclareDocumentCommand \foo +% { > { \SplitList { ; } } m } +% { \MappingFunction #1 } +% \end{verbatim} +% Any category code $13$ (active) \meta{tokens} will be replaced +% before the split takes place. +% \end{function} +% +% \subsection{Separating interface and implementation} +% +% One \emph{experimental} idea implemented in \pkg{xparse} is to +% separate out document command interfaces (the argument specification) +% from the implementation (code). This is carried out using a +% pair of functions, \cs{DeclareDocumentCommandInterface} and +% \cs{DeclareDocumentCommandImplementation} +% +% \begin{function}{\DeclareDocumentCommandInterface} +% \begin{syntax} +% \cs{DeclareDocumentCommandInterface} \meta{function} +% ~~~~\Arg{implementation} \Arg{arg spec} +% \end{syntax} +% This declares a \meta{function}, which will take arguments as detailed +% in the \meta{arg spec}. When executed, the \meta{function} will look for +% code stored as an \meta{implementation}. +% \end{function} +% +% \begin{function}{\DeclareDocumentCommandImplementation} +% \begin{syntax} +% \cs{DeclareDocumentCommandImplementation} +% ~~~~\Arg{implementation} \meta{args} \Arg{code} +% \end{syntax} +% Declares the \meta{implementation} for a function to accept \meta{args} +% arguments and expand to \meta{code}. An implementation must take the +% same number of arguments as a linked interface, although this is not +% enforced by the code. +% \end{function} +% +% \subsection{Fully-expandable document commands} +% +% There are \emph{very rare} occasion when it may be useful to create +% functions using a fully-expandable argument grabber. To support this, +% \pkg{xparse} can create expandable functions as well as the usual +% robust ones. This imposes a number of restrictions on the nature of +% the arguments accepted by a function, and the code it implements. +% This facility should only be used when \emph{absolutely necessary}; +% if you do not understand when this might be, \emph{do not use these +% functions}! +% +% \begin{function}{\DeclareExpandableDocumentCommand} +% \begin{syntax} +% \cs{DeclareExpandableDocumentCommand} +% ~~~~\meta{function} \Arg{arg spec} \Arg{code} +% \end{syntax} +% This command is used to create a document-level \meta{function}, +% which will grab its arguments in a fully-expandable manner. The +% argument specification for the function is given by \meta{arg spec}, +% and the function will execute \meta{code}. In general, \meta{code} will +% also be fully expandable, although it is possible that this will +% not be the case (for example, a function for use in a table might +% expand so that \cs{omit} is the first non-expandable token). +% +% Parsing arguments expandably imposes a number of restrictions on +% both the type of arguments that can be read and the error checking +% available: +% \begin{itemize} +% \item The last argument (if any are present) must be one of the +% mandatory types: \texttt{l}, \texttt{m} or \texttt{u}. +% \item All arguments are either short or long: it is not possible +% to mix short and long argument types. +% \item The `optional group' argument types \texttt{g} and +% \texttt{G} are not available. +% \item It is not possible to differentiate between, for example +% |\foo[| and |\foo{[}|: in both cases the \texttt{[} will be +% interpreted as the start of an optional argument. As a result +% result, checking for optional arguments is less robust than +% in the standard version. +% \end{itemize} +% \pkg{xparse} will issue an error if an argument specifier is given +% which does not conform to the first three requirements. The last +% item is an issue when the function is used, and so is beyond the +% scope of \pkg{xparse} itself. +% \end{function} +% +% \subsection{Access to the argument specification} +% +% The argument specifications for document commands and environments are +% available for examination and use. +% +% \begin{function}{\GetDocumentCommandArgSpec, \GetDocumentEnvironmentArgSpec} +% \begin{syntax} +% \cs{GetDocumentCommandArgSpec} \meta{function} +% \cs{GetDocumentEnvironmentArgSpec} \meta{environment} +% \end{syntax} +% These functions transfer the current argument specification for the +% requested \meta{function} or \meta{environment} into the token list +% variable \cs{ArgumentSpecification}. If the \meta{function} or +% \meta{environment} has no known argument specification then an error +% is issued. The assignment to \cs{ArgumentSpecification} is local to +% the current \TeX{} group. +% \end{function} +% +% \begin{function} +% {\ShowDocumentCommandArgSpec, \ShowDocumentEnvironmentArgSpec} +% \begin{syntax} +% \cs{ShowDocumentCommandArgSpec} \meta{function} +% \cs{ShowDocumentEnvironmentArgSpec} \meta{environment} +% \end{syntax} +% These functions show the current argument specification for the +% requested \meta{function} or \meta{environment} at the terminal. If +% the \meta{function} or \meta{environment} has no known argument +% specification then an error is issued. +% \end{function} +% +% \section{Load-time options} +% +% \DescribeOption{log-declarations} +% The package recognises the load-time option \texttt{log-declarations}, +% which is a key--value option taking the value \texttt{true} and +% \texttt{false}. By default, the option is set to \texttt{true}, meaning +% that each command or environment declared is logged. By loading +% \pkg{xparse} using +% \begin{verbatim} +% \usepackage[load-declarations=false]{xparse} +% \end{verbatim} +% this may be suppressed and no information messages are produced. +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{xparse} implementation} +% +% \begin{macrocode} +%<*package> +% \end{macrocode} +% +% \begin{macrocode} +\ProvidesExplPackage + {\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription} +\RequirePackage{expl3} +% \end{macrocode} +% +% A check to make sure that \pkg{expl3} is not too old +% \begin{macrocode} +\@ifpackagelater { l3token } { 2011/07/02 } + { } + { + \PackageError { xparse } { Support~package~l3kernel~too~old. } + { + Please~install~an~up~to~date~version~of~l3kernel~ + using~your~TeX~package~manager~or~from~CTAN.\\ \\ + Loading~xparse~will~abort! + } + \tex_endinput:D + } +% \end{macrocode} +% +% \subsection{Variables and constants} +% +% \begin{variable}{\c_xparse_shorthands_prop} +% Shorthands are stored as a property list: this is set up here as it +% is a constant. +% \begin{macrocode} +\prop_new:N \c_xparse_shorthands_prop +\prop_put:Nnn \c_xparse_shorthands_prop { o } { d[] } +\prop_put:Nnn \c_xparse_shorthands_prop { O } { D[] } +\prop_put:Nnn \c_xparse_shorthands_prop { s } { t* } +% \end{macrocode} + %\end{variable} +% +% \begin{variable}{\l_xparse_arg_tl} +% Token list variable for single grabbed argument when post-processing. +% \begin{macrocode} +\tl_new:N \l_xparse_arg_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_xparse_args_tl} +% Token list variable for grabbed arguments. +% \begin{macrocode} +\tl_new:N \l_xparse_args_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_xparse_environment_bool} +% Generating environments uses the same mechanism as generating +% functions. However, full processing of arguments is always needed +% for environments, and so the function-generating code needs to +% know this. +% \begin{macrocode} +\bool_new:N \l_xparse_environment_bool +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_xparse_error_bool} +% Used to signal an error when creating expandable functions. +% \begin{macrocode} +\bool_new:N \l_xparse_error_bool +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_xparse_function_tl} +% When creating expandable functions, the current function name needs +% to be passed along. +% \begin{macrocode} +\tl_new:N \l_xparse_function_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_xparse_last_arg_tl} +% Used when creating expandable arguments. +% \begin{macrocode} +\tl_new:N \l_xparse_last_arg_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_xparse_long_bool} +% A flag for \cs{long} arguments. +% \begin{macrocode} +\bool_new:N \l_xparse_long_bool +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_xparse_m_args_int} +% The number of simple \texttt{m} arguments is tracked so they can be +% dumped \emph{en masse}. +% \begin{macrocode} +\int_new:N \l_xparse_m_args_int +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_xparse_m_only_bool} +% A flag to indicate that only \texttt{m} arguments have been found. +% \begin{macrocode} +\bool_new:N \l_xparse_m_only_bool +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_xparse_mandatory_args_int} +% So that trailing optional arguments can be picked up, a count has to +% be taken of all mandatory arguments. This is then decreased as +% mandatory arguments are added to the signature, so will be zero +% only if there are no more mandatory arguments to add. +% \begin{macrocode} +\int_new:N \l_xparse_mandatory_args_int +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_xparse_processor_bool} +% When reading through the argument specifier, a flag is needed to +% show that a processor has been found for the current argument. This +% is used when checking how to handle \texttt{m} arguments. +% \begin{macrocode} +\bool_new:N \l_xparse_processor_bool +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_xparse_processor_int} +% In the grabber routine, each processor is saved with a number +% recording the order it was found in. The total is then used to work +% back through the grabbers so they apply to the argument right to left. +% \begin{macrocode} +\int_new:N \l_xparse_processor_int +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_xparse_signature_tl} +% Token list variable for constructing signatures. +% \begin{macrocode} +\tl_new:N \l_xparse_signature_tl +% \end{macrocode} +%\end{variable} +% +% \begin{variable}{\l_xparse_tmp_tl} +% A general purpose token list variable. +% \begin{macrocode} +\tl_new:N \l_xparse_tmp_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_xparse_total_args_int} +% The total number of arguments is used to create the internal function +% which has a fixed number of arguments. +% \begin{macrocode} +\int_new:N \l_xparse_total_args_int +% \end{macrocode} +% \end{variable} +% +% \subsection{Turning the argument specifier into grabbers} +% +% \begin{macro}{\xparse_add_grabber_mandatory:N} +% \begin{macro}{\xparse_add_grabber_optional:N} +% To keep the various checks needed in one place, adding the grabber to +% the signature is done here. For mandatory arguments, the only question +% is whether to add a long grabber. For optional arguments, there is +% also a check to see if any mandatory arguments are still to be added. +% This is used to determine whether to skip spaces or not where +% searching for the argument. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \xparse_add_grabber_mandatory:N #1 + { + \tl_put_right:Nx \l_xparse_signature_tl + { + \exp_not:c + { xparse_grab_ #1 \bool_if:NT \l_xparse_long_bool { _long } :w } + } + \bool_set_false:N \l_xparse_long_bool + \int_decr:N \l_xparse_mandatory_args_int + } +\cs_new_protected_nopar:Npn \xparse_add_grabber_optional:N #1 + { + \tl_put_right:Nx \l_xparse_signature_tl + { + \exp_not:c + { + xparse_grab_ #1 + \bool_if:NT \l_xparse_long_bool { _long } + \int_compare:nNnF \l_xparse_mandatory_args_int > \c_zero + { _trailing } + :w + } + } + \bool_set_false:N \l_xparse_long_bool + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% All of the argument-adding functions work in essentially the same +% way, except the one for \texttt{m} arguments. Any collected \texttt{m} +% arguments are added to the signature, then the appropriate grabber +% is added to the signature. Some of the adding functions also pick up +% one or more arguments, and are also added to the signature. All of the +% functions then call the loop function \cs{xparse_prepare_signature:N}. +% +% \begin{macro}{\xparse_add_type_+:w} +% Making the next argument \cs{long} means setting the flag and +% knocking one back off the total argument count. The \texttt{m} +% arguments are recorded here as this has to be done for every case +% where there is then a \cs{long} argument. +% \begin{macrocode} +\cs_new_protected_nopar:cpn { xparse_add_type_+:w } + { + \xparse_flush_m_args: + \bool_set_true:N \l_xparse_long_bool + \bool_set_false:N \l_xparse_m_only_bool + \int_decr:N \l_xparse_total_args_int + \xparse_prepare_signature:N + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\xparse_add_type_>:w} +% When a processor is found, the function \cs{xparse_process_arg:n} +% is added to the signature along with the processor code itself. When +% the signature is used, the code will be added to an execution list by +% \cs{xparse_process_arg:n}. Here, the loop calls +% \cs{xparse_prepare_signature_aux:N} rather than +% \cs{xparse_prepare_signature:N} so that the flag is not reset. +% \begin{macrocode} +\cs_new_protected:cpn { xparse_add_type_>:w } #1 + { + \bool_set_true:N \l_xparse_processor_bool + \xparse_flush_m_args: + \int_decr:N \l_xparse_total_args_int + \tl_put_right:Nn \l_xparse_signature_tl { \xparse_process_arg:n {#1} } + \xparse_prepare_signature_aux:N + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\xparse_add_type_d:w} +% To save on repeated code, \texttt{d} is actually turned into +% the same grabber as is used by \texttt{D}, by putting the +% \cs{NoValue} default in the correct place. So there is some +% simple argument re-arrangement to do. Remember that |#1| and |#2| +% should be single tokens. +% \begin{macrocode} +\cs_new_protected:Npn \xparse_add_type_d:w #1#2 + { \xparse_add_type_D:w #1 #2 { \NoValue } } +% \end{macrocode} +%\end{macro} +% +% \begin{macro}{\xparse_add_type_D:w} +% All of the optional delimited arguments are handled internally by +% the \texttt{D} type. At this stage, the two delimiters are stored +% along with the default value. +% \begin{macrocode} +\cs_new_protected:Npn \xparse_add_type_D:w #1#2#3 + { + \xparse_flush_m_args: + \xparse_add_grabber_optional:N D + \tl_put_right:Nn \l_xparse_signature_tl { #1 #2 {#3} } + \xparse_prepare_signature:N + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\xparse_add_type_g:w} +% The \texttt{g} type is simply an alias for \texttt{G} with the +% correct default built-in. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \xparse_add_type_g:w + { \xparse_add_type_G:w { \NoValue } } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\xparse_add_type_G:w} +% For the \texttt{G} type, the grabber and the default are added to +% the signature. +% \begin{macrocode} +\cs_new_protected:Npn \xparse_add_type_G:w #1 + { + \xparse_flush_m_args: + \xparse_add_grabber_optional:N G + \tl_put_right:Nn \l_xparse_signature_tl { {#1} } + \xparse_prepare_signature:N + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\xparse_add_type_l:w} +% Finding \texttt{l} arguments is very simple: there is nothing to do +% other than add the grabber. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \xparse_add_type_l:w + { + \xparse_flush_m_args: + \xparse_add_grabber_mandatory:N l + \xparse_prepare_signature:N + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\xparse_add_type_m:w} +% The \texttt{m} type is special as short arguments which are not +% post-processed are simply counted at this stage. Thus there is a check +% to see if either of these cases apply. If so, a one-argument grabber +% is added to the signature. On the other hand, if a standard short +% argument is required it is simply counted at this stage, to be +% added later using \cs{xparse_flush_m_args:}. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \xparse_add_type_m:w + { + \bool_if:nTF { \l_xparse_long_bool || \l_xparse_processor_bool } + { + \xparse_flush_m_args: + \xparse_add_grabber_mandatory:N m + } + { \int_incr:N \l_xparse_m_args_int } + \xparse_prepare_signature:N + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\xparse_add_type_t:w} +% Setting up a \texttt{t} argument means collecting one token for the +% test, and adding it along with the grabber to the signature. +% \begin{macrocode} +\cs_new_protected:Npn \xparse_add_type_t:w #1 + { + \xparse_flush_m_args: + \xparse_add_grabber_optional:N t + \tl_put_right:Nn \l_xparse_signature_tl { #1 } + \xparse_prepare_signature:N + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\xparse_add_type_u:w} +% At the set up stage, the \texttt{u} type argument is identical to the +% \texttt{G} type except for the name of the grabber function. +% \begin{macrocode} +\cs_new_protected:Npn \xparse_add_type_u:w #1 + { + \xparse_flush_m_args: + \xparse_add_grabber_mandatory:N u + \tl_put_right:Nn \l_xparse_signature_tl { {#1} } + \xparse_prepare_signature:N + } +% \end{macrocode} +%\end{macro} +% +% \begin{macro}{\xparse_check_and_add:N} +% This function checks if the argument type actually exists and gives +% an error if it doesn't. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \xparse_check_and_add:N #1 + { + \cs_if_free:cTF { xparse_add_type_ #1 :w } + { + \msg_error:nnx { xparse } { unknown-argument-type } + { \tl_to_str:n {#1} } + \xparse_add_type_m:w + } + { \use:c { xparse_add_type_ #1 :w } } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\xparse_count_mandatory:n} +% \begin{macro}{\xparse_count_mandatory:N} +% \begin{macro}[aux]{\xparse_count_mandatory_aux:N} +% To count up mandatory arguments before the main parsing run, the +% same approach is used. First, check if the current token is a +% short-cut for another argument type. If it is, expand it and loop +% again. If not, then look for a `counting' function to check the +% argument type. No error is raised here if one is not found as one +% will be raised by later code. +% \begin{macrocode} +\cs_new_protected:Npn \xparse_count_mandatory:n #1 + { + \int_zero:N \l_xparse_mandatory_args_int + \xparse_count_mandatory:N #1 \q_nil + } +\cs_new_protected:Npn \xparse_count_mandatory:N #1 + { + \quark_if_nil:NF #1 + { + \prop_if_in:NnTF \c_xparse_shorthands_prop {#1} + { + \prop_get:NnN \c_xparse_shorthands_prop {#1} \l_xparse_tmp_tl + \exp_last_unbraced:NV \xparse_count_mandatory:N \l_xparse_tmp_tl + } + { \xparse_count_mandatory_aux:N #1 } + } + } +\cs_new_protected:Npn \xparse_count_mandatory_aux:N #1 + { + \cs_if_free:cTF { xparse_count_type_ #1 :w } + { \xparse_count_type_m:w } + { \use:c { xparse_count_type_ #1 :w } } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\xparse_count_type_>:w} +% \begin{macro}{\xparse_count_type_+:w} +% \begin{macro}{\xparse_count_type_d:w} +% \begin{macro}{\xparse_count_type_D:w} +% \begin{macro}{\xparse_count_type_g:w} +% \begin{macro}{\xparse_count_type_G:w} +% \begin{macro}{\xparse_count_type_l:w} +% \begin{macro}{\xparse_count_type_m:w} +% \begin{macro}{\xparse_count_type_t:w} +% \begin{macro}{\xparse_count_type_u:w} +% For counting the mandatory arguments, a function is provided for +% each argument type that will mop any extra arguments and call the +% loop function. Only the counting functions for mandatory arguments +% actually do anything: the rest are simply there to ensure the loop +% continues correctly. +% \begin{macrocode} +\cs_new_protected:cpn { xparse_count_type_>:w } #1 + { \xparse_count_mandatory:N } +\cs_new_protected_nopar:cpn { xparse_count_type_+:w } + { \xparse_count_mandatory:N } +\cs_new_protected:Npn \xparse_count_type_d:w #1#2 + { \xparse_count_mandatory:N } +\cs_new_protected:Npn \xparse_count_type_D:w #1#2#3 + { \xparse_count_mandatory:N } +\cs_new_protected_nopar:Npn \xparse_count_type_g:w + { \xparse_count_mandatory:N } +\cs_new_protected:Npn \xparse_count_type_G:w #1 + { \xparse_count_mandatory:N } +\cs_new_protected_nopar:Npn \xparse_count_type_l:w + { + \int_incr:N \l_xparse_mandatory_args_int + \xparse_count_mandatory:N + } +\cs_new_protected_nopar:Npn \xparse_count_type_m:w + { + \int_incr:N \l_xparse_mandatory_args_int + \xparse_count_mandatory:N + } +\cs_new_protected:Npn \xparse_count_type_t:w #1 + { \xparse_count_mandatory:N } +\cs_new_protected:Npn \xparse_count_type_u:w #1 + { + \int_incr:N \l_xparse_mandatory_args_int + \xparse_count_mandatory:N + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\xparse_declare_cmd:Nnn} +% \begin{macro}[aux]{\xparse_declare_cmd_aux:Nnn} +% \begin{macro}[aux]{\xparse_declare_cmd_aux:cnn} +% \begin{macro}[aux]{\xparse_declare_cmd_all_m:Nn} +% \begin{macro}[aux]{\xparse_declare_cmd_mixed:Nn} +% First, the signature is set up from the argument specification. There +% is then a check: if only \texttt{m} arguments are needed (which +% includes functions with no arguments at all) then the definition is +% simple. On the other hand, if the signature is more complex then an +% internal function actually contains the code with the user function +% as a simple wrapper. +% \begin{macrocode} +\cs_new_protected:Npn \xparse_declare_cmd:Nnn #1#2 + { + \cs_if_exist:NTF #1 + { + \msg_warning:nnxx { xparse } { redefine-command } + { \token_to_str:N #1 } { \tl_to_str:n {#2} } + } + { + \msg_info:nnxx { xparse } { define-command } + { \token_to_str:N #1 } { \tl_to_str:n {#2} } + } + \xparse_declare_cmd_aux:Nnn #1 {#2} + } +\cs_new_protected:Npn \xparse_declare_cmd_aux:Nnn #1#2#3 + { + \tl_clear_new:c { l_xparse_ \token_to_str:N #1 _arg_spec_tl } + \tl_set:cn { l_xparse_ \token_to_str:N #1 _arg_spec_tl } {#2} + \xparse_count_mandatory:n {#2} + \xparse_prepare_signature:n {#2} + \bool_if:NTF \l_xparse_m_only_bool + { \xparse_declare_cmd_all_m:Nn #1 {#3} } + { \xparse_declare_cmd_mixed:Nn #1 {#3} } + } +\cs_generate_variant:Nn \xparse_declare_cmd_aux:Nnn { cnn } +\cs_new_protected:Npn \xparse_declare_cmd_all_m:Nn #1#2 + { + \cs_generate_from_arg_count:NNnn + #1 \cs_set_protected_nopar:Npn \l_xparse_total_args_int {#2} + } +\cs_new_protected:Npn \xparse_declare_cmd_mixed:Nn #1#2 + { + \group_begin: + \tex_escapechar:D 92 \scan_stop: + \tl_set:Nx \l_xparse_function_tl { \token_to_str:N #1 } + \exp_args:NNNo \group_end: + \tl_set:Nn \l_xparse_function_tl { \l_xparse_function_tl } + \cs_set_protected_nopar:Npx #1 + { + \exp_not:n + { + \int_zero:N \l_xparse_processor_int + \tl_set:Nn \l_xparse_args_tl + } + { \exp_not:c { \l_xparse_function_tl } } + \exp_not:o \l_xparse_signature_tl + \exp_not:N \l_xparse_args_tl + } + \cs_generate_from_arg_count:cNnn + { \token_to_str:N #1 } \cs_set:Npn \l_xparse_total_args_int {#2} + } +% \end{macrocode} +% \end{macro} +% \end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +% +% \begin{macro}{\xparse_declare_cmd_implementation:nNn} +% Creating a stand-alone implementation using the \enquote{two-part} +% mechanism is quite easy as this is just a wrapper for +% \cs{cs_generate_from_arg_count:cNnn}. +% \begin{macrocode} +\cs_new_protected:Npn \xparse_declare_cmd_implementation:nNn #1#2#3 + { + \cs_generate_from_arg_count:cNnn { implementation_ #1 :w } + \cs_set:Npn {#2} {#3} + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\xparse_declare_cmd_interface:Nnn} +% \begin{macro}[aux]{\xparse_declare_cmd_interface_all_m:Nn} +% \begin{macro}[aux]{\xparse_declare_cmd_interface_mixed:Nn} +% As with the basic function \cs{xparse_declare_cmd:Nnn}, there are +% three things to do here. First, generate a signature from the +% argument specification. Then use that to create a function which +% will call the implementation part. Finally, a holder implementation +% is created. As before, there is a short-cut for functions which only +% have \texttt{m} type arguments. +% \begin{macrocode} +\cs_new_protected:Npn \xparse_declare_cmd_interface:Nnn #1#2#3 + { + \xparse_prepare_signature:n {#3} + \bool_if:NTF \l_xparse_m_only_bool + { \xparse_declare_cmd_interface_all_m:Nn #1 {#2} } + { \xparse_declare_cmd_interface_mixed:Nn #1 {#2} } + \cs_generate_from_arg_count:cNnn { implementation_ #2 :w } + \cs_set:Npn \l_xparse_total_args_int { '#2' } + } +\cs_new_protected:Npn \xparse_declare_cmd_interface_all_m:Nn #1#2 + { + \cs_generate_from_arg_count:NNnn + #1 \cs_set_protected_nopar:Npn \l_xparse_total_args_int + { \use:c { implementation_ #2 :w } } + } +\cs_new_protected:Npn \xparse_declare_cmd_interface_mixed:Nn #1#2 + { + \cs_set_protected_nopar:Npx #1 + { + \exp_not:n + { + \int_zero:N \l_xparse_processor_int + \tl_set:Nn \l_xparse_args_tl + } + { \exp_not:c { \token_to_str:N #1 } } + \exp_not:o \l_xparse_signature_tl + \exp_not:N \l_xparse_args_tl + } + \cs_generate_from_arg_count:cNnn + { \token_to_str:N #1 } \cs_set:Npn \l_xparse_total_args_int + { \use:c { implementation_ #2 :w } } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\xparse_declare_env:nnnn} +% The idea here is to make sure that the end of the environment has the +% same arguments available as the beginning. +% \begin{macrocode} +\cs_new_protected:Npn \xparse_declare_env:nnnn #1#2#3#4 + { + \bool_set_true:N \l_xparse_environment_bool + \cs_if_exist:cTF {#1} + { + \msg_warning:nnxx { xparse } { redefine-environment } + { \tl_to_str:n {#1} } { \tl_to_str:n {#2} } + } + { + \msg_info:nnxx { xparse } { define-environment } + { \tl_to_str:n {#1} } { \tl_to_str:n {#2} } + } + \xparse_declare_cmd_aux:cnn { environment_begin_ #1 :w } {#2} + { + \group_begin: + \cs_set_protected_nopar:cpx { environment_end_ #1 :w } + { + \exp_not:c { environment_end_ #1 _aux:N } + \exp_not:o \l_xparse_args_tl + \group_end: + } + #3 + } + \cs_set_protected_nopar:cpx { environment_end_ #1 : } + { \exp_not:c { environment_end_ #1 :w } } + \bool_set_false:N \l_xparse_environment_bool + \cs_set_nopar:cpx { environment_end_ #1 _aux:N } ##1 + { \exp_not:c { environment_end_ #1 _aux :w } } + \cs_generate_from_arg_count:cNnn + { environment_end_ #1 _aux :w } \cs_set:Npn + \l_xparse_total_args_int {#4} + \cs_set_eq:cc {#1} { environment_begin_ #1 :w } + \cs_set_eq:cc { end #1 } { environment_end_ #1 : } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\xparse_flush_m_args:} +% As \texttt{m} arguments are simply counted, there is a need to add +% them to the token register in a block. As this function can only +% be called if something other than \texttt{m} turns up, the flag can +% be switched here. The total number of mandatory arguments added to +% the signature is also decreased by the appropriate amount. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \xparse_flush_m_args: + { + \cs_if_exist:cT { xparse_grab_m_ \int_use:N \l_xparse_m_args_int :w } + { + \tl_put_right:Nx \l_xparse_signature_tl + { \exp_not:c { xparse_grab_m_ \int_use:N \l_xparse_m_args_int :w } } + \int_set:Nn \l_xparse_mandatory_args_int + { \l_xparse_mandatory_args_int - \l_xparse_m_args_int } + } + \int_zero:N \l_xparse_m_args_int + \bool_set_false:N \l_xparse_m_only_bool + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[TF]{\xparse_if_no_value:n} +% Tests for \cs{NoValue}. +% \begin{macrocode} +\prg_new_conditional:Npnn \xparse_if_no_value:n #1 { T , F , TF } + { \str_if_eq:nnTF {#1} { \NoValue } \prg_return_true: \prg_return_false: } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\xparse_prepare_signature:n} +% Creating the signature is a case of working through the input and +% turning into the output in \cs{l_xparse_signature_tl}. A track is +% also kept of the total number of arguments. This function sets +% everything up then hands off to the parser. +% \begin{macrocode} +\cs_new_protected:Npn \xparse_prepare_signature:n #1 + { + \bool_set_false:N \l_xparse_long_bool + \int_zero:N \l_xparse_m_args_int + \bool_if:NTF \l_xparse_environment_bool + { \bool_set_false:N \l_xparse_m_only_bool } + { \bool_set_true:N \l_xparse_m_only_bool } + \bool_set_false:N \l_xparse_processor_bool + \tl_clear:N \l_xparse_signature_tl + \int_zero:N \l_xparse_total_args_int + \xparse_prepare_signature:N #1 \q_nil + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\xparse_prepare_signature:N} +% \begin{macro}[aux]{\xparse_prepare_signature_aux:N} +% The main signature-preparation loop is in two parts, to keep the code +% a little clearer. Most of the checks here is pretty clear, with a key +% point to watch what is next on the stack so that the loop continues +% correctly. +% \begin{macrocode} +\cs_new_protected:Npn \xparse_prepare_signature:N #1 + { + \bool_set_false:N \l_xparse_processor_bool + \xparse_prepare_signature_aux:N #1 + } +\cs_new_protected:Npn \xparse_prepare_signature_aux:N #1 + { + \quark_if_nil:NTF #1 + { \bool_if:NF \l_xparse_m_only_bool { \xparse_flush_m_args: } } + { + \prop_if_in:NnTF \c_xparse_shorthands_prop {#1} + { + \prop_get:NnN \c_xparse_shorthands_prop {#1} \l_xparse_tmp_tl + \exp_after:wN \xparse_prepare_signature:N \l_xparse_tmp_tl + } + { + \int_incr:N \l_xparse_total_args_int + \xparse_check_and_add:N #1 + } + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\xparse_process_arg:n} +% Processors are saved for use later during the grabbing process. +% \begin{macrocode} +\cs_new_protected:Npn \xparse_process_arg:n #1 + { + \int_incr:N \l_xparse_processor_int + \cs_set:cpn { xparse_processor_ \int_use:N \l_xparse_processor_int :n } ##1 + { #1 {##1} } + } +% \end{macrocode} +% \end{macro} +% +% \subsection{Grabbing arguments} +% +% \begin{macro}{\xparse_add_arg:n, \xparse_add_arg:V} +% \begin{macro}[aux]{\xparse_add_arg_aux:n, \xparse_add_arg_aux:V} +% The argument-storing system provides a single point for interfacing +% with processors. They are done in a loop, counting downward. In this +% way, the processor which was found last is executed first. The result +% is that processors apply from right to left, as intended. Notice that +% a set of braces are added back around the result of processing so that +% the internal function will correctly pick up one argument for each +% input argument. +% \begin{macrocode} +\cs_new_protected:Npn \xparse_add_arg:n #1 + { + \int_compare:nNnTF \l_xparse_processor_int = \c_zero + { \tl_put_right:Nn \l_xparse_args_tl { {#1} } } + { + \xparse_if_no_value:nTF {#1} + { + \int_zero:N \l_xparse_processor_int + \tl_put_right:Nn \l_xparse_args_tl { {#1} } + } + { \xparse_add_arg_aux:n {#1} } + } + } +\cs_generate_variant:Nn \xparse_add_arg:n { V } +\cs_new_protected:Npn \xparse_add_arg_aux:n #1 + { + \tl_set_eq:NN \ProcessedArgument \l_xparse_arg_tl + \use:c { xparse_processor_ \int_use:N \l_xparse_processor_int :n } {#1} + \int_decr:N \l_xparse_processor_int + \int_compare:nNnTF \l_xparse_processor_int = \c_zero + { + \tl_put_right:Nx \l_xparse_args_tl + { { \exp_not:V \ProcessedArgument } } + } + { \xparse_add_arg_aux:V \ProcessedArgument } +} +\cs_generate_variant:Nn \xparse_add_arg_aux:n { V } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% All of the grabbers follow the same basic pattern. The initial +% function sets up the appropriate information to define +% \cs{parse_grab_arg:w} to grab the argument. This means determining +% whether to use \cs{cs_set:Npn} or \cs{cs_set_nopar:Npn}, and for +% optional arguments whether to skip spaces. In all cases, +% \cs{xparse_grab_arg:w} is then called to actually do the grabbing. +% +% \begin{macro}{\xparse_grab_arg:w} +% \begin{macro}[aux]{\xparse_grab_arg_aux_i:w} +% \begin{macro}[aux]{\xparse_grab_arg_aux_ii:w} +% Each time an argument is actually grabbed, \pkg{xparse} defines a +% function to do it. In that way, long arguments from previous functions +% can be included in the definition of the grabber function, so that +% it does not raise an error if not long. The generic function used +% for this is reserved here. A couple of auxiliary functions are also +% needed in various places. +% \begin{macrocode} +\cs_new_protected:Npn \xparse_grab_arg:w { } +\cs_new_protected:Npn \xparse_grab_arg_aux_i:w { } +\cs_new_protected:Npn \xparse_grab_arg_aux_ii:w { } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\xparse_grab_D:w} +% \begin{macro}{\xparse_grab_D_long:w} +% \begin{macro}{\xparse_grab_D_trailing:w} +% \begin{macro}{\xparse_grab_D_long_trailing:w} +% The generic delimited argument grabber. The auxiliary function does +% a peek test before calling \cs{xparse_grab_arg:w}, so that the +% optional nature of the argument works as expected. +% \begin{macrocode} +\cs_new_protected:Npn \xparse_grab_D:w #1#2#3#4 \l_xparse_args_tl + { + \xparse_grab_D_aux:NNnnNn #1 #2 {#3} {#4} \cs_set_protected_nopar:Npn + { _ignore_spaces } + } +\cs_new_protected:Npn \xparse_grab_D_long:w #1#2#3#4 \l_xparse_args_tl + { + \xparse_grab_D_aux:NNnnNn #1 #2 {#3} {#4} \cs_set_protected:Npn + { _ignore_spaces } + } +\cs_new_protected:Npn \xparse_grab_D_trailing:w #1#2#3#4 \l_xparse_args_tl + { \xparse_grab_D_aux:NNnnNn #1 #2 {#3} {#4} \cs_set_protected_nopar:Npn { } } +\cs_new_protected:Npn \xparse_grab_D_long_trailing:w #1#2#3#4 \l_xparse_args_tl + { \xparse_grab_D_aux:NNnnNn #1 #2 {#3} {#4} \cs_set_protected:Npn { } } +% \end{macrocode} +% \begin{macro}[aux]{\xparse_grab_D_aux:NNnnNn} +% This is a bit complicated. The idea is that, in order to check for +% nested optional argument tokens (\texttt{[[...]]} and so on) the +% argument needs to be grabbed without removing any braces at all. If +% this is not done, then cases like |[{[}]| fail. So after testing for +% an optional argument, it is collected piece-wise. First, the opening +% token is removed, then a check is made for a group. If it looks like +% the entire argument is a group, then an extra set of braces are +% added back in. The closing token is then used to collect everything +% else. There is then a test to see if there is nesting, by looking +% for a \enquote{spare} open-argument token. If that is found, things hand +% off to a loop to deal with that. +% \begin{macrocode} +\cs_new_protected:Npn \xparse_grab_D_aux:NNnnNn #1#2#3#4#5#6 + { + #5 \xparse_grab_arg:w #1 + { + \peek_meaning:NTF \c_group_begin_token + { \xparse_grab_arg_aux_i:w } + { \xparse_grab_arg_aux_ii:w } + } + #5 \xparse_grab_arg_aux_i:w ##1 + { + \peek_charcode:NTF #2 + { \xparse_grab_arg_aux_ii:w { {##1} } } + { \xparse_grab_arg_aux_ii:w {##1} } + } + #5 \xparse_grab_arg_aux_ii:w ##1 #2 + { + \tl_if_in:nnTF {##1} {#1} + { \xparse_grab_D_nested:NNnnN #1 #2 {##1} {#4} #5 } + { + \xparse_add_arg:n {##1} + #4 \l_xparse_args_tl + } + } + \use:c { peek_charcode #6 :NTF } #1 + { \xparse_grab_arg:w } + { + \xparse_add_arg:n {#3} + #4 \l_xparse_args_tl + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \begin{macro}[aux]{\xparse_grab_D_nested:NNnnN} +% \begin{macro}{\l_xparse_nesting_a_tl} +% \begin{macro}{\l_xparse_nesting_b_tl} +% \begin{macro}{\q_xparse} +% Catching nested optional arguments means more work. The aim here is +% to collect up each pair of optional tokens without \TeX{} helping out, +% and without counting anything. The code above will already have +% removed the leading opening token and a closing token, but the +% wrong one. The aim is then to work through the the material grabbed +% so far and divide it up on each opening token, grabbing a closing +% token to match (thus working in pairs). Once there are no opening +% tokens, then there is a second check to see if there are any +% opening tokens in the second part of the argument (for things +% like |[][]|). Once everything has been found, the entire collected +% material is added to the output as a single argument. +% \begin{macrocode} +\tl_new:N \l_xparse_nesting_a_tl +\tl_new:N \l_xparse_nesting_b_tl +\quark_new:N \q_xparse +\cs_new_protected:Npn \xparse_grab_D_nested:NNnnN #1#2#3#4#5 + { + \tl_clear:N \l_xparse_nesting_a_tl + \tl_clear:N \l_xparse_nesting_b_tl + #5 \xparse_grab_arg:w ##1 #1 ##2 \q_xparse ##3 #2 + { + \tl_put_right:Nn \l_xparse_nesting_a_tl { ##1 #1 } + \tl_put_right:Nn \l_xparse_nesting_b_tl { #2 ##3 } + \tl_if_in:nnTF {##2} {#1} + { \xparse_grab_arg:w ##2 \q_xparse } + { + \tl_put_right:Nn \l_xparse_nesting_a_tl {##2} + \tl_if_in:NnTF \l_xparse_nesting_b_tl {#1} + { + \tl_set_eq:NN \l_xparse_tmp_tl \l_xparse_nesting_b_tl + \tl_clear:N \l_xparse_nesting_b_tl + \exp_after:wN \xparse_grab_arg:w \l_xparse_tmp_tl \q_xparse + } + { + \tl_put_right:No \l_xparse_nesting_a_tl + \l_xparse_nesting_b_tl + \xparse_add_arg:V \l_xparse_nesting_a_tl + #4 \l_xparse_args_tl + } + } + } + \xparse_grab_arg:w #3 \q_xparse + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\xparse_grab_G:w} +% \begin{macro}{\xparse_grab_G_long:w} +% \begin{macro}{\xparse_grab_G_trailing:w} +% \begin{macro}{\xparse_grab_G_long_trailing:w} +% \begin{macro}[aux]{\xparse_grab_G_aux:nnNn} +% Optional groups are checked by meaning, so that the same code will +% work with, for example, Con\TeX{}t-like input. +% \begin{macrocode} +\cs_new_protected:Npn \xparse_grab_G:w #1#2 \l_xparse_args_tl + { + \xparse_grab_G_aux:nnNn {#1} {#2} \cs_set_protected_nopar:Npn + { _ignore_spaces } + } +\cs_new_protected:Npn \xparse_grab_G_long:w #1#2 \l_xparse_args_tl + { + \xparse_grab_G_aux:nnNn {#1} {#2} \cs_set_protected:Npn { _ignore_spaces } + } +\cs_new_protected:Npn \xparse_grab_G_trailing:w #1#2 \l_xparse_args_tl + { \xparse_grab_G_aux:nnNn {#1} {#2} \cs_set_protected_nopar:Npn { } } +\cs_new_protected:Npn \xparse_grab_G_long_trailing:w #1#2 \l_xparse_args_tl + { \xparse_grab_G_aux:nnNn {#1} {#2} \cs_set_protected:Npn { } } +\cs_new_protected:Npn \xparse_grab_G_aux:nnNn #1#2#3#4 + { + #3 \xparse_grab_arg:w ##1 + { + \xparse_add_arg:n {##1} + #2 \l_xparse_args_tl + } + \use:c { peek_meaning #4 :NTF } \c_group_begin_token + { \xparse_grab_arg:w } + { + \xparse_add_arg:n {#1} + #2 \l_xparse_args_tl + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\xparse_grab_l:w} +% \begin{macro}{\xparse_grab_l_long:w} +% \begin{macro}[aux]{\xparse_grab_l_aux:nN} +% Argument grabbers for mandatory \TeX\ arguments are pretty simple. +% \begin{macrocode} +\cs_new_protected:Npn \xparse_grab_l:w #1 \l_xparse_args_tl + { \xparse_grab_l_aux:nN {#1} \cs_set_protected_nopar:Npn } +\cs_new_protected:Npn \xparse_grab_l_long:w #1 \l_xparse_args_tl + { \xparse_grab_l_aux:nN {#1} \cs_set_protected:Npn } +\cs_new_protected:Npn \xparse_grab_l_aux:nN #1#2 + { + #2 \xparse_grab_arg:w ##1## + { + \xparse_add_arg:n {##1} + #1 \l_xparse_args_tl + } + \xparse_grab_arg:w + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\xparse_grab_m:w} +% \begin{macro}{\xparse_grab_m_long:w} +% Collecting a single mandatory argument is quite easy. +% \begin{macrocode} +\cs_new_protected:Npn \xparse_grab_m:w #1 \l_xparse_args_tl + { + \cs_set_protected_nopar:Npn \xparse_grab_arg:w ##1 + { + \xparse_add_arg:n {##1} + #1 \l_xparse_args_tl + } + \xparse_grab_arg:w + } +\cs_new_protected:Npn \xparse_grab_m_long:w #1 \l_xparse_args_tl + { + \cs_set_protected:Npn \xparse_grab_arg:w ##1 + { + \xparse_add_arg:n {##1} + #1 \l_xparse_args_tl + } + \xparse_grab_arg:w + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\xparse_grab_m_1:w} +% \begin{macro}{\xparse_grab_m_2:w} +% \begin{macro}{\xparse_grab_m_3:w} +% \begin{macro}{\xparse_grab_m_4:w} +% \begin{macro}{\xparse_grab_m_5:w} +% \begin{macro}{\xparse_grab_m_6:w} +% \begin{macro}{\xparse_grab_m_7:w} +% \begin{macro}{\xparse_grab_m_8:w} +% Grabbing 1--8 mandatory arguments. We don't need to worry about +% nine arguments as this is only possible if everything is +% mandatory. Each function has an auxiliary so that \cs{par} tokens +% from other arguments still work. +% \begin{macrocode} +\cs_new_protected:cpn { xparse_grab_m_1:w } #1 \l_xparse_args_tl + { + \cs_set_protected_nopar:Npn \xparse_grab_arg:w ##1 + { + \tl_put_right:Nn \l_xparse_args_tl { {##1} } + #1 \l_xparse_args_tl + } + \xparse_grab_arg:w + } +\cs_new_protected:cpn { xparse_grab_m_2:w } #1 \l_xparse_args_tl + { + \cs_set_protected_nopar:Npn \xparse_grab_arg:w ##1##2 + { + \tl_put_right:Nn \l_xparse_args_tl { {##1} {##2} } + #1 \l_xparse_args_tl + } + \xparse_grab_arg:w + } +\cs_new_protected:cpn { xparse_grab_m_3:w } #1 \l_xparse_args_tl + { + \cs_set_protected_nopar:Npn \xparse_grab_arg:w ##1##2##3 + { + \tl_put_right:Nn \l_xparse_args_tl { {##1} {##2} {##3} } + #1 \l_xparse_args_tl + } + \xparse_grab_arg:w + } +\cs_new_protected:cpn { xparse_grab_m_4:w } #1 \l_xparse_args_tl + { + \cs_set_protected_nopar:Npn \xparse_grab_arg:w ##1##2##3##4 + { + \tl_put_right:Nn \l_xparse_args_tl { {##1} {##2} {##3} {##4} } + #1 \l_xparse_args_tl + } + \xparse_grab_arg:w + } +\cs_new_protected:cpn { xparse_grab_m_5:w } #1 \l_xparse_args_tl + { + \cs_set_protected_nopar:Npn \xparse_grab_arg:w ##1##2##3##4##5 + { + \tl_put_right:Nn \l_xparse_args_tl { {##1} {##2} {##3} {##4} {##5} } + #1 \l_xparse_args_tl + } + \xparse_grab_arg:w + } +\cs_new_protected:cpn { xparse_grab_m_6:w } #1 \l_xparse_args_tl + { + \cs_set_protected_nopar:Npn \xparse_grab_arg:w ##1##2##3##4##5##6 + { + \tl_put_right:Nn \l_xparse_args_tl + { {##1} {##2} {##3} {##4} {##5} {##6} } + #1 \l_xparse_args_tl + } + \xparse_grab_arg:w + } +\cs_new_protected:cpn { xparse_grab_m_7:w } #1 \l_xparse_args_tl + { + \cs_set_protected_nopar:Npn \xparse_grab_arg:w ##1##2##3##4##5##6##7 + { + \tl_put_right:Nn \l_xparse_args_tl + { {##1} {##2} {##3} {##4} {##5} {##6} {##7} } + #1 \l_xparse_args_tl + } + \xparse_grab_arg:w + } +\cs_new_protected:cpn { xparse_grab_m_8:w } #1 \l_xparse_args_tl + { + \cs_set_protected_nopar:Npn \xparse_grab_arg:w ##1##2##3##4##5##6##7##8 + { + \tl_put_right:Nn \l_xparse_args_tl + { {##1} {##2} {##3} {##4} {##5} {##6} {##7} {##8} } + #1 \l_xparse_args_tl + } + \xparse_grab_arg:w + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +%\end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\xparse_grab_t:w} +% \begin{macro}{\xparse_grab_t_long:w} +% \begin{macro}{\xparse_grab_t_trailing:w} +% \begin{macro}{\xparse_grab_t_long_trailing:w} +% \begin{macro}[aux]{\xparse_grab_t_aux:NnNn} +% Dealing with a token is quite easy. Check the match, remove the +% token if needed and add a flag to the output. +% \begin{macrocode} +\cs_new_protected:Npn \xparse_grab_t:w #1#2 \l_xparse_args_tl + { + \xparse_grab_t_aux:NnNn #1 {#2} \cs_set_protected_nopar:Npn + { _ignore_spaces } + } +\cs_new_protected:Npn \xparse_grab_t_long:w #1#2 \l_xparse_args_tl + { \xparse_grab_t_aux:NnNn #1 {#2} \cs_set_protected:Npn { _ignore_spaces } } +\cs_new_protected:Npn \xparse_grab_t_trailing:w #1#2 \l_xparse_args_tl + { \xparse_grab_t_aux:NnNn #1 {#2} \cs_set_protected_nopar:Npn { } } +\cs_new_protected:Npn \xparse_grab_t_long_trailing:w #1#2 \l_xparse_args_tl + { \xparse_grab_t_aux:NnNn #1 {#2} \cs_set_protected:Npn { } } +\cs_new_protected:Npn \xparse_grab_t_aux:NnNn #1#2#3#4 + { + #3 \xparse_grab_arg:w + { + \use:c { peek_charcode_remove #4 :NTF } #1 + { + \xparse_add_arg:n { \BooleanTrue } + #2 \l_xparse_args_tl + } + { + \xparse_add_arg:n { \BooleanFalse } + #2 \l_xparse_args_tl + } + } + \xparse_grab_arg:w + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\xparse_grab_u:w} +% \begin{macro}{\xparse_grab_u_long:w} +% \begin{macro}[aux]{\xparse_grab_u_aux:NnN} +% Grabbing up to a list of tokens is quite easy: define the grabber, +% and then collect. +% \begin{macrocode} +\cs_new_protected:Npn \xparse_grab_u:w #1#2 \l_xparse_args_tl + { \xparse_grab_u_aux:NnN {#1} {#2} \cs_set_protected_nopar:Npn } +\cs_new_protected:Npn \xparse_grab_u_long:w #1#2 \l_xparse_args_tl + { \xparse_grab_u_aux:NnN {#1} {#2} \cs_set_protected:Npn } +\cs_new_protected:Npn \xparse_grab_u_aux:NnN #1#2#3 + { + #3 \xparse_grab_arg:w ##1 #1 + { + \xparse_add_arg:n {##1} + #2 \l_xparse_args_tl + } + \xparse_grab_arg:w + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{Argument processors} +% +% \begin{macro}{\xparse_process_to_str:n} +% A basic argument processor: as much an example as anything else. +% \begin{macrocode} +\cs_new_protected:Npn \xparse_process_to_str:n #1 + { \tl_set:Nx \ProcessedArgument { \tl_to_str:n {#1} } } +% \end{macrocode} +%\end{macro} +% +% \begin{macro}{\xparse_bool_reverse:N} +% A simple reversal. +% \begin{macrocode} +\cs_new_protected:Npn \xparse_bool_reverse:N #1 + { + \bool_if:NTF #1 + { \tl_set:Nn \ProcessedArgument { \c_false_bool } } + { \tl_set:Nn \ProcessedArgument { \c_true_bool } } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\l_xparse_split_argument_tl} +% \begin{macro}{\xparse_split_argument:nnn} +% \begin{macro}[aux]{\xparse_split_argument_aux_i:w} +% \begin{macro}[aux]{\xparse_split_argument_aux_ii:w} +% \begin{macro}[aux]{\xparse_split_argument_aux_iii:w} +% The idea of this function is to split the input $n + 1$ times using +% a given token. +% \begin{macrocode} +\tl_new:N \l_xparse_split_argument_tl +\group_begin: + \char_set_catcode_active:N \@ + \cs_new_protected:Npn \xparse_split_argument:nnn #1#2#3 + { + \tl_set:Nn \l_xparse_split_argument_tl {#3} + \group_begin: + \char_set_lccode:nn { `\@ } { `#2} + \tl_to_lowercase:n + { + \group_end: + \tl_replace_all_in:Nnn \l_xparse_split_argument_tl { @ } {#2} + } + \cs_set_protected:Npn \xparse_split_argument_aux_i:w + ##1 \q_mark ##2 #2 ##3 \q_stop + { + \tl_put_right:Nn \ProcessedArgument { {##2} } + ##1 \q_mark ##3 \q_stop + } + \cs_set_protected:Npn \xparse_split_argument_aux_iii:w + ##1 #2 ##2 \q_stop + { + \IfNoValueF {##1} + { + \msg_error:nnxxx { xparse } { split-excess-tokens } + { \tl_to_str:n {#2} } { \tl_to_str:n {#1} } + { \tl_to_str:n {#3} } + } + } + \tl_set:Nx \l_xparse_tmp_tl + { + \prg_replicate:nn { #1 + 1 } + { \xparse_split_argument_aux_i:w } + \xparse_split_argument_aux_ii:w + \exp_not:N \q_mark + \exp_not:o \l_xparse_split_argument_tl + \prg_replicate:nn {#1} { \exp_not:n {#2} \NoValue } + \exp_not:n { #2 \q_stop } + } + \l_xparse_tmp_tl + } +\group_end: +\cs_new_protected:Npn \xparse_split_argument_aux_i:w { } +\cs_new_protected:Npn \xparse_split_argument_aux_ii:w + #1 \q_mark #2 \q_stop + { + \tl_if_empty:nF {#2} + { \xparse_split_argument_aux_iii:w #2 \q_stop } + } +\cs_new_protected:Npn \xparse_split_argument_aux_iii:w { } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +%\begin{macro}{\l_xparse_split_list_tl} +%\begin{macro}{\xparse_split_list:nn} +%\begin{macro}{\xparse_split_list_aux:w} +% Splitting a list is done again by first dealing with active +% characters, then looping over the list using the same method as the +% \cs{clist_map_\ldots} functions. +% \begin{macrocode} +\tl_new:N \l_xparse_split_list_tl +\group_begin: + \char_set_catcode_active:N \@ + \cs_new_protected:Npn \xparse_split_list:nn #1#2 + { + \tl_set:Nn \l_xparse_split_list_tl {#2} + \group_begin: + \char_set_lccode:nn { `\@ } { `#1 } + \tl_to_lowercase:n + { + \group_end: + \tl_replace_all_in:Nnn \l_xparse_split_list_tl { @ } {#1} + } + \cs_set:Npn \xparse_split_list_aux:w ##1 #1 + { + \quark_if_recursion_tail_stop:n {##1} + \tl_put_right:Nn \ProcessedArgument { {##1} } + \xparse_split_list_aux:w + } + \tl_if_empty:NTF \l_xparse_split_list_tl + { \tl_set:Nn \ProcessedArgument { { } } } + { + \tl_clear:N \ProcessedArgument + \exp_after:wN \xparse_split_list_aux:w + \l_xparse_split_list_tl #1 + \q_recursion_tail #1 \q_recursion_stop + } + } +\group_end: +\cs_new_protected:Npn \xparse_split_list_aux:w { } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{Creating expandable functions} +% +% The trick here is to pass each grabbed argument along a chain of +% auxiliary functions. Each one ultimately calls the next in the chain, +% so that all of the arguments are passed along delimited using +% \cs{q_xparse}. At the end of the chain, the marker is removed +% so that the user-supplied code can be passed the correct number +% of arguments. All of this is done by expansion! +% +% \begin{macro}{\xparse_exp_add_type_d:w} +% As in the standard case, the trick here is to slot in the default +% and treat as type \texttt{D}. +% \begin{macrocode} +\cs_new_protected:Npn \xparse_exp_add_type_d:w #1#2 + { \xparse_exp_add_type_D:w #1 #2 { \NoValue } } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\xparse_exp_add_type_D:w} +% The most complex argument to grab in an expandable manner is the +% general delimited one. First, a short-cut is set up in +% \cs{l_xparse_tmp_tl} for the name of the current grabber function. +% This is then created to grab one argument and test if it is equal +% to the opening delimiter. If the test fails, the code adds the default +% value and closing delimiter before `recycling' the argument. In either +% case, the second auxiliary function is called. It finds the closing +% delimiter and so the optional argument (if any). The function then +% calls the next one in the chain, passing along the argument(s) +% grabbed thus-far using \cs{q_xparse} as a marker. +% \begin{macrocode} +\cs_new_protected:Npn \xparse_exp_add_type_D:w #1#2#3 + { + \tl_set:Nx \l_xparse_tmp_tl + { + \exp_after:wN \token_to_str:N \l_xparse_function_tl + \int_use:N \l_xparse_total_args_int + } + \xparse_exp_set:cpx { \l_xparse_tmp_tl } ##1 \q_xparse ##2 + { + \exp_not:N \tl_if_head_eq_charcode:nNTF {##2} #1 + { + \exp_not:c { \l_xparse_tmp_tl aux } + ##1 \exp_not:N \q_xparse + } + { + \exp_not:c { \l_xparse_tmp_tl aux } + ##1 \exp_not:N \q_xparse #3 #2 {##2} + } + } + \xparse_exp_set:cpx { \l_xparse_tmp_tl aux} ##1 \q_xparse ##2 #2 + { + \exp_not:c + { + \exp_after:wN \token_to_str:N \l_xparse_function_tl + \int_eval:n { \l_xparse_total_args_int + 1 } + } + ##1 {##2} \exp_not:N \q_xparse + } + \xparse_exp_prepare_function:N + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\xparse_exp_add_type_l:w} +% \begin{macro}{\xparse_exp_add_type_m:w} +% Gathering \texttt{l} and \texttt{m} arguments is almost the same. +% The grabber for the current argument is created to simply get the +% necessary argument and pass it along with any others through to the +% next function in the chain. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \xparse_exp_add_type_l:w + { + \xparse_exp_set:cpx + { + \exp_after:wN \token_to_str:N \l_xparse_function_tl + \int_use:N \l_xparse_total_args_int + } + ##1 \q_xparse ##2## + { + \exp_not:c + { + \exp_after:wN \token_to_str:N \l_xparse_function_tl + \int_eval:n { \l_xparse_total_args_int + 1 } + } + ##1 {##2} \exp_not:N \q_xparse + } + \xparse_exp_prepare_function:N + } +\cs_new_protected_nopar:Npn \xparse_exp_add_type_m:w + { + \int_incr:N \l_xparse_m_args_int + \xparse_exp_set:cpx + { + \exp_after:wN \token_to_str:N \l_xparse_function_tl + \int_use:N \l_xparse_total_args_int + } + ##1 \q_xparse ##2 + { + \exp_not:c + { + \exp_after:wN \token_to_str:N \l_xparse_function_tl + \int_eval:n { \l_xparse_total_args_int + 1 } + } + ##1 {##2} \exp_not:N \q_xparse + } + \xparse_exp_prepare_function:N + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\xparse_exp_add_type_t:w} +% Looking for a single token is a simpler version of the \texttt{D} +% code. The same idea of picking up one argument is used, but there is +% no need for a second function as there is no closing token to find. So +% either \cs{BooleanTrue} or \cs{BooleanFalse} are added to the list of +% arguments. In the later case, the grabber argument must be `recycled'. +% \begin{macrocode} +\cs_new_protected:Npn \xparse_exp_add_type_t:w #1 + { + \tl_set:Nx \l_xparse_tmp_tl + { + \exp_after:wN \token_to_str:N \l_xparse_function_tl + \int_eval:n { \l_xparse_total_args_int + 1 } + } + \xparse_exp_set:cpx + { + \exp_after:wN \token_to_str:N \l_xparse_function_tl + \int_use:N \l_xparse_total_args_int + } + ##1 \q_xparse ##2 + { + \exp_not:N \tl_if_head_eq_charcode:nNTF {##2} #1 + { + \exp_not:c { \l_xparse_tmp_tl } + ##1 \exp_not:n { { \BooleanTrue } \q_xparse } + } + { + \exp_not:c { \l_xparse_tmp_tl } + ##1 \exp_not:n { { \BooleanFalse } \q_xparse {##2} } + } + } + \xparse_exp_prepare_function:N + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\xparse_exp_add_type_u:w} +% Setting up for a \texttt{u} argument is a case of defining the +% grabber for the current argument in a delimited fashion. The rest of +% the process is as the other grabbers: add to the chain and call the +% next function. +% \begin{macrocode} +\cs_new_protected:Npn \xparse_exp_add_type_u:w #1 + { + \xparse_exp_set:cpx + { + \exp_after:wN \token_to_str:N \l_xparse_function_tl + \int_use:N \l_xparse_total_args_int + } + ##1 \q_xparse ##2 #1 + { + \exp_not:c + { + \exp_after:wN \token_to_str:N \l_xparse_function_tl + \int_eval:n { \l_xparse_total_args_int + 1 } + } + ##1 {##2} \exp_not:N \q_xparse + } + \xparse_exp_prepare_function:N + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\xparse_exp_check_and_add:N} +% Virtually identical to the normal version, except calling the +% expandable \texttt{add} functions rather than the standard versions. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \xparse_exp_check_and_add:N #1 + { + \cs_if_free:cTF { xparse_exp_add_type_ #1 :w } + { + \msg_error:nnx { xparse } { unknown-argument-type } + { \tl_to_str:n {#1} } + \tl_set:Nn \l_xparse_last_arg_tl { m } + \xparse_exp_add_type_m:w + } + { + \tl_set:Nn \l_xparse_last_arg_tl {#1} + \use:c { xparse_exp_add_type_ #1 :w } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\xparse_exp_declare_cmd:Nnn} +% \begin{macro}[aux]{\xparse_exp_declare_cmd_all_m:Nn} +% \begin{macro}[aux]{\xparse_exp_declare_cmd_mixed:Nn} +% \begin{macro}[aux]{\xparse_exp_declare_cmd_mixed_aux:Nn} +% The overall scheme here is very different from the standard method. +% For each argument, an internal function is created to grab an argument +% and pass along previous ones. Each `daisy chains' to call the next +% one in the sequence. Thus at the end of the chain, an extra `argument' +% function is included to unwind the chain and pass data to the the +% internal function containing the actual code. If all of the arguments +% are type \texttt{m}, then the same tick is used as in the standard +% version. The \texttt{x} in the lead-off and mop-up functions makes +% sure that the braces around the first argument are not lost. +% \begin{macrocode} +\cs_new_protected:Npn \xparse_exp_declare_cmd:Nnn #1#2#3 + { + \cs_if_exist:NTF #1 + { + \msg_warning:nnxx { xparse } { redefine-command } + { \token_to_str:N #1 } { \tl_to_str:n {#2} } + } + { + \msg_info:nnxx { xparse } { define-command } + { \token_to_str:N #1 } { \tl_to_str:n {#2} } + } + \group_begin: + \tex_escapechar:D 92 \scan_stop: + \tl_set:Nx \l_xparse_function_tl { \token_to_str:N #1} + \exp_args:NNNo \group_end: + \tl_set:Nn \l_xparse_function_tl { \l_xparse_function_tl } + \xparse_exp_prepare_function:n {#2} + \int_compare:nNnTF \l_xparse_total_args_int = \l_xparse_m_args_int + { \xparse_exp_declare_cmd_all_m:Nn #1 {#3} } + { \xparse_exp_declare_cmd_mixed:Nn #1 {#3} } + } +\cs_new_protected:Npn \xparse_exp_declare_cmd_all_m:Nn #1#2 + { + \bool_if:NTF \l_xparse_long_bool + { + \cs_generate_from_arg_count:NNnn + #1 \cs_set:Npn \l_xparse_total_args_int {#2} + } + { + \cs_generate_from_arg_count:NNnn + #1 \cs_set_nopar:Npn \l_xparse_total_args_int {#2} + } + } +\cs_new_protected:Npn \xparse_exp_declare_cmd_mixed:Nn #1#2 + { + \tl_if_in:noTF { l m u } \l_xparse_last_arg_tl + { \xparse_exp_declare_cmd_mixed_aux:Nn #1 {#2} } + { \msg_error:nn { xparse } { expandable-ending-optional } } + } +\cs_new_protected:Npn \xparse_exp_declare_cmd_mixed_aux:Nn #1#2 + { + \cs_set_nopar:Npx #1 + { \exp_not:c { \token_to_str:N #1 1 } x \exp_not:N \q_xparse } + \cs_set_nopar:cpx + { \token_to_str:N #1 \int_eval:n { \l_xparse_total_args_int + 1 } } + x ##1 \q_xparse + { \exp_not:c { \token_to_str:N #1 } ##1 } + \cs_generate_from_arg_count:cNnn + { \token_to_str:N #1 } \cs_set:Npn \l_xparse_total_args_int {#2} + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\xparse_exp_prepare_function:n} +% \begin{macro}[aux]{\xparse_exp_prepare_function_aux:n} +% A couple of early validation tests. Processors are forbidden, as are +% \texttt{g}, \texttt{l} and \texttt{u} arguments (the later more for +% ease than any technical reason). +% \begin{macrocode} +\cs_new_protected:Npn \xparse_exp_prepare_function:n #1 + { + \bool_set_false:N \l_xparse_error_bool + \tl_if_in:nnT {#1} { > } + { + \msg_error:nnx { xparse } { processor-in-expandable } + { \tl_to_str:n {#1} } + \bool_set_true:N \l_xparse_error_bool + } + \tl_if_in:nnT {#1} { g } + { + \msg_error:nnx { xparse } { grouped-in-expandable } + { g } { \tl_to_str:n {#1} } + \bool_set_true:N \l_xparse_error_bool + } + \tl_if_in:nnT {#1} { G } + { + \msg_error:nnx { xparse } { grouped-in-expandable } + { G } { \tl_to_str:n {#1} } + \bool_set_true:N \l_xparse_error_bool + } + \bool_if:NF \l_xparse_error_bool + { \xparse_exp_prepare_function_aux:n {#1} } + } +\cs_new_protected:Npn \xparse_exp_prepare_function_aux:n #1 + { + \cs_set_eq:NN \xparse_prepare_next:w \xparse_exp_prepare_function:N + \cs_set_eq:NN \xparse_exp_set:cpx \cs_set_nopar:cpx + \bool_set_false:N \l_xparse_long_bool + \int_zero:N \l_xparse_m_args_int + \int_zero:N \l_xparse_total_args_int + \tl_if_in:nnT {#1} { + } + { + \bool_set_true:N \l_xparse_long_bool + \cs_set_eq:NN \xparse_exp_set:cpx \cs_set:cpx + } + \xparse_exp_prepare_function:N #1 \q_nil + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\xparse_exp_prepare_function:N} +% \begin{macro}[aux]{\xparse_exp_prepare_function_long:N} +% \begin{macro}[aux]{\xparse_exp_prepare_function_short:N} +% Preparing functions is a case of reading the signature, as in the +% normal case. However, everything has to be either short or long, and +% so there is an extra step to make sure that once one \texttt{+} has +% been seen everything has one. That detour then takes us back to +% a standard looping concept. +% \begin{macrocode} +\cs_new_protected:Npn \xparse_exp_prepare_function:N #1 + { + \bool_if:NTF \l_xparse_long_bool + { \xparse_exp_prepare_function_long:N #1 } + { \xparse_exp_prepare_function_short:N #1 } +} +\cs_new_protected:Npn \xparse_exp_prepare_function_long:N #1 + { + \quark_if_nil:NF #1 + { + \str_if_eq:nnTF {#1} { + } + { \xparse_exp_prepare_function_short:N } + { + \msg_error:nn { xparse } { inconsistent-long } + \xparse_exp_prepare_function_short:N #1 + } + } + } +\cs_new_protected:Npn \xparse_exp_prepare_function_short:N #1 + { + \quark_if_nil:NF #1 + { + \prop_if_in:NnTF \c_xparse_shorthands_prop {#1} + { + \prop_get:NnN \c_xparse_shorthands_prop {#1} \l_xparse_tmp_tl + \bool_if:NT \l_xparse_long_bool + { \tl_put_left:Nn \l_xparse_tmp_tl { + } } + \exp_after:wN \xparse_exp_prepare_function:N \l_xparse_tmp_tl + } + { + \int_incr:N \l_xparse_total_args_int + \xparse_exp_check_and_add:N #1 + } + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\xparse_exp_set:cpx} +% A short-cut to save constantly re-testing \cs{l_xparse_long_bool}. +% \begin{macrocode} +\cs_new_eq:NN \xparse_exp_set:cpx \cs_set_nopar:cpx +% \end{macrocode} +% \end{macro} +% +% \subsection{Access to the argument specification} +% +% \begin{macro}{\xparse_get_arg_spec:N} +% \begin{macro}{\xparse_get_arg_spec:n} +% \begin{macro}{\ArgumentSpecification} +% Recovering the argument specification is also trivial, using the +% \cs{tl_set_eq:cN} function. +% \begin{macrocode} +\cs_new_protected:Npn \xparse_get_arg_spec:N #1 + { + \cs_if_exist:cTF { l_xparse_ \token_to_str:N #1 _arg_spec_tl } + { + \tl_set_eq:Nc \ArgumentSpecification + { l_xparse_ \token_to_str:N #1 _arg_spec_tl } + } + { + \msg_error:nnx { xparse } { unknown-document-command } + { \token_to_str:N #1 } + } + } +\cs_new_protected:Npn \xparse_get_arg_spec:n #1 + { + \cs_if_exist:cTF { l_xparse_ #1 _arg_spec_tl } + { \tl_set_eq:Nc \ArgumentSpecification { l_xparse_ #1 _arg_spec_tl } } + { + \msg_error:nnx { xparse } { unknown-document-environment } + { \tl_to_str:n {#1} } + } + } +\tl_new:N \ArgumentSpecification +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\xparse_show_arg_spec:N} +% \begin{macro}{\xparse_show_arg_spec:n} +% Showing the argument specification simply means finding it and then +% calling the \cs{tl_show:c} function. +% \begin{macrocode} +\cs_new_protected:Npn \xparse_show_arg_spec:N #1 + { + \cs_if_exist:cTF { l_xparse_ \token_to_str:N #1 _arg_spec_tl } + { + \tl_set_eq:Nc \ArgumentSpecification + { l_xparse_ \token_to_str:N #1 _arg_spec_tl } + \tl_show:N \ArgumentSpecification + } + { + \msg_error:nnx { xparse } { unknown-document-command } + { \token_to_str:N #1 } + } + } +\cs_new_protected:Npn \xparse_show_arg_spec:n #1 + { + \cs_if_exist:cTF { l_xparse_ #1 _arg_spec_tl } + { + \tl_set_eq:Nc \ArgumentSpecification { l_xparse_ #1 _arg_spec_tl } + \tl_show:N \ArgumentSpecification + } + { + \msg_error:nnx { xparse } { unknown-document-environment } + { \tl_to_str:n {#1} } + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +%\subsection{Messages} +% +% Some messages intended as errors. +% \begin{macrocode} +\msg_new:nnnn { xparse } { command-already-defined } + { Command~'#1'~already~defined! } + { + You~have~used~\NewDocumentCommand + with~a~command~that~already~has~a~definition. \\ + The~existing~definition~of~'#1'~will~be~overwritten. + } +\msg_new:nnnn { xparse } { command-not-yet-defined } + { Command ~'#1'~not~yet~defined! } + { + You~have~used~\RenewDocumentCommand + with~a~command~that~was~never~defined.\\ + A~new~command~'#1'~will~be~created. + } +\msg_new:nnnn { xparse } { environment-already-defined } + { Environment~'#1'~already~defined! } + { + You~have~used~\NewDocumentEnvironment + with~an~environment~that~already~has~a~definition.\\ + The~existing~definition~of~'#1'~will~be~overwritten. + } +\msg_new:nnnn { xparse } { environment-mismatch } + { Mismatch~between~start~and~end~of~environment. } + { + The~current~environment~is~called~'#1',~but~you~have~tried~to~ + end~one~called~'#2'.~Environments~have~to~be~properly~nested. + } +\msg_new:nnnn { xparse } { environment-not-yet-defined } + { Environment~'#1'~not~yet~defined! } + { + You~have~used~\RenewDocumentEnvironment + with~an~environment~that~was~never~defined.\\ + A~new~environment~'#1'~will~be~created. + } +\msg_new:nnnn { xparse } { environment-unknown } + { Environment~'#1'~undefined. } + { + You~have~tried~to~start~an~environment~called~'#1',~ + but~this~has~never~been~defined.\\ + The~command~will~be~ignored. + } +\msg_new:nnnn { xparse } { expandable-ending-optional } + { Signature~for~expandable~command~ends~with~optional~argument. } + { + \c_msg_coding_error_text_tl + Expandable~commands~must~have~a~final~mandatory~argument~ + (or~no~arguments~at~all).~You~cannot~have~a~terminal~optional~ + argument~with~expandable~commands. + } +\msg_new:nnnn { xparse } { grouped-in-expandable } + { Argument~specifier~'#1'~forbidden~in~expandable~commands. } + { + \c_msg_coding_error_text_tl + Argument~specification~'#2'~contains~the~optional~grouped~ + argument~'#1':~ + this~is only~supported~for~standard~robust~functions. + } +\msg_new:nnnn { xparse } { inconsistent-long } + { Inconsistent~long~arguments~for~expandable~command. } + { + \c_msg_coding_error_text_tl + The~arguments~for~an~expandable~command~must~either~all~be~ + short~or~all~be~long.~You~have~tried~to~mix~the~two~types. + } +\msg_new:nnnn { xparse } { processor-in-expandable } + { Argument~processors~cannot~be~used~with~expandable~functions. } + { + \c_msg_coding_error_text_tl + Argument~specification~'#1'~contains~a~processor~function:~ + this~is~only~supported~for~standard~robust~functions. + } +\msg_new:nnnn { xparse } { split-excess-tokens } + { Too~many~'#1'~tokens~when~trying~to~split~argument. } + { + LaTeX~was~asked~to~split~the~input~'#3'~ + at~each~occurrence~of~the~token~'#1',~up~to~a~maximum~of~#2~parts.~ + There~were~too~many~'#1'~tokens. + } +\msg_new:nnnn { xparse } { unknown-argument-type } + { Unknown~argument~type~'#1'~replaced~by~'m'. } + { + \c_msg_coding_error_text_tl + The~letter~'#1'~does~not~specify~a~known~argument~type.~ + LaTeX~will~assume~you~want~a~standard~mandatory~argument~(type~'m'). + } +\msg_new:nnnn { xparse } { unknown-document-command } + { Unknown~document~command~'#1'. } + { + You~have~asked~for~the~argument~specification~for~a~command~'#1',~ + but~this~is~not~a~document~command. + } +\msg_new:nnnn { xparse } { unknown-document-environment } + { Unknown~document~environment~'#1'. } + { + You~have~asked~for~the~argument~specification~for~a~command~'#1',~ + but~this~is~not~a~document~environment. + } +% \end{macrocode} +% +% Intended more for information. +% \begin{macrocode} +\msg_new:nnn { xparse } { define-command } + { + Defining~document~command~#1~ + with~arg.~spec.~'#2'~\msg_line_context:. + } +\msg_new:nnn { xparse } { define-environment } + { + Defining~document~environment~'#1'~ + with~arg.~spec.~'#2'~\msg_line_context:. + } +\msg_new:nnn { xparse } { redefine-command } + { + Redefining~document~command~#1~ + with~arg.~spec.~'#2'~\msg_line_context:. + } +\msg_new:nnn { xparse } { redefine-environment } + { + Redefining~document~environment~'#1'~ + with~arg.~spec.~'#2'~\msg_line_context:. + } +% \end{macrocode} +% +% \subsection{User functions} +% +% The user functions are more or less just the internal functions +% renamed. +% +% \begin{macro}{\BooleanFalse} +% \begin{macro}{\BooleanTrue} +% Design-space names for the Boolean values. +% \begin{macrocode} +\cs_new_eq:NN \BooleanFalse \c_false_bool +\cs_new_eq:NN \BooleanTrue \c_true_bool +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\DeclareDocumentCommand} +% \begin{macro}{\NewDocumentCommand} +% \begin{macro}{\RenewDocumentCommand} +% \begin{macro}{\ProvideDocumentCommand} +% The user macros are pretty simple wrappers around the internal ones. +% \begin{macrocode} +\cs_new_protected:Npn \DeclareDocumentCommand #1#2#3 + { \xparse_declare_cmd:Nnn #1 {#2} {#3} } +\cs_new_protected:Npn \NewDocumentCommand #1#2#3 + { + \cs_if_exist:NTF #1 + { + \msg_error:nnx { xparse } { command-already-defined } + { \token_to_str:N #1 } + } + { \xparse_declare_cmd:Nnn #1 {#2} {#3} } + } +\cs_new_protected:Npn \RenewDocumentCommand #1#2#3 + { + \cs_if_exist:NTF #1 + { \xparse_declare_cmd_aux:Nnn #1 {#2} {#3} } + { + \msg_error:nnx { xparse } { command-not-yet-defined } + { \token_to_str:N #1 } + } + } +\cs_new_protected:Npn \ProvideDocumentCommand #1#2#3 + { \cs_if_exist:NF #1 { \xparse_declare_cmd:Nnn #1 {#2} {#3} } } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\DeclareDocumentCommandImplementation} +% \begin{macro}{\DeclareDocumentCommandInterface} +% The separate implementation/interface system is again pretty simple +% to create at the outer layer. +% \begin{macrocode} +\cs_new_protected:Npn \DeclareDocumentCommandImplementation #1#2#3 + { \xparse_declare_cmd_implementation:nNn {#1} #2 {#3} } +\cs_new_protected:Npn \DeclareDocumentCommandInterface #1#2#3 + { \xparse_declare_cmd_interface:Nnn #1 {#2} {#3} } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\DeclareDocumentEnvironment} +% \begin{macro}{\NewDocumentEnvironment} +% \begin{macro}{\RenewDocumentEnvironment} +% \begin{macro}{\ProvideDocumentEnvironment} +% Very similar for environments. +% \begin{macrocode} +\cs_new_protected:Npn \DeclareDocumentEnvironment #1#2#3#4 + { \xparse_declare_env:nnnn {#1} {#2} {#3} {#4} } +\cs_new_protected:Npn \NewDocumentEnvironment #1#2#3#4 + { + \cs_if_exist:cTF {#1} + { \msg_error:nnx { xparse } { environment-already-defined } {#1} } + { \xparse_declare_env:nnnn {#1} {#2} {#3} {#4} } +} +\cs_new_protected:Npn \RenewDocumentEnvironment #1#2#3#4 + { + \cs_if_exist:cTF {#1} + { \xparse_declare_env:nnnn {#1} {#2} {#3} {#4} } + { \msg_error:nnx { xparse } { environment-not-yet-defined } {#1} } + } +\cs_new_protected:Npn \ProvideDocumentEnvironment #1#2#3#4 + { \cs_if_exist:cF { #1 } { \xparse_declare_env:nnnn {#1} {#2} {#3} {#4} } } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\DeclareExpandableDocumentCommand} +% The expandable version of the basic function is essentially the same. +% \begin{macrocode} +\cs_new_protected:Npn \DeclareExpandableDocumentCommand #1#2#3 + { \xparse_exp_declare_cmd:Nnn #1 {#2} {#3} } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[TF]{\IfBoolean} +% The logical \meta{true} and \meta{false} statements are just the +% normal \cs{c_true_bool} and \cs{c_false_bool}, so testing for them is +% done with the \cs{bool_if:NTF} functions from \textsf{l3prg}. +% \begin{macrocode} +\cs_new_eq:NN \IfBooleanTF \bool_if:NTF +\cs_new_eq:NN \IfBooleanT \bool_if:NT +\cs_new_eq:NN \IfBooleanF \bool_if:NF +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[TF]{\IfNoValue} +% Simple re-naming. +% \begin{macrocode} +\cs_new_eq:NN \IfNoValueF \xparse_if_no_value:nF +\cs_new_eq:NN \IfNoValueT \xparse_if_no_value:nT +\cs_new_eq:NN \IfNoValueTF \xparse_if_no_value:nTF +% \end{macrocode} +% \end{macro} +% \begin{macro}[TF]{\IfValue} +% Inverted logic. +% \begin{macrocode} +\cs_set:Npn \IfValueF { \xparse_if_no_value:nT } +\cs_set:Npn \IfValueT { \xparse_if_no_value:nF } +\cs_set:Npn \IfValueTF #1#2#3 { \xparse_if_no_value:nTF {#1} {#3} {#2} } +% \end{macrocode} +% \end{macro} +% +% \begin{variable}{\NoValue} +% The marker for no value being give: this can be typeset safely. +% This is coded by hand as making it \cs{protected} ensures that it +% will not turn into anything else by accident. +% \begin{macrocode} +\cs_new_protected:Npn \NoValue { -NoValue- } +% \end{macrocode} +%\end{variable} +% +% \begin{macro}{\ProcessedArgument} +% Processed arguments are returned using this name, which is reserved +% here although the definition will change. +% \begin{macrocode} +\tl_new:N \ProcessedArgument +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\ReverseBoolean} +% A processor to reverse the logic for token detection. +% \begin{macrocode} +\cs_new_eq:NN \ReverseBoolean \xparse_bool_reverse:N +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SplitArgument} +% \begin{macro}{\SplitList} +% Another simple copy. +% \begin{macrocode} +\cs_new_eq:NN \SplitArgument \xparse_split_argument:nnn +\cs_new_eq:NN \SplitList \xparse_split_list:nn +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\GetDocumentCommandArgSpec} +% \begin{macro}{\GetDocumentEnvironmentArgSpec} +% \begin{macro}{\ShowDocumentCommandArgSpec} +% \begin{macro}{\ShowDocumentEnvironmentArgSpec} +% More simple mappings. +% \begin{macrocode} +\cs_new_eq:NN \GetDocumentCommandArgSpec \xparse_get_arg_spec:N +\cs_new_eq:NN \GetDocumentEnvironmmentArgSpec \xparse_get_arg_spec:n +\cs_new_eq:NN \ShowDocumentCommandArgSpec \xparse_show_arg_spec:N +\cs_new_eq:NN \ShowDocumentEnvironmentArgSpec \xparse_show_arg_spec:n +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{Package options} +% +% A faked key--value option to keep the log clean. Not yet perfect, but +% better than nothing. +% \begin{macrocode} +\DeclareOption { log-declarations = true } { } +\DeclareOption { log-declarations = false } + { + \msg_redirect_module:nnn { xparse } { info } { none } + \msg_redirect_module:nnn { xparse } { warning } { none } + } +\DeclareOption { log-declarations } { } +\ProcessOptions \scan_stop: +% \end{macrocode} +% +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex diff --git a/Master/texmf-dist/source/latex/l3packages/xparse/xparse.ins b/Master/texmf-dist/source/latex/l3packages/xparse/xparse.ins new file mode 100644 index 00000000000..995ddbb8ff0 --- /dev/null +++ b/Master/texmf-dist/source/latex/l3packages/xparse/xparse.ins @@ -0,0 +1,40 @@ +\iffalse meta-comment + +File xparse.ins Copyright (C) 2000-2011 The 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 "l3packages 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. + +\fi + +\input docstrip.tex +\askforoverwritefalse + +\preamble + +EXPERIMENTAL CODE + +Do not distribute this file without also distributing the +source files specified above. + +Do not distribute a modified version of this file. + +\endpreamble +% stop docstrip adding \endinput +\postamble +\endpostamble + +\keepsilent + +\generate{\file{xparse.sty} {\from{xparse.dtx} {package}}} + +\endbatchfile |