%D \module
%D   [      file=t-xdesc,
%D        version=2001.07.16,
%D          title=\CONTEXT\ Style File,
%D       subtitle=Extended Descriptions,
%D         author=Giuseppe Bilotta,
%D           date=\currentdate,
%D      copyright={Giuseppe Bilotta}]

%D \usemodule[xdesc]

%D The need for extended descriptions arose while compiling an
%D \RPG\ manual. I needed a special way to treat descriptions
%D of, say, spells, or monsters. In such a situation, the
%D \quotation{object} (spell, monster) has lots of attributes,
%D plus a \quotation{standard} description. This information, once
%D collected, can be typeset in various ways (the expert reader
%D will see \XML\ shadow on this), so we could talk about a
%D \quotation{template} to be filled with the information.
%D
%D The final intent of this module is to allow the user to type
%D something like
%D \startTEX
%D \defineextendeddescription[spell][spells]%
%D                          [class,level,range,save]
%D \stopTEX
%D to define a new description set with attributes \attr{class},
%D \attr{level}, \attr{range}, \attr{save}. All descriptions have
%D the default slots \slot{name}, \slot{desc} which hold the name
%D and the actual text of the description (a future version might
%D also have a default third slot, a short description).
%D
%D The actual descriptions would then have to be input in the form
%D \startTEX
%D \spell[detmagic][class=Cleric,level=1,range={$10''$},save=None]
%D       {Detect Magic}
%D       {This spell allows the cleric to detect the presence of a
%D        magical or enchanted object, which will glow when within
%D        range.}
%D \stopTEX
%D
%D Note that the previous \TeX\ code will not actually typeset
%D anything. But the whole info will be stored. Before an actual
%D spell can be typeset, one needs to define a template to be
%D filled by the info. Such a template will be defined with a
%D command like
%D \startTEX
%D \starttemplate[spell][long]
%D {\bf\em <name>} \par
%D {\bf Class:} <class> \par
%D {\bf Level:} <level> \par
%D {\bf Range:} <range> \par
%D {\bf Saving Throw:} <none> \par
%D \blank
%D <desc>
%D \blank
%D \stoptemplate
%D \stopTEX
%D
%D Testing with templates revealed that it is possible to have
%D \quotation{conditional templates}, coded with
%D \tex{doifelse{<tagname>}{content}{true branch}{false branch}}.
%D this will execute the {\tt true branch} if the tag {\tt
%D <tagname>} has content {\tt content}; otherwise the {\tt false
%D branch} is executed.
%D 
%D When a template is used, the slots (surrounded by brackets)
%D will be replaced by the actual values of the attributes. To use
%D a template, the user selects the template to be used with:
%D \startTEX
%D \selecttemplate[spell][long]
%D \stopTEX
%D and then can typesets the spells with a command as simple as:
%D \startTEX
%D \getspell[detmagic]
%D \stopTEX
%D
%D (Note to myself: there has been a change in the names of the
%D functions to comply with \CONTEXT\ use of \tex{get...} instead
%D of \tex{use...})
%D
%D In the future it will be possible to create lists of the
%D described items, with commands like:
%D \startTEX
%D \completelistofspells[criterium={class=Cleric},
%D                       sortby=level,template=tname]
%D \stopTEX
%D which will list all the clerical spells, sorted by level, using
%D template {\tt tname}.
%D
%D Let's now see the code. We start with a small
%D \quotation{patch}, needed because the \CONTEXT\ command
%D \tex{dosetvalue} keeps checking for \tex{k!} prefixed
%D variables, which is awfull since there is no \tex{dogetvalue}
%D to act the reverse when getting the values. I wonder why Hans
%D removed the \tex{dogetvalue} function~\dots

\unprotect

\def\mysimplesetvalue#1#2{\@EA\def\csname #1#2\endcsname}

%D We now define the command that creates a description; note the
%D use of \#? between brackes to eat up space and allow clean
%D coding.

