summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2009-11-26 19:24:51 +0000
committerKarl Berry <karl@freefriends.org>2009-11-26 19:24:51 +0000
commit7749142c6b66c1dc668af8960889578eb9a08e0a (patch)
tree7c72d5f4899829f6bb46d603ae6f1b7fa05213e4
parent5273fcd7dff0684b0cce66c6baa4b32589909357 (diff)
xpackages 1750 (25nov09)
git-svn-id: svn://tug.org/texlive/trunk@16178 c570f23f-e606-0410-a88d-b1316a301751
-rw-r--r--Master/texmf-dist/doc/latex/xpackages/README59
-rw-r--r--Master/texmf-dist/doc/latex/xpackages/xbase/ldcsetup.pdfbin207075 -> 355486 bytes
-rw-r--r--Master/texmf-dist/doc/latex/xpackages/xbase/template.pdfbin361353 -> 542520 bytes
-rw-r--r--Master/texmf-dist/doc/latex/xpackages/xbase/xparse.pdfbin764909 -> 805759 bytes
-rw-r--r--Master/texmf-dist/doc/latex/xpackages/xbase/xtemplate.pdfbin0 -> 927934 bytes
-rw-r--r--Master/texmf-dist/doc/latex/xpackages/xtras/l3keys2e.pdfbin419801 -> 427597 bytes
-rw-r--r--Master/texmf-dist/source/latex/xpackages/xbase/ldcsetup.dtx6
-rw-r--r--Master/texmf-dist/source/latex/xpackages/xbase/template-test.tex4
-rw-r--r--Master/texmf-dist/source/latex/xpackages/xbase/template.dtx16
-rw-r--r--Master/texmf-dist/source/latex/xpackages/xbase/tprestrict-test.tex4
-rw-r--r--Master/texmf-dist/source/latex/xpackages/xbase/xbase.ins9
-rw-r--r--Master/texmf-dist/source/latex/xpackages/xbase/xparse-test.tex4
-rw-r--r--Master/texmf-dist/source/latex/xpackages/xbase/xparse.dtx625
-rw-r--r--Master/texmf-dist/source/latex/xpackages/xbase/xtemplate.dtx3390
-rw-r--r--Master/texmf-dist/source/latex/xpackages/xtras/l3keys2e.dtx12
-rw-r--r--Master/texmf-dist/tex/latex/xpackages/xbase/ldcsetup.sty4
-rw-r--r--Master/texmf-dist/tex/latex/xpackages/xbase/template.sty14
-rw-r--r--Master/texmf-dist/tex/latex/xpackages/xbase/xparse.sty396
-rw-r--r--Master/texmf-dist/tex/latex/xpackages/xbase/xtemplate.sty1251
-rw-r--r--Master/texmf-dist/tex/latex/xpackages/xtras/l3keys2e.sty12
20 files changed, 5429 insertions, 377 deletions
diff --git a/Master/texmf-dist/doc/latex/xpackages/README b/Master/texmf-dist/doc/latex/xpackages/README
index ccef2cc6007..571316db1dd 100644
--- a/Master/texmf-dist/doc/latex/xpackages/README
+++ b/Master/texmf-dist/doc/latex/xpackages/README
@@ -1,9 +1,8 @@
- Experimental Packages Demonstrating
- Possible LaTeX3 High-Level Concepts
- ====================================
+ Experimental LaTeX3 High-Level Concepts
+ =======================================
- 2009/06/09
+ 2009/11/25
WHERE TO GET IT
@@ -19,12 +18,13 @@ instructions.
OVERVIEW
--------
-The `xpackages' term is a designation used for proto-type
-implementations of new concepts for a LaTeX Designer Interface. Some
-work as standalone packages providing new functionality, such as the
-packages in xbase; others go deeper and redefine LaTeX internals in
-order to provide newer and better methods for managing certain
-constructs.
+The xpackages are a collection of experimental implementations
+for aspects of the LaTeX3 kernel, dealing with higher-level
+ideas such as the Desginer Interface. Some of them work as stand
+alone packages, providing new functionality, and can be used
+on top of LaTeX2e with no changes to the existing kernel.
+Others go further, and redefine LaTeX2e internals to provide
+better methods for managing certain constructs.
All xpackages require expl3 and, in addition to this, many require
functionality provided by the packages within the xbase bundle.
@@ -32,30 +32,44 @@ functionality provided by the packages within the xbase bundle.
Currently included in the CTAN release of xpackages are the following
bundles:
xbase
+ xtras
xbase
-----
-The xbase bundle provides the packages xparse and template, and the
-support package ldcsetup.
+The xbase bundle provides mechansims for defining document commands
+(xparse) and design constructions (xtemplate).
The xparse package provides a high-level interface for declaring
document commands, e.g., a uniform way to define commands taking
optional arguments, optional stars (and others), mandatory arguments
and more.
-The template package provides an interface for defining generic
-functions using a key=val syntax.
+The xtemplate package provides an interface for defining generic
+functions using a key=val syntax. This is designed to be
+"self-documenting", with the key definitions providing information
+on how they are to be used.
-The ldcsetup package used to establish prototype LaTeX3 coding conventions,
-needed by xparse and xbase, but is now slowly being stripped in favor
-of functionality added to expl3.
+The legacy template and ldcsetup packages are included at the
+present time, but new LaTeX3 code will not use these!
-Files included:
- source: xbase.ins, xparse.dtx, template.dtx, ldcsetup.dtx
- test: template-test.tex, template-test2.tex, tprestrict-test.tex,
- xparse-test.tex
+Source files:
+ - xbase.ins
+ - xparse.dtx
+ - xtemplate.dtx
+xtras
+-----
+
+The xtras bundle provides functionality to bridge between LaTeX2e
+and LaTeX3. It provides add-ons to LaTeX2e to allow other xpackages
+to be used in the LaTeX2e context.
+
+The l3keys2e package allows keys defined using l3keys to be used
+as package and class options with LaTeX2e. This is tied to the
+method the existing kernel uses for processing options, and so it
+is likely that a stand-alone LaTeX3 kernel will use a very different
+approach.
DISCUSSION
@@ -83,9 +97,6 @@ LaTeX kernel". However please do *not* use this method for
suggestions / comments / improvements / etc. For this the list LATEX-L
should be used instead.
-Also please don't expect these package to work with *any* code that
-floats around in the LaTeX2e world. :-)
-
--- Copyright 1998 -- 2009
The LaTeX3 Project. All rights reserved ---
diff --git a/Master/texmf-dist/doc/latex/xpackages/xbase/ldcsetup.pdf b/Master/texmf-dist/doc/latex/xpackages/xbase/ldcsetup.pdf
index 07615093cbe..8419fc46f85 100644
--- a/Master/texmf-dist/doc/latex/xpackages/xbase/ldcsetup.pdf
+++ b/Master/texmf-dist/doc/latex/xpackages/xbase/ldcsetup.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/xpackages/xbase/template.pdf b/Master/texmf-dist/doc/latex/xpackages/xbase/template.pdf
index 4d67cb17a13..4c1585d2b95 100644
--- a/Master/texmf-dist/doc/latex/xpackages/xbase/template.pdf
+++ b/Master/texmf-dist/doc/latex/xpackages/xbase/template.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/xpackages/xbase/xparse.pdf b/Master/texmf-dist/doc/latex/xpackages/xbase/xparse.pdf
index 8dd55866da1..e160164393e 100644
--- a/Master/texmf-dist/doc/latex/xpackages/xbase/xparse.pdf
+++ b/Master/texmf-dist/doc/latex/xpackages/xbase/xparse.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/xpackages/xbase/xtemplate.pdf b/Master/texmf-dist/doc/latex/xpackages/xbase/xtemplate.pdf
new file mode 100644
index 00000000000..559fe9e22c0
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/xpackages/xbase/xtemplate.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/xpackages/xtras/l3keys2e.pdf b/Master/texmf-dist/doc/latex/xpackages/xtras/l3keys2e.pdf
index 75583163f48..2faa703aa9d 100644
--- a/Master/texmf-dist/doc/latex/xpackages/xtras/l3keys2e.pdf
+++ b/Master/texmf-dist/doc/latex/xpackages/xtras/l3keys2e.pdf
Binary files differ
diff --git a/Master/texmf-dist/source/latex/xpackages/xbase/ldcsetup.dtx b/Master/texmf-dist/source/latex/xpackages/xbase/ldcsetup.dtx
index 09e37c55cb3..b47930bc217 100644
--- a/Master/texmf-dist/source/latex/xpackages/xbase/ldcsetup.dtx
+++ b/Master/texmf-dist/source/latex/xpackages/xbase/ldcsetup.dtx
@@ -18,7 +18,7 @@
%%
%% The development version of the bundle can be found at
%%
-%% http://www.latex-project.org/cgi-bin/cvsweb.cgi/
+%% http://www.latex-project.org/svnroot/experimental/trunk/
%%
%% for those people who are interested.
%%
@@ -37,7 +37,7 @@
\RequirePackage{expl3}
%</driver|package>
%\fi
-\GetIdInfo$Id: ldcsetup.dtx 1295 2009-05-06 08:32:25Z will $
+\GetIdInfo$Id: ldcsetup.dtx 1628 2009-10-25 09:54:34Z mittelba $
{coding conventions and stuff}
%\iffalse
%<*driver>
@@ -45,7 +45,7 @@
\ProvidesFile{\filename.\filenameext}
[\filedate\space v\fileversion\space\filedescription]
%\iffalse
-\documentclass{ltxdoc}
+\documentclass{l3doc}
\begin{document}
\DocInput{ldcsetup.dtx}
\end{document}
diff --git a/Master/texmf-dist/source/latex/xpackages/xbase/template-test.tex b/Master/texmf-dist/source/latex/xpackages/xbase/template-test.tex
index f8c47c82d59..5684ce7a90f 100644
--- a/Master/texmf-dist/source/latex/xpackages/xbase/template-test.tex
+++ b/Master/texmf-dist/source/latex/xpackages/xbase/template-test.tex
@@ -17,7 +17,7 @@
%%
%% The development version of the bundle can be found at
%%
-%% http://www.latex-project.org/cgi-bin/cvsweb.cgi/
+%% http://www.latex-project.org/svnroot/experimental/trunk/
%%
%% for those people who are interested.
%%
@@ -32,7 +32,7 @@
%%
%% -----------------------------------------------------------------------
%%
-%% $Id: template-test.tex 251 2004-11-11 19:01:16Z mittelba $
+%% $Id: template-test.tex 1628 2009-10-25 09:54:34Z mittelba $
%%
% \fi
%
diff --git a/Master/texmf-dist/source/latex/xpackages/xbase/template.dtx b/Master/texmf-dist/source/latex/xpackages/xbase/template.dtx
index 8b38f6d216c..376b4929933 100644
--- a/Master/texmf-dist/source/latex/xpackages/xbase/template.dtx
+++ b/Master/texmf-dist/source/latex/xpackages/xbase/template.dtx
@@ -18,7 +18,7 @@
%%
%% The development version of the bundle can be found at
%%
-%% http://www.latex-project.org/cgi-bin/cvsweb.cgi/
+%% http://www.latex-project.org/svnroot/experimental/trunk/
%%
%% for those people who are interested.
%%
@@ -37,7 +37,7 @@
\RequirePackage{expl3}
%</driver|package>
%\fi
-\GetIdInfo$Id: template.dtx 1461 2009-08-15 08:38:12Z joseph $
+\GetIdInfo$Id: template.dtx 1670 2009-11-01 22:34:54Z will $
{template}
%\iffalse
%<*driver>
@@ -45,7 +45,7 @@
\ProvidesFile{\filename.\filenameext}
[\filedate\space v\fileversion\space\filedescription]
%\iffalse
-\documentclass{ltxdoc}
+\documentclass{l3doc}
\makeatletter
\newenvironment{decl}[1][]%
{\par\small\addvspace{4.5ex plus 1ex}%
@@ -1149,7 +1149,7 @@
% |#2| template type/template name\\
% |#3| key value assignments for parameters of |#2|
% \begin{macrocode}
-\cs_new_nopar:Nn \TP_declare_instance:Nnn {
+\cs_new_nopar:Npn \TP_declare_instance:Nnn #1#2#3 {
\group_begin:
\TP_instdecl_generate_assignments:nn {#2}{#3}
\cs_gset_nopar:Npx #1 {
@@ -1262,7 +1262,7 @@
% |{type}| returns prefix for csnames for template type,
% based on current collection.
% \begin{macrocode}
-\cs_new_nopar:Nn \TP_get_csname_prefix:n {
+\cs_new_nopar:Npn \TP_get_csname_prefix:n #1 {
<\exp_after:wN\exp_after:wN\exp_after:wN
\use_i:nn
\cs:w TP@<#1>\cs_end:>#1/
@@ -1274,7 +1274,7 @@
% \begin{macro}{\TP_get_arg_count:n}
% |{type}| returns arg count for the template type.
% \begin{macrocode}
-\cs_new_nopar:Nn \TP_get_arg_count:n {
+\cs_new_nopar:Npn \TP_get_arg_count:n #1 {
\exp_after:wN\exp_after:wN\exp_after:wN
\use_ii:nn
\cs:w TP@<#1>\cs_end:
@@ -1357,7 +1357,7 @@
% to look at the first token of the value, to see what sort of key
% it is, so call a helper function to split that off.
% \begin{macrocode}
-\cs_new_nopar:Nn \TP_templdecl_process_KV:nn {%
+\cs_new_nopar:Npn \TP_templdecl_process_KV:nn #1#2 {%
\cs_set_eq:NN \TP_templdecl_add_global_or_nothing: \prg_do_nothing:
\bool_set_false:N\l_TP_global_assignment_bool
\tl_set:Nn\l_TP_currkey_tl{#1}
@@ -1370,7 +1370,7 @@
% \begin{macro}{\TP_templdecl_parse_KV:N}
% Case switch on the possible key types.
% \begin{macrocode}
-\cs_new_nopar:Nn \TP_templdecl_parse_KV:N {
+\cs_new_nopar:Npn \TP_templdecl_parse_KV:N #1 {
% \end{macrocode}
% In |#1| we have key, in |#2| the first character after the equal
% sign and in |#3| the remainder of the line. We now have to parse
diff --git a/Master/texmf-dist/source/latex/xpackages/xbase/tprestrict-test.tex b/Master/texmf-dist/source/latex/xpackages/xbase/tprestrict-test.tex
index a787694abff..d981888d450 100644
--- a/Master/texmf-dist/source/latex/xpackages/xbase/tprestrict-test.tex
+++ b/Master/texmf-dist/source/latex/xpackages/xbase/tprestrict-test.tex
@@ -17,7 +17,7 @@
%%
%% The development version of the bundle can be found at
%%
-%% http://www.latex-project.org/cgi-bin/cvsweb.cgi/
+%% http://www.latex-project.org/svnroot/experimental/trunk/
%%
%% for those people who are interested.
%%
@@ -32,7 +32,7 @@
%%
%% -----------------------------------------------------------------------
%%
-%% $Id: tprestrict-test.tex 251 2004-11-11 19:01:16Z mittelba $
+%% $Id: tprestrict-test.tex 1628 2009-10-25 09:54:34Z mittelba $
%%
% \fi
%
diff --git a/Master/texmf-dist/source/latex/xpackages/xbase/xbase.ins b/Master/texmf-dist/source/latex/xpackages/xbase/xbase.ins
index 742a1aa8dc3..aef2755ba99 100644
--- a/Master/texmf-dist/source/latex/xpackages/xbase/xbase.ins
+++ b/Master/texmf-dist/source/latex/xpackages/xbase/xbase.ins
@@ -4,10 +4,10 @@
%% driver files from the dtx files in this package when run through
%% LaTeX or TeX.
%%
-%% (C) Copyright 2000-2005 LaTeX3 Project
+%% (C) Copyright 2000-2009 LaTeX3 Project
%%
%% It may be distributed and/or modified under the conditions of the
-%% LaTeX Project Public License (LPPL), either version 1.3a of this
+%% 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
%%
@@ -22,7 +22,7 @@
%%
%% The development version of the bundle can be found at
%%
-%% http://www.latex-project.org/cgi-bin/cvsweb.cgi/
+%% http://www.latex-project.org/svnroot/experimental/trunk/
%%
%% for those people who are interested.
%%
@@ -37,7 +37,7 @@
%%
%% -----------------------------------------------------------------------
%%
-%% $Id: xbase.ins 302 2005-03-01 22:49:14Z morten $
+%% $Id: xbase.ins 1650 2009-10-30 22:34:24Z joseph $
%%
% \fi
%
@@ -67,6 +67,7 @@ You may however distribute the bundle without such generated files.
\generate{%
\file{ldcsetup.sty}{\from{ldcsetup.dtx}{package}}
\file{template.sty}{\from{template.dtx}{package,trace}}
+ \file{xtemplate.sty}{\from{xtemplate.dtx}{package}}
\file{xparse.sty}{\from{xparse.dtx}{package}}
}
diff --git a/Master/texmf-dist/source/latex/xpackages/xbase/xparse-test.tex b/Master/texmf-dist/source/latex/xpackages/xbase/xparse-test.tex
index 9e681adf520..8614c4ed06a 100644
--- a/Master/texmf-dist/source/latex/xpackages/xbase/xparse-test.tex
+++ b/Master/texmf-dist/source/latex/xpackages/xbase/xparse-test.tex
@@ -17,7 +17,7 @@
%%
%% The development version of the bundle can be found at
%%
-%% http://www.latex-project.org/cgi-bin/cvsweb.cgi/
+%% http://www.latex-project.org/svnroot/experimental/trunk/
%%
%% for those people who are interested.
%%
@@ -32,7 +32,7 @@
%%
%% -----------------------------------------------------------------------
%%
-%% $Id: xparse-test.tex 1487 2009-08-22 15:55:24Z joseph $
+%% $Id: xparse-test.tex 1628 2009-10-25 09:54:34Z mittelba $
%%
% \fi
%
diff --git a/Master/texmf-dist/source/latex/xpackages/xbase/xparse.dtx b/Master/texmf-dist/source/latex/xpackages/xbase/xparse.dtx
index c227c4612f3..49f83b1efbf 100644
--- a/Master/texmf-dist/source/latex/xpackages/xbase/xparse.dtx
+++ b/Master/texmf-dist/source/latex/xpackages/xbase/xparse.dtx
@@ -41,7 +41,7 @@
\RequirePackage{l3names}
%</driver|package>
%\fi
-\GetIdInfo$Id: xparse.dtx 1497 2009-08-31 19:17:53Z joseph $
+\GetIdInfo$Id: xparse.dtx 1727 2009-11-06 22:58:32Z joseph $
{Generic document command parser}
%\iffalse
%<*driver>
@@ -89,7 +89,7 @@
% \item \cs{RenewDocumentEnvironment}
% \item \cs{ProvideDocumentEnvironment}
% \item \cs{IfNoValue(TF)} (the need for \cs{IfValue(TF)} is currently
-% an item of active discussion)
+% an item of active discussion)x
% \item \cs{IfBoolean(TF)}
%\end{itemize}
% with the other functions currently regarded as `experimental'. Please
@@ -99,14 +99,14 @@
%\subsection{Specifying arguments}
%
% Before introducing the functions used to create document commands,
-% the method for specifiying arguments with \pkg{xparse} will be
+% 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 thorugh to internal functions.
+% 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,
@@ -141,7 +141,7 @@
% \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
-% shortcuts to an appropriated-constructed \texttt{D} type argument.
+% 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).
@@ -149,7 +149,10 @@
% \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 |}|).
+% 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
@@ -305,9 +308,9 @@
% will use a different internal function if the optional argument
% is given than if it is not present.
%
-% As the \cs{IfNoValue} tests are expandable, it is possible to test
-% these values later, for example at the point of typesetting or in
-% an expansion context.
+% 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}{\IfValue / (TF) (EXP)}
@@ -316,7 +319,7 @@
% \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 senario.
+% form makes the most sense for a given code scenario.
%\end{function}
%
%\begin{variable}{
@@ -368,15 +371,20 @@
% followed by \cs{ProcessorB} to the tokens grabbed by the \texttt{m}
% argument.
%
-%\begin{variable}{\l_xparse_arg_toks}
+%\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 in the
-% variable \cs{l_xparse_arg_toks}. This will always be empty when the
-% processor function is called by \pkg{xparse}, even if more than one
-% argument processor is applied.
+% Processor functions should return the processed argument as the
+% variable \cs{ProcessedArgument}. This is initialised as a toks before
+% each processor is called, but may also be set equal to any other
+% variable type:
+% \begin{verbatim}
+% \toks_set:Nn \ProcessedArgument { <content> }
+% \toks_set:NV \ProcessedArgument \LocalVariable
+% \cs_set_eq:NN \ProcessedArgument \LocalVariable
+% \end{verbatim}
%\end{variable}
%
%\begin{function}{\xparse_process_to_str:n}
@@ -430,7 +438,7 @@
%\subsection{Separating interface and implementation}
%
% One \emph{experimental} idea implemented in \pkg{xparse} is to
-% separate out document command intefaces (the argument specification)
+% 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}
@@ -438,10 +446,10 @@
%\begin{function}{\DeclareDocumentCommandInterface}
% \begin{syntax}
% "\DeclareDocumentCommandInterface" <function>
-% ~~~~\Arg{implementation} \Arg{arg.~spec}
+% ~~~~\Arg{implementation} \Arg{arg spec}
% \end{syntax}
% This declares a <function>, which will take arguments as detailed
-% in the <arg.~spec>. When executed, the <function> will look for
+% in the <arg spec>. When executed, the <function> will look for
% code stored as an <implementation>.
%\end{function}
%
@@ -493,7 +501,7 @@
% \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
-% interpretted as the start of an optional argument. As a result
+% 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}
@@ -510,6 +518,12 @@
% and not be be altered later!
%\end{variable}
%
+%\begin{variable}{\l_xparse_arg_toks}
+% Token register used as internal representation of
+% \cs{ProcessedArgument}. Unlike the later, this register should not
+% be used directly when creating new processors.
+%\end{variable}
+%
%\begin{variable}{\l_xparse_args_toks}
% Token register for arguments as they are picked up for passing on to
% user functions.
@@ -520,6 +534,12 @@
% the beginning.
%\end{variable}
%
+%\begin{variable}{\l_xparse_environment_bool}
+% When creating functions, a short cut can be taken if all of the
+% arguments are of \texttt{m} type. The code for environments cannot
+% do that, and so a flag is needed.
+%\end{variable}
+%
%\begin{variable}{\l_xparse_error_bool}
% For flagging up errors when making expandable commands.
%\end{variable}
@@ -548,7 +568,7 @@
%
%\begin{variable}{\l_xparse_m_only_bool}
% Flag used to indicate that all arguments are of type \texttt{m},
-% with no no modificiations.
+% with no no modifications.
%\end{variable}
%
%\begin{variable}{\l_xparse_mandatory_args_int}
@@ -558,6 +578,15 @@
% be zero for any trailing optional arguments.
%\end{variable}
%
+%\begin{variable}{
+% \l_xparse_nested_int |
+% \l_xparse_nested_toks
+%}
+% Nested optional (delimited) arguments have to be handled by hand:
+% \TeX\ will not count up the token-matching. So an integer is needed
+% to count tokens, and a token register to build up the argument.
+%\end{variable}
+%
%\begin{variable}{\l_xparse_processor_bool}
% When converting an argument specification into a signature there is
% a need to know if there are any argument processors set up. This is
@@ -573,8 +602,8 @@
%\end{variable}
%
%\begin{variable}{\l_xparse_signature_toks}
-% For constucting the signature of the function defined. As
-% \pkg{xparse} works thorugh an argument specification, grabber
+% For constructing the signature of the function defined. As
+% \pkg{xparse} works through an argument specification, grabber
% functions are added to this toks for each argument.
%\end{variable}
%
@@ -585,7 +614,7 @@
%
%\begin{variable}{\l_xparse_total_args_int}
% Used to enumerate the total number of arguments (i.e., the number of
-% ingroup letters in the argument specification).
+% letters in the argument specification).
%\end{variable}
%
%\begin{variable}{\q_xparse_stop}
@@ -594,7 +623,10 @@
%
%\subsection{Internal functions}
%
-%\begin{function}{\xparse_add_arg:n}
+%\begin{function}{
+% \xparse_add_arg:n |
+% \xparse_add_arg:V
+%}
% \begin{syntax}
% "\xparse_add_arg:n" <grabbed arg>
% \end{syntax}
@@ -653,7 +685,7 @@
% Used to count how many mandatory arguments an argument specification
% contains. The \texttt{n} function carries out the set up, before
% handing of to the \texttt{N} function. This reads one token, and
-% calls the approriate counter function.
+% calls the appropriate counter function.
%\end{function}
%
%\begin{function}{
@@ -676,10 +708,7 @@
% mandatory arguments do any more than call the loop again.
%\end{function}
%
-%\begin{function}{
-% \xparse_declare_cmd:Nnn|
-% \xparse_declare_cmd:cnn
-%}
+%\begin{function}{\xparse_declare_cmd:Nnn}
% \begin{syntax}
% "\xparse_declare_cmd:Nnn" <function> \Arg{signature}
% ~~~~\Arg{code}
@@ -722,7 +751,7 @@
% ~~~~\Arg{start code} \Arg{end code}
% \end{syntax}
% Declares <env> as an environment taking <arg spec> arguments
-% at \cs{begin}\{<env>\}. The <start code> is eceutre at the beginning
+% at \cs{begin}\{<env>\}. The <start code> is executed at the beginning
% of the environment, and the <end code> at the end. Both parts may
% use the arguments defined by <arg spec>.
% \begin{texnote}
@@ -780,7 +809,7 @@
% Argument grabbing functions, which re-arrange other <arg data>
% so that the argument is read correctly. The \texttt{trailing}
% versions do not skip spaces when searching for optional arguments.
-% For each argument type, the various versions feed the approriate
+% For each argument type, the various versions feed the appropriate
% information to a common auxiliary function which then sets up
% \cs{xparse_grab_arg:w} to actually carry out the argument absorption.
%\end{function}
@@ -922,6 +951,16 @@
% \end{macrocode}
%\end{macro}
%
+%\begin{macro}{\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{macro}
+%
%\begin{macro}{\l_xparse_error_bool}
% Used to signal an error when creating expandable functions.
% \begin{macrocode}
@@ -976,6 +1015,18 @@
% \end{macrocode}
%\end{macro}
%
+%\begin{macro}{\l_xparse_nested_int}
+%\begin{macro}{\l_xparse_nested_toks}
+% To deal with nested delimited arguments, the code needs to do some
+% token counting `by hand'. That requires an integer, and also a token
+% register to store the growing argument collected.
+% \begin{macrocode}
+\int_new:N \l_xparse_nested_int
+\toks_new:N \l_xparse_nested_toks
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%
%\begin{macro}{\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
@@ -1035,7 +1086,7 @@
% This is used to determine whether to skip spaces or not where
% searching for the argument.
% \begin{macrocode}
-\cs_new_nopar:Nn \xparse_add_grabber_mandatory:N {
+\cs_new_nopar:Npn \xparse_add_grabber_mandatory:N #1 {
\toks_put_right:Nx \l_xparse_signature_toks {
\exp_not:c {
xparse_grab_ #1 \bool_if:NT \l_xparse_long_bool { _long } :w
@@ -1044,7 +1095,7 @@
\bool_set_false:N \l_xparse_long_bool
\int_decr:N \l_xparse_mandatory_args_int
}
-\cs_new_nopar:Nn \xparse_add_grabber_optional:N {
+\cs_new_nopar:Npn \xparse_add_grabber_optional:N #1 {
\toks_put_right:Nx \l_xparse_signature_toks {
\exp_not:c {
xparse_grab_ #1
@@ -1070,7 +1121,7 @@
%
%\begin{macro}{\xparse_add_type_+:w}
% Making the next argument \cs{long} means setting the flag and
-% knocking one back off the totatl argument count. The \texttt{m}
+% 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}
@@ -1087,7 +1138,7 @@
%\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 excution list by
+% 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.
@@ -1109,7 +1160,7 @@
% 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|
-% shoudl be single tokens.
+% should be single tokens.
% \begin{macrocode}
\cs_new:Npn \xparse_add_type_d:w #1#2 {
\xparse_add_type_D:w #1 #2 { \NoValue }
@@ -1218,9 +1269,9 @@
% This function checks if the argument type actually exists and gives
% an error if it doesn't.
% \begin{macrocode}
-\cs_new_nopar:Nn \xparse_check_and_add:N {
+\cs_new_nopar:Npn \xparse_check_and_add:N #1 {
\cs_if_free:cTF { xparse_add_type_ #1 :w } {
- \msg_error:nnx { xparse } { unknown-argument-type } {#1}
+ \msg_kernel_error:nnx { xparse } { unknown-argument-type } {#1}
\xparse_add_type_m:w
}{
\use:c { xparse_add_type_ #1 :w }
@@ -1234,16 +1285,16 @@
%\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
-% shrot-cut for another argument type. If it is, expand it and loop
+% 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:Nn \xparse_count_mandatory:n {
+\cs_new:Npn \xparse_count_mandatory:n #1 {
\int_zero:N \l_xparse_mandatory_args_int
\xparse_count_mandatory:N #1 \q_nil
}
-\cs_new:Nn \xparse_count_mandatory:N {
+\cs_new: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
@@ -1253,7 +1304,7 @@
}
}
}
-\cs_new:Nn \xparse_count_mandatory_aux:N {
+\cs_new:Npn \xparse_count_mandatory_aux:N #1 {
\cs_if_free:cTF { xparse_count_type_ #1 :w } {
\xparse_count_type_m:w
}{
@@ -1327,7 +1378,8 @@
%\end{macro}
%
%\begin{macro}{\xparse_declare_cmd:Nnn}
-%\begin{macro}{\xparse_declare_cmd:cnn}
+%\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
@@ -1337,7 +1389,19 @@
% internal function actually contains the code with the user function
% as a simple wrapper.
% \begin{macrocode}
-\cs_new:Nn \xparse_declare_cmd:Nnn {
+\cs_new:Npn \xparse_declare_cmd:Nnn #1#2 {
+ \cs_if_exist:NTF #1
+ {
+ \msg_kernel_warning:nnxx { xparse } { redefine-command }
+ { \exp_not:N #1 } { \exp_not:n {#2} }
+ }
+ {
+ \msg_kernel_info:nnxx { xparse } { define-command }
+ { \exp_not:N #1 } { \exp_not:n {#2} }
+ }
+ \xparse_declare_cmd_aux:Nnn #1 {#2}
+}
+\cs_new:Npn \xparse_declare_cmd_aux:Nnn #1#2#3 {
\xparse_count_mandatory:n {#2}
\xparse_prepare_signature:n {#2}
\bool_if:NTF \l_xparse_m_only_bool {
@@ -1346,12 +1410,12 @@
\xparse_declare_cmd_mixed:Nn #1 {#3}
}
}
-\cs_generate_variant:Nn \xparse_declare_cmd:Nnn { cnn }
-\cs_new:Nn \xparse_declare_cmd_all_m:Nn {
+\cs_generate_variant:Nn \xparse_declare_cmd_aux:Nnn { cnn }
+\cs_new: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:Nn \xparse_declare_cmd_mixed:Nn {
+\cs_new:Npn \xparse_declare_cmd_mixed:Nn #1#2 {
\cs_set_protected_nopar:Npx #1 {
\exp_not:n {
\int_zero:N \l_xparse_processor_int
@@ -1368,13 +1432,14 @@
%\end{macro}
%\end{macro}
%\end{macro}
+%\end{macro}
%
%\begin{macro}{\xparse_declare_cmd_implementation:nNn}
-% Creating a stand-alone implementation uisn the `two-part' mechanism
+% Creating a stand-alone implementation using the `two-part' mechanism
% is quite easy as this is just a wrapper for
% \cs{cs_generate_from_arg_count:cNnn}.
% \begin{macrocode}
-\cs_new:Nn \xparse_declare_cmd_implementation:nNn {
+\cs_new:Npn \xparse_declare_cmd_implementation:nNn #1#2#3 {
\cs_generate_from_arg_count:cNnn { implementation_ #1 :w }
\cs_set:Npn {#2} {#3}
}
@@ -1391,7 +1456,7 @@
% is created. As before, there is a short-cut for functions which only
% have \texttt{m} type arguments.
% \begin{macrocode}
-\cs_new:Nn \xparse_declare_cmd_interface:Nnn {
+\cs_new: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}
@@ -1401,12 +1466,12 @@
\cs_generate_from_arg_count:cNnn { implementation_ #2 :w }
\cs_set:Npn \l_xparse_total_args_int { ``#2'' }
}
-\cs_new:Nn \xparse_declare_cmd_interface_all_m:Nn {
+\cs_new: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:Nn \xparse_declare_cmd_interface_mixed:Nn {
+\cs_new: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
@@ -1428,20 +1493,38 @@
% 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:Nn \xparse_declare_env:nnnn {
- \xparse_declare_cmd:cnn { environment_begin_ #1 :w } {#2} {
+\cs_new:Npn \xparse_declare_env:nnnn #1#2#3#4 {
+ \bool_set_true:N \l_xparse_environment_bool
+%</initex|package>
+%<*initex>
+ \cs_if_exist:cTF { environment_begin_ #1 :w }
+%</initex>
+%<*package>
+ \cs_if_exist:cTF {#1}
+%</package>
+%<*initex|package>
+ {
+ \msg_kernel_warning:nnxx { xparse } { redefine-environment }
+ {#1} { \exp_not:n {#2} }
+ }
+ {
+ \msg_kernel_info:nnxx { xparse } { define-environment }
+ {#1} { \exp_not:n {#2} }
+ }
+ \xparse_declare_cmd_aux:cnn { environment_begin_ #1 :w } {#2} {
\group_begin:
\toks_set_eq:NN \l_xparse_environment_args_toks
\l_xparse_args_toks
#3
}
+ \bool_set_false:N \l_xparse_environment_bool
\cs_set_nopar:cpx { environment_end_ #1 :w } {
\exp_not:N \exp_last_unbraced:NV
\exp_not:c { environment_end_ #1 _aux:N }
\exp_not:N \l_xparse_environment_args_toks
\exp_not:N \group_end:
}
- \cs_set_nopar:cx { environment_end_ #1 _aux:N } {
+ \cs_set_nopar:cpx { environment_end_ #1 _aux:N } ##1 {
\exp_not:c { environment_end_ #1 _aux :w }
}
\cs_generate_from_arg_count:cNnn
@@ -1464,7 +1547,7 @@
% be switched here. The total number of mandatory arguments added to
% the signature is also decreased by the appropriate amount.
% \begin{macrocode}
-\cs_new_nopar:Nn \xparse_flush_m_args: {
+\cs_new_nopar:Npn \xparse_flush_m_args: {
\cs_if_exist:cT {
xparse_grab_m_ \int_use:N \l_xparse_m_args_int :w
} {
@@ -1501,10 +1584,14 @@
% also kept of the total number of arguments. This function sets
% everything up then hands off to the parser.
% \begin{macrocode}
-\cs_new:Nn \xparse_prepare_signature:n {
+\cs_new:Npn \xparse_prepare_signature:n #1 {
\bool_set_false:N \l_xparse_long_bool
\int_zero:N \l_xparse_m_args_int
- \bool_set_true:N \l_xparse_m_only_bool
+ \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
\toks_clear:N \l_xparse_signature_toks
\int_zero:N \l_xparse_total_args_int
@@ -1520,11 +1607,11 @@
% point to watch what is next on the stack so that the loop continues
% correctly.
% \begin{macrocode}
-\cs_new:Nn \xparse_prepare_signature:N {
+\cs_new:Npn \xparse_prepare_signature:N #1 {
\bool_set_false:N \l_xparse_processor_bool
\xparse_prepare_signature_aux:N #1
}
-\cs_new:Nn \xparse_prepare_signature_aux:N {
+\cs_new:Npn \xparse_prepare_signature_aux:N #1 {
\quark_if_nil:NTF #1 {
\bool_if:NF \l_xparse_m_only_bool {
\xparse_flush_m_args:
@@ -1534,7 +1621,7 @@
\prop_get:NnN \c_xparse_shorthands_prop {#1} \l_xparse_tmp_tl
\exp_last_unbraced:NV \xparse_prepare_signature:N \l_xparse_tmp_tl
}{
- \int_incr:N \l_xparse_total_args_int
+ \int_incr:N \l_xparse_total_args_int
\xparse_check_and_add:N #1
}
}
@@ -1544,13 +1631,13 @@
%\end{macro}
%
%\begin{macro}{\xparse_process_arg:n}
-% Processors are saved for use later during the grabbbing process.
+% Processors are saved for use later during the grabbing process.
% \begin{macrocode}
-\cs_new:Nn \xparse_process_arg:n {
+\cs_new:Npn \xparse_process_arg:n #1 {
\int_incr:N \l_xparse_processor_int
- \cs_set:cn {
+ \cs_set:cpn {
xparse_processor_ \int_use:N \l_xparse_processor_int :n
- }
+ } ##1
{ #1 {##1} }
}
% \end{macrocode}
@@ -1559,17 +1646,18 @@
%\subsection{Grabbing arguments}
%
%\begin{macro}{\xparse_add_arg:n}
+%\begin{macro}{\xparse_add_arg:V}
%\begin{macro}[aux]{\xparse_add_arg_aux:n}
%\begin{macro}[aux]{\xparse_add_arg_aux:V}
% The argument-storing system provides a single point for interfacing
-% with processors. They are done in a loop, couning downward. In this
+% 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:Nn \xparse_add_arg:n {
+\cs_new:Npn \xparse_add_arg:n #1 {
\intexpr_compare:nTF { \l_xparse_processor_int = \c_zero } {
\toks_put_right:Nn \l_xparse_args_toks { {#1} }
}{
@@ -1581,16 +1669,18 @@
}
}
}
-\cs_new:Nn \xparse_add_arg_aux:n {
+\cs_generate_variant:Nn \xparse_add_arg:n { V }
+\cs_new:Npn \xparse_add_arg_aux:n #1 {
+ \cs_set_eq:NN \ProcessedArgument \l_xparse_arg_toks
\use:c { xparse_processor_ \int_use:N \l_xparse_processor_int :n }
{#1}
\int_decr:N \l_xparse_processor_int
\intexpr_compare:nTF { \l_xparse_processor_int = \c_zero } {
- \toks_put_right:No \l_xparse_args_toks {
- \exp_after:wN { \toks_use:N \l_xparse_arg_toks }
+ \toks_put_right:Nx \l_xparse_args_toks {
+ { \exp_not:V \ProcessedArgument }
}
}{
- \xparse_add_arg_aux:V \l_xparse_arg_toks
+ \xparse_add_arg_aux:V \ProcessedArgument
}
}
\cs_generate_variant:Nn \xparse_add_arg_aux:n { V }
@@ -1598,30 +1688,37 @@
%\end{macro}
%\end{macro}
%\end{macro}
+%\end{macro}
%
-% All of the grabbers follow the same basic pattern. The intial function
-% sets u 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.
+% 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.
+% for this is reserved here. A couple of auxiliary functions are also
+% needed in various places.
% \begin{macrocode}
-\cs_new:Npn \xparse_grab_aux:w { }
+\cs_new:Npn \xparse_grab_arg:w { }
+\cs_new:Npn \xparse_grab_arg_aux_i:w { }
+\cs_new: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}
-%\begin{macro}[aux]{\xparse_grab_D_aux:NNnnNn}
% 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.
@@ -1641,10 +1738,42 @@
\l_xparse_args_toks {
\xparse_grab_D_aux:NNnnNn #1 #2 {#3} {#4} \cs_set:Npn { }
}
-\cs_set:Nn \xparse_grab_D_aux:NNnnNn {
- #5 \xparse_grab_arg:w #1 ##1 #2 {
- \xparse_add_arg:n {##1}
- #4 \l_xparse_args_toks
+% \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 `spare' open-argument token. If that is found, things hand off
+% to a loop to deal with that.
+% \begin{macrocode}
+\cs_new: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 {#4} #5 {##1}
+ }{
+ \xparse_add_arg:n {##1}
+ #4 \l_xparse_args_toks
+ }
}
\use:c { peek_charcode #6 :NTF } #1 {
\xparse_grab_arg:w
@@ -1659,13 +1788,47 @@
%\end{macro}
%\end{macro}
%\end{macro}
+%\begin{macro}[aux]{\xparse_grab_D_nested:NNnNn}
+%\begin{macro}[aux]{\xparse_grab_D_nested_aux:n}
+% Catching nested optional arguments means more work. As \TeX\ does not
+% help here, the brackets have to be counted by hand. The code then
+% keeps looking for closing tokens until all of the opening ones
+% are matched.
+% \begin{macrocode}
+\cs_new:Npn \xparse_grab_D_nested:NNnNn #1#2#3#4#5 {
+ \int_zero:N \l_xparse_nested_int
+ \toks_set:Nn \l_xparse_nested_toks { #5 #2 }
+ \cs_set:Npn \xparse_grab_D_nested_aux:n ##1 {
+ \tl_if_eq:nnT {#1} {##1} {
+ \int_incr:N \l_xparse_nested_int
+ }
+ }
+ \tl_map_function:nN {#5} \xparse_grab_D_nested_aux:n
+ #4 \xparse_grab_arg:w ##1 #2 {
+ \int_decr:N \l_xparse_nested_int
+ \tl_map_function:nN {##1} \xparse_grab_D_nested_aux:n
+ \intexpr_compare:nTF { \l_xparse_nested_int = \c_zero } {
+ \toks_put_right:Nn \l_xparse_nested_toks {##1}
+ \xparse_add_arg:V \l_xparse_nested_toks
+ #3 \l_xparse_args_toks
+ }{
+ \toks_put_right:Nn \l_xparse_nested_toks { ##1 #2 }
+ \xparse_grab_arg:w
+ }
+ }
+ \xparse_grab_arg:w
+}
+\cs_new:Npn \xparse_grab_D_nested_aux:n #1 { }
+% \end{macrocode}
+%\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 checed by meaning, so that the same code will
+% 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:Npn \xparse_grab_G:w #1#2 \l_xparse_args_toks {
@@ -1680,7 +1843,7 @@
\cs_new:Npn \xparse_grab_G_long_trailing:w #1#2 \l_xparse_args_toks {
\xparse_grab_G_aux:nnNn {#1} {#2} \cs_set:Npn { }
}
-\cs_set:Nn \xparse_grab_G_aux:nnNn {
+\cs_set: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_toks
@@ -1710,9 +1873,9 @@
\cs_new:Npn \xparse_grab_l_long:w #1 \l_xparse_args_toks {
\xparse_grab_l_aux:nN {#1} \cs_set:Npn
}
-\cs_new:Nn \xparse_grab_l_aux:nN {
+\cs_new:Npn \xparse_grab_l_aux:nN #1#2 {
#2 \xparse_grab_arg:w ##1## {
- \xparse_add_arg:n \l_xparse_args_toks {##1}
+ \xparse_add_arg:n {##1}
#1 \l_xparse_args_toks
}
\xparse_grab_arg:w
@@ -1851,7 +2014,7 @@
\cs_new:Npn \xparse_grab_t_long_trailing:w #1#2 \l_xparse_args_toks {
\xparse_grab_t_aux:NnNn #1 {#2} \cs_set:Npn { }
}
-\cs_new:Nn \xparse_grab_t_aux:NnNn {
+\cs_new: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 }
@@ -1882,7 +2045,7 @@
\cs_new:Npn \xparse_grab_u_long:w #1#2 \l_xparse_args_toks {
\xparse_grab_u_aux:NnN {#1} {#2} \cs_set:Npn
}
-\cs_new:Nn \xparse_grab_u_aux:NnN {
+\cs_new: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_toks
@@ -1899,8 +2062,8 @@
%\begin{macro}{\xparse_process_to_str:n}
% A basic argument processor: as much an example as anything else.
% \begin{macrocode}
-\cs_new:Nn \xparse_process_to_str:n {
- \toks_set:Nx \l_xparse_arg_toks {
+\cs_new:Npn \xparse_process_to_str:n #1 {
+ \toks_set:Nx \ProcessedArgument {
\tl_to_str:n {#1}
}
}
@@ -1911,15 +2074,15 @@
%\begin{macro}[aux]{\xparse_process_comma_split_aux:w}
% Turns a co-ordinate pair into two separate values.
% \begin{macrocode}
-\cs_new:Nn \xparse_process_comma_split:n {
+\cs_new:Npn \xparse_process_comma_split:n #1 {
\tl_if_in:nnTF {#1} { , } {
\xparse_process_comma_split_aux:w #1 \q_stop
}{
- \toks_set:Nn \l_xparse_arg_toks { {#1} { \NoValue } }
+ \toks_set:Nn \ProcessedArgument { {#1} { \NoValue } }
}
}
\cs_new:Npn \xparse_process_comma_split_aux:w #1 , #2 \q_stop {
- \toks_set:Nn \l_xparse_arg_toks { {#1} {#2} }
+ \toks_set:Nn \ProcessedArgument { {#1} {#2} }
}
% \end{macrocode}
%\end{macro}
@@ -1946,7 +2109,7 @@
%
%\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 shortcut is set up in
+% general delimited one. First, a short-cut is set up in
% \cs{l_xparse_tmpa_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
@@ -2075,9 +2238,9 @@
% Virtually identical to the normal version, except calling the
% expandable \texttt{add} functions rather than the standard versions.
% \begin{macrocode}
-\cs_new_nopar:Nn \xparse_exp_check_and_add:N {
+\cs_new_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 } {#1}
+ \msg_kernel_error:nnx { xparse } { unknown-argument-type } {#1}
\tl_set:Nn \l_xparse_last_arg_tl { m }
\xparse_exp_add_type_m:w
}{
@@ -2093,8 +2256,8 @@
%\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 fucntion is created to grab an argument
-% and pass along prevous ones. Each `daisy chains' to call the next
+% 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
@@ -2102,7 +2265,16 @@
% 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:Nn \xparse_exp_declare_cmd:Nnn {
+\cs_new:Npn \xparse_exp_declare_cmd:Nnn #1#2#3 {
+ \cs_if_exist:NTF #1
+ {
+ \msg_kernel_warning:nnxx { xparse } { redefine-command }
+ { \exp_not:N #1 } { \exp_not:n {#2} }
+ }
+ {
+ \msg_kernel_info:nnxx { xparse } { define-command }
+ { \exp_not:N #1 } { \exp_not:n {#2} }
+ }
\tl_set:Nn \l_xparse_function_tl {#1}
\xparse_exp_prepare_function:n {#2}
\intexpr_compare:nTF {
@@ -2113,7 +2285,7 @@
\xparse_exp_declare_cmd_mixed:Nn #1 {#3}
}
}
-\cs_new:Nn \xparse_exp_declare_cmd_all_m:Nn {
+\cs_new: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}
@@ -2122,14 +2294,14 @@
#1 \cs_set_nopar:Npn \l_xparse_total_args_int {#2}
}
}
-\cs_new:Nn \xparse_exp_declare_cmd_mixed:Nn {
+\cs_new:Npn \xparse_exp_declare_cmd_mixed:Nn #1#2 {
\exp_args:NnV \tl_if_in:nnTF { l m u } \l_xparse_last_arg_tl {
\xparse_exp_declare_cmd_mixed_aux:Nn #1 {#2}
}{
- \msg_error:nn { xparse } { expandable-ending-optional }
+ \msg_kernel_error:nn { xparse } { expandable-ending-optional }
}
}
-\cs_new:Nn \xparse_exp_declare_cmd_mixed_aux:Nn {
+\cs_new: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_stop
}
@@ -2153,25 +2325,27 @@
% \texttt{g}, \texttt{l} and \texttt{u} arguments (the later more for
% ease than any technical reason).
% \begin{macrocode}
-\cs_new:Nn \xparse_exp_prepare_function:n {
+\cs_new: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 } {#1}
+ \msg_kernel_error:nnx { xparse } { processor-in-expandable } {#1}
\bool_set_true:N \l_xparse_error_bool
}
\tl_if_in:nnT {#1} { g } {
- \msg_error:nnx { xparse } { grouped-in-expandable } {#1}
+ \msg_kernel_error:nnx { xparse } { grouped-in-expandable }
+ { g } {#1}
\bool_set_true:N \l_xparse_error_bool
}
\tl_if_in:nnT {#1} { G } {
- \msg_error:nnx { xparse } { grouped-in-expandable } {#1}
+ \msg_kernel_error:nnx { xparse } { grouped-in-expandable }
+ { G } {#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:Nn \xparse_exp_prepare_function_aux:n {
+\cs_new: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
@@ -2190,27 +2364,30 @@
%\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
+% 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:Nn \xparse_exp_prepare_function:N {
+\cs_new: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:Nn \xparse_exp_prepare_function_long:N {
+\cs_new:Npn \xparse_exp_prepare_function_long:N #1 {
\quark_if_nil:NF #1 {
\tl_if_eq:nnTF {#1} { + } {
\xparse_exp_prepare_function_short:N
}{
- \msg_error:nn { xparse } { inconsistent-long }
+ \msg_kernel_error:nn { xparse } { expandable-inconsistent-long }
\xparse_exp_prepare_function_short:N #1
}
-
}
}
-\cs_new:Nn \xparse_exp_prepare_function_short:N {
+\cs_new: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
@@ -2231,7 +2408,7 @@
%\end{macro}
%
%\begin{macro}{\xparse_exp_set:cpx}
-% A shortcut to save constantly re-testing \cs{l_xparse_long_bool}.
+% 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}
@@ -2239,53 +2416,104 @@
%
%\subsection{Messages}
%
-% Some error messages.
-% \begin{macrocode}
-\msg_new:nnnn { xparse } { command-already-defined } {%
- Command name `\token_to_str:N #1' already defined!%
-}{%
- You have used \token_to_str:N \NewDocumentCommand\\%
- with a command that already has a definition.\\%
- Perhaps you meant \token_to_str:N \RenewDocumentCommand.%
-}
-\msg_new:nnnn { xparse } { command-not-yet-defined } {%
- Command `\token_to_str:N #1' not yet defined!%
-}{%
- You have used \token_to_str:N \RenewDocumentCommand\\%
- with a command that was never defined.\\%
- Perhaps you meant \token_to_str:N \NewDocumentCommand.%
-}
-\msg_new:nnn { xparse } { environment-already-defined } {%
- Environment `#1' already defined!%
-}
-\msg_new:nnn { xparse } { environment-not-yet-defined } {%
- Environment `#1' not yet defined!%
-}
-\msg_new:nnnn { xparse } { expandable-ending-optional } {%
- Expandable command signature ends in optional argument.%
-}{%
- Expandable functions must have a final mandatory argument.%
-}
-\msg_new:nnnn { xparse } { grouped-in-expandable } {%
- Optional grouped arguments cannot be used with expandable functions.%
-}{%
- Argument specification `#1' contains an optional grouped argument:\\%
- this is only supported for standard robust functions.%
-}
-\msg_new:nnnn { xparse } { inconsistent-long } {%
- Inconsistent long arguments.%
-}{%
- Expandable commands must have all arguments long if any at all.%
-}
-\msg_new:nnnn { xparse } { processor-in-expandable } {%
- Argument processors cannot be used with expandable functions.%
-}{%
- Argument specification `#1' contains a processor function:\\%
- this is only supported for standard robust functions.%
-}
-\msg_new:nnn { xparse } { unknown-argument-type } {%
- Unknown argument type `#1' replaced by `m'. Fingers crossed ...%
-}
+% Some messages intended as errors.
+% \begin{macrocode}
+\msg_kernel_new:nnnn { xparse } { command-already-defined }
+ {Command `#1' already defined!}
+ {%
+ You have used \token_to_str:N \NewDocumentCommand\\%
+ with a command that already has a definition.\\%
+ Perhaps you meant \token_to_str:N \RenewDocumentCommand.%
+ }
+\msg_kernel_new:nnnn { xparse } { command-not-yet-defined }
+ {Command `#1' not yet defined!}
+ {%
+ You have used \token_to_str:N \RenewDocumentCommand\\%
+ with a command that was never defined.\\%
+ Perhaps you meant \token_to_str:N \NewDocumentCommand.%
+ }
+\msg_kernel_new:nnnn { xparse } { environment-already-defined }
+ {Environment `#1' already defined!}
+ {%
+ You have used \token_to_str:N \NewDocumentEnvironment\\%
+ with a command that already has a definition.\\%
+ Perhaps you meant \token_to_str:N \RenewDocumentEnvironment.%
+ }
+\msg_kernel_new:nnnn { xparse } { environment-not-yet-defined }
+ {Environment `#1' not yet defined!}
+ {%
+ You have used \token_to_str:N \RenewDocumentEnvironment\\%
+ with a command that was never defined.\\%
+ Perhaps you meant \token_to_str:N \NewDocumentEnvironment.%
+ }
+\msg_kernel_new:nnnn { xparse } { expandable-ending-optional }
+ {%
+ Signature for expandable command ends with \\%
+ optional argument \msg_line_context:.%
+ }
+ {%
+ Expandable commands must have a final mandatory argument\\%
+ (or no arguments at all). You cannot have a terminal optional\\%
+ argument with expandable commands.%
+ }
+\msg_kernel_new:nnnn { xparse } { expandable-inconsistent-long }
+ {%
+ Inconsistent handling of long arguments for\\%
+ expandable command \msg_line_context:.%
+ }
+ {%
+ The arguments for an expandable command must either all be\\%
+ short or all be long. You have tried to mix the two types.%
+ }
+\msg_kernel_new:nnnn { xparse } { grouped-in-expandable }
+ {%
+ Argument specifier `#1' forbidden in expandable commands
+ \msg_line_context:.%
+ }
+ {%
+ Argument specification `#2' contains the optional grouped
+ argument `#1':\\%
+ this is only supported for standard robust functions.%
+ }
+\msg_kernel_new:nnnn { xparse } { processor-in-expandable }
+ {%
+ Argument processors cannot be used\\%
+ with expandable functions \msg_line_context:.%
+ }
+ {%
+ Argument specification `#1' contains a processor function:\\%
+ this is only supported for standard robust functions.%
+ }
+\msg_kernel_new:nnnn { xparse } { unknown-argument-type }
+ {Unknown argument type `#1' replaced by `m'. Fingers crossed ...}
+ {%
+ The letter `#1' does not specify a known argument type.\\%
+ I'm assuming you want a standard mandatory argument (type `m').%
+ }
+% \end{macrocode}
+%
+% Intended more for information.
+% \begin{macrocode}
+\msg_kernel_new:nnn { xparse } { define-command }
+ {%
+ Defining document command #1\\%
+ with arg. spec. `#2' \msg_line_context:.%
+ }
+\msg_kernel_new:nnn { xparse } { define-environment }
+ {%
+ Defining document environment `#1'\\%
+ with arg. spec. `#2' \msg_line_context:.%
+ }
+\msg_kernel_new:nnn { xparse } { redefine-command }
+ {%
+ Redefining document command #1\\%
+ with arg. spec. `#2' \msg_line_context:.%
+ }
+\msg_kernel_new:nnn { xparse } { redefine-environment }
+ {%
+ Redefining document environment `#1'\\%
+ with arg. spec. `#2' \msg_line_context:.%
+ }
% \end{macrocode}
%
%\subsection{User functions}
@@ -2309,24 +2537,26 @@
%\begin{macro}{\ProvideDocumentCommand}
% The user macros are pretty simple wrappers around the internal ones.
% \begin{macrocode}
-\xparse_declare_cmd:Nnn \DeclareDocumentCommand { +m +m +m } {
+\cs_new_protected:Npn \DeclareDocumentCommand #1#2#3 {
\xparse_declare_cmd:Nnn #1 {#2} {#3}
}
-\DeclareDocumentCommand \NewDocumentCommand { +m +m +m } {
+\cs_new_protected:Npn \NewDocumentCommand #1#2#3 {
\cs_if_exist:NTF #1 {
- \msg_error:nnx { xparse } { command-already-defined } {#1}
+ \msg_kernel_error:nnx { xparse } { command-already-defined }
+ { \exp_not:N #1 }
}{
\xparse_declare_cmd:Nnn #1 {#2} {#3}
}
}
-\NewDocumentCommand \RenewDocumentCommand { +m +m +m } {
+\cs_new_protected:Npn \RenewDocumentCommand #1#2#3 {
\cs_if_exist:NTF #1 {
\xparse_declare_cmd:Nnn #1 {#2} {#3}
}{
- \msg_error:nnx { xparse } { command-not-yet-defined } {#1}
+ \msg_kernel_error:nnx { xparse } { command-not-yet-defined }
+ { \exp_not:N #1 }
}
}
-\NewDocumentCommand \ProvideDocumentCommand { +m +m +m } {
+\cs_new_protected:Npn \ProvideDocumentCommand #1#2#3 {
\cs_if_exist:NF #1 {
\xparse_declare_cmd:Nnn #1 {#2} {#3}
}
@@ -2342,10 +2572,10 @@
% The separate implementation/interface system is again pretty simple
% to create at the outer layer.
% \begin{macrocode}
-\NewDocumentCommand \DeclareDocumentCommandImplementation { m m +m } {
+\cs_new_protected:Npn \DeclareDocumentCommandImplementation #1#2#3 {
\xparse_declare_cmd_implementation:nNn {#1} #2 {#3}
}
-\NewDocumentCommand \DeclareDocumentCommandInterface { m m +m } {
+\cs_new_protected:Npn \DeclareDocumentCommandInterface #1#2#3 {
\xparse_declare_cmd_interface:Nnn #1 {#2} {#3}
}
% \end{macrocode}
@@ -2358,25 +2588,48 @@
%\begin{macro}{\ProvideDocumentEnvironment}
% Very similar for environments.
% \begin{macrocode}
-\NewDocumentCommand \DeclareDocumentEnvironment { m +m +m +m } {
+\cs_new_protected:Npn \DeclareDocumentEnvironment #1#2#3#4 {
\xparse_declare_env:nnnn {#1} {#2} {#3} {#4}
}
-\NewDocumentCommand \NewDocumentEnvironment { m +m +m +m } {
+\cs_new_protected:Npn \NewDocumentEnvironment #1#2#3#4 {
+%</initex|package>
+%<*initex>
\cs_if_exist:cTF { environment_begin_ #1 :w } {
- \msg_error:nnx { xparse } { environment-already-defined } {#1}
+%</initex>
+%<*package>
+ \cs_if_exist:cTF {#1} {
+%</package>
+%<*initex|package>
+ \msg_kernel_error:nnx { xparse }
+ { environment-already-defined } {#1}
}{
\xparse_declare_env:nnnn {#1} {#2} {#3} {#4}
}
}
-\NewDocumentCommand \RenewDocumentEnvironment { m +m +m +m } {
- \cs_if_exist:cTF { environment_begin_ #1 :w } {
+\cs_new_protected:Npn \RenewDocumentEnvironment #1#2#3#4 {
+%</initex|package>
+%<*initex>
+ \cs_if_exist:cTF { environment_begin_ #1 :w } {
+%</initex>
+%<*package>
+ \cs_if_exist:cTF {#1} {
+%</package>
+%<*initex|package>
\xparse_declare_env:nnnn {#1} {#2} {#3} {#4}
}{
- \msg_error:nnx { xparse } { environment-not-yet-defined } {#1}
+ \msg_kernel_error:nnx { xparse }
+ { environment-not-yet-defined } {#1}
}
}
-\NewDocumentCommand \ProvideDocumentEnvironment { m +m +m +m } {
+\cs_new_protected:Npn \ProvideDocumentEnvironment #1#2#3#4 {
+%</initex|package>
+%<*initex>
\cs_if_exist:cF { environment_begin_ #1 :w } {
+%</initex>
+%<*package>
+ \cs_if_exist:cF { #1 } {
+%</package>
+%<*initex|package>
\xparse_declare_env:nnnn {#1} {#2} {#3} {#4}
}
}
@@ -2387,9 +2640,9 @@
%\end{macro}
%
%\begin{macro}{\DeclareExpandableDocumentCommand}
-% The expanable version of the basic function is essentially the same.
+% The expandable version of the basic function is essentially the same.
% \begin{macrocode}
-\NewDocumentCommand \DeclareExpandableDocumentCommand { +m +m +m } {
+\cs_new_protected:Npn \DeclareExpandableDocumentCommand #1#2#3 {
\xparse_exp_declare_cmd:Nnn #1 {#2} {#3}
}
% \end{macrocode}
@@ -2430,7 +2683,15 @@
% This is coded by hand as making it \cs{protected} ensures that it
% will not turn into anything else by accident.
% \begin{macrocode}
-\NewDocumentCommand \NoValue { } { -NoValue- }
+\cs_new_protected:Npn \NoValue { -NoValue- }
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\ProcessedArgument}
+% Processed arguments are returned using this name, which is reserved
+% here although the definition will change.
+% \begin{macrocode}
+\cs_new:Npn \ProcessedArgument { }
% \end{macrocode}
%\end{macro}
%
diff --git a/Master/texmf-dist/source/latex/xpackages/xbase/xtemplate.dtx b/Master/texmf-dist/source/latex/xpackages/xbase/xtemplate.dtx
new file mode 100644
index 00000000000..445474da3ef
--- /dev/null
+++ b/Master/texmf-dist/source/latex/xpackages/xbase/xtemplate.dtx
@@ -0,0 +1,3390 @@
+% \iffalse
+%% File: xtemplate.dtx (C) Copyright 1999-2001 David Carlisle, Frank Mittelbach
+%% (C) Copyright 2004-2009 Frank Mittelbach, 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
+%%1
+%% This file is part of the ``xbase 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{l3names}
+%</driver|package>
+%\fi
+\GetIdInfo$Id: xtemplate.dtx 1746 2009-11-16 01:34:59Z will $
+ {Prototype document functions}
+%\iffalse
+%<*driver>
+%\fi
+\ProvidesFile{\filename.\filenameext}
+ [\filedate\space v\fileversion\space\filedescription]
+%\iffalse
+\documentclass[full]{l3doc}
+\ExplSyntaxOn
+% SYNTAX environments getting ugly. This helps:
+\cs_if_exist:NT \g_doc_syntax_dim {
+ \dim_set:Nn \g_doc_syntax_dim {\textwidth}
+}
+\ExplSyntaxOff
+\usepackage{booktabs}
+\begin{document}
+ \DocInput{xtemplate.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \title{The \textsf{xtemplate} package\thanks{This file
+% has version number \fileversion, last
+% revised \filedate.}}
+% \author{\Team}
+% \date{\filedate}
+% \maketitle
+%
+% \begin{documentation}
+%
+% \section{Introduction}
+%
+% There are three broad `layers' between putting down ideas into a source file
+% and ending up with a typeset document. These layers of document writing are:
+% \begin{enumerate}
+% \item Authoring of the text, with mark-up
+% \item Document layout design
+% \item Implementation (with \TeX\ programming) of the design
+% \end{enumerate}
+% We write the text as an author, and we see the visual output of the design
+% after the document is generated; the \TeX\ implementation in the middle is
+% the glue between the two.
+%
+% \LaTeX's greatest success has been to standardise a system of mark-up that
+% balances the trade-off between ease of reading and ease of writing to suit
+% almost all forms of technical writing. It's
+% other original strength was a good background in typographical design; while
+% the standard \LaTeXe\ classes look somewhat dated now in terms of their
+% visual design, their typography is generally sound. (Barring the occasional
+% minor faults.)
+%
+% However, \LaTeXe\ has always lacked a standard approach to customising
+% the visual design of a document. Changing the looks of the standard classes
+% involved either:
+% \begin{itemize}
+% \item Creating a new version of the implementation code of the class and
+% editing it.
+% \item Loading one of the many packages to customise certain elements of
+% the standard classes.
+% \item Loading a completely different document class, such as
+% \textsf{KOMA-Script} or \textsf{memoir}, that allows easy
+% customisation.
+% \end{itemize}
+% All three of these approaches have their drawbacks and learning curves.
+%
+% The idea behind \pkg{xtemplate} is to cleanly separate the three layers
+% introduced at the beginning of this section, so that document authors who
+% are not programmers can easily change the design of their documents.
+% \pkg{xtemplate} also makes it easier for \LaTeX\ programmers to provide
+% their own customisations on top of a pre-existing class.
+%
+% \section{What is a document?}
+%
+% Besides the textual content of the words themselves, the source file of a
+% document contains mark-up elements that add structure to the document.
+% These elements include sectional divisions, figure/table captions,
+% lists of various sorts, theorems/proofs, and so on.
+% The list will be different for every document that can be written.
+%
+% Each element can be represented logically without worrying about the
+% formatting, with mark-up such as \cmd\section, \cmd\caption,
+% "\begin{enumerate}" and so on.
+% The output of each one of these document
+% elements will be a typeset representation of the information marked up, and
+% the visual arrangement and design of these elements can vary widely in
+% producing a variety of desired outcomes.
+%
+% For each type of document element, there may be design variations that
+% contain the same sort of information but present it in slightly different
+% ways.
+% For example, the difference between a numbered and an unnumbered
+% section, \cmd\section\ and \cmd\section"*", or the difference between an
+% itemised list or an enumerated list.
+%
+% There are three distinct layers in the definition of `a document' at this
+% level:
+% \begin{enumerate}
+% \item Semantic elements such as the ideas of sections and lists.
+% \item A set of design solutions for representing these elements visually.
+% \item Specific variations for these designs that represent the elements in the document.
+% \end{enumerate}
+% In the parlance of the \pkg{xtemplate} package, we call these object types,
+% templates, and instances, and they are discussed below in
+% sections \ref{sec:objects}, \ref{sec:templates}, and~\ref{sec:instances},
+% respectively.
+%
+% \section {Objects, templates, and instances}
+%
+% By formally declaring our document to be composed of mark-up elements
+% grouped into objects, which are interpreted and typeset with a set of
+% templates, each of which has one or more instances with which to compose each
+% and every semantic unit of the text, we can cleanly separate
+% the components of document construction.
+% The \pkg{xtemplate} package provides the tools to do this.
+%
+% \subsection{Object types}\label{sec:objects}
+%
+% An `object type' (or sometimes just `object') is an abstract idea of a
+% document element that takes a
+% fixed number of arguments corresponding to the information from the
+% document author that it is representing.
+% A sectioning object, for example, might take three inputs: `title',
+% `short title', and `label'.
+%
+% Any given document class will define which object types are to be used in
+% the
+% document, and any template of a given object type can be used to generate an
+% instance for the object.
+% (Of course, different templates will produce different typeset
+% representations, but the underlying content will be the same.)
+%
+% \begin{function}{\DeclareObjectType}
+% \begin{syntax}
+% "\DeclareObjectType" \Arg{name} \Arg{Nargs}
+% \end{syntax}
+% This function defines an \emph{object type},
+% where \meta{name} is the name of the object type and \meta{Nargs} is the number of
+% arguments an instance of this type should take. For example,
+% \begin{quote}
+% \begin{verbatim}
+% \DeclareObjectType{sectioning}{3}
+% \end{verbatim}
+% \end{quote}
+% Note that object types are global entities: \cs{DeclareObjectType}
+% will apply outside of any \TeX\ grouping in force when it is
+% called.
+% \end{function}
+%
+% \subsection{Templates}\label{sec:templates}
+%
+% A \emph{template} is a generalised design solution for representing the
+% information of a specified \emph{object type}.
+% Templates that do the same thing~--- e.g., two completely different ways of
+% printing a chapter heading~--- are grouped together by their object type and
+% given
+% separate names.
+% There are two important parts to a template:
+% \begin{itemize}
+% \item The parameters it takes to vary the design it is producing.
+% \item The implementation of the design.
+% \end{itemize}
+% As a document author or designer does not care about the implementation
+% but rather only the interface to the template, these two aspects of the template
+% definition are split into two independent declarations, \cmd\DeclareTemplateInterface\
+% and \cmd\DeclareTemplateCode.
+%
+% \begin{function}{\DeclareTemplateInterface}
+% \par
+% \begin{syntax}
+% "\DeclareTemplateInterface" \Arg{object type} \Arg{template} \Arg{Nargs}
+% "{"
+% " "<name of key 1> ":" <key type 1> ","
+% " "<name of key 2> ":" <key type 2> "=" <optional default> ","
+% " ..."
+% "}"
+% \end{syntax}
+% The \meta{name of keys} can be any string of \textsc{ascii} characters (with
+% the exception of ":", "=" and "," as they are part of the syntax);
+% we recommend only using lower case letters and dashes, however.
+% Note that spaces in key names are ignored, so that key names can be
+% spaced out for ease of reading without affecting the recognition of
+% keys inside and outside of code blocks.
+%
+% The <key types> define what sort of input the key accepts, such as `boolean',
+% `integer', and so on. The complete list of possible <key types> is shown in
+% \autoref{tab:keytypes}.
+%
+% Like objects, templates are global entities: both
+% \cs{DeclareTemplateInterface} \cs{DeclareTemplateCode} will apply
+% outside of any \TeX\ grouping in force when it is called.
+% \end{function}
+%
+% \begin{table}[p]
+% \begin{tabular}{@{}ll@{}}
+% \toprule
+% Key Type & Description of input \\
+% \midrule
+% "boolean" & "true" or "false" \\
+% "choice "\Arg{choices} & A list of pre-defined choices \\
+% "code" & Generalised key type; use "#1" as the input to the key \\
+% "commalist" & A comma-separated list of arbitrary items \\
+% "function "$N$ & A function definition with $N$ arguments
+% ($N$ from $0$ to $9$) \\
+% "instance "\Arg{name} & An instance of type \meta{name} \\
+% "integer" & An integer expression (e.g., {\small "(1 + 5)/2"}) \\
+% "length" & A dimension expression (e.g., {\small "3pt + 2cm"}) \\
+% "skip" & A dimension expression with glue
+% (e.g., {\small "3pt plus 2pt minus 1pt"}) \\
+% "tokenlist" & A `token list' input; any text or commands \\
+% \bottomrule
+% \end{tabular}
+% \caption{`Key types' for defining template interfaces with \cs{DeclareTemplateInterface}.}
+% \label{tab:keytypes}
+% \end{table}
+%
+% \begin{table}[p]
+% \begin{tabular}{@{}lcl@{}}
+% \toprule
+% Key Type && Description of binding \\
+% \midrule
+% "boolean" &$\star$& Boolean variable; e.g., "\l_tmpa_bool" \\
+% "choice" && "{" \meta{choice\,$_1$} "=" \meta{code\,$_1$} "," \meta{choice\,$_2$} "=" \meta{code\,$_2$} "," \dots "}" \\
+% "code" && \meta{code} ; use "#1" as the input to the key \\
+% "commalist" &$\star$& Comma-list variable; e.g., "\l_tmpa_clist" \\
+% "function" &$\star$& Function w/ $N$ arguments; e.g., "\use_i:nn" \\
+% "instance" &$\star$& An instance variable; e.g., "\g_foo_instance" \\
+% "integer" &$\star$& Integer variable; e.g., "\l_tmpa_int" \\
+% "length" &$\star$& Dimension variable; e.g., "\l_tmpa_dim" \\
+% "skip" &$\star$& Skip variable; e.g., "\l_tmpa_skip" \\
+% "tokenlist" &$\star$& Token list variable; e.g., "\l_tmpa_tl" \\
+% \bottomrule
+% \end{tabular}
+% \caption{Bindings required for different key types when defining template implementations with \cs{DeclareTemplateCode}. Starred entries may be prefixed with the keyword \texttt{global} to make a global assignment.}
+% \label{tab:keyvariables}
+% \end{table}
+%
+% \begin{function}{\DeclareTemplateCode}
+% \par
+% \begin{syntax}
+% "\DeclareTemplateCode" \Arg{object type} \Arg{template} \Arg{Nargs}
+% "{"
+% " "<name of key 1> "=" <internal variable or code 1> ","
+% " "<name of key 2> "=" <internal variable or code 2> ","
+% " ..."
+% "}{"
+% " "\meta{implementation code}
+% " \AssignTemplateKeys"
+% " "\meta{more implementation code}
+% "}"
+% \end{syntax}
+% After the keys have been declared with "\DeclareTemplateInterface", the
+% implementation binds each <name of key> with an <internal variable>
+% (for key types such as `integer', `length', `tokenlist', etc.)
+% \unskip\footnote{^^A
+% It is possible, if you wish, to use the same variable for multiple keys;
+% this allows `key synonyms' to be defined such as |color| and |colour| which
+% can perform the same function in the template implementation.}
+% or with a certain <code> fragment to execute, which will be described below.
+%
+% Assignments to variables which should be made globally are indicated by adding the
+% word \texttt{global} before the variable name:
+%
+% \begin{syntax}
+% " "<name of key 1> "=" <internal variable 1> ","
+% " "<name of key 2> "=" global <internal variable 2> ","
+% \end{syntax}
+%
+% The key types "choices" and "code" do not take variable bindings; instead,
+% fragments of code are defined which are executed instead. The complete list
+% of bindings taken by different key types is shown in \autoref{tab:keyvariables}.
+% The "choices" key type is explained fully in \autoref{sec:choices-key} below.
+%
+% \begin{function}{\AssignTemplateKeys}
+% \par
+% The final argument of \cs{DeclareTemplateCode} contains the <implementation code>
+% for the template design, taking arguments |#1|, |#2|, etc.\ according to the number of
+% arguments allowed, <Nargs>. \cs{AssignTemplateKeys} must be
+% executed in order to assign variables and perform code executions according
+% to the keys set.
+% \end{function}
+% \end{function}
+%
+% \subsection{Multiple choices}
+% \label{sec:choices-key}
+%
+% The \texttt{choice} keytype implements multiple choice input. At the
+% interface level, only the list of valid choices is needed:
+% \begin{verbatim}
+% \DeclareTemplateInterface { foo } { bar } 0 {
+% key-name : choice { A,B,C }
+% }
+% \end{verbatim}
+% where the choices are given as a comma-list (which must therefore
+% be wrapped in braces). A default value can also be given:
+% \begin{verbatim}
+% \DeclareTemplateInterface { foo } { bar } 0 {
+% key-name : choice { A,B,C } = A
+% }
+% \end{verbatim}
+%
+% At the implementation level, each choice is associated with code,
+% using a nested key--value list.
+% \begin{verbatim}
+% \DeclareTemplateCode { foo } { bar } 0 {
+% key-name = {
+% A = Code-A ,
+% B = Code-B ,
+% C = Code-C ,
+% }
+% } { ... }
+% \end{verbatim}
+% The two choice lists should match, but in the implementation a
+% special \texttt{unknown} choice is also available. This can be used
+% to ignore values and implement an `else' branch:
+% \begin{verbatim}
+% \DeclareTemplateCode { foo } { bar } 0 {
+% key-name = {
+% A = Code-A ,
+% B = Code-B ,
+% C = Code-C ,
+% unknown = Else-code
+% }
+% } { ... }
+% \end{verbatim}
+% The \texttt{unknown} entry must be the last one given, and should
+% \emph{not} be listed in the interface part of of the template.
+%
+% \subsection{Instances}\label{sec:instances}
+%
+% After a template is defined it still needs to be put to use.
+% The parameters that it expects need to be defined before it can be used in
+% a document.
+% Every time a template has parameters given to it, an \emph{instance} is
+% created, and this is the code that ends up in the document to perform the
+% typesetting of whatever pieces of information are input into it.
+%
+% For example, a template might say `here is a section with or without a
+% number that might be centred or left aligned and print its contents in a
+% certain font of a certain size, with a bit of a gap before and after it'
+% whereas an instance declares `this is a section with a number, which is centred and set
+% in 12pt italic with a 10pt skip before and a 12pt skip after it'.
+%
+% Therefore, an instance is just a frozen version of a template with specific
+% settings as chosen by the designer.
+%
+% \begin{function}{\DeclareInstance}
+% \par
+% \begin{syntax}
+% "\DeclareInstance" \Arg{object type} \Arg{instance} \Arg{template} \Arg{parameters}
+% \end{syntax}
+% The name of the instance being declared is <instance>, with <parameters>
+% the keyval input to set some or all of the <template> keys to specific values.
+%
+% Here is a hypothetical example, where |sectioning| might be an object to be used
+% for document subdivisions, |section-num| an instance referring to a `numbered section',
+% and |basic| a template for |sectioning| that performs just the basic layout, say:
+% \begin{quote}
+% \begin{verbatim}
+% \DeclareInstance{sectioning}{section-num}{basic} {
+% numbered = true ,
+% justification = center ,
+% font = \normalsize\itshape ,
+% before-skip = 10pt ,
+% after-skip = 12pt ,
+% }
+% \end{verbatim}
+% \end{quote}
+% \end{function}
+%
+%
+% \subsection{Document interface}
+%
+% After the instances have been chosen, document commands must be declared to
+% use those instances in the document. \cmd\UseInstance\ calls instances directly,
+% and this command should be used internally in document-level mark-up.
+%
+% \begin{function}{\UseInstance}
+% \par
+% \begin{syntax}
+% "\UseInstance" \Arg{object type} \Arg{instance} <arguments>
+% \end{syntax}
+% \end{function}
+%
+% It will take as many arguments as were defined for the object type.
+%
+% Use \textsf{xparse} to declare the document commands in terms of instances.
+% Another hypothetical example:
+% \begin{quote}
+% \begin{verbatim}
+% \DeclareDocumentCommand\section{ som }{
+% \IfBooleanTF #1
+% {
+% \UseInstance{sectioning}{section-nonum}{#2}{#3}
+% }
+% {
+% \UseInstance{sectioning}{section-num}{#2}{#3}
+% }
+% }
+% \end{verbatim}
+% \end{quote}
+%
+% \begin{function}{\UseTemplate}
+% \par
+% \begin{syntax}
+% "\UseTemplate" \Arg{object type} \Arg{template} \Arg{settings} <arguments>
+% \end{syntax}
+% There are occasions where creating an instance of a template does not
+% make sense, as it will only be used once. In this case, templates can
+% be used directly, with the key settings given as an argument to the
+% \cs{UseTemplate} function. This will also work when giving an argument
+% to a key which needs an instance. For example, if we have an key
+% \texttt{instance-key} which expects an instance of \texttt{object2},
+% then we can either declare an instance:
+% \begin{quote}
+% \begin{verbatim}
+% \DeclareInstance {object2} {template2} {temp-instance} {
+% <settings>
+% }
+% \DeclareInstance {object} {template} {instance} {
+% instance-key = temp-instance
+% }
+% \end{verbatim}
+% \end{quote}
+% or use the template directly:
+% \begin{quote}
+% \begin{verbatim}
+% \DeclareInstance {object} {template} {instance} {
+% instance-key = \UseTemplate {object2} {template2} {<settings>}
+% }
+% \end{verbatim}
+% \end{quote}
+% Which is the best approach will depend on the exact nature of the
+% situation.
+% \end{function}
+%
+% \subsection{Summaries}
+%
+% For the document designer:
+% \begin{itemize}
+% \item The class will define which object types are used in a document.
+% \item The class will define user commands that contain the required
+% instances that the document must use.
+% \item Having knowledge of a variety of suitable templates, for each
+% required instance a template can be selected and instantiated based on the
+% parameters defined by \cmd\DeclareTemplateInterface.
+% \end{itemize}
+%
+% For the class programmer:
+% \begin{itemize}
+% \item Define the different object types of document elements: what the semantics
+% are and what information is required.
+% \item Create document commands to call instances that fulfil the needs of
+% the object types.
+% \item Implement the required templates to produce typeset implementations
+% of the document elements and instantiate them with the appropriate names.
+% \end{itemize}
+%
+% \section{Instances in different contexts}
+%
+% We may wish the behaviour of an instance to change as it is used in varying contexts.
+% For example, in the frontmatter of a document, section numbering is
+% different. Semantics are the same, but the typesetting changes. But we want
+% to use the same user commands, and hence the same instance names.
+%
+% \emph{Collections} allow us to define multiple instances that we can switch
+% between. Collections are activated with \cmd\UseCollection.
+%
+% At present, it is not clear whether collections fully address the
+% issues they target. They should therefore be regarded as highly
+% experimental, and may be changed or withdrawn in the future if
+% it appears that they do not work well enough!
+%
+% \begin{function}{\DeclareCollectionInstance}
+%
+% \begin{syntax}
+% "\DeclareCollectionInstance" \Arg{collection} \Arg{object type} \Arg{instance} \Arg{template}\\\hfill \Arg{parameters}
+% \end{syntax}
+% \end{function}
+%
+% \begin{function}{\UseCollection}
+% \begin{syntax}
+% "\UseCollection" \Arg{object type} \Arg{collection}
+% \end{syntax}
+% \end{function}
+%
+% The instance declared will override another instance of the same name when
+% the collection is active. Note that a collection instance can only be declared if
+% the \emph{original} instance already exists.
+%
+% An example might be:
+% \begin{verbatim}
+% \UseCollection{sectioning}{frontmatter}
+% \section{Nomenclature}
+% ...
+% \UseCollection{sectioning}{default}
+% \section{Introduction}
+% \end{verbatim}
+% In both cases, the same instance (perhaps `"section-num"') is being used inside
+% the \cs{section}. But \cs{DeclareCollectionInstance} will have been used for
+% the `"frontmatter"' and override the instance that is used in the default case.
+%
+% \section{Bits 'n' pieces}
+%
+% \subsection{Does an instance exist?}
+%
+% \begin{function}{\IfInstanceExist / (TF)}
+%
+% \begin{syntax}
+% "\IfInstanceExistTF" \Arg{object type} \Arg{instance} \Arg{true code} \Arg{false code}
+% "\IfInstanceExistT" \Arg{object type} \Arg{instance} \Arg{true code}
+% "\IfInstanceExistF" \Arg{object type} \Arg{instance} \Arg{false code}
+% \end{syntax}
+% Test if <instance> has been declared. This is useful when the use of an instance
+% depends on some global variable, such as the current font selection. Designers
+% or users can then implement specific designs for exact situations rather than
+% relying on blanket parameter redefinitions. See \pkg{xfrac} for a good example of this.
+% \end{function}
+%
+% \subsection{Changing the defaults of a template's keys}
+%
+% Template parameters may be assigned specific defaults for instances to use
+% if the instance declaration doesn't explicit set those parameters.
+% In some cases, the document designer will wish to edit these defaults to
+% allow them to `cascade' to the instances.
+% The alternative would be to set each parameter identically for each
+% instance declaration, a tedious and error-prone process.
+% \begin{function}{\EditTemplateDefaults}
+%
+% \begin{syntax}
+% "\EditTemplateDefaults" \Arg{object type} \Arg{template} \Arg{new defaults}
+% \end{syntax}
+% \end{function}
+%
+% This command only takes effect for instances that have not yet been declared.
+% Use "\EditInstance" if you wish to change an instance that already exists.
+%
+% \subsection{Small changes to an instance}
+%
+% When a designer creates an instance but the user wishes to slightly tweak
+% it, it is convenient to not have to reset all of the (possibly many)
+% parameters defining that instance and only override the specific parameter
+% that should be changed.
+% \begin{function}{\EditInstance|\EditCollectionInstance}
+% \par
+% \begin{syntax}
+% "\EditInstance" \Arg{object type} \Arg{instance} \Arg{new parameters}
+% "\EditCollectionInstance" \Arg{object type} \Arg{collection} \Arg{instance}\\\hfill \Arg{template} \Arg{new parameters}
+% \end{syntax}
+% These functions change the key settings of an instance of an object
+% type. If the instance was derived from a template, this information
+% is used to find the correct keys to use for the editing process.
+% It may be convenient to use "\ShowInstanceValues" to inspect the values
+% used to set the keys originally.
+% \end{function}
+%
+%
+% \subsection{Parameters evaluated now}
+%
+% \begin{function}{\EvaluateNow}
+% \begin{syntax}
+% "\EvaluteNow" \Arg{expression}
+% \end{syntax}
+% The standard method when creating an instance from a template is to
+% evaluate the <expression> when the instance is used. However, it may
+% be desirable to calculate the value when declared, which can be
+% forced using \cs{EvaluateNow}. Currently, this functionality is
+% regarded as experimental: the team have not found an example where it
+% is actually needed, and so it may be dropped \emph{if} no good
+% examples are suggested!
+% \end{function}
+%
+%
+% \subsection{Setting one key to the value of another}
+%
+% It is often useful to use the value of one key as the default for another.
+% \begin{function}{\KeyValue}
+% \begin{syntax}
+% "\KeyValue" \Arg{key name}
+% \end{syntax}
+% This command is used as the argument to an instance key; it will set that
+% key to the value of <key name> each time the instance is executed at run-time.
+% Using \cs{KeyValue} means that the designer does not need to know
+% how a particular key has been implemented.
+% \end{function}
+%
+% \subsection{When template parameters should be frozen}
+%
+% A class designer may be inheriting templates declared by someone else,
+% either third-party code or the \LaTeX\ kernel itself. Sometimes these
+% templates will be overly general for the purposes of the document. The user
+% should be able to customise parts of the template instances, but otherwise
+% be restricted to only those parameters allowed by the designer.
+%
+% "\DeclareRestrictedTemplate" creates a derived version of a template for
+% which certain parameters are frozen as specified but the remaining parameters are
+% available to be set as usual in an instance declaration.
+%
+% \begin{function}{\DeclareRestrictedTemplate}
+% \par
+% \begin{syntax}
+% |\DeclareRestrictedTemplate| \Arg{object type} \Arg{parent} \Arg{new template} \Arg{frozen parameters}
+% \end{syntax}
+% Defines <new template> based on template <parent> (of certain <object type>)
+% with certain keys set and frozen as defined in <keyvals>.
+% \end{function}
+%
+% \section{Getting information about templates and instances}
+%
+% \begin{function}{
+% \ShowTemplateCode |
+% \ShowTemplateDefaults |
+% \ShowTemplateKeytypes |
+% \ShowTemplateVariables }
+%
+% \begin{syntax}
+% "\ShowTemplateCode" \Arg{object type} \Arg{template}
+% \end{syntax}
+% These functions pause the typesetting and display
+% in the console the various pieces of information for a template.
+% \end{function}
+%
+% \begin{function}{ \ShowInstanceValues | \ShowCollectionInstanceValues }
+%
+% \begin{syntax}
+% "\ShowInstanceValues" \Arg{object type} \Arg{instance}
+% "\ShowCollectionInstanceValues" \Arg{object type} \Arg{collection} \Arg{instance}
+% \end{syntax}
+% These functions pause the typesetting and display in the console
+% information about an instance or a collection instance.
+% \end{function}
+%
+% Note that \pkg{xtemplate} uses various special key names internally.
+% These all contain a space when stored (which normal keys do not:
+% spaces are removed). The same applies to choices: these are stored
+% internally as \texttt{\meta{key}~\meta{choice}}. These will show up
+% when using the \cs{Show\ldots} functions. The design means that
+% there is no danger of a clash between user keys and internal keys.
+% Also, standard keys are stored with all letters detokenized, whereas
+% the special keys use letters with category code $11$ (letter), again
+% to avoid any issues.
+%
+% \section{Examples}
+%
+% (Nothing here yet.)
+%
+%\section{Code documentation}
+%
+%\subsection{Variables and constants}
+%
+%\begin{variable}{
+% \c_xtemplate_code_root_tl |
+% \c_xtemplate_defaults_root_tl |
+% \c_xtemplate_instances_root_tl |
+% \c_xtemplate_keytypes_root_tl |
+% \c_xtemplate_restrict_root_tl |
+% \c_xtemplate_values_root_tl |
+% \c_xtemplate_vars_root_tl |
+%}
+% A number of pieces of code and lists of properties have to be stored
+% for templates and instances. The various csname roots are set up as
+% token lists to avoid use of the literal text in the code.
+%\end{variable}
+%
+%\begin{variable}{\c_xtemplate_key_order_tl}
+% The order keys are declared in must be stored (as property lists
+% have no `order'). The special property used is named here.
+%\end{variable}
+%
+%\begin{variable}{\c_xtemplate_keytypes_arg_clist}
+% Some keytypes (such as \texttt{instance}) need additional
+% information, given as an argument. The list of keytypes that need this
+% extra data is set up here, for later use when splitting things.
+%\end{variable}
+%
+%\begin{variable}{\g_xtemplate_object_type_prop}
+% For tracking which object types have been declared, and the number
+% of arguments each requires.
+%\end{variable}
+%
+%\begin{variable}{\l_xtemplate_assignments_toks}
+% This token register is used in two places. First, it is where the
+% list of assignments for an instance is constructed during
+% \cs{DeclareInstance}. Second, it is where these are copied to to
+% allow \cs{AssignTemplateKeys} to work correctly.
+%\end{variable}
+%
+%\begin{variable}{\l_xtemplate_collection_tl}
+% The name of the current instance collection active. If no collection
+% is in use, this will simply be empty.
+%\end{variable}
+%
+%\begin{variable}{\l_xtemplate_collections_prop}
+% Records the collection in force for each object type.
+%\end{variable}
+%
+%\begin{variable}{
+% \l_xtemplate_default_tl |
+% \l_xtemplate_key_name_tl |
+% \l_xtemplate_keytype_tl |
+% \l_xtemplate_keytype_arg_tl |
+% \l_xtemplate_value_tl |
+% \l_xtemplate_var_tl |
+%}
+% When processing keys, various properties for the current key need to
+% be available. These are copied from the property list to appropriately
+% named token lists, and back again, as needed.
+%\end{variable}
+%
+%\begin{variable}{\l_xtemplate_error_bool}
+% Used to indicate an error when parsing a key list, so that further
+% processing can be abandoned.
+%\end{variable}
+%
+%\begin{variable}{\l_xtemplate_global_bool}
+% When actually assigning data to variables, a check is made to see
+% if this should be global. The flag here is used to indicate this.
+%\end{variable}
+%
+%\begin{variable}{\l_xtemplate_key_seq}
+% The order in which keys are defined is stored here for later
+% recovery and use. It is transferred into the property list for the
+% template when the template is saved.
+%\end{variable}
+%
+%\begin{variable}{\l_xtemplate_restrict_bool}
+% Flag used when editing templates, so that simple editing and
+% restricting can share the same underlying editing method.
+%\end{variable}
+%
+%\begin{variable}{
+% \l_xtemplate_restricted_clist |
+% \l_xtemplate_keytypes_prop |
+% \l_xtemplate_values_prop |
+% \l_xtemplate_vars_prop |
+%}
+% To avoid needing to refer to the data about a template or instance
+% by csname in a large number of locations, the data is copied to these
+% scratch variables and back again for processing. This makes the code
+% easier to follow.
+%\end{variable}
+%
+%\begin{variable}{
+% \l_xtemplate_tmp_clist |
+% \l_xtemplate_tmp_dim |
+% \l_xtemplate_tmp_int |
+% \l_xtemplate_tmp_skip |
+% \l_xtemplate_tmp_tl |
+%}
+% Used when carrying out assignments, as the pre-processing can take
+% place here before passing data through to the storage area defined
+% by the implementation part of a template. The token list is also used
+% for general scratch purposes by \pkg{xtemplate}.
+%\end{variable}
+%
+%\begin{variable}{\l_xtemplate_restrict_bool}
+% Flag used when editing templates, so that simple editing and
+% restricting can share the same underlying editing method.
+%\end{variable}
+%
+%\subsection{Execute or error functions}
+%
+% These all either execute code (if the tests are true) or issue
+% errors (if the test fails).
+%
+%\begin{function}{\xtemplate_execute_if_arg_agree:nnT}
+% \begin{syntax}
+% "\xtemplate_execute_if_arg_agree:nnT" \marg{type} \marg{num}
+% ~~~~\marg{true code}
+% \end{syntax}
+% Tests if the number of arguments required by <type> is equal
+% to <num>, then executes either <true code> or generates an error as
+% appropriate.
+%\end{function}
+%
+%\begin{function}{\xtemplate_execute_if_code_exist:nnT}
+% \begin{syntax}
+% "\xtemplate_execute_if_code_exist:nnT" \marg{type} \marg{template}
+% ~~~~\marg{true code}
+% \end{syntax}
+% Tests if <template> of <type> has been defined (i.e., the code has
+% been created for an implementation), then executes either
+% <true code> or generates an error as appropriate.
+%\end{function}
+%
+%\begin{function}{
+% \xtemplate_execute_if_keytype_exist:nT |
+% \xtemplate_execute_if_keytype_exist:VT
+%}
+% \begin{syntax}
+% "\xtemplate_execute_if_keytype_exist:nT" \marg{keytype}
+% ~~~~\marg{true code}
+% \end{syntax}
+% Tests if <keytype> is a known keytype, then executes either
+% <true code> or generates an error as appropriate.
+%\end{function}
+%
+%\begin{function}{\xtemplate_execute_if_type_exist:nT}
+% \begin{syntax}
+% "\xtemplate_if_type_exist:nT" \marg{type} \marg{true code}
+% \end{syntax}
+% Tests if template <type> has been created, then executes either
+% <true code> or generates an error as appropriate.
+%\end{function}
+%
+%\begin{function}{\xtemplate_execute_if_keys_exist:nnT}
+% \begin{syntax}
+% "\xtemplate_if_keys_exist:nnT" \marg{type} \marg{template}
+% ~~~~\marg{true code}
+% \end{syntax}
+% Tests if keys for <template> of <type> have been declared (but
+% not necessarily given an implementation), , then executes either
+% <true code> or generates an error as appropriate.
+%\end{function}
+%
+%\subsection{Utility functions}
+%
+%\begin{function}{
+% \xtemplate_if_key_value:nT / (EXP) |
+% \xtemplate_if_key_value:VT / (EXP)
+%}
+% \begin{syntax}
+% "\xtemplate_if_key_value:nT" \marg{tokens} \marg{true code}
+% \end{syntax}
+% Tests if the first token in <tokens> is \cs{KeyValue}.
+%\end{function}
+%
+%\begin{function}{\xtemplate_if_eval_now:nTF / (EXP)}
+% \begin{syntax}
+% "\xtemplate_if_eval_now:nTF" \marg{tokens}
+% ~~~~\marg{true code} \marg{false code}
+% \end{syntax}
+% Tests if the first token in <tokens> is a marker for evaluating
+% now (\cs{EvaluateNow}).
+%\end{function}
+%
+%\begin{function}{\xtemplate_if_instance_exist:nnn / (TF) (EXP)}
+% \begin{syntax}
+% "\xtemplate_if_instance_exist:nnnTF" \marg{type}
+% ~~~~\marg{collection} \marg{instance} \marg{true code}
+% \marg{false code}
+% \end{syntax}
+% Tests if <instance> of <type> exists for the <collection> given.
+%\end{function}
+%
+%\begin{function}{\xtemplate_if_use_template:nTF / (EXP)}
+% \begin{syntax}
+% "\xtemplate_if_use_template:nTF" \marg{assignment}
+% ~~~~\marg{true code} \marg{false code}
+% \end{syntax}
+% Tests if {assignment} begins with \cs{UseTemplate}.
+%\end{function}
+%
+%\begin{function}{
+% \xtemplate_store_defaults:n |
+% \xtemplate_store_keytypes:n |
+% \xtemplate_store_restrictions:n |
+% \xtemplate_store_values:n |
+% \xtemplate_store_vars:n |
+%}
+% \begin{syntax}
+% "\xtemplate_store_defaults:n" \marg{full name}
+% \end{syntax}
+% These functions copy information about the current template or
+% instance from the scratch variables to those for storing the
+% information. The <full name> of the instance or template is needed:
+% this includes the <type> and <collection> (if applicable).
+%\end{function}
+%
+%\begin{function}{
+% \xtemplate_recover_defaults:n |
+% \xtemplate_recover_keytypes:n |
+% \xtemplate_recover_restrictions:n |
+% \xtemplate_recover_values:n |
+% \xtemplate_recover_vars:n |
+%}
+% \begin{syntax}
+% "\xtemplate_recover_defaults:n" \marg{full name}
+% \end{syntax}
+% The reverse of the \texttt{store} functions, these functions copy
+% data from the storage areas to the scratch variables for use in the
+% module. Again, the <full name> is needed, including the <type>.
+%\end{function}
+%
+%\subsection{Creating object types}
+%
+%\begin{function}{\xtemplate_declare_object_type:nn}
+% \begin{syntax}
+% "\xtemplate_declare_object_type:nn" \marg{type} \marg{num}
+% \end{syntax}
+% Declares <type> of object, to accept <num> arguments.
+%\end{function}
+%
+%\subsection{Declaring template keys}
+%
+%\begin{function}{\xtemplate_declare_template_keys:nnnn}
+% \begin{syntax}
+% "\xtemplate_declare_template_keys:nnnn" \marg{type}
+% ~~~~\marg{template} \marg{num} \marg{keyvals}
+% \end{syntax}
+% Declares <template> of <type>, and accepting <num> arguments, with
+% key types and default values defined by <keyvals>.
+%\end{function}
+%
+%\begin{function}{
+% \xtemplate_parse_keys_elt:n |
+% \xtemplate_parse_keys_elt:nn
+%}
+% \begin{syntax}
+% "\xtemplate_parse_keys_elt:nn" \marg{key} \marg{value}
+% \end{syntax}
+% Functions used to process each key--value pair when declaring
+% keys from <keyvals>.
+%\end{function}
+%
+%\begin{function}{\xtemplate_split_keytype:n}
+% \begin{syntax}
+% "\xtemplate_split_keytype:n" \marg{key}
+% \end{syntax}
+% Splits a <key> into a key name (stored as \cs{l_xtemplate_key_tl})
+% and a keytype (stored as \cs{l_xtemplate_keytype_tl}).
+%\end{function}
+%
+%\begin{function}{
+% \xtemplate_split_keytype_arg:n |
+% \xtemplate_split_keytype_arg:V
+%}
+% \begin{syntax}
+% "\xtemplate_split_keytype_arg:n" \marg{keytype}
+% \end{syntax}
+% Splits a <keytype> into the type itself and any optional qualifying
+% text. The results are stored in \cs{l_xtemplate_keytype_tl} and
+% \cs{l_xtemplate_keytype_arg_tl}.
+%\end{function}
+%
+%\subsection{Storing defaults and values}
+%
+%\begin{function}{
+% \xtemplate_store_value_boolean:n |
+% \xtemplate_store_value_choice:n |
+% \xtemplate_store_value_choice:V |
+% \xtemplate_store_value_code:n |
+% \xtemplate_store_value_commalist:n |
+% \xtemplate_store_value_function:n |
+% \xtemplate_store_value_function:n |
+% \xtemplate_store_value_instance:n |
+% \xtemplate_store_value_tokenlist:n |
+% \xtemplate_store_value_integer:n |
+% \xtemplate_store_value_length:n |
+% \xtemplate_store_value_skip:n |
+%}
+% \begin{syntax}
+% "\xtemplate_store_value_boolean:n" \marg{value}
+% \end{syntax}
+% Store values of the given keytype for later assignment to variables.
+% For the numeric and Boolean data types, the value is evaluated
+% at this stage unless \cs{DelayEvaluation} or \cs{KeyValue} are
+% used in the <value>.
+%\end{function}
+%
+%\begin{function}{\xtemplate_store_value_choice_name:n}
+% \begin{syntax}
+% "\xtemplate_store_value_choice_name:n" \marg{value}
+% \end{syntax}
+% Stores the name of a choice for a multiple choice key, which will
+% be turned into an implementation when code is available.
+%\end{function}
+%
+%\subsection{Implementing templates}
+%
+%\begin{function}{\xtemplate_declare_template_code:nnnnn}
+% \begin{syntax}
+% "\xtemplate_declare_template_code:nnnnn" \marg{type}
+% ~~~~\marg{template} \marg{num} \marg{keyvals} \marg{code}
+% \end{syntax}
+% Declares implementation of <template> of <type>, and accepting <num>
+% arguments, with keys implemented as listed in <keyvals> and with
+% <code> to be executed when the <template> is used.
+%\end{function}
+%
+%\begin{function}{\xtemplate_store_key_implementation:nnn}
+% \begin{syntax}
+% "\xtemplate_store_key_implementation:nnn" \marg{type}
+% ~~~~\marg{template} \marg{keyvals}
+% \end{syntax}
+% Stores the implementation for keys as specified in <keyvals> for
+% a <template> of <type>.
+%\end{function}
+%
+%\begin{function}{
+% \xtemplate_parse_vars_elt:n |
+% \xtemplate_parse_vars_elt:nn
+%}
+% \begin{syntax}
+% "\xtemplate_parse_vars_elt:nn" \marg{key} \marg{variable}
+% \end{syntax}
+% Used by the key--value parser to assign a <variable> for each
+% <key> listed.
+%\end{function}
+%
+%
+%\begin{function}{\xtemplate_store_key_implementation:nnn}
+% \begin{syntax}
+% "\xtemplate_store_key_implementation:nnn" \marg{type}
+% ~~~~\marg{template} \marg{keyvals}
+% \end{syntax}
+% Stores the implementation for keys as specified in <keyvals> for
+% a <template> of <type>.
+%\end{function}
+%
+%\begin{function}{\xtemplate_implement_choices:n}
+% \begin{syntax}
+% "\xtemplate_implement_choices:n" {key--value list}
+% \end{syntax}
+% Master function for turning <key-value lsit> into a set of choices.
+%\end{function}
+
+%
+%\begin{function}{
+% \xtemplate_implement_choice_elt:n |
+% \xtemplate_implement_choice_elt:nn
+%}
+% \begin{syntax}
+% "\xtemplate_implement_choice_elt:nn" \marg{choice} \marg{code}
+% \end{syntax}
+% Used by the key--value parser to convert a key--value list of
+% choices and code into working multiple choice values.
+%\end{function}
+%
+%\subsection{Modifying templates}
+%
+%\begin{function}{\xtemplate_declare_restricted:nnnn}
+% \begin{syntax}
+% "\xtemplate_declare_restricted:nnnn" \marg{type} \marg{parent}
+% ~~~~\marg{restricted} \marg{keyvals}
+% \end{syntax}
+% Creates <restricted> template of <type> based on <parent> by fixing
+% values as listed in <keyvals>.
+%\end{function}
+%
+%\begin{function}{\xtemplate_edit_defaults:nnn}
+% \begin{syntax}
+% "\xtemplate_edit_defaults:nnn" \marg{type} \marg{template}
+% ~~~~\marg{keyvals}
+% \end{syntax}
+% Modifies the default values for <template> of <type> as instructed
+% in <keyvals>.
+%\end{function}
+%
+%\begin{function}{\xtemplate_parse_values:nn}
+% \begin{syntax}
+% "\xtemplate_parse_values:nn" \marg{name} \marg{keyvals}
+% \end{syntax}
+% Parses <keyvals> for full <name>, finding the value for each key
+% and storing it for later assignment.
+%\end{function}
+%
+%\begin{function}{
+% \xtemplate_parse_values_elt:n |
+% \xtemplate_parse_values_elt:nn
+%}
+% \begin{syntax}
+% "\xtemplate_parse_values_elt:nn" \marg{key} \marg{variable}
+% \end{syntax}
+% Used by the key--value parser to find <value> to assing to
+% implementation of <key>.
+%\end{function}
+%
+%\begin{function}{\xtemplate_set_template_eq:nn}
+% \begin{syntax}
+% "\xtemplate_set_template_eq:nn" \marg{copy} \marg{parent}
+% \end{syntax}
+% Copies all of <parent> template to the <copy>, where both are full
+% names (i.e., a template plus type).
+%\end{function}
+%
+%\subsection{Creating instances}
+%
+%\begin{function}{\xtemplate_declare_instance:nnnnn}
+% \begin{syntax}
+% "\xtemplate_declare_instance:nnnnn" \marg{type} \marg{template}
+% ~~~~\marg{collection} \marg{instance} \marg{keyvals}
+% \end{syntax}
+% Declares an <instance> (within <collection>) of <template> of <type>,
+% using <keyvals> to define the instance.
+%\end{function}
+%
+%\begin{function}{\xtemplate_edit_instance:nnnn}
+% \begin{syntax}
+% "\xtemplate_declare_instance:nnnn" \marg{type} \marg{collection}
+% ~~~~\marg{instance} \marg{keyvals}
+% \end{syntax}
+% Modifies an <instance> (within <collection>) of <type>, using
+% <keyvals> to modify the instance.
+%\end{function}
+%
+%\begin{function}{\xtemplate_convert_to_assignments:}
+% \begin{syntax}
+% "\xtemplate_convert_to_assignments:"
+% \end{syntax}
+% Converts the contents of the various scratch property lists into
+% a list of variable assignments in \cs{l_xtemplate_assignments_toks}.
+%\end{function}
+%
+%\begin{function}{\xtemplate_find_global:}
+% \begin{syntax}
+% "\xtemplate_find_global:"
+% \end{syntax}
+% Checks in \cs{l_xtemplate_var_tl} for the special text
+% \texttt{global}, which is removed from the variable is found. The
+% flag \cs{l_xtemplate_global_bool} is then set as appropriate.
+%\end{function}
+%
+%\subsection{Converting values to assignments}
+%
+%\begin{function}{
+% \xtemplate_assign_boolean: |
+% \xtemplate_assign_choice: |
+% \xtemplate_assign_code: |
+% \xtemplate_assign_code:n |
+% \xtemplate_assign_commalist: |
+% \xtemplate_assign_function: |
+% \xtemplate_assign_instance: |
+% \xtemplate_assign_integer: |
+% \xtemplate_assign_length: |
+% \xtemplate_assign_skip: |
+% \xtemplate_assign_tokenlist:
+%}
+% \begin{syntax}
+% "\xtemplate_assign_boolean:"
+% \end{syntax}
+% Convert the given <keytype> of <key> into an assignment to a
+% <variable>.
+%\end{function}
+%
+%\begin{function}{\xtemplate_assign_variable:N}
+% \begin{syntax}
+% "\xtemplate_assign_variable:N" <function>
+% \end{syntax}
+% Convert the current contents of \cs{l_xtemplate_value_tl} into an
+% assignment using <function> to the variable named in
+% \cs{l_xtemplate_var_tl}.
+%\end{function}
+%
+%\begin{function}{\xtemplate_key_to_value:}
+% \begin{syntax}
+% "\xtemplate_key_to_value:"
+% \end{syntax}
+% Converts an attribute named using \cs{KeyValue} into the
+% value of the underlying implementation variable.
+%\end{function}
+%
+%\subsection{Using instances}
+%
+%\begin{function}{\xtemplate_use_instance:nn}
+% \begin{syntax}
+% "\xtemplate_use_instance:nn" \marg{type} \marg{instance}
+% \end{syntax}
+% Executes code stored for <instance> of <type>, taking account of
+% any active collection.
+%\end{function}
+%
+%\begin{function}{\xtemplate_use_template:nnn}
+% \begin{syntax}
+% "\xtemplate_use_template:nnn" \marg{type} \marg{template}
+% ~~~~\marg{settings}
+% \end{syntax}
+% Executes code stored for <template> of <type> using <settings>.
+%\end{function}
+%
+%\begin{function}{\xtemplate_use_collection:nn}
+% \begin{syntax}
+% "\xtemplate_use_collection:nn" \marg{type} \marg{collection}
+% \end{syntax}
+% Activates <collection> for instances of \marg{type}.
+%\end{function}
+%
+%\begin{function}{\xtemplate_get_collection:n}
+% \begin{syntax}
+% "\xtemplate_get_collection:n" \marg{type}
+% \end{syntax}
+% Sets \cs{l_xtemplate_collection_tl} to the name of the collection
+% in force for templates of <type>.
+%\end{function}
+%
+%\begin{function}{\xtemplate_assignments_pop:}
+% \begin{syntax}
+% "\xtemplate_assignments_pop:"
+% \end{syntax}
+% Pops \cs{l_xtemplate_assignment_toks}, and therefore executes
+% the assignements stored there.
+%\end{function}
+%
+%\begin{function}{\xtemplate_assignments_push:n}
+% \begin{syntax}
+% "\xtemplate_assignments_push:n" \marg{assignments}
+% \end{syntax}
+% Pushes <assignments> to \cs{l_xtemplate_assignment_toks} for later
+% execution.
+%\end{function}
+%
+%\subsection{Showing details}
+%
+%\begin{function}{\xtemplate_show_code:nn}
+% \begin{syntax}
+% "\xtemplate_show_code:nn" \marg{type} \marg{template}
+% \end{syntax}
+% Shows code associated with <template> of <type>.
+%\end{function}
+%
+%\begin{function}{\xtemplate_show_code:nn}
+% \begin{syntax}
+% "\xtemplate_show_code:nn" \marg{type} \marg{template}
+% \end{syntax}
+% Shows code associated with <template> of <type>.
+%\end{function}
+%
+%\begin{function}{\xtemplate_show_defaults:nn}
+% \begin{syntax}
+% "\xtemplate_show_default:nn" \marg{type} \marg{template}
+% \end{syntax}
+% Shows default values associated with <template> of <type>.
+%\end{function}
+%
+%\begin{function}{\xtemplate_show_keytypes:nn}
+% \begin{syntax}
+% "\xtemplate_show_keytypes:nn" \marg{type} \marg{template}
+% \end{syntax}
+% Shows key types associated with <template> of <type>.
+%\end{function}
+%
+%\begin{function}{\xtemplate_show_values:nnn}
+% \begin{syntax}
+% "\xtemplate_show_code:nnn" \marg{type} \marg{collection}
+% ~~~~\marg{instance}
+% \end{syntax}
+% Shows values associated with <instance> of <type> within
+% <collection>.
+%\end{function}
+%
+
+%\begin{function}{\xtemplate_show_vars:nn}
+% \begin{syntax}
+% "\xtemplate_show_vars:nn" \marg{type} \marg{template}
+% \end{syntax}
+% Shows variables associated with <template> of <type>.
+%\end{function}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+%\section{Implementation}
+%
+% \pkg{xtemplate} only needs \pkg{expl3}; in format mode, this can be
+% skipped.
+% \begin{macrocode}
+%<*package>
+\ProvidesExplPackage
+ {\filename}{\filedate}{\fileversion}{\filedescription}
+\RequirePackage{expl3}
+%</package>
+%<*initex|package>
+% \end{macrocode}
+%
+%\subsubsection{Variables and constants}
+%
+%\begin{macro}{\c_xtemplate_code_root_tl}
+%\begin{macro}{\c_xtemplate_defaults_root_tl}
+%\begin{macro}{\c_xtemplate_instances_root_tl}
+%\begin{macro}{\c_xtemplate_keytypes_root_tl}
+%\begin{macro}{\c_xtemplate_restrict_root_tl}
+%\begin{macro}{\c_xtemplate_values_root_tl}
+%\begin{macro}{\c_xtemplate_vars_root_tl}
+% So that literal values are kept to a minimum.
+% \begin{macrocode}
+\tl_new:Nn \c_xtemplate_code_root_tl { xtemplate_code > }
+\tl_new:Nn \c_xtemplate_defaults_root_tl { xtemplate_defaults > }
+\tl_new:Nn \c_xtemplate_instances_root_tl { xtemplate_instances > }
+\tl_new:Nn \c_xtemplate_keytypes_root_tl { xtemplate_keytypes > }
+\tl_new:Nn \c_xtemplate_restrict_root_tl { xtemplate_restrict > }
+\tl_new:Nn \c_xtemplate_values_root_tl { xtemplate_values > }
+\tl_new:Nn \c_xtemplate_vars_root_tl { xtemplate_vars > }
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\c_xtemplate_key_order_tl}
+% A special property name, used to store the order keys are defined
+% in.
+% \begin{macrocode}
+\tl_new:Nn \c_xtemplate_key_order_tl { key~order }
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\c_xtemplate_keytypes_arg_clist}
+% A list of keytypes which also need additional data (an argument), used
+% to parse the keytype correctly.
+% \begin{macrocode}
+\clist_new:N \c_xtemplate_keytypes_arg_clist
+\clist_put_right:Nn \c_xtemplate_keytypes_arg_clist { choice }
+\clist_put_right:Nn \c_xtemplate_keytypes_arg_clist { function }
+\clist_put_right:Nn \c_xtemplate_keytypes_arg_clist { instance }
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\g_xtemplate_object_type_prop}
+% For storing types and the associated number of arguments.
+% \begin{macrocode}
+\prop_new:N \g_xtemplate_object_type_prop
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\l_xtemplate_assignments_toks}
+% When creating an instance, the assigned values are collected here. A
+% toks is needed as there can be |#| tokens.
+% \begin{macrocode}
+\toks_new:N \l_xtemplate_assignments_toks
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\l_xtemplate_collection_tl}
+% The current instance collection name is stored here.
+% \begin{macrocode}
+\tl_new:N \l_xtemplate_collection_tl
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\l_xtemplate_collections_prop}
+% Lists current collection in force, indexed by object type.
+% \begin{macrocode}
+\prop_new:N \l_xtemplate_collections_prop
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\l_xtemplate_default_tl}
+% The default value for a key is recovered here from the property list
+% in which it is stored. The internal implementation of property lists
+% means that this is safe even with un-escaped |#| tokens.
+% \begin{macrocode}
+\tl_new:N \l_xtemplate_default_tl
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\l_xtemplate_error_bool}
+% A flag for errors to be carried forward.
+% \begin{macrocode}
+\bool_new:N \l_xtemplate_error_bool
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\l_xtemplate_global_bool}
+% Used to indicate that assignments should be global.
+% \begin{macrocode}
+\bool_new:N \l_xtemplate_global_bool
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\l_xtemplate_restrict_bool}
+% A flag to indicate that a template is being restricted.
+% \begin{macrocode}
+\bool_new:N \l_xtemplate_restrict_bool
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\l_xtemplate_restricted_clist}
+% A scratch list for restricting templates.
+% \begin{macrocode}
+\clist_new:N \l_xtemplate_restricted_clist
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\l_xtemplate_key_name_tl}
+%\begin{macro}{\l_xtemplate_keytype_tl}
+%\begin{macro}{\l_xtemplate_keytype_arg_tl}
+%\begin{macro}{\l_xtemplate_value_tl}
+%\begin{macro}{\l_xtemplate_var_tl}
+% When defining each key in a template, the name and type of the key
+% need to be separated and stored. Any argument needed by the
+% keytype is also stored separately.
+% \begin{macrocode}
+\tl_new:N \l_xtemplate_key_name_tl
+\tl_new:N \l_xtemplate_keytype_tl
+\tl_new:N \l_xtemplate_keytype_arg_tl
+\tl_new:N \l_xtemplate_value_tl
+\tl_new:N \l_xtemplate_var_tl
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\l_xtemplate_key_seq}
+% The order that keys are declared needs to be know, so that they can
+% be set in the same way. As property lists are not ordered data types,
+% a separate list needs to be kept which \emph{is} ordered. This will
+% then be stored in the property list.
+% \begin{macrocode}
+\seq_new:N \l_xtemplate_key_seq
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\l_xtemplate_keytypes_prop}
+%\begin{macro}{\l_xtemplate_values_prop}
+%\begin{macro}{\l_xtemplate_vars_prop}
+% To avoid needing too many difficult-to-follow csname assignments,
+% various scratch token registers are used to build up data, which is
+% then transferred
+% \begin{macrocode}
+\prop_new:N \l_xtemplate_keytypes_prop
+\prop_new:N \l_xtemplate_values_prop
+\prop_new:N \l_xtemplate_vars_prop
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\l_xtemplate_tmp_clist}
+%\begin{macro}{\l_xtemplate_tmp_dim}
+%\begin{macro}{\l_xtemplate_tmp_int}
+%\begin{macro}{\l_xtemplate_tmp_skip}
+% For pre-processing the data stored by \pkg{xtemplate}, a number of
+% scratch variables are needed. The assignments are made to these in the
+% first instance, unless evaluation is delayed.
+% \begin{macrocode}
+\clist_new:N \l_xtemplate_tmp_clist
+\dim_new:N \l_xtemplate_tmp_dim
+\int_new:N \l_xtemplate_tmp_int
+\skip_new:N \l_xtemplate_tmp_skip
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\l_xtemplate_tmp_tl}
+% A scratch variable for comparisons and so on.
+% \begin{macrocode}
+\tl_new:N \l_xtemplate_tmp_tl
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\xtemplate_space:}
+% A space!
+% \begin{macrocode}
+\cs_new_eq:NN \xtemplate_space: \iow_space:
+% \end{macrocode}
+%\end{macro}
+%
+%\subsection{Testing existence and validity}
+%
+% There are a number of checks needed for either the existence of
+% a object type, template or instance. There are also some for the
+% validity of a particular call. All of these are collected up here.
+%
+%\begin{macro}{\xtemplate_execute_if_arg_agree:nnT}
+% A test agreement between the number of arguments for the template
+% type and that specified when creating a template. This is not done as a
+% separate conditional for efficiency and better error message
+% \begin{macrocode}
+\cs_new:Npn \xtemplate_execute_if_arg_agree:nnT #1#2#3 {
+ \prop_get:NnN \g_xtemplate_object_type_prop {#1} \l_xtemplate_tmp_tl
+ \intexpr_compare:nTF { #2 = \l_xtemplate_tmp_tl }
+ {#3}
+ {
+ \msg_kernel_error:nnxxx { xtemplate }
+ { argument-number-mismatch } {#1} { \l_xtemplate_tmp_tl } {#2}
+ }
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\xtemplate_execute_if_code_exist:nnT}
+% A template is only fully declared if the code has been set up,
+% which can be checked by looking for the template function itself.
+% \begin{macrocode}
+\cs_new:Npn \xtemplate_execute_if_code_exist:nnT #1#2#3 {
+ \cs_if_exist:cTF { \c_xtemplate_code_root_tl #1 / #2 :w }
+ {#3}
+ {
+ \msg_kernel_error:nnxx { xtemplate } { no-template-code }
+ {#1} {#2}
+ }
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\xtemplate_execute_if_keytype_exist:nT}
+%\begin{macro}{\xtemplate_execute_if_keytype_exist:VF}
+% The test for valid keytypes looks for a function to set up the key,
+% which is part of the `code' side of the template definition. This
+% avoids having different lists for the two parts of the process.
+% \begin{macrocode}
+\cs_new:Npn \xtemplate_execute_if_keytype_exist:nT #1#2 {
+ \cs_if_exist:cTF { xtemplate_store_value_ #1 :n }
+ {#2}
+ { \msg_kernel_error:nnx { xtemplate } { unknown-keytype } {#1} }
+}
+\cs_generate_variant:Nn \xtemplate_execute_if_keytype_exist:nT { V }
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\xtemplate_execute_if_type_exist:nT}
+% To check that a particular object type is valid.
+% \begin{macrocode}
+\cs_new:Npn \xtemplate_execute_if_type_exist:nT #1#2 {
+ \prop_if_in:NnTF \g_xtemplate_object_type_prop {#1}
+ {#2}
+ { \msg_kernel_error:nnx { xtemplate } { unknown-object-type } {#1} }
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\xtemplate_execute_if_keys_exist:nnT}
+% To check that the keys for a template have been set up before trying
+% to create any code, a simple check for the correctly-named keytype
+% property list.
+% \begin{macrocode}
+\cs_new:Npn \xtemplate_if_keys_exist:nnT #1#2#3 {
+ \cs_if_exist:cTF
+ { g_ \c_xtemplate_keytypes_root_tl #1 / #2 _prop }
+ {#3}
+ {
+ \msg_kernel_error:nnxx { xtemplate } { unknown-template }
+ {#1} {#2}
+ }
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\xtemplate_if_key_value:nT}
+%\begin{macro}{\xtemplate_if_key_value:VT}
+% Tests for the first token in a string being \cs{KeyValue}, where
+% \cs{DelayEvaluation} is not important.
+% \begin{macrocode}
+\prg_set_conditional:Nnn \xtemplate_if_key_value:n { T } {
+ \tl_if_eq:noTF { \KeyValue } { \tl_head:w #1 \q_nil } {
+ \prg_return_true:
+ }{
+ \prg_return_false:
+ }
+}
+\cs_generate_variant:Nn \xtemplate_if_key_value:nT { V }
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\xtemplate_if_eval_now:nTF}
+% Tests for the first token in a string being \cs{EvaluateNow}.
+% \begin{macrocode}
+\prg_new_conditional:Nnn \xtemplate_if_eval_now:n { TF } {
+ \tl_if_eq:noTF { \EvaluateNow } { \tl_head:w #1 \q_nil } {
+ \prg_return_true:
+ }{
+ \prg_return_false:
+ }
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}[TF]{\xtemplate_if_instance_exist:nnn}
+% Testing for an instance is collection dependent.
+% \begin{macrocode}
+\prg_new_conditional:Nnn \xtemplate_if_instance_exist:nnn { T, F, TF } {
+ \cs_if_exist:cTF { \c_xtemplate_instances_root_tl #1 / #2 / #3 :w } {
+ \prg_return_true:
+ }{
+ \prg_return_false:
+ }
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\xtemplate_if_use_template:nTF}
+% Tests for the first token in a string being \cs{UseTemplate}.
+% \begin{macrocode}
+\prg_new_conditional:Nnn \xtemplate_if_use_template:n { TF } {
+ \tl_if_eq:noTF { \UseTemplate } { \tl_head:w #1 \q_nil } {
+ \prg_return_true:
+ }{
+ \prg_return_false:
+ }
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\subsubsection{Saving and recovering property lists}
+%
+% The various property lists for templates have to be shuffled in
+% and out of storage.
+%
+%\begin{macro}{\xtemplate_store_defaults:n}
+%\begin{macro}{\xtemplate_store_keytypes:n}
+%\begin{macro}{\xtemplate_store_restrictions:n}
+%\begin{macro}{\xtemplate_store_values:n}
+%\begin{macro}{\xtemplate_store_vars:n}
+% The defaults and keytypes are transferred from the scratch property
+% lists to the `proper' lists for the template being created.
+% \begin{macrocode}
+\cs_new:Npn \xtemplate_store_defaults:n #1 {
+ \cs_if_free:cT { g_ \c_xtemplate_defaults_root_tl #1 _prop } {
+ \prop_new:c { g_ \c_xtemplate_defaults_root_tl #1 _prop }
+ }
+ \prop_gset_eq:cN { g_ \c_xtemplate_defaults_root_tl #1 _prop }
+ \l_xtemplate_values_prop
+}
+\cs_new:Npn \xtemplate_store_keytypes:n #1 {
+ \cs_if_free:cTF { g_ \c_xtemplate_keytypes_root_tl #1 _prop } {
+ \msg_kernel_info:nnx { xtemplate } { define-template-interface }
+ {#1}
+ \prop_new:c { g_ \c_xtemplate_keytypes_root_tl #1 _prop }
+ }
+ {
+ \msg_kernel_warning:nnx { xtemplate }
+ { redefine-template-interface } {#1}
+ }
+ \prop_gset_eq:cN { g_ \c_xtemplate_keytypes_root_tl #1 _prop }
+ \l_xtemplate_keytypes_prop
+}
+\cs_new:Npn \xtemplate_store_values:n #1 {
+ \cs_if_free:cT { l_ \c_xtemplate_values_root_tl #1 _prop } {
+ \prop_new:c { l_ \c_xtemplate_values_root_tl #1 _prop }
+ }
+ \prop_set_eq:cN { l_ \c_xtemplate_values_root_tl #1 _prop }
+ \l_xtemplate_values_prop
+}
+\cs_new:Npn \xtemplate_store_restrictions:n #1 {
+ \clist_gset_eq:cN { g_ \c_xtemplate_restrict_root_tl #1 _clist }
+ \l_xtemplate_restrict_clist
+}
+\cs_new:Npn \xtemplate_store_vars:n #1 {
+ \cs_if_free:cTF { g_ \c_xtemplate_vars_root_tl #1 _prop } {
+ \msg_kernel_info:nnx { xtemplate } { define-template-code } {#1}
+ \prop_new:c { g_ \c_xtemplate_vars_root_tl #1 _prop }
+ }
+ {
+ \msg_kernel_warning:nnx { xtemplate } { redefine-template-code }
+ {#1}
+ }
+ \prop_gset_eq:cN { g_ \c_xtemplate_vars_root_tl #1 _prop }
+ \l_xtemplate_vars_prop
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\xtemplate_recover_defaults:n}
+%\begin{macro}{\xtemplate_recover_keytypes:n}
+%\begin{macro}{\xtemplate_recover_restrictions:n}
+%\begin{macro}{\xtemplate_recover_values:n}
+%\begin{macro}{\xtemplate_recover_vars:n}
+% Recovering the stored data for a template is rather less complex
+% than storing it. All that happens is the data is transferred from
+% the permanent to the scratch storage.
+% \begin{macrocode}
+\cs_new:Npn \xtemplate_recover_defaults:n #1 {
+ \prop_set_eq:Nc \l_xtemplate_values_prop
+ { g_ \c_xtemplate_defaults_root_tl #1 _prop }
+}
+\cs_new:Npn \xtemplate_recover_keytypes:n #1 {
+ \prop_set_eq:Nc \l_xtemplate_keytypes_prop
+ { g_ \c_xtemplate_keytypes_root_tl #1 _prop }
+}
+\cs_new:Npn \xtemplate_recover_restrictions:n #1 {
+ \clist_set_eq:Nc \l_xtemplate_restrict_clist
+ { g_ \c_xtemplate_restrict_root_tl #1 _clist }
+}
+\cs_new:Npn \xtemplate_recover_values:n #1 {
+ \prop_set_eq:Nc \l_xtemplate_values_prop
+ { l_ \c_xtemplate_values_root_tl #1 _prop }
+}
+\cs_new:Npn \xtemplate_recover_vars:n #1 {
+ \prop_set_eq:Nc \l_xtemplate_vars_prop
+ { g_ \c_xtemplate_vars_root_tl #1 _prop }
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\subsubsection{Creating new object types}
+%
+%\begin{macro}{\xtemplate_declare_object_type:nn}
+% Although the object type is the `top level' of the template system,
+% it is actually very easy to implement. All that happens is that the
+% number of arguments required is recorded, indexed by the name of the
+% object type.
+% \begin{macrocode}
+\cs_new:Npn \xtemplate_declare_object_type:nn #1#2 {
+ \int_set:Nn \l_xtemplate_tmp_int {#2}
+ \bool_if:nTF {
+ \intexpr_compare_p:n { #2 > \c_nine } ||
+ \intexpr_compare_p:n { #2 < \c_zero }
+ } {
+ \msg_kernel_error:nnxx { xtemplate } { bad-number-of-arguments }
+ {#1} { \exp_not:V \l_xtemplate_tmp_int }
+ }{
+ \prop_if_in:NnTF \g_xtemplate_object_type_prop {#1}
+ {
+ \msg_kernel_warning:nnxx { xtemplate } { redefine-object-type }
+ {#1} {#2}
+ }
+ {
+ \msg_kernel_info:nnxx { xtemplate } { define-object-type }
+ {#1} {#2}
+ }
+ \prop_gput:NnV \g_xtemplate_object_type_prop {#1}
+ \l_xtemplate_tmp_int
+ }
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\subsection{Design part of template declaration}
+%
+% The `design' part of a template declaration defines the general
+% behaviour of each key, and possibly a default value. However, it does
+% not include the implementation. This means that what happens here is
+% the two properties are saved to appropriate lists, which can then
+% be used later to recover the information when implementing the keys.
+%
+%\begin{macro}{\xtemplate_declare_template_keys:nnnn}
+% The main function for the `design' part of creating a template starts
+% by checking that the object type exists and that the number of
+% arguments required agree. If that is all fine, then the two storage
+% areas for defaults and keytypes are initialised. The mechanism is then
+% set up for the \pkg{l3keyval} module to actually parse the keys.
+% Finally, the code hands of to the storage routine to save the parsed
+% information properly.
+% \begin{macrocode}
+\cs_new:Npn \xtemplate_declare_template_keys:nnnn #1#2#3#4 {
+ \xtemplate_execute_if_type_exist:nT {#1}
+ {
+ \xtemplate_execute_if_arg_agree:nnT {#1} {#3}
+ {
+ \prop_clear:N \l_xtemplate_values_prop
+ \prop_clear:N \l_xtemplate_keytypes_prop
+ \seq_clear:N \l_xtemplate_key_seq
+ \cs_set_eq:NN \KV_key_no_value_elt:n \xtemplate_parse_keys_elt:n
+ \cs_set_eq:NN \KV_key_value_elt:nn \xtemplate_parse_keys_elt:nn
+ \KV_parse_space_removal_sanitize:n {#4}
+ \prop_put:NVV \l_xtemplate_keytypes_prop \c_xtemplate_key_order_tl
+ \l_xtemplate_key_seq
+ \xtemplate_store_defaults:n { #1 / #2 }
+ \xtemplate_store_keytypes:n { #1 / #2 }
+ }
+ }
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\xtemplate_parse_keys_elt:n}
+%\begin{macro}[aux]{\xtemplate_parse_keys_elt_aux:n}
+%\begin{macro}[aux]{\xtemplate_parse_keys_elt_aux:}
+% Processing the key part of the key--value pair is always carried out
+% using this function, even if a value was found. First, the key name
+% is separated from the keytype, and if necessary the keytype is
+% separated into two parts. This information is then used to check that
+% the keytype is valid, before storing the keytype (plus argument if
+% necessary) as a property of the key name. The key name is also stored
+% (in braces) in the token list to record the order the keys are defined
+% in.
+% \begin{macrocode}
+\cs_new:Npn \xtemplate_parse_keys_elt:n #1 {
+ \xtemplate_split_keytype:n {#1}
+ \bool_if:NF \l_xtemplate_error_bool
+ {
+ \xtemplate_execute_if_keytype_exist:VT \l_xtemplate_keytype_tl
+ {
+ \clist_map_function:nN { choice , function , instance }
+ \xtemplate_parse_keys_elt_aux:n
+ \bool_if:NF \l_xtemplate_error_bool
+ {
+ \seq_if_in:NVTF \l_xtemplate_key_seq
+ \l_xtemplate_key_name_tl
+ {
+ \msg_kernel_error:nnx { xtemplate }
+ { duplicate-key-interface }
+ { \l_xtemplate_key_name_tl }
+ }
+ { \xtemplate_parse_keys_elt_aux: }
+ }
+ }
+ }
+}
+\cs_new_nopar:Npn \xtemplate_parse_keys_elt_aux:n #1 {
+ \tl_if_eq:VnT \l_xtemplate_keytype_tl {#1} {
+ \tl_if_empty:NT \l_xtemplate_keytype_arg_tl {
+ \msg_kernel_error:nnx { xtemplate }
+ { keytype-requires-argument } {#1}
+ \bool_set_true:N \l_xtemplate_error_bool
+ \clist_map_break:
+ }
+ }
+}
+\cs_new_nopar:Npn \xtemplate_parse_keys_elt_aux: {
+ \tl_set:Nx \l_xtemplate_tmp_tl {
+ \l_xtemplate_keytype_tl
+ \l_xtemplate_keytype_arg_tl
+ }
+ \prop_put:NVV \l_xtemplate_keytypes_prop \l_xtemplate_key_name_tl
+ \l_xtemplate_tmp_tl
+ \seq_put_right:NV \l_xtemplate_key_seq \l_xtemplate_key_name_tl
+ \tl_if_eq:VnT \l_xtemplate_keytype_tl { choice } {
+ \clist_if_in:NnT \l_xtemplate_keytype_arg_tl { unknown } {
+ \msg_kernel_error:nn { xtemplate } { choice-unknown-reserved }
+ }
+ }
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\xtemplate_parse_keys_elt:nn}
+% For keys which have a default, the keytype and key name are first
+% separated out by the \cs{xtemplate_parse_keys_elt:n}
+% routine, before storing the default value in the scratch property list.
+% Choices have special handling as the code is not yet available to
+% actually do the storing!
+% \begin{macrocode}
+\cs_new:Npn \xtemplate_parse_keys_elt:nn #1#2 {
+ \xtemplate_parse_keys_elt:n {#1}
+ \tl_if_eq:VnTF \l_xtemplate_keytype_tl { choice } {
+ \xtemplate_store_value_choice_name:n {#2}
+ }{
+ \use:c { xtemplate_store_value_ \l_xtemplate_keytype_tl :n } {#2}
+ }
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\xtemplate_split_keytype:n}
+%\begin{macro}[aux]{\xtemplate_split_keytype_aux:w}
+% The keytype and key name should be separated by `\texttt{:}'. As the
+% definition might be given inside or outside of a code block, spaces
+% are removed and the category code of colons is standardised. After
+% that, the standard delimited argument method is used to separate the
+% two parts.
+% \begin{macrocode}
+\group_begin:
+\char_set_lccode:nn { `\@ } { `\: }
+\char_make_other:N \@
+\tl_to_lowercase:n {
+ \group_end:
+ \cs_new:Npn \xtemplate_split_keytype:n #1 {
+ \bool_set_false:N \l_xtemplate_error_bool
+ \tl_set:Nn \l_xtemplate_tmpa_tl {#1}
+ \tl_replace_all_in:Nnn \l_xtemplate_tmpa_tl { ~ } { }
+ \tl_replace_all_in:Nnn \l_xtemplate_tmpa_tl { : } { @ }
+ \tl_if_in:VnTF \l_xtemplate_tmpa_tl { @ } {
+ \exp_after:wN \xtemplate_split_keytype_aux:w \l_xtemplate_tmpa_tl
+ \q_stop
+ }{
+ \bool_set_true:N \l_xtemplate_error_bool
+ \msg_kernel_error:nnx { xtemplate } { no-keytype } {#1}
+ }
+ }
+ \cs_new:Npn \xtemplate_split_keytype_aux:w #1 @ #2 \q_stop {
+ \tl_if_empty:nT {#1} {
+ \msg_kernel_error:nnx { xtemplate } { empty-key-name } { @ #2 }
+ }
+ \tl_set:Nx \l_xtemplate_key_name_tl { \tl_to_str:n {#1} }
+ \xtemplate_split_keytype_arg:n {#2}
+ }
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\xtemplate_split_keytype_arg:n}
+%\begin{macro}{\xtemplate_split_keytype_arg:V}
+%\begin{macro}[aux]{\xtemplate_split_keytype_arg_aux:n}
+%\begin{macro}[aux]{\xtemplate_split_keytype_arg_aux:w}
+% The second stage of sorting out the keytype is to check for an
+% argument. As there is no convenient delimiting token to look for,
+% a check is made instead for each possible text value for the keytype.
+% To keep things faster, this only involves the keytypes that need an
+% argument. If a match is made, then a check is also needed to see that
+% it is at the start of the keytype information. All being well, the
+% split can then be applied. Any non-matching keytypes are assumed to
+% be `correct' as given, and are left alone (this is checked by other
+% code).
+% \begin{macrocode}
+\cs_new:Npn \xtemplate_split_keytype_arg:n #1 {
+ \tl_set:Nn \l_xtemplate_keytype_tl {#1}
+ \tl_clear:N \l_xtemplate_keytype_arg_tl
+ \cs_set_nopar:Npn \xtemplate_split_keytype_arg_aux:n ##1 {
+ \tl_if_in:nnT {#1} {##1} {
+ \cs_set:Npn \xtemplate_split_keytype_arg_aux:w
+ ####1 ##1 ####2 \q_stop {
+ \tl_if_empty:nT {####1} {
+ \tl_set:Nn \l_xtemplate_keytype_tl {##1}
+ \tl_set:Nn \l_xtemplate_keytype_arg_tl {####2}
+ \clist_map_break:
+ }
+ }
+ \xtemplate_split_keytype_arg_aux:w #1 \q_stop
+ }
+ }
+ \clist_map_function:NN \c_xtemplate_keytypes_arg_clist
+ \xtemplate_split_keytype_arg_aux:n
+}
+\cs_generate_variant:Nn \xtemplate_split_keytype_arg:n { V }
+\cs_new_nopar:Npn \xtemplate_split_keytype_arg_aux:n #1 { }
+\cs_new_nopar:Npn \xtemplate_split_keytype_arg_aux:w #1 \q_stop { }
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\subsubsection{Storing values}
+%
+% As \pkg{xtemplate} pre-processes key values for efficiency reasons,
+% there is a need to convert the values given as defaults into
+% `ready to use' data. The same general idea is true when an instance
+% is declared. However, assignments are not made until an instance is
+% used, and so there has to be some intermediate storage. Furthermore,
+% the ability to delay evaluation of results is needed. To achieve these
+% aims, a series of `process and store' functions are defined here.
+%
+% All of the information about the key (the key name and the keytype)
+% is already stored as variables. The same property list is always used
+% to store the data, meaning that the only argument required is the
+% value to be processed and potentially stored.
+%
+%\begin{macro}{\xtemplate_store_value_boolean:n}
+% Storing Boolean values requires a test for delayed evaluation, but
+% is different to the various numerical variable types as there are
+% only two possible values to store. So the code here tests the default
+% switch and then records the meaning (either \texttt{true} or
+% \texttt{false}).
+% \begin{macrocode}
+\cs_new:Npn \xtemplate_store_value_boolean:n #1 {
+ \xtemplate_if_eval_now:nTF {#1} {
+ \bool_if:cTF { c_ #1 _bool } {
+ \prop_put:NVn \l_xtemplate_values_prop \l_xtemplate_key_name_tl
+ { true }
+ }{
+ \prop_put:NVn \l_xtemplate_values_prop \l_xtemplate_key_name_tl
+ { false }
+ }
+ }{
+ \prop_put:NVn \l_xtemplate_values_prop \l_xtemplate_key_name_tl {#1}
+ }
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\xtemplate_store_value_choice:n}
+%\begin{macro}{\xtemplate_store_value_choice:V}
+%\begin{macro}[aux]{\xtemplate_store_value_choice_aux:n}
+%\begin{macro}[aux]{\xtemplate_store_value_choice_aux:V}
+%\begin{macro}{\xtemplate_store_value_choice_name:n}
+% Choices are a bit odd, as they have to be handled in two parts. When
+% an interface is being created, the default is stored with a hidden
+% name (using spaces and letter category codes). When a choice is
+% actually being used, there is a check for the choice itself, then
+% code to handle an unknown before issuing an error.
+% \begin{macrocode}
+\cs_new:Npn \xtemplate_store_value_choice:n #1 {
+ \tl_set:Nx \l_xtemplate_tmp_tl
+ { \l_xtemplate_key_name_tl \xtemplate_space: #1 }
+ \prop_if_in:NVTF \l_xtemplate_vars_prop \l_xtemplate_tmp_tl {
+ \xtemplate_store_value_choice_aux:V \l_xtemplate_tmp_tl
+ }{
+ \tl_set:Nx \l_xtemplate_tmp_tl
+ { \l_xtemplate_key_name_tl \xtemplate_space: unknown }
+ \prop_if_in:NVTF \l_xtemplate_vars_prop \l_xtemplate_tmp_tl {
+ \xtemplate_store_value_choice_aux:V \l_xtemplate_tmp_tl
+ }{
+ \prop_get:NVN \l_xtemplate_keytypes_prop \l_xtemplate_key_name_tl
+ \l_xtemplate_tmp_tl
+ \xtemplate_split_keytype_arg:V \l_xtemplate_tmp_tl
+ \msg_kernel_error:nnxxx { xtemplate } { unknown-choice }
+ {#1}
+ { \l_xtemplate_key_name_tl }
+ { \l_xtemplate_keytype_arg_tl }
+ \prop_gdel:NV \l_xtemplate_values_prop \l_xtemplate_key_name_tl
+ }
+ }
+}
+\cs_generate_variant:Nn \xtemplate_store_value_choice:n { V }
+\cs_new:Npn \xtemplate_store_value_choice_aux:n #1 {
+ \prop_get:NnN \l_xtemplate_vars_prop {#1} \l_xtemplate_tmp_tl
+ \prop_put:NVV \l_xtemplate_values_prop \l_xtemplate_key_name_tl
+ \l_xtemplate_tmp_tl
+}
+\cs_generate_variant:Nn \xtemplate_store_value_choice_aux:n { V }
+\cs_new:Npn \xtemplate_store_value_choice_name:n #1 {
+ \tl_set:Nx \l_xtemplate_tmp_tl
+ { \l_xtemplate_key_name_tl \xtemplate_space: default }
+ \prop_put:NVn \l_xtemplate_values_prop \l_xtemplate_tmp_tl {#1}
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\xtemplate_store_value_code:n}
+%\begin{macro}{\xtemplate_store_value_commalist:n}
+%\begin{macro}{\xtemplate_store_value_function:n}
+%\begin{macro}{\xtemplate_store_value_instance:n}
+%\begin{macro}{\xtemplate_store_value_tokenlist:n}
+% With no need to worry about delayed evaluation, these keytypes all
+% just store the input directly.
+% \begin{macrocode}
+\cs_new:Npn \xtemplate_store_value_code:n #1 {
+ \prop_put:NVn \l_xtemplate_values_prop \l_xtemplate_key_name_tl {#1}
+}
+\cs_new:Npn \xtemplate_store_value_commalist:n #1 {
+ \prop_put:NVn \l_xtemplate_values_prop \l_xtemplate_key_name_tl {#1}
+}
+\cs_new:Npn \xtemplate_store_value_function:n #1 {
+ \prop_put:NVn \l_xtemplate_values_prop \l_xtemplate_key_name_tl {#1}
+}
+\cs_new:Npn \xtemplate_store_value_instance:n #1 {
+ \prop_put:NVn \l_xtemplate_values_prop \l_xtemplate_key_name_tl {#1}
+}
+\cs_new:Npn \xtemplate_store_value_tokenlist:n #1 {
+ \prop_put:NVn \l_xtemplate_values_prop \l_xtemplate_key_name_tl {#1}
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\xtemplate_store_value_integer:n}
+%\begin{macro}{\xtemplate_store_value_length:n}
+%\begin{macro}{\xtemplate_store_value_skip:n}
+% Storing the value of a number is in all cases more or less the same.
+% If evaluation is taking place now, assignment is made to a scratch
+% variable, and this result is then stored. On the other hand, if
+% evaluation is delayed the current data is simply stored `as is'.
+% \begin{macrocode}
+\cs_new:Npn \xtemplate_store_value_integer:n #1 {
+ \xtemplate_if_eval_now:nTF {#1} {
+ \int_set:Nn \l_xtemplate_tmp_int {#1}
+ \prop_put:NVV \l_xtemplate_values_prop \l_xtemplate_key_name_tl
+ \l_xtemplate_tmp_int
+ }{
+ \prop_put:NVn \l_xtemplate_values_prop \l_xtemplate_key_name_tl {#1}
+ }
+}
+\cs_new:Npn \xtemplate_store_value_length:n #1 {
+ \xtemplate_if_eval_now:nTF {#1} {
+ \dim_set:Nn \l_xtemplate_tmp_dim {#1}
+ \prop_put:NVV \l_xtemplate_values_prop \l_xtemplate_key_name_tl
+ \l_xtemplate_tmp_dim
+ }{
+ \prop_put:NVn \l_xtemplate_values_prop \l_xtemplate_key_name_tl {#1}
+ }
+}
+\cs_new:Npn \xtemplate_store_value_skip:n #1 {
+ \xtemplate_if_eval_now:nTF {#1} {
+ \skip_set:Nn \l_xtemplate_tmp_skip {#1}
+ \prop_put:NVV \l_xtemplate_values_prop \l_xtemplate_key_name_tl
+ \l_xtemplate_tmp_skip
+ }{
+ \prop_put:NVn \l_xtemplate_values_prop \l_xtemplate_key_name_tl {#1}
+ }
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\subsubsection{Implementation part of template declaration}
+%
+%\begin{macro}{\xtemplate_declare_template_code:nnnnn}
+% The main function for implementing a template starts with a couple of
+% simple checks to make sure that there are no obvious mistakes: the
+% number of arguments must agree and the template keys must have been
+% declared.
+% \begin{macrocode}
+\cs_new:Npn \xtemplate_declare_template_code:nnnnn #1#2#3#4#5 {
+ \xtemplate_execute_if_type_exist:nT {#1}
+ {
+ \xtemplate_execute_if_arg_agree:nnT {#1}{#3}
+ {
+ \xtemplate_if_keys_exist:nnT {#1} {#2}
+ {
+ \xtemplate_store_key_implementation:nnn {#1} {#2} {#4}
+ \cs_generate_from_arg_count:cNnn
+ { \c_xtemplate_code_root_tl #1 / #2 :w } \cs_gset:Npn
+ {#3} {#5}
+ }
+ }
+ }
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\xtemplate_store_key_implementation:nnn}
+% Actually storing the implementation part of a template is quite easy
+% as it only requires the list of keys given to be turned into a
+% property list. There is also some error-checking to do, hence the need
+% to have the list of defined keytypes available. In certain cases
+% (when choices are involved) parsing the key results in changes to the
+% default values. That is why they are loaded and then saved again.
+% \begin{macrocode}
+\cs_set:Npn \xtemplate_store_key_implementation:nnn #1#2#3 {
+ \xtemplate_recover_defaults:n { #1 / #2 }
+ \xtemplate_recover_keytypes:n { #1 / #2 }
+ \prop_clear:N \l_xtemplate_vars_prop
+ \cs_set_eq:NN \KV_key_no_value_elt:n \xtemplate_parse_vars_elt:n
+ \cs_set_eq:NN \KV_key_value_elt:nn \xtemplate_parse_vars_elt:nn
+ \KV_parse_space_removal_sanitize:n {#3}
+% \end{macrocode}
+% In certain cases (when choices are involved) parsing the key results in
+% changes to the default values. Therefore we have to save those back.
+% \begin{macrocode}
+ \xtemplate_store_defaults:n { #1 / #2 }
+ \xtemplate_store_vars:n { #1 / #2 }
+ \clist_clear:N \l_xtemplate_restrict_clist
+ \xtemplate_store_restrictions:n { #1 / #2 }
+ \prop_del:NV \l_xtemplate_keytypes_prop \c_xtemplate_key_order_tl
+ \prop_if_empty:NF \l_xtemplate_keytypes_prop {
+ \prop_map_inline:Nn \l_xtemplate_keytypes_prop {
+ \msg_kernel_error:nnxxx { xtemplate } { key-not-implemented }
+ {##1} {#2} {#1}
+ }
+ }
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\xtemplate_parse_vars_elt:n}
+% At the implementation stage, every key must have a value given. So
+% this is an error function.
+% \begin{macrocode}
+\cs_new:Npn \xtemplate_parse_vars_elt:n #1 {
+ \msg_kernel_error:nnx { xtemplate } { key-no-variable } {#1}
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\xtemplate_parse_vars_elt:nn}
+% The actual storage part here is very simple: the storage bin name
+% is placed into the property list. At the same time, a comparison is
+% made with the keytypes defined earlier: if there is a mismatch then
+% an error is raised.
+% \begin{macrocode}
+\cs_new:Npn \xtemplate_parse_vars_elt:nn #1#2 {
+ \tl_set:Nx \l_xtemplate_key_name_tl { \tl_to_str:n {#1} }
+ \tl_replace_all_in:Nnn \l_xtemplate_key_name_tl { ~ } { }
+ \prop_if_in:NVTF \l_xtemplate_keytypes_prop \l_xtemplate_key_name_tl {
+ \prop_get:NVN \l_xtemplate_keytypes_prop \l_xtemplate_key_name_tl
+ \l_xtemplate_keytype_tl
+ \xtemplate_split_keytype_arg:V \l_xtemplate_keytype_tl
+ \xtemplate_parse_vars_elt_aux:n {#2}
+ \prop_del:NV \l_xtemplate_keytypes_prop \l_xtemplate_key_name_tl
+ }{
+ \msg_kernel_error:nnx { xtemplate } { unknown-key } {#1}
+ }
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}[aux]{\xtemplate_parse_vars_elt_aux:n}
+%\begin{macro}[aux]{\xtemplate_parse_vars_elt_aux:w}
+% There now needs to be some sanity checking on the variable name
+% given. This does not apply for \texttt{choice} or
+% \texttt{code} `variables', but in all other cases the variable needs
+% to exist. Also, the only prefix acceptable is \texttt{global}. So
+% there are a few related checks to make.
+% \begin{macrocode}
+\cs_new:Npn \xtemplate_parse_vars_elt_aux:n #1 {
+ \tl_if_eq:VnTF \l_xtemplate_keytype_tl { choice }
+ {
+ \xtemplate_implement_choices:n {#1}
+ }
+ {
+ \tl_if_eq:VnTF \l_xtemplate_keytype_tl { code }
+ {
+ \prop_put:NVn \l_xtemplate_vars_prop
+ \l_xtemplate_key_name_tl {#1}
+ }
+ {
+ \tl_if_eq:noTF {#1} { \tl_head:w #1 \q_nil }
+ {
+ \cs_if_exist:NTF #1
+ {
+ \prop_put:NVn \l_xtemplate_vars_prop
+ \l_xtemplate_key_name_tl {#1}
+ }
+ {
+ \msg_kernel_error:nnx { xtemplate }
+ { undeclared-variable }
+ { \exp_not:N #1 }
+ }
+ }
+ {
+ \tl_if_in:nnTF {#1} { global }
+ { \xtemplate_parse_vars_elt_aux:w #1 \q_nil }
+ {
+ \msg_kernel_error:nnx { xtemplate } { bad-variable }
+ { \exp_not:n {#1} }
+ }
+ }
+ }
+ }
+}
+\cs_new:Npn \xtemplate_parse_vars_elt_aux:w #1 global #2 \q_nil {
+ \tl_if_empty:nTF {#1}
+ {
+ \tl_if_eq:noTF {#2} { \tl_head:w #2 \q_nil }
+ {
+ \cs_if_exist:NTF #2
+ {
+ \prop_put:NVn \l_xtemplate_vars_prop
+ \l_xtemplate_key_name_tl { #1 global #2 }
+ }
+ {
+ \msg_kernel_error:nnx { xtemplate }
+ { undeclared-variable }
+ { \exp_not:N #2 }
+ }
+ }
+ {
+ \msg_kernel_error:nnx { xtemplate } { bad-variable }
+ { \exp_not:n { #1 global #2 } }
+ }
+ }
+ {
+ \msg_kernel_error:nnx { xtemplate } { bad-variable }
+ { \exp_not:n { #1 global #2 } }
+ }
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\xtemplate_implement_choices:n}
+% Implementing choices requires a second key--value loop. So after a
+% little set-up, the standard parser is called. There is then a
+% check for a default choice being set: at this stage the name of
+% the choice is replaced by the code to implement it.
+% \begin{macrocode}
+\cs_new:Npn \xtemplate_implement_choices:n #1 {
+ \clist_set_eq:NN \l_xtemplate_tmp_clist \l_xtemplate_keytype_arg_tl
+ \cs_set_eq:NN \KV_key_no_value_elt:n \xtemplate_implement_choice_elt:n
+ \cs_set_eq:NN \KV_key_value_elt:nn \xtemplate_implement_choice_elt:nn
+ \prop_put:NVn \l_xtemplate_vars_prop \l_xtemplate_key_name_tl { }
+ \KV_parse_space_removal_sanitize:n {#1}
+ \cs_set_eq:NN \KV_key_no_value_elt:n \xtemplate_parse_vars_elt:n
+ \cs_set_eq:NN \KV_key_value_elt:nn \xtemplate_parse_vars_elt:nn
+ \tl_set:Nx \l_xtemplate_tmp_tl
+ { \l_xtemplate_key_name_tl \xtemplate_space: default }
+ \prop_if_in:NVT \l_xtemplate_values_prop \l_xtemplate_tmp_tl {
+ \prop_get:NVN \l_xtemplate_values_prop \l_xtemplate_tmp_tl
+ \l_xtemplate_tmp_tl
+ \xtemplate_store_value_choice:V \l_xtemplate_tmp_tl
+ }
+ \clist_if_empty:NF \l_xtemplate_tmp_clist {
+ \clist_map_inline:Nn \l_xtemplate_tmp_clist
+ {
+ \msg_kernel_error:nnx { xtemplate } { choice-not-implemented }
+ {##1}
+ }
+ }
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\xtemplate_implement_choice_elt:n}
+%\begin{macro}{\xtemplate_implement_choice_elt:nn}
+% The actual storage of the implementation of a choice is mainly about
+% error checking. The code here ensures that all choices have to have
+% been declared, apart from the special \texttt{unknown} choice, which
+% must come last. The code for each choice is stored along with the
+% key name in the variables property list.
+% \begin{macrocode}
+\cs_new:Npn \xtemplate_implement_choice_elt:n #1 {
+ \clist_if_empty:NTF \l_xtemplate_tmp_clist {
+ \tl_if_eq:nnF {#1} { unknown } {
+ \prop_get:NVN \l_xtemplate_keytypes_prop \l_xtemplate_key_name_tl
+ \l_xtemplate_tmp_tl
+ \xtemplate_split_keytype_arg:V \l_xtemplate_tmp_tl
+ \msg_kernel_error:nnxxx { xtemplate } { unknown-choice }
+ {#1}
+ { \l_xtemplate_key_name_tl }
+ { \l_xtemplate_keytype_arg_tl }
+ }
+ }{
+ \clist_if_in:NnTF \l_xtemplate_tmp_clist {#1} {
+ \clist_remove_element:Nn \l_xtemplate_tmp_clist {#1}
+ }{
+ \prop_get:NVN \l_xtemplate_keytypes_prop \l_xtemplate_key_name_tl
+ \l_xtemplate_tmp_tl
+ \xtemplate_split_keytype_arg:V \l_xtemplate_tmp_tl
+ \msg_kernel_error:nnxxx { xtemplate } { unknown-choice }
+ {#1}
+ { \l_xtemplate_key_name_tl }
+ { \l_xtemplate_keytype_arg_tl }
+ }
+ }
+}
+\cs_new:Npn \xtemplate_implement_choice_elt:nn #1#2 {
+ \xtemplate_implement_choice_elt:n {#1}
+ \tl_set:Nx \l_xtemplate_tmp_tl
+ { \l_xtemplate_key_name_tl \xtemplate_space: #1 }
+ \prop_put:NVn \l_xtemplate_vars_prop \l_xtemplate_tmp_tl {#2}
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%
+%\subsubsection{Editing template defaults}
+%
+% Template defaults can be edited either with no other changes or
+% to prevent further editing, forming a ``restricted template''.
+% In the later case, a new template results, whereas simple editing
+% does not produce a new template name.
+%
+%\begin{macro}{\xtemplate_declare_restricted:nnnn}
+% Creating a restricted template means copying the old template to the
+% new one first.
+% \begin{macrocode}
+\cs_new:Npn \xtemplate_declare_restricted:nnnn #1#2#3#4 {
+ \xtemplate_if_keys_exist:nnT {#1} {#2}
+ {
+ \xtemplate_set_template_eq:nn { #1 / #3 } { #1 / #2 }
+ \bool_set_true:N \l_xtemplate_restrict_bool
+ \xtemplate_edit_defaults_aux:nnn {#1} {#3} {#4}
+ }
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\xtemplate_edit_defaults:nnn}
+%\begin{macro}[aux]{\xtemplate_edit_defaults_aux:nnn}
+% Editing the template defaults means getting the values back out
+% of the store, then parsing the list of new values before putting
+% the updated list back into storage. The auxiliary function is used
+% to allow code-sharing with the template-restriction system.
+% \begin{macrocode}
+\cs_new:Npn \xtemplate_edit_defaults:nnn {
+ \bool_set_false:N \l_xtemplate_restrict_bool
+ \xtemplate_edit_defaults_aux:nnn
+}
+\cs_new:Npn \xtemplate_edit_defaults_aux:nnn #1#2#3 {
+ \xtemplate_if_keys_exist:nnT {#1} {#2}
+ {
+ \xtemplate_recover_defaults:n { #1 / #2 }
+ \xtemplate_recover_restrictions:n { #1 / #2 }
+ \xtemplate_parse_values:nn { #1 / #2 } {#3}
+ \xtemplate_store_defaults:n { #1 / #2 }
+ \xtemplate_store_restrictions:n { #1 / #2 }
+ }
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\xtemplate_parse_values:nn}
+% The routine to parse values is the same for both editing a
+% template and setting up an instance. So the code here does only the
+% minimum necessary for reading the values.
+% \begin{macrocode}
+\cs_new:Npn \xtemplate_parse_values:nn #1#2 {
+ \xtemplate_recover_keytypes:n {#1}
+ \clist_clear:N \l_xtemplate_restricted_clist
+ \cs_set_eq:NN \KV_key_no_value_elt:n \xtemplate_parse_values_elt:n
+ \cs_set_eq:NN \KV_key_value_elt:nn \xtemplate_parse_values_elt:nn
+ \KV_parse_space_removal_sanitize:n {#2}
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\xtemplate_parse_values_elt:n}
+% Every key needs a value, so this is just an error routine.
+% \begin{macrocode}
+\cs_new:Npn \xtemplate_parse_values_elt:n #1 {
+ \bool_set_true:N \l_xtemplate_error_bool
+ \msg_kernel_error:nnx { xtemplate } { key-no-value } {#1}
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\xtemplate_parse_values_elt:nn}
+%\begin{macro}[aux]{\xtemplate_parse_values_elt_aux:nn}
+%\begin{macro}[aux]{\xtemplate_parse_values_elt_aux:Vn}
+% To store the value, find the keytype then call the saving function.
+% These need the current key name saved as \cs{l_xtemplate_key_name_tl}.
+% When a template is being restricted, the setting code will be
+% skipped for restricted keys.
+% \begin{macrocode}
+\cs_new:Npn \xtemplate_parse_values_elt:nn #1#2 {
+ \tl_set:Nx \l_xtemplate_key_name_tl { \tl_to_str:n {#1} }
+ \tl_replace_all_in:Nnn \l_xtemplate_key_name_tl { ~ } { }
+ \prop_if_in:NVTF \l_xtemplate_keytypes_prop \l_xtemplate_key_name_tl {
+ \bool_if:NTF \l_xtemplate_restrict_bool {
+ \clist_if_in:NVF \l_xtemplate_restricted_clist
+ \l_xtemplate_key_name_tl {
+ \xtemplate_parse_values_elt_aux:Vn \l_xtemplate_key_name_tl {#2}
+ }
+ }{
+ \xtemplate_parse_values_elt_aux:Vn \l_xtemplate_key_name_tl {#2}
+ }
+ }{
+ \msg_kernel_error:nnx { xtemplate } { unknown-key }
+ { \l_xtemplate_key_name_tl }
+ }
+}
+\cs_new:Npn \xtemplate_parse_values_elt_aux:nn #1#2 {
+ \clist_put_right:Nn \l_xtemplate_restricted_clist {#1}
+ \prop_get:NnN \l_xtemplate_keytypes_prop {#1} \l_xtemplate_tmp_tl
+ \xtemplate_split_keytype_arg:V \l_xtemplate_tmp_tl
+ \use:c { xtemplate_store_value_ \l_xtemplate_keytype_tl :n } {#2}
+}
+\cs_generate_variant:Nn \xtemplate_parse_values_elt_aux:nn { Vn }
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\xtemplate_set_template_eq:nn}
+% To copy a template, each of the lists plus the code has to be copied
+% across. To keep this independent of the list storage system, it is
+% all done with two-part shuffles.
+% \begin{macrocode}
+\cs_new:Npn \xtemplate_set_template_eq:nn #1#2 {
+ \xtemplate_recover_defaults:n {#2}
+ \xtemplate_store_defaults:n {#1}
+ \xtemplate_recover_keytypes:n {#2}
+ \xtemplate_store_keytypes:n {#1}
+ \xtemplate_recover_vars:n {#2}
+ \xtemplate_store_vars:n {#1}
+ \cs_gset_eq:cc { \c_xtemplate_code_root_tl #1 :w }
+ { \c_xtemplate_code_root_tl #2 :w }
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\subsubsection{Creating instances of templates}
+%
+%\begin{macro}{\xtemplate_declare_instance:nnnnn}
+%\begin{macro}[aux]{\xtemplate_declare_instance_aux:nnnnn}
+% Making an instance has two distinct parts. First, the keys given are
+% parsed to transfer the values into the structured data format used
+% internally. This allows the default and given values to be combined
+% with no repetition. In the second step, the structured data is
+% converted to pre-defined variable assignments, and these are stored
+% in the function for the instance. A final check is also made so that
+% there is always an instance `outside' of any collection.
+% \begin{macrocode}
+\cs_new:Npn \xtemplate_declare_instance:nnnnn #1#2#3#4#5 {
+ \xtemplate_execute_if_code_exist:nnT {#1} {#2}
+ {
+ \xtemplate_recover_defaults:n { #1 / #2 }
+ \xtemplate_recover_vars:n { #1 / #2 }
+ \xtemplate_declare_instance_aux:nnnnn {#1} {#2} {#3} {#4} {#5}
+ }
+}
+\cs_new:Npn \xtemplate_declare_instance_aux:nnnnn #1#2#3#4#5 {
+ \bool_set_false:N \l_xtemplate_error_bool
+ \xtemplate_parse_values:nn { #1 / #2 } {#5}
+ \bool_if:NF \l_xtemplate_error_bool {
+ \prop_put:Nnn \l_xtemplate_values_prop { from~template } {#2}
+ \xtemplate_store_values:n { #1 / #3 / #4 }
+ \xtemplate_convert_to_assignments:
+ \cs_set:cpx { \c_xtemplate_instances_root_tl #1 / #3 / #4 :w } {
+ \exp_not:N \xtemplate_assignments_push:n {
+ \exp_not:V \l_xtemplate_assignments_toks
+ }
+ \exp_not:c { \c_xtemplate_code_root_tl #1 / #2 :w }
+ }
+ \xtemplate_if_instance_exist:nnnF {#1} { } {#4} {
+ \cs_set_eq:cc
+ { \c_xtemplate_instances_root_tl #1 / / #4 :w }
+ { \c_xtemplate_instances_root_tl #1 / #3 / #4 :w }
+ }
+ }
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\xtemplate_edit_instance:nnnn}
+%\begin{macro}[aux]{\xtemplate_edit_instance_aux:nnnnn}
+%\begin{macro}[aux]{\xtemplate_edit_instance_aux:nVnnn}
+% Editing an instance is almost identical to declaring one. The only
+% variation is the source of the values to use. When editing, they are
+% recovered from the previous instance run.
+% \begin{macrocode}
+\cs_new:Npn \xtemplate_edit_instance:nnnn #1#2#3 {
+ \xtemplate_if_instance_exist:nnnTF {#1} {#2} {#3}
+ {
+ \xtemplate_recover_values:n { #1 / #2 / #3 }
+ \prop_get:NnN \l_xtemplate_values_prop { from~template }
+ \l_xtemplate_tmp_tl
+ \xtemplate_edit_instance_aux:nVnnn {#1} \l_xtemplate_tmp_tl
+ {#2} {#3}
+ }
+ {
+ \msg_kernel_error:nnxx { xtemplate } { unknown-instance }
+ {#1} {#3}
+ }
+}
+\cs_new:Npn \xtemplate_edit_instance_aux:nnnnn #1#2 {
+ \xtemplate_recover_vars:n { #1 / #2 }
+ \xtemplate_declare_instance_aux:nnnnn {#1} {#2}
+}
+\cs_generate_variant:Nn \xtemplate_edit_instance_aux:nnnnn { nV }
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\xtemplate_convert_to_assignments:}
+%\begin{macro}[aux]{\xtemplate_convert_to_assignments_aux:n}
+%\begin{macro}[aux]{\xtemplate_convert_to_assignments_aux:nn}
+%\begin{macro}[aux]{\xtemplate_convert_to_assignments_aux:nV}
+% The idea on converting to a set of assignments is to loop over each
+% key, so that the loop order follows the declaration order of the keys.
+% This is done using a sequence as property lists are not ``ordered''.
+% \begin{macrocode}
+\cs_new_nopar:Npn \xtemplate_convert_to_assignments: {
+ \toks_clear:N \l_xtemplate_assignments_toks
+ \prop_get:NVN \l_xtemplate_keytypes_prop \c_xtemplate_key_order_tl
+ \l_xtemplate_key_seq
+ \seq_map_function:NN \l_xtemplate_key_seq
+ \xtemplate_convert_to_assignments_aux:n
+}
+\cs_new:Npn \xtemplate_convert_to_assignments_aux:n #1 {
+ \prop_get:NnN \l_xtemplate_keytypes_prop {#1} \l_xtemplate_tmp_tl
+ \xtemplate_convert_to_assignments_aux:nV {#1} \l_xtemplate_tmp_tl
+}
+% \end{macrocode}
+% The second auxiliary function actually does the work. The
+% arguments here are the key name (|#1|) and the keytype (|#2|).
+% From those, the value to assign and the name of the appropriate
+% variable are recovered. A bit of work is then needed to sort out
+% keytypes with arguments (for example instances), and to look for
+% global assignments. Once that is done, a hand-off can be made to the
+% handler for the relevant keytype.
+% \begin{macrocode}
+\cs_new:Npn \xtemplate_convert_to_assignments_aux:nn #1#2 {
+ \prop_if_in:NnT \l_xtemplate_values_prop {#1} {
+ \prop_if_in:NnTF \l_xtemplate_vars_prop {#1} {
+ \prop_get:NnN \l_xtemplate_values_prop {#1} \l_xtemplate_value_tl
+ \prop_get:NnN \l_xtemplate_vars_prop {#1} \l_xtemplate_var_tl
+ \xtemplate_split_keytype_arg:n {#2}
+ \tl_if_eq:VnF \l_xtemplate_keytype_tl { choice } {
+ \tl_if_eq:VnF \l_xtemplate_keytype_tl { code } {
+ \xtemplate_find_global:
+ }
+ }
+ \use:c { xtemplate_assign_ \l_xtemplate_keytype_tl : }
+ }{
+ \msg_kernel_error:nnx { xtemplate } { unknown-attribute } {#1}
+ }
+ }
+}
+\cs_generate_variant:Nn \xtemplate_convert_to_assignments_aux:nn { nV }
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\xtemplate_find_global:}
+%\begin{macro}[aux]{\xtemplate_find_global_aux:w}
+% Global assignments should have the phrase ``global'' at the front.
+% This is pretty easy to find: no other error checking, though.
+% \begin{macrocode}
+\cs_new_nopar:Npn \xtemplate_find_global: {
+ \bool_set_false:N \l_xtemplate_global_bool
+ \tl_if_in:VnT \l_xtemplate_var_tl { global } {
+ \exp_after:wN \xtemplate_find_global_aux:w \l_xtemplate_var_tl \q_stop
+ }
+}
+\cs_new:Npn \xtemplate_find_global_aux:w #1 global #2 \q_stop {
+ \tl_set:Nn \l_xtemplate_var_tl {#2}
+ \bool_set_true:N \l_xtemplate_global_bool
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%
+%\subsection{Using templates directly}
+%
+% \begin{macro}{\xtemplate_use_template:nnn}
+% Directly use a template with a particular parameter setting.
+% This is also picked up if used in a nested fashion inside a parameter
+% list. The idea is essentially the same as creating an instance,
+% just with no saving of the result.
+% \begin{macrocode}
+\cs_new:Npn \xtemplate_use_template:nnn #1#2#3 {
+ \xtemplate_recover_defaults:n { #1 / #2 }
+ \xtemplate_recover_vars:n { #1 / #2 }
+ \xtemplate_parse_values:nn { #1 / #2 } {#3}
+ \xtemplate_convert_to_assignments:
+ \use:c { \c_xtemplate_code_root_tl #1 / #2 :w }
+}
+% \end{macrocode}
+% \end{macro}
+%
+%\subsubsection{Assigning values to variables}
+%
+%\begin{macro}{\xtemplate_assign_boolean:}
+%\begin{macro}[aux]{\xtemplate_assign_boolean_aux:n}
+% Setting a Boolean value is slightly different to everything else
+% as the value can be used to work out which \texttt{set} function to
+% call. As long as there is no need to recover things from another
+% variable, everything is pretty easy.
+% \begin{macrocode}
+\cs_new_nopar:Npn \xtemplate_assign_boolean: {
+ \bool_if:NTF \l_xtemplate_global_bool {
+ \xtemplate_assign_boolean_aux:n { bool_gset }
+ }{
+ \xtemplate_assign_boolean_aux:n { bool_set }
+ }
+}
+\cs_new_nopar:Npn \xtemplate_assign_boolean_aux:n #1 {
+ \xtemplate_if_key_value:VT \l_xtemplate_value_tl {
+ \xtemplate_key_to_value:
+ }
+ \toks_put_left:Nx \l_xtemplate_assignments_toks {
+ \exp_not:c { #1 _ \l_xtemplate_value_tl :N }
+ \exp_not:V \l_xtemplate_var_tl
+ }
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\xtemplate_assign_choice:}
+% Assigning a choice is actually trivial: the code needed will
+% be in \cs{l_xtemplate_value_tl}, and is simply copied to the correct
+% place.
+% \begin{macrocode}
+\cs_new_nopar:Npn \xtemplate_assign_choice: {
+ \toks_put_left:NV \l_xtemplate_assignments_toks \l_xtemplate_value_tl
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\xtemplate_assign_code:}
+%\begin{macro}{\xtemplate_assign_code:n}
+% Assigning general code to a key needs a scratch function to be created
+% and run when \cs{AssignTemplateKeys} is called. So the appropriate
+% definition then use is created in the toks.
+% \begin{macrocode}
+\cs_new_nopar:Npn \xtemplate_assign_code: {
+ \toks_put_left:Nx \l_xtemplate_assignments_toks {
+ \exp_not:N \cs_set:Npn \exp_not:N \xtemplate_assign_code:n ##1 {
+ \exp_not:V \l_xtemplate_var_tl
+ }
+ \exp_not:N \xtemplate_assign_code:n
+ { \exp_not:V \l_xtemplate_value_tl }
+ }
+}
+\cs_new:Npn \xtemplate_assign_code:n #1 { }
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\xtemplate_assign_function:}
+%\begin{macro}[aux]{\xtemplate_assign_function_aux:N}
+% For functions, the toks needs to have a cs-generation step created.
+% This looks a bit messy but is only actually one function.
+% \begin{macrocode}
+\cs_new_nopar:Npn \xtemplate_assign_function: {
+ \bool_if:NTF \l_xtemplate_global_bool {
+ \xtemplate_assign_function_aux:N \cs_gset:Npn
+ }{
+ \xtemplate_assign_function_aux:N \cs_set:Npn
+ }
+}
+\cs_new_nopar:Npn \xtemplate_assign_function_aux:N #1 {
+ \toks_put_left:Nx \l_xtemplate_assignments_toks {
+ \exp_not:N \cs_generate_from_arg_count:NNnn
+ \exp_not:V \l_xtemplate_var_tl
+ \exp_not:N #1
+ { \exp_not:V \l_xtemplate_keytype_arg_tl }
+ { \exp_not:V \l_xtemplate_value_tl }
+ }
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\xtemplate_assign_instance:}
+%\begin{macro}[aux]{\xtemplate_assign_instance_aux:N}
+% Using an instance means adding the appropriate function creation to
+% the toks. No checks are made at this stage, so if the instance is
+% not valid then errors will arise later.
+% \begin{macrocode}
+\cs_new_nopar:Npn \xtemplate_assign_instance: {
+ \bool_if:NTF \l_xtemplate_global_bool {
+ \xtemplate_assign_instance_aux:N \cs_gset:Npn
+ }{
+ \xtemplate_assign_instance_aux:N \cs_set:Npn
+ }
+}
+\cs_new_nopar:Npn \xtemplate_assign_instance_aux:N #1 {
+ \toks_put_left:Nx \l_xtemplate_assignments_toks {
+ \exp_not:N #1 \exp_not:V \l_xtemplate_var_tl {
+ \exp_not:N \xtemplate_use_instance:nn
+ { \exp_not:V \l_xtemplate_keytype_arg_tl }
+ { \exp_not:V \l_xtemplate_value_tl }
+ }
+ }
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\xtemplate_assign_integer:}
+%\begin{macro}{\xtemplate_assign_length:}
+%\begin{macro}{\xtemplate_assign_skip:}
+% All of the calculated assignments use the same underlying code, with
+% only the low-level assignment function changing.
+% \begin{macrocode}
+\cs_new_nopar:Npn \xtemplate_assign_integer: {
+ \bool_if:NTF \l_xtemplate_global_bool {
+ \xtemplate_assign_variable:N \int_gset:Nn
+ }{
+ \xtemplate_assign_variable:N \int_set:Nn
+ }
+}
+\cs_new_nopar:Npn \xtemplate_assign_length: {
+ \bool_if:NTF \l_xtemplate_global_bool {
+ \xtemplate_assign_variable:N \dim_gset:Nn
+ }{
+ \xtemplate_assign_variable:N \dim_set:Nn
+ }
+}
+\cs_new_nopar:Npn \xtemplate_assign_skip: {
+ \bool_if:NTF \l_xtemplate_global_bool {
+ \xtemplate_assign_variable:N \skip_gset:Nn
+ }{
+ \xtemplate_assign_variable:N \skip_set:Nn
+ }
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\xtemplate_assign_tokenlist:}
+%\begin{macro}{\xtemplate_assign_commalist:}
+%\begin{macro}[aux]{\xtemplate_assign_tokenlist_aux:N}
+% Storing lists of tokens is easy: no complex calculations and no
+% need to worry about numbers of arguments. The comma list version
+% takes advantage of the low-level implementation of the variable type
+% to keep down code duplication.
+% \begin{macrocode}
+\cs_new_nopar:Npn \xtemplate_assign_tokenlist: {
+ \bool_if:NTF \l_xtemplate_global_bool {
+ \xtemplate_assign_tokenlist_aux:N \tl_gset:Nn
+ }{
+ \xtemplate_assign_tokenlist_aux:N \tl_set:Nn
+ }
+}
+\cs_new_eq:NN \xtemplate_assign_commalist:
+ \xtemplate_assign_tokenlist:
+\cs_new_nopar:Npn \xtemplate_assign_tokenlist_aux:N #1 {
+ \toks_put_left:Nx \l_xtemplate_assignments_toks {
+ \exp_not:N #1 \exp_not:V \l_xtemplate_var_tl
+ { \exp_not:V \l_xtemplate_value_tl }
+ }
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\xtemplate_assign_variable:N}
+% A general-purpose function for all of the numerical assignments.
+% As long as the value is not coming from another variable, the stored
+% value is simply transferred for output.
+% \begin{macrocode}
+\cs_new_nopar:Npn \xtemplate_assign_variable:N #1 {
+ \xtemplate_if_key_value:VT \l_xtemplate_value_tl {
+ \xtemplate_key_to_value:
+ }
+ \toks_put_left:Nx \l_xtemplate_assignments_toks {
+ \exp_not:N #1 \exp_not:V \l_xtemplate_var_tl
+ { \exp_not:V \l_xtemplate_value_tl }
+ }
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\xtemplate_key_to_value:}
+%\begin{macro}[aux]{\xtemplate_key_to_value_aux:w}
+% The idea here is to recover the attribute value of another key. To
+% do that, the marker is removed and a look up takes place. If this
+% is successful, then the name of the variable of the attribute is
+% returned. This assumes that the value will be used in context where
+% it will be converted to a value, for example when setting a number.
+% \begin{macrocode}
+\cs_new_nopar:Npn \xtemplate_key_to_value: {
+ \exp_after:wN \xtemplate_key_to_value_aux:w \l_xtemplate_value_tl
+}
+\cs_new:Npn \xtemplate_key_to_value_aux:w \KeyValue #1 {
+ \tl_set:Nx \l_xtemplate_tmp_tl { \tl_to_str:n {#1} }
+ \tl_replace_all_in:Nnn \l_xtemplate_key_name_tl { ~ } { }
+ \prop_if_in:NVTF \l_xtemplate_vars_prop \l_xtemplate_tmp_tl {
+ \prop_get:NVN \l_xtemplate_vars_prop \l_xtemplate_tmp_tl
+ \l_xtemplate_value_tl
+ }{
+ \msg_kernel_error:nnx { xtemplate } { unknown-attribute }
+ { \l_xtemplate_tmp_tl }
+ }
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%
+%\subsubsection{Using instances}
+%
+%\begin{macro}{\xtemplate_use_instance:nn}
+%\begin{macro}[aux]{\xtemplate_use_instance_aux:nNnnn}
+%\begin{macro}[aux]{\xtemplate_use_instance_aux:nn}
+% Using an instance is just a question of finding the appropriate
+% function. There is the possibility that a collection instance exists,
+% so this is checked before trying the general instance. If nothing is
+% found, an error is raised. One additional complication is that
+% if the first token of argument |#2| is \cs{UseTemplate} then that
+% is also valid. There is an error-test to make sure that the
+% types agree, and if so the template is used directly.
+% \begin{macrocode}
+\cs_new:Npn \xtemplate_use_instance:nn #1#2 {
+ \xtemplate_if_use_template:nTF {#2} {
+ \xtemplate_use_instance_aux:nNnnn {#1} #2
+ }{
+ \xtemplate_use_instance_aux:nn {#1} {#2}
+ }
+}
+\cs_new:Npn \xtemplate_use_instance_aux:nNnnn #1#2#3#4#5 {
+ \tl_if_eq:nnTF {#1} {#3} {
+ \xtemplate_use_template:nnn {#3} {#4} {#5}
+ }{
+ \msg_kernel_error:nnxx { xtemplate } { type-mismatch } {#1} {#3}
+ }
+}
+\cs_new:Npn \xtemplate_use_instance_aux:nn #1#2 {
+ \xtemplate_get_collection:n {#1}
+ \xtemplate_if_instance_exist:nnnTF
+ {#1} { \l_xtemplate_collection_tl } {#2} {
+ \use:c {
+ \c_xtemplate_instances_root_tl #1 / \l_xtemplate_collection_tl /#2
+ :w
+ }
+ }{
+ \xtemplate_if_instance_exist:nnnTF {#1} { } {#2} {
+ \use:c { \c_xtemplate_instances_root_tl #1 / / #2 :w }
+ }{
+ \msg_kernel_error:nnxx { xtemplate } { unknown-instance }
+ {#1} {#2}
+ }
+ }
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\xtemplate_use_collection:nn}
+% Switching to an instance collection is just a question of setting the
+% appropriate list.
+% \begin{macrocode}
+\cs_new:Npn \xtemplate_use_collection:nn #1#2 {
+ \prop_put:Nnn \l_xtemplate_collections_prop {#1} {#2}
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\xtemplate_get_collection:n}
+% Recovering the collection for a given type is pretty easy: just a read
+% from the list.
+% \begin{macrocode}
+\cs_new:Npn \xtemplate_get_collection:n #1 {
+ \prop_if_in:NnTF \l_xtemplate_collections_prop {#1} {
+ \prop_get:NnN \l_xtemplate_collections_prop {#1}
+ \l_xtemplate_collection_tl
+ }{
+ \tl_clear:N \l_xtemplate_collection_tl
+ }
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\subsubsection{Assignment manipulation}
+%
+% A few functions to transfer assignments about, as this is needed by
+% \cs{AssignTemplateKeys}.
+%
+%\begin{macro}{\xtemplate_assignments_pop:}
+% To actually use the assignments.
+% \begin{macrocode}
+\cs_new_nopar:Npn \xtemplate_assignments_pop: {
+ \toks_use:N \l_xtemplate_assignments_toks
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\xtemplate_assignments_push:n}
+% Here, the assignments are stored for later use.
+% \begin{macrocode}
+\cs_new:Npn \xtemplate_assignments_push:n #1 {
+ \toks_set:Nn \l_xtemplate_assignments_toks {#1}
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\subsubsection{Showing templates and instances}
+%
+%\begin{macro}{\xtemplate_show_code:nn}
+% Showing the code for a template is just a translation of
+% \cs{cs_show:c}.
+% \begin{macrocode}
+\cs_new:Npn \xtemplate_show_code:nn #1#2 {
+ \xtemplate_execute_if_code_exist:nnT {#1} {#2}
+ { \cs_show:c { \c_xtemplate_code_root_tl #1 / #2 :w } }
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\xtemplate_show_defaults:nn}
+%\begin{macro}{\xtemplate_show_keytypes:nn}
+%\begin{macro}{\xtemplate_show_values:nnn}
+%\begin{macro}{\xtemplate_show_vars:nn}
+% Showing the internal data is a case of getting the appropriate
+% property list back, then displaying the scratch variable.
+% \begin{macrocode}
+\cs_new:Npn \xtemplate_show_defaults:nn #1#2 {
+ \xtemplate_if_keys_exist:nnT {#1} {#2}
+ {
+ \xtemplate_recover_defaults:n { #1 / #2 }
+ \prop_display:N \l_xtemplate_values_prop
+ }
+}
+\cs_new:Npn \xtemplate_show_keytypes:nn #1#2 {
+ \xtemplate_if_keys_exist:nnT {#1} {#2}
+ {
+ \xtemplate_recover_keytypes:n { #1 / #2 }
+ \prop_display:N \l_xtemplate_keytypes_prop
+ }
+}
+\cs_new:Npn \xtemplate_show_values:nnn #1#2#3 {
+ \xtemplate_if_instance_exist:nnnTF {#1} {#2} {#3}
+ {
+ \xtemplate_recover_values:n { #1 / #2 / #3 }
+ \prop_display:N \l_xtemplate_values_prop
+ }
+ {
+ \msg_kernel_error:nnxx { xtemplate } { unknown-instance }
+ {#1} {#2}
+ }
+}
+\cs_new:Npn \xtemplate_show_vars:nn #1#2 {
+ \xtemplate_execute_if_code_exist:nnT {#1} {#2}
+ {
+ \xtemplate_recover_vars:n { #1 / #2 }
+ \prop_display:N \l_xtemplate_vars_prop
+ }
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\subsubsection{Messages}
+%
+% The text for error messages: short and long text for all of them.
+% \begin{macrocode}
+\msg_kernel_new:nnnn { xtemplate } { argument-number-mismatch }
+ {Object type `#1' takes `#2' not `#3' argument(s).}
+ {%
+ Objects of type `#1' require `#2' arguments.\\%
+ You have tried to make a template for `#1'\\%
+ with `#3' arguments, which is not possible:\\%
+ the number of arguments must agree.%
+ }
+\msg_kernel_new:nnnn { xtemplate } { bad-number-of-arguments }
+ {%
+ Impossible number of arguments declared for\\%
+ object type `#1'.%
+ }
+ {%
+ An object may accept between 0 and 9 arguments.\\%
+ You asked to use #2 arguments: this is not supported.%
+ }
+\msg_kernel_new:nnnn { xtemplate } { bad-variable }
+ {Incorrect variable description \msg_line_context:.}
+ {%
+ The argument `#1'\\%
+ is not of the form `<variable>' or `global <variable>'.\\%
+ It must be given in one of these formats to be used in a template.%
+ }
+\msg_kernel_new:nnnn { xtemplate } { choice-not-implemented }
+ {The choice `#1' has no implementation \msg_line_context:.}
+ {%
+ Each choice listed in the interface for a template must\\%
+ have an implementation.\\%
+ I did not find an implementation for `#1'.%
+ }
+\msg_kernel_new:nnnn { xtemplate } { choice-unknown-reserved }
+ {The choice `unknown' cannot be given for a template key.}
+ {%
+ The `unknown' choice is automatically checked by template when\\%
+ a choice key is given with an unknown value. It should not be\\%
+ included in the list of named choices for a key, and is always\\%
+ given last in the implementation of choices.%
+ }
+\msg_kernel_new:nnnn { xtemplate } { duplicate-key-interface }
+ {Key `#1' appears twice in interface definition \msg_line_context:.}
+ {%
+ Each key can only have one interface declared in a template.\\%
+ I found two interfaces for `#1': probably a typing error.%
+ }
+\msg_kernel_new:nnnn { xtemplate } { empty-key-name }
+ {No key name found in `#1' \msg_line_context:.}
+ {%
+ A template key name and type is given in the form:\\%
+ \msg_space: <name> : <type> \\%
+ Parsing your input, I found a `:' but nothing before
+ it!%
+ }
+\msg_kernel_new:nnnn { xtemplate } { key-no-value }
+ {The key `#1' has no value \msg_line_context:.}
+ {%
+ When creating an instance of a template\\%
+ every key listed must include a value:
+ \msg_two_spaces: <key> = <value>
+ }
+\msg_kernel_new:nnnn { xtemplate } { key-no-variable }
+ {The key `#1' requires implementation details \msg_line_context:.}
+ {%
+ When creating template code using
+ \token_to_str:N \DeclareTemplateCode,\\%
+ each key name must have an associated implementation.\\%
+ This should be given after an `=' sign: I did not find one.%
+ }
+\msg_kernel_new:nnnn { xtemplate } { key-not-implemented }
+ {Key `#1' has no implementation \msg_line_context:.}
+ {%
+ The definition of key implementations for template `#2'\\%
+ of object type `#3' does not include any details for key `#1'.\\%
+ The key was declared in the interface definition,\\%
+ and so an implementation is required.%
+ }
+\msg_kernel_new:nnnn { xtemplate } { keytype-requires-argument }
+ {The keytype `#1' requires an argument \msg_line_context:}
+ {%
+ You should have put:\\%
+ \msg_two_spaces: <key-name> : #1
+ \token_to_str:N { <argument> \token_to_str:N } \\%
+ but I did not find an <argument>.%
+ }
+\msg_kernel_new:nnnn { xtemplate } { no-keytype }
+ {The key `#1' is missing a keytype \msg_line_context:}
+ {%
+ You should have put:\\%
+ \msg_two_spaces: #1 : <keytype>\\%
+ but I did not find an <keytype>.%
+ }
+\msg_kernel_new:nnnn { xtemplate } { no-template-code }
+ {%
+ The template `#2' of type `#1' is unknown\\%
+ or has no implementation.%
+ }
+ {%
+ You need to declare a template with
+ \token_to_str:N \DeclareTemplateInterface \\%
+ and its code with
+ \token_to_str:N \DeclareTemplateCode \msg_space:
+ prior to using it.%
+ }
+\msg_kernel_new:nnnn { xtemplate } { type-mismatch }
+ {Object types `#1' and `#2' do not agree.}
+ {%
+ You are trying to use a template directly with
+ \token_to_str:N \UseInstance \\%
+ (or a similar function), but the object types do not match.%
+ }
+\msg_kernel_new:nnnn { xtemplate } { undeclared-variable }
+ {The variable #1has not been declared.}
+ {%
+ Before declaring an instance, all of the required variables\\%
+ used in template keys must be created.%
+ }
+\msg_kernel_new:nnnn { xtemplate } { unknown-attribute }
+ {The template attribute `#1' is unknown.}
+ {%
+ There is a definition in the current template reading\\%
+ \token_to_str:N \KeyValue
+ \token_to_str:N { #1 \token_to_str:N }\\%
+ but there is no key called `#1'.%
+ }
+\msg_kernel_new:nnnn { xtemplate } { unknown-choice }
+ {The choice `#1' was not declared for key `#2' \msg_line_context:.}
+ {%
+ The key `#2' takes a fixed number of choices:\\%
+ \clist_map_function:NN #3 \xtemplate_unknown_choice_aux:n
+ and this list does not include `#1'.%
+ }
+\cs_new:Npn \xtemplate_unknown_choice_aux:n #1 { -~ #1 ;\\}
+\msg_kernel_new:nnnn { xtemplate } { unknown-keytype }
+ {The keytype `#1' is unknown \msg_line_context:.}
+ {%
+ Valid keytypes are:\\%
+ - boolean;\\%
+ - choice;\\%
+ - code;\\%
+ - commalist;\\%
+ - function;\\%
+ - instance;\\%
+ - integer;\\%
+ - length;\\%
+ - skip;\\%
+ - tokenlist.%
+ }
+\msg_kernel_new:nnnn { xtemplate } { unknown-object-type }
+ {The object type `#1' is unknown \msg_line_context:.}
+ {%
+ An object type needs to be declared with
+ \token_to_str:N \DeclareObjectType \msg_space:
+ prior to using it.%
+ }
+\msg_kernel_new:nnnn { xtemplate } { unknown-instance }
+ {The instance `#2' of type `#1' is unknown.}
+ {%
+ You have asked to use an instance `#2',\\%
+ but this has not been created.%
+ }
+\msg_kernel_new:nnnn { xtemplate } { unknown-key }
+ {Unknown template key `#1' \msg_line_context:.}
+ {%
+ The key `#1' was not declared in the interface\\%
+ for the current template.\\%
+ Probably you have misspelled the key name.%
+ }
+\msg_kernel_new:nnnn { xtemplate } { unknown-template }
+ {The template `#2' of type `#1' is unknown \msg_line_context:.}
+ {%
+ No interface has been declared for a template\\%
+ `#2' of object type `#1'.%
+ }
+% \end{macrocode}
+%
+% Information messages only have text: more text should not be needed.
+% \begin{macrocode}
+\msg_kernel_new:nnn { xtemplate } { define-template-code }
+ {Defining template code for `#1' \msg_line_context:.}
+\msg_kernel_new:nnn { xtemplate } { define-template-interface }
+ {Defining template interface for `#1' \msg_line_context:.}
+\msg_kernel_new:nnn { xtemplate } { define-object-type }
+ {Defining object type `#1' with #2 argument(s) \msg_line_context:.}
+\msg_kernel_new:nnn { xtemplate } { redefine-template-code }
+ {Redefining template code for `#1' \msg_line_context:.}
+\msg_kernel_new:nnn { xtemplate } { redefine-template-interface }
+ {Redefining template interface for `#1' \msg_line_context:.}
+\msg_kernel_new:nnn { xtemplate } { redefine-object-type }
+ {Redefining object type `#1' with #2 argument(s) \msg_line_context:.}
+% \end{macrocode}
+%
+%\subsubsection{User functions}
+%
+% The user functions provided by \pkg{xtemplate} are pretty much direct
+% copies of internal ones. However, by sticking to the \pkg{xparse}
+% approach only the appropriate arguments are long.
+%
+%\begin{macro}{\DeclareObjectType}
+%\begin{macro}{\DeclareTemplateInterface}
+%\begin{macro}{\DeclareTemplateCode}
+%\begin{macro}{\DeclareRestrictedTemplate}
+%\begin{macro}{\EditTemplateDefaults}
+%\begin{macro}{\DeclareInstance}
+%\begin{macro}{\DeclareCollectionInstance}
+%\begin{macro}{\EditInstance}
+%\begin{macro}{\EditCollectionInstance}
+%\begin{macro}{\UseTemplate}
+%\begin{macro}{\UseInstance}
+%\begin{macro}{\UseCollection}
+% All simple translations, with the appropriate long/short argument
+% filtering.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \DeclareObjectType #1#2 {
+ \xtemplate_declare_object_type:nn {#1} {#2}
+}
+\cs_new_protected:Npn \DeclareTemplateInterface #1#2#3#4 {
+ \xtemplate_declare_template_keys:nnnn {#1} {#2} {#3} {#4}
+}
+\cs_new_protected:Npn \DeclareTemplateCode #1#2#3#4#5 {
+ \xtemplate_declare_template_code:nnnnn {#1} {#2} {#3} {#4} {#5}
+}
+\cs_new_protected:Npn \DeclareRestrictedTemplate #1#2#3#4 {
+ \xtemplate_declare_restricted:nnnn {#1} {#2} {#3} {#4}
+}
+\cs_new_protected:Npn \DeclareInstance #1#2#3#4 {
+ \xtemplate_declare_instance:nnnnn {#1} {#3} { } {#2} {#4}
+}
+\cs_new_protected:Npn \DeclareCollectionInstance #1#2#3#4#5 {
+ \xtemplate_declare_instance:nnnnn {#2} {#4} {#1} {#3} {#5}
+}
+\cs_new_protected:Npn \EditTemplateDefaults #1#2#3 {
+ \xtemplate_edit_defaults:nnn {#1} {#2} {#3}
+}
+\cs_new_protected:Npn \EditInstance #1#2#3 {
+ \xtemplate_edit_instance:nnnn {#1} { } {#2} {#3}
+}
+\cs_new_protected:Npn \EditCollectionInstance #1#2#3#4 {
+ \xtemplate_edit_instance:nnnn {#2} {#1} {#3} {#4}
+}
+\cs_new_protected_nopar:Npn \UseTemplate #1#2#3 {
+ \xtemplate_use_template:nnn {#1} {#2} {#3}
+}
+\cs_new_protected_nopar:Npn \UseInstance #1#2 {
+ \xtemplate_use_instance:nn {#1} {#2}
+}
+\cs_new_protected_nopar:Npn \UseCollection #1#2 {
+ \xtemplate_use_collection:nn {#1} {#2}
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\ShowTemplateCode}
+%\begin{macro}{\ShowTemplateDefaults}
+%\begin{macro}{\ShowTemplateKeytypes}
+%\begin{macro}{\ShowTemplateVariables}
+%\begin{macro}{\ShowInstanceValues}
+%\begin{macro}{\ShowCollectionInstanceValues}
+% The show functions are again just translation.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \ShowTemplateCode #1#2 {
+ \xtemplate_show_code:nn {#1} {#2}
+}
+\cs_new_protected_nopar:Npn \ShowTemplateDefaults #1#2 {
+ \xtemplate_show_defaults:nn {#1} {#2}
+}
+\cs_new_protected_nopar:Npn \ShowTemplateKeytypes #1#2 {
+ \xtemplate_show_keytypes:nn {#1} {#2}
+}
+\cs_new_protected_nopar:Npn \ShowTemplateVariables #1#2 {
+ \xtemplate_show_vars:nn {#1} {#2}
+}
+\cs_new_protected_nopar:Npn \ShowInstanceValues #1#2 {
+ \xtemplate_show_values:nnn {#1} { } {#2}
+}
+\cs_new_protected_nopar:Npn \ShowCollectionInstanceValues #1#2#3 {
+ \xtemplate_show_values:nnn {#1} {#2} {#3}
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}[TF]{\IfInstanceExist}
+% More direct translation: only the base instance is checked for.
+% \begin{macrocode}
+\cs_new_nopar:Npn \IfInstanceExistTF #1#2 {
+ \xtemplate_if_instance_exist:nnnTF {#1} { } {#2}
+}
+\cs_new_nopar:Npn \IfInstanceExistT #1#2 {
+ \xtemplate_if_instance_exist:nnnT {#1} { } {#2}
+}
+\cs_new_nopar:Npn \IfInstanceExistF #1#2 {
+ \xtemplate_if_instance_exist:nnnF {#1} { } {#2}
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\EvaluateNow}
+%\begin{macro}{\KeyValue}
+% These are both do nothing functions. Both simply dump their arguments
+% when executed: this should not happen with \cs{KeyValue}.
+%
+% They need to be expandable as they might get called in the context of
+% setting some register value.
+% \begin{macrocode}
+\cs_new_protected:Npn \EvaluateNow #1 {#1}
+\cs_new_protected:Npn \KeyValue #1 {#1}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\AssignTemplateKeys}
+% A short call to use a token register by proxy.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \AssignTemplateKeys {
+ \xtemplate_assignments_pop:
+}
+% \end{macrocode}
+%\end{macro}
+%
+%
+%
+%\subsubsection{Recent additions to the code}
+%
+% \begin{macro}{\TP_split_finite_skip_value:nnNN}
+% This macro is for use in error checking template values like
+% "text-float-sep" that can't contain infinite glue and needs the
+% shrink and/or stretch components. First argument is the skip
+% register (which is likely to be user input), second is a template
+% key name, and the last two are the \meta{dimen} registers that
+% stores the stretch and shrink components. Assignments are global.
+% \begin{macrocode}
+\cs_new_nopar:Npn \TP_split_finite_skip_value:nnNN #1#2{
+ \skip_split_finite_else_action:nnNN {#1} {
+ \PackageError{xtemplate}{Value~ for~ key~ #2~ contains~ `fil(ll)'}
+ {Only~ finite~ minus~ or~ plus~ parts~ are~ allowed~ for~ this~ key.}
+ }
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+%</initex|package>
+% \end{macrocode}
+%
+%\PrintIndex
+%
+%\end{implementation}
diff --git a/Master/texmf-dist/source/latex/xpackages/xtras/l3keys2e.dtx b/Master/texmf-dist/source/latex/xpackages/xtras/l3keys2e.dtx
index 9595206ee53..91e4dac4c48 100644
--- a/Master/texmf-dist/source/latex/xpackages/xtras/l3keys2e.dtx
+++ b/Master/texmf-dist/source/latex/xpackages/xtras/l3keys2e.dtx
@@ -196,7 +196,7 @@
% \texttt{unknown} key is set if it does not already exist for the
% current module.
% \begin{macrocode}
-\cs_new:Nn \keys_latexe_options:n {
+\cs_new:Npn \keys_latexe_options:n #1 {
\clist_clear:N \keys_latexe_options_clist
\keys_latexe_options_global:n {#1}
\keys_latexe_options_local:
@@ -224,7 +224,7 @@
% file type. The initial test is needed as \LaTeXe\ allows variables to
% be equal to \cs{scan_stop:}, which is forbidden in \LaTeX3 code.
% \begin{macrocode}
-\cs_new:Nn \keys_latexe_options_global:n {
+\cs_new:Npn \keys_latexe_options_global:n #1 {
\cs_if_eq:NNF \@classoptionslist \scan_stop: {
\cs_if_eq:NNTF \@currext \@clsextension {
\keys_latexe_options_class:n {#1}
@@ -242,7 +242,7 @@
% the combined list for processing. On the other hand, unused options
% are stored up in \cs{@unusedoptionlist}.
% \begin{macrocode}
-\cs_new:Nn \keys_latexe_options_class:n {
+\cs_new:Npn \keys_latexe_options_class:n #1 {
\clist_map_inline:Nn \@classoptionslist {
\keys_if_exist:nnTF {#1} { \keys_latexe_remove_equals:n {##1} } {
\clist_put_right:Nn \keys_latexe_options_clist {##1}
@@ -260,7 +260,7 @@
% there is nothing to do if the option is not applicable. Each valid
% option also needs to be removed from \cs{@unusedoptionlist}.
% \begin{macrocode}
-\cs_new:Nn \keys_latexe_options_package:n {
+\cs_new:Npn \keys_latexe_options_package:n #1 {
\clist_map_inline:Nn \@classoptionslist {
\keys_if_exist:nnT {#1} { \keys_latexe_remove_equals:n {##1} } {
\clist_put_right:Nn \keys_latexe_options_clist {##1}
@@ -276,7 +276,7 @@
% \LaTeXe\ stores options for each file in a macro which may or may not
% exist, hence the need to use \cs{cs_if_exist:c}.
% \begin{macrocode}
-\cs_new_nopar:Nn \keys_latexe_options_local: {
+\cs_new_nopar:Npn \keys_latexe_options_local: {
\cs_if_eq:NNF \@currext \@clsextension {
\cs_if_exist:cT { opt@ \@currname . \@currext } {
\exp_args:NNc \clist_put_right:NV \keys_latexe_options_clist
@@ -293,7 +293,7 @@
% sign from the input. This is all wrapped up in an \texttt{n} function
% so that there will always be a sign available.
% \begin{macrocode}
-\cs_new:Nn \keys_latexe_remove_equals:n {
+\cs_new:Npn \keys_latexe_remove_equals:n #1 {
\keys_latexe_remove_equals:w #1 = \q_stop
}
\cs_new:Npn \keys_latexe_remove_equals:w #1 = #2 \q_stop {#1}
diff --git a/Master/texmf-dist/tex/latex/xpackages/xbase/ldcsetup.sty b/Master/texmf-dist/tex/latex/xpackages/xbase/ldcsetup.sty
index 7f26ce16cbb..915f77a1f2e 100644
--- a/Master/texmf-dist/tex/latex/xpackages/xbase/ldcsetup.sty
+++ b/Master/texmf-dist/tex/latex/xpackages/xbase/ldcsetup.sty
@@ -38,7 +38,7 @@
%%
%% The development version of the bundle can be found at
%%
-%% http://www.latex-project.org/cgi-bin/cvsweb.cgi/
+%% http://www.latex-project.org/svnroot/experimental/trunk/
%%
%% for those people who are interested.
%%
@@ -54,7 +54,7 @@
%% -----------------------------------------------------------------------
%%
\RequirePackage{expl3}
-\GetIdInfo$Id: ldcsetup.dtx 1295 2009-05-06 08:32:25Z will $
+\GetIdInfo$Id: ldcsetup.dtx 1628 2009-10-25 09:54:34Z mittelba $
{coding conventions and stuff}
\ProvidesExplPackage
{\filename}{\filedate}{\fileversion}{\filedescription}
diff --git a/Master/texmf-dist/tex/latex/xpackages/xbase/template.sty b/Master/texmf-dist/tex/latex/xpackages/xbase/template.sty
index b91b2d6715e..0e900e2323a 100644
--- a/Master/texmf-dist/tex/latex/xpackages/xbase/template.sty
+++ b/Master/texmf-dist/tex/latex/xpackages/xbase/template.sty
@@ -38,7 +38,7 @@
%%
%% The development version of the bundle can be found at
%%
-%% http://www.latex-project.org/cgi-bin/cvsweb.cgi/
+%% http://www.latex-project.org/svnroot/experimental/trunk/
%%
%% for those people who are interested.
%%
@@ -54,7 +54,7 @@
%% -----------------------------------------------------------------------
%%
\RequirePackage{expl3}
-\GetIdInfo$Id: template.dtx 1461 2009-08-15 08:38:12Z joseph $
+\GetIdInfo$Id: template.dtx 1670 2009-11-01 22:34:54Z will $
{template}
\ProvidesExplPackage
{\filename}{\filedate}{\fileversion}{\filedescription}
@@ -62,7 +62,7 @@
\RequirePackage{ldcsetup,xparse}
\toks_new:N\l_TP_KV_assignments_toks
\toks_new:N\l_TP_default_assignments_toks
-\cs_new_nopar:Nn \TP_declare_instance:Nnn {
+\cs_new_nopar:Npn \TP_declare_instance:Nnn #1#2#3 {
\group_begin:
\TP_instdecl_generate_assignments:nn {#2}{#3}
\cs_gset_nopar:Npx #1 {
@@ -103,12 +103,12 @@
}
\cs_new_nopar:Npn \DeclareTemplateType #1#2{
\tl_set:cn {TP@<#1>} {{}#2}}
-\cs_new_nopar:Nn \TP_get_csname_prefix:n {
+\cs_new_nopar:Npn \TP_get_csname_prefix:n #1 {
<\exp_after:wN\exp_after:wN\exp_after:wN
\use_i:nn
\cs:w TP@<#1>\cs_end:>#1/
}
-\cs_new_nopar:Nn \TP_get_arg_count:n {
+\cs_new_nopar:Npn \TP_get_arg_count:n #1 {
\exp_after:wN\exp_after:wN\exp_after:wN
\use_ii:nn
\cs:w TP@<#1>\cs_end:
@@ -141,12 +141,12 @@
\cs_set:Npn {#3}{#5}
}
\cs_set:Npn \tl_set:cx {\exp_args:Nc \tl_set:Nx}
-\cs_new_nopar:Nn \TP_templdecl_process_KV:nn {%
+\cs_new_nopar:Npn \TP_templdecl_process_KV:nn #1#2 {%
\cs_set_eq:NN \TP_templdecl_add_global_or_nothing: \prg_do_nothing:
\bool_set_false:N\l_TP_global_assignment_bool
\tl_set:Nn\l_TP_currkey_tl{#1}
\TP_templdecl_parse_KV:N#2\q_stop}
-\cs_new_nopar:Nn \TP_templdecl_parse_KV:N {
+\cs_new_nopar:Npn \TP_templdecl_parse_KV:N #1 {
\cs_if_free:cTF{TP_use_arg_type_#1:w}
{\PackageError{template}{Unknown~key~type~ (#1)~for~\l_TP_currkey_tl}\@eha}
{\use:c{TP_use_arg_type_#1:w}}
diff --git a/Master/texmf-dist/tex/latex/xpackages/xbase/xparse.sty b/Master/texmf-dist/tex/latex/xpackages/xbase/xparse.sty
index 9bc5164a748..9b542606a88 100644
--- a/Master/texmf-dist/tex/latex/xpackages/xbase/xparse.sty
+++ b/Master/texmf-dist/tex/latex/xpackages/xbase/xparse.sty
@@ -57,7 +57,7 @@
%% -----------------------------------------------------------------------
%%
\RequirePackage{l3names}
-\GetIdInfo$Id: xparse.dtx 1497 2009-08-31 19:17:53Z joseph $
+\GetIdInfo$Id: xparse.dtx 1727 2009-11-06 22:58:32Z joseph $
{Generic document command parser}
\ProvidesExplPackage
{\filename}{\filedate}{\fileversion}{\filedescription}
@@ -69,6 +69,7 @@
\toks_new:N \l_xparse_arg_toks
\toks_new:N \l_xparse_args_toks
\toks_new:N \l_xparse_environment_args_toks
+\bool_new:N \l_xparse_environment_bool
\bool_new:N \l_xparse_error_bool
\tl_new:N \l_xparse_function_tl
\toks_new:N \l_xparse_last_arg_tl
@@ -76,13 +77,15 @@
\int_new:N \l_xparse_m_args_int
\bool_new:N \l_xparse_m_only_bool
\int_new:N \l_xparse_mandatory_args_int
+\int_new:N \l_xparse_nested_int
+\toks_new:N \l_xparse_nested_toks
\bool_new:N \l_xparse_processor_bool
\int_new:N \l_xparse_processor_int
\toks_new:N \l_xparse_signature_toks
\tl_new:N \l_xparse_tmp_tl
\int_new:N \l_xparse_total_args_int
\quark_new:N \q_xparse_stop
-\cs_new_nopar:Nn \xparse_add_grabber_mandatory:N {
+\cs_new_nopar:Npn \xparse_add_grabber_mandatory:N #1 {
\toks_put_right:Nx \l_xparse_signature_toks {
\exp_not:c {
xparse_grab_ #1 \bool_if:NT \l_xparse_long_bool { _long } :w
@@ -91,7 +94,7 @@
\bool_set_false:N \l_xparse_long_bool
\int_decr:N \l_xparse_mandatory_args_int
}
-\cs_new_nopar:Nn \xparse_add_grabber_optional:N {
+\cs_new_nopar:Npn \xparse_add_grabber_optional:N #1 {
\toks_put_right:Nx \l_xparse_signature_toks {
\exp_not:c {
xparse_grab_ #1
@@ -166,19 +169,19 @@
\toks_put_right:Nn \l_xparse_signature_toks { {#1} }
\xparse_prepare_signature:N
}
-\cs_new_nopar:Nn \xparse_check_and_add:N {
+\cs_new_nopar:Npn \xparse_check_and_add:N #1 {
\cs_if_free:cTF { xparse_add_type_ #1 :w } {
- \msg_error:nnx { xparse } { unknown-argument-type } {#1}
+ \msg_kernel_error:nnx { xparse } { unknown-argument-type } {#1}
\xparse_add_type_m:w
}{
\use:c { xparse_add_type_ #1 :w }
}
}
-\cs_new:Nn \xparse_count_mandatory:n {
+\cs_new:Npn \xparse_count_mandatory:n #1 {
\int_zero:N \l_xparse_mandatory_args_int
\xparse_count_mandatory:N #1 \q_nil
}
-\cs_new:Nn \xparse_count_mandatory:N {
+\cs_new: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
@@ -188,7 +191,7 @@
}
}
}
-\cs_new:Nn \xparse_count_mandatory_aux:N {
+\cs_new:Npn \xparse_count_mandatory_aux:N #1 {
\cs_if_free:cTF { xparse_count_type_ #1 :w } {
\xparse_count_type_m:w
}{
@@ -228,7 +231,19 @@
\int_incr:N \l_xparse_mandatory_args_int
\xparse_count_mandatory:N
}
-\cs_new:Nn \xparse_declare_cmd:Nnn {
+\cs_new:Npn \xparse_declare_cmd:Nnn #1#2 {
+ \cs_if_exist:NTF #1
+ {
+ \msg_kernel_warning:nnxx { xparse } { redefine-command }
+ { \exp_not:N #1 } { \exp_not:n {#2} }
+ }
+ {
+ \msg_kernel_info:nnxx { xparse } { define-command }
+ { \exp_not:N #1 } { \exp_not:n {#2} }
+ }
+ \xparse_declare_cmd_aux:Nnn #1 {#2}
+}
+\cs_new:Npn \xparse_declare_cmd_aux:Nnn #1#2#3 {
\xparse_count_mandatory:n {#2}
\xparse_prepare_signature:n {#2}
\bool_if:NTF \l_xparse_m_only_bool {
@@ -237,12 +252,12 @@
\xparse_declare_cmd_mixed:Nn #1 {#3}
}
}
-\cs_generate_variant:Nn \xparse_declare_cmd:Nnn { cnn }
-\cs_new:Nn \xparse_declare_cmd_all_m:Nn {
+\cs_generate_variant:Nn \xparse_declare_cmd_aux:Nnn { cnn }
+\cs_new: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:Nn \xparse_declare_cmd_mixed:Nn {
+\cs_new:Npn \xparse_declare_cmd_mixed:Nn #1#2 {
\cs_set_protected_nopar:Npx #1 {
\exp_not:n {
\int_zero:N \l_xparse_processor_int
@@ -254,11 +269,11 @@
\cs_generate_from_arg_count:cNnn
{ \token_to_str:N #1 } \cs_set:Npn \l_xparse_total_args_int {#2}
}
-\cs_new:Nn \xparse_declare_cmd_implementation:nNn {
+\cs_new:Npn \xparse_declare_cmd_implementation:nNn #1#2#3 {
\cs_generate_from_arg_count:cNnn { implementation_ #1 :w }
\cs_set:Npn {#2} {#3}
}
-\cs_new:Nn \xparse_declare_cmd_interface:Nnn {
+\cs_new: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}
@@ -268,12 +283,12 @@
\cs_generate_from_arg_count:cNnn { implementation_ #2 :w }
\cs_set:Npn \l_xparse_total_args_int { ``#2'' }
}
-\cs_new:Nn \xparse_declare_cmd_interface_all_m:Nn {
+\cs_new: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:Nn \xparse_declare_cmd_interface_mixed:Nn {
+\cs_new: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
@@ -286,20 +301,31 @@
{ \token_to_str:N #1 } \cs_set:Npn \l_xparse_total_args_int
{ \use:c { implementation_ #2 :w } }
}
-\cs_new:Nn \xparse_declare_env:nnnn {
- \xparse_declare_cmd:cnn { environment_begin_ #1 :w } {#2} {
+\cs_new:Npn \xparse_declare_env:nnnn #1#2#3#4 {
+ \bool_set_true:N \l_xparse_environment_bool
+ \cs_if_exist:cTF {#1}
+ {
+ \msg_kernel_warning:nnxx { xparse } { redefine-environment }
+ {#1} { \exp_not:n {#2} }
+ }
+ {
+ \msg_kernel_info:nnxx { xparse } { define-environment }
+ {#1} { \exp_not:n {#2} }
+ }
+ \xparse_declare_cmd_aux:cnn { environment_begin_ #1 :w } {#2} {
\group_begin:
\toks_set_eq:NN \l_xparse_environment_args_toks
\l_xparse_args_toks
#3
}
+ \bool_set_false:N \l_xparse_environment_bool
\cs_set_nopar:cpx { environment_end_ #1 :w } {
\exp_not:N \exp_last_unbraced:NV
\exp_not:c { environment_end_ #1 _aux:N }
\exp_not:N \l_xparse_environment_args_toks
\exp_not:N \group_end:
}
- \cs_set_nopar:cx { environment_end_ #1 _aux:N } {
+ \cs_set_nopar:cpx { environment_end_ #1 _aux:N } ##1 {
\exp_not:c { environment_end_ #1 _aux :w }
}
\cs_generate_from_arg_count:cNnn
@@ -308,7 +334,7 @@
\cs_set_eq:cc {#1} { environment_begin_ #1 :w }
\cs_set_eq:cc { end #1 } { environment_end_ #1 :w }
}
-\cs_new_nopar:Nn \xparse_flush_m_args: {
+\cs_new_nopar:Npn \xparse_flush_m_args: {
\cs_if_exist:cT {
xparse_grab_m_ \int_use:N \l_xparse_m_args_int :w
} {
@@ -329,20 +355,24 @@
\prg_return_false:
}
}
-\cs_new:Nn \xparse_prepare_signature:n {
+\cs_new:Npn \xparse_prepare_signature:n #1 {
\bool_set_false:N \l_xparse_long_bool
\int_zero:N \l_xparse_m_args_int
- \bool_set_true:N \l_xparse_m_only_bool
+ \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
\toks_clear:N \l_xparse_signature_toks
\int_zero:N \l_xparse_total_args_int
\xparse_prepare_signature:N #1 \q_nil
}
-\cs_new:Nn \xparse_prepare_signature:N {
+\cs_new:Npn \xparse_prepare_signature:N #1 {
\bool_set_false:N \l_xparse_processor_bool
\xparse_prepare_signature_aux:N #1
}
-\cs_new:Nn \xparse_prepare_signature_aux:N {
+\cs_new:Npn \xparse_prepare_signature_aux:N #1 {
\quark_if_nil:NTF #1 {
\bool_if:NF \l_xparse_m_only_bool {
\xparse_flush_m_args:
@@ -352,19 +382,19 @@
\prop_get:NnN \c_xparse_shorthands_prop {#1} \l_xparse_tmp_tl
\exp_last_unbraced:NV \xparse_prepare_signature:N \l_xparse_tmp_tl
}{
- \int_incr:N \l_xparse_total_args_int
+ \int_incr:N \l_xparse_total_args_int
\xparse_check_and_add:N #1
}
}
}
-\cs_new:Nn \xparse_process_arg:n {
+\cs_new:Npn \xparse_process_arg:n #1 {
\int_incr:N \l_xparse_processor_int
- \cs_set:cn {
+ \cs_set:cpn {
xparse_processor_ \int_use:N \l_xparse_processor_int :n
- }
+ } ##1
{ #1 {##1} }
}
-\cs_new:Nn \xparse_add_arg:n {
+\cs_new:Npn \xparse_add_arg:n #1 {
\intexpr_compare:nTF { \l_xparse_processor_int = \c_zero } {
\toks_put_right:Nn \l_xparse_args_toks { {#1} }
}{
@@ -376,20 +406,24 @@
}
}
}
-\cs_new:Nn \xparse_add_arg_aux:n {
+\cs_generate_variant:Nn \xparse_add_arg:n { V }
+\cs_new:Npn \xparse_add_arg_aux:n #1 {
+ \cs_set_eq:NN \ProcessedArgument \l_xparse_arg_toks
\use:c { xparse_processor_ \int_use:N \l_xparse_processor_int :n }
{#1}
\int_decr:N \l_xparse_processor_int
\intexpr_compare:nTF { \l_xparse_processor_int = \c_zero } {
- \toks_put_right:No \l_xparse_args_toks {
- \exp_after:wN { \toks_use:N \l_xparse_arg_toks }
+ \toks_put_right:Nx \l_xparse_args_toks {
+ { \exp_not:V \ProcessedArgument }
}
}{
- \xparse_add_arg_aux:V \l_xparse_arg_toks
+ \xparse_add_arg_aux:V \ProcessedArgument
}
}
\cs_generate_variant:Nn \xparse_add_arg_aux:n { V }
-\cs_new:Npn \xparse_grab_aux:w { }
+\cs_new:Npn \xparse_grab_arg:w { }
+\cs_new:Npn \xparse_grab_arg_aux_i:w { }
+\cs_new:Npn \xparse_grab_arg_aux_ii:w { }
\cs_new:Npn \xparse_grab_D:w #1#2#3#4 \l_xparse_args_toks {
\xparse_grab_D_aux:NNnnNn #1 #2 {#3} {#4} \cs_set_nopar:Npn
{ _ignore_spaces }
@@ -405,10 +439,28 @@
\l_xparse_args_toks {
\xparse_grab_D_aux:NNnnNn #1 #2 {#3} {#4} \cs_set:Npn { }
}
-\cs_set:Nn \xparse_grab_D_aux:NNnnNn {
- #5 \xparse_grab_arg:w #1 ##1 #2 {
- \xparse_add_arg:n {##1}
- #4 \l_xparse_args_toks
+\cs_new: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 {#4} #5 {##1}
+ }{
+ \xparse_add_arg:n {##1}
+ #4 \l_xparse_args_toks
+ }
}
\use:c { peek_charcode #6 :NTF } #1 {
\xparse_grab_arg:w
@@ -417,6 +469,30 @@
#4 \l_xparse_args_toks
}
}
+\cs_new:Npn \xparse_grab_D_nested:NNnNn #1#2#3#4#5 {
+ \int_zero:N \l_xparse_nested_int
+ \toks_set:Nn \l_xparse_nested_toks { #5 #2 }
+ \cs_set:Npn \xparse_grab_D_nested_aux:n ##1 {
+ \tl_if_eq:nnT {#1} {##1} {
+ \int_incr:N \l_xparse_nested_int
+ }
+ }
+ \tl_map_function:nN {#5} \xparse_grab_D_nested_aux:n
+ #4 \xparse_grab_arg:w ##1 #2 {
+ \int_decr:N \l_xparse_nested_int
+ \tl_map_function:nN {##1} \xparse_grab_D_nested_aux:n
+ \intexpr_compare:nTF { \l_xparse_nested_int = \c_zero } {
+ \toks_put_right:Nn \l_xparse_nested_toks {##1}
+ \xparse_add_arg:V \l_xparse_nested_toks
+ #3 \l_xparse_args_toks
+ }{
+ \toks_put_right:Nn \l_xparse_nested_toks { ##1 #2 }
+ \xparse_grab_arg:w
+ }
+ }
+ \xparse_grab_arg:w
+}
+\cs_new:Npn \xparse_grab_D_nested_aux:n #1 { }
\cs_new:Npn \xparse_grab_G:w #1#2 \l_xparse_args_toks {
\xparse_grab_G_aux:nnNn {#1} {#2} \cs_set_nopar:Npn { _ignore_spaces }
}
@@ -429,7 +505,7 @@
\cs_new:Npn \xparse_grab_G_long_trailing:w #1#2 \l_xparse_args_toks {
\xparse_grab_G_aux:nnNn {#1} {#2} \cs_set:Npn { }
}
-\cs_set:Nn \xparse_grab_G_aux:nnNn {
+\cs_set: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_toks
@@ -447,9 +523,9 @@
\cs_new:Npn \xparse_grab_l_long:w #1 \l_xparse_args_toks {
\xparse_grab_l_aux:nN {#1} \cs_set:Npn
}
-\cs_new:Nn \xparse_grab_l_aux:nN {
+\cs_new:Npn \xparse_grab_l_aux:nN #1#2 {
#2 \xparse_grab_arg:w ##1## {
- \xparse_add_arg:n \l_xparse_args_toks {##1}
+ \xparse_add_arg:n {##1}
#1 \l_xparse_args_toks
}
\xparse_grab_arg:w
@@ -544,7 +620,7 @@
\cs_new:Npn \xparse_grab_t_long_trailing:w #1#2 \l_xparse_args_toks {
\xparse_grab_t_aux:NnNn #1 {#2} \cs_set:Npn { }
}
-\cs_new:Nn \xparse_grab_t_aux:NnNn {
+\cs_new: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 }
@@ -562,27 +638,27 @@
\cs_new:Npn \xparse_grab_u_long:w #1#2 \l_xparse_args_toks {
\xparse_grab_u_aux:NnN {#1} {#2} \cs_set:Npn
}
-\cs_new:Nn \xparse_grab_u_aux:NnN {
+\cs_new: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_toks
}
\xparse_grab_arg:w
}
-\cs_new:Nn \xparse_process_to_str:n {
- \toks_set:Nx \l_xparse_arg_toks {
+\cs_new:Npn \xparse_process_to_str:n #1 {
+ \toks_set:Nx \ProcessedArgument {
\tl_to_str:n {#1}
}
}
-\cs_new:Nn \xparse_process_comma_split:n {
+\cs_new:Npn \xparse_process_comma_split:n #1 {
\tl_if_in:nnTF {#1} { , } {
\xparse_process_comma_split_aux:w #1 \q_stop
}{
- \toks_set:Nn \l_xparse_arg_toks { {#1} { \NoValue } }
+ \toks_set:Nn \ProcessedArgument { {#1} { \NoValue } }
}
}
\cs_new:Npn \xparse_process_comma_split_aux:w #1 , #2 \q_stop {
- \toks_set:Nn \l_xparse_arg_toks { {#1} {#2} }
+ \toks_set:Nn \ProcessedArgument { {#1} {#2} }
}
\cs_new:Npn \xparse_exp_add_type_d:w #1#2 {
\xparse_exp_add_type_D:w #1 #2 { \NoValue }
@@ -669,9 +745,9 @@
}
\xparse_exp_prepare_function:N
}
-\cs_new_nopar:Nn \xparse_exp_check_and_add:N {
+\cs_new_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 } {#1}
+ \msg_kernel_error:nnx { xparse } { unknown-argument-type } {#1}
\tl_set:Nn \l_xparse_last_arg_tl { m }
\xparse_exp_add_type_m:w
}{
@@ -679,7 +755,16 @@
\use:c { xparse_exp_add_type_ #1 :w }
}
}
-\cs_new:Nn \xparse_exp_declare_cmd:Nnn {
+\cs_new:Npn \xparse_exp_declare_cmd:Nnn #1#2#3 {
+ \cs_if_exist:NTF #1
+ {
+ \msg_kernel_warning:nnxx { xparse } { redefine-command }
+ { \exp_not:N #1 } { \exp_not:n {#2} }
+ }
+ {
+ \msg_kernel_info:nnxx { xparse } { define-command }
+ { \exp_not:N #1 } { \exp_not:n {#2} }
+ }
\tl_set:Nn \l_xparse_function_tl {#1}
\xparse_exp_prepare_function:n {#2}
\intexpr_compare:nTF {
@@ -690,7 +775,7 @@
\xparse_exp_declare_cmd_mixed:Nn #1 {#3}
}
}
-\cs_new:Nn \xparse_exp_declare_cmd_all_m:Nn {
+\cs_new: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}
@@ -699,14 +784,14 @@
#1 \cs_set_nopar:Npn \l_xparse_total_args_int {#2}
}
}
-\cs_new:Nn \xparse_exp_declare_cmd_mixed:Nn {
+\cs_new:Npn \xparse_exp_declare_cmd_mixed:Nn #1#2 {
\exp_args:NnV \tl_if_in:nnTF { l m u } \l_xparse_last_arg_tl {
\xparse_exp_declare_cmd_mixed_aux:Nn #1 {#2}
}{
- \msg_error:nn { xparse } { expandable-ending-optional }
+ \msg_kernel_error:nn { xparse } { expandable-ending-optional }
}
}
-\cs_new:Nn \xparse_exp_declare_cmd_mixed_aux:Nn {
+\cs_new: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_stop
}
@@ -718,25 +803,27 @@
\cs_generate_from_arg_count:cNnn
{ \token_to_str:N #1 } \cs_set:Npn \l_xparse_total_args_int {#2}
}
-\cs_new:Nn \xparse_exp_prepare_function:n {
+\cs_new: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 } {#1}
+ \msg_kernel_error:nnx { xparse } { processor-in-expandable } {#1}
\bool_set_true:N \l_xparse_error_bool
}
\tl_if_in:nnT {#1} { g } {
- \msg_error:nnx { xparse } { grouped-in-expandable } {#1}
+ \msg_kernel_error:nnx { xparse } { grouped-in-expandable }
+ { g } {#1}
\bool_set_true:N \l_xparse_error_bool
}
\tl_if_in:nnT {#1} { G } {
- \msg_error:nnx { xparse } { grouped-in-expandable } {#1}
+ \msg_kernel_error:nnx { xparse } { grouped-in-expandable }
+ { G } {#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:Nn \xparse_exp_prepare_function_aux:n {
+\cs_new: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
@@ -748,25 +835,24 @@
}
\xparse_exp_prepare_function:N #1 \q_nil
}
-\cs_new:Nn \xparse_exp_prepare_function:N {
+\cs_new: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:Nn \xparse_exp_prepare_function_long:N {
+\cs_new:Npn \xparse_exp_prepare_function_long:N #1 {
\quark_if_nil:NF #1 {
\tl_if_eq:nnTF {#1} { + } {
\xparse_exp_prepare_function_short:N
}{
- \msg_error:nn { xparse } { inconsistent-long }
+ \msg_kernel_error:nn { xparse } { expandable-inconsistent-long }
\xparse_exp_prepare_function_short:N #1
}
-
}
}
-\cs_new:Nn \xparse_exp_prepare_function_short:N {
+\cs_new: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
@@ -782,104 +868,155 @@
}
}
\cs_new_eq:NN \xparse_exp_set:cpx \cs_set_nopar:cpx
-\msg_new:nnnn { xparse } { command-already-defined } {%
- Command name `\token_to_str:N #1' already defined!%
-}{%
- You have used \token_to_str:N \NewDocumentCommand\\%
- with a command that already has a definition.\\%
- Perhaps you meant \token_to_str:N \RenewDocumentCommand.%
-}
-\msg_new:nnnn { xparse } { command-not-yet-defined } {%
- Command `\token_to_str:N #1' not yet defined!%
-}{%
- You have used \token_to_str:N \RenewDocumentCommand\\%
- with a command that was never defined.\\%
- Perhaps you meant \token_to_str:N \NewDocumentCommand.%
-}
-\msg_new:nnn { xparse } { environment-already-defined } {%
- Environment `#1' already defined!%
-}
-\msg_new:nnn { xparse } { environment-not-yet-defined } {%
- Environment `#1' not yet defined!%
-}
-\msg_new:nnnn { xparse } { expandable-ending-optional } {%
- Expandable command signature ends in optional argument.%
-}{%
- Expandable functions must have a final mandatory argument.%
-}
-\msg_new:nnnn { xparse } { grouped-in-expandable } {%
- Optional grouped arguments cannot be used with expandable functions.%
-}{%
- Argument specification `#1' contains an optional grouped argument:\\%
- this is only supported for standard robust functions.%
-}
-\msg_new:nnnn { xparse } { inconsistent-long } {%
- Inconsistent long arguments.%
-}{%
- Expandable commands must have all arguments long if any at all.%
-}
-\msg_new:nnnn { xparse } { processor-in-expandable } {%
- Argument processors cannot be used with expandable functions.%
-}{%
- Argument specification `#1' contains a processor function:\\%
- this is only supported for standard robust functions.%
-}
-\msg_new:nnn { xparse } { unknown-argument-type } {%
- Unknown argument type `#1' replaced by `m'. Fingers crossed ...%
-}
+\msg_kernel_new:nnnn { xparse } { command-already-defined }
+ {Command `#1' already defined!}
+ {%
+ You have used \token_to_str:N \NewDocumentCommand\\%
+ with a command that already has a definition.\\%
+ Perhaps you meant \token_to_str:N \RenewDocumentCommand.%
+ }
+\msg_kernel_new:nnnn { xparse } { command-not-yet-defined }
+ {Command `#1' not yet defined!}
+ {%
+ You have used \token_to_str:N \RenewDocumentCommand\\%
+ with a command that was never defined.\\%
+ Perhaps you meant \token_to_str:N \NewDocumentCommand.%
+ }
+\msg_kernel_new:nnnn { xparse } { environment-already-defined }
+ {Environment `#1' already defined!}
+ {%
+ You have used \token_to_str:N \NewDocumentEnvironment\\%
+ with a command that already has a definition.\\%
+ Perhaps you meant \token_to_str:N \RenewDocumentEnvironment.%
+ }
+\msg_kernel_new:nnnn { xparse } { environment-not-yet-defined }
+ {Environment `#1' not yet defined!}
+ {%
+ You have used \token_to_str:N \RenewDocumentEnvironment\\%
+ with a command that was never defined.\\%
+ Perhaps you meant \token_to_str:N \NewDocumentEnvironment.%
+ }
+\msg_kernel_new:nnnn { xparse } { expandable-ending-optional }
+ {%
+ Signature for expandable command ends with \\%
+ optional argument \msg_line_context:.%
+ }
+ {%
+ Expandable commands must have a final mandatory argument\\%
+ (or no arguments at all). You cannot have a terminal optional\\%
+ argument with expandable commands.%
+ }
+\msg_kernel_new:nnnn { xparse } { expandable-inconsistent-long }
+ {%
+ Inconsistent handling of long arguments for\\%
+ expandable command \msg_line_context:.%
+ }
+ {%
+ The arguments for an expandable command must either all be\\%
+ short or all be long. You have tried to mix the two types.%
+ }
+\msg_kernel_new:nnnn { xparse } { grouped-in-expandable }
+ {%
+ Argument specifier `#1' forbidden in expandable commands
+ \msg_line_context:.%
+ }
+ {%
+ Argument specification `#2' contains the optional grouped
+ argument `#1':\\%
+ this is only supported for standard robust functions.%
+ }
+\msg_kernel_new:nnnn { xparse } { processor-in-expandable }
+ {%
+ Argument processors cannot be used\\%
+ with expandable functions \msg_line_context:.%
+ }
+ {%
+ Argument specification `#1' contains a processor function:\\%
+ this is only supported for standard robust functions.%
+ }
+\msg_kernel_new:nnnn { xparse } { unknown-argument-type }
+ {Unknown argument type `#1' replaced by `m'. Fingers crossed ...}
+ {%
+ The letter `#1' does not specify a known argument type.\\%
+ I'm assuming you want a standard mandatory argument (type `m').%
+ }
+\msg_kernel_new:nnn { xparse } { define-command }
+ {%
+ Defining document command #1\\%
+ with arg. spec. `#2' \msg_line_context:.%
+ }
+\msg_kernel_new:nnn { xparse } { define-environment }
+ {%
+ Defining document environment `#1'\\%
+ with arg. spec. `#2' \msg_line_context:.%
+ }
+\msg_kernel_new:nnn { xparse } { redefine-command }
+ {%
+ Redefining document command #1\\%
+ with arg. spec. `#2' \msg_line_context:.%
+ }
+\msg_kernel_new:nnn { xparse } { redefine-environment }
+ {%
+ Redefining document environment `#1'\\%
+ with arg. spec. `#2' \msg_line_context:.%
+ }
\cs_new_eq:NN \BooleanFalse \c_false_bool
\cs_new_eq:NN \BooleanTrue \c_true_bool
-\xparse_declare_cmd:Nnn \DeclareDocumentCommand { +m +m +m } {
+\cs_new_protected:Npn \DeclareDocumentCommand #1#2#3 {
\xparse_declare_cmd:Nnn #1 {#2} {#3}
}
-\DeclareDocumentCommand \NewDocumentCommand { +m +m +m } {
+\cs_new_protected:Npn \NewDocumentCommand #1#2#3 {
\cs_if_exist:NTF #1 {
- \msg_error:nnx { xparse } { command-already-defined } {#1}
+ \msg_kernel_error:nnx { xparse } { command-already-defined }
+ { \exp_not:N #1 }
}{
\xparse_declare_cmd:Nnn #1 {#2} {#3}
}
}
-\NewDocumentCommand \RenewDocumentCommand { +m +m +m } {
+\cs_new_protected:Npn \RenewDocumentCommand #1#2#3 {
\cs_if_exist:NTF #1 {
\xparse_declare_cmd:Nnn #1 {#2} {#3}
}{
- \msg_error:nnx { xparse } { command-not-yet-defined } {#1}
+ \msg_kernel_error:nnx { xparse } { command-not-yet-defined }
+ { \exp_not:N #1 }
}
}
-\NewDocumentCommand \ProvideDocumentCommand { +m +m +m } {
+\cs_new_protected:Npn \ProvideDocumentCommand #1#2#3 {
\cs_if_exist:NF #1 {
\xparse_declare_cmd:Nnn #1 {#2} {#3}
}
}
-\NewDocumentCommand \DeclareDocumentCommandImplementation { m m +m } {
+\cs_new_protected:Npn \DeclareDocumentCommandImplementation #1#2#3 {
\xparse_declare_cmd_implementation:nNn {#1} #2 {#3}
}
-\NewDocumentCommand \DeclareDocumentCommandInterface { m m +m } {
+\cs_new_protected:Npn \DeclareDocumentCommandInterface #1#2#3 {
\xparse_declare_cmd_interface:Nnn #1 {#2} {#3}
}
-\NewDocumentCommand \DeclareDocumentEnvironment { m +m +m +m } {
+\cs_new_protected:Npn \DeclareDocumentEnvironment #1#2#3#4 {
\xparse_declare_env:nnnn {#1} {#2} {#3} {#4}
}
-\NewDocumentCommand \NewDocumentEnvironment { m +m +m +m } {
- \cs_if_exist:cTF { environment_begin_ #1 :w } {
- \msg_error:nnx { xparse } { environment-already-defined } {#1}
+\cs_new_protected:Npn \NewDocumentEnvironment #1#2#3#4 {
+ \cs_if_exist:cTF {#1} {
+ \msg_kernel_error:nnx { xparse }
+ { environment-already-defined } {#1}
}{
\xparse_declare_env:nnnn {#1} {#2} {#3} {#4}
}
}
-\NewDocumentCommand \RenewDocumentEnvironment { m +m +m +m } {
- \cs_if_exist:cTF { environment_begin_ #1 :w } {
+\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}
+ \msg_kernel_error:nnx { xparse }
+ { environment-not-yet-defined } {#1}
}
}
-\NewDocumentCommand \ProvideDocumentEnvironment { m +m +m +m } {
- \cs_if_exist:cF { environment_begin_ #1 :w } {
+\cs_new_protected:Npn \ProvideDocumentEnvironment #1#2#3#4 {
+ \cs_if_exist:cF { #1 } {
\xparse_declare_env:nnnn {#1} {#2} {#3} {#4}
}
}
-\NewDocumentCommand \DeclareExpandableDocumentCommand { +m +m +m } {
+\cs_new_protected:Npn \DeclareExpandableDocumentCommand #1#2#3 {
\xparse_exp_declare_cmd:Nnn #1 {#2} {#3}
}
\cs_new_eq:NN \IfBooleanTF \bool_if:NTF
@@ -893,7 +1030,8 @@
\cs_set:Npn \IfValueTF #1#2#3 {
\xparse_if_no_value:nTF {#1} {#3} {#2}
}
-\NewDocumentCommand \NoValue { } { -NoValue- }
+\cs_new_protected:Npn \NoValue { -NoValue- }
+\cs_new:Npn \ProcessedArgument { }
\endinput
%%
%% End of file `xparse.sty'.
diff --git a/Master/texmf-dist/tex/latex/xpackages/xbase/xtemplate.sty b/Master/texmf-dist/tex/latex/xpackages/xbase/xtemplate.sty
new file mode 100644
index 00000000000..467b9722af2
--- /dev/null
+++ b/Master/texmf-dist/tex/latex/xpackages/xbase/xtemplate.sty
@@ -0,0 +1,1251 @@
+%%
+%% This is file `xtemplate.sty',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% xtemplate.dtx (with options: `package')
+%%
+%% (C) Copyright The LaTeX3 Project and any individual authors
+%% listed elsewhere in this file.
+%%
+%% This is a generated file.
+%%
+%% This file was generated from file(s) of the xbase bundle.
+%% ---------------------------------------------------------
+%%
+%% This file may only be distributed together with a copy of this bundle.
+%% You may however distribute the bundle without such generated files.
+%%
+%% ======================================================================
+%%
+%% File: xtemplate.dtx (C) Copyright 1999-2001 David Carlisle, Frank Mittelbach
+%% (C) Copyright 2004-2009 Frank Mittelbach, 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
+%%1
+%% This file is part of the ``xbase 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.
+%%
+%% -----------------------------------------------------------------------
+%%
+\RequirePackage{l3names}
+\GetIdInfo$Id: xtemplate.dtx 1746 2009-11-16 01:34:59Z will $
+ {Prototype document functions}
+
+
+\ProvidesExplPackage
+ {\filename}{\filedate}{\fileversion}{\filedescription}
+\RequirePackage{expl3}
+\tl_new:Nn \c_xtemplate_code_root_tl { xtemplate_code > }
+\tl_new:Nn \c_xtemplate_defaults_root_tl { xtemplate_defaults > }
+\tl_new:Nn \c_xtemplate_instances_root_tl { xtemplate_instances > }
+\tl_new:Nn \c_xtemplate_keytypes_root_tl { xtemplate_keytypes > }
+\tl_new:Nn \c_xtemplate_restrict_root_tl { xtemplate_restrict > }
+\tl_new:Nn \c_xtemplate_values_root_tl { xtemplate_values > }
+\tl_new:Nn \c_xtemplate_vars_root_tl { xtemplate_vars > }
+\tl_new:Nn \c_xtemplate_key_order_tl { key~order }
+\clist_new:N \c_xtemplate_keytypes_arg_clist
+\clist_put_right:Nn \c_xtemplate_keytypes_arg_clist { choice }
+\clist_put_right:Nn \c_xtemplate_keytypes_arg_clist { function }
+\clist_put_right:Nn \c_xtemplate_keytypes_arg_clist { instance }
+\prop_new:N \g_xtemplate_object_type_prop
+\toks_new:N \l_xtemplate_assignments_toks
+\tl_new:N \l_xtemplate_collection_tl
+\prop_new:N \l_xtemplate_collections_prop
+\tl_new:N \l_xtemplate_default_tl
+\bool_new:N \l_xtemplate_error_bool
+\bool_new:N \l_xtemplate_global_bool
+\bool_new:N \l_xtemplate_restrict_bool
+\clist_new:N \l_xtemplate_restricted_clist
+\tl_new:N \l_xtemplate_key_name_tl
+\tl_new:N \l_xtemplate_keytype_tl
+\tl_new:N \l_xtemplate_keytype_arg_tl
+\tl_new:N \l_xtemplate_value_tl
+\tl_new:N \l_xtemplate_var_tl
+\seq_new:N \l_xtemplate_key_seq
+\prop_new:N \l_xtemplate_keytypes_prop
+\prop_new:N \l_xtemplate_values_prop
+\prop_new:N \l_xtemplate_vars_prop
+\clist_new:N \l_xtemplate_tmp_clist
+\dim_new:N \l_xtemplate_tmp_dim
+\int_new:N \l_xtemplate_tmp_int
+\skip_new:N \l_xtemplate_tmp_skip
+\tl_new:N \l_xtemplate_tmp_tl
+\cs_new_eq:NN \xtemplate_space: \iow_space:
+\cs_new:Npn \xtemplate_execute_if_arg_agree:nnT #1#2#3 {
+ \prop_get:NnN \g_xtemplate_object_type_prop {#1} \l_xtemplate_tmp_tl
+ \intexpr_compare:nTF { #2 = \l_xtemplate_tmp_tl }
+ {#3}
+ {
+ \msg_kernel_error:nnxxx { xtemplate }
+ { argument-number-mismatch } {#1} { \l_xtemplate_tmp_tl } {#2}
+ }
+}
+\cs_new:Npn \xtemplate_execute_if_code_exist:nnT #1#2#3 {
+ \cs_if_exist:cTF { \c_xtemplate_code_root_tl #1 / #2 :w }
+ {#3}
+ {
+ \msg_kernel_error:nnxx { xtemplate } { no-template-code }
+ {#1} {#2}
+ }
+}
+\cs_new:Npn \xtemplate_execute_if_keytype_exist:nT #1#2 {
+ \cs_if_exist:cTF { xtemplate_store_value_ #1 :n }
+ {#2}
+ { \msg_kernel_error:nnx { xtemplate } { unknown-keytype } {#1} }
+}
+\cs_generate_variant:Nn \xtemplate_execute_if_keytype_exist:nT { V }
+\cs_new:Npn \xtemplate_execute_if_type_exist:nT #1#2 {
+ \prop_if_in:NnTF \g_xtemplate_object_type_prop {#1}
+ {#2}
+ { \msg_kernel_error:nnx { xtemplate } { unknown-object-type } {#1} }
+}
+\cs_new:Npn \xtemplate_if_keys_exist:nnT #1#2#3 {
+ \cs_if_exist:cTF
+ { g_ \c_xtemplate_keytypes_root_tl #1 / #2 _prop }
+ {#3}
+ {
+ \msg_kernel_error:nnxx { xtemplate } { unknown-template }
+ {#1} {#2}
+ }
+}
+\prg_set_conditional:Nnn \xtemplate_if_key_value:n { T } {
+ \tl_if_eq:noTF { \KeyValue } { \tl_head:w #1 \q_nil } {
+ \prg_return_true:
+ }{
+ \prg_return_false:
+ }
+}
+\cs_generate_variant:Nn \xtemplate_if_key_value:nT { V }
+\prg_new_conditional:Nnn \xtemplate_if_eval_now:n { TF } {
+ \tl_if_eq:noTF { \EvaluateNow } { \tl_head:w #1 \q_nil } {
+ \prg_return_true:
+ }{
+ \prg_return_false:
+ }
+}
+\prg_new_conditional:Nnn \xtemplate_if_instance_exist:nnn { T, F, TF } {
+ \cs_if_exist:cTF { \c_xtemplate_instances_root_tl #1 / #2 / #3 :w } {
+ \prg_return_true:
+ }{
+ \prg_return_false:
+ }
+}
+\prg_new_conditional:Nnn \xtemplate_if_use_template:n { TF } {
+ \tl_if_eq:noTF { \UseTemplate } { \tl_head:w #1 \q_nil } {
+ \prg_return_true:
+ }{
+ \prg_return_false:
+ }
+}
+\cs_new:Npn \xtemplate_store_defaults:n #1 {
+ \cs_if_free:cT { g_ \c_xtemplate_defaults_root_tl #1 _prop } {
+ \prop_new:c { g_ \c_xtemplate_defaults_root_tl #1 _prop }
+ }
+ \prop_gset_eq:cN { g_ \c_xtemplate_defaults_root_tl #1 _prop }
+ \l_xtemplate_values_prop
+}
+\cs_new:Npn \xtemplate_store_keytypes:n #1 {
+ \cs_if_free:cTF { g_ \c_xtemplate_keytypes_root_tl #1 _prop } {
+ \msg_kernel_info:nnx { xtemplate } { define-template-interface }
+ {#1}
+ \prop_new:c { g_ \c_xtemplate_keytypes_root_tl #1 _prop }
+ }
+ {
+ \msg_kernel_warning:nnx { xtemplate }
+ { redefine-template-interface } {#1}
+ }
+ \prop_gset_eq:cN { g_ \c_xtemplate_keytypes_root_tl #1 _prop }
+ \l_xtemplate_keytypes_prop
+}
+\cs_new:Npn \xtemplate_store_values:n #1 {
+ \cs_if_free:cT { l_ \c_xtemplate_values_root_tl #1 _prop } {
+ \prop_new:c { l_ \c_xtemplate_values_root_tl #1 _prop }
+ }
+ \prop_set_eq:cN { l_ \c_xtemplate_values_root_tl #1 _prop }
+ \l_xtemplate_values_prop
+}
+\cs_new:Npn \xtemplate_store_restrictions:n #1 {
+ \clist_gset_eq:cN { g_ \c_xtemplate_restrict_root_tl #1 _clist }
+ \l_xtemplate_restrict_clist
+}
+\cs_new:Npn \xtemplate_store_vars:n #1 {
+ \cs_if_free:cTF { g_ \c_xtemplate_vars_root_tl #1 _prop } {
+ \msg_kernel_info:nnx { xtemplate } { define-template-code } {#1}
+ \prop_new:c { g_ \c_xtemplate_vars_root_tl #1 _prop }
+ }
+ {
+ \msg_kernel_warning:nnx { xtemplate } { redefine-template-code }
+ {#1}
+ }
+ \prop_gset_eq:cN { g_ \c_xtemplate_vars_root_tl #1 _prop }
+ \l_xtemplate_vars_prop
+}
+\cs_new:Npn \xtemplate_recover_defaults:n #1 {
+ \prop_set_eq:Nc \l_xtemplate_values_prop
+ { g_ \c_xtemplate_defaults_root_tl #1 _prop }
+}
+\cs_new:Npn \xtemplate_recover_keytypes:n #1 {
+ \prop_set_eq:Nc \l_xtemplate_keytypes_prop
+ { g_ \c_xtemplate_keytypes_root_tl #1 _prop }
+}
+\cs_new:Npn \xtemplate_recover_restrictions:n #1 {
+ \clist_set_eq:Nc \l_xtemplate_restrict_clist
+ { g_ \c_xtemplate_restrict_root_tl #1 _clist }
+}
+\cs_new:Npn \xtemplate_recover_values:n #1 {
+ \prop_set_eq:Nc \l_xtemplate_values_prop
+ { l_ \c_xtemplate_values_root_tl #1 _prop }
+}
+\cs_new:Npn \xtemplate_recover_vars:n #1 {
+ \prop_set_eq:Nc \l_xtemplate_vars_prop
+ { g_ \c_xtemplate_vars_root_tl #1 _prop }
+}
+\cs_new:Npn \xtemplate_declare_object_type:nn #1#2 {
+ \int_set:Nn \l_xtemplate_tmp_int {#2}
+ \bool_if:nTF {
+ \intexpr_compare_p:n { #2 > \c_nine } ||
+ \intexpr_compare_p:n { #2 < \c_zero }
+ } {
+ \msg_kernel_error:nnxx { xtemplate } { bad-number-of-arguments }
+ {#1} { \exp_not:V \l_xtemplate_tmp_int }
+ }{
+ \prop_if_in:NnTF \g_xtemplate_object_type_prop {#1}
+ {
+ \msg_kernel_warning:nnxx { xtemplate } { redefine-object-type }
+ {#1} {#2}
+ }
+ {
+ \msg_kernel_info:nnxx { xtemplate } { define-object-type }
+ {#1} {#2}
+ }
+ \prop_gput:NnV \g_xtemplate_object_type_prop {#1}
+ \l_xtemplate_tmp_int
+ }
+}
+\cs_new:Npn \xtemplate_declare_template_keys:nnnn #1#2#3#4 {
+ \xtemplate_execute_if_type_exist:nT {#1}
+ {
+ \xtemplate_execute_if_arg_agree:nnT {#1} {#3}
+ {
+ \prop_clear:N \l_xtemplate_values_prop
+ \prop_clear:N \l_xtemplate_keytypes_prop
+ \seq_clear:N \l_xtemplate_key_seq
+ \cs_set_eq:NN \KV_key_no_value_elt:n \xtemplate_parse_keys_elt:n
+ \cs_set_eq:NN \KV_key_value_elt:nn \xtemplate_parse_keys_elt:nn
+ \KV_parse_space_removal_sanitize:n {#4}
+ \prop_put:NVV \l_xtemplate_keytypes_prop \c_xtemplate_key_order_tl
+ \l_xtemplate_key_seq
+ \xtemplate_store_defaults:n { #1 / #2 }
+ \xtemplate_store_keytypes:n { #1 / #2 }
+ }
+ }
+}
+\cs_new:Npn \xtemplate_parse_keys_elt:n #1 {
+ \xtemplate_split_keytype:n {#1}
+ \bool_if:NF \l_xtemplate_error_bool
+ {
+ \xtemplate_execute_if_keytype_exist:VT \l_xtemplate_keytype_tl
+ {
+ \clist_map_function:nN { choice , function , instance }
+ \xtemplate_parse_keys_elt_aux:n
+ \bool_if:NF \l_xtemplate_error_bool
+ {
+ \seq_if_in:NVTF \l_xtemplate_key_seq
+ \l_xtemplate_key_name_tl
+ {
+ \msg_kernel_error:nnx { xtemplate }
+ { duplicate-key-interface }
+ { \l_xtemplate_key_name_tl }
+ }
+ { \xtemplate_parse_keys_elt_aux: }
+ }
+ }
+ }
+}
+\cs_new_nopar:Npn \xtemplate_parse_keys_elt_aux:n #1 {
+ \tl_if_eq:VnT \l_xtemplate_keytype_tl {#1} {
+ \tl_if_empty:NT \l_xtemplate_keytype_arg_tl {
+ \msg_kernel_error:nnx { xtemplate }
+ { keytype-requires-argument } {#1}
+ \bool_set_true:N \l_xtemplate_error_bool
+ \clist_map_break:
+ }
+ }
+}
+\cs_new_nopar:Npn \xtemplate_parse_keys_elt_aux: {
+ \tl_set:Nx \l_xtemplate_tmp_tl {
+ \l_xtemplate_keytype_tl
+ \l_xtemplate_keytype_arg_tl
+ }
+ \prop_put:NVV \l_xtemplate_keytypes_prop \l_xtemplate_key_name_tl
+ \l_xtemplate_tmp_tl
+ \seq_put_right:NV \l_xtemplate_key_seq \l_xtemplate_key_name_tl
+ \tl_if_eq:VnT \l_xtemplate_keytype_tl { choice } {
+ \clist_if_in:NnT \l_xtemplate_keytype_arg_tl { unknown } {
+ \msg_kernel_error:nn { xtemplate } { choice-unknown-reserved }
+ }
+ }
+}
+\cs_new:Npn \xtemplate_parse_keys_elt:nn #1#2 {
+ \xtemplate_parse_keys_elt:n {#1}
+ \tl_if_eq:VnTF \l_xtemplate_keytype_tl { choice } {
+ \xtemplate_store_value_choice_name:n {#2}
+ }{
+ \use:c { xtemplate_store_value_ \l_xtemplate_keytype_tl :n } {#2}
+ }
+}
+\group_begin:
+\char_set_lccode:nn { `\@ } { `\: }
+\char_make_other:N \@
+\tl_to_lowercase:n {
+ \group_end:
+ \cs_new:Npn \xtemplate_split_keytype:n #1 {
+ \bool_set_false:N \l_xtemplate_error_bool
+ \tl_set:Nn \l_xtemplate_tmpa_tl {#1}
+ \tl_replace_all_in:Nnn \l_xtemplate_tmpa_tl { ~ } { }
+ \tl_replace_all_in:Nnn \l_xtemplate_tmpa_tl { : } { @ }
+ \tl_if_in:VnTF \l_xtemplate_tmpa_tl { @ } {
+ \exp_after:wN \xtemplate_split_keytype_aux:w \l_xtemplate_tmpa_tl
+ \q_stop
+ }{
+ \bool_set_true:N \l_xtemplate_error_bool
+ \msg_kernel_error:nnx { xtemplate } { no-keytype } {#1}
+ }
+ }
+ \cs_new:Npn \xtemplate_split_keytype_aux:w #1 @ #2 \q_stop {
+ \tl_if_empty:nT {#1} {
+ \msg_kernel_error:nnx { xtemplate } { empty-key-name } { @ #2 }
+ }
+ \tl_set:Nx \l_xtemplate_key_name_tl { \tl_to_str:n {#1} }
+ \xtemplate_split_keytype_arg:n {#2}
+ }
+}
+\cs_new:Npn \xtemplate_split_keytype_arg:n #1 {
+ \tl_set:Nn \l_xtemplate_keytype_tl {#1}
+ \tl_clear:N \l_xtemplate_keytype_arg_tl
+ \cs_set_nopar:Npn \xtemplate_split_keytype_arg_aux:n ##1 {
+ \tl_if_in:nnT {#1} {##1} {
+ \cs_set:Npn \xtemplate_split_keytype_arg_aux:w
+ ####1 ##1 ####2 \q_stop {
+ \tl_if_empty:nT {####1} {
+ \tl_set:Nn \l_xtemplate_keytype_tl {##1}
+ \tl_set:Nn \l_xtemplate_keytype_arg_tl {####2}
+ \clist_map_break:
+ }
+ }
+ \xtemplate_split_keytype_arg_aux:w #1 \q_stop
+ }
+ }
+ \clist_map_function:NN \c_xtemplate_keytypes_arg_clist
+ \xtemplate_split_keytype_arg_aux:n
+}
+\cs_generate_variant:Nn \xtemplate_split_keytype_arg:n { V }
+\cs_new_nopar:Npn \xtemplate_split_keytype_arg_aux:n #1 { }
+\cs_new_nopar:Npn \xtemplate_split_keytype_arg_aux:w #1 \q_stop { }
+\cs_new:Npn \xtemplate_store_value_boolean:n #1 {
+ \xtemplate_if_eval_now:nTF {#1} {
+ \bool_if:cTF { c_ #1 _bool } {
+ \prop_put:NVn \l_xtemplate_values_prop \l_xtemplate_key_name_tl
+ { true }
+ }{
+ \prop_put:NVn \l_xtemplate_values_prop \l_xtemplate_key_name_tl
+ { false }
+ }
+ }{
+ \prop_put:NVn \l_xtemplate_values_prop \l_xtemplate_key_name_tl {#1}
+ }
+}
+\cs_new:Npn \xtemplate_store_value_choice:n #1 {
+ \tl_set:Nx \l_xtemplate_tmp_tl
+ { \l_xtemplate_key_name_tl \xtemplate_space: #1 }
+ \prop_if_in:NVTF \l_xtemplate_vars_prop \l_xtemplate_tmp_tl {
+ \xtemplate_store_value_choice_aux:V \l_xtemplate_tmp_tl
+ }{
+ \tl_set:Nx \l_xtemplate_tmp_tl
+ { \l_xtemplate_key_name_tl \xtemplate_space: unknown }
+ \prop_if_in:NVTF \l_xtemplate_vars_prop \l_xtemplate_tmp_tl {
+ \xtemplate_store_value_choice_aux:V \l_xtemplate_tmp_tl
+ }{
+ \prop_get:NVN \l_xtemplate_keytypes_prop \l_xtemplate_key_name_tl
+ \l_xtemplate_tmp_tl
+ \xtemplate_split_keytype_arg:V \l_xtemplate_tmp_tl
+ \msg_kernel_error:nnxxx { xtemplate } { unknown-choice }
+ {#1}
+ { \l_xtemplate_key_name_tl }
+ { \l_xtemplate_keytype_arg_tl }
+ \prop_gdel:NV \l_xtemplate_values_prop \l_xtemplate_key_name_tl
+ }
+ }
+}
+\cs_generate_variant:Nn \xtemplate_store_value_choice:n { V }
+\cs_new:Npn \xtemplate_store_value_choice_aux:n #1 {
+ \prop_get:NnN \l_xtemplate_vars_prop {#1} \l_xtemplate_tmp_tl
+ \prop_put:NVV \l_xtemplate_values_prop \l_xtemplate_key_name_tl
+ \l_xtemplate_tmp_tl
+}
+\cs_generate_variant:Nn \xtemplate_store_value_choice_aux:n { V }
+\cs_new:Npn \xtemplate_store_value_choice_name:n #1 {
+ \tl_set:Nx \l_xtemplate_tmp_tl
+ { \l_xtemplate_key_name_tl \xtemplate_space: default }
+ \prop_put:NVn \l_xtemplate_values_prop \l_xtemplate_tmp_tl {#1}
+}
+\cs_new:Npn \xtemplate_store_value_code:n #1 {
+ \prop_put:NVn \l_xtemplate_values_prop \l_xtemplate_key_name_tl {#1}
+}
+\cs_new:Npn \xtemplate_store_value_commalist:n #1 {
+ \prop_put:NVn \l_xtemplate_values_prop \l_xtemplate_key_name_tl {#1}
+}
+\cs_new:Npn \xtemplate_store_value_function:n #1 {
+ \prop_put:NVn \l_xtemplate_values_prop \l_xtemplate_key_name_tl {#1}
+}
+\cs_new:Npn \xtemplate_store_value_instance:n #1 {
+ \prop_put:NVn \l_xtemplate_values_prop \l_xtemplate_key_name_tl {#1}
+}
+\cs_new:Npn \xtemplate_store_value_tokenlist:n #1 {
+ \prop_put:NVn \l_xtemplate_values_prop \l_xtemplate_key_name_tl {#1}
+}
+\cs_new:Npn \xtemplate_store_value_integer:n #1 {
+ \xtemplate_if_eval_now:nTF {#1} {
+ \int_set:Nn \l_xtemplate_tmp_int {#1}
+ \prop_put:NVV \l_xtemplate_values_prop \l_xtemplate_key_name_tl
+ \l_xtemplate_tmp_int
+ }{
+ \prop_put:NVn \l_xtemplate_values_prop \l_xtemplate_key_name_tl {#1}
+ }
+}
+\cs_new:Npn \xtemplate_store_value_length:n #1 {
+ \xtemplate_if_eval_now:nTF {#1} {
+ \dim_set:Nn \l_xtemplate_tmp_dim {#1}
+ \prop_put:NVV \l_xtemplate_values_prop \l_xtemplate_key_name_tl
+ \l_xtemplate_tmp_dim
+ }{
+ \prop_put:NVn \l_xtemplate_values_prop \l_xtemplate_key_name_tl {#1}
+ }
+}
+\cs_new:Npn \xtemplate_store_value_skip:n #1 {
+ \xtemplate_if_eval_now:nTF {#1} {
+ \skip_set:Nn \l_xtemplate_tmp_skip {#1}
+ \prop_put:NVV \l_xtemplate_values_prop \l_xtemplate_key_name_tl
+ \l_xtemplate_tmp_skip
+ }{
+ \prop_put:NVn \l_xtemplate_values_prop \l_xtemplate_key_name_tl {#1}
+ }
+}
+\cs_new:Npn \xtemplate_declare_template_code:nnnnn #1#2#3#4#5 {
+ \xtemplate_execute_if_type_exist:nT {#1}
+ {
+ \xtemplate_execute_if_arg_agree:nnT {#1}{#3}
+ {
+ \xtemplate_if_keys_exist:nnT {#1} {#2}
+ {
+ \xtemplate_store_key_implementation:nnn {#1} {#2} {#4}
+ \cs_generate_from_arg_count:cNnn
+ { \c_xtemplate_code_root_tl #1 / #2 :w } \cs_gset:Npn
+ {#3} {#5}
+ }
+ }
+ }
+}
+\cs_set:Npn \xtemplate_store_key_implementation:nnn #1#2#3 {
+ \xtemplate_recover_defaults:n { #1 / #2 }
+ \xtemplate_recover_keytypes:n { #1 / #2 }
+ \prop_clear:N \l_xtemplate_vars_prop
+ \cs_set_eq:NN \KV_key_no_value_elt:n \xtemplate_parse_vars_elt:n
+ \cs_set_eq:NN \KV_key_value_elt:nn \xtemplate_parse_vars_elt:nn
+ \KV_parse_space_removal_sanitize:n {#3}
+ \xtemplate_store_defaults:n { #1 / #2 }
+ \xtemplate_store_vars:n { #1 / #2 }
+ \clist_clear:N \l_xtemplate_restrict_clist
+ \xtemplate_store_restrictions:n { #1 / #2 }
+ \prop_del:NV \l_xtemplate_keytypes_prop \c_xtemplate_key_order_tl
+ \prop_if_empty:NF \l_xtemplate_keytypes_prop {
+ \prop_map_inline:Nn \l_xtemplate_keytypes_prop {
+ \msg_kernel_error:nnxxx { xtemplate } { key-not-implemented }
+ {##1} {#2} {#1}
+ }
+ }
+}
+\cs_new:Npn \xtemplate_parse_vars_elt:n #1 {
+ \msg_kernel_error:nnx { xtemplate } { key-no-variable } {#1}
+}
+\cs_new:Npn \xtemplate_parse_vars_elt:nn #1#2 {
+ \tl_set:Nx \l_xtemplate_key_name_tl { \tl_to_str:n {#1} }
+ \tl_replace_all_in:Nnn \l_xtemplate_key_name_tl { ~ } { }
+ \prop_if_in:NVTF \l_xtemplate_keytypes_prop \l_xtemplate_key_name_tl {
+ \prop_get:NVN \l_xtemplate_keytypes_prop \l_xtemplate_key_name_tl
+ \l_xtemplate_keytype_tl
+ \xtemplate_split_keytype_arg:V \l_xtemplate_keytype_tl
+ \xtemplate_parse_vars_elt_aux:n {#2}
+ \prop_del:NV \l_xtemplate_keytypes_prop \l_xtemplate_key_name_tl
+ }{
+ \msg_kernel_error:nnx { xtemplate } { unknown-key } {#1}
+ }
+}
+\cs_new:Npn \xtemplate_parse_vars_elt_aux:n #1 {
+ \tl_if_eq:VnTF \l_xtemplate_keytype_tl { choice }
+ {
+ \xtemplate_implement_choices:n {#1}
+ }
+ {
+ \tl_if_eq:VnTF \l_xtemplate_keytype_tl { code }
+ {
+ \prop_put:NVn \l_xtemplate_vars_prop
+ \l_xtemplate_key_name_tl {#1}
+ }
+ {
+ \tl_if_eq:noTF {#1} { \tl_head:w #1 \q_nil }
+ {
+ \cs_if_exist:NTF #1
+ {
+ \prop_put:NVn \l_xtemplate_vars_prop
+ \l_xtemplate_key_name_tl {#1}
+ }
+ {
+ \msg_kernel_error:nnx { xtemplate }
+ { undeclared-variable }
+ { \exp_not:N #1 }
+ }
+ }
+ {
+ \tl_if_in:nnTF {#1} { global }
+ { \xtemplate_parse_vars_elt_aux:w #1 \q_nil }
+ {
+ \msg_kernel_error:nnx { xtemplate } { bad-variable }
+ { \exp_not:n {#1} }
+ }
+ }
+ }
+ }
+}
+\cs_new:Npn \xtemplate_parse_vars_elt_aux:w #1 global #2 \q_nil {
+ \tl_if_empty:nTF {#1}
+ {
+ \tl_if_eq:noTF {#2} { \tl_head:w #2 \q_nil }
+ {
+ \cs_if_exist:NTF #2
+ {
+ \prop_put:NVn \l_xtemplate_vars_prop
+ \l_xtemplate_key_name_tl { #1 global #2 }
+ }
+ {
+ \msg_kernel_error:nnx { xtemplate }
+ { undeclared-variable }
+ { \exp_not:N #2 }
+ }
+ }
+ {
+ \msg_kernel_error:nnx { xtemplate } { bad-variable }
+ { \exp_not:n { #1 global #2 } }
+ }
+ }
+ {
+ \msg_kernel_error:nnx { xtemplate } { bad-variable }
+ { \exp_not:n { #1 global #2 } }
+ }
+}
+\cs_new:Npn \xtemplate_implement_choices:n #1 {
+ \clist_set_eq:NN \l_xtemplate_tmp_clist \l_xtemplate_keytype_arg_tl
+ \cs_set_eq:NN \KV_key_no_value_elt:n \xtemplate_implement_choice_elt:n
+ \cs_set_eq:NN \KV_key_value_elt:nn \xtemplate_implement_choice_elt:nn
+ \prop_put:NVn \l_xtemplate_vars_prop \l_xtemplate_key_name_tl { }
+ \KV_parse_space_removal_sanitize:n {#1}
+ \cs_set_eq:NN \KV_key_no_value_elt:n \xtemplate_parse_vars_elt:n
+ \cs_set_eq:NN \KV_key_value_elt:nn \xtemplate_parse_vars_elt:nn
+ \tl_set:Nx \l_xtemplate_tmp_tl
+ { \l_xtemplate_key_name_tl \xtemplate_space: default }
+ \prop_if_in:NVT \l_xtemplate_values_prop \l_xtemplate_tmp_tl {
+ \prop_get:NVN \l_xtemplate_values_prop \l_xtemplate_tmp_tl
+ \l_xtemplate_tmp_tl
+ \xtemplate_store_value_choice:V \l_xtemplate_tmp_tl
+ }
+ \clist_if_empty:NF \l_xtemplate_tmp_clist {
+ \clist_map_inline:Nn \l_xtemplate_tmp_clist
+ {
+ \msg_kernel_error:nnx { xtemplate } { choice-not-implemented }
+ {##1}
+ }
+ }
+}
+\cs_new:Npn \xtemplate_implement_choice_elt:n #1 {
+ \clist_if_empty:NTF \l_xtemplate_tmp_clist {
+ \tl_if_eq:nnF {#1} { unknown } {
+ \prop_get:NVN \l_xtemplate_keytypes_prop \l_xtemplate_key_name_tl
+ \l_xtemplate_tmp_tl
+ \xtemplate_split_keytype_arg:V \l_xtemplate_tmp_tl
+ \msg_kernel_error:nnxxx { xtemplate } { unknown-choice }
+ {#1}
+ { \l_xtemplate_key_name_tl }
+ { \l_xtemplate_keytype_arg_tl }
+ }
+ }{
+ \clist_if_in:NnTF \l_xtemplate_tmp_clist {#1} {
+ \clist_remove_element:Nn \l_xtemplate_tmp_clist {#1}
+ }{
+ \prop_get:NVN \l_xtemplate_keytypes_prop \l_xtemplate_key_name_tl
+ \l_xtemplate_tmp_tl
+ \xtemplate_split_keytype_arg:V \l_xtemplate_tmp_tl
+ \msg_kernel_error:nnxxx { xtemplate } { unknown-choice }
+ {#1}
+ { \l_xtemplate_key_name_tl }
+ { \l_xtemplate_keytype_arg_tl }
+ }
+ }
+}
+\cs_new:Npn \xtemplate_implement_choice_elt:nn #1#2 {
+ \xtemplate_implement_choice_elt:n {#1}
+ \tl_set:Nx \l_xtemplate_tmp_tl
+ { \l_xtemplate_key_name_tl \xtemplate_space: #1 }
+ \prop_put:NVn \l_xtemplate_vars_prop \l_xtemplate_tmp_tl {#2}
+}
+\cs_new:Npn \xtemplate_declare_restricted:nnnn #1#2#3#4 {
+ \xtemplate_if_keys_exist:nnT {#1} {#2}
+ {
+ \xtemplate_set_template_eq:nn { #1 / #3 } { #1 / #2 }
+ \bool_set_true:N \l_xtemplate_restrict_bool
+ \xtemplate_edit_defaults_aux:nnn {#1} {#3} {#4}
+ }
+}
+\cs_new:Npn \xtemplate_edit_defaults:nnn {
+ \bool_set_false:N \l_xtemplate_restrict_bool
+ \xtemplate_edit_defaults_aux:nnn
+}
+\cs_new:Npn \xtemplate_edit_defaults_aux:nnn #1#2#3 {
+ \xtemplate_if_keys_exist:nnT {#1} {#2}
+ {
+ \xtemplate_recover_defaults:n { #1 / #2 }
+ \xtemplate_recover_restrictions:n { #1 / #2 }
+ \xtemplate_parse_values:nn { #1 / #2 } {#3}
+ \xtemplate_store_defaults:n { #1 / #2 }
+ \xtemplate_store_restrictions:n { #1 / #2 }
+ }
+}
+\cs_new:Npn \xtemplate_parse_values:nn #1#2 {
+ \xtemplate_recover_keytypes:n {#1}
+ \clist_clear:N \l_xtemplate_restricted_clist
+ \cs_set_eq:NN \KV_key_no_value_elt:n \xtemplate_parse_values_elt:n
+ \cs_set_eq:NN \KV_key_value_elt:nn \xtemplate_parse_values_elt:nn
+ \KV_parse_space_removal_sanitize:n {#2}
+}
+\cs_new:Npn \xtemplate_parse_values_elt:n #1 {
+ \bool_set_true:N \l_xtemplate_error_bool
+ \msg_kernel_error:nnx { xtemplate } { key-no-value } {#1}
+}
+\cs_new:Npn \xtemplate_parse_values_elt:nn #1#2 {
+ \tl_set:Nx \l_xtemplate_key_name_tl { \tl_to_str:n {#1} }
+ \tl_replace_all_in:Nnn \l_xtemplate_key_name_tl { ~ } { }
+ \prop_if_in:NVTF \l_xtemplate_keytypes_prop \l_xtemplate_key_name_tl {
+ \bool_if:NTF \l_xtemplate_restrict_bool {
+ \clist_if_in:NVF \l_xtemplate_restricted_clist
+ \l_xtemplate_key_name_tl {
+ \xtemplate_parse_values_elt_aux:Vn \l_xtemplate_key_name_tl {#2}
+ }
+ }{
+ \xtemplate_parse_values_elt_aux:Vn \l_xtemplate_key_name_tl {#2}
+ }
+ }{
+ \msg_kernel_error:nnx { xtemplate } { unknown-key }
+ { \l_xtemplate_key_name_tl }
+ }
+}
+\cs_new:Npn \xtemplate_parse_values_elt_aux:nn #1#2 {
+ \clist_put_right:Nn \l_xtemplate_restricted_clist {#1}
+ \prop_get:NnN \l_xtemplate_keytypes_prop {#1} \l_xtemplate_tmp_tl
+ \xtemplate_split_keytype_arg:V \l_xtemplate_tmp_tl
+ \use:c { xtemplate_store_value_ \l_xtemplate_keytype_tl :n } {#2}
+}
+\cs_generate_variant:Nn \xtemplate_parse_values_elt_aux:nn { Vn }
+\cs_new:Npn \xtemplate_set_template_eq:nn #1#2 {
+ \xtemplate_recover_defaults:n {#2}
+ \xtemplate_store_defaults:n {#1}
+ \xtemplate_recover_keytypes:n {#2}
+ \xtemplate_store_keytypes:n {#1}
+ \xtemplate_recover_vars:n {#2}
+ \xtemplate_store_vars:n {#1}
+ \cs_gset_eq:cc { \c_xtemplate_code_root_tl #1 :w }
+ { \c_xtemplate_code_root_tl #2 :w }
+}
+\cs_new:Npn \xtemplate_declare_instance:nnnnn #1#2#3#4#5 {
+ \xtemplate_execute_if_code_exist:nnT {#1} {#2}
+ {
+ \xtemplate_recover_defaults:n { #1 / #2 }
+ \xtemplate_recover_vars:n { #1 / #2 }
+ \xtemplate_declare_instance_aux:nnnnn {#1} {#2} {#3} {#4} {#5}
+ }
+}
+\cs_new:Npn \xtemplate_declare_instance_aux:nnnnn #1#2#3#4#5 {
+ \bool_set_false:N \l_xtemplate_error_bool
+ \xtemplate_parse_values:nn { #1 / #2 } {#5}
+ \bool_if:NF \l_xtemplate_error_bool {
+ \prop_put:Nnn \l_xtemplate_values_prop { from~template } {#2}
+ \xtemplate_store_values:n { #1 / #3 / #4 }
+ \xtemplate_convert_to_assignments:
+ \cs_set:cpx { \c_xtemplate_instances_root_tl #1 / #3 / #4 :w } {
+ \exp_not:N \xtemplate_assignments_push:n {
+ \exp_not:V \l_xtemplate_assignments_toks
+ }
+ \exp_not:c { \c_xtemplate_code_root_tl #1 / #2 :w }
+ }
+ \xtemplate_if_instance_exist:nnnF {#1} { } {#4} {
+ \cs_set_eq:cc
+ { \c_xtemplate_instances_root_tl #1 / / #4 :w }
+ { \c_xtemplate_instances_root_tl #1 / #3 / #4 :w }
+ }
+ }
+}
+\cs_new:Npn \xtemplate_edit_instance:nnnn #1#2#3 {
+ \xtemplate_if_instance_exist:nnnTF {#1} {#2} {#3}
+ {
+ \xtemplate_recover_values:n { #1 / #2 / #3 }
+ \prop_get:NnN \l_xtemplate_values_prop { from~template }
+ \l_xtemplate_tmp_tl
+ \xtemplate_edit_instance_aux:nVnnn {#1} \l_xtemplate_tmp_tl
+ {#2} {#3}
+ }
+ {
+ \msg_kernel_error:nnxx { xtemplate } { unknown-instance }
+ {#1} {#3}
+ }
+}
+\cs_new:Npn \xtemplate_edit_instance_aux:nnnnn #1#2 {
+ \xtemplate_recover_vars:n { #1 / #2 }
+ \xtemplate_declare_instance_aux:nnnnn {#1} {#2}
+}
+\cs_generate_variant:Nn \xtemplate_edit_instance_aux:nnnnn { nV }
+\cs_new_nopar:Npn \xtemplate_convert_to_assignments: {
+ \toks_clear:N \l_xtemplate_assignments_toks
+ \prop_get:NVN \l_xtemplate_keytypes_prop \c_xtemplate_key_order_tl
+ \l_xtemplate_key_seq
+ \seq_map_function:NN \l_xtemplate_key_seq
+ \xtemplate_convert_to_assignments_aux:n
+}
+\cs_new:Npn \xtemplate_convert_to_assignments_aux:n #1 {
+ \prop_get:NnN \l_xtemplate_keytypes_prop {#1} \l_xtemplate_tmp_tl
+ \xtemplate_convert_to_assignments_aux:nV {#1} \l_xtemplate_tmp_tl
+}
+\cs_new:Npn \xtemplate_convert_to_assignments_aux:nn #1#2 {
+ \prop_if_in:NnT \l_xtemplate_values_prop {#1} {
+ \prop_if_in:NnTF \l_xtemplate_vars_prop {#1} {
+ \prop_get:NnN \l_xtemplate_values_prop {#1} \l_xtemplate_value_tl
+ \prop_get:NnN \l_xtemplate_vars_prop {#1} \l_xtemplate_var_tl
+ \xtemplate_split_keytype_arg:n {#2}
+ \tl_if_eq:VnF \l_xtemplate_keytype_tl { choice } {
+ \tl_if_eq:VnF \l_xtemplate_keytype_tl { code } {
+ \xtemplate_find_global:
+ }
+ }
+ \use:c { xtemplate_assign_ \l_xtemplate_keytype_tl : }
+ }{
+ \msg_kernel_error:nnx { xtemplate } { unknown-attribute } {#1}
+ }
+ }
+}
+\cs_generate_variant:Nn \xtemplate_convert_to_assignments_aux:nn { nV }
+\cs_new_nopar:Npn \xtemplate_find_global: {
+ \bool_set_false:N \l_xtemplate_global_bool
+ \tl_if_in:VnT \l_xtemplate_var_tl { global } {
+ \exp_after:wN \xtemplate_find_global_aux:w \l_xtemplate_var_tl \q_stop
+ }
+}
+\cs_new:Npn \xtemplate_find_global_aux:w #1 global #2 \q_stop {
+ \tl_set:Nn \l_xtemplate_var_tl {#2}
+ \bool_set_true:N \l_xtemplate_global_bool
+}
+\cs_new:Npn \xtemplate_use_template:nnn #1#2#3 {
+ \xtemplate_recover_defaults:n { #1 / #2 }
+ \xtemplate_recover_vars:n { #1 / #2 }
+ \xtemplate_parse_values:nn { #1 / #2 } {#3}
+ \xtemplate_convert_to_assignments:
+ \use:c { \c_xtemplate_code_root_tl #1 / #2 :w }
+}
+\cs_new_nopar:Npn \xtemplate_assign_boolean: {
+ \bool_if:NTF \l_xtemplate_global_bool {
+ \xtemplate_assign_boolean_aux:n { bool_gset }
+ }{
+ \xtemplate_assign_boolean_aux:n { bool_set }
+ }
+}
+\cs_new_nopar:Npn \xtemplate_assign_boolean_aux:n #1 {
+ \xtemplate_if_key_value:VT \l_xtemplate_value_tl {
+ \xtemplate_key_to_value:
+ }
+ \toks_put_left:Nx \l_xtemplate_assignments_toks {
+ \exp_not:c { #1 _ \l_xtemplate_value_tl :N }
+ \exp_not:V \l_xtemplate_var_tl
+ }
+}
+\cs_new_nopar:Npn \xtemplate_assign_choice: {
+ \toks_put_left:NV \l_xtemplate_assignments_toks \l_xtemplate_value_tl
+}
+\cs_new_nopar:Npn \xtemplate_assign_code: {
+ \toks_put_left:Nx \l_xtemplate_assignments_toks {
+ \exp_not:N \cs_set:Npn \exp_not:N \xtemplate_assign_code:n ##1 {
+ \exp_not:V \l_xtemplate_var_tl
+ }
+ \exp_not:N \xtemplate_assign_code:n
+ { \exp_not:V \l_xtemplate_value_tl }
+ }
+}
+\cs_new:Npn \xtemplate_assign_code:n #1 { }
+\cs_new_nopar:Npn \xtemplate_assign_function: {
+ \bool_if:NTF \l_xtemplate_global_bool {
+ \xtemplate_assign_function_aux:N \cs_gset:Npn
+ }{
+ \xtemplate_assign_function_aux:N \cs_set:Npn
+ }
+}
+\cs_new_nopar:Npn \xtemplate_assign_function_aux:N #1 {
+ \toks_put_left:Nx \l_xtemplate_assignments_toks {
+ \exp_not:N \cs_generate_from_arg_count:NNnn
+ \exp_not:V \l_xtemplate_var_tl
+ \exp_not:N #1
+ { \exp_not:V \l_xtemplate_keytype_arg_tl }
+ { \exp_not:V \l_xtemplate_value_tl }
+ }
+}
+\cs_new_nopar:Npn \xtemplate_assign_instance: {
+ \bool_if:NTF \l_xtemplate_global_bool {
+ \xtemplate_assign_instance_aux:N \cs_gset:Npn
+ }{
+ \xtemplate_assign_instance_aux:N \cs_set:Npn
+ }
+}
+\cs_new_nopar:Npn \xtemplate_assign_instance_aux:N #1 {
+ \toks_put_left:Nx \l_xtemplate_assignments_toks {
+ \exp_not:N #1 \exp_not:V \l_xtemplate_var_tl {
+ \exp_not:N \xtemplate_use_instance:nn
+ { \exp_not:V \l_xtemplate_keytype_arg_tl }
+ { \exp_not:V \l_xtemplate_value_tl }
+ }
+ }
+}
+\cs_new_nopar:Npn \xtemplate_assign_integer: {
+ \bool_if:NTF \l_xtemplate_global_bool {
+ \xtemplate_assign_variable:N \int_gset:Nn
+ }{
+ \xtemplate_assign_variable:N \int_set:Nn
+ }
+}
+\cs_new_nopar:Npn \xtemplate_assign_length: {
+ \bool_if:NTF \l_xtemplate_global_bool {
+ \xtemplate_assign_variable:N \dim_gset:Nn
+ }{
+ \xtemplate_assign_variable:N \dim_set:Nn
+ }
+}
+\cs_new_nopar:Npn \xtemplate_assign_skip: {
+ \bool_if:NTF \l_xtemplate_global_bool {
+ \xtemplate_assign_variable:N \skip_gset:Nn
+ }{
+ \xtemplate_assign_variable:N \skip_set:Nn
+ }
+}
+\cs_new_nopar:Npn \xtemplate_assign_tokenlist: {
+ \bool_if:NTF \l_xtemplate_global_bool {
+ \xtemplate_assign_tokenlist_aux:N \tl_gset:Nn
+ }{
+ \xtemplate_assign_tokenlist_aux:N \tl_set:Nn
+ }
+}
+\cs_new_eq:NN \xtemplate_assign_commalist:
+ \xtemplate_assign_tokenlist:
+\cs_new_nopar:Npn \xtemplate_assign_tokenlist_aux:N #1 {
+ \toks_put_left:Nx \l_xtemplate_assignments_toks {
+ \exp_not:N #1 \exp_not:V \l_xtemplate_var_tl
+ { \exp_not:V \l_xtemplate_value_tl }
+ }
+}
+\cs_new_nopar:Npn \xtemplate_assign_variable:N #1 {
+ \xtemplate_if_key_value:VT \l_xtemplate_value_tl {
+ \xtemplate_key_to_value:
+ }
+ \toks_put_left:Nx \l_xtemplate_assignments_toks {
+ \exp_not:N #1 \exp_not:V \l_xtemplate_var_tl
+ { \exp_not:V \l_xtemplate_value_tl }
+ }
+}
+\cs_new_nopar:Npn \xtemplate_key_to_value: {
+ \exp_after:wN \xtemplate_key_to_value_aux:w \l_xtemplate_value_tl
+}
+\cs_new:Npn \xtemplate_key_to_value_aux:w \KeyValue #1 {
+ \tl_set:Nx \l_xtemplate_tmp_tl { \tl_to_str:n {#1} }
+ \tl_replace_all_in:Nnn \l_xtemplate_key_name_tl { ~ } { }
+ \prop_if_in:NVTF \l_xtemplate_vars_prop \l_xtemplate_tmp_tl {
+ \prop_get:NVN \l_xtemplate_vars_prop \l_xtemplate_tmp_tl
+ \l_xtemplate_value_tl
+ }{
+ \msg_kernel_error:nnx { xtemplate } { unknown-attribute }
+ { \l_xtemplate_tmp_tl }
+ }
+}
+\cs_new:Npn \xtemplate_use_instance:nn #1#2 {
+ \xtemplate_if_use_template:nTF {#2} {
+ \xtemplate_use_instance_aux:nNnnn {#1} #2
+ }{
+ \xtemplate_use_instance_aux:nn {#1} {#2}
+ }
+}
+\cs_new:Npn \xtemplate_use_instance_aux:nNnnn #1#2#3#4#5 {
+ \tl_if_eq:nnTF {#1} {#3} {
+ \xtemplate_use_template:nnn {#3} {#4} {#5}
+ }{
+ \msg_kernel_error:nnxx { xtemplate } { type-mismatch } {#1} {#3}
+ }
+}
+\cs_new:Npn \xtemplate_use_instance_aux:nn #1#2 {
+ \xtemplate_get_collection:n {#1}
+ \xtemplate_if_instance_exist:nnnTF
+ {#1} { \l_xtemplate_collection_tl } {#2} {
+ \use:c {
+ \c_xtemplate_instances_root_tl #1 / \l_xtemplate_collection_tl /#2
+ :w
+ }
+ }{
+ \xtemplate_if_instance_exist:nnnTF {#1} { } {#2} {
+ \use:c { \c_xtemplate_instances_root_tl #1 / / #2 :w }
+ }{
+ \msg_kernel_error:nnxx { xtemplate } { unknown-instance }
+ {#1} {#2}
+ }
+ }
+}
+\cs_new:Npn \xtemplate_use_collection:nn #1#2 {
+ \prop_put:Nnn \l_xtemplate_collections_prop {#1} {#2}
+}
+\cs_new:Npn \xtemplate_get_collection:n #1 {
+ \prop_if_in:NnTF \l_xtemplate_collections_prop {#1} {
+ \prop_get:NnN \l_xtemplate_collections_prop {#1}
+ \l_xtemplate_collection_tl
+ }{
+ \tl_clear:N \l_xtemplate_collection_tl
+ }
+}
+\cs_new_nopar:Npn \xtemplate_assignments_pop: {
+ \toks_use:N \l_xtemplate_assignments_toks
+}
+\cs_new:Npn \xtemplate_assignments_push:n #1 {
+ \toks_set:Nn \l_xtemplate_assignments_toks {#1}
+}
+\cs_new:Npn \xtemplate_show_code:nn #1#2 {
+ \xtemplate_execute_if_code_exist:nnT {#1} {#2}
+ { \cs_show:c { \c_xtemplate_code_root_tl #1 / #2 :w } }
+}
+\cs_new:Npn \xtemplate_show_defaults:nn #1#2 {
+ \xtemplate_if_keys_exist:nnT {#1} {#2}
+ {
+ \xtemplate_recover_defaults:n { #1 / #2 }
+ \prop_display:N \l_xtemplate_values_prop
+ }
+}
+\cs_new:Npn \xtemplate_show_keytypes:nn #1#2 {
+ \xtemplate_if_keys_exist:nnT {#1} {#2}
+ {
+ \xtemplate_recover_keytypes:n { #1 / #2 }
+ \prop_display:N \l_xtemplate_keytypes_prop
+ }
+}
+\cs_new:Npn \xtemplate_show_values:nnn #1#2#3 {
+ \xtemplate_if_instance_exist:nnnTF {#1} {#2} {#3}
+ {
+ \xtemplate_recover_values:n { #1 / #2 / #3 }
+ \prop_display:N \l_xtemplate_values_prop
+ }
+ {
+ \msg_kernel_error:nnxx { xtemplate } { unknown-instance }
+ {#1} {#2}
+ }
+}
+\cs_new:Npn \xtemplate_show_vars:nn #1#2 {
+ \xtemplate_execute_if_code_exist:nnT {#1} {#2}
+ {
+ \xtemplate_recover_vars:n { #1 / #2 }
+ \prop_display:N \l_xtemplate_vars_prop
+ }
+}
+\msg_kernel_new:nnnn { xtemplate } { argument-number-mismatch }
+ {Object type `#1' takes `#2' not `#3' argument(s).}
+ {%
+ Objects of type `#1' require `#2' arguments.\\%
+ You have tried to make a template for `#1'\\%
+ with `#3' arguments, which is not possible:\\%
+ the number of arguments must agree.%
+ }
+\msg_kernel_new:nnnn { xtemplate } { bad-number-of-arguments }
+ {%
+ Impossible number of arguments declared for\\%
+ object type `#1'.%
+ }
+ {%
+ An object may accept between 0 and 9 arguments.\\%
+ You asked to use #2 arguments: this is not supported.%
+ }
+\msg_kernel_new:nnnn { xtemplate } { bad-variable }
+ {Incorrect variable description \msg_line_context:.}
+ {%
+ The argument `#1'\\%
+ is not of the form `<variable>' or `global <variable>'.\\%
+ It must be given in one of these formats to be used in a template.%
+ }
+\msg_kernel_new:nnnn { xtemplate } { choice-not-implemented }
+ {The choice `#1' has no implementation \msg_line_context:.}
+ {%
+ Each choice listed in the interface for a template must\\%
+ have an implementation.\\%
+ I did not find an implementation for `#1'.%
+ }
+\msg_kernel_new:nnnn { xtemplate } { choice-unknown-reserved }
+ {The choice `unknown' cannot be given for a template key.}
+ {%
+ The `unknown' choice is automatically checked by template when\\%
+ a choice key is given with an unknown value. It should not be\\%
+ included in the list of named choices for a key, and is always\\%
+ given last in the implementation of choices.%
+ }
+\msg_kernel_new:nnnn { xtemplate } { duplicate-key-interface }
+ {Key `#1' appears twice in interface definition \msg_line_context:.}
+ {%
+ Each key can only have one interface declared in a template.\\%
+ I found two interfaces for `#1': probably a typing error.%
+ }
+\msg_kernel_new:nnnn { xtemplate } { empty-key-name }
+ {No key name found in `#1' \msg_line_context:.}
+ {%
+ A template key name and type is given in the form:\\%
+ \msg_space: <name> : <type> \\%
+ Parsing your input, I found a `:' but nothing before
+ it!%
+ }
+\msg_kernel_new:nnnn { xtemplate } { key-no-value }
+ {The key `#1' has no value \msg_line_context:.}
+ {%
+ When creating an instance of a template\\%
+ every key listed must include a value:
+ \msg_two_spaces: <key> = <value>
+ }
+\msg_kernel_new:nnnn { xtemplate } { key-no-variable }
+ {The key `#1' requires implementation details \msg_line_context:.}
+ {%
+ When creating template code using
+ \token_to_str:N \DeclareTemplateCode,\\%
+ each key name must have an associated implementation.\\%
+ This should be given after an `=' sign: I did not find one.%
+ }
+\msg_kernel_new:nnnn { xtemplate } { key-not-implemented }
+ {Key `#1' has no implementation \msg_line_context:.}
+ {%
+ The definition of key implementations for template `#2'\\%
+ of object type `#3' does not include any details for key `#1'.\\%
+ The key was declared in the interface definition,\\%
+ and so an implementation is required.%
+ }
+\msg_kernel_new:nnnn { xtemplate } { keytype-requires-argument }
+ {The keytype `#1' requires an argument \msg_line_context:}
+ {%
+ You should have put:\\%
+ \msg_two_spaces: <key-name> : #1
+ \token_to_str:N { <argument> \token_to_str:N } \\%
+ but I did not find an <argument>.%
+ }
+\msg_kernel_new:nnnn { xtemplate } { no-keytype }
+ {The key `#1' is missing a keytype \msg_line_context:}
+ {%
+ You should have put:\\%
+ \msg_two_spaces: #1 : <keytype>\\%
+ but I did not find an <keytype>.%
+ }
+\msg_kernel_new:nnnn { xtemplate } { no-template-code }
+ {%
+ The template `#2' of type `#1' is unknown\\%
+ or has no implementation.%
+ }
+ {%
+ You need to declare a template with
+ \token_to_str:N \DeclareTemplateInterface \\%
+ and its code with
+ \token_to_str:N \DeclareTemplateCode \msg_space:
+ prior to using it.%
+ }
+\msg_kernel_new:nnnn { xtemplate } { type-mismatch }
+ {Object types `#1' and `#2' do not agree.}
+ {%
+ You are trying to use a template directly with
+ \token_to_str:N \UseInstance \\%
+ (or a similar function), but the object types do not match.%
+ }
+\msg_kernel_new:nnnn { xtemplate } { undeclared-variable }
+ {The variable #1has not been declared.}
+ {%
+ Before declaring an instance, all of the required variables\\%
+ used in template keys must be created.%
+ }
+\msg_kernel_new:nnnn { xtemplate } { unknown-attribute }
+ {The template attribute `#1' is unknown.}
+ {%
+ There is a definition in the current template reading\\%
+ \token_to_str:N \KeyValue
+ \token_to_str:N { #1 \token_to_str:N }\\%
+ but there is no key called `#1'.%
+ }
+\msg_kernel_new:nnnn { xtemplate } { unknown-choice }
+ {The choice `#1' was not declared for key `#2' \msg_line_context:.}
+ {%
+ The key `#2' takes a fixed number of choices:\\%
+ \clist_map_function:NN #3 \xtemplate_unknown_choice_aux:n
+ and this list does not include `#1'.%
+ }
+\cs_new:Npn \xtemplate_unknown_choice_aux:n #1 { -~ #1 ;\\}
+\msg_kernel_new:nnnn { xtemplate } { unknown-keytype }
+ {The keytype `#1' is unknown \msg_line_context:.}
+ {%
+ Valid keytypes are:\\%
+ - boolean;\\%
+ - choice;\\%
+ - code;\\%
+ - commalist;\\%
+ - function;\\%
+ - instance;\\%
+ - integer;\\%
+ - length;\\%
+ - skip;\\%
+ - tokenlist.%
+ }
+\msg_kernel_new:nnnn { xtemplate } { unknown-object-type }
+ {The object type `#1' is unknown \msg_line_context:.}
+ {%
+ An object type needs to be declared with
+ \token_to_str:N \DeclareObjectType \msg_space:
+ prior to using it.%
+ }
+\msg_kernel_new:nnnn { xtemplate } { unknown-instance }
+ {The instance `#2' of type `#1' is unknown.}
+ {%
+ You have asked to use an instance `#2',\\%
+ but this has not been created.%
+ }
+\msg_kernel_new:nnnn { xtemplate } { unknown-key }
+ {Unknown template key `#1' \msg_line_context:.}
+ {%
+ The key `#1' was not declared in the interface\\%
+ for the current template.\\%
+ Probably you have misspelled the key name.%
+ }
+\msg_kernel_new:nnnn { xtemplate } { unknown-template }
+ {The template `#2' of type `#1' is unknown \msg_line_context:.}
+ {%
+ No interface has been declared for a template\\%
+ `#2' of object type `#1'.%
+ }
+\msg_kernel_new:nnn { xtemplate } { define-template-code }
+ {Defining template code for `#1' \msg_line_context:.}
+\msg_kernel_new:nnn { xtemplate } { define-template-interface }
+ {Defining template interface for `#1' \msg_line_context:.}
+\msg_kernel_new:nnn { xtemplate } { define-object-type }
+ {Defining object type `#1' with #2 argument(s) \msg_line_context:.}
+\msg_kernel_new:nnn { xtemplate } { redefine-template-code }
+ {Redefining template code for `#1' \msg_line_context:.}
+\msg_kernel_new:nnn { xtemplate } { redefine-template-interface }
+ {Redefining template interface for `#1' \msg_line_context:.}
+\msg_kernel_new:nnn { xtemplate } { redefine-object-type }
+ {Redefining object type `#1' with #2 argument(s) \msg_line_context:.}
+\cs_new_protected_nopar:Npn \DeclareObjectType #1#2 {
+ \xtemplate_declare_object_type:nn {#1} {#2}
+}
+\cs_new_protected:Npn \DeclareTemplateInterface #1#2#3#4 {
+ \xtemplate_declare_template_keys:nnnn {#1} {#2} {#3} {#4}
+}
+\cs_new_protected:Npn \DeclareTemplateCode #1#2#3#4#5 {
+ \xtemplate_declare_template_code:nnnnn {#1} {#2} {#3} {#4} {#5}
+}
+\cs_new_protected:Npn \DeclareRestrictedTemplate #1#2#3#4 {
+ \xtemplate_declare_restricted:nnnn {#1} {#2} {#3} {#4}
+}
+\cs_new_protected:Npn \DeclareInstance #1#2#3#4 {
+ \xtemplate_declare_instance:nnnnn {#1} {#3} { } {#2} {#4}
+}
+\cs_new_protected:Npn \DeclareCollectionInstance #1#2#3#4#5 {
+ \xtemplate_declare_instance:nnnnn {#2} {#4} {#1} {#3} {#5}
+}
+\cs_new_protected:Npn \EditTemplateDefaults #1#2#3 {
+ \xtemplate_edit_defaults:nnn {#1} {#2} {#3}
+}
+\cs_new_protected:Npn \EditInstance #1#2#3 {
+ \xtemplate_edit_instance:nnnn {#1} { } {#2} {#3}
+}
+\cs_new_protected:Npn \EditCollectionInstance #1#2#3#4 {
+ \xtemplate_edit_instance:nnnn {#2} {#1} {#3} {#4}
+}
+\cs_new_protected_nopar:Npn \UseTemplate #1#2#3 {
+ \xtemplate_use_template:nnn {#1} {#2} {#3}
+}
+\cs_new_protected_nopar:Npn \UseInstance #1#2 {
+ \xtemplate_use_instance:nn {#1} {#2}
+}
+\cs_new_protected_nopar:Npn \UseCollection #1#2 {
+ \xtemplate_use_collection:nn {#1} {#2}
+}
+\cs_new_protected_nopar:Npn \ShowTemplateCode #1#2 {
+ \xtemplate_show_code:nn {#1} {#2}
+}
+\cs_new_protected_nopar:Npn \ShowTemplateDefaults #1#2 {
+ \xtemplate_show_defaults:nn {#1} {#2}
+}
+\cs_new_protected_nopar:Npn \ShowTemplateKeytypes #1#2 {
+ \xtemplate_show_keytypes:nn {#1} {#2}
+}
+\cs_new_protected_nopar:Npn \ShowTemplateVariables #1#2 {
+ \xtemplate_show_vars:nn {#1} {#2}
+}
+\cs_new_protected_nopar:Npn \ShowInstanceValues #1#2 {
+ \xtemplate_show_values:nnn {#1} { } {#2}
+}
+\cs_new_protected_nopar:Npn \ShowCollectionInstanceValues #1#2#3 {
+ \xtemplate_show_values:nnn {#1} {#2} {#3}
+}
+\cs_new_nopar:Npn \IfInstanceExistTF #1#2 {
+ \xtemplate_if_instance_exist:nnnTF {#1} { } {#2}
+}
+\cs_new_nopar:Npn \IfInstanceExistT #1#2 {
+ \xtemplate_if_instance_exist:nnnT {#1} { } {#2}
+}
+\cs_new_nopar:Npn \IfInstanceExistF #1#2 {
+ \xtemplate_if_instance_exist:nnnF {#1} { } {#2}
+}
+\cs_new_protected:Npn \EvaluateNow #1 {#1}
+\cs_new_protected:Npn \KeyValue #1 {#1}
+\cs_new_protected_nopar:Npn \AssignTemplateKeys {
+ \xtemplate_assignments_pop:
+}
+\cs_new_nopar:Npn \TP_split_finite_skip_value:nnNN #1#2{
+ \skip_split_finite_else_action:nnNN {#1} {
+ \PackageError{xtemplate}{Value~ for~ key~ #2~ contains~ `fil(ll)'}
+ {Only~ finite~ minus~ or~ plus~ parts~ are~ allowed~ for~ this~ key.}
+ }
+}
+\endinput
+%%
+%% End of file `xtemplate.sty'.
diff --git a/Master/texmf-dist/tex/latex/xpackages/xtras/l3keys2e.sty b/Master/texmf-dist/tex/latex/xpackages/xtras/l3keys2e.sty
index 67e67fe285a..e108b0aff35 100644
--- a/Master/texmf-dist/tex/latex/xpackages/xtras/l3keys2e.sty
+++ b/Master/texmf-dist/tex/latex/xpackages/xtras/l3keys2e.sty
@@ -51,7 +51,7 @@
{\filename}{\filedate}{\fileversion}{\filedescription}
\RequirePackage{xparse}
\clist_new:N \keys_latexe_options_clist
-\cs_new:Nn \keys_latexe_options:n {
+\cs_new:Npn \keys_latexe_options:n #1 {
\clist_clear:N \keys_latexe_options_clist
\keys_latexe_options_global:n {#1}
\keys_latexe_options_local:
@@ -70,7 +70,7 @@
Unknown~option~`#1'\\%
for~module~#2.%
}
-\cs_new:Nn \keys_latexe_options_global:n {
+\cs_new:Npn \keys_latexe_options_global:n #1 {
\cs_if_eq:NNF \@classoptionslist \scan_stop: {
\cs_if_eq:NNTF \@currext \@clsextension {
\keys_latexe_options_class:n {#1}
@@ -79,7 +79,7 @@
}
}
}
-\cs_new:Nn \keys_latexe_options_class:n {
+\cs_new:Npn \keys_latexe_options_class:n #1 {
\clist_map_inline:Nn \@classoptionslist {
\keys_if_exist:nnTF {#1} { \keys_latexe_remove_equals:n {##1} } {
\clist_put_right:Nn \keys_latexe_options_clist {##1}
@@ -88,7 +88,7 @@
}
}
}
-\cs_new:Nn \keys_latexe_options_package:n {
+\cs_new:Npn \keys_latexe_options_package:n #1 {
\clist_map_inline:Nn \@classoptionslist {
\keys_if_exist:nnT {#1} { \keys_latexe_remove_equals:n {##1} } {
\clist_put_right:Nn \keys_latexe_options_clist {##1}
@@ -96,7 +96,7 @@
}
}
}
-\cs_new_nopar:Nn \keys_latexe_options_local: {
+\cs_new_nopar:Npn \keys_latexe_options_local: {
\cs_if_eq:NNF \@currext \@clsextension {
\cs_if_exist:cT { opt@ \@currname . \@currext } {
\exp_args:NNc \clist_put_right:NV \keys_latexe_options_clist
@@ -104,7 +104,7 @@
}
}
}
-\cs_new:Nn \keys_latexe_remove_equals:n {
+\cs_new:Npn \keys_latexe_remove_equals:n #1 {
\keys_latexe_remove_equals:w #1 = \q_stop
}
\cs_new:Npn \keys_latexe_remove_equals:w #1 = #2 \q_stop {#1}