## LATEX-L@LISTSERV.UNI-HEIDELBERG.DE

 Options: Use Forum View Use Monospaced Font Show Text Part by Default Condense Mail Headers Message: [<< First] [< Prev] [Next >] [Last >>] Topic: [<< First] [< Prev] [Next >] [Last >>] Author: [<< First] [< Prev] [Next >] [Last >>]

Some months ago I pointed out in another message that I wanted to make
some remarks about templates. Well, we all know the pace of this list,
where months play the rôle of days, so here it is:

There is something about how collections work that puzzles me.
Currently, if one wishes to use the instance "iname" of the type "type",
one has to write

\UseInstance{type}{iname},

no matter whether the instance was declared via \DeclareInstance or via
\DeclareCollectionInstance. So, ¿what are the collections for? I know,
to restrict the use of an instance to a particular collection.

Form my point of view the existence of instances should be independent
from the association of particular instances with certain collections.
Thus, a file may store the declaration of a bunch of instances for a
particular template, say, for a heading formating template. Supose they
are called ''simple", "beautiful", "front1", "front2", where the names
of the last ones suggest that they are specifically designed to be used
in front matters. And suppose that for a particular work or in a
particular series of books the designer decides to make use of the
instance "front1" to format the headings at the frontmatter. Then he may
write

and at some point in the document near the beginning the author or, more
likely, a macro defined by the designer, writes

so that from now on (normal scoping rules) the instance to be used to
format headings is the corresponding to the collection frontmatter. An
so when the time comes to create a heading (posibly inside another
macro) one simply writes

where the empty second argument means: "Use the instance that is in
force for the type heading", and an error is issued if such an instance
doesn't exist, i.e., if there has not been a previous call to
\UseCollection where the first argument is "heading" and also a suitable
call to \AssociateInstanceCollection. This allows the creation of very
simple high level commands. Think for example about formating a caption.
One may simply use always \UseInstance{caption}{}, and the setting of
the collection in force will be made by the commands that format the
particular float: figures, tables, pieces of code,... Thus, once the
skeleton is written, a separate format-defining file will consist of
severall calls to \AssociateInstanceCollection{type}{collection}{iname}
(among other tings), setting the appearance of the documment.

Furthermore, one could write

\SetCollection{frontamtter}

in order to set in force all the instances of all types that have been
associated to the collection.

I think it wouldn't be very difficult to implement this. At the present
time the command that gets executed when \UseInstance is called is

\<coll>type/iname,

wher "coll" may be empty. We can have simply \type/iname. The definition
of \AssociateInstanceCollection would then be:

\def\AssociateInstanceCollection#1#2#3{    % type, collection, iname
\let:cc{#1/??_#2}{#1/#3}
}

Where it can be seen that ??_coll is a faked iname that gets assigned to
a real iname via \AssociateInstanceCollection.
The code for \UseCollection is then

\def\UseCollection#1#2{    % type, collection
\let:cc{#1/???}{#1/??_#2}
}

And so type/??? means "current iname according to the collection in
force for this type". This definition needs a check to test if
\type/??_coll has been associated to a real iname, and if not issue an
error or define \type/??_coll to issue an error. This last option allows
the association to take place latter, since \UseCollection may appear in
the definition of a macro that expects the association to be performed
before the macro is called. It will also complicate the initial check
for \type/??_coll, but see below.

We need also, at the moment of declaring a type, to define \type/??? to
issue an error. If we do not the user will get the error "the instance
??? for type heading is not defined", or something like that.

The command \SetCollection executes, if it is defined,
\TP_tlp_set_collection_coll (coll is #1):

\def:Npn\SetCollection#1{
\cs:w TP_tlp_set_collection_#1\cs_end:
}

\TP_tlp_set_collection_coll will get dinamically defined by adding code
to it every time we call \AssociateInstanceCollection. We have then to
modify the previous definition of this macro. It may also be useful to
know which instance is associated to a particular collection, if any. In
particular, it is necesary for the check needed at \SetCollection:

