% \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-08-01}
\def\ltlabtemplateversion{0.6a}
%<*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>}}
%
%
% \title{Extending the \LaTeX{} templating mechanism}
% \author{\LaTeX{} Project\thanks{Initial implementation by Frank Mittelbach.}}
% \date{v\ltlabtemplateversion\ \ltlabtemplatedate}
%
% \maketitle
%
%
% \begin{abstract}
%    Explain the concepts and requirements for \enquote{order} keys in templates.
% \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-1,
%                                  number, separator-2, 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-1}, \texttt{number},
%    \texttt{punct}, \texttt{separator-2}, 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-1 : tokenlist = \enspace ,
%    ...
%\end{verbatim}
%    and
%\begin{verbatim}
%    title       = \l_@@_title_tl ,
%    separator-1 = name {l_@@_separator-1_tl} ,
%    ...
%\end{verbatim}
%    Again, we had to make use of the \texttt{name} keyword because
%    the key \key{separator-1} 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 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 \texttt{note} 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 typsetting.
%
%    \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}
%
%    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 one item such as a \key{note} is not present, then a
%    separator before it should be dropped, e.g., one should not 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.
%
%    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 the typical setup is
%\begin{verbatim}
%    separator-1 : tokenlist = \ ,
%    separator-2 : tokenlist = \ ,
%    ...
%\end{verbatim}
%
%\begin{verbatim}
%    separator-1 = name {l_@@_separator-1_tl} ,
%    separator-2 = name {l_@@_separator-2_tl} ,
%    ...
%\end{verbatim}
%    up to \key{separator-5} 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.
%
%    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't use the standard separators. In that case use a
%    normal item and give it the value that you want for the
%    separation, e.g., a newline plus some vertical spacing.
%
%
% \subsection{Grouping keys 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. 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-1, number, label>, ... }
%\end{verbatim}
%    would group \texttt{prefix}, \texttt{separator-1}, 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 and 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.
%
%    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.
%   \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.  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 globablly 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}
%
% \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 {
  \typeout{-------------------- #1 ----------------}
  \mode_if_horizontal:TF
       { \typeout{==>~hmode} }
       { \typeout{==>~vmode} }
       \typeout{==>~para-tagging:~ 
                \bool_if:NTF \l__tag_para_bool {on}{off}
  }
  \tag_mc_if_in:TF
      { \typeout{\@spaces mc~ status:~ open} }
      { \typeout{\@spaces mc~ status:~ closed} }
  \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}
%    Setting up the command to restore the MC state after
%    processing. This can be shortened a lot if the debugging code gets
%    removed. 
%    \begin{macrocode}
  \tag_mc_if_in:TF
      { \cs_set_protected:Npn \@@_restore_mc_state: {
          \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{}
              }
        }
      }
      { \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}
%    Save the list of allowed items for checking later.
%    \begin{macrocode}
  \clist_set:Nn \l_@@_allowed_items_clist { #3 }
%    \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. 
%    \begin{macrocode}
  \clist_map_inline:cn {l _ _ #1_#2_clist }
        { \clist_if_in:NnTF \l_@@_allowed_items_clist { ##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 or the item is not in the
%    \cs{l_@@_allowed_items_clist} 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 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}
%    
%    \begin{macrocode}
  \checkstatus{End}
%    \end{macrocode}
%    Then we restore the MC state that was current at the beginning.  
%    \begin{macrocode}
  \@@_restore_mc_state:
%    \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 \l_@@_allowed_items_clist
    {
%    \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:c   { l _ _ #1_\use_none:n ##1_decls_tl }
        }
        {
          \tl_if_in:nnF {##1} >
             {
               \tl_clear:c   { l _ _ #1_##1_decls_tl }
               \tl_clear: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}{\l_@@_allowed_items_clist}
%    Internal variable to hold the allow items.
%    \begin{macrocode}
\clist_new:N \l_@@_allowed_items_clist
%    \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-1}
\template_new_order_separator:n {separator-2}
\template_new_order_separator:n {separator-3}
\template_new_order_separator:n {separator-4}
\template_new_order_separator:n {separator-5}
%    \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}{\@@_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
              \tl_if_empty:NF
                  \g__template_collected_separators_tl
                  { -~ dropping~ collected~ separators }
            }
            \tl_gclear:N \g__template_collected_separators_tl
          }
%    \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}
          {
            %  \leavevmode % <-- no longer needed?
            \@@_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:
\checkstatus{After~ #4}
          }
     }
}
%    \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{label~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:
%    \begin{macrocode}
  \tl_new:c { l _ _ #1_<#2_tl }
  \tl_new:c { l _ _ #1_#2>_tl }
}
%    \end{macrocode}
%  \end{macro}
%    \begin{macrocode}
%    \end{macrocode}
%    
%    
%
%
%    \begin{macrocode}
\ExplSyntaxOff
%    \end{macrocode}
%
%    \begin{macrocode}
%</package>
%    \end{macrocode}
%
% \end{implementation}
%
% \Finale
%
\endinput

