[latex3-commits] [git/LaTeX3-latex3-latex2e] prototype: First conversion of xtemplate to l3keys internals (ab522f86)

Joseph Wright joseph.wright at morningstar2.co.uk
Tue Mar 8 14:20:26 CET 2022


Repository : https://github.com/latex3/latex2e
On branch  : prototype
Link       : https://github.com/latex3/latex2e/commit/ab522f866b71e7140ecdba50af8721458b599cd4

>---------------------------------------------------------------

commit ab522f866b71e7140ecdba50af8721458b599cd4
Author: Joseph Wright <joseph.wright at morningstar2.co.uk>
Date:   Tue Mar 8 13:20:26 2022 +0000

    First conversion of xtemplate to l3keys internals


>---------------------------------------------------------------

ab522f866b71e7140ecdba50af8721458b599cd4
 required/latex-lab/changes.txt                  |   6 +
 required/latex-lab/documentmetadata-support.ins |   4 +-
 required/latex-lab/ltprototype.dtx              | 512 ++++++++++++++++++++++++
 3 files changed, 521 insertions(+), 1 deletion(-)

diff --git a/required/latex-lab/changes.txt b/required/latex-lab/changes.txt
index 9551d74b..0af1eb6f 100644
--- a/required/latex-lab/changes.txt
+++ b/required/latex-lab/changes.txt
@@ -1,3 +1,9 @@
+2022-03-08 Joseph Wright <Joseph.Wright at latex-project.org>
+
+	* ltprototype.dtx
+	 New file re-implementing ides from on xtemplate.dtx using updated
+	 keyval support
+
 2021-12-30 Ulrike Fischer <Ulrike.Fischer at latex-project.org>
 
 	* documentmeta-support.dtx:
diff --git a/required/latex-lab/documentmetadata-support.ins b/required/latex-lab/documentmetadata-support.ins
index 431f88d8..5ef2f21d 100644
--- a/required/latex-lab/documentmetadata-support.ins
+++ b/required/latex-lab/documentmetadata-support.ins
@@ -35,7 +35,7 @@
 
 This is a generated file.
 