\def:Npn\AssociateInstanceCollection#1#2#3{    % type, collection, iname
\let:cc{#1/??_#2}{#1/#3}

%Here we localy (important) add the command \UseCollection{#1}{#2} to
de definition of \TP_tlp_set_collection_coll
\tlp_put_right:cn{TP_tlp_set_collection_#2}{\UseCollection{#1}{#2}}

%Record that type+collection is from now on iname:
\def:cpn{TPC>/#1/#2}{#3}        %Note the order #1/#2. We always
regard a collection as an indirect iname for types.
}

And the definition of \UseCollection will then be:

\def:Npn\UseCollection#1#2{    % type, collection
\expandafter\ifx\csname TPC>/#1/#2\endcsname\relax    %define #1/??_#2
to be an error message
\def:cpn{#1/??_2}{PackageError{template}{There is not defined any
instance of type #1 to be used with the collection #2}}
\else
\let:cc{#1/???}{#1/??_#2}
\fi
}

We need also to modify slightly the definition of UseInstance to check
if the second argument is empty, and if so execute \type/??? (i.e.

It is important that the list TP_tlp_set_collection_coll (for every
particular coll) be updated locally, as the collection in force is also
associated locally. It works properly because \UseCollection{type}{coll}
is appended to the right, so that local settings override those from an
outer scope. We cannot provide a global \gAssociateInstanceCollection,
since a global setting of TP_tlp_set_collection_coll will play havoc on
the other types. (We can make a really ugly hack, by executing
\globalhack_TP_type_coll, defined as

{\tlp_put_right:cn{TP_tlp_set_collection_coll}{\UseCollection{type}{coll}}\aftergroup\globalhack_TP_type_coll},

where type and coll are parameters #1 and #2, but this does not seem the
right solution).
The right solution is to make TP_tlp_set_collection_coll consist of
several tlp! So that TP_tlp_set_collection_front could be for example

Each of the individual tlp's is really a stak, where inner associations
get added to the left and thus override outer ones. The final definition
of \AssociateInstanceCollection is then:

\def:Npn\AssociateInstanceCollection#1#2#3{    % type, collection, iname
\let:cc{#1/??_#2}{#1/#3}

%The following line is pseudocode. It doesn't seem to be difficult to
translate into code,
%but this is the first time I use a tlp or any of its relatives (I
can't even remember which kinds of structures exsit),
%so I didn't bother to look in the manual for the functions that I need.
look if \cs:w TP_tlp_set_collection_#2_#1\end_cs: appears in \cs:w
TP_tlp_set_collection_#2\end_cs:    %Assume the real function is of type TF
{

\tlp_gput_right:cc{TP_tlp_set_collection_#2}{TP_tlp_set_collection_#2_#1}
%Make it global so that we insert it once and for ever
\gdef:cn{TP_tlp_set_collection_#2_#1}{}
}
{}
\tlp_put_right:cn{TP_tlp_set_collection_#2_#1}{\UseCollection{#1}{#2}}

%Record that type+collection is from now on iname:
\def:cpn{TPC>/#1/#2}{#3}        %Note the order #1/#2. We always
regard a collection as an indirect iname for types.
}

This new definition of \AssociateInstanceCollection needs
TP_tlp_set_collection_coll to exist, so we may either add a check and
create it if necessary, or define
\DeclareCollection#1{ \tlp_new:cn{TP_tlp_set_collection_#1}{}.

A global version of \AssociateInstanceCollection is now trivial:

\def:Npn\AssociateInstanceCollection#1#2#3{    % type, collection, iname
\glet:cc{#1/??_#2}{#1/#3}

look if \cs:w TP_tlp_set_collection_#2_#1\end_cs: appears in \cs:w
TP_tlp_set_collection_#2\end_cs:    %Assume the real function is of type TF
{

\tlp_gput_right:cc{TP_tlp_set_collection_#2}{TP_tlp_set_collection_#2_#1}
}
{}
\gdef:cn{TP_tlp_set_collection_#2_#1}{\UseCollection{#1}{#2}}

\gdef:cpn{TPC>/#1/#2}{#3}
}

Successive calls to  \AssociateInstanceCollection within the same group
will keep unnecessary \UseCollection{type}{coll}, but I think it is not
a problem in practice, and in order to eliminate them we should know
whether the last \UseCollection{type}{coll} of
TP_tlp_set_collection_coll_type comes from the current gruop or from an
outer one, which seem awckward.

And that's all!
If all of the above is useless, do not feel sympathy whith me! I really
needed to unrust myself, its a long time since I last worked with TeX.

Javier A.