\def\defineextendeddescription[#1]#2[#3]#4[#5]%
    {% Parameter #1 is the name of the description,
     % Parameter #3 is the plural,
     % Parameter #5 is the list of the attributes
     % Parameters #2 and #4 are only used to eat spaces
     % 
     % The attribute list is initially empty
     \def\templist{}
     %
     % Let's now define the command which will parse the provided
     % attribute list and add these attributes to the attribute
     % list of the description being defined. Note that an '=' is
     % added if not present. This way of processing the list
     % allows the user to provide default values in the definition.
     \def\setcomplexattr##1%
         {\doifinstringelse{=}{##1}
              {\addtocommalist{##1}\templist}
              {\addtocommalist{##1=}\templist}
         }
     % Let's now process the list:
     \processcommalist[#5]\setcomplexattr
     \@EA\let\csname #1:attrlist\endcsname\templist
     % Let's now define the command that will parse the
     % description. Note that it will take two bracketed
     % arguments, the first one of which is obligatory (since it's
     % the hook that manages the described object). The second,
     % optional argument is the list of attributes. The third
     % argument is the name of the described object, and the
     % fourth is the description of the object. The values are
     % stored in the category desc:description~name:hook; for
     % example, the command \tex{spell[stupid]} will store the
     % values in the the category desc:spell:stupid
     \@EA\edef\csname #1\endcsname%
         {\noexpand\dodoubleempty\csname do#1\endcsname}%
     \@EA\long\@EA\edef\csname do#1\endcsname[##1][##2]##3##4%
         {\noexpand\dogetparameters\noexpand\mysimplesetvalue[desc:#1:##1:]
                        [\csname #1:attrlist\endcsname,
                         ##2]%
          \noexpand\setvalue{desc:#1:##1:name}{##3}%
          \noexpand\setvalue{desc:#1:##1:desc}{##4}
          \noexpand\def\csname desc:last#1\endcsname{##1}%
          }
     % Let's now define the command which will typeset the
     % described object. It will just print an error. The real
     % command will be defined by the \tex{selecttemplate} macro.
     \@EA\edef\csname get#1\endcsname%
         {\noexpand\dosingleempty\csname doget#1\endcsname}
     \@EA\def\csname doget#1\endcsname[##1]{No template selected!}
     % Let's now define the registering of descriptions.
     \definesorting[desc:#1][desc:#3]\relax
     \setvalue{placelistof#3}{\csname placelistofdesc:#3\endcsname}
     \setvalue{completelistof#3}{\csname completelistofdesc:#3\endcsname}
     \setupheadtext[desc:#3=\Word{#3}]
     }

\def\starttemplate%
     {\bgroup
      \catcode`\<=\active\relax
      \dostarttemplate%
     }
\long\def\dostarttemplate[#1][#2]#3\stoptemplate%
    {% Parameter #1 is the name of the application using the
     %              template
     % Parameter #2 is the name of the template itself. Note that
     %              different can have a template with the same
     %              name, without running the risk of conflict.
     % Parameter #3 is the actual template
     % Observe the \tex{do...} trick to let the macro be defined
     % with active angle brackets. This is important because
     % catcodes are fixed at reading time.
     \@EA\long\@EA\gdef\csname template:#1:#2\endcsname%
         {\bgroup
          #3
          \egroup
         }
     \egroup
    }
{
% This is needed because otherwise the following \tex{def<} will
% not work:
\catcode`\<=\active
% Now let's define the template selector.
\gdef\selecttemplate[#1][#2]%
    {% Parameter #1 is the name of the application using the
     %              template
     % Parameter #2 is the name of the template itself. Note that
     %              different can have a template with the same
     %              name, without running the risk of conflict.
     \@EA\def\csname doget#1\endcsname[##1]%
         {\bgroup
          \catcode`\<=\active
          \iffirstargument%
             \def<####1>{\getvalue{desc:#1:##1:####1}}
          \else%
             \edef\!!stringa{\csname desc:last#1\endcsname}
             \edef<####1>{\noexpand\getvalue{desc:#1:\!!stringa:####1}}
          \fi
          \edef\!!stringa{<name>}
          \@EA\csname\@EA d\@EA e\@EA s\@EA c\@EA:\@EA#1\@EA\endcsname\@EA{\!!stringa}
          \csname template:#1:#2\endcsname
          \egroup
         }
    }
}
\protect

%D The real example:
%D 
%D \defineextendeddescription[spell][spells]
%D                           [class,level,range,save]
%D
%D \spell[detmagic][class=Cleric,level=1,range=$10''$,save=None]
%D       {Detect Magic}
%D       {This spell allows the cleric to detect the presence of a
%D        magical or enchanted object, which will glow when within
%D        range.}
%D
%D \getspell[detmagic]
%D
%D \getspell
%D
%D \starttemplate[spell][long]
%D \blank
%D {\bf\em <name>} \par
%D {\bf Class:} <class> \par
%D {\bf Level:} <level> \par
%D {\bf Range:} <range> \par
%D {\bf Saving Throw:} <save> \par
%D \blank
%D <desc>
%D \blank
%D \stoptemplate
%D 
%D \selecttemplate[spell][long]
%D 
%D \getspell
%D 
%D \getspell[detmagic]
%D

\endinput

