% \iffalse %% %% (C) Copyright 1999 David Carlisle, Frank Mittelbach %% All rights reserved. %% %% Not for general distribution. In its present form it is not allowed %% to put this package onto CD or an archive without consulting the %% the authors. %% %<*dtx> \ProvidesFile{template.dtx} % %\NeedsTeXFormat{LaTeX2e} %\ProvidesPackage{template} %\ProvidesFile{template.drv} % \fi % \ProvidesFile{template.dtx} [1999/09/28 v0.14 template parsing (DPC,FMi)] % % \iffalse %<*driver> \documentclass{ltxdoc} \makeatletter \newenvironment{decl}[1][]% {\par\small\addvspace{4.5ex plus 1ex}% \vskip -\parskip \ifx\relax#1\relax \def\@decl@date{}% \else \def\@decl@date{\NEWfeature{#1}}% \fi \noindent\hspace{-\leftmargini}% \begin{tabular}{|l|}\hline\ignorespaces}% {\\\hline\end{tabular}\nobreak\@decl@date\par\nobreak \vspace{2.3ex}\vskip -\parskip\@afterheading} \makeatother \begin{document} \DocInput{template.dtx} \end{document} % % \fi % % % \CheckSum{864} % % \GetFileInfo{template.dtx} % % \title{The \textsf{template} package\thanks{This file % has version number \fileversion, last % revised \filedate.}} % \author{DPC, FMi} % \date{\filedate} % \maketitle % % \changes{0.06}{1998/12/17}{generic functions reborn as templates} % % \tableofcontents % % \section{Introduction} % A \emph{Template} is a named `function' that has a fixed number % of \emph{mandatory arguments} and an additional set of \emph{keys} % or `named attributes' that are set in a `key value list'. That is, % a comma separated set of assignments of the form:\\ % \meta{key$_1$} |=| \meta{value$_1$} |,| % \meta{key$_2$} |=| \meta{value$_2$} \ldots % % More specific instances of the template may be declared by % specifying settings of the parameters. The key value list is parsed % at the time the instance is declared, and an `internal' set of % parameter assignments is passed to the template code. It is normally % not parsed at run-time, though it is possible to enforce this % behaviour. % % Templates have a \emph{type} and a \emph{name}. Templates % of the same type have the same argument and parameter % structure. That is, templates of the same type are expected to be % exchangeable semantically. (However, except for checking that % templates of the same type always have the same number of arguments % this is not enforced by the code.) % % A template type is declared via the |\DeclareTemplateType| % declaration which takes two arguments: the name for the type and the % number of arguments a template of this type requires. % % Templates are declared via the |\DeclareTemplate| % command which takes five arguments % \begin{itemize} % \item The \emph{type} of the template (no |\|). % \item The \emph{name} of the template (no |\|). % \item The number of arguments for the template (same as on type % declaration). % \item A list declaring the keys accepted by the template, % with information about the action to take when the key is specified % with a value. % \item The code for the template. This may be arbitrary \TeX\ % code. At some point it should execute |\DoParameterAssignments| % to run the parameter assigments. % % The mandatory arguments are accessed via |#1|, |#2|, \ldots % \end{itemize} % % % Each element of the key specification list is of the form: % \begin{flushleft} % \meta{key name} |=| % \meta{key type} \meta{optional default} \meta{internal code} % \end{flushleft} % % The \meta{key types} are essentially specified by giving a symbolic % representation of the assignment function to be used by \TeX. % % Currently the possibilities are % % \begin{center}\catcode`|=12 % \begin{tabular}{l|ll|l} % key type& letter& internal code& argument form\\\hline % Command & f\emph{n}&command name & command definition\\ % name & n & command name & command definition\\ % length & l & length register& calc length syntax\\ % fake length & L & command name & calc length syntax\\ % count & c & count register& calc count syntax\\ % fake count & C & command name & calc count syntax\\ % boolean & b & name of \verb|\newif| switch& true or false\\ % switch & s & \marg{true code}\marg{false code}& true or false\\ % instance& i\marg{type}& command name& instance of this \emph{type}\\ % direct & x & Internal code& any\\ % general & g & general code & any % \end{tabular} % \end{center} % % In addition, any of these types may be prefixed by |+| to % denote a global assignment (described below). % |f| takes a digit from 0--9 to denote the number of arguments. % |n| is in fact the same as |f0|. When an instance is declared % The value assigned to the key should be the definition of % the command, using |#1|\ldots|#9| to denote the specified arguments. % % |c| takes an internal form a count register, % not a \LaTeX\ counter name. % % For |f|, |n|, |l|, and |c|, the assignment is done twice, once % at the time an instance is \emph{declared}. (This may involve % using \textsf{calc} expresions. Then the `primitive assignment' % of the value (not using calc) is copied to the internal parameter % list, to be executed when an instance is run. Sometimes you need the % expression to be evaluated at the time an instance is run rather % than the time it is declared. For example it may be an expression % involving some values that are not fixed throughout a document. % In this case the instance declaration may give a value in the % form |\DelayedEvaluation|\marg{calc expression}. In this case % the value is not evaluated when the instance is declared, and % instead the entire expression is copied to the `internal parameter % list' and is evaluated whenever the instance is used. % % |L| and |C| take the same value types as |l| and |c| but the internal % assignments are to macros not registers. % % Keys declared with |b| and |s| each take values either \emph{true} or % \emph{false}. if the key zzz is declared with |b| then specifying % |zzz=true| will essentially pass |\zzztrue| to the internal parameter % list (although in fact |\zzztrue| need not be defined) . If instead % zzz had been declared via |s|, then |zzz=true| would pass the tokens % of the \marg{true code} to the internal parameter list. % % If a key is specified as |x|, then when used the \emph{internal code} % will be copied to the internal parameter lists. This code may use |#1| % to denote the value supplied to the key in the instance declaration. % Note that this code is \emph{only} copied at the time the instance is % declared. It is not executed at this time. It is executed when the % instance is executed.\footnote{Despite the question of whether or % not x and g are still necessary these days, they have the wrong % `names' since x is the one that is not executed during delcaration % while g is.} % % If a key is declared with |g| then the code is run at the time the % instance is declared. By default \emph{nothing} is passed to the % internal parameter list. This code may use |#1| to denote the % value that will be supplied when an instance is declared. % Any code that should be run when an instance is executed should % be explicitly passed to the internal parameter list using % |\addto@hook\TP@toks{|\ldots|}| % % A key declared with |i|\marg{type} takes as value the name of a % declared instance of that type. The command token associated with % the key will store a command essentially equivalent to a call % to |\UseInstance|\marg{type}\marg{name}, but in a slightly optimised % internal form. % As an exception to this rule the replacement code may be of the form % |\UseTemplate| followed by the key settings for the template % but without the mandatory arguments. In this case the `inner' % instance declaration is `pre compiled' and the token assigned to % the store the value assigned to this key will execute an instance % of the template directly, it will not re-parse the keyword settings % each time the instance is used. % % \section{Commands} % % % \subsection{Template declaration commands} % % \begin{decl} % |\DeclareTemplateType| \marg{type}\marg{num} % \end{decl} % Declare a template type. % % \begin{decl} % |\DeclareTemplate| % \marg{type}\marg{tname}\marg{num}\marg{keyspec}\marg{code} % \end{decl} % Declare a template \meta{tname} of type \meta{type} with the set of % keys as defined by \meta{keyspec}. From this template instances can % be declared using |\DeclareInstance| At runtime such instances will run % \meta{code} and expect \meta{num} mandatory arguments (same number % for all templates of one type).\footnote{The \meta{num} argument is % redundent as it can be deduced from the type. However, for practical % reasons it seems better to keep that information with each % individual template declaration.} % % \begin{decl} % |\DeclareRestrictedTemplate| % \marg{type}\marg{new-tname}\marg{old-tname}\marg{keyvals} % \end{decl} % Declare as new template \meta{new-tname} for type \meta{type} by % taking template \meta{old-tname} as the basis and setting one or % more of its keys to specific values. % % \begin{decl} % |\DoParameterAssignments| % \end{decl} % The list of key value assignments made (and saved) during template % declaration is evaluated at this point in the template code. % % % \subsection{Instance declaration commands} % % \begin{decl} % |\DeclareInstance| \marg{type}\marg{iname}\marg{tname}\marg{keyvals} % \end{decl} % Declare an instance of type \meta{type} named \meta{iname} build % from using template \meta{tname} with key settings as given by % \meta{keyvals}. % % \begin{decl} % |\DeclareCollectionInstance| % \marg{collection}\marg{type}\marg{iname}\marg{tname}\marg{keyvals} % \end{decl} % Same as |\DeclareInstance| except that this instance is only active % when for the type \meta{type} the collection \meta{collection} was % selected via |\UseCollection|. E.g., within the frontmatter one % could make all headings behave differently by defining collection % instances for template type `head'. % % \subsection{Key value commands} % % \begin{decl} % |\DelayEvaluation|\marg{code} % \end{decl} % Used in the value spec for an instance to declare that the value % \meta{code} should not be evaluated at declaration time but at % run-time. Can also be used in the defaults for keys (given in square % brackets) in the declaration of templates. % % \begin{decl} % |\MultiSelection| \meta{counter} \marg{cases} \marg{else} % \end{decl} % Used in the value spec for an instance key to declare that the value of % this key depends on the current setting of \meta{counter} at run-time. % The \meta{cases} argument is a comma-separated list of ``values'', % the \meta{else} argument a single ``value''. If at run-time % \meta{counter} has the value $i$ then the $i$-th element of the % \meta{cases} list is selected. If that does not exist the % \meta{else} case is returned. % % % \subsection{Processing commands} % % \begin{decl} % |\UseTemplate| \marg{type}\marg{tname}\marg{keyval} % \end{decl} % Execute a template \meta{tname} of type \meta{type} at run-time % using \meta{keyvals} as the value assignments for its keys. In this % case the keys are evaluated at run-time thus this method is far % slower than using a predeclared instance of this template (see % below). This command can also appear as the value for a key of type % `i' in which case the evaluation happens at declaration time of the % template that contains this key! % % % \begin{decl} % |\UseInstance| \marg{type}\marg{iname} % \end{decl} % Run the instance \meta{iname} of template type \meta{type}. If a % collection is in force see if there is a collection instance of name % \meta{iname} and if so run that instead. % % \begin{decl} % |\UseCollection| \marg{type}\marg{collection} % \end{decl} % Declare that from now on (normal scoping rules) the collection % \meta{collection} for template type \meta{type} is in force. This % means that a call to |\UseInstance| will first check if there is a % collection instance defined, and if so use that instance, otherwise % use the normal instance. % % % \subsection{Test commands} % % \begin{decl} % |\IfExistsInstanceTF| \marg{type}\marg{iname}\marg{true}\marg{false} % \end{decl} % Test if for template type \meta{type} an instance with name % \meta{iname} exists. Select \meta{true} or \meta{false} code % accordingly. % % % % \section{Examples of template key types} % % The general syntax for key specification in templates (fourth argument % of the command |\DeclareTemplate|) is: %\begin{flushleft} %| {| \\ %| | \meta{key-name$_1$} |=|\meta{key-type$_1$} % \meta{optional-default$_1$} \meta{storage-bin$_1$}|,|\\ %| | \meta{key-name$_2$} |=|\meta{key-type$_2$} % \meta{optional-default$_2$} \meta{storage-bin$_2$}|,|\\ %| ...|\\ %| }| %\end{flushleft} % In this section we look at all possible key types and give examples % for them. % % % \subsection{Attributes that receive names as values} % % The type |n| expects to receive a \LaTeX{} name as a value. Used, % for example, to specify the name of a \LaTeX{} counter to use. %\begin{verbatim} % heading-id =n \heading@id, % counter-id =n [\DelayEvaluation{\heading@id}] \heading@counter, %\end{verbatim} % Notice the use of |\DelayEvaluation| in the default of % |counter-id|. It is necessary to make the default the token % |\heading@id| if we want to inherit the value from the |heading-id| % key. Otherwise it gets value of |\heading@id| at the time the % instance is declared. % % % \subsection{Attributes that receive functions as values} % % % The type |f|\meta{num} expects a function with \meta{num} arguments % as a value. The arguments are denoted by |#1|, |#2|, etc. In most % cases either |f0| (for declarations) or |f1| (to format one argument) are % needed. %\begin{verbatim} % initial-font =f0 \initial@font, % initial-format =f1 [#1] \initial@boxhandling, %\end{verbatim} % % \subsection{Attributes that receive dimensions as values} % % As far as specifying instances the |l| and |L| type behave % identically. They differ only in the type of internal storage-bin % they need: |l| expects a length register while |L| expects an % ordinary macro name and assigns its value via |\def|. %\begin{verbatim} % pre-sep =l \topsep, % post-sep =L \botsep, %\end{verbatim} % % % % \subsection{Attributes that receive integers as values} % % The |c| and |C| type receive integers as values. Again either of % them can be transparently used. In case of |c| the % \meta{storage-bin} has to be a \TeX{} count register not a \LaTeX{} % counter name, i.e., set up via |\newcount|. (\LaTeX{} counters can % be used as well if they are accessed via their internal name, i.e., % via |\c@|\meta{\LaTeX-counter}) %\begin{verbatim} % pre-penalty =c \@beginparpenalty, % penalty =C \hmaterial@penalty, %\end{verbatim} % % % % \subsection{Attributes that receive template instances as values} % % The type |i|\marg{type} takes as value the name of a declared % instance of that type. The \meta{storage-bin} associated with the % key will store a command essentially equivalent to a call to % |\UseInstance|\marg{type}\marg{name}, but in a slightly optimised % internal form. % % As an exception to this rule the replacement code may be of the form % |\UseTemplate| followed by the key settings for the template but % without the mandatory arguments. In this case the `inner' instance % declaration is `pre compiled' and the token assigned to the store % the value assigned to this key will execute an instance of the % template directly, it will not re-parse the keyword settings each % time the instance is used. %\begin{verbatim} % justification-setup =i{justification} \list@justification, %\end{verbatim} % % Usage within an instance declaration is either %\begin{verbatim} % justification-setup = raggedright, %\end{verbatim} % i.e., name of a declared instance or a call to |\UseTemplate| %\begin{verbatim} % justification-setup = \UseTemplate{justification}{TeX} % { startskip = 0pt, ... }, %\end{verbatim} % % % % \subsection{Attributes that receive true or false values} % % The type |s| expects the strings |true| or |false| as values. In % this case the declaration has no \meta{storage-bin}. Instead the % declaration consists of two brace groups containing code. Depending % on the value one of the groups gets copied verbatim into the % internal parameter list of the instance and gets executed at % run-time at the point where |\DoParameterAssignments| is seen. %\begin{verbatim} % item-implicit-boolean =s % { \def\item@implicit@code{\item\relax} }{}, % numbered-boolean =b [true] @heading@nums, %\end{verbatim} % % % \subsection{Attributes that accept any value} % % The type |g| is a low-level specification which contains arbitrary % code in place of the \meta{storage-bin}. This code is evaluated at % declaration time of the instance and by default \emph{nothing} is % passed to the internal parameter list (this has to happen explicitly % from within the code). |#1| may be used to access the value % specified. % The main purpose for this type is of historical nature (originally % most of the other types have been implemented internally using |g|). % % The type |x| also requires code in place of the \meta{storage-bin}. % However with this type all of the code is copied unevaluated to the % internal parameter list. There are some applications for this type % when implementing customisable defaults. However, it is likely that % it will not survive a final release. %\begin{verbatim} % generic-key =g \typeout{#1}, % extra-assigns =x \typeout{#1}, %\end{verbatim} % % % % % % % \section{A complete example} % % The following example shows a sketch of a template for typesetting % captions to be used as part of a larger mechanism setting whole % floats.\footnote{I made it up while I went along so if you spot the % ``missing brace'' or some other blunder tell me, FMi.} % % We declare a template type \texttt{caption} then define an example % template for that type and finally produce some instances from that. % % \subsection{Declaring the template type} % % To define the template type we first have to ask ourselves what % information would be varying each time such a template is used? A % potential answer could be the following: % \begin{itemize} % \item % The float name, e.g., `Table' or `Fig.' etc. % \item % The float % number e.g., `10' or `3--c' etc. % \item % The actual caption text as specified in the document. % \end{itemize} % Since the above items would be differed in each instantiation of % such a template we would pass them as mandatory argument to the % template. % % Are there others? Possibly. Here are two more that seem to be % useful, at least in a number of cases: % \begin{itemize} % \item % The text of the legend in document classes that distinguish % between caption text (heading to the figure/table) and legend % (explanatory material) % \item % Measure to which the caption should be typeset. % \end{itemize} % The last one of these might need some extra explanation. Suppose a % design requires that the caption width is decided depending on the % width of the table of figure, e.g., the caption is supposed to % typeset below some illustration and should not be wider than that % illustration, or the caption is typeset aside to the illustration % using the remaining space. In that case the process that formats the % whole float needs to communicate with the current template to pass % that (varying) information along. Of course, that could happen by % using global variables, e.g., the outer process sets the measure as % desired before calling the caption formatting template. What makes % more sense is likely to be a matter of taste but it also has to do % with the precise semantics of the template type. Staying with our % example: if the the semantics of the template type \texttt{caption} % is supposed to produce a formatted box (in \TeX{} terms) then we % should pass the measure as an argument if we ever intend to allow % for variations. If on the other hand the semantics are to format a % certain set of text into the current galley (which has measure of % its own) then a measure argument would not belong to this template % type. % % Are there other variations sensible? Yes, for example, instead of % passing a fixed string like ``Fig.'' as the first argument one could % pass an abstract float type identifier and let the template worry to % deduce from that information what fixed string to produce. % % Another question: why should we pass the fixed text (or an abstract % identifier from which it can be deduced) and the number as separate % arguments to the template instead of passing a combined string (like % it is done in the |\@makecaption| command of \LaTeXe{})? Answer: % because this allows to build templates that can individually % manipulate both bits of information, e.g., to format the number in a % different font, etc. % % So what are the conclusions of this discussion? Defining the % semantics of a template type is difficult and often needs several % trials to come up with something that is covering the anticipated % use. There is clearly not a cardinal way for defining template % types; how the overall separation into smaller units is done is % partly a matter of taste and partly a matter of the major layout % characteristics that one tries to support. % % Returning to our example: let's assume we settle for the first four % arguments, i.e., the calling template is responsible for setting the % measure for the caption text if necessary. % % What we also have to do is to define (at least for ourselves) what % data the arguments accept and what their semantics are. An informal % summary of that could be the following: % \begin{center} % \begin{tabular}{rrl} % \textit{Arg} & \textit{Data Type} & \textit{Description} \\[3pt] % 1 & text & fixed float description % \\ % 2 & text/|\NoValue| & float number % \\ % 3 & text & caption text % \\ % 4 & text/|\NoValue| & legend text % \\ % \end{tabular} % \end{center} % The second and the fourth argument are allowed to be missing (i.e., % can get |\NoValue| passed as a value). Note that the empty string in % case of a text argument is different from |\NoValue|. % % We further declare that it is permissible for a template of this % type to ignore the information provided by all arguments except 3, % i.e., the caption text. % % Finally the result of the template formatting should is to typeset % text into a current galley (paragraph mode in \LaTeX{} lingua). % % All the above is semantic information that (at least right now) is % not being enforced by declaring a template type (except for the % number of arguments) but each template of a certain type is supposed % to conform to this specification nonetheless.\footnote{To make this % even clearer we are thinking of extending the template type % declaration with another argument in which one has to formally or % informally (?) specifies information like the one in the table % above.} % % This finally leads to the following declaration: %\begin{verbatim} %\DeclareTemplateType{caption}{4} %\end{verbatim} % % \subsection{Defining a first template} % % We start by defining a simple template of type \texttt{caption} % which roughly formats a caption like those being presented in % \LaTeXe{}'s article class, i.e., the caption is typeset as a % paragraph if it is longer than a single line, otherwise it is % centered. The legend even if present is ignored. Above and below we % give the designer the possibility to add some space. % % In fact the examples is more or less identical in code to % |\@makecaption| except that if the second argument (i.e., the % number) is |\NoValue| it and its preceding space\footnote{For those % who wonder: spaces are by default ignored within definitions when % the new packages are used due to a command \texttt{\textbackslash % IgnoreWhiteSpace}, do get a normal space one has to use % \texttt{\textasciitilde} and to obtain an unbreakable space % \texttt{\textbackslash nobreakspace}.} gets ignored. % % We start by declaring the template \texttt{toosimple} of type % \texttt{caption} having four mandatory arguments (as described in % the discussion of the template type). %\begin{verbatim} %\DeclareTemplate{caption}{toosimple}{4} %\end{verbatim} % The next argument of |\DeclareTemplate| lists all keys for the % template. In this case we have keys for the vertical spaces above % and below. We make them type |L| to save on registers but with a bit % of care we could also have used scratch registers like |\@tempskipa| % etc. Their default values are both zero. %\begin{verbatim} % { % above-skip =L [0pt] \caption@above@skip , % below-skip =L [0pt] \caption@below@skip , % } %\end{verbatim} % The final argument of |\DeclareTemplate| contains the actual % processing code. We start with looking at the second mandatory % argument (caption number) to find out if it is |\NoValue| and % depending on the result define a helper command |\caption@start|. %\begin{verbatim} % { % \IfNoValueTF{#2} % { \def\caption@start{#1:~} } % { \def\caption@start{#1~#2:~} } %\end{verbatim} % Having dealt with the prelims we now run |\DoParameterAssigments| at % which point the keys of the template are made available, e.g., at % this point all those right hand containers such as % |\caption@above@skip| get assigned the value specified in an % instantiation of the template. (That scheme allows to do preliminary % processing up front, e.g., defaults for the keys could be assigned % prior to that point in which case they are overwritten if the % template instance specifies a different value. the use of specifying % defaults via the |[..]| syntax as done above is slightly faster at % run-time but needs more memory.) %\begin{verbatim} % \DoParameterAssigments %\end{verbatim} % The rest of the code should look familiar to anybody who ever looked % at \texttt{article.cls}. The only point worth mentioning are the % |\relax| commands after |\caption@above@skip| and % |\caption@below@skip|. Since we have decided to use |L| as key type % these commands are macros and not registers containing the % dimensions as strings. This means that we have to be careful to % ensure that \TeX{} knows where the dimension ends. In certain cases % text following such a command might be mistaken as being part of the % dimension (e.g., if followed by the word \texttt{plus}, etc.). In % the code below this could only happen for the second |\vskip| but it % is good practice to always add a terminating |\relax| to avoid such % hidden traps. %\begin{verbatim} % \vskip \caption@above@skip \relax % \sbox \@tempboxa {\caption@start #3} % \ifdim \wd\@tempboxa >\hsize % \caption@start #3\par % \else % \global \@minipagefalse % \hb@xt@\hsize{\hfil\box\@tempboxa\hfil} % \fi % \vskip \caption@below@skip \relax % } %\end{verbatim} % % Why is the above template of not much use? Simply because it doesn't % offer any flexibility to declare different designs. The only % alteration offered to the designer is to modify the space above and % below the caption, e.g., the following declaration would mimic the % definition within the \texttt{article.cls} class of \LaTeXe: %\begin{verbatim} %\DeclareInstance{caption}{article}{toosimple} % { % above-skip = 0pt, % below-skip = 10pt, % } %\end{verbatim} % And that's all that can be manipulated. All items that people asking % to change, e.g., not having a colon after the number, using % different fonts and font sizes, etc.\ are still hard-wired and thus % inaccessible. So we have to do better if we want to make use of the % power the template mechanism offers. % % % % \subsection{Defining a better template} % % First step in defining better templates is to ask ourselves a couple % of questions: % \begin{itemize} % \item What are the main characteristics of the layout the template % is supposed to support? % \item What are the elements that we want to allow (or can allow) the % designer to modify? % \end{itemize} % % Take the first question first: the layout supported by the template % of the previous section had as its main characteristics that it % would center the caption if it would fit in a single line in the % current measure. We could consider this being an unchangable % characteristic of the layout this template produces (and a designer % would need to use a different template of type \texttt{caption} if a % design compatible with this restriction is desired) or we could try % to make our template smarter by adding bells and wistles that allow % the designer to say stuff like: %\begin{verbatim} % one-line-format = \hfil #1 \hfil, %\end{verbatim} % or %\begin{verbatim} % one-line-action = center, %\end{verbatim} % depending on how we intend to offer changing the behavior of the % template. Like when trying to define sensible template types we have % no single road to heaven (and probably as many to hell) --- it has a % lot to do with how we think about design. % % My advice, after having tried to work with these concepts for a % while, is to keep templates simple in so far as that most of not all % attribute for a template should be relevant for the design. In other % words, if you have attributes that, depending on their setting, make % half of the other attributes not applicable then it may be % appropriate to think about providing several templates instead. To % give an example from \LaTeXe: instead of having |\@startsection| % deal with both vertical heads and run-in heads provide individual % templates. (|\@startsection| is this famous command where design % switches are build in by making dimensions negative to signal % something and afterwards use the absolute value.) % Another way to look at this is to say that a template should % normally not contain large amounts of code which is only selected in % a subset of attribute settings. % % As said before there are no golden rules, it is perfectly possible % to make hugely complicated templates that solve every possible % aspect of layout one could think of in one go --- it is just that % with keeping it more simple one can get the same functionality with % less headaches for the template writer as well as the template user % later on. % % Returning to our example: allowing to handle the case of a single % line caption specially could well be considered part of the % template. In contrast: layouts that would put the caption number % sideways, i.e., which would need totally different internal coding % should probably be coded as a separate template of type % \texttt{caption}. % % So for our next example template we settle for the fixed caption % text plus number (if any) being at the beginning of the variable % caption text (coming from the document) and being together formatted % as some sort of a pargraph. In case of the whole caption being a % single line we allow the designer to specify how to lay it out % (e.g., centered, flush left, etc.). If there is a legend it will get % formatted by a vertical space followed by the legend formatted as % another paragraph. % % More precisely we allow for the following bells and wistles: %\begin{verbatim} %\DeclareTemplate{caption}{lesssimple}{4} % { %\end{verbatim} % The designer can specify the space above and below the caption like % we did in our first example. %\begin{verbatim} % above-skip =L [0pt] \caption@above@skip , % below-skip =L [0pt] \caption@below@skip , %\end{verbatim} % Regarding the caption number we support the case where no number is % present (the value being |\NoValue|) as well as the number being % present. For both cases the designer has to specify what formatting % should be attached. By default all is being typeset in the font the % whole caption is presented but if there is a need for it the % designer can use the following keys to attach special formatting % devices to each particular item beside specifying special spacing % information or replacing the default colon after the number with % something else. %\begin{verbatim} % number-format =f2 [#1~#2:~] \caption@number@format, % nonumber-format =f1 [#1:~] \caption@nonumber@format, %\end{verbatim} % If the caption is fitting onto a single line we make it possible % for the designer to specify how this single line should be % positioned (the default is to center the line). %\begin{verbatim} % single-line-format =f1 [\hfil#1\hfil] \caption@single@line@format, %\end{verbatim} % The font for the caption (including the fixed text and the number % unless specified differently above) is going to be the one decided % by the next key. %\begin{verbatim} % caption-font =f0 [\normalfont] \caption@font, %\end{verbatim} % The next attribute deserves some extra explanation: here we make use % of an interface which is explained in more detail when we reveil the % support for galley formatting.\footnote{Guess I have to apologize % for the fact that i partly make use of that interface in this % example while on other occasions (like the use of vertical spacing) % within the example I do not---consistency around midnight is not my % strength I fear (FMi).} In a nutshell the template type \texttt{hj} % (hyphenation \& justification) allows one to define a) the % justification concepts applied to the upcoming paragraphs, e.g., % whether they should be set flush left, adjusted, first line % centered, etc.\ b) the linebreaking strategy used and c) the % hyphenation rules which should apply. All this is done by selecting % an appropriate (predefined) instance of this type as will hopefully % become somewhat clearer in the example instances shown below. %\begin{verbatim} % caption-hj-setup =i {hj} [default] \caption@hj@instance, %\end{verbatim} % In case there is a legend to format we give the designer the % possibility to specify by how much vertical space it should be % separated from the preceding paragraph (i.e., the caption text). The % attributes for font and hj setup are comparable to those for the % caption text itself (except that they will only apply to the % legend). The only addition is the key \texttt{legend-text} which is % allowed to take a fixed text (plus any formating and spacing for it) % which will be added to the front of the legend in case it is % provided at all (by default it is empty). %\begin{verbatim} % legend-sep =L [0pt] \caption@legend@sep , % legend-text =f0 [] \caption@legend@text, % legend-font =f0 [\normalfont] \caption@legend@font, % legend-hj-setup =i {hj} [default] \caption@legend@hj@instance, % } %\end{verbatim} % The actual code for the template should hold few if any % surprises. In fact it is more or less identical to the one of the % first template example, except that now we have now taken out some % of the hardwired decisions and placed them into attributes. %\begin{verbatim} % { % \IfNoValueTF{#2} % { \def\caption@start{\caption@number@format{#1}{#2}} } % { \def\caption@start{\caption@nonumber@format{#1}} } % \DoParameterAssigments % \vskip \caption@above@skip \relax %\end{verbatim} % To properly measure the caption to determine if it fits a single % line we have to set it in the right font, so here as well as below % we have to apply |\caption@font|. %\begin{verbatim} % \sbox \@tempboxa {\caption@font \caption@start #3} % \ifdim \wd\@tempboxa >\hsize % \begingroup % \caption@font \caption@hj@instance % \caption@start #3\par % \endgroup % \else % \global \@minipagefalse % \hb@xt@\hsize{\caption@single@line@format{\box\@tempboxa}} % \fi %\end{verbatim} % To decide whether or not we have to set any legend we have to test % |#4| for being |\NoValue|. This part of the code was not present in % the previous example but otherwise should be straight forward. %\begin{verbatim} % \IfNoValueF{#4} % { % \vskip \caption@legend@sep \relax % \begingroup % \caption@legend@font \caption@legend@hj@instance % \caption@legend@text % #4\par % \endgroup % } % \vskip \caption@below@skip \relax % } %\end{verbatim} % % I wouldn't claim the the above template is good or contains % everything that would be desired and I'm sure that in the end we % will have several such template for typesetting the caption part and % perhaps decide on a different template type in the first place. So % this is only to give a glimpse of how the template interface could % be applied and I hope that reading it can see a) how they can apply % it to other areas as well as see what is wrong with the example % itself. % % To just note one point that i thought of being wrong after writing % the above paragraphs: the key \texttt{single-line-format} was % declared to be a function with one argument with the idea that % besides specifying the single line should be centered (|\hfil|) on % both sides, or flush left, or flush right (|\hfil| on one side) one % could also specify something like %\begin{verbatim} % single-line-format = \hspace{10pt}#1\hfil, %\end{verbatim} % that is a fixed indentation on the left in case where the caption is % a single line. However, of course one can't. Or at least it is not % safe to do so since our test in the code tests the width of the line % without taking into account such a finite fixed space and guess what % might happen? So in summary, flexibility needs some thought and % often some afterthoughts as well --- happy thinking :-) % % % % \subsection{Defining a few instances} % % So let us conclude this example with a few sample instances. We % start with one that repeats what current \LaTeXe{} provides in the % article class. It shows all keys with values. However in fact only % the first key is actually needed since all others are the same as % the default values in the template (and of course a legend is not % specifiable in standard \LaTeX{} coding so those settings simply do % not apply anyway). %\begin{verbatim} %\DeclareInstance{caption}{article}{lesssimple} % { % above-skip = 10pt, % below-skip = 0pt, % number-format = #1~#2:~, % nonumber-format = #1:~, % single-line-format = \hfil#1\hfil, % caption-font = \normalfont, % caption-hj-setup = default, % legend-sep = 0pt, % legend-text = , % legend-font = \normalfont, % legend-hj-setup = default, % } %\end{verbatim} % % The next examples are taken from books on the shelf essentially a % random selection I fear. This one is from \emph{Introduction to % Database Design} by C.~J.~Date and it uses Helvetica for the caption % text with the caption flush left, with the figure and the fixed % string (e.g., `Fig.' in bold face) separated by a quad of space. No % legend either so this is not set up. The \texttt{hj} instance % \texttt{noindentflushleft} is supposed to produce a ragged right paragraph % without any indentation. It would have to be set up elsewhere % (instance to the template of type \texttt{hj}). %\begin{verbatim} %\DeclareInstance{caption}{DATE}{lesssimple} % { % above-skip = 10pt, % below-skip = 0pt, % number-format = \textbf{#1~#2}\quad, % nonumber-format = \textbf{#1}\quad, % single-line-format = #1\hfil, % caption-font = \fontfamily{phv} \normalfont, % caption-hj-setup = noindentflushleft, % } %\end{verbatim} % % The final example is from the book ``Methods of Book Design'' by % H.~Williamson which sets the caption centered if it fits a single % line but adjusted as a paragraph without any indentation if longer % than a single line. It uses old style numerals followed by a period % for the number (though the example isn't quite right as i guess the % text font used already has oldstyle numerals as default, so % |\oldstylenums| is in fact not necessary). %\begin{verbatim} %\DeclareInstance{caption}{WILLIAMSON}{lesssimple} % { % above-skip = 10pt, % below-skip = 0pt, % number-format = #1~\oldstylenums{#2}.~, % nonumber-format = #1~, % single-line-format = \hfil#1\hfil, % caption-font = \normalfont, % caption-hj-setup = noindentadjusted, % } %\end{verbatim} % % % % \section{Notes} % % \subsection{Note on multi-valued parameters} % % % The following code\footnote{docu taken from trial implementation in % xlists.dtx, FMi} implements for registers (ie L,l,C,c keys) and % for names (ie n key) a multi-selection mechanism of the following % form: % \begin{verbatim} % key = \MultiSelection \@listdepth { % \DelayEvaluation {2.5em}, % 20pt + 34pt } % { \DelayEvaluation {1em} }, % \end{verbatim} % where the first argument to |\MultiSelection| is a counter, the % second argument is a comma separated list of values denoting the % values for the cases 1, 2,\ldots, and the third argument contains % the value for all other cases. % % The values are evaluated at declaration time in case of registers % and therefore can contain calc expressions as well as % |\DelayEvaluation|. % % Due to the implementation the case list is not allowed to have a % trailing comma! And of course no checks are made whatsoever :-( % % A probably much nicer syntax would be something like this: % \begin{verbatim} % key = \MultiSelection { % selector = \@listdepth, % 1 = \DelayEvaluation {2.5em}, % 2 = 20pt + 34pt, % else = \DelayEvaluation {1em} % }, % \end{verbatim} % but i found that too difficult to implement right now. % % I think it should also be considered if this kind of thing should be % a generally available feature on all key types especially on the % f\meta{number} ones. % % Anyway it is what i need for lists right now and as such it is % sufficient. % % % \subsection{Notes on template restriction} % % Possible semantics: % % a: just:-) changes the defaults ie the new template has as % defaults those of its source as modified by the supplied % keyvals; % % b: similar to a: but also removes some keywords ie the new template % will not accept the keywods whose values are set by the suppied % keyvals; % % c: plan C. % % % Towards an implementation of b: but without a restriction on what % keys appear where. % % % % % \subsection{Open issues} % % In this section unresolved issues or ideas to think about and % perhaps implement are collected. There is no particular order to % them. % % \begin{itemize} % \item The order of arguments in |\UseCollection| is illogical in my % eyes! A collection typically modifies the behavior of several % types and thus should perhaps be first (as it is in the % |\DeclareCollectionInstance| case). Or not, or what? % % \item How should |\IfExistsInstanceTF| behave for Collection % instances? Do we need a special check for those or a default % action? Or do we need an additional test for the existence of % collection instances? % % \item It was suggested that the template type declaration should get % another argument in which (in?)formally the semantics for the % template types are described, e.g., data type of arguments, % resulting output, \ldots{} (somewhat like the description arguments % for functions and variables in Emacs-Lisp). The advantage being % that this helps employing the templates better as well as perhaps % guiding context sensitive editors to support the work with such % templates (e.g., providing help texts). % % \item The same might be of interest for the keys of individual % templates though here syntax support is already available to some % extend by the declaration of key types. % % \item There might be a need to distinguish between \TeX's dimen and % skip registers. Right now this is not done and both |l| and |L| % accepts what \LaTeX{} calls ``rubber length'' specifications. % % \item The type |b| can probably vanish. It is equivalent to % specifying the mutators of a |\newif| command in the brace groups, % e.g. %\begin{verbatim} % numbered-boolean =b [true] @heading@nums, % numbered-boolean =s [true] {\@heading@numstrue} % {\@heading@numsfalse}, %\end{verbatim} % % \item See issue raised about syntax (and semantics) for % |\Multiselection|. % % \end{itemize} % % \StopEventually{} % % \section{Implementation} % \begin{macrocode} %<*package> % \end{macrocode} % % \begin{macrocode} \RequirePackage{ldcsetup} % \end{macrocode} % % Ignore white space in this package. % \begin{macrocode} \IgnoreWhiteSpace % \end{macrocode} % % Declare a private token register for building parameter lists. % Having the number saves a few expandafters % (probably not needed in the end). % \begin{macrocode} \newtoks\TP@toks \newtoks\TP@toksb \newtoks\TP@toksc % \end{macrocode} % % % \begin{macro}{\functiondefine} % |\def| setup with a latex style `number of arguments' argument. % definition setup left in toksb for possible future use. % \begin{macrocode} \def\functiondefine#1#2#3{% \def\@tempa##1#1##2##{% \TP@toksb\expandafter{\expandafter\def\expandafter#2\@gobble##1#1} \the\TP@toksb}% \@tempa0##1##2##3##4##5##6##7##8##9{#3}} % \end{macrocode} % \end{macro} % % \begin{macro}{\TP@DCI} % Declare a command name to be an instance of a template % ie with a particular setting of the parameters.\\ % |#1| internal command name for instance to be (globally) declared\\ % |#2| template type/template name\\ % |#3| key value assignments for parameters of |#2| % \begin{macrocode} \def\TP@DCI#1#2#3{ \begingroup \TP@get@restrictions {#2} % puts stuff in \TP@toks \toks@\expandafter\expandafter\expandafter {\csname TPD>/#2\endcsname\relax\relax} \setkeys{\the\TP@toksc} % temp OK? {#3} % adds stuff to \TP@toks \expandafter\TP@add@default \the\toks@ % prepends stuff to \TP@toks \xdef#1{ \expandafter\ifx\csname TP>/#2\endcsname\TP@dpa \the\TP@toks \else \noexpand\TP@assignments{\the\TP@toks} \expandafter\noexpand\csname TP>/#2\endcsname \fi} \endgroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\TP@dpa} % \begin{macrocode} \long\def\TP@dpa{\DoParameterAssignments} % \end{macrocode} % \end{macro} % % \begin{macro}{\TP@add@default} % \begin{macrocode} \def\TP@add@default#1#2{ \ifx#1\relax \else \@temptokena{#2} \edef\@tempa{{\the\@temptokena\the\TP@toks}} \TP@toks\@tempa \expandafter\TP@add@default \fi} % \end{macrocode} % \end{macro} % % % \begin{macro}{\UseTemplate} % |{type}{templatename}{keyval}| % Directly use a template with a particular parameter setting. % This is also picked up if used in a nested fashion inside a parameter % list.\\ % |#1| type of a template.\\ % |#2| name of a template.\\ % |#3| key value assignments for parameters of |#1|. % \begin{macrocode} \def\UseTemplate#1#2#3{ \TP@get@restrictions {#1/#2} % from here ... \toks@\expandafter\expandafter\expandafter {\csname TPD>/#1/#2\endcsname\relax\relax} \setkeys{\the\TP@toksc}{#3} \expandafter \TP@add@default \the\toks@ % to here is : % Shared with \def\DeclareCommandInstance \TP@push \csname TP>/#1/#2\endcsname} % \end{macrocode} % \end{macro} % % \begin{macro}{\DoParameterAssignments} % Acces the list stored in |\TP@toks|. % \begin{macrocode} \def\DoParameterAssignments{ \expandafter\TP@pop\the\TP@stack\@@} % \end{macrocode} % % \end{macro} % % \begin{macro}{\TP@pop} % \begin{macrocode} \def\TP@pop#1#2\@@{ \global\TP@stack{#2} #1} % \end{macrocode} % \end{macro} % % \begin{macro}{\TP@stack} % \begin{macrocode} \newtoks\TP@stack % \end{macrocode} % \end{macro} % % \begin{macro}{\TP@stack} % \begin{macrocode} \global\TP@stack{\relax}% avoid brace loss % \end{macrocode} % \end{macro} % % \begin{macro}{\TP@assignments} % Access the list stored in |\TP@toks|. % \begin{macrocode} \def\TP@assignments{ \afterassignment\TP@push\TP@toks} % \end{macrocode} % % \end{macro} % % \begin{macro}{\TP@push} % \begin{macrocode} \def\TP@push{ \global\TP@stack\expandafter {\expandafter{\the\expandafter\TP@toks\expandafter} \the\TP@stack}} % \end{macrocode} % \end{macro} % % \begin{macro}{\DeclareTemplateType} % |{type}{nofarg}| % \begin{macrocode} \def\DeclareTemplateType#1#2{ \expandafter\def\csname TP@<#1>\endcsname{{}#2}} % \end{macrocode} % \end{macro} % % % \begin{macro}{\TP@prefix} % |{type}| returns prefix for csnames for type, based on current collection. % \begin{macrocode} \def\TP@prefix#1{ <\expandafter\expandafter\expandafter \@firstoftwo\csname TP@<#1>\endcsname>#1/} % \end{macrocode} % % \end{macro} % % \begin{macro}{\TP@args} % |{type}| returns arg count for type, % \begin{macrocode} \def\TP@args#1{ \expandafter\expandafter\expandafter \@secondoftwo\csname TP@<#1>\endcsname} % \end{macrocode} % \end{macro} % % % \begin{macro}{\DeclareTemplate} % |{type}{templatename}{nofarg}{keywordspec}{code}| % \begin{macrocode} \long\def\DeclareTemplate#1#2#3#4#5{ \@ifundefined{TP@<#1>} {\undefinedtype\DeclareTemplateType{#1}#3} {\ifnum#3=\TP@args{#1}\relax\else \BadArgCount\fi} % \end{macrocode} % Parse the key declaration, and execute the list with a suitable % definition of |\KV@elt|. % \begin{macrocode} \let\KV@elt\TP@elt \def\KV@default@elt##1{ \PackageError{template}{Missing = after ##1}\@ehd} \def\TP@name{#1/#2} \toks@{} \KV@parse{#4} % \end{macrocode} % % Define the defaults % \begin{macrocode} \expandafter\edef\csname TPD>/\TP@name\endcsname{\the\toks@} % \end{macrocode} % % Define the template % \begin{macrocode} \expandafter\newcommand\csname TP>/\TP@name\endcsname[#3]{#5}} % \end{macrocode} % \end{macro} % % \begin{macro}{\TP@elt} % The list of undefined keys and values is put in the list of the form\\ % |\KV@elt|\marg{key}\marg{val}%^^A % |\KV@elt|\marg{key}\marg{val}\ldots\\ % So just need to give this macro a suitable definition. We just need % to look at the first token of the value, to see what sort of key % it is, so call a helper function to split that off. % \begin{macrocode} \def\TP@elt#1#2{% \let\TP@global\@empty \TP@do{#1}#2\TP@do} % \end{macrocode} % \end{macro} % % \begin{macro}{\TP@f@shift} % Helper for |\TP@do|. % \begin{macrocode} \def\TP@f@shift#1#2{% \TP@testopt{#1}{\TPkeycommand{#1}{#2}}} % \end{macrocode} % \end{macro} % % \begin{macro}{\TP@i@shift} % Helper for |\TP@do|. % \begin{macrocode} \def\TP@i@shift#1#2{% \TP@testopt{#1}{\TP@instance{#1}{#2}}} % \end{macrocode} % % declaration |hd =i{head} \fooo| \\ % use |hd = mine|\\ % makes |\fooo| shorthand for |\UseInstance{head}{mine}| % % also allowed: |hd = \UseTemplate{head}{...}{...}|\\ % in case you want to use an unnamed instance of type |head| % in this place. % \end{macro} % % \begin{macro}{\TP@instance} % \begin{macrocode} \def\TP@instance#1#2#3{ \TP@define@key{#1}{ \TPinstance#3{#2}{##1}}} % \end{macrocode} % \end{macro} % % \begin{macro}{\TPinstance} % \begin{macrocode} \def\TPinstance#1#2#3{ \expandafter\ifx\@car#3.\@nil\UseTemplate \typeout{\string\UseTemplate\space seen} % \end{macrocode} % % code below from |\TPkeycommand| (should be combined and cleaned up) % at this point one should also check if first arg of |\UseTemplate| % corresponds to |#2| and if not complain (not done) % % \begin{macrocode} {\TP@fudge#3} \expandafter\addto@hook\expandafter\TP@toks\expandafter{ \expandafter\KV@toks\expandafter{\TP@gtemp} \edef#1{\the\KV@toks}} \else \@letinstance#1{#2}{#3} \expandafter\expandafter\expandafter\addto@hook \expandafter\expandafter\expandafter\TP@toks \expandafter\expandafter\expandafter{ \@letinstance#1{#2}{#3}} \fi} % \end{macrocode} % \end{macro} % % % \begin{macro}{\TP@do} % Case switch on the possible key types. % \begin{macrocode} \def\TP@do#1#2#3\TP@do{ \ifx#2f \TP@f@shift{#1}#3\@@ \else\ifx#2n \TP@testopt{#1}{\TPnamecommand{#1}}#3\@@ \else\ifx#2l \TP@testopt{#1}{\TP@register\setlength{#1}}#3\@@ \else\ifx#2L \TP@testopt{#1}{\TP@fakeregister\setlength\fake@length {#1}}#3\@@ \else\ifx#2c \TP@testopt{#1}{\TP@register\SetInternalCounter{#1}}#3\@@ \else\ifx#2C \TP@testopt{#1}{\TP@fakeregister\SetInternalCounter\@tempcnta {#1}}#3\@@ \else\ifx#2b \TP@testopt{#1}{\TP@setboolean{#1}}#3\@@ \else\ifx#2s \TP@testopt{#1}{\TP@booltest{#1}}#3\@@ \else\ifx#2g \TP@testopt{#1}{\TP@setgeneral{#1}}#3\@@ \else\ifx#2x \TP@testopt{#1}{\TP@setx{#1}}#3\@@ \else\ifx#2i \TP@i@shift{#1}#3\@@ \else\ifx#2+ \def\TP@global{\addto@hook\TP@toks{\global}} \TP@do{#1}#3\TP@do \else \PackageError{template}{Unknown~key~type~ (#2)~for~#1}\@eha \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi} % \end{macrocode} % \end{macro} % % \begin{macro}{\TP@testopt} % \begin{macrocode} \def\TP@testopt#1#2{ \@ifnextchar[%] {\TP@test@pt{#1}{#2}} {\TP@zap@@{#2}}} % \end{macrocode} % \end{macro} % % \begin{macro}{\TP@zap@@} % \begin{macrocode} \def\TP@zap@@#1#2\@@{ #1{#2}} % \end{macrocode} % \end{macro} % % \begin{macro}{\TP@test@pt} % \begin{macrocode} \def\TP@test@pt#1#2[#3]#4\@@{ #2 {#4} \begingroup \TP@toks{} \let\TP@remove\@gobble \csname KV@\TP@name @#1\endcsname{#3} \expandafter \endgroup \expandafter \toks@\expandafter{ \csname KV@\TP@name @#1\expandafter\endcsname\expandafter {\the\expandafter\TP@toks\expandafter}\the\toks@}} % \end{macrocode} % \end{macro} % % \begin{macro}{\TP@setgeneral} % \begin{macrocode} \def\TP@setx#1#2{ \TP@define@key{#1}{\addto@hook\TP@toks{#2}}} % \end{macrocode} % \end{macro} % % \begin{macro}{\TP@setgeneral} % \begin{macrocode} \def\TP@setgeneral#1#2{ \TP@define@key{#1}{#2}} % \end{macrocode} % % \end{macro} % % \begin{macro}{\TP@setboolean} % \begin{macrocode} \def\TP@setboolean#1#2{ \expandafter\let\csname if#2\endcsname\iftrue \TP@define@key{#1}{ \TPsetboolean{#2}{##1}} } % \end{macrocode} % \end{macro} % % \begin{macro}{\TPsetboolean} % Modify so the boolean does not need to have been % declared with |\newif| % \begin{macrocode} \def\TPsetboolean#1#2{ \expandafter\ifx\csname if#2\endcsname\relax \PackageError{template}{Bad~boolean~setting~#1=#2}\@eha \else \expandafter\let\csname if#1\expandafter\endcsname \csname if#2\endcsname \expandafter\addto@hook\expandafter\TP@toks\expandafter{ \expandafter\let \csname if#1\expandafter\endcsname\csname if#2\endcsname} \fi} % \end{macrocode} % % \end{macro} % % \begin{macro}{\TP@booltest} % \begin{macrocode} \def\TP@booltest#1#2{ \TP@define@key{#1}{ \TPbooltest{##1}#2}} % \end{macrocode} % \end{macro} % % \begin{macro}{\TP@true} % \begin{macrocode} \def\TP@true{true} % \end{macrocode} % \end{macro} % % \begin{macro}{\TPbooltest} % \begin{macrocode} \def\TPbooltest#1#2#3{ % no error check on this yet. \def\@tempa{#1} \ifx\@tempa\TP@true \addto@hook\TP@toks{#2} \else \addto@hook\TP@toks{#3} \fi} % \end{macrocode} % \end{macro} % % \begin{macro}{\TP@register} % This is normally called automatically by |\DeclareTemplate|. % % Command for setting a template attribute whose name % corresponds directly to a tex count or length register\\ % |#1| the fuction to set the value eg \setlength.\\ % |#2| key name.\\ % |#3| the register to set. % % This command \emph{fully evaluates} the argument at declare time, % and assigns the value to the register. It also passes an assignment % of the register to the final value into the parameter list for the % template. % % If the value is a call to |\DelayEvaluation|, don't evaluate it now, % just pass the whole assignment to the template. % % [Note that the code below contains some : being used in csnames in other files % this is currently being allowed by default but in this one it is right now % manually added --- need fixing either way] % \begin{macrocode} \catcode`\:=11\relax \def\TP@register#1#2#3{ \TP@define@key{#2}{ \expandafter\ifx\@car##1\@nil\DelayEvaluation \addto@hook\TP@toks{#1#3{##1}} \else % \end{macrocode} % % % check for |\MultiSelection| creeping up and if so add something like % % \begin{verbatim} % \setlength\register{\ifcase\selector \or value1 \or value2 % ... \else valueotherwise \fi} % \end{verbatim} % to |\TP@toks|. % % \begin{macrocode} \expandafter\ifx\@car##1..\@nil\MultiSelection \begingroup \TP@multi#1#3##1 \endgroup % \end{macrocode} % % % there are probably better ways to do this :-) % % \begin{macrocode} \expandafter\in@\expandafter\DelayEvaluation \expandafter{\the\TP@multi@toks} \ifin@ \addto@hook:No\TP@toks {\expandafter#1\expandafter#3\expandafter {\the\TP@multi@toks}} \else \addto@hook:No\TP@toks {\expandafter #3 \expandafter= \the\TP@multi@toks\relax} \fi % \end{macrocode} % % % otherwise do as before % % \begin{macrocode} \else #1#3{##1} \addto@hook:No\TP@toks {\expandafter #3 \expandafter= \the#3\relax} \fi\fi}} % \end{macrocode} % \end{macro} % % % % % \begin{macro}{\addto@hook:No} % \begin{macrocode} \def\addto@hook:No#1#2 { \expandafter\addto@hook\expandafter#1\expandafter{#2}} \catcode`\:=12\relax % \end{macrocode} % \end{macro} % % % % % \begin{macro}{\DelayEvaluation} % \begin{macrocode} \let\DelayEvaluation\@firstofone % \end{macrocode} % \end{macro} % % \begin{macro}{\TPkeycommand} % Same for macro names. Again usually called automatically when % declaring a new template.\\ % |#1| the key.\\ % |#2| Determines how many arguments the function should have.\\ % |#3| The macro to be defined. % % If the `|##1|`, the value passed as the argument of the key |#1| % to the macro |#3| is invoked starts with |\FunctionInstance|, then a % special procedure is taken. Instead of defining a macro with the % specified number of arguments, the paramater list of the nested % function instance is parsed, and |#3| is defined to be a macro % expanding to that instance. In this case the specified template % is responsible for picking up the requested number of % arguments. (This is \emph{not} checked.) % \begin{macrocode} \def\TP@define@key#1#2{% \expandafter\def \csname KV@\TP@name @#1\expandafter\endcsname \expandafter##\expandafter1 \expandafter{ \expandafter\TP@remove \csname KV@\TP@name @#1\expandafter\endcsname \TP@global #2}} % \end{macrocode} % \end{macro} % % \begin{macro}{\TP@remove} % \begin{macrocode} \def\TP@remove#1{ \def\@tempa##1#1##2##3#1##4\@@{ \toks@{##1##3}} \expandafter\@tempa\the\toks@#1\relax#1\@@} % \end{macrocode} % \end{macro} % % \begin{macro}{\TPkeycommand} % \begin{macrocode} \def\TPkeycommand#1#2#3{ \TP@define@key{#1}{ % \end{macrocode} % % |##1| can either be arbitrary inline code, in which case it will be % defined with |\newcommand[val]| so it needs to use |#1| -- |#val|. % % define it locally here % \begin{macrocode} \functiondefine#2#3{##1} % \end{macrocode} % % \begin{macrocode} \expandafter\addto@hook\expandafter\TP@toks\expandafter{ \the\TP@toksb{##1}} } } % \end{macrocode} % \end{macro} % % % % \begin{macro}{\TPnamecommand} % Here is the extended version that tries to deal with % |\MultiSelection|. % % In case of `n' keys there is no evaluation at declaration time so it % is not sensible to look for |\DelayEvaluation|. For this reason as % well as for the fact that |\TP@multi| above assumes that it deals % with registers that can be accessed via |\the| we have to use a % different command to handle the |\MultiSelection| args but % it is essentially doing the same. % % \begin{macrocode} \catcode`\:=11\relax \def\TPnamecommand#1#2{ \TP@define@key{#1}{ \expandafter\ifx\@car##1..\@nil\MultiSelection \begingroup \TP@multi@name##1 \endgroup \addto@hook:No\TP@toks {\expandafter\def\expandafter#2\expandafter {\the\TP@multi@toks}} \else \def#2{##1} % setting it? \addto@hook\TP@toks{\def#2{##1}} \fi } } \catcode`\:=12\relax % \end{macrocode} % \end{macro} % % \begin{macro}{\TP@multi@name} % \begin{macrocode} %\catcode`\:=12\relax \def\TP@multi@name #1#2#3#4{ \global\TP@multi@toks{\ifcase #2} \@for\next:=\@empty #3\do{ \TP@do@multi\next } \global\addto@hook\TP@multi@toks{\else #4\fi} } %\catcode`\:=11\relax % \end{macrocode} % \end{macro} % % % % % % % % % \begin{macro}{\DeclareInstance} % |{type}{instname}{templatename}{keyval}| % \begin{macrocode} \def\DeclareInstance{\DeclareCollectionInstance{}} % \end{macrocode} % \end{macro} % % \begin{macro}{\DeclareCollectionInstance} % |{collection}{type}{instname}{templatename}{keyval}| % \begin{macrocode} \long\def\DeclareCollectionInstance#1#2#3#4{ \expandafter\TP@DCI\csname<#1>#2/#3\endcsname{#2/#4}} % \end{macrocode} % \end{macro} % % \begin{macro}{\UseCollection} % |{type}{collection}| % \begin{macrocode} \def\UseCollection#1#2{ \expandafter\edef\csname TP@<#1>\endcsname{ {#2} \TP@args{#1}}} % \end{macrocode} % \end{macro} % % \begin{macro}{\@letinstance} % |\internalcommand{type}{instname}| % \begin{macrocode} \def\@letinstance#1#2#3{ \expandafter\let\expandafter#1\csname \@ifundefined{\TP@prefix{#2}#3} {<>#2/} {\TP@prefix{#2}} #3 \endcsname} % \end{macrocode} % \end{macro} % % \begin{macro}{\UseInstance} % |{type}{instname}| % \begin{macrocode} \def\UseInstance#1#2{ \@letinstance\@tempa{#1}{#2} \ifx\@tempa\relax \INSTANCEundefined \else \expandafter\@tempa \fi} % \end{macrocode} % \end{macro} % % \begin{macro}{\TP@fudge} % \begin{macrocode} \long\def\TP@fudge#1#2#3{% \TP@DCI\TP@gtemp{#2/#3}} % \end{macrocode} % \end{macro} % % \begin{macro}{\ShowTemplate} % Some extension to |\ShowTemplate| so that we also get to see the % restrictions if any % \begin{macrocode} \def\ShowTemplate#1#2{ \typeout{*******~ Template:~ #1/#2~ *******} \typeout{*} \typeout{*~ Defaults:} \typeout{*} \typeout{\string\TPD>/#1/#2= \expandafter\meaning\csname TPD>/#1/#2\endcsname} \typeout{*} \typeout{*~ Restrictions:} \typeout{*} \typeout{\string\TPR>/#1/#2= \expandafter\meaning\csname TPR>/#1/#2\endcsname} \typeout{*} \typeout{*~ Body:} \typeout{*} \expandafter\show\csname TP>/#1/#2\endcsname} % \end{macrocode} % \end{macro} % % % \begin{macro}{\ShowCollectionInstance} % \begin{macrocode} \def\ShowCollectionInstance#1#2#3{ \typeout{*******~ Instance:~ <#1>#2/#3~ *******} \typeout{*} \expandafter\show\csname <#1>#2/#3\endcsname} \def\ShowInstance{\ShowCollectionInstance{}} % \end{macrocode} % \end{macro} % % \begin{macro}{\TP@fakeregister} % |{setcomand}{privateregister}{key}{internalcode}| % \begin{macrocode} \catcode`\:=11\relax \def\TP@fakeregister#1#2#3#4{ \TP@define@key{#3}{ \expandafter\ifx\@car##1..\@nil\DelayEvaluation % \end{macrocode} % In the v0.08 version of \texttt{template.dtx} a % |\DelayEvaluation| for a faked register would simply be equiv to % a |\def| (code is below commented out). The negative side effect % of this is that something like |=L| used with |\DelayEvaluation| % would not allow for calc syntax since it would end up as % |\def|\allowbreak|\foo|\allowbreak|{a+b}|. The code below changes % this to first assign to a scratch register (at runtime) and then % do an |\edef|. Could be coded differently to save space (at cost % of time) % \begin{macrocode} % \addto@hook\TP@toks{\def#4{##1}} \addto@hook\TP@toks{#1#2{##1}\edef#4{\the#2}} \else % \end{macrocode} % % % Otherwise same game for fake registers except that instead of % passing the register to |\TP@multi| we pass a temp fake one and % doing a def instead of using |\setlength| or |\setcounter| % % and i haven't done the |\DelayEvaluation| bit for that case! as % i'm not sure what the best approach is for those % things\footnote{we might disallow it for that case in general --- % not a nice rule but an explainable one} % % \begin{macrocode} \expandafter\ifx\@car##1..\@nil\MultiSelection \begingroup \TP@multi#1#2##1 \endgroup \addto@hook:No\TP@toks {\expandafter\def\expandafter#4\expandafter {\the\TP@multi@toks}} \else #1#2{##1} \addto@hook:No\TP@toks {\expandafter \def \expandafter #4 \expandafter {\the#2}} \fi\fi}} \catcode`\:=12\relax % \end{macrocode} % \end{macro} % % % \begin{macro}{\TP@multi@toks} % \begin{macrocode} \newtoks\TP@multi@toks % \end{macrocode} % \end{macro} % % \begin{macro}{\TP@multi} % \marg{operation} \marg{register} |\MultiSelection| % \marg{selector} \marg{case-list} \marg{else-case} % % This command builds up the |\ifcase| code from the three arguments % of |\MultiSelection| and stores it in |\TP@multi@toks|. This code is % supposed to be run in a group so a) we don't have to initialise % |\TP@multi@toks| and b) all changes to the used registers not % affecting the outside. % % Warning: this code uses |\@for| which will not work if put into files where % ``:'' was made a letter! % % \begin{macrocode} %\catcode`\:=12\relax \def\TP@multi #1#2#3#4#5#6{ \global\TP@multi@toks{\ifcase #4} \@for\next:=\@empty #5\do{ \expandafter \expandafter\expandafter\ifx\expandafter \@car\next..\@nil\DelayEvaluation \TP@do@multi\next \else #1#2{\next} \TP@do@multi{\the#2} \fi } \global\addto@hook\TP@multi@toks{\else #6\fi} } %\catcode`\:=11\relax % \end{macrocode} % % Since we intend to add |\or| to |\TP@multi@toks| within the |\@for| % loop we have to hide it carefully or else we will get some unmatched % conditionals. % \end{macro} % % \begin{macro}{\TP@do@multi} % \begin{macrocode} \def\TP@do@multi#1{ \global\expandafter\addto@hook\expandafter\TP@multi@toks \expandafter{\expandafter\or #1 } } % \end{macrocode} % \end{macro} % % Since i like to set things like |item-label-text| using this % mechanism i need to handle the `n' key specially. % % Actually i could have probably extended |\TPkeycommand| thus making % this generally available to all f\meta{number} keys but was too lazy % (or too stupid) to get it right first time so settled for the simple % solution. % % So |\TP@do| now calls |\TPnamecommand| for the `n' key. looks like % this thus be fixed some time soon % % % % % % % \begin{macro}{\fake@length} % \begin{macrocode} \newlength\fake@length % \end{macrocode} % \end{macro} % % % \begin{macro}{\IfExistsInstanceTF} % tests that there is a \emph{default} definition % taken from xinitials.dtx: % \begin{macrocode} \def\IfExistsInstanceTF#1#2{ \expandafter\ifx\csname <>#1/#2\endcsname\relax \expandafter\@secondoftwo \else \expandafter\@firstoftwo \fi} % \end{macrocode} % % FMi: what happens if we are in collection FOO and there exists an % instance I for type T within this collection but there doesn't exist % an instance in the empty collection? % % What would happen if \ldots\ --- not clear to me what the sematics % really should be. The code below is not better only different( and % slower).\footnote{fix semantics} % \begin{macrocode} \def\IfExistsInstanceTF#1#2{ \@letinstance\@tempa{#1}{#2} \ifx\@tempa\relax \expandafter\@secondoftwo \else \expandafter\@firstoftwo \fi} % \end{macrocode} % \end{macro} % % \begin{macro}{\DeclareRestrictedTemplate} % Setting it up: % %| \DeclareRestrictedTemplate|\\ % |{T-type} {new-T-name} {source-T-name} {keyvals}| % % This uses the same code as {T-type} {source-T-name} but adds % settings from {keyvals} % \begin{macrocode} \def\DeclareRestrictedTemplate#1#2#3#4{ % CCC do we need a group here?? \letcc { TPD>/#1/#2 } { TPD>/#1/#3 } \letcc { TP>/#1/#2 } { TP>/#1/#3 } \TP@get@restrictions {#1/#3} % puts stuff in \TP@toks \setkeys{\the\TP@toksc} % temp OK? {#4} % adds stuff to \TP@toks \TP@store@restrictions {#1/#2}{#1/#3}} % stores the contents of % \TP@toks % \end{macrocode} % \end{macro} % % \begin{macro}{\letcc} % \begin{macrocode} \def\letcc#1#2{ \expandafter \let \csname #1 \expandafter \endcsname \csname #2 \endcsname} % \end{macrocode} % \end{macro} % % Internals: % % \begin{macro}{\TP@get@restrictions} % These could probably be inlined, even when they do something! % \begin{macrocode} \def\TP@get@restrictions#1{ % Returns to \TP@toks the restrictions % stored in the TP-structure (at present % in YAM) of the template #1 \@ifundefined {TPR>/#1} {\TP@toks {}} {\TP@toks \expandafter\expandafter\expandafter {\csname TPR>/#1\endcsname}} \@ifundefined {TPO>/#1} {\@namedef {TPO>/#1} {#1} \TP@toksc {#1} } % temp OK? {\TP@toksc \expandafter\expandafter\expandafter {\csname TPO>/#1\endcsname} }} % \end{macrocode} % \end{macro} % % \begin{macro}{\TP@store@restrictions} % \begin{macrocode} \def\TP@store@restrictions#1#2{ % Stores the contents of \TP@toks % in the TP-structure (at present % in YAM) of the template #1 \expandafter\edef\csname TPR>/#1\endcsname{\the\TP@toks} \@ifundefined{TPO>/#2} {\@namedef{TPO>/#1}{#2}} {\letcc{TPO>/#1}{TPO>/#2}}} % \end{macrocode} % \end{macro} % % \begin{macrocode} % % \end{macrocode} % % \Finale %