X-Git-Url: https://git.distorted.org.uk/~mdw/sod/blobdiff_plain/89092cc1f7b225d6caa59f2c10e7126009b0df02..4b3a72700ae8799ba6ba07969e2677f2168d32a9:/doc/sod.sty

diff --git a/doc/sod.sty b/doc/sod.sty
index 4d50de9..592ff5c 100644
--- a/doc/sod.sty
+++ b/doc/sod.sty
@@ -73,7 +73,8 @@
 %% Diagram settings.
 \tikzset{
   every picture/.style={>=stealth, thick},
-  lit/.style={font=\sffamily}
+  lit/.style={font=\sffamily},
+  dashed/.style={dash pattern=on 2.19pt off 2.19pt}
 }
 
 %% Metavariables are italics without decoration.
@@ -106,8 +107,8 @@
 
 %% Intercept grammar typesetting and replace the vertical bar with the
 %% maths-font version.
-\let\@@grammar\grammar
-\def\grammar{\def\textbar{\hbox{$|$}}\@@grammar}
+\let\@@syn@shorts\syn@shorts
+\def\syn@shorts{\def\textbar{\hbox{$|$}}\@@syn@shorts}
 
 %% Collect super- and subscripts.  (Note that underscores are active for the
 %% most part.)  When we're done, end maths mode if we entered it
@@ -189,8 +190,17 @@
 %%%--------------------------------------------------------------------------
 %%% Environment for setting programs.
 
+%% Save `\kill' so that `longtable' won't clobber it.
+\let\prog@@kill\kill
+
 %% Main guts of `prog' and `nprog'.
-\def\@prog{\let\prog@@cr\@tabcr\let\@tabcr\@progcr\codeface\tabbing}
+\def\@prog{%
+  \let\prog@@cr\@tabcr%
+  \let\@tabcr\@progcr%
+  \let\kill\prog@@kill%
+  \codeface%
+  \tabbing%
+}
 
 %% Newlines: called by `\\' within a `prog'.
 %%
