% \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} % % % \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 = { , ... } %\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 = {