-Copyright 2021 LaTeX Project
+Copyright 2021,2022 LaTeX Project
 
 This file was generated from file(s) of the  `LaTeX-lab Bundle'.
 ------------------------------------------------------------------------------------
@@ -68,4 +68,6 @@ where one can also log issues in case there are any.
 \generate{\file{phase-I-latex-lab-testphase.ltx}{\from{latex-lab-testphase.dtx}{phase-I}}}
 \generate{\file{phase-II-latex-lab-testphase.ltx}{\from{latex-lab-testphase.dtx}{phase-II}}}
 
+\generate{\file{ltprototype.sty}{\from{ltprototype.dtx}{2ekernel}}}
+
 \endbatchfile
diff --git a/required/latex-lab/ltprototype.dtx b/required/latex-lab/ltprototype.dtx
new file mode 100644
index 00000000..244b041d
--- /dev/null
+++ b/required/latex-lab/ltprototype.dtx
@@ -0,0 +1,512 @@
+% \iffalse meta-comment
+%
+%% File: ltprototype.dtx
+%
+% Copyright (C) 1999 Frank Mittelbach, Chris Rowley, David Carlisle
+%           (C) 2004-2010 Frank Mittelbach, The LaTeX Project
+%           (C) 2011-2022 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
+%
+% This file is part of the "latex-lab bundle" (The Work in LPPL)
+% and all files in that bundle must be distributed together.
+%
+% -----------------------------------------------------------------------
+%
+% The development version of the bundle can be found at
+%
+%    https://github.com/latex3/latex2e
+%
+% for those people who are interested.
+%
+%<*driver>
+\documentclass[full]{l3doc}
+\begin{document}
+  \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \title{^^A
+%   The \textsf{ltprototype} package\\ Prototype document functions^^A
+% }
+%
+% \author{^^A
+%  The \LaTeX{} Project\thanks
+%    {^^A
+%      E-mail:
+%        \href{mailto:latex-team at latex-project.org}
+%          {latex-team at latex-project.org}^^A
+%    }^^A
+% }
+%
+% \date{Released 2022-01-12}
+%
+% \maketitle
+%
+% \begin{documentation}
+%
+% There are three broad \enquote{layers} between putting down ideas into
+% a source file and ending up with a typeset document. These layers of
+% document writing are
+% \begin{enumerate}
+%   \item authoring of the text with mark-up;
+%   \item document layout design;
+%   \item implementation (with \TeX{} programming) of the design.
+% \end{enumerate}
+% We write the text as an author, and we see the visual output of the design
+% after the document is generated; the \TeX{} implementation in the middle is
+% the glue between the two.
+%
+% \LaTeX{}'s greatest success has been to standardise a system of mark-up that
+% balances the trade-off between ease of reading and ease of writing to suit
+% almost all forms of technical writing. It's
+% other original strength was a good background in typographical design; while
+% the standard \LaTeXe{} classes look somewhat dated now in terms of their
+% visual design, their typography is generally sound. (Barring the occasional
+% minor faults.)
+%
+% However, \LaTeXe{} has always lacked a standard approach to customising
+% the visual design of a document. Changing the looks of the standard classes
+% involved either:
+% \begin{itemize}
+%   \item Creating a new version of the implementation code of the class and
+%     editing it.
+%   \item Loading one of the many packages to customise certain elements of
+%     the standard classes.
+%   \item Loading a completely different document class, such as
+%     \textsf{KOMA-Script} or \textsf{memoir}, that allows easy customisation.
+% \end{itemize}
+% All three of these approaches have their drawbacks and learning curves.
+%
+% The idea behind \pkg{xtemplate} is to cleanly separate the three layers
+% introduced at the beginning of this section, so that document authors who
+% are not programmers can easily change the design of their documents.
+% \pkg{xtemplate} also makes it easier for \LaTeX{} programmers to provide
+% their own customisations on top of a pre-existing class.
+%
+% \section{What is a document?}
+%
+% Besides the textual content of the words themselves, the source file
+% of a document contains mark-up elements that add structure to the
+% document. These elements include sectional divisions, figure/table
+% captions, lists of various sorts, theorems/proofs, and so on.
+% The list will be different for every document that can be written.
+%
+% Each element can be represented logically without worrying about the
+% formatting, with mark-up such as \cs{section}, \cs{caption},
+% |\begin{enumerate}| and so on. The output of each one of these
+% document elements will be a typeset representation of the information
+% marked up, and the visual arrangement and design of these elements
+% can vary widely in producing a variety of desired outcomes.
+%
+% For each type of document element, there may be design variations that
+% contain the same sort of information but present it in slightly
+% different ways. For example, the difference between a numbered and an
+% unnumbered section, \cs{section} and |\section*|, or the difference
+% between an itemised list or an enumerated list.
+%
+% There are three distinct layers in the definition of
+% \enquote{a document} at this level
+% \begin{enumerate}
+%   \item semantic elements such as the ideas of sections and lists;
+%   \item a set of design solutions for representing these elements
+%     visually;
+%   \item specific variations for these designs that represent the
+%     elements in the document.
+% \end{enumerate}
+% In the parlance of the template system, these are called object types,
+% templates, and instances, and they are discussed below in sections
+% \ref{sec:objects}, \ref{sec:templates}, and~\ref{sec:instances},
+% respectively.
+%
+% By formally declaring documents to be composed of mark-up elements
+% grouped into objects, which are interpreted and typeset with a set of
+% templates, each of which has one or more instances with which to
+% compose each and every semantic unit of the text, we can cleanly
+% separate the components of document construction.
+%
+% \section{Object types}
+% \label{sec:objects}
+%
+% An \emph{object type} (sometimes just \enquote{object}) is an
+% abstract idea of a document element that takes a fixed number of
+% arguments corresponding to the information from the document author
+% that it is representing. A sectioning object, for example, might take
+% three inputs: \enquote{title}, \enquote{short title}, and
+% \enquote{label}.
+%
+% Any given document class will define which object types are to be
+% used in the document, and any template of a given object type can be
+% used to generate an instance for the object. (Of course, different
+% templates will produce different typeset representations, but the
+% underlying content will be the same.)
+%
+% \begin{function}{\prototype_declare_object:nn}
+%   \begin{syntax}
+%     \cs{prototype_declare_object:nn} \Arg{object type} \Arg{no.~of args}
+%   \end{syntax}
+%  This function defines an \meta{object type} taking
+%  \meta{no.~of arguments}, where the \meta{object type} is an
+%  abstraction as discussed above. For example,
+%   \begin{verbatim}
+%     \prototype_declare_object:nn { sectioning } { 3 }
+%   \end{verbatim}
+%  creates an object type \enquote{sectioning}, where each use of that
+%  object type will need three arguments.
+% \end{function}
+%
+% \section{Templates}
+% \label{sec:templates}
+%
+% A \emph{template} is a generalised design solution for representing
+% the information of a specified object type. Templates that do the same
+% thing, but in different ways, are grouped together by their object type
+% and given separate names. There are two important parts to a template:
+% \begin{itemize}
+%   \item the parameters it takes to vary the design it is producing;
+%   \item the implementation of the design.
+% \end{itemize}
+%
+% \begin{function}{\prototype_declare_template:nnnn}
+%   \begin{syntax}
+%     \cs{prototype_declare_template:nnnn}
+%     ~~\Arg{object type} \Arg{template}
+%     ~~\Arg{key definitions} \Arg{code}
+%   \end{syntax}
+%   A \meta{template} interface is declared for a particular
+%   \meta{object type}. The interface itself is
+%   defined by the \meta{key definitions}, which is itself a key--value list
+%   using the same interface as \cs{keys_define:nn}. (The keys created
+%   here \emph{are} managed \pkg{l3keys} in the tree
+%   \texttt{template/\mea{object}/\meta{template}}). As described below,
+%   the keys should be defined such that they can be set multiple times:
+%   first to a default value, then to a specific value for an instance
+%   and finally to a per-use override.
+%
+%   The \meta{code} argument of \cs{template_declare_template:nnnn} is used
+%   as the replacement text for the template when it is used, either
+%   directly or as an instance. This may therefore accept arguments
+%   |#1|, |#2|, \emph{etc}.~as detailed by the \meta{number of arguments}
+%   taken by the object type. The template and instance key values (see
+%   below) are assigned before the \meta{code} is inserted.
+% \end{function}
+%
+% \begin{function}{\prototype_declare_defaults:nnn}
+%   \begin{syntax}
+%     \cs{prototype_declare_template:nnnn}
+%     ~~\Arg{object type} \Arg{template} \Arg{defaults}
+%   \end{syntax}
+%   Sets the default values for each \meta{key} in a \meta{template}. When
+%   a template is used, these values are applied first \emph{before} those
+%   set by \cs{prototype_use_template:nnn} or
+%   \cs{prototype_declare_instance:nnnn}. If not default is given, the
+%   prevailing state when the template is used will apply.
+% \end{function}
+%
+% \section{Instances}
+% \label{sec:instances}
+%
+% After a template is defined it still needs to be put to use. The
+% parameters that it expects need to be defined before it can be used in
+% a document. Every time a template has parameters given to it, an
+% \emph{instance} is created, and this is the code that ends up in the
+% document to perform the typesetting of whatever pieces of information
+% are input into it.
+%
+% For example, a template might say \enquote{here is a section with or
+% without a number that might be centred or left aligned and print its
+% contents in a certain font of a certain size, with a bit of a gap
+% before and after it} whereas an instance declares \enquote{this is a
+% section with a number, which is centred and set in $12\,\text{pt}$
+% italic with a $10\,\text{pt}$ skip before and a
+% $12\,\text{pt}$ skip after it}. Therefore, an instance is just a
+% frozen version of a template with specific settings as chosen by the
+% designer.
+%
+% \begin{function}{\prototype_declare_instance:nnnn}
+%   \begin{syntax}
+%     \cs{prototype_declare_instance:nnnn}
+%     ~~\Arg{object type} \Arg{instance} \Arg{template} \Arg{parameters}
+%   \end{syntax}
+%   This function uses a \meta{template} for an \meta{object type}
+%   to create an \meta{instance}. The \meta{instance} will be set
+%   up using the \meta{parameters}, which will set some of the
+%   \meta{keys} in the \meta{template}.
+%
+%   As a practical example, consider an object type for document sections
+%   (which might include chapters, parts, sections, \emph{etc}.), which
+%   is called \texttt{sectioning}. One possible template for this
+%   object type might be called \texttt{basic}, and one instance of this
+%   template would be a numbered section. The instance declaration might
+%   read:
+%   \begin{verbatim}
+%     \prototype_declare_instance:nnnn { sectioning } { section-num } { basic }
+%       {
+%         numbered      = true ,
+%         justification = center ,
+%         font          = \normalsize\itshape ,
+%         before-skip   = 10pt ,
+%         after-skip    = 12pt ,
+%       }
+%   \end{verbatim}
+%   Of course, the key names here are entirely imaginary, but illustrate
+%   the general idea of fixing some settings.
+% \end{function}
+%
+% \section{Document interface}
+%
+% After the instances have been chosen, document commands must be
+% declared to use those instances in the document. \cs{UseInstance}
+% calls instances directly, and this command should be used internally
+% in document-level mark-up.
+%
+% \begin{function}{\prototype_use_instance:nnn}
+%   \begin{syntax}
+%     \cs{prototype_use_instance:nnn}
+%     ~~\Arg{object type} \Arg{instance} \meta{arguments}
+%   \end{syntax}
+%   Uses an \meta{instance} of the \meta{object type}, which will require
+%   \meta{arguments} as determined by the number specified for the
+%   \meta{object type}. The \meta{instance} must have been declared
+%   before it can be used, otherwise an error is raised.
+% \end{function}
+%
+% \begin{function}{\prototype_use_template:nnnn}
+%   \begin{syntax}
+%     \cs{prototype_use_template:nnnn} \Arg{object type} \Arg{template}
+%     ~~\Arg{settings} \meta{arguments}
+%   \end{syntax}
+%   Uses the \meta{template} of the specified \meta{object type},
+%   applying the \meta{settings} and absorbing \meta{arguments} as
+%   detailed by the \meta{object type} declaration. This in effect
+%   is the same as creating an instance using
+%   \cs{template_declare_instance:nnnn} and immediately using it with
+%   \cs{template_use_instance:nnn}, but without the instance having any
+%   further existence. It is therefore useful where a template needs to
+%   be used once.
+%   \end{verbatim}
+% \end{function}
+%
+% \section{Per-use overriding of template settings}
+%
+% The key settings for a template or instance can be overridden using
+% \cs{keys_set:nn} with the key path
+% \texttt{prototype/\meta{object}/\meta{template}}. This will likely occur
+% immediately after the start of the template code.
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{ltprototype} Implementation}
+%
+% \subsection{File declaration}
+%    \begin{macrocode}
+%<*package>
+\ProvidesFile{ltprototype.sty}
+  [2022-03-25 v0.1a Experimental prototype document functions]
+%</package>
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+%<*2ekernel>
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+%<@@=prototype>
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\ExplSyntaxOn
+%    \end{macrocode}
+%
+% \subsection{Setup}
+%
+% \begin{variable}{\l_@@_tmp_tl}
+%    \begin{macrocode}
+\tl_new:N \l_@@_tmp_tl
+%    \end{macrocode}
+% \end{variable}
+%
+% \subsection{Data structures}
+%
+% \begin{variable}{\l_@@_object_prop}
+%    \begin{macrocode}
+\prop_new:N \l_@@_object_prop
+%    \end{macrocode}
+% \end{variable}
+%
+% \subsection{Creating objects}
+%
+% \begin{macro}{\prototype_declare_object:nn, \@@_declare_object:nn}
+%   Although the object type is the \enquote{top level} of the template
+%   system, it is actually very easy to implement. All that happens is that
+%   the number of arguments required is recorded, indexed by the name of the
+%   object type.
+%    \begin{macrocode}
+\cs_new_protected:Npn \prototype_declare_object:nn #1#2
+  {
+    \exp_args:Nx \@@_declare_object:nn { \int_eval:n {#2} } {#1}
+  }
+\cs_new_protected:Npn \@@_declare_object:nn #1#2
+  {
+    \int_compare:nTF { 0 <= #1 <= 9 }
+      {
+        \msg_info:nnnn { prototype } { declare-object-type } {#2} {#1}
+        \prop_put:Nnn \l_@@_object_prop {#2} {#1}
+      }
+      { \msg_error:nnxx { prototype } { bad-number-of-arguments } {#2} {#1} }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Templates and instances}
+%
+% \begin{variable}{\l_@@_assignments_tl}
+%   Used to insert the set keys.
+%    \begin{macrocode}
+\tl_new:N \l_@@_assignments_tl
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\prototype_declare_template:nnnn}
+% \begin{macro}{\prototype_declare_defaults:nnn}
+%   Creating a template means defining the keys, storing the defaults and
+%   creating the function. The defaults are done separately from the other
+%   parts as that fits the \pkg{l3keys} pattern but also makes it easy to
+%   alter that aspect without changing the core implementation.
+%    \begin{macrocode}
+\cs_new_protected:Npn \prototype_declare_template:nnnn #1#2#3#4
+  {
+    \prop_get:NnNTF \l_@@_object_prop {#1} \l_@@_tmp_tl
+      {
+        \keys_define:nn { prototype / #1 / #2 } {#3}
+        \tl_clear_new:c { l_@@_defaults_ #1 _ #2 _tl }
+        \cs_generate_from_arg_count:cNnn
+          { @@_template_ #1 _ #2 :w }
+          \cs_set_protected:Npn
+          { \l_@@_tmp_tl }
+          {
+            \tl_use:N \l_@@_assignments_tl
+            #4
+          }
+      }
+      { \msg_error:nnn { prototype } { unknown-object-type } {#1} }
+  }
+\cs_new_protected:Npn \prototype_declare_defaults:nnn #1#2#3
+  {
+    \cs_if_exist:cTF { @@_template_ #1 _ #2 :w }
+      { \tl_set:cn { l_@@_defaults_ #1 _ #2 _tl } {#3} }
+      { \msg_error:nnn { prototype } { unknown-template } {#1} {#2} }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+%    \begin{macrocode}
+\cs_generate_variant:Nn \keys_precompile:Nnn { Nnv }
+%    \end{macrocode}
+%
+% \begin{macro}{\prototype_use_template:nnn}
+% \begin{macro}{\prototype_declare_instance:nnnn}
+% \begin{macro}{\@@_declare_aux:nnnn}
+%   Using a template and creating an instance are the same thing other
+%   than the final step: using the template or storing the key settings.
+%   We do not attempt to maximise efficiency in setting, rather we have
+%   a clear approach in which the final assignments may have multiple
+%   entries.
+%    \begin{macrocode}
+\cs_new_protected:Npn \prototype_use_template:nnn #1#2#3
+  {
+    \@@_declare_aux:nnnn {#1} {#2} {#3}
+      { \use:c { @@_template_ #1 _ #2 :w } }
+  }
+\cs_new_protected:Npn \prototype_declare_instance:nnnn #1#2#3#4
+  {
+    \@@_declare_aux:nnnn {#1} {#2} {#4}
+      {
+        \tl_clear_new:c { l_@@_instance_ #1 _ #3 _tl }
+        \tl_set_eq:cN { l_@@_instance_ #1 _ #3 _tl }
+          \l_@@_assignments_tl
+      }
+  }
+\cs_new_protected:Npn \@@_declare_aux:nnnn #1#2#3#4
+  {
+    \cs_if_exist:cTF { @@_template_ #1 _ #2 :w }
+      {
+        \keys_precompile:Nnv \l_@@_assignments_tl
+          { prototype / #1 / #2 }
+          { l_@@_defaults_ #1 _ #2 _tl } 
+        \keys_precompile:Nnn \l_@@_tmp_tl { prototype / #1 / #2 } {#3}
+        \tl_put_right:NV \l_@@_assignments_tl \l_@@_tmp_tl
+        #4
+      }
+      { \msg_error:nnn { prototype } { unknown-template } {#1} {#2} }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\prototype_use_instance:nn}
+%   Recover the values and insert the code.
+%    \begin{macrocode}
+\cs_new_protected:Npn \prototype_use_instance:nn #1#2
+  {
+    \tl_if_exist:cTF { l_@@_instance_ #1 _ #2 _tl }
+      {
+        \tl_set_eq:Nc \l_@@_assignments_tl
+          { l_@@_instance_ #1 _ #2 _tl }
+        \use:c { @@_template_ #1 _ #2 :w }
+      }
+      { \msg_error:nnn { prototype } { unknown-instance } {#1} {#2} }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Messages}
+%
+%    \begin{macrocode}
+\msg_new:nnnn { prototype } { bad-number-of-arguments }
+  { Bad~number~of~arguments~for~object~type~'#1'. }
+  {
+    An~object~may~accept~between~0~and~9~arguments.\\
+    You~asked~to~use~#2~arguments:~this~is~not~supported.
+  }
+\msg_new:nnnn { prototype } { unknown-instance }
+  { The~instance~'#2'~of~type~'#1'~is~unknown. }
+  {
+    You~have~asked~to~use~an~instance~'#2',~
+    but~this~has~not~been~created.
+  }
+\msg_new:nnnn { prototype } { unknown-object-type }
+  { The~object~type~'#1'~is~unknown. }
+  { An~object~type~needs~to~be~declared~prior~to~using~it. }
+\msg_new:nnnn { prototype } { unknown-template }
+  { The~template~'#2'~of~type~'#1'~is~unknown. }
+  {
+    No~interface~has~been~declared~for~a~template~
+    '#2'~of~object~type~'#1'.
+  }
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\msg_new:nnn { prototype } { declare-object-type }
+  { Declaring~object~type~'#1'~taking~#2~argument(s). }
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\ExplSyntaxOff
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+%</2ekernel>
+%    \end{macrocode}
+%
+% \end{implementation}
\ No newline at end of file





More information about the latex3-commits mailing list.