X-Git-Url: https://git.distorted.org.uk/~mdw/sod/blobdiff_plain/aadea863f48c4b1b4cdd20f2d6eeb5fde627c2c4..944bf9362ff51217b1617f85126d26e821b8aa91:/doc/sod.sty diff --git a/doc/sod.sty b/doc/sod.sty index 75acc2d..9da7def 100644 --- a/doc/sod.sty +++ b/doc/sod.sty @@ -106,8 +106,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 +189,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 +246,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. @@ -386,25 +430,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 +506,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*} @@ -468,8 +523,29 @@ \@namedef{describe*}#1{\desc@begin{#1}} \expandafter\let\csname enddescribe*\endcsname\desc@end -%% \descref{CAT}{...}...{LABEL}[TEXT] -%% \descref*{CAT}{...}...{LABEL} +%% \parse@dlbl{NEXT}[MOD]{CAT}{...}...{LABEL} +%% +%% Parse a description label, and call +%% +%% NEXT{MOD}{CAT}{{...}...}{LABEL} +%% +%% This handles defaulting the MOD correctly, based on the LABEL text. See +%% `\descref' for the details. +\def\parse@dlbl#1{\@ifnextchar[{\parse@dlbl@a{#1}}{\parse@dlbl@c{#1}}} +\def\parse@dlbl@a#1[#2]#3{\@desc@dispatch{descargs}{#3}{#1{#2}{#3}}} +\def\parse@dlbl@c#1#2% + {\@desc@dispatch{descargs}{#2}{\parse@dlbl@cb{#1}{#2}}} +\def\parse@dlbl@cb#1#2#3#4{% + \def\temp@##1##2*##3\q@{\def\temp@{##1##3}}\temp@#4*\q@% + \ifx\temp@\@starstar\def\next@{#1{muffs}{#2}{#3}{#4}}% + \else\def\temp@##1##2\q@{\def\temp@{##1}}\temp@#4\q@% + \if:\temp@\def\next@{#1{kwd}{#2}{#3}{#4}} + \else\def\next@{#1{plain}{#2}{#3}{#4}}\fi\fi% + \next@% +} + +%% \descref[MOD]{CAT}{...}...{LABEL}[TEXT] +%% \descref*[MOD]{CAT}{...}...{LABEL} %% %% Typesets a cross-reference to a described thing. The CAT names the %% category of thing being described, and the LABEL names the specific thing. @@ -477,32 +553,79 @@ %% The {...}... are any additional arguments required by the category's kind %% (e.g., method specializers). %% -%% The precise rules for how the LABEL matches the name in the description -%% depend on the description's modifier: +%% The MOD is the modifier to apply, similar (but subtly different from) to +%% the `describe' environment. If omitted, it will usually default to +%% `plain', but in the absence of a NAME, some kinds of synopses are +%% recognized specially: %% -%% * `plain', `muffs', and `kwd': the LABEL is the same as the NAME. -%% * `setf': the LABEL should be `setf/NAME'. +%% * `*NAME*': defaults MOD to `muffs'. +%% +%% * `:NAME': defaults MOD to `kwd'. +%% +%% (`setf' is /not/ specially detected here. Write an explicit `setf' +%% modifier if necessary, because it's no more typing.) %% %% Usually a page-number cross-reference is included, so as to help readers %% of a dead-tree copy; this is suppressed by the `*' version. \def\descref{\@ifstar% - {\descref@i{}\@gobble{}}% - {\descref@i{ (}{\noexpand\autopageref}{)}}} -\def\descref@i#1#2#3#4#5{\@ifnextchar@preserve[% - {\descref@ii{#1}{#2}{#3}{#4}{#5}}% - {\descref@iii{#1}{#2}{#3}{#4}{#5}{}}} -\def\descref@ii#1#2#3#4#5[#6]{\descref@iii{#1}{#2}{#3}{#4}{#5}{ #6}} -\def\descref@iii#1#2#3#4#5#6{% + {\parse@dlbl{\descref@i\relax\@gobble\relax}}% + {\parse@dlbl{\descref@i{ (}\autopageref)}}} +\def\descref@i#1#2#3#4#5#6#7{\@ifnextchar@preserve[% + % {PGA}{PGB}{PGC}{MOD}{CAT}{{...}...}{LABEL} + {\descref@ii{#1}{#2}{#3}{#4}{#5}{#6}{#7}}% + {\descref@iii{#1}{#2}{#3}{#4}{#5}{#6}{#7}{}}} +\def\descref@ii#1#2#3#4#5#6#7[#8]% + % {PGA}{PGB}{PGC}{MOD}{CAT}{{...}...}{LABEL}[AFTER] + {\descref@iii{#1}{#2}{#3}{#4}{#5}{#6}{#7}{ #8}} +\def\descref@iii#1#2#3#4#5#6#7#8{% + % {PGA}{PGB}{PGC}{MOD}{CAT}{{...}...}{LABEL}{AFTER} \begingroup% - \let\protect\@empty% - \def\@uscore{-\@gobble}% - \edef\@tempa##1{% - \endgroup% - \noexpand\hyperref[#4:#5]% - ##1% - #2{#4:#5}% - }% - \@tempa{{\code{#5}}#6#1}#3% + \let\protect\@empty\def\@uscore{-\@gobble}% + \edef\temp@{\@desc@dispatch{desclabel}{#5}{#4}{#5}#6{#7}}% + \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.