% \iffalse meta-comment
%
%% File: latex-lab-context.dtx (C) Copyright 2025 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\ltlabcontextdate{2026-01-16}
\def\ltlabcontextversion{0.5b}
%<*driver>
\DocumentMetadata{tagging=on,pdfstandard=ua-2,lang=en}
\documentclass{l3in2edoc}

\EnableCrossrefs
\CodelineIndex
\begin{document}
  \DocInput{latex-lab-context.dtx}
\end{document}
%</driver>
%
% \fi
%
% \title{The \textsf{latex-lab-context} package\\
%    Providing context for template instances and code that needs
%    to know where and when it is executed}
%
% \author{\LaTeX{} Project\thanks{Initial implementation done by Frank Mittelbach}}
% \date{v\ltlabcontextversion\ \ltlabcontextdate}
%
% \maketitle
%
% \newcommand{\xt}[1]{\textsl{\textsf{#1}}}
% \newcommand{\TODO}[1]{\textbf{[TODO:} #1\textbf{]}}
%
% \providecommand\hook[1]{\texttt{#1}}
%
% \begin{abstract}
% \end{abstract}
%
% \section{Introduction}
%
%    In this module we implement the concept of \enquote{contexts}
%    within the document and depending on the current context
%    formatting behavior might change. The main application for this
%    is in instances of templates (where things can be easily automated
%    to react to context), but it is probably also applicable to other
%    situations (but these might need more thought).
%
% \subsection{Definition of a  \enquote{context}}
%
%   The \enquote{context} is an attribute of every point of the
%   formatted document, i.e., at each point during the formatting one
%   can determine in which \enquote{context} the formatting happens
%   and based on this adjust the formatting method.
%   
%   The \enquote{context} is not an entirely flat structure: we
%   distinguish between the \enquote{primary context} and the
%   \enquote{secondary context} both of which can be changed
%   individually based on a number of rules as discussed below.
%   
%   Any context is denoted by a name (\verb=[a-z]*= letters only). The
%   empty name is allowed to ease specification of the common case
%   (i.e., the default \enquote{primary context} is the main galley
%   and by default no \enquote{secondary context} is specified).
%   
% \subsection{The \enquote{primary context}}
%   
%   The \enquote{primary context} is described with a fixed (but
%   extensible?) set of names:
%   \begin{itemize}
%
%   \item \meta{empty} denotes that we are in \enquote{galley} context
%      producing text for the page;
%
%   \item \texttt{caption}
%      denotes that we are typesetting the caption text of a \cs{caption} command
%      --- this is also used for captions outside of floats,
%
%   \item \texttt{footnote}
%      denotes that we are typesetting the footnote text;
%
%   \item \texttt{float}
%      denotes that we are typesetting a float;
%
%   \item \texttt{marginal}
%      denotes that we are typesetting a marginal;
%
%   \item \texttt{header}
%      denotes that we are typesetting the running header;
%
%   \item \texttt{footer}
%      denotes that we are typesetting the running footer.
%
%   \end{itemize}
%   
%   When the \enquote{primary context} is set it replaces the current
%   \enquote{primary context} and resets the \enquote{secondary
%   context} to \meta{empty}.  The setting is local, i.e., it obeys
%   grouping.
%   
%   It would be possible to be more granular, i.e., differentiate
%   between types of float etc. But for now I suggest to start out
%   with this small set.
%
%   We may want to require that a context name is declared before its
%   first use, e.g., via \cs{DeclarePrimaryContext} (right now this is
%   not necessary.
%   
%   
% \subsection{The \enquote{secondary context}}
%   
%   The \enquote{secondary context} concerns itself (for now) only
%   with font size changes, because that is most commonly a cause for
%   layout changes.  It is described through a fixed (but extensible?)
%   set of names:
%   
%   \begin{itemize}
%   \item
%      \meta{empty} denotes that there is no special secondary
%      context, i.e., that we are producing material in \cs{normalsize};
%
%   \item \texttt{tiny}
%      denotes that we are typesetting in \cs{tiny} font size;
%   
%   \item and similarly for \texttt{scriptsize},
%     \texttt{footnotesize}, \texttt{small}, \texttt{large},
%     \texttt{Large}, \texttt{LARGE}, \texttt{huge}, and \texttt{Huge}.  
%   \end{itemize}
%   The above list of secondary contexts are automatically set by the
%   standard \LaTeX{} font size commands (as part of \cs{@setfontsize}). Classes
%   that use additional font size commands but do not use the
%   \LaTeXe{} command for this need to explicitly set the secondary
%   context with \cs{SetSecondaryContext} if they want their size be
%   recognized as a context.
%   
%
% 
% \section{Setting context}
%
% \begin{function}{\SetPrimaryContext}
%   \begin{syntax}
%     \cs{SetPrimaryContext} \Arg{new context}
%   \end{syntax}
%   The \meta{new context} should be a name consisting only of
%   lowercase letters a--z (and to make sense only a name that is
%   actually used---typos will go undetected).
%   
%   This declaration checks if there is a rule for the combination of
%   the current context and the requested \meta{new context} (see
%   \cs{DeclarePrimaryContextRule}) and if so applies it to determine
%   to which context the \enquote{primary context} should be set. 
%   If there is no such rule then \meta{new context} will be used
%   unconditionally.
%
%   As a second action the command executes
%   \cs{SetSecondaryContext}\texttt{\{\}}, i.e., it clears the
%   \enquote{secondary context}.
%
%   The effects are local, i.e., both context changes revert to the
%   previous value at the end of the current group.
% \end{function}
%
%
%
% \begin{function}{\DeclarePrimaryContextRule}
%   \begin{syntax}
%     \cs{DeclarePrimaryContextRule} \Arg{current}\Arg{new}\Arg{result}
%   \end{syntax}
%   This declaration defines the rule that when the current primary
%   context is \meta{current} and \meta{new} is requested as the new
%   context then instead \meta{result} is made the new
%   \enquote{primary context}.
%
%   If \texttt{*} is used in the first argument then this indicates
%   any current context and thus \meta{new} is always replaced by
%   \meta{result}. This can be more concisely written as
%   \begin{quote}
%     \cs{DeclarePrimaryContextRule*} \Arg{new}\Arg{result}
%   \end{quote}
%   if preferred.
%
%   Declaring such rules is a global operation.
% \end{function}
%
%
%
% \begin{function}{\SetSecondaryContext}
%   \begin{syntax}
%     \cs{SetSecondaryContext} \Arg{new context}
%   \end{syntax}
%   The \meta{new context} should be a name consisting only of
%   lowercase letters a--z (and to make sense only a name that is
%   actually used---typos will go undetected).
%   
%   This declaration checks if there is a rule for the combination of
%   the current secondary context and the requested \meta{new context}
%   (see \cs{DeclareSecondaryContextRule}) and if so applies it to
%   determine to which context the \enquote{secondary context} should
%   be set. If there is no such rule then \meta{new context} will
%   be used unconditionally.
%
%   The effect is local, i.e., the context change reverts to the
%   previous value at the end of the current group.
% \end{function}
%
%
%
% \begin{function}{\DeclareSecondaryContextRule}
%   \begin{syntax}
%     \cs{DeclareSecondaryContextRule} \Arg{current}\Arg{new}\Arg{result}
%   \end{syntax}
%   This declaration defines the rule that when the current secondary
%   context is \meta{current} and \meta{new} is requested as the new
%   context then instead \meta{result} is made the new
%   \enquote{secondary context}.
%
%   If \texttt{*} is used in the first argument then this indicates
%   any current context and thus \meta{new} is always replaced by
%   \meta{result}. This can be more concisely written as
%   \begin{quote}
%     \cs{DeclareSecondaryContextRule*} \Arg{new}\Arg{result}
%   \end{quote}
%   if preferred.
%
%   Declaring such rules is a global operation.
% \end{function}
%
%
%
% \section{Context usage in template instances}
%
%   If a template instance is used via
%   \cs{UseInstance}\Arg{type}\Arg{inst-name} then this normally
%   results in calling up an instance of  type \meta{type} with the name
%   \meta{inst-name}.\footnote{Such instances are defined with
%   \cs{DeclareInstance} or \cs{DeclareInstanceCopy}, see the
%   documentation in
%   \texttt{lttemplates-doc.pdf}.}
%
%   However, when the \enquote{primary context} and/or the \enquote{secondary
%   context} is non-empty then \cs{UseInstance} searches for an
%   instance that is especially tailored to the current context.
%   This works as follows:
%   \begin{itemize}
%   \item The string\texttt{:}\meta{primary
%   context}\texttt{:}\meta{secondary context} is appended to
%   \meta{inst-name} and if that instance exist it is
%   used.\footnote{Note that this means that
%   if the \meta{primary context} is empty we effectively append
%   \texttt{::}\meta{secondary context}.}
%   \item
%     If not then \meta{inst-name}\texttt{:}\meta{primary context} is
%   tried next.
%   \item
%     If that doesn't exist either then \meta{inst-name} is used as usual.
%   \end{itemize}
% 
%   This means it becomes trivial to alter the behavior of
%   instances if they appear in a special typesetting context. For
%   example, in \LaTeXe{} display blocks, e.g., lists, center, etc., all
%   changed their vertical spacing setup if the surrounding text was
%   in \cs{small} or in \cs{footnotesize} (but did nothing if you
%   typeset in, say, \cs{Large} which had the strange effect that
%   lists in \cs{Large} or \cs{huge} got whatever was set by a size
%   command that changed list parameters).
%
%   With the new context model all you have to do is to provide
%   additional instances, e.g., if \texttt{itemize-1} is the instance
%   name for itemized lists on the first level then
%   \texttt{itemize-1:footnote} would be the instance to be used if an
%   itemize environment is used  within a footnote.
%
%   In addition (or alternatively) you could setup
%   \texttt{itemize-1::Large} which would be selected if the
%   itemize is in the main galley (empty primary context) and the
%   fontsize at the outside is \cs{Large}.
% 
% 
% \section{Notes}
%
%   With special classes, e.g., \texttt{ltx-talk}, additional primaries
%   could be added (and secondaries could be using the modes rather
%   than or in addition to the fontsizes). Or the modes could be part
%   of the primary names \dots. Could do with some experimentation
%   what works best.
%   
%   If the design of a class requires identical behavior in different
%   contexts, e.g., the same behavior in \texttt{header} and
%   \texttt{footer}, it is possible to simplify the setup by only
%   specifying the design for the \texttt{header} context and then
%   declaring:
%\begin{verbatim}
%   \DeclarePrimaryContextRule{*}{footer}{header}
%\end{verbatim}
%
%   One can also add new primary or secondary contexts simply by making
%   use of \cs{Set...Context} declarations with a new name and then
%   use these named contexts when setting up special instance
%   versions.
%
%   What is currently not so easy is to get rid of context names that
%   have been set up, e.g., to use your own \texttt{wipple} and
%   \texttt{wopple} as secondary contexts and make sure that fontsize
%   commands to not overwrite the context. Right now that would
%   require a lot of rules like
%\begin{verbatim}
%   \DeclareSecondaryContextRule{wipple}{tiny}{wipple}
%   \DeclareSecondaryContextRule{wipple}{footnotesize}{wipple}
%   \DeclareSecondaryContextRule{wipple}{scriptsize}{wipple}
%   ...
%\end{verbatim}
%   so perhaps this interface needs changes or some augmentation, if
%   such thing turn out to be useful, e.g., supporting
%   \verb=\DeclareSecondaryContextRule{*}{tiny}{*}= to indicate this.
%
%   Another possibility is to support several independent dimensions
%   as secondary contexts (then \enquote{fontsize} could be one and
%   the \enquote{wipple-wopple} one the other. which of these are used
%   when instances are selected could then (perhaps) be a function of
%   the template type but for a heading type looking at
%   front/main/back matter would be more appropriate.\footnote{Then, of
%   course, a primary context change would not reset any secondary
%   context.}
%
%   Bottom line, what is here is nothing more than a first prototype
%   and likely to change to some extent.
%
% \section{Currently mainly internal interfaces}
%
% \begin{variable}{\l_context_primary_str}
%   This variable holds the current primary context name (or is empty
%   if we are in the context of the main galley).
% \end{variable}
%
% \begin{variable}{\l_context_secondary_str}
%   This variable holds the current secondary context name (or is
%   empty if we are typesetting in \cs{normalsize}). It is by default
%   automatically set by all fontsize commands in core \LaTeX{}. If
%   additional secondary contexts are used then the variable may not
%   be empty even if we are typesetting in \cs{normalsize}
% \end{variable}

% \section{Debugging}
% 
% \begin{function}{\DebugContextsOn,\DebugContextsOff, \context_debug_on:, \context_debug_off:}
% 
%   These commands enable/disable debugging messages for context related
%   processing.
% 
% \end{function}
%
% \begin{function}{\DebugTemplatesOn,\DebugTemplatesOff, \template_debug_on:, \template_debug_off:}
% 
%   These commands enable/disable debugging messages for template related
%   processing. (Belongs into \file{lttemplates.dtx} one day.)
% 
% \end{function}
%
%
% \section{Changes to internals of \LaTeX}
%
% \begin{function}{\@setfontsize}
%   This command has be augmented to execute \cs{SetSecondaryContext}
%   with the name of the current fontsize command as the context argument.
% \end{function}
%
% \begin{function}{\@float}
%   This command has been augmented to execute \cs{SetPrimaryContext}\texttt{\{float\}}.
%   This results in the body of all real floats being typeset in the
%   primary \texttt{float} context. Not covered are packages or
%   methods that make floats not using \cs{@float} or making pseudo
%   floats, e.g., something not floating but having a caption.
% \end{function}
%
%
%
%
%
% \section{Implementation}
%    \begin{macrocode}
%<*package>
%<@@=tag>
%    \end{macrocode}
%    \begin{macrocode}
\ProvidesExplPackage {latex-lab-testphase-context}
                     {\ltlabcontextdate}
                     {\ltlabcontextversion}
  {Providing context for instance, etc.}
%    \end{macrocode}
%
%    \begin{macrocode}
%<*package>
%<@@=context>
%    \end{macrocode}
%
%    \begin{macrocode}
\RequirePackage{latex-lab-testphase-block}  
%    \end{macrocode}
%    
%    
%    
%    
%    
% \subsubsection{Debugging}
%
%    
%  \begin{variable}{\g_@@_debug_bool}
%    
%    \begin{macrocode}
\bool_new:N \g_@@_debug_bool
%    \end{macrocode}
%  \end{variable}
%
%
%  \begin{macro}{\@@_debug:n,\@@_debug_typeout:n}
%    
%    \begin{macrocode}
\cs_new_eq:NN \@@_debug:n \use_none:n
\cs_new_eq:NN \@@_debug_typeout:n \use_none:n
%    \end{macrocode}
%  \end{macro}
%
%  \begin{macro}{\context_debug_on:,\context_debug_off:,
%                \@@_debug_gset:}
%    \begin{macrocode}
\cs_new_protected:Npn \context_debug_on:
  {
    \bool_gset_true:N \g_@@_debug_bool
    \@@_debug_gset:
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new_protected:Npn \context_debug_off:
  {
    \bool_gset_false:N \g_@@_debug_bool
    \@@_debug_gset:
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new_protected:Npn \@@_debug_gset:
  {
    \cs_gset_protected:Npx \@@_debug:n ##1
      { \bool_if:NT \g_@@_debug_bool {##1} }
    \cs_gset_protected:Npx \@@_debug_typeout:n ##1
      { \bool_if:NT \g_@@_debug_bool { \typeout{[Context]~ ==>~ ##1} } }
  }
%    \end{macrocode}
%  \end{macro}
%
%
%  \begin{macro}{\DebugContextsOn,\DebugContextsOff}
%    
%    \begin{macrocode}
\cs_new_protected:Npn \DebugContextsOn  { \context_debug_on:  }
\cs_new_protected:Npn \DebugContextsOff { \context_debug_off: }
%    \end{macrocode}
%    
%    \begin{macrocode}
\DebugContextsOff
%    \end{macrocode}
%  \end{macro}
%
%
%
%
%  \begin{macro}{\l_context_primary_str}
%    Variable to hold the name of the current primary context.
%    \begin{macrocode}
\str_new:N \l_context_primary_str
%    \end{macrocode}
%  \end{macro}
%
%
%
%
%  \begin{macro}{\SetPrimaryContext}
%    Change the context: if the target context is empty, just do
%   it. Otherwise if we have a rule for the current context and new context
%   use that; otherwise if there is a star rule apply that; otherwise
%   set the new value as requested,
%    \begin{macrocode}
\cs_new_protected:Npn \SetPrimaryContext #1 {
  \str_set:Ne \l_context_primary_str
     { \tl_if_empty:nF { #1 }
       { \cs_if_exist_use:cF
         { g_@@_primary_ \l_context_primary_str _ #1 _tl }
         { \cs_if_exist_use:cF
           { g_@@_primary_ * _ #1 _tl }
           { #1 }
         }
       }
     }
  \@@_debug_typeout:n{set~primary~ <-~ \l_context_primary_str }   
%    \end{macrocode}
%    Also reset the secondary context.
%    \begin{macrocode}
  \SetSecondaryContext {}
}
%    \end{macrocode}
%  \end{macro}
%
%
%  \begin{macro}{\DeclarePrimaryContextRule}
%    Rules are simply stored in macro names:
%    \begin{macrocode}
\cs_new_protected:Npn \DeclarePrimaryContextRule #1#2#3 {
  \tl_gclear_new:c { g_@@_primary_ #1 _ #2 _tl }
  \tl_gset:cn      { g_@@_primary_ #1 _ #2 _tl } {#3}
}
%    \end{macrocode}
%  \end{macro}
%
%
%  \begin{macro}{\l_context_secondary_str}
%    Variable to hold the name of the current secondary context.
%    \TODO{perhaps to be replaced by a multi-dimensional solution}
%    \begin{macrocode}
\str_new:N \l_context_secondary_str
%    \end{macrocode}
%  \end{macro}
%
%
%  \begin{macro}{\SetSecondaryContext}
%    Similar to \cs{SetPrimaryContext}.
%    \begin{macrocode}
\cs_new_protected:Npn \SetSecondaryContext #1 {
  \str_set:Ne \l_context_secondary_str
     { \tl_if_empty:nF { #1 }
       { \cs_if_exist_use:cF
         { g_@@_secondary_ \l_context_secondary_str _ #1 _tl }
         { \cs_if_exist_use:cF
           { g_@@_secondary_ * _ #1 _tl }
           { #1 }
         }
       }
     }
  \@@_debug_typeout:n{set~ secondary~ <-~ \l_context_secondary_str }   
}
%    \end{macrocode}
%  \end{macro}
%
%
%  \begin{macro}{\DeclareSecondaryContextRule}
%    
%    \begin{macrocode}
\cs_new_protected:Npn \DeclareSecondaryContextRule #1#2#3 {
  \tl_gclear_new:c { g_@@_secondary_ #1 _ #2 _tl }
  \tl_gset:cn      { g_@@_secondary_ #1 _ #2 _tl } {#3}
}
%    \end{macrocode}
%  \end{macro}
%
%
%
% \subsection{Supporting font size changes as a secondary context}
%
%
%
%  \begin{macro}{\@setfontsize}
%    We try to be careful when setting the name as we don't know if
%   \cs{string} returns a backslash or not.
%    \begin{macrocode}
\def\@setfontsize#1#2#3{\@nomath#1%
  \ifx\protect\@typeset@protect
  \let\@currsize#1%
  \begingroup
    \escapechar\m@ne
    \expandafter
  \endgroup
    \expandafter
  \SetSecondaryContext
    \expandafter {\string#1}%
  \fi
  \fontsize{#2}{#3}\selectfont
}
%    \end{macrocode}
%    If we are typesetting in \cs{normalsize} we don't want that as as
%    the context, so here is a first application of a rule.
%    \begin{macrocode}

\DeclareSecondaryContextRule{*}{normalsize}{}
%    \end{macrocode}
%  \end{macro}
%
%
%
% \subsection{Supporting primary context}
%
% \subsubsection{Float context}
%
%  \begin{macro}{\@float}
%    This should  work with most float pages. There are of course some
%    classes or packages that produce pseudo floats without calling
%    \cs{@float}. These need to be handled separately by adding a
%    \cs{SetPrimaryContext} in their code.
%    \begin{macrocode}
\AddToHook{cmd/@float/before}{\SetPrimaryContext{float}}
%    \end{macrocode}
%  \end{macro}
%
%
% \subsubsection{Caption context}
%
% \TODO{in latex-lab-float}
% \cs{@makecaption} is redefined there and the context should be set in that
% command (or its replacement one day).
%
% \TODO{longtable and anything else that runs around producing \cs{caption}s}
%
%
% \subsubsection{Footnote context}
%
% \TODO{in latex-lab-footnote}
%
%
%
% \subsubsection{Header context}
%
% \TODO{}
%
%
%
% \subsubsection{Footer context}
%
% \TODO{}
%
%
%
% \subsubsection{Marginal context}
%
% \TODO{}
%
%
%
%
%
% \subsection{Changes to lttemplates.dtx code}
%
%    \begin{macrocode}
%<@@=template>
%    \end{macrocode}
%
%
%
%
%  \begin{macro}{\@@_use_instance_aux:nn}
%    This is the command that is used by \cs{UseInstance} to select and
%    execute a requested instance. So we now have to have a little
%    more logic here.

%    In the normal case (both primary and secondary context are empty)
%    we now have 3 tests. We have up to 4 tests if only primary is
%    non-empty and up to 5 tests if secondary is non-empty.
%    \begin{macrocode}
\cs_set_protected:Npn \@@_use_instance_aux:nn #1#2 {
  \@@_debug:n { \str_if_empty:NF \l_context_primary_str
                  { \@@_debug_typeout:n {primary~ context~ is~
                                        '\l_context_primary_str' } } }
  \@@_debug:n { \str_if_empty:NF \l_context_secondary_str
                  { \@@_debug_typeout:n {secondary~ context~ is~
                                        '\l_context_secondary_str' } } }
  \tl_if_empty:NTF \l__context_secondary_tl
     {
       \str_if_empty:NTF \l_context_primary_str
          {
            \@@_if_instance_exist:nnTF { #1 } { #2 }
              { \@@_use_existing_instance:nn { #1 } { #2 } }
              { \msg_error:nnnn { template } { unknown-instance } {#1} {#2} }
          }
          {
            \@@_if_instance_exist:nnTF { #1 } { #2 : \l_context_primary_str  }
               { \@@_use_existing_instance:nn { #1 }
                                              { #2 : \l_context_primary_str } }
              {
                \@@_if_instance_exist:nnTF { #1 } { #2 }
                  { \@@_use_existing_instance:nn { #1 } { #2 } }
                  { \msg_error:nnnn { template } { unknown-instance } {#1} {#2} }
              }
          }
     }
     {
       \@@_if_instance_exist:nnTF { #1 }
                                  { #2 : \l_context_primary_str
                                       : \l_context_secondary_str  }
         { \@@_use_existing_instance:nn { #1 }
            { #2 : \l_context_primary_str : \l_context_secondary_str } }
         {
           \str_if_empty:NTF \l_context_primary_str
              {
                \@@_if_instance_exist:nnTF { #1 } { #2 }
                  { \@@_use_existing_instance:nn { #1 } { #2 } }
                  { \msg_error:nnnn { template } { unknown-instance } {#1} {#2} }
              }
              {
                \@@_if_instance_exist:nnTF { #1 }
                                           { #2 : \l_context_primary_str  }
                  { \_@@_use_existing_instance:nn { #1 }
                                                  { #2 : \l_context_primary_str } }
                  {
                    \@@_if_instance_exist:nnTF { #1 } { #2 }
                      { \@@_use_existing_instance:nn { #1 } { #2 } }
                      { \msg_error:nnnn { template } { unknown-instance } {#1} {#2} }
                  }
              }
         }
     }
}
%    \end{macrocode}
%  \end{macro}
%
%    
%
%
%  \begin{macro}{\_@@_use_existing_instance:nn}
%    We combine all debugging info for an execution of the instance in one
%    macro, to be used when we know for sure that this instance
%    exists.
%    \begin{macrocode}
\cs_new_protected:Npn \_@@_use_existing_instance:nn #1#2 {
  \@@_debug_typeout:n{Use~ '#1'~ instance:~ #2  \on@line }
  \use:c { \c_@@_instances_root_tl #1 / #2 }
}
%    \end{macrocode}
%  \end{macro}
%
%
% \subsubsection{Debugging of templates}
%
%    
%  \begin{variable}{\g_@@_debug_bool}
%    
%    \begin{macrocode}
\bool_new:N \g_@@_debug_bool
%    \end{macrocode}
%  \end{variable}
%
%
%  \begin{macro}{\@@_debug:n,\@@_debug_typeout:n}
%    
%    \begin{macrocode}
\cs_new_eq:NN \@@_debug:n \use_none:n
\cs_new_eq:NN \@@_debug_typeout:n \use_none:n
%    \end{macrocode}
%  \end{macro}
%
%  \begin{macro}{\template_debug_on:,\template_debug_off:,
%                \@@_debug_gset:}
%    \begin{macrocode}
\cs_new_protected:Npn \template_debug_on:
  {
    \bool_gset_true:N \g_@@_debug_bool
    \@@_debug_gset:
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new_protected:Npn \template_debug_off:
  {
    \bool_gset_false:N \g_@@_debug_bool
    \@@_debug_gset:
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new_protected:Npn \@@_debug_gset:
  {
    \cs_gset_protected:Npx \@@_debug:n ##1
      { \bool_if:NT \g_@@_debug_bool {##1} }
    \cs_gset_protected:Npx \@@_debug_typeout:n ##1
      { \bool_if:NT \g_@@_debug_bool { \typeout{[Template]~ ==>~ ##1} } }
  }
%    \end{macrocode}
%  \end{macro}
%
%
%  \begin{macro}{\DebugTemplatesOn,\DebugTemplatesOff}
%    
%    \begin{macrocode}
\cs_new_protected:Npn \DebugTemplatesOn  { \template_debug_on:  }
\cs_new_protected:Npn \DebugTemplatesOff { \template_debug_off: }
%    \end{macrocode}
%    
%    \begin{macrocode}
\DebugTemplatesOn
%    \end{macrocode}
%  \end{macro}
%
%
%
%
%    \begin{macrocode}
%</package>
%    \end{macrocode}
%
%
%
%
%    \begin{macrocode}
%<*latex-lab>
\ProvidesFile{context-latex-lab-testphase.ltx}
        [\ltlabcontextdate\space v\ltlabcontextversion\space 
         latex-lab wrapper context]

\RequirePackage{latex-lab-testphase-context}

%</latex-lab>
%    \end{macrocode}
