% \iffalse meta-comment
%
%% File: latex-lab-template.dtx
%
% Copyright (C) 2026 The LaTeX 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
%
%    https://www.latex-project.org/lppl.txt
%
%
% The latex-lab bundle is developed in the LaTeX2e GitHub.
% Issues may be reported at
%
%    https://github.com/latex3/latex2e/issues
%
\def\ltlabtemplatedate{2026-09-06}
\def\ltlabtemplateversion{0.6f}
%<*driver>
\DocumentMetadata{tagging=on,pdfstandard=ua-2}

\documentclass[kernel]{l3in2edoc}


\usepackage{amstext}
\usepackage{xcolor}

\EnableCrossrefs
\CodelineIndex
%\OnlyDescription

\usepackage{todonotes}

\begin{document}
  \DocInput{latex-lab-template.dtx}

  \PrintIndex
\end{document}
%</driver>
%
% \fi
%
%
% \NewDocumentCommand\fmi{sO{}m}
%   {\IfBooleanTF{#1}{\todo[inline,#2]{#3}}^^A
%                    {\todo[#2]{#3}}}
%
% \NewDocumentCommand\ufi{sO{}m}
%   {\IfBooleanTF{#1}{\todo[inline,#2]{UFi:#3}}^^A
%                    {\todo[#2]{UFi:#3}}}
%
% \providecommand\key[1]{\texttt{#1}}
% \providecommand\insttype[1]{\texttt{#1}}
%
% \providecommand\struct[1]{\texttt{<#1>}}
%
% \DeleteShortVerb\|
%
% \title{Extending the \LaTeX{} templating mechanism}
% \author{\LaTeX{} Project\thanks{Initial implementation by Frank Mittelbach.}}
% \date{v\ltlabtemplateversion\ \ltlabtemplatedate}
%
% \maketitle
%
%
% \begin{abstract}
%    This module contains code for the kernel implementation of
%    templates (in \texttt{lttemplate.dtx}). After suitable testing
%    this will be moved there. 
% \end{abstract}
%
%
% \tableofcontents
% \medskip
%
%
% \begin{documentation}
%
% \section{Handling \meta{order} keys in a generic way}
%
%    Templates often have to typeset several items of textual data
%    (from keys and/or from template arguments) with slight variations
%    from instance to instance, e.g., the ordering and the separation
%    between the items might differ or in other cases only a subset of
%    the items are present (or supported). For example, a theorem-like
%    environment typically wants to have a fixed title, a number, some
%    punctuation, and possibly a note (provided through document
%    input). However, one design might ask for \enquote{Lemma 3.2 (note)},
%     the next for \enquote{3.2 Lemma. (note)}, and another for
%    \enquote{3.2 Lemma \textit{note}.} with a different ordering and
%    a punctuation somewhere or not.
%
%    While it is, of course, possible to achieve this by providing
%    different templates that only differ in small aspects, it is often
%    better to do this by providing a template key that defines the
%    order of certain elements (and in which you can leave out some)
%    and have the template code process this key and in this way achieve
%    various layouts through a single template.
%
%    To make this possible such \meta{order} keys and their allowed
%    values need to follow a few conventions that we explain below and
%    give some examples.
%
%
%
% \subsection{Conventions for the \meta{order} comma list key}
%
%    The \meta{order} key has to be a clist and the corresponding
%    variable name (i.e., the binding) must be
%    \cs{l_@@_\meta{order}_clist}, e.g., in
%    \cs{DeclareTemplateInterface}
%\begin{verbatim}
%    caption-order : commalist = { title, separator-a,
%                                  number, separator-b, note, punct }
%\end{verbatim}
%    and in \cs{DeclareTemplateCode}
%\begin{verbatim}
%    caption-order = name {l_@@_caption-order_clist}
%\end{verbatim}
%    The clist variable needs to contain the \meta{order} key name
%    which is why we had to resort to the \texttt{name} interface to
%    get a nonstandard variable name containing a \texttt{-}. For
%    simple key names like \key{order}, that would not be necessary
%    and the line would look like this:
%\begin{verbatim}
%    order = \l_@@_order_clist
%\end{verbatim}
%    Of course, there is no requirement to provide a default value (as
%    we did above) but in many cases there is a commonly used sequence that
%    could be provided as a default.
%
%
% \subsection{Conventions for the items in the \meta{order} key clist}
%
%    For each \meta{item} in the comma list, e.g, in the above example
%    \texttt{title}, \texttt{separator-a}, \texttt{number},
%    \texttt{punct}, \texttt{separator-b}, and \texttt{note}, there has
%    to exist a variable with the name \cs{l_@@_\meta{item}_tl}. If
%    the items themselves are keys in the template that is achieved
%    through settings such as
%\begin{verbatim}
%    title       : tokenlist = Lemma ,
%    separator-a : tokenlist = \enspace ,
%    ...
%\end{verbatim}
%    and
%\begin{verbatim}
%    title       = \l_@@_title_tl ,
%    separator-a = name {l_@@_separator-a_tl} ,
%    ...
%\end{verbatim}
%    Again, we had to make use of the \texttt{name} keyword because
%    the key \key{separator-a} contains a hyphen.
%
%    If the data of such an item is user input and provided through a
%    mandatory argument to the template, e.g., the data for a
%    \texttt{note}, then you can fulfill the requirement by defining the
%    variable in the template code, e.g.,
%\begin{verbatim}
%    \tl_set:Nn \l_@@_note_tl {#3} 
%\end{verbatim}
%    or in whatever argument the note data is passed to the template.
%
%    If the user hasn't provided a note, then this is indicated by
%    passing \cs{NoValue} to the template in that argument (as long as
%    \cs{NewDocumentCommand} or a similar extended command definition
%    offered by the \LaTeX{} kernel is used). In that case the
%    mechanism correctly interprets this and ignores a \texttt{note}
%    item in the processing of the \meta{order} key.
%
%    The existence of \cs{l_@@_\meta{item}_tl} is required: if it is
%    not defined, then using \meta{item} in the comma list will lead to
%    an error message.
%
%    Not required, but often wanted, are the following additional
%    token list variables and commands (per \meta{item}):
%    \begin{description}
%    \item[\cs{l_@@_\meta{item}_decls_tl}]
%
%      A token list that contains declarations (such as font changes)
%      that are applied just before the \meta{item} data is
%      typeset. Processing happens in a group, so that changes are
%      reverted after the \meta{item} was typeset.
%
%    \item[\cs{@@_\meta{item}_format:n}]
%
%      A command that receives the \meta{item} data as its argument and
%      can then manipulate it prior to typesetting.
%
%    \end{description}
%
%    So in summary what gets typeset is
%    \begin{quote}
%     \cs{group_begin:} \\
%       \hspace*{1em} \cs{l_@@_\meta{item}_decls_tl} \\
%       \hspace*{1em} \cs{@@_\meta{item}_format:n}
%            \texttt{\{} \cs{l_@@_\meta{item}_tl} \texttt{\}}  \\
%      \cs{group_end:}
%    \end{quote}
%
%    Note that this means that paragraph parameters (such as
%    \cs{baselineskip}) that are only evaluated at the end of a
%    paragraph are ignored if placed in \cs{l_@@_\meta{item}_decls_tl}
%    or \cs{@@_\meta{item}_format:n} unless the latter contains a
%    \cs{par} that ends the current paragraph.\footnote{This is
%    different from separator items that are executed outside of these
%    groups. This means that parameter changes done in a separator are
%    seen by all following \meta{item}s.}
%
%
%
%    Strictly speaking, the \cs{l_@@_\meta{item}_decls_tl} token list
%    is not needed, since all one can do with it can also be done
%    through a suitably defined \cs{@@_\meta{item}_format:n}
%    command. Thus, what to use is often a matter of taste. Our
%    default templates provide both to cater for different
%    preferences.
%
%    If the token list variable and command are exposed via keys (so that
%    they can be set in an instance) then the names have to be
%    given exactly as specified above in order for the mechanism to
%    pick them up. However, you are free to choose whatever key name
%    you like. By convention, we use \key{\meta{item}-decls} and
%    \key{\meta{item}-format} as key names because we always use
%    \texttt{-} in longer key names.
%
%
% \subsection{Conventions for the separators used in the \meta{order} key clist}
%
%    Besides items containing textual data there is also often the
%    need to specify data that separates them (typically by some
%    space). These separators need a somewhat different handling,
%    because if an item such as a \key{note} is not present, then a
%    separator before it should normally be dropped, e.g., one does
%    not want to get
%    \enquote{Lemma 3.2\textvisiblespace .} but \enquote{Lemma 3.2.}
%    if the punctuation key \key{punct} comes at the end of the
%    \meta{order} list and the \key{note} before it was dropped.
%
%    Similarly, in some situations one wants to drop a separator after
%    a data item that has no value, that can be done too, by combining
%    the separator with the special \texttt{?} or \texttt{|} items
%    discussed below.
%
%    To support this behavior, it is necessary for the mechanism to
%    identify that a \meta{item} name is a separator and not a normal
%    textual item.
%    We therefore recommend to use (some of) the following names that
%    have already been prepared for use with the
%    mechanism.\footnote{It is possible to use other names or provide
%    more with the help of \cs{template_new_order_separator:n} if
%    really necessary, but the five (or rather six) we offer should
%    normally be sufficient.}
%
%    So a typical setup is
%\begin{verbatim}
%    separator-a : tokenlist = \ ,
%    separator-b : tokenlist = \ ,
%    ...
%\end{verbatim}
%
%\begin{verbatim}
%    separator-a = name {l_@@_separator-a_tl} ,
%    separator-b = name {l_@@_separator-b_tl} ,
%    ...
%\end{verbatim}
%    up to \key{separator-e} and for cases where you need only one
%    separator there is also the key \texttt{separator} (which can, of
%    course, also be used in addition to the others).
%
%    If several separators are specified directly after another in the
%    \meta{order} clist then all of them are typeset or dropped
%    depending on the next item that isn't a separator. Separator(s)
%    at the very start of the clist use the same logic.
%
%    If a separator is specified at the very end of the clist it is
%    always typeset (unless the special item \text{|} is used after it
%    in which case it is only typeset if the preceding data item had a value).
%
%    If you need some separation that should not be dropped in case
%    the next normal item is absent (i.e., has \cs{NoValue} as its
%    value) then you can use \texttt{|} after it to control it from
%    the previous data item or use \texttt{!} to typeset it
%    unconditionally.
%
%
% \subsection{The special items  \texttt{?}, \texttt{|}, and
%    \texttt{!} in the \meta{order} key clist}
%
%    Separators \emph{before} an item that has \cs{NoValue} as its value are
%    dropped, but in some cases some or all of the separators
%    \emph{following} such an item should also be dropped. For
%    example, in the order list
%\begin{verbatim}
%    order = {prefix, separator-a, number, ...
%\end{verbatim}
%    one normally doesn't want a space in front of the \texttt{number}
%    if there is no \texttt{prefix}. To implement such scenarios
%    easily, one can use the special item \texttt{?}, which has the
%    following effect: it drops all collected separators if the
%    last data item was dropped, otherwise it does nothing and the
%    decision what to do with the collected separators happens when
%    the next data item is processed. For
%    example, if we have
%\begin{verbatim}
%    order = {prefix, separator-a, ? , separator-b, number, ...
%\end{verbatim}
%    and \texttt{prefix} was \cs{NoValue} then \texttt{separator-a} is
%    dropped but \texttt{separator-b} after the \texttt{?} is used
%    unless \texttt{number} is also \cs{NoValue}. If \texttt{prefix}
%    has a value but \texttt{number} has no value, then both
%    separators are dropped.
%
%    The \texttt{|} special item is similar but in that case
%    separators on the left of it are fully controlled by the previous
%    data item, i.e., if that item has no value they are dropped and if it
%    has a value then they are directly typeset and thus independent
%    of the next data item.
%
%    Finally, there is also a \texttt{!} special item which results in
%    all collected separators to be unconditionally typeset, i.e.,
%    \texttt{separator,!} behaves as if the separator is a normal data
%    item (except that separators do not have corresponding
%    \texttt{...-decls} or \texttt{...-format} keys for customization).
%
%    For even more granular control, there is also
%    \cs{IfValueLastOrderItemTF} which can be used inside a separator
%    (or even inside the value of a normal data item)
%    to produce different actions depending on whether or not the last
%    data item had a value.
%
%
% \subsection{Grouping items in the \meta{order} key clist}
%
%    In some cases it is necessary to group some items in the
%    \meta{order} clist, e.g., to indicate that the \texttt{prefix}
%    and the \texttt{number} form the caption label when it comes to
%    tagging structures. This is done by using special items in the
%    clist: \texttt{<\meta{name}} to start a group and
%    \texttt{\meta{name}>} to end it. For example
%\begin{verbatim}
%    order = { <label, prefix, separator-a, number, label>, ... }
%\end{verbatim}
%    would group \texttt{prefix}, \texttt{separator-a}, and
%    \texttt{number}.
%
%    These special group items have to be declared using the
%    declaration \cs{template_new_order_group:nnnnnn}. With such a
%    declaration they are made known to the order key processing
%    mechanism. In addition, the necessary tagging support code is
%    defined, e.g., in the above example tagging support would
%    probably add a \struct{Lbl} structure.
%
%    Even though we may want to use \texttt{label} as a group
%    \meta{name} in different kinds of templates, the underlying
%    tagging support code will most likely differ from case to
%    case. The declaration therefore takes the current \meta{module}
%    as its first argument and \meta{name} as its second
%    argument.\footnote{This may need extension or change, e.g.,
%    perhaps we need to make it based on the current template type and
%    template name to achieve a proper separation, but for now we hope
%    that \meta{module} is enough. This is quite different to the case
%    of separators which can be reused across all templates because
%    they only need to pass their values to the order key processing
%    mechanism, i.e., their definition is always the same.} The
%    remaining four arguments define what should happen when
%    \texttt{<\meta{name}} and \texttt{\meta{name}>} are
%    processed. Details are given in the implementation section.
%
%
%    To specify specific (typesetting) declarations for such a group
%    the token list \cs{l_@@_\meta{name}_decls_tl} is available. Thus,
%    the template can set up, for example
%\begin{verbatim}
%    label-decls : tokenlist = ,
%\end{verbatim}
%    and
%\begin{verbatim}
%    label-decls = \l_@@_label_decls_tl ,
%\end{verbatim}
%    to enable customization during instance declaration. If no
%    customization is desired then just don't expose the variable in
%    which case it automatically remains empty.  Note that
%    \cs{@@_\meta{name}_format:n} \emph{is not supported} for such
%    groups.
%
%    Examples for such group items can already be found in
%    \insttype{thmstyle} templates and in \insttype{caption}
%    templates. More will follow over time.
%
%
%
% \subsection{Processing the \meta{order} key in the template code}
%
%    In the template code you use the \meta{order} key in the following way
%\begin{flushleft}\ttfamily\obeyspaces
%  \ \ \ \cs{template_process_order_clist:nnn}  \\
%  \ \ \ \ \ \ \{ \meta{module} \}              \\
%  \ \ \ \ \ \ \{ \meta{order key name} \}      \\
%  \ \ \ \ \ \ \{ \meta{supported items} \}
%\end{flushleft}
%    where first argument is the current module name (i.e., what \texttt{@@}
%    produces but without the leading \verb/__/)  and the second
%    argument is the name of your order key to process.
%    The
%    third argument is a comma list of support items, i.e., the value
%    of the \meta{order key name} must contain only items from that
%    argument.\footnote{This is checked to prevent the use of items
%    that aren't supported by the current template but are
%    defined by some other template and would therefore
%    produce unpredictable and erroneous results.}
%
%    This command then typesets the items listed in the \meta{order}
%    key or more precisely the content stored in the associated token
%    list parameters \cs{l_@@_\meta{item}_tl}, applying
%    \cs{l_@@_\meta{item}_decls_tl} and/or
%    \cs{@@_\meta{item}_format:n} if defined, and ignoring those items
%    that have \cs{NoValue} as their token list value. Separators in
%    front of ignored items are dropped, all others are typeset in the
%    specified places unless the list contains any special items
%    \texttt{?}, \texttt{|}, or \texttt{!} in which case they control
%    what happens with the separators.
%
%    The command also handles the tagging, i.e., it adds the necessary
%    structures. How this can be influenced is described below.
%
%
%
% \subsection{Tagging produced when processing the \meta{order} key}
%
%    If nothing special is specified then the order key processing
%    mechanism typesets the items without adding any specific tagging
%    structures. It does, however, ensure that everything is wrapped
%    into one or more MCs (marked content structures). This is
%    normally automatically done by \LaTeX{}'s paragraph
%    tagging. However, in situations where the mechanism is applied,
%    we often need \cs{tagpdfparaOff} in which case switching in and
%    out of hmode does not generate MCs on its own.
%    The \cs{template_process_order_clist:nnn} command therefore
%    \begin{itemize}
%    \item
%      checks and remembers if an MC is already open at the start;
%    \item
%      if not, it opens one;
%    \item
%      it then processes all items, possibly also adding structure
%      elements as explained below;
%    \item
%      and at the end it restores the MC state it had found at the
%      beginning, e.g., closes the MC if none was open at the
%      start. However, if it ends in vertical mode it does not reopen
%      an MC if one was open when it started.
%   \end{itemize}
%
%    In addition it is also possible to surround individual items from
%    the \meta{order} list with a structure element, e.g., a
%    \struct{text-fragment} or an \struct{Artifact}. In this case, the
%    current MC is ended, the structure and a new MC are started, then
%    the item is typeset. Afterwards the MC and the structure are
%    closed and the next item in the list then opens a new MC to be
%    used for the remainder of the \meta{order} list.\footnote{Perhaps
%    a better approach would be to use dedicated sockets generated
%    from the \meta{item} name. That would give more flexibility that
%    may be needed.}
%
%    For this to work the desired structure name needs to be stored in
%    the token list
%    \cs{l_@@_\meta{item}_tag_tl}. This can be hardwired  in the
%    template code or offered through a key, if the need for
%    customization is expected, e.g.
%\begin{verbatim}
%    prefix-tag-name : tokenlist ,
%\end{verbatim}
%    and
%\begin{verbatim}
%    prefix-tag-name = \l_@@_prefix_tag_tl ,
%\end{verbatim}
%    and then changed with \texttt{prefix-tag-name = Artifact} in an
%    instance. 
%
%    As already mentioned, the grouping items also produce special
%    tagging. For example, an order key setting for a caption might
%    look like
%\begin{verbatim}
%    order = { <label , ... , label> , <data , ... , data> }
%\end{verbatim}
%    where the \texttt{label} group generates a \struct{Lbl}
%    structure element (with paragraph tagging off and MC handling
%    inside managed by the order key processing), and the \texttt{data}
%    group that generates one or more \struct{text-block} structures
%    (aka.\ \struct{P}) and may also contain other structures such as
%    lists or quotations.
%
%    To make this possible, the \cs{template_new_order_group:nnnnnn}
%    declaration defines a normal and a tagging socket for use in
%    \texttt{<\meta{name}} and another pair for use in
%    \texttt{\meta{name}>}. The names are
%    \texttt{\meta{module}/\meta{name}/begin} and \texttt{.../end},
%    respectively. The normal sockets are usually empty, but may
%    contain a \cs{leavevmode} or a \cs{par} (or something else) if
%    tagging is handled through normal paragraph processing and a
%    defined state at the start or end is needed. Most of the time,
%    the tagging payload is only in the tagging sockets.
%
%
% \section{Interfaces}
%
%
% \begin{function}{\template_process_order_clist:nnn}
% \begin{syntax}
% \cs{template_process_order_clist:nnn}
%  \quad \Arg{module} \Arg{order key name} \Arg{supported items}
% \end{syntax}
%^^A
%    Takes an \meta{order}  key and processes its items, i.e., typesets
%    them and adds tagging structures.
%
%    The current \meta{module} is explicitly given, i.e., what
%    \verb=@@= would produce but without the two underscores as
%    prefix, e.g., \verb=thmstyle=. It is used to construct related
%    variables and is needed in error messages. The \meta{order key
%    name} is the name of the key you want to process. Finally, the
%    \meta{supported items} argument lists the items that are allowed
%    to appear in the value of the order key (except for \texttt{?},
%    \texttt{|}, and \texttt{!} that do not need to be listed
%    explicitly).  Thus a typical call would be
%\begin{verbatim}
%    \template_process_order_clist:nnn
%       {thmstyle}
%       {order}
%       {note,number,punct,separator,title}
%\end{verbatim}
% \end{function}
%
%
%
%
%
% \begin{function}{\template_new_order_separator:n}
% \begin{syntax}
% \cs{template_new_order_separator:n}\Arg{separator item name}
% \end{syntax}
%    Separators are items in an order clist that are supposed to
%    vanish if the next normal item is not present (typically they
%    generate some space). Their names need to be predeclared to have
%    that role which is done with \cs{template_new_order_separator:n}.
%    Once declared the \meta{separator item name} has this role in any
%    order key, i.e., in contrast to group items the declaration
%    applies globally and not only to names in a specific module.
%
%    A suitable number of names are predeclared, so that function
%    should be seldom needed.
% \end{function}
%
%
%
%
%
% \begin{function}{\template_new_order_group:nnnnnn}
% \begin{syntax}
% \cs{template_new_order_group:nnnnnn} \Arg{module} \Arg{group}
%  \qquad\Arg{begin normal socket code} \Arg{begin tagging socket code}
%  \qquad\Arg{end normal socket code} \Arg{end tagging socket code}
% \end{syntax}
%^^A
%    This declares a new pair of \meta{group} items in \meta{module}
%    and declares sockets with the names
%    \texttt{\meta{module}/\meta{group}/begin} and
%    \texttt{\meta{module}/\meta{group}/end}, both as normal and as
%    tagging sockets. It also defines plugs with the name
%    \texttt{default} for each of them from the content of the
%    arguments 3--6.
%
%    Further plugs can be defined through
%    \cs{NewSocketPlug} or
%    \cs{NewTaggingSocketPlug} declarations
%    and plugged in
%    when necessary.
% \end{function}
%
%
% \section{Other code updates/extensions}
%
%    \cs{SetKnownTemplateKeys} is updated to do nothing (i.e., not
%    start key parsing)) if the argument is empty or contains
%    \cs{NoValue} (after one expansion). These are typical scenarios,
%    e.g., when a key list is passed in as \cs{UnusedTemplateKeys}. If
%    the argument contains a key/value list without any indirection
%    then an \texttt{o}-expansion will expand the first letter of the
%    first key so no harm is done.
%
%    \cs{SetTemplateKeys} was changed to use \cs{SetKnownTemplateKeys}
%    and then test \cs{UnusedTemplateKeys} instead of using the
%    low-level mechanism, because the latter exposes internals of the
%    implementation in its error message when an unknown key is
%    encountered as it shows the full path of the key.
%
%    The command \cs{__template_debug_typeout:n} was made public (as
%    \cs{template_debug_typeout:n} because any template may want to
%    issue debugging messages that are activated when
%    \cs{DebugTemplatesOn} is used.
%
%    The conditional \cs{IfTemplateExistsTF} and its variants have
%    been added so that classes or packages can check if a certain
%    template is provided and then declare instances based on it and
%    if not do something else.
% \end{documentation}
%
% \MaybeStop{}
%
% \newpage
%
% \begin{implementation}
% 
% \section{The Implementation}
%
%    This code will eventually move to \texttt{lttemplate.dtx}, for now
%    it is only available when \cs{DocumentMetadata} is used.
%
%    \begin{macrocode}
%<*package>
%<@@=template>
%    \end{macrocode}
%    
%
%    \begin{macrocode}
\ProvidesPackage {latex-lab-testphase-template}
                 [\ltlabtemplatedate\space v\ltlabtemplateversion\space
                            template implementation]
\ExplSyntaxOn
%    \end{macrocode}
%
%    
%    
%  \begin{macro}{\checkstatus}
%    A temporary debugging helper.
%    \begin{macrocode}
\cs_new_protected:Npn \checkstatus #1 {
  \@@_debug_typeout:n{-------------------- #1 ----------------}
  \mode_if_horizontal:TF
       { \@@_debug_typeout:n{==>~hmode} }
       { \@@_debug_typeout:n{==>~vmode} }
  
  \@@_debug_typeout:n{==>~para-tagging:~
			      \bool_if:NTF \l__tag_para_bool
				 { on~ (using~ \l__tag_para_tag_tl)}
				 { off }
	           	     }
  \tag_mc_if_in:TF
      { \@@_debug_typeout:n{\@spaces mc~ status:~ open} }
      { \@@_debug_typeout:n{\@spaces mc~ status:~ closed} }
  \@@_debug:n { \ShowTagging{struct-stack=log } }
%  \@@_debug:n { \ShowTagging{struct-stack } }
}      
%    \end{macrocode}
%  \end{macro}
%    
%    
%    
%  \begin{macro}{\template_process_order_clist:nnn}
%    The processing interface inside template code.
%    \begin{macrocode}
\cs_new_protected:Npn \template_process_order_clist:nnn #1#2#3 {
  \@@_debug_typeout:n { Processing~ order~ key~ '#2'}
  \checkstatus{Start}
%    \end{macrocode}
%    
%    \begin{macrocode}
  \group_begin:
%    \end{macrocode}
%    Setting up the command to restore the MC state after
%    processing. This can be shortened a lot if the debugging code
%    gets removed and then it could probably use the push/pop
%    commands.\fmi{drop the debugging eventually}
%    \begin{macrocode}
  \tag_mc_if_in:TF
      { \cs_set_protected:Npn \@@_restore_mc_state: {
          \mode_if_horizontal:TF
            {
              \tag_mc_if_in:TF
                  { \@@_debug_typeout:n {\@spaces mc~ restore~
                      already~open} 
                  }
                  { \@@_debug_typeout:n {\@spaces mc~ restore~ to~ open}
                    \tag_mc_begin:n{}
                  }
            }
%    \end{macrocode}
%    Do not restore an initially open MC if we end up in vertical mode
%    after the order key processing. That means there was some
%    \cs{par} along the way and we assume that this did the closing
%    (which would be the correct state then)\fmi{Verify logic, I
%    haven't fully convinced myself!}
%    \begin{macrocode}
            { \@@_debug_typeout:n {\@spaces no~ mc~ restore~ in~
                vertical~ mode }
            }
        }
      }
      { \cs_set_protected:Npn \@@_restore_mc_state: {
          \tag_mc_if_in:TF
              { \@@_debug_typeout:n {\@spaces mc~ restore~ to~ closed} 
                \tag_mc_end:
              }
              { \@@_debug_typeout:n {\@spaces mc~ restore~
                                                       already~closed} 
              }
        }
      }
%    \end{macrocode}
%    To support the special \texttt{?}, \texttt{|}, and \texttt{!}
%    values in any order list we need to announce it to the
%    algorithm. The flag used for this is a token list that has the
%    current module in its name, so we do this here, because there is
%    no point in making the template writer add this.
%    \begin{macrocode}
  \tl_clear_new:c { l _ _ #1_?_tl }
  \tl_clear_new:c { l _ _ #1_|_tl }
  \tl_clear_new:c { l _ _ #1_!_tl }
%    \end{macrocode}
%    Also initialize the boolean that tells us if the last data item
%    had a value (start of the list is considered to be an invisible
%    item with a value).
%    \begin{macrocode}
  \bool_gset_true:N \g_@@_order_item_value_bool
%    \end{macrocode}
%  
%    Loop through the comma list stored in the order key and process
%    it item by item. The order key variable is \cs{l__\#1_\#2_clist}
%    but we write it as
%    \verb*=l _ _ #...= in the code to avoid bogus warnings from
%   \texttt{l3doc} about using private names from other modules. We do
%    the same for other construct variables. Argument \texttt{\#3}
%    holds the list of allowed items to which we add \texttt{?},
%    \texttt{|}, and  \texttt{!}
%    because they should be always allowed.
%    \begin{macrocode}
  \clist_map_inline:cn {l _ _ #1_#2_clist }
        { \clist_if_in:nnTF { ?, | , ! , #3 } { ##1 }
           {
%    \end{macrocode}
%    For each clist item the token list \cs{l__\meta{module}_\meta{item}_tl}
%    must exist! If it does then the clist item is processed with
%    \cs{@@_process_order_key:NNnnn} which receives 2 
%    token lists  (pre-constructed for efficiency) as well as the module
%    name, the clist item name, and the order key name from which it
%    came from.
%    \begin{macrocode}
            \cs_if_exist:cTF { l _ _ #1_##1_tl }
               { \exp_args:Ncc
                 \@@_process_order_key:NNnnn
                   { l _ _ #1_##1_tl }
                   { l _ _ #1_##1_tag_tl }
                   { #1 }
                   { ##1 }
                   { #2 }
               }
%    \end{macrocode}
%    If the token list doesn't exist we raise an error:
%    \begin{macrocode}
               { \msg_error:nnnn { template } { unknown-key-value }
                                { #2 } { ##1 }
               }
           }
%    \end{macrocode}
%    If the item was not in the allowed list (i.e.,
%    \texttt{?,|,!,\#3}) we raise the same error.
%    \begin{macrocode}
           { \msg_error:nnnn { template } { unknown-key-value }
                               { #2 } { ##1 }
           }
        }
%    \end{macrocode}
%    In case the clist ended in separator items we insert those now as that
%    hasn't happened yet.
%    \begin{macrocode}
  \@@_insert_collected_separators:
%    \end{macrocode}
%    
%    Then we restore the MC state that was current at the beginning.  
%    \begin{macrocode}
  \@@_restore_mc_state:
%    \end{macrocode}
%
%    \begin{macrocode}
  \group_end:
%    \end{macrocode}
%
%    \begin{macrocode}
  \checkstatus{End}
%    \end{macrocode}
%
%    Finally we clear all token lists that may have been set up by the
%    template and used the processing. This avoids that we get bogus
%    matches in other templates that also use the item name but
%    without setting up default declarations for customization.
%    \begin{macrocode}
  \clist_map_inline:nn {#3}
    {
%    \end{macrocode}
%    The list may contain group items starting with \texttt{<} and for
%    them we have to get rid of the first character. For group items
%    ending in \texttt{>} nothing needs to be done.
%    \begin{macrocode}
      \tl_if_head_eq_meaning:nNTF {##1} <
        {
          \tl_clear_new:c   { l _ _ #1_\use_none:n ##1_decls_tl }
        }
        {
          \tl_if_in:nnF {##1} >
             {
%    \end{macrocode}
%    We actually clear a bit too much as this also loops through all
%    the separators but it is simply to clear a few additional token
%    lists rather than to figure out if the current \texttt{\#\#1} is
%    a name set up as a separator.\fmi{maybe change that.}
%    \begin{macrocode}
               \tl_clear_new:c { l _ _ #1_##1_decls_tl }
               \tl_clear_new:c { l _ _ #1_##1_tag_tl }
               \cs_set_eq:cN   { l _ _ #1_##1_format:n } \use:n
             }
        }
    }
}
%    \end{macrocode}
%    
%    \begin{macrocode}
\msg_new:nnnn { template } { unknown-key-value }
  { The~ value~ '#2'~ in~ key~ '#1'~ is~ not~ recognized. }
  {
    Perhaps~ a~ misspelling~ or~ the~ current~ template~
    instance~ uses~ special~ values.
  }
%    \end{macrocode}
%  \end{macro}
%    
%    
%    
%  \begin{macro}{\@@_restore_mc_state:}
%    Internal command to keep track of the MC state before and after
%    order key processing.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_restore_mc_state:{}  
%    \end{macrocode}
%  \end{macro}
%    
%    
%    
%    
%  \begin{macro}{\g_@@_order_item_value_bool}
%    We keep track of whether or not the last data item had a value
%    through a global boolean.
%    \begin{macrocode}
\bool_new:N \g_@@_order_item_value_bool
%    \end{macrocode}
%  \end{macro}
%    
%    
%    
%  \begin{macro}{\IfValueLastOrderItemTF,
%    \IfValueLastOrderItemT,\IfValueLastOrderItemF}
%    Conditionals for use in separator values (or even data item
%    values) to do some conditional processing based whether or not
%    the last item had a value.
%    \begin{macrocode}
\cs_new_protected:Npn \IfValueLastOrderItemTF {
  \bool_if:NTF \g_@@_order_item_value_bool
}
\cs_new_protected:Npn \IfValueLastOrderItemT {
  \bool_if:NT \g_@@_order_item_value_bool
}
\cs_new_protected:Npn \IfValueLastOrderItemF {
  \bool_if:NF \g_@@_order_item_value_bool
}
%    \end{macrocode}
%  \end{macro}
%    
%    
%    
%  \begin{macro}{\template_new_order_separator:n}
%    Declare a new separator item that can be used with any order
%    key. They are all mapped to run \cs{@@_process_special_order_separator:nn}.
%    \begin{macrocode}
\cs_new_protected:Npn \template_new_order_separator:n #1 {
  \cs_new_eq:cN { @@_process_special_order_#1:nn }
                \@@_process_special_order_separator:nn
}
%    \end{macrocode}
%  \end{macro}
%    
%    
%    
%  \begin{macro}{\@@_process_special_order_separator:nn}
%    Processing a separator item simply means that we append its
%    content to \cs{g_@@_collected_separators_tl}.
%
%    This implicitly defines the separator called \texttt{separator}.
%    \begin{macrocode}
\cs_new:Npn \@@_process_special_order_separator:nn #1#2 {
    \@@_debug_typeout:n {\@spaces collecting~ separator~ data }
    \tl_gput_right:Ne \g_@@_collected_separators_tl
       { \exp_not:c { l _ _ #1_#2_tl } }
}
%    \end{macrocode}
%  \end{macro}
%    
%    
%     We predefine a number of additional separators.
%    \begin{macrocode}
\template_new_order_separator:n {separator-a}
\template_new_order_separator:n {separator-b}
\template_new_order_separator:n {separator-c}
\template_new_order_separator:n {separator-d}
\template_new_order_separator:n {separator-e}
%    \end{macrocode}
%    
%  \begin{macro}{\g_@@_collected_separators_tl}
%    The global tokenlist in which we collect separator data during
%    the processing.
%    \begin{macrocode}
\tl_new:N \g_@@_collected_separators_tl
%    \end{macrocode}
%  \end{macro}
%    
%    
%    
%  \begin{macro}{\@@_insert_collected_separators:}
%    Inserting collected separators is done by typesetting the content
%    of \cs{g_@@_collected_separators_tl} if it is non-empty.
%    \begin{macrocode}
\cs_new:Npn \@@_insert_collected_separators: {
  \tl_if_empty:NF
      \g_@@_collected_separators_tl
      {
        \@@_debug_typeout:n {\@spaces 
          using~ collected~ separator~ data }
%    \end{macrocode}
%    If we aren't already inside an MC we may have to start one and then typeset
%    what was collected:
        %    \begin{macrocode}
        \@@_open_mc_if_necessary:n { \@spaces opening~ mc~ for~
                                     separator } 
        \g_@@_collected_separators_tl
%    \end{macrocode}
%    If in horizontal mode we also add a fake pdf space to ensure that
%    the separator is seen as a space of some sort in the tagging
%    structure.
%    \begin{macrocode}
        \mode_if_horizontal:T \pdffakespace
%    \end{macrocode}
%    Finally we clear the tokenlist.
%    \begin{macrocode}
        \tl_gclear:N \g_@@_collected_separators_tl
      }
}
%    \end{macrocode}
%  \end{macro}
%    
%    
%    
%  \begin{macro}{\@@_drop_collected_separators:}
%    Dropping collected separators simply means clearing the
%    \cs{g_@@_collected_separators_tl} token list.
%    \begin{macrocode}
\cs_new:Npn \@@_drop_collected_separators: {
  \tl_if_empty:NF \g_@@_collected_separators_tl
     {
       \@@_debug_typeout:n {\@spaces
                            dropping~ collected~ separators }
       \tl_gclear:N \g_@@_collected_separators_tl
     }
}
%    \end{macrocode}
%  \end{macro}
%    
%    
%    
%  \begin{macro}{\@@_open_mc_if_necessary:n}
%    Open an MC if none is open and it isn't automatically done when
%    switching to hmode. The argument is a debugging/info message.
%    \begin{macrocode}
\cs_new:Npn \@@_open_mc_if_necessary:n #1 {
%    \end{macrocode}
%    If \cs{l__tag_para_bool} is false we have to always open an MC if
%    none is open.
%    However, if this is true, i.e., the MC is
%    handled by the paragraph builder we only have to do it if we are
%    already in horizontal mode but no MC is open for some reason.
%    \begin{macrocode}
  \tag_mc_if_in:TF
    { \@@_debug_typeout:n {\@spaces mc~ already~ open} }
    { \bool_if:NTF \l__tag_para_bool
        { \mode_if_horizontal:T
            {
              \tag_mc_begin:n {}
              \@@_debug_typeout:n { #1 }
            }
        }
        { \tag_mc_begin:n {}
          \@@_debug_typeout:n { #1 }
        }
    }
}
%    \end{macrocode}
%  \end{macro}
%    
%  \begin{macro}{\@@_process_order_key:NNnnn}
%    The heart of the processing: dealing with one item. Arguments are
%    \begin{itemize}
%    \item Token list variable holding the item data (or \cs{NoValue})
%    \item Token list variable holding the item tag name (or empty or \cs{relax})
%    \item Current module name
%    \item Current item to be processed
%    \item Name of the order key being processed
%    \end{itemize}
%    \begin{macrocode}
\cs_new_protected:Npn \@@_process_order_key:NNnnn #1#2#3#4#5 {
  \@@_debug_typeout:n { Processing~ key~ '#4'~ in~ '#5' }
%    \end{macrocode}
%    There are two types of items, either normal ones or special ones
%    (separators or group items). The latter can be identified by
%    checking if the command \cs{@@_process_special_order_
%    \meta{item}:nn} exists.\footnote{This means that you can't have
%    an item being a normal one in one template but a special one in
%    another, but --- tough.}
%    \begin{macrocode}
  \cs_if_exist:cTF { @@_process_special_order_ #4 :nn }
%    \end{macrocode}
%    If we have a special item we call its processing function and
%    pass it the current module and the current item name, i.e.,
%    \texttt{\#3} and \texttt{\#4}.
%    \begin{macrocode}
     { \@@_debug_typeout:n{\@spaces special~group~or~separator~item}
       \use:c  { @@_process_special_order_ #4 :nn } {#3}{#4}
     }
%    \end{macrocode}
%    If we have a normal item then its value may be \cs{NoValue} in
%    which case we ignore it and also drop any collected separators.
%    \begin{macrocode}
     { \tl_if_novalue:oTF #1
          { \@@_debug_typeout:n {\@spaces \exp_not:N \NoValue  }
            \@@_drop_collected_separators:
%    \end{macrocode}
%    Current item has no value so update the boolean tracking that.
%    \begin{macrocode}
            \bool_gset_false:N \g_@@_order_item_value_bool
          }
%    \end{macrocode}
%    If the item has a real value (including an empty one) we insert all
%    collected separators and then typeset the item in a group to keep
%    formatting changes local.
%    \begin{macrocode}
          { \@@_insert_collected_separators:
            \group_begin:
%    \end{macrocode}
%    The token list variable for the tag name in \verb=#2= may not
%    exist, in which case it was set to \cs{scan_stop:}
%    (aka.\ \cs{relax}) by \TeX{} in
%    the \cs{cs:w} operation generating the argument. We therefore
%    make a quick test and declare it as a token list variable, if
%    necessary. 
%    \begin{macrocode}
            \cs_if_eq:NNT #2 \scan_stop:
              { \tl_new:N #2 }
%    \end{macrocode}
%    We can now be sure that the tag name variable is either empty (no
%    tag) or contains a tag name. If it is empty all we have to do is
%    to ensure that we have an open MC when typesetting starts.
%    \begin{macrocode}
            \tl_if_empty:NTF #2
              { \@@_open_mc_if_necessary:n { \@spaces opening~ mc~
                                             for~ '#4'} } 
%    \end{macrocode}
%    Otherwise, we have to build a structure around the item
%    data. Thus, we first have to close an open MC (if one is open).
%    \begin{macrocode}
              { \tag_mc_if_in:T
                { \@@_debug_typeout:n { \@spaces closing~ mc~ before~
                                        struct~ '#2' }
                  \tag_mc_end:
                }
                \tag_struct_begin:n { tag=#2 }
                \tag_mc_begin:n {}
                \@@_debug_typeout:n { \@spaces opening~ mc~ inside~
                                      struct~ '#2'  }
              }
%    \end{macrocode}
%    The token list with declarations may not exist and the same might
%    be true for the formatting command for the current item. If
%    that's the case we declare them \ldots
%    \begin{macrocode}
            \tl_if_exist:cF { l _ _ #3_#4_decls_tl }
               { \@@_debug_typeout:n { \@spaces #4-decls~ not~ defined~
                                       by~ the~ template } 
                 \tl_new:c { l _ _ #3_#4_decls_tl }
               }
            \cs_if_exist:cF { _ _ #3_#4_format:n }
               { \@@_debug_typeout:n { \@spaces #4-format~ not~
                                       defined~ by~ the~ template } 
                 \cs_new_eq:cN  { _ _ #3_#4_format:n } \use:n
               }
%    \end{macrocode}
%    \ldots\ and then typeset the item data stored in \texttt{\#1}:
%    \begin{macrocode}
            \use:c { l _ _ #3_#4_decls_tl }
            \@@_debug_typeout:n {\@spaces typeset~ '#4'~ data } 
            \use:c {  _ _ #3_#4_format:n } { #1 }
%    \end{macrocode}
%    Finally, we have to close the structure if we opened one earlier.
%    \begin{macrocode}
            \tl_if_empty:NF #2
                { \tag_mc_end: \tag_struct_end:
                  \@@_debug_typeout:n { \@spaces reopening~ mc~ after~
                                        struct~ '#2' } 
                  \tag_mc_begin:n {}
                }
            \group_end:
%    \end{macrocode}
%    Current item had a value so update the boolean tracking that.
%    \begin{macrocode}
            \bool_gset_true:N \g_@@_order_item_value_bool
%    \end{macrocode}
%    
%    \begin{macrocode}
\checkstatus{After~ #4}
          }
     }
}
%    \end{macrocode}
%  \end{macro}
%    
%    
%    
%    
%  \begin{macro}{\@@_process_special_order_?:nn}
%    We need this internal command to tell the algorithm that
%    \texttt{?} is a special item in the order list.
%
%    It checks if collected separators should be dropped and if so
%    does that.
%    \begin{macrocode}
\cs_set:cpn { @@_process_special_order_?:nn } #1#2 {
  \bool_if:NF \g_@@_order_item_value_bool
    { \@@_drop_collected_separators: }
}
%    \end{macrocode}
%  \end{macro}
%    
%    
%  \begin{macro}{\@@_process_special_order_|:nn}
%    The special item \texttt{|} similar but immediately typesets the
%    collected separators if the previous data item had a
%    value.
%    \begin{macrocode}
\cs_set:cpn { @@_process_special_order_|:nn } #1#2 {
  \bool_if:NTF \g_@@_order_item_value_bool
    { \@@_insert_collected_separators: }
    { \@@_drop_collected_separators:   }
}
%    \end{macrocode}
%  \end{macro}
%    
%    
%  \begin{macro}{\@@_process_special_order_!:nn}
%    Thee special item \texttt{!} unconditionally typesets the separators.
%    \begin{macrocode}
\cs_set:cpn { @@_process_special_order_!:nn } #1#2 {
  \@@_insert_collected_separators:
}
%    \end{macrocode}
%  \end{macro}
%    
%    
%    
%    
%    
%  \begin{macro}{\template_new_order_group:nnnnnn}
%    Declare a pair of group items \texttt{<\meta{\#2}} and
%    \texttt{\meta{\#2}>}.
%
%    For this, we first define \cs{@@_process_special_order_<\#2:nn}:
%    \begin{macrocode}
\cs_new_protected:Npn \template_new_order_group:nnnnnn #1#2#3#4#5#6 {
  \cs_set:cpn { @@_process_special_order_<#2:nn } ##1##2 {
%    \end{macrocode}
%    Start by inserting any collected separators up to this point.
%    \begin{macrocode}
    \@@_insert_collected_separators:
%    \end{macrocode}
%    Then start a group and process the declaration for the group.
%    \begin{macrocode}
    \group_begin:
      \tl_use:c { l _ _ #1_#2_decls_tl}
%    \end{macrocode}
%    Then run the normal and the tagging sockets for \texttt{\#1/\#2/begin}.
%    \begin{macrocode}
      \UseSocket{X-#1/#2/begin}
      \@@_debug_typeout:n {\@spaces use~tagging~socket~#1/#2/begin }
      \UseTaggingSocket{X-#1/#2/begin}                 % X- for now because of
                                                       % existing
                                                       % sockets from
                                                       % old implementation -
                                                       % needs cleanup
  }
%    \end{macrocode}
%    
%    When we reach the end group item we run this command:
%    \begin{macrocode}
  \cs_set:cpn { @@_process_special_order_#2>:nn } ##1##2 {
%    \end{macrocode}
%    Again, first typeset any collected separators, then the sockets
%    and finally closing the group:
%    \begin{macrocode}
      \@@_insert_collected_separators:
      \UseSocket{X-#1/#2/end}
      \@@_debug_typeout:n {\@spaces use~tagging~socket~#1/#2/end }
      \UseTaggingSocket{X-#1/#2/end}
    \group_end:
    \checkstatus{#2~end}
  }
%    \end{macrocode}
%    Here are the socket declarations:
%    \begin{macrocode}
  \NewSocket{X-#1/#2/begin}{0}
  \NewSocket{X-#1/#2/end}{0}
  \NewTaggingSocket{X-#1/#2/begin}{0}
  \NewTaggingSocket{X-#1/#2/end}{0}
%    \end{macrocode}
%    And these are the default plug settings:
%    \begin{macrocode}
  \NewSocketPlug{X-#1/#2/begin}{default}{#3}
  \NewTaggingSocketPlug{X-#1/#2/begin}{default}{#4}
  \NewSocketPlug{X-#1/#2/end}{default}{#5}
  \NewTaggingSocketPlug{X-#1/#2/end}{default}{#6}
%    \end{macrocode}
%
%    \begin{macrocode}
  \AssignSocketPlug{X-#1/#2/begin}{default}
  \AssignTaggingSocketPlug{X-#1/#2/begin}{default}
  \AssignSocketPlug{X-#1/#2/end}{default}
  \AssignTaggingSocketPlug{X-#1/#2/end}{default}
%    \end{macrocode}
%    And here is the token list for the declarations.
%    \begin{macrocode}
  \tl_new:c { l _ _ #1_#2_decls_tl }
%    \end{macrocode}
%    We also need the following two token lists to be defined to keep
%    the algorithm happy: they serve as a flag that these items are
%    allowed in the order key value.
%    \begin{macrocode}
  \tl_new:c { l _ _ #1_<#2_tl }
  \tl_new:c { l _ _ #1_#2>_tl }
}
%    \end{macrocode}
%  \end{macro}
%    \begin{macrocode}
%    \end{macrocode}
%    
%    
%
%
%    
%
% \section{Other code updates/extensions}
%    
% \subsection{Augmented \cs{SetKnownTemplateKeys}}
%
%
%  \begin{macro}{\SetKnownTemplateKeys}
%    A key/val list passed to  \cs{SetKnownTemplateKeys} can either be
%    empty (in which we do not want to start up the parsing machinery)
%    or it could be \cs{NoValue} in which we do not want to do that
%    either. The latter can happen, for example, with \env{verbatim}
%    where we define the optional argument with
%    \verb/={late-legacy-code} !o/ so that people can write
%    \verb/\begin{verbatim}[\small]/ a syntax promoted by the TUGboat
%    class.
%    \begin{macrocode}
\cs_set_protected:Npn \SetKnownTemplateKeys #1#2#3
  {
%    \end{macrocode}
%    An \enquote{empty} argument (or rather one that is empty after one
%    expansion) is the most likely case so we test for this first.
%    \begin{macrocode}
    \tl_if_empty:oTF {#3}
      {
        \tl_set_eq:NN  \UnusedTemplateKeys \c_empty_tl
      }
      {
        \tl_if_novalue:nTF {#3}
          {
            \tl_set_eq:NN  \UnusedTemplateKeys \c_empty_tl
          }
          {
            \keys_set_known:noN { template / #1 / #2 } {#3}
                                \UnusedTemplateKeys
          }
      }
  }
%    \end{macrocode}
%  \end{macro}
%
%
%
%  \begin{macro}{\SetTemplateKeys}
%    Same kind of extension for \cs{SetTemplateKeys}:
%    \begin{macrocode}
\cs_set_protected:Npn \SetTemplateKeys #1#2#3 {
    \SetKnownTemplateKeys {#1}{#2}{#3}
%FMi    
    \tl_if_empty:NF \UnusedTemplateKeys
       {
         \msg_error:nneo { block } { unknown-keys }
             { current~ template~ instance }  % we don't know which
             \UnusedTemplateKeys
       }
    \tl_set_eq:NN  \UnusedTemplateKeys \c_empty_tl
}
%    \end{macrocode}
%  \end{macro}
%
% \subsection{Tracing templates and instances}
%
%  \begin{macro}{\template_debug_typeout:n}
%    I guess that tracing macro is needed in several modules, so
%    should become public (or at least kernel).
%    \begin{macrocode}
\cs_new_protected:Npn \template_debug_typeout:n { \__template_debug_typeout:n }
%    \end{macrocode}
%  \end{macro}
%
%
%
%
%  \begin{macro}{\IfTemplateExistsTF,\IfTemplateExistsT,\IfTemplateExistsF,
%                \__template_if_exist:nn}
%    Test if a certain template was defined (so that it can be used in
%    instance declarations.
%    \begin{macrocode}
\prg_new_conditional:Npnn \__template_if_exist:nn #1#2 { T, F, TF }
  {
    \cs_if_exist:cTF { \c__template__keytypes_root_tl #1 / #2 }
      \prg_return_true:
      \prg_return_false:
  }
\cs_new:Npn \IfTemplateExistsTF #1#2
  { \__template_if_template_exist:nnTF {#1} {#2} }
\cs_new:Npn \IfTemplateExistsT #1#2
  { \__template_if_template_exist:nnT {#1} {#2} }
\cs_new:Npn \IfTemplateExistsF #1#2
  { \__template_if_template_exist:nnF {#1} {#2} }
%    \end{macrocode}
%    
%    \begin{macrocode}
%    \end{macrocode}
%  \end{macro}
%
%
%
%
%
%    \begin{macrocode}
\ExplSyntaxOff
%    \end{macrocode}
%
%    \begin{macrocode}
%</package>
%    \end{macrocode}
%
% \end{implementation}
%
% \Finale
%
\endinput