@@ -237,6 +247,41 @@
 %% Show a backslash by the right-hand margin; for multiline macros etc.
 \def\macsl{\`\textbackslash\hskip\leftmargin}
 
+%% \maplist{THING}{{ITEM}...}: Invoke THING{ITEM} for each ITEM in turn.
+\def\maplist#1#2{\map@i{#1}#2\q@}
+\def\map@i#1{\def\next@{\map@ii{#1}}\futurelet\ch@\next@}
+\def\map@ii#1{\ifx\ch@\q@\expandafter\@gobble%
+  \else\def\next@{\map@iii{#1}}\expandafter\next@\fi}
+\def\map@iii#1#2{#1{#2}\map@i{#1}}
+
+%% \crossproduct{THING}{{LIST}...} where each LIST is {ITEM}...
+%% For each possible way of selecting one ITEM from each LIST, in order,
+%% invoke THING{{ITEM}...}
+\toksdef\cprod@new=0
+\toksdef\cprod@old=2
+\toksdef\cprod@head=4
+\toksdef\cprod@tail=6
+\def\crossproduct#1#2{%
+  \cprod@new{{}}%
+  \maplist{\cprod@f{#1}}{#2}%
+  \cprod@head{#1}%
+  \edef\next@{\noexpand\maplist{\the\cprod@head}{\the\cprod@new}}
+  \next@%
+}
+\def\cprod@f#1#2{%
+  \cprod@old\cprod@new\cprod@new{}%
+  \maplist\cprod@g{#2}%
+}
+\def\cprod@g#1{%
+  \cprod@head{#1}%
+  \expandafter\maplist\expandafter\cprod@h\expandafter{\the\cprod@old}%
+}
+\def\cprod@h#1{%
+  \cprod@tail{#1}%
+  \cprod@new\expandafter{\the\expandafter\cprod@new\expandafter{%
+      \the\expandafter\cprod@tail\the\cprod@head}}%
+}
+
 %%%--------------------------------------------------------------------------
 %%% Machinery for describing functions, etc.
 
@@ -261,7 +306,14 @@
 \def\@descname@i[#1]#2{%
   \expandafter\let\expandafter\@tempa\csname cat!#2\endcsname%
   \expandafter\let\expandafter\@tempb\csname modcat/#1\endcsname%
-  \ifx\@tempa\relax\@tempb{#2}\else\@tempa\@tempb\fi}
+  \ifx\@tempa\relax\PackageError{sod}{unknown description category `#2'}%
+    {I don't know what `#2' means as a thing you might try to\MessageBreak
+     document.  Maybe you mistyped it, or forgot to say\MessageBreak
+     `\protect\definedescribecategory' for it.  For now I'm going\MessageBreak
+     just use the literal string `#2' and hope that doesn't look\MessageBreak
+     too terrible.}%
+    \@tempb{#2}%
+  \else\@tempa\@tempb\fi}
 
 %% Call a modifier method.
 \def\@mod@dispatch#1#2{\csname #1/#2\endcsname}
@@ -386,25 +438,33 @@
   #1{setf}{#2}{#3}{#5}{#4}}
 
 %% \dhead[MOD]{CAT}{...}...[NAME]{SYNOPSIS}
+%% \dhead*[MOD]{CAT}{...}...[NAME]{SYNOPSIS}
 %%
 %% Typeset a description head.  Use this within the first argument of
 %% `describe*'; see `describe' for the details.
+%%
+%% With `*', don't set labels or add items to the index.
 \newif\if@dheadfirst
-\def\dhead{\parse@dhd\dhead@}
+\newif\if@dheadindex
+\def\dhead{\@ifstar%
+  {\parse@dhd{\global\@dheadindexfalse\dhead@}}%
+  {\parse@dhd{\global\@dheadindextrue\dhead@}}}
 \def\dhead@#1#2#3#4#5{%  {MOD}{CAT}{{...}...}{NAME}{SYNOPSIS}
   \if@dheadfirst\global\@dheadfirstfalse\else\relax\\*[\smallskipamount]\fi%
-  \phantomsection%
-  {\let\protect\@empty\let\@uscore\relax%
-   \edef\temp@{\@desc@dispatch{desclabel}{#2}{#1}{#2}#3{#4}}%
-   \def\@uscore{_\@gobble}\expandafter\message\expandafter{\temp@}%
-   \def\@uscore{-\@gobble}\expandafter\label\expandafter{\temp@}}%
-  {\begingroup\lccode`\~=`\_\lowercase{\endgroup\def~{_}}%
-   \protected@edef\@tempa##1{%
-     \noexpand\index{\@desc@dispatch{descindex}{#2}{#1}{#2}#3{#4}##1}}%
-   \toks@\expandafter{\@tempa{|)}}%
-   \toks\tw@\expandafter{\after@desc}%
-   \xdef\after@desc{\the\toks\tw@\the\toks@}%
-   \@tempa{|(}}%
+  \if@dheadindex%
+    \phantomsection%
+    {\let\protect\@empty\let\@uscore\relax%
+     \edef\temp@{\@desc@dispatch{desclabel}{#2}{#1}{#2}#3{#4}}%
+     \def\@uscore{_\@gobble}\expandafter\message\expandafter{\temp@}%
+     \def\@uscore{-\@gobble}\expandafter\label\expandafter{\temp@}}%
+    {\begingroup\lccode`\~=`\_\lowercase{\endgroup\def~{_}}%
+     \protected@edef\@tempa##1{%
+       \noexpand\index{\@desc@dispatch{descindex}{#2}{#1}{#2}#3{#4}##1}}%
+     \toks@\expandafter{\@tempa{|)}}%
+     \toks\tw@\expandafter{\after@desc}%
+     \xdef\after@desc{\the\toks\tw@\the\toks@}%
+     \@tempa{|(}}%
+  \fi%
   \rlap{\hb@xt@\linewidth{\hfil\normalfont\bfseries
       [\describecategoryname[#1]{#2}]}}%
   #5%
@@ -454,7 +514,10 @@
 %%
 %%   * `:NAME': defaults MOD to `kwd'.
 \def\describe{\parse@dhd\desc@}
-\def\desc@#1#2#3#4#5{\desc@begin{\dhead@{#1}{#2}{#3}{#4}{#5}}}
+\def\desc@#1#2#3#4#5{%
+  \global\@dheadindextrue%
+  \desc@begin{\dhead@{#1}{#2}{#3}{#4}{#5}}%
+}
 \let\enddescribe\desc@end
 
 %% \begin{describe*}
@@ -527,9 +590,50 @@
   \begingroup%
     \let\protect\@empty\def\@uscore{-\@gobble}%
     \edef\temp@{\@desc@dispatch{desclabel}{#5}{#4}{#5}#6{#7}}%
-    \hyperref[\temp@]{\code{#7}}#8%
-    #1#2{\temp@}#3%
+    \edef\next@##1##2##3{\endgroup%
+      \noexpand\hyperref[\temp@]{##1}##2{\temp@}##3}%
+  \next@{\code{#7}}{#8#1#2}{#3}%
+}
+
+%% \descindex[MOD]{CAT}{...}...{LABEL}[SUFFIX]
+%%
+%% Set a label and index entry here, as if for a description.  The CAT names
+%% the category of thing being described, and the LABEL names the specific
+%% thing, as for `\descref'.  The {...}... are any additional arguments
+%% required by the category's kind (e.g., method specializers).  The MOD is
+%% the modifier to apply; see `\descref' for the details.
+%%
+%% The SUFFIX is appended to the index-entry text; by default it is empty.
+%% Useful values are `|(' and `|)' to set ranges.
+\def\descindex{\parse@dlbl\descindex@i}
+\def\descindex@i#1#2#3#4{\@ifnextchar[%
+  {\descindex@ii{#1}{#2}{#3}{#4}}%
+  {\descindex@ii{#1}{#2}{#3}{#4}[]}}
+\def\descindex@ii#1#2#3#4[#5]{%
+  {\begingroup\lccode`\~=`\_\lowercase{\endgroup\def~{_}}%
+   \protected@edef\@tempa{%
+     \noexpand\index{\@desc@dispatch{descindex}{#2}{#1}{#2}#3{#4}#5}}%
+   \@tempa}%
+}
+
+%% \desclabel[MOD]{CAT}{...}...{LABEL}[INDEX-SUFFIX]
+%%
+%% Set a label and index entry here, as if for a description.  The CAT names
+%% the category of thing being described, and the LABEL names the specific
+%% thing, as for `\descref'.  The {...}... are any additional arguments
+%% required by the category's kind (e.g., method specializers).  The MOD is
+%% the modifier to apply; see `\descref' for the details.
+%%
+%% This will also add an index entry, as for `\descindex'; the INDEX-SUFFIX
+%% argument has the same effect as its SUFFIX argument.
+\def\desclabel{\parse@dlbl\desclabel@i}
+\def\desclabel@i#1#2#3#4{%
+  \begingroup%
+    \let\protect\@empty\def\@uscore{-\@gobble}%
+    \edef\@tempa{\@desc@dispatch{desclabel}{#2}{#1}{#2}#3{#4}}%
+    \phantomsection\label{\@tempa}%
   \endgroup%
+  \descindex@i{#1}{#2}{#3}{#4}%
 }
 
 %% Description categories.
