I've spent the weekend actually getting the templated index package running, so now I've gained some new experience with these things. The good news are that I got the design as I wanted it almost immediately; this suggests to me that the separation of design (which gets put in <keyvals>) and control structures (which is the <code> for the template) furthers good programming. In fact I suspect that if one is to develop a new LaTeX2e package which involves a lot of design issues, the best route might be to start develop it as a LaTeX2e* package (or at least a templated package) and then write a 2e version which follows the structure of the 2e* version (emulating the instances only, not the templates or template types). In any case, I will try this approach in the next step of the templated index package project. The bad news are that before I got it running I had to spend several hours tracking down the exact reason that the <keyvals> weren't parsed as I wanted them to. This was initially very hard but it got easier once I hacked ldcsetup.sty to actually print how it had parsed the keyvals (see latex-bugs expl3/3302; apparently something of the kind will be included in the official code as well), however it was still much too easy to make \DeclareTemplate go haywire by making a typo in the <keyvals> argument. One thing I think would solve most of these problems, or at least enable TeX to catch them at a much earlier stage, would be to change the keyval defaults from being bracked-delimited to brace-delimited (i.e. put in a group). It is certainly no harder to check if the next character is a `{' than to check if it is a `[': just do \@ifnextchar\bgroup instead of \@ifnextchar[. The main advantage with this is that the use of special characters inside the keyval default will no longer mess up the parsing; currently \DeclareTemplate{foo}{bar}{0}{ foo =f0 [, ] \punctuation }{\DoParameterAssignments} will die rather horribly because the comma inside the brackets will start the declaration of a new key. When \TP@test@pt tries to grab the default value it will only stop at the end of the file or a \par, because the right brace that was intended to end the default value is hidden inside a group. Currently \DeclareTemplate{foo}{bar}{0}{ foo =f0 [{, }] \punctuation }{\DoParameterAssignments} does work and the braces are removed when the default value is grabbed, but one would avoid errors better if it was \DeclareTemplate{foo}{bar}{0}{ foo =f0 {, } \punctuation }{\DoParameterAssignments} since then the comma wouldn't be visible to \[log in to unmask] Other characters that need this kind of special care in defaults are = and ]. Some other things I reacted to: The difference between a template and an instance could be explained better. I had gotten the impression that instance=template where there are no unrestricted keyvals left, but after looking closer at the code I can see that this is not the case; in particular you need to do much more processing of a template before you can use it than you need to do an instance. You'll have to put a lot of \describecsfamily's into template.dtx before you can call it reasonably documented, but before you do that you may want to consider changing the control sequence families used. Currently control sequence names are pieced together as <root><name_1><separator_1><name_2><separator_2> ... <name_n> (for templates the <root> seems to be TP>/, the <name_1> is the template type, <separator_1> is /, <name_2> is the template name, and n=2). This practice works fine if n=1 or the <separator_i>'s cannot be appear in the <name_i>'s, but that is not the case with the template code. A solution less sensitive to strange characters in <name_i>'s would be to surround each <name_i> with a brace group (\csname doesn't mind category 1 and 2 characters), since even an ingenious fool has work very hard to get braces mismatched in arguments, whereas with the current naming scheme \DeclareTemplate{foo}{bar/baz}... and \DeclareTemplate{foo/bar}{baz}... would be stored in the same macros. Lars Hellström