diff options
Diffstat (limited to 'web/noweb/src/tex/support.nw.orig')
-rw-r--r-- | web/noweb/src/tex/support.nw.orig | 1301 |
1 files changed, 1301 insertions, 0 deletions
diff --git a/web/noweb/src/tex/support.nw.orig b/web/noweb/src/tex/support.nw.orig new file mode 100644 index 0000000000..c706a0b4cb --- /dev/null +++ b/web/noweb/src/tex/support.nw.orig @@ -0,0 +1,1301 @@ +% -*- mode: Noweb; noweb-code-mode: tex-mode -*- +\documentstyle[noweb,twoside]{article} +\pagestyle{noweb} +\noweboptions{longchunks,smallcode} +\title{{\TeX} support for {\tt noweb}} +\author{Norman Ramsey} +\newcommand{\stylehook}{\marginpar{\raggedright\sl Style hook}} +\begin{document} +\maketitle +\tableofcontents +@ +This document describes the {\TeX} code that supports {\tt noweave} +and {\tt noweb}. Those interested in customizing their output should +focus on Section~\ref{section:sty}. +Hooks you can easily use (apart from those provided by +[[\noweboptions]]) are indicated by marginal notes. +This file contains both plain {\TeX} and {\LaTeX} support: +<<nwmac.tex>>= +% nwmac.tex -- plain TeX support for noweb +% DON'T read or edit this file! Use ...noweb-source/tex/support.nw instead. +<<noweb.sty>>= +% noweb.sty -- LaTeX support for noweb +% DON'T read or edit this file! Use ...noweb-source/tex/support.nw instead. +@ + +\section{Basic {\TeX} support for {\tt noweb}} +This basic code is used for both {\TeX} and {\LaTeX}. +The first step is to define [[\codehsize]], which is the width in +which code is set, and [[\codemargin]], which is the amount by which +it is indented.\stylehook +<<kernel>>= +% make \hsize in code sufficient for 88 columns +\setbox0=\hbox{\tt m} +\newdimen\codehsize +\codehsize=91\wd0 % 88 columns wasn't enough; I don't know why +\newdimen\codemargin +\codemargin=0pt +@ %def \codehsize \codemargin +[[\defspace]] is the space we would like on the right of navigational info +that appears on definition lines, so that it lines up with the text above +and below. +<<kernel>>= +\newdimen\nwdefspace +\nwdefspace=\codehsize +%% \advance\nwdefspace by -\textwidth\relax +\advance\nwdefspace by -\hsize\relax +@ +Most code is set in an environment in which [[\setupcode]] has been +executed. +In this environment, only [[\]], [[{]], and [[}]] have their usual +categories; every other character represents itself. +Appropriate [[\chardef]]s ensure that the special characters can be +escaped with a backslash. +<<kernel>>= +\chardef\other=12 +\def\setupcode{% + \chardef\\=`\\ + \chardef\{=`\{ + \chardef\}=`\} + \catcode`\$=\other + \catcode`\&=\other + \catcode`\#=\other + \catcode`\%=\other + \catcode`\~=\other + \catcode`\_=\other + \catcode`\^=\other + \catcode`\"=\other % fixes problem with german.sty + \obeyspaces\Tt +} +\let\nwlbrace=\{ +\let\nwrbrace=\} +@ %def \setupcode +[[\eatline]] is used to consume newlines that should be ignored, +for example, the newlines at the end of [[@ %def ]]{\em identifiers} lines. +I can't remember what [[\startline]] or [[\newlines]] are for; I don't +think {\tt noweave} ever emits them. +<<kernel>>= +{\catcode`\^^M=\active % make CR an active character + \gdef\newlines{\catcode`\^^M=\active % make CR an active character + \def^^M{\par\startline}}% + \gdef\eatline#1^^M{\relax}% +} +%%% DON'T \gdef^^M{\par\startline}}% in case ^^M appears in a \write +\def\startline{\noindent\hskip\parindent\ignorespaces} +\def\nwnewline{\ifvmode\else\hfil\break\fi} +@ %def \startline \eatline \nwnewline + +Within a code environment, it may be necessary to restore the +category codes in order to set a module (chunk) name. +This hack doesn't properly restore [["]] for use in {\tt german.sty}. +<<kernel>>= +{\obeyspaces\global\let =\ } % from texbook, p 381 +\def\setupmodname{% + \catcode`\$=3 + \catcode`\&=4 + \catcode`\#=6 + \catcode`\%=14 + \catcode`\~=13 + \catcode`\_=8 + \catcode`\^=7 + \catcode`\ =10 + \catcode`\^^M=5 + \let\{\nwlbrace + \let\}\nwrbrace + % bad news --- don't know what catcode to give " + \Rm} +@ %def \setupmodname +@ \sublabel{ref:fred} + +{\tt noweave} brackets uses of chunk names with [[\LA]] and [[\RA]], which +handle the angle brackets, font, and environment. + +As it stands, chunk names can be broken across lines (or pages). This +could result in unnecessary page breaks in code +(c.f.~p.~\pageref{sec:pagebreaking}). [[\let\\maybehbox=\mbox]] to +\stylehook +avoid breaking them +(or to make them work in math mode); this is done in code chunks, but could be done +in general. +<<kernel>>= +\def\LA{\begingroup\maybehbox\bgroup\setupmodname\It$\langle$} +\def\RA{\/$\rangle$\egroup\endgroup} +\def\code{\leavevmode\begingroup\setupcode\newlines} +\def\edoc{\endgroup} +\let\maybehbox\relax +@ %def \LA \RA \maybehbox + +[[\equivbox]] and [[\plusequivbox]] are used to set the +``\unhcopy\equivbox'' +and ``\unhcopy\plusequivbox'' that open a chunk definition or its +continuation. +{\tt noweave} brackets definitions of chunk names with [[\moddef]] and +either [[\endmoddef]] or [[\plusendmoddef]]. +<<kernel>>= +\newbox\equivbox +\setbox\equivbox=\hbox{$\equiv$} +\newbox\plusequivbox +\setbox\plusequivbox=\hbox{$\mathord{+}\mathord{\equiv}$} +% \moddef can't have an argument because there might be \code...\edoc +\def\moddef{\leavevmode\kern-\codemargin\LA} +\def\endmoddef{\RA\ifmmode\equiv\else\unhcopy\equivbox\fi + \nobreak\hfill\nobreak} +\def\plusendmoddef{\RA\ifmmode\mathord{+}\mathord{\equiv}\else\unhcopy\plusequivbox\fi + \nobreak\hfill\nobreak} +@ %def \equivbox \plusequivbox \moddef \endmoddef \plusendmoddef +@ +Within a code environment, margin tags might be used to mark sub-page +numbers in the margins, separated by [[\nwmarginglue]].\stylehook +The interaction with [[\moddef]] involves tricky kerning. +The tag itself is displayed using [[\nwthemargintag]] +<<noweb.sty>>= +\def\nwopt@nomargintag{\let\nwmargintag=\@gobble} +\def\nwopt@margintag{% + \def\nwmargintag##1{\leavevmode\llap{##1\kern\nwmarginglue\kern\codemargin}}} +\def\nwopt@margintag{% + \def\nwmargintag##1{\leavevmode\kern-\codemargin\nwthemargintag{##1}\kern\codemargin}} +\def\nwthemargintag#1{\llap{#1\kern\nwmarginglue}} +\nwopt@margintag +\newdimen\nwmarginglue +\nwmarginglue=0.3in +@ %def \nwmargintag margintag nomargintag \nwmarginglue +\iffalse +<<man page: [[\noweboptions]]>>= +.TP +.B margintag +Put the sub-page number (tag) of each code-chunk definition in the +left margin. (Default) +.TP +.B nomargintag +Don't use margin tags. +@ \fi +[[\nwtagstyle]] determines the style in which tags are displayed.\stylehook +<<noweb.sty>>= +\def\nwtagstyle{\footnotesize\Rm} +@ +<<kernel>>= +\def\chunklist{% +\errhelp{I changed \chunklist to \nowebchunks. +I'll try to avoid such incompatible changes in the future.}% +\errmessage{Use \string\nowebchunks\space instead of \string\chunklist}} +\def\nowebchunks{\message{<Warning: You need noweave -x to use \string\nowebchunks>}} +\def\nowebindex{\message{<Warning: You need noweave -index to use \string\nowebindex>}} +@ %def \chunklist \nowebchunks \nowebindex +@ We have to be careful with font-changing in the presence of +different font-selection schemes. In the \LaTeX{} New Font Selection +Scheme something like [[\it\tt]] will attempt to use an italic +typewriter font. Thus we define new commands like [[\Tt]] which will +work with both the Plain and old and new \LaTeX{} schemes. (Note that +NFSS will be standard in the next version of \LaTeX.) A problem with +these definitions arises with NFSS: in math mode the won't work +unless the {\tt oldlfont} backwards-compatibility option is in effect. +For the moment, you can get round this by using [[\mbox]]. + +If you wanted code set in a different font, you could re-define +[[\Tt]].\stylehook{} [\LaTeX2e actually behaves like OFSS, but the +extra [[\reset@font]] does no harm.] +<<kernel>>= +% here is support for the new-style (capitalized) font-changing commands +% thanks to Dave Love +\ifx\documentstyle\undefined + \let\Rm=\rm \let\It=\it \let\Tt=\tt % plain +\else\ifx\selectfont\undefined + \let\Rm=\rm \let\It=\it \let\Tt=\tt % LaTeX OFSS +\else % LaTeX NFSS + \def\Rm{\reset@font\rm} + \def\It{\reset@font\it} + \def\Tt{\reset@font\tt} + \def\Bf{\reset@font\bf} +\fi\fi +\ifx\reset@font\undefined \let\reset@font=\relax \fi +@ %def \Rm \Tt \It \Bf +@ +\clearpage +\section{The {\tt noweb} document-style option for {\LaTeX}} +\label{section:sty} +{\LaTeX} support begins with the kernel shown above. +<<noweb.sty>>= +<<kernel>> +@ +\subsection{Support for noweb options} +<<noweb.sty>>= +\def\noweboptions#1{% + \def\@nwoptionlist{#1}% + \@for\@nwoption:=\@nwoptionlist\do{% + \@ifundefined{nwopt@\@nwoption}{% + \@latexerr{There is no such noweb option as '\@nwoption'}\@eha}{% + \csname nwopt@\@nwoption\endcsname}}} +@ %def \noweboptions +\subsection{Adjusting placement of code on the page} +{\LaTeX} requires a larger [[\codehsize]] because +code is indented by [[\codemargin]].\stylehook +<<noweb.sty>>= +\codemargin=10pt +\advance\codehsize by \codemargin % make room for indentation of code +\advance\nwdefspace by \codemargin % and fix adjustment for def/use +@ +[[\noweboptions{shift}]] is used to shift the whole page left to make room for +the wide code lines. +It may be emitted by {\tt noweave -shift}, or it might be given by a user. +<<noweb.sty>>= +\def\nwopt@shift{% + \dimen@=-0.8in + \if@twoside % Values for two-sided printing: + \advance\evensidemargin by \dimen@ + \else % Values for one-sided printing: + \advance\evensidemargin by \dimen@ + \advance\oddsidemargin by \dimen@ + \fi +% \advance \marginparwidth -\dimen@ +} +\let\nwopt@noshift\@empty +@ %def shift noshift + +\iffalse +<<man page: [[\noweboptions]]>>= +.TP +.B shift +Shift text to the left so that long code lines won't extend +off the right-hand side of the page. +@ \fi + +\subsection{Page-breaking strategy}\label{sec:pagebreaking} + +We want to insert penalties aiming for: +\begin{enumerate} +\item +No page breaks in the middle of a code chunk unless necessary to avoid +an overfull vbox; +\item +Documentation immediately preceding a code chunk should appear on +the same page as that code chunk unless doing so would violate rule 1. +\end{enumerate} +[[\filbreak]] is useful for this sort of thing (see {\em The \TeX + book\/}) and is used to encourage breaks at the right places between +chunks. Appropriate penalties are inserted elsewhere, between code +lines in particular. + +\subsection{Environments for setting code} + +[[\nwbegincode]] and [[\nwendcode]] are used by {\tt noweave} to bracket +code chunks. +The [[webcode]] environment is intended for users who want to paste +{\tt noweave} output into papers. + +The definition of [[\nwbegincode]] is based on the verbatim +implementation in {\tt verbatim.sty}, which will, presumably be in the +next version of \LaTeX\@. One thing it does differently, apart from +the catcode changes is setting [[\linewidth]]; this will avoid some +overfull hboxen when the code lines are too long, but the lines won't +be broken anyhow (even within chunk names because of the +[[\maybehbox]] definition). +<<noweb.sty>>= +\def\nwbegincode#1{% + \begingroup + <<[[\nwbegincode]] separation and penalties>> + \@begincode } +\def\nwendcode{\endtrivlist \endgroup \filbreak} % keeps code on 1 page + +\newenvironment{webcode}{% + \@begincode +}{% + \endtrivlist} +@ %def \nwbegincode \nwendcode webcode +@ This is just common code between [[\nwbegincode]] and [[webcode]]. +<<noweb.sty>>= +\def\@begincode{% + <<[[\trivlist]] clich\'e (\`a la {\Tt verbatim})>> + \linewidth\codehsize + <<[[\obeylines]] setup>> + <<zap ligatures, fix spaces>> + \nowebsize \setupcode + \let\maybehbox\mbox } +@ %def \@begincode +@ \iffalse +<<man page: [[\noweboptions]]>>= +.TP +.B smallcode +Set code in +.I LaTeX +.B "\\\\small" +font instead of +.B "\\\\normalsize." +@ \fi +@ [[\nowebsize]] governs the size at which code is set; users who want +to minimize code can [[\let\nowebsize=\small]]. +Slitex users should try +\begin{quote} +[[\def\nowebsize{\normalsize\baselineskip=20pt \parskip=5pt }]] +\end{quote} +to avoid code lines that are too far apart. +[[\nwcodetopsep]] is +the glue placed before code chunks.\stylehook +<<noweb.sty>>= + \newskip\nwcodetopsep \nwcodetopsep = 3pt plus 1.2pt minus 1pt + \let\nowebsize=\normalsize + \def\nwopt@smallcode{\let\nowebsize=\small} +@ %def \nwcodetopsep \nowebsize smallcode +@ Maybe the penalties ought to be parameters\dots +<<[[\nwbegincode]] separation and penalties>>= + \topsep \nwcodetopsep + \@beginparpenalty \@highpenalty + \@endparpenalty -\@highpenalty +@ +The [[\trivlist]] clich\'e isn't quite a clich\'e because we adjust +[[\leftskip]] for indentation by [[\codemargin]] and adjust +[[\rightskip]] to allow lines up to [[\codehsize]] long without +overfull boxen +($\mbox{[[\codehsize]]}=\mbox{[[\hsize]]}+\mbox{[[\rightskip]]}$). +Note that [[\hsize]] isn't altered. +<<[[\trivlist]] clich\'e (\`a la {\Tt verbatim})>>= + \trivlist \item[]% + \leftskip\@totalleftmargin \advance\leftskip\codemargin + \rightskip\hsize \advance\rightskip -\codehsize + \parskip\z@ \parindent\z@ \parfillskip\@flushglue +@ The penalty inserted between verbatim lines would normally be +[[\interlinepenalty]], but we want to prohibit breaks there. +@ +Note the bug lurking somewhere in this code, as reported by Steven Ooms: +\begin{quote} +I have some lay-out +problems in the documentation chunks. When using the (La)TeX commands +[[\hline]] or [[\vtop]] the right margin is always extended far beyond the page +margin after the first code chunk has been typeset. I'm still looking for +the exact cause of it, but to me it seems that LaTeX supposes for those +commands that the line width for the documentation chunk is as large as that +for code chunks, which isn't true in reality. +\end{quote} +@ +<<[[\obeylines]] setup>>= + \@@par + \def\par{\leavevmode\null \@@par \penalty\nwcodepenalty}% + \obeylines +@ [[\nwcodepenalty]] is the penalty for breaking between lines in a +code chunk. If you set it to 10000, code will never be broken across +pages.\stylehook{} I guess this should be settable in [[\noweboptions]]. +<<noweb.sty>>= +\newcount\nwcodepenalty \nwcodepenalty=\@highpenalty +@ %def \nwcodepenalty +The cursing chunk accounts for the addition of a mess of characters +to those reset by [[\@noligs]] in \LaTeX2e. +<<zap ligatures, fix spaces>>= + \@noligs <<make all those damn active characters ``other''>> + \setupcode \frenchspacing \@vobeyspaces +@ +We can't make [[`]] ``other,'' because then we'll get ligatures. +(Why Don put these ligatures in the [[\tt]] font I wish I knew.) +But we'll step on all the others. +<<make all those damn active characters ``other''>>= + \ifx\verbatim@nolig@list\undefined\else + \let\do=\nw@makeother \verbatim@nolig@list \do@noligs\` + \fi +<<noweb.sty>>= +\def\nw@makeother#1{\catcode`#1=12 } +@ +{\tt noweave} uses [[\nwbegindocs{nnn}]] and [[\nwenddocs]] to bracket +documentation chunks. +If a documentation chunk does not continue the current paragraph, +{\tt noweave} inserts [[\nwdocspar]], which uses +[[\filbreak]] in an attempt to keep the documentation chunk on the +same page as the code chunk that follows it. (The code chunk will +have another [[\filbreak]] after it---see [[\nwbegincode]].) +[[\nwbegindocs]] doesn't start a +new paragraph if the previous chunk didn't end one, i.e.\ didn't enter +vmode; if it does start a new one, it's only indented by the use of +[[\nwdocspar]]. +<<noweb.sty>>= +\def\nwbegindocs#1{\ifvmode\noindent\fi} +\let\nwenddocs=\relax +\let\nwdocspar=\filbreak +@ %def \nwbegindocs \nwdocspar \nwenddocs +The page-breaking strategy implies ragged bottom pages, so we should +turn it on in general (this is relevant for the {\tt report} style): +<<noweb.sty>>= +\raggedbottom +<<nwmac.tex>>= +\def\nwdocspar{\par\semifilbreak} +@ + +{\tt noweave} doesn't bracket quoted code with [[\code]] and [[\edoc]] any more. +It probably should do something nifty, just to make {\TeX} hackers happy, but it doesn't. +<<noweb.sty>>= +\def\code{\leavevmode\begingroup\setupcode\@vobeyspaces\obeylines} +\let\edoc=\endgroup +@ +\subsection{The {\tt noweb} page style} +Headers contain file name, date, and page number. +{\tt noweave} emits [[\nwfilename{]]{\em name}[[}]] for each new file. +In the {\tt noweb} page style, new files cause page breaks; +otherwise they are ignored. +<<noweb.sty>>= +\newdimen\@original@textwidth +\def\ps@noweb{% + \@original@textwidth=\textwidth + \let\@mkboth\@gobbletwo + \def\@oddfoot{}\def\@evenfoot{}% No feet. + \if@twoside % If two-sided printing. + \def\@evenhead{\hbox to \@original@textwidth{% + \Rm \thepage\qquad{\Tt\leftmark}\hfil\today}}% Left heading. + \def\@oddhead{\hbox to \@original@textwidth{% + \Rm \today\hfil{\Tt\leftmark}\qquad\thepage}}% Right heading. + \else % If one-sided printing. + \def\@oddhead{\hbox to \@original@textwidth{% + \Rm \today\hfil{\Tt\leftmark}\qquad\thepage}}% Right heading. + \let\@evenhead\@oddhead + \fi + \let\chaptermark\@gobble + \let\sectionmark\@gobble + \let\subsectionmark\@gobble + \let\subsubsectionmark\@gobble + \let\paragraphmark\@gobble + \let\subparagraphmark\@gobble + \def\nwfilename{\begingroup\let\do\@makeother\dospecials + \catcode`\{=1 \catcode`\}=2 \nw@filename} + \def\nw@filename##1{\endgroup\markboth{##1}{##1}\let\nw@filename=\nw@laterfilename}% +} +\def\nw@laterfilename#1{\endgroup\clearpage \markboth{#1}{#1}} +\let\nwfilename=\@gobble +@ %def \@original@textwidth \ps@noweb \nwfilename +@ +\subsection{Chunk cross-reference} +[[\nwalsodefined]], [[\nwused]], and [[\nwnotused]] are emitted by the {\tt +noweb} cross-referencers. (What arguments?) +If unused chunks are output chunks, a filter can slip in +[[\let\nwnotused\nwoutput]]. +The style uses [[\nwcodecomment]] for all annotations that follow code +chunks. +Fiddling with it can change the appearance of the output. +Note that [[\nwcodecomment]] is used after [[\nwbegincode]], with +[[\obeylines]] in efect. Since linebreaking can occur here, we need +to change the [[\interlinepenalty]]. +A little vertical space ([[\nwcodecommentsep]]\stylehook) appears before the first +comment. + +We firkled with [[\rightskip]] in [[\nwbegincode]] above; now we want to +reset it so that paragraphs are the normal width ([[\textwidth]], +possibly less [[\codemargin]]) and set ragged right. This is done as +usuall by making [[\rightskip]] naturally zero but stretchable. +<<noweb.sty>>= +\def\nwcodecomment#1{\@@par\penalty\nwcodepenalty + <<add [[\nwcodecommentsep]] if this is the first [[\nwcodecomment]]>>% + \hspace{-\codemargin}{% + \rightskip=0pt plus1in + \interlinepenalty\nwcodepenalty + \let\\\relax\footnotesize\Rm #1\@@par\penalty\nwcodepenalty}} +@ %def \nwcodecomment +This stuff is used at the end of a chunk. +<<noweb.sty>>= +\def\@nwalsodefined#1{\nwcodecomment{This definition is continued \nwpageprep\ \@pagesl{#1}.}} +\def\@nwused#1{\nwcodecomment{This code is used \nwpageprep\ \@pagesl{#1}.}} +\def\@nwnotused#1{\nwcodecomment{Root chunk (not used in this document).}} +\def\nwoutput#1{\nwcodecomment{This code is written to file {\Tt \@stripstar#1*\stripped}.}} +\def\@stripstar#1*#2\stripped{#1} +@ %def \nwalsodefined \nwused \nwnotused \nwoutput +<<add [[\nwcodecommentsep]] if this is the first [[\nwcodecomment]]>>= +\if@firstnwcodecomment + \vskip\nwcodecommentsep\penalty\nwcodepenalty\@firstnwcodecommentfalse +\fi +@ +This stuff on the definition line. +Note the hooks\stylehook{} for pointer styles. +<<noweb.sty>>= +\newcommand{\nwprevdefptr}[1]{% + \mbox{$\mathord{\triangleleft}\,\mathord{\mbox{\subpageref{#1}}}$}} +\newcommand{\nwnextdefptr}[1]{% + \mbox{$\mathord{\mbox{\subpageref{#1}}}\,\mathord{\triangleright}$}} + +\newcommand{\@nwprevnextdefs}[2]{% + {\nwtagstyle + \ifx\relax#1\else ~~\nwprevdefptr{#1}\fi + \ifx\relax#2\else ~~\nwnextdefptr{#2}\fi}} +\newcommand{\@nwusesondefline}[1]{{\nwtagstyle~~(\@pagenumsl{#1})}} +\newcommand{\@nwstartdeflinemarkup}{\nobreak\hskip 1.5em plus 1fill\nobreak} +\newcommand{\@nwenddeflinemarkup}{\nobreak\hskip \nwdefspace minus\nwdefspace\nobreak} +@ +And here are the options we use to choose one or the other. +<<noweb.sty>>= +\def\nwopt@longxref{% + \let\nwalsodefined\@nwalsodefined + \let\nwused\@nwused + \let\nwnotused\@nwnotused + \let\nwprevnextdefs\@gobbletwo + \let\nwusesondefline\@gobble + \let\nwstartdeflinemarkup\relax + \let\nwenddeflinemarkup\relax +} +\def\nwopt@shortxref{% + \let\nwalsodefined\@gobble + \let\nwused\@gobble + \let\nwnotused\@gobble + \let\nwprevnextdefs\@nwprevnextdefs + \let\nwusesondefline\@nwusesondefline + \let\nwstartdeflinemarkup\@nwstartdeflinemarkup + \let\nwenddeflinemarkup\@nwenddeflinemarkup +} +\nwopt@shortxref % to hell with backward compatibility! +@ \iffalse +<<man page: [[\noweboptions]]>>= +.TP +.B longxref, shortxref +Use either long, Knuth-style chunk cross-reference, or short, +Hanson-style chunk cross-reference. +The former uses small paragraphs after the chunk; +the latter uses symbols on the definition line. +Defaults to +.B shortxref. +@ \fi +<<noweb.sty>>= +\newskip\nwcodecommentsep \nwcodecommentsep=3pt plus 1pt minus 1pt +\newif\if@firstnwcodecomment\@firstnwcodecommenttrue +@ +\subsection{Page ranges} +The goal is to combine sub-page numbers in a way that makes sense. +Multiple sub-pages of one page become that page, and individual +pages are combined into ranges. +(A range may be only one page.) +<<noweb.sty>>= +\newcount\@nwlopage\newcount\@nwhipage % range lo..hi-1 +\newcount\@nwlosub % subpage of lo +\newcount\@nwhisub % subpage of hi +\def\@nwfirstpage#1#2{% subpage page + \@nwlopage=#2 \@nwlosub=#1 + \advance\@nwpagecount by \@ne + <<$\mbox{[[\@nwhipage]]} := \mbox{[[\@nwlopage]]}+1$>>} +\def\@nwnextpage#1#2{% subpage page + \ifnum\@nwhipage=#2 + \advance\@nwhipage by \@ne \advance\@nwpagecount by \@ne \@nwhisub=#1 \else + \ifnum#2<\@nwlopage <<new range starting with [[#2]]>>\else + \ifnum#2>\@nwhipage <<new range starting with [[#2]]>>\else + \@nwlosub=0 \@nwhisub=0 + \fi\fi\fi + } +<<new range starting with [[#2]]>>= +<<add range to range list>>\@nwfirstpage{#1}{#2} +<<$\mbox{[[\@nwhipage]]} := \mbox{[[\@nwlopage]]}+1$>>= +\@nwhipage=\@nwlopage\advance\@nwhipage by \@ne +<<add range to range list>>= +<<set [[\@tempa]] to page range(s), marked with [[\\]]>>% +\edef\@tempa{\noexpand\nwix@cons\noexpand\nw@pages{\@tempa}}\@tempa +<<set [[\@tempa]] to page range(s), marked with [[\\]]>>= +\advance\@nwhipage by \m@ne +\ifnum\@nwhipage=\@nwlopage + \edef\@tempa{\noexpand\noexpand\noexpand\\% + {\nwthepagenum{\number\@nwlosub}{\number\@nwlopage}}}% +\else + \count@=\@nwhipage \advance\count@ by \m@ne + \ifnum\count@=\@nwlopage % consecutive pages + \edef\@tempa{\noexpand\noexpand\noexpand\\% + {\nwthepagenum{\number\@nwlosub}{\number\@nwlopage}}% + \noexpand\noexpand\noexpand\\% + {\nwthepagenum{\number\@nwhisub}{\number\@nwhipage}}}% + \else <<use rules from Chicago style manual>>% + \fi +\fi +<<use rules from Chicago style manual>>= +\ifnum\@nwlopage<110 <<normal range>>\else + \count@=\@nwlopage \divide\count@ by 100 \multiply\count@ by 100 + \ifnum\count@=\@nwlopage <<normal range>>\else + \count@=\@nwlopage \divide\count@ by 100 + \@nwpagetemp=\@nwhipage \divide\@nwpagetemp by 100 + \ifnum\count@=\@nwpagetemp % lo--least 2 digits of hi + \multiply\@nwpagetemp by 100 + \advance \@nwhipage by -\@nwpagetemp + <<normal range>>% + \else <<normal range>>% + \fi + \fi +\fi +<<normal range>>= +\edef\@tempa{\noexpand\noexpand\noexpand\\{\number\@nwlopage--\number\@nwhipage}} +<<noweb.sty>>= +\newcount\@nwpagetemp +@ +The sequence [[\@pagesl]] makes a range of pages from a list of labels. +[[\subpages]] works from a list of [[{{subpage}{page}}]]. +<<noweb.sty>>= +\newcount\@nwpagecount +\def\@nwfirstpagel#1{% label + \@ifundefined{r@#1}{<<warn of undefined reference to [[#1]] and add page ??>>}{% + \edef\@tempa{\noexpand\@nwfirstpage\subpagepair{#1}}\@tempa}} +\def\@nwnextpagel#1{% label + \@ifundefined{r@#1}{<<warn of undefined reference to [[#1]] and add page ??>>}{% + \edef\@tempa{\noexpand\@nwnextpage\subpagepair{#1}}\@tempa}} +\def\@pagesl#1{% list of labels + \gdef\nw@pages{}\@nwpagecount=0 + \def\\##1{\@nwfirstpagel{##1}\let\\=\@nwnextpagel}#1% + <<add range to range list>>\let\\=\relax + \nwpageword\ifnum\@nwpagecount=1 \else s\fi~\commafy{\nw@pages}} +\def\@pagenumsl#1{% list of labels -- doesn't include word `pages', commas, or `and' + \gdef\nw@pages{}\@nwpagecount=0 + \def\\##1{\@nwfirstpagel{##1}\let\\=\@nwnextpagel}#1% + <<add range to range list>>\def\\{\let\\=~}\nw@pages} +\def\subpages#1{% list of {{subpage}{page}} + \gdef\nw@pages{}\@nwpagecount=0 + \def\\##1{\edef\@tempa{\noexpand\@nwfirstpage##1}\@tempa + \def\\####1{\edef\@tempa{\noexpand\@nwnextpage####1}\@tempa}}#1% + <<add range to range list>>\let\\=\relax + \nwpageword\ifnum\@nwpagecount=1 \else s\fi~\commafy{\nw@pages}} +\def\@nwaddrange{<<add range to range list>>} +@ +[[\nwpageword]] and [[\nwpageprep]] let you change the wording of the cross-reference +information. +<<noweb.sty>>= +\def\nwpageword{chunk} % was page +\def\nwpageprep{in} % was on +<<warn of undefined reference to [[#1]] and add page ??>>= +<<warn of undefined reference to [[#1]]>>% +\nwix@cons\nw@pages{\\{\bf ??}} +@ +\subsection{Sub-page references} +This is the wonderful code that Dave Love provided to make page +references like 7a, 7b, and so on. + +This code +provides a mechanism for defining `page +sub-references' using [[\sublabel{foo}]] referenced with +[[\subpageref{foo}]]. Sub-references will be numbered like these real +examples: \subpageref{ref:foo}, \subpageref{ref:bar}, +\subpageref{ref:baz}\sublabel{ref:foo}\sublabel{ref:bar}\sublabel{ref:baz} +etc.\ unless there is only one on the page, in which case the letter +will be dropped like this: \subpageref{ref:fred}. + +To be able to use [[\subpageref]] we must define the label with +[[\sublabel]], used like label. (Using +[[\ref]] with a label defined by [[\sublabel]] will +produce the sub-reference number, by the way, and [[\pageref]] +works as expected.) Note that +[[\subpageref]] is robust and [[\ref]] and [[\pageref]] are redefined to be +robust also, as they will be in future \LaTeX{} releases. +Incidentally, these expand to the relevant text plus [[\null]]---you +might want to strip this off, e.g.\ for sorting lists. + + +There are various ways we could attack this task (which is made +non-trivial by the well-known asynchrony of (La)\TeX's output +routine), but +they all must depend on hacks in the [[.aux]] file or a similar one. +Joachim Schrod's [[fnpag.sty]] does the same sort of thing differently +to this \LaTeX-specific approach. See [[latex.tex]] for enlightenment +on the cross-referencing mechanism and the \LaTeX{} internals used +below. [DL: The internals change in \LaTeX2e compared with +\LaTeX~2.09. The code here still works, though.] + +@ +The [[\subpageref]] macro first does a normal [[\pageref]]. If the +reference is actually defined, it then goes on to check whether the +control sequence [[2on]]\LA{}{page referenced}\RA{} is defined and sets the +[[\ref]] value to get [[a]] etc.\ if so. The magic, of course, is in +defining the [[2on]] bit appropriately. +[[\subpageref]] also tries to include the right hyperstuff for xhdvi. +<<noweb.sty>>= +\newcommand{\subpageref}[1]{% + \nwhyperreference{#1}{% + \@ifundefined{r@#1}% + {\pageref{#1}}% + {\@ifundefined{2on\@pageref{#1}}% + {\pageref{#1}}% + {\expandafter\expandafter\expandafter\nwthepagenum\csname r@#1\endcsname}}}} +@ %def \subpageref +[[\subpagepair]] produces a [[{subpage}{page}]] pair. +<<noweb.sty>>= +\newcommand{\subpagepair}[1]{% % produces {subpage}{page} + \@ifundefined{r@#1}% + {{0}{0}}% + {\@ifundefined{2on\@pageref{#1}}% + {{0}{\expandafter\expandafter\expandafter\@cdr\csname r@#1\endcsname\@nil}}% + {\@nameuse{r@#1}}}} +@ +[[\@pageref]] is like [[\pageref]], but it expands to [[\relax]] without a warning +if the reference is undefined. +<<noweb.sty>>= +\def\@pageref#1{\expandafter\expandafter\expandafter + \@cdr\csname r@#1\endcsname\@nil} +@ %def \@pageref +@ +[[\sublabel]] is like the [[\label]] command, except that it writes +[[\newsublabel]] onto the [[.aux]] file rather than [[\newlabel]]. +For hyperreferencing, all labels must be hypertext +anchors, for which we use [[\nwblindhyperanchor]]. +<<noweb.sty>>= +\newcommand{\sublabel}[1]{% + \nwblindhyperanchor{#1}% + \@bsphack\if@filesw {\let\thepage\relax + \def\protect{\noexpand\noexpand\noexpand}% + \edef\@tempa{\write\@auxout{\string + \newsublabel{#1}{{}{\thepage}}}}% + \expandafter}\@tempa + \if@nobreak \ifvmode\nobreak\fi\fi\fi\@esphack} +@ %def \sublabel +[[\nosublabel]] creates a label with a sub-page part of~0. +<<noweb.sty>>= +\newcommand{\nosublabel}[1]{% + \@bsphack\if@filesw {\let\thepage\relax + \def\protect{\noexpand\noexpand\noexpand}% + \edef\@tempa{\write\@auxout{\string + \newlabel{#1}{{0}{\thepage}}}}% + \expandafter}\@tempa + \if@nobreak \ifvmode\nobreak\fi\fi\fi\@esphack} +@ %def \sublabel +@ +[[\newsublabel]] is the macro that does the important work. It is called with the +same sort of arguments as [[\newlabel]]: the first argument is the +label name and the second is [[{]]\LA ref value[[}{]]page number\RA[[}]]. +(Note that the only definition here which needs to be +global is the one which is, and that [[\global]] is redefined by +[[\enddocument]], which will bite you if you use it\dots) +<<noweb.sty>>= +<<definition of [[\newsublabel]]>> +@ +First we extract the page number into [[\this@page]]. +<<definition of [[\newsublabel]]>>= +\newcommand{\newsublabel}[2]{% + \edef\this@page{\@cdr#2\@nil}% +@ %def \newsublabel +@ +Then we see whether it's changed from the value of [[\last@page]] +which was stashed away by the last [[\newsublabel]] (or is [[\relax]] if +this is the first one). If the page has changed, we reset the +counter [[\sub@page]] telling us how many sub-labels there have been +on the page. +<<definition of [[\newsublabel]]>>= + \ifx\this@page\last@page\else + \sub@page=\z@ + \fi + \edef\last@page{\this@page} + \advance\sub@page by \@ne +@ +If we've had at least two on the page, we define the +[[2on]]\LA{}{page no.}\RA{} macro to indicate the fact. +<<definition of [[\newsublabel]]>>= + \ifnum\sub@page=\tw@ + \global\@namedef{2on\this@page}{}% + \fi +@ +Then we write a normal [[\newlabel]] with the sub-reference as the +normal reference value in the second argument. +<<definition of [[\newsublabel]]>>= + \edef\@tempa{\noexpand\newlabel{#1}% + {{\number\sub@page}{\this@page}}}% + \@tempa} +@ +We need to define these. +<<noweb.sty>>= +\def\last@page{\relax} +\newcount\sub@page +@ %def \last@page \sub@page +@ +We use Rainer's new expandable definitions of [[\ref]] and +[[\pageref]] to minimise the risk of nasty surprises. +<<noweb.sty>>= +% RmS 92/08/14: made \ref and \pageref robust +\def\ref#1{\@ifundefined{r@#1}{{\bf ??}<<warn of undefined reference to [[#1]]>>}% + {\expandafter\expandafter\expandafter + \@car\csname r@#1\endcsname\@nil\null}} +\def\pageref#1{\@ifundefined{r@#1}{{\bf ??}<<warn of undefined reference to [[#1]]>>}% + {\expandafter\expandafter\expandafter + \@cdr\csname r@#1\endcsname\@nil\null}} +\def\@refpair#1{\@ifundefined{r@#1}{{0}{0}<<warn of undefined reference to [[#1]]>>}% + {\@nameuse{r@#1}}} +<<warn of undefined reference to [[#1]]>>= +\@warning{Reference `#1' on page \thepage \space undefined} +@ %def \ref \pageref +@ + +Here a a couple of hooks for formatting sub-page numbers, +which can be alphbetic, numeric, or omitted.\stylehook +<<noweb.sty>>= +\def\@alphasubpagenum#1#2{#2\ifnum#1=0 \else\@alph{#1}\fi} +\def\@nosubpagenum#1#2{#2} +\def\@numsubpagenum#1#2{#2\ifnum#1=0 \else.\@arabic{#1}\fi} +\def\nwopt@nosubpage{\let\nwthepagenum=\@nosubpagenum\nwopt@nomargintag} +\def\nwopt@numsubpage{\let\nwthepagenum=\@numsubpagenum} +\def\nwopt@alphasubpage{\let\nwthepagenum=\@alphasubpagenum} +\nwopt@alphasubpage +@ %def \nwthepagenum nosubpage numsubpage alphasubpage +\iffalse +<<man page: [[\noweboptions]]>>= +.TP +.B alphasubpage, numsubpage, nosubpage +Number chunks by the number of the page on which they appear, +followed by an alphabetic (numeric, not used) ``sub-page'' indicator. +Defaults to +.B alphasubpage. +.B nosubpage +implies +.B nomargintag. +@ \fi +@ + +\subsection{{\tt WEB}-like chunk numbering} +Here's a righteous hack: we get the effect of WEB-like chunk numbers +just by redefining [[\sublabel]] to use a counter instead of the current page number. +Since the numbers are all distinct, no sub-page number is ever used. +<<noweb.sty>>= +\newcount\nw@chunkcount +\nw@chunkcount=\@ne +\newcommand{\weblabel}[1]{% + \@bsphack\if@filesw {\let\thepage\relax + \def\protect{\noexpand\noexpand\noexpand}% + \edef\@tempa{\write\@auxout{\string + \newsublabel{#1}{{}{\number\nw@chunkcount}}}}% + \expandafter}\@tempa + \global\advance\nw@chunkcount by \@ne + \if@nobreak \ifvmode\nobreak\fi\fi\fi\@esphack} +\def\nwopt@webnumbering{\let\sublabel=\weblabel\def\nwpageword{chunk}\def\nwpageprep{in}} +@ %def \weblabel webnumbering +\iffalse +<<man page: [[\noweboptions]]>>= +.TP +.B webnumbering +Number chunks consecutively, in +.I WEB +style, instead of using sub-page numbers. +@ \fi +@ +\subsection{Indexing (identifier cross-reference) support} + +\subsubsection{Tracking definitions and uses} +All index definitions and uses are associated with +a label defined with [[\sublabel]] or [[\nosublabel]]. +Either the label is the [[\sublabel]] of the code chunk in which the definition or use +appears, or it is a [[\nosublabel]] appearing in the middle of a +documentation chunk. +<<noweb.sty>>= +% \nwindexdefn{printable name}{identifying label}{label of chunk} +% \nwindexuse{printable name}{identifying label}{label of chunk} + +\def\nwindexdefn#1#2#3{\@auxix{\protect\nwixd}{#2}{#3}} +\def\nwindexuse#1#2#3{\@auxix{\protect\nwixu}{#2}{#3}} + +\def\@auxix#1#2#3{% {marker}{id label}{subpage label} + \@bsphack\if@filesw {\let\nwixd\relax\let\nwixu\relax + \def\protect{\noexpand\noexpand\noexpand}% + \edef\@tempa{\write\@auxout{\string\nwixadd{#1}{#2}{#3}}}% + \expandafter}\@tempa + \if@nobreak \ifvmode\nobreak\fi\fi\fi\@esphack} +@ %def \nwindexdefn \nwindexuse \@auxix +<<noweb.sty>>= +% \nwixadd{marker}{idlabel}{subpage label} +\def\nwixadd#1#2#3{% + \@ifundefined{nwixl@#2}% + {\global\@namedef{nwixl@#2}{#1{#3}}}% + {\expandafter\nwix@cons\csname nwixl@#2\endcsname{#1{#3}}}} +@ %def \nwixadd +@ +\subsubsection{Writing lists with commas and ``and''} +You get one of +\begin{itemize} +\item ``$a$'' +\item ``$a$ and $b$'' +\item ``$a$, $\ldots$, $b$, and $c$'' +\end{itemize} +Plus [[\\]] is applied to each element of the list. +<<noweb.sty>>= +\newcount\@commacount +\def\commafy#1{% + {\nwix@listcount{#1}\@commacount=\nwix@counter + \let\@comma@each=\\% + \ifcase\@commacount\let\\=\@comma@each\or\let\\=\@comma@each\or + \def\\{\def\\{ and \@comma@each}\@comma@each}\else + \def\\{\def\\{, % + \advance\@commacount by \m@ne + \ifnum\@commacount=1 and~\fi\@comma@each}\@comma@each}\fi + #1}} +@ %def \@commacount \commafy + +\subsubsection{New, improved index code} +There are two kinds of lists. +One kind is a generic list in which elements are preceded by [[\\]]. +If the elements are index elements, they are {\em[[{]]printable +identifier[[}{]]label[[}]]} pairs. +The other kind is a list of sub-page labels, in which each +element is preceded by either [[\nwixd]] or [[\nwixu]]. +<<noweb.sty>>= +\def\nwix@cons#1#2{% {list}{\marker{element}} + {\toks0=\expandafter{#1}\def\@tempa{#2}\toks2=\expandafter{\@tempa}% + \xdef#1{\the\toks0 \the\toks2 }}} +@ %def \nwix@cons +The reference list for an identifier labelled {\em id} +is always called [[\nwixl@]]{\em id}. +Most applications will work with reference lists by applying [[\\]] +either to the defs or to the uses. +<<noweb.sty>>= +\def\nwix@uses#1{% {label} + \def\nwixu{\\}\let\nwixd\@gobble\@nameuse{nwixl@#1}} +\def\nwix@defs#1{% {label} + \def\nwixd{\\}\let\nwixu\@gobble\@nameuse{nwixl@#1}} +@ %def \nwix@uses \nwix@defs + +Some applications count uses to see whether there is any need to +display information. +<<noweb.sty>>= +\newcount\nwix@counter +\def\nwix@listcount#1{% {list with \\} + {\count@=0 + \def\\##1{\advance\count@ by \@ne }% + #1\global\nwix@counter=\count@ }} +\def\nwix@usecount#1{\nwix@listcount{\nwix@uses{#1}}} +\def\nwix@defcount#1{\nwix@listcount{\nwix@defs{#1}}} +@ %def \nwix@listcount \nwix@usecount \nwix@defcount +@ +\subsubsection{Supporting a mini-index at the end of each chunk} +When displaying identifiers used, show the identifier and its +definitions. +<<noweb.sty>>= +\def\nwix@id@defs#1{% index pair + {{\Tt \@car#1\@nil}% + \def\\##1{~\subpageref{##1}}\nwix@defs{\@cdr#1\@nil}}} +\def\nwidentuses#1{% list of index pairs + \nwcodecomment{Uses \let\\=\nwix@id@defs\commafy{#1}.}} +@ %def \nwidentuses \nwix@id@defs +The definitions section is a bit more complex, because it is omitted +if none of the identifiers defined is ever used. +<<noweb.sty>>= +\def\nwix@totaluses#1{% list of index pairs + {\count@=0 + \def\\##1{\nwix@usecount{\@cdr##1\@nil}\advance\count@ by\nwix@counter}% + #1\global\nwix@counter\count@ }} +\def\nwix@id@uses#1#2{% {ident}{label} + \nwix@usecount{#2}\ifnum\nwix@counter>0 + {\advance\leftskip by \codemargin + \nwcodecomment{{\Tt #1}, used \nwpageprep\ \@pagesl{\nwix@uses{#2}}.}}% + \else + \ifnw@hideunuseddefs\else + {\advance\leftskip by \codemargin \nwcodecomment{{\Tt #1}, never used.}}% + \fi + \fi} +\def\nwidentdefs#1{% list of index pairs + \ifnw@hideunuseddefs\nwix@totaluses{#1}\else\nwix@listcount{#1}\fi + \ifnum\nwix@counter>0 + \nwcodecomment{Defines:}% + {\def\\##1{\nwix@id@uses ##1}#1}% + \fi} +<<noweb.sty>>= +\newif\ifnw@hideunuseddefs\nw@hideunuseddefsfalse +\def\nwopt@hideunuseddefs{\nw@hideunuseddefstrue} +@ +\iffalse +<<man page: [[\noweboptions]]>>= +.TP +.B hideunuseddefs +Omit defined but unused identifiers from +the local identifier cross-reference (Preston Briggs). +@ \fi +<<noweb.sty>>= +\def\nwopt@noidentxref{% + \let\nwidentdefs\@gobble + \let\nwidentuses\@gobble} +@ +\iffalse +<<man page: [[\noweboptions]]>>= +.TP +.B noidentxref +Omit the local identifier cross-reference which follows each code chunk. +@ \fi + +\subsubsection{Support for chunk and identifier indices} +The index in the back shows absolutely all the pages. +<<noweb.sty>>= +\def\nw@underlinedefs{% {list with \nwixd, \nwixu} + \let\\=\relax\def\nw@comma{, } + \def\nwixd##1{\\\underline{\subpageref{##1}}\let\\\nw@comma}% + \def\nwixu##1{\\\subpageref{##1}\let\\\nw@comma}} + +\def\nw@indexline#1#2{% + {\indent {\Tt #1}: \nw@underlinedefs\@nameuse{nwixl@#2}\par}} + +\newenvironment{thenowebindex}{\parindent=-10pt \parskip=\z@ + \advance\leftskip by 10pt + \advance\rightskip by 0pt plus1in\par\@afterindenttrue + \def\\##1{\nw@indexline##1}}{} +@ +The information comes from the list [[nwisx@i]]. +<<noweb.sty>>= +\def\nowebindex{% + \@ifundefined{nwixs@i}% + {\@warning{The \string\nowebindex\space is empty}}% + {\begin{thenowebindex}\@nameuse{nwixs@i}\end{thenowebindex}}} +@ +Here's a more efficient version for the external case: +<<noweb.sty>>= +\def\nowebindex@external{% + {\let\nwixadds@c=\@gobble + \def\nwixadds@i##1{\nw@indexline##1}% + \def\nwixaddsx##1##2{\@nameuse{nwixadds@##1}{##2}}% + \begin{thenowebindex}\@input{\jobname.nwi}\end{thenowebindex}}} +@ +That list ([[nwisx@i]]) is created by calls to [[\nwixlogsorted{i}]]. +<<noweb.sty>>= +\def\nwixlogsorted#1#2{% list data + \@bsphack\if@filesw + \toks0={#2}\immediate\write\@auxout{\string\nwixadds{#1}{\the\toks0}} + \if@nobreak \ifvmode\nobreak\fi\fi\fi\@esphack} +@ +[[nwixs@c]] and [[nwixs@i]] are sorted lists of chunks and identifiers, respectively. +<<noweb.sty>>= +\def\nwixadds#1#2{% + \@ifundefined{nwixs@#1}% + {\global\@namedef{nwixs@#1}{\\{#2}}}% + {\expandafter\nwix@cons\csname nwixs@#1\endcsname{\\{#2}}}} +\let\nwixaddsx=\@gobbletwo +@ +If an external index is used, we need a [[.nwi]] file, +[[\nwixadds]] is to be ignored, and we use [[\nwixaddsx]]. +<<noweb.sty>>= +\def\nwopt@externalindex{% + \ifx\nwixadds\@gobbletwo % already called + \else + \let\nwixaddsx=\nwixadds \let\nwixadds=\@gobbletwo + \let\nowebindex=\nowebindex@external + \let\nowebchunks=\nowebchunks@external + \fi} +@ +\iffalse +<<man page: [[\noweboptions]]>>= +.TP +.B externalindex +Use an index generated with +.I noindex(1) +(q.v.). +@ \fi +@ +<<noweb.sty>>= +\def\nowebchunks{% + \@ifundefined{nwixs@c}% + {\@warning{The are no \string\nowebchunks}}% + {\begin{thenowebchunks}\@nameuse{nwixs@c}\end{thenowebchunks}}} +\def\nowebchunks@external{% + {\let\nwixadds@i=\@gobble + \def\nwixadds@c##1{\nw@onechunk##1}% + \def\nwixaddsx##1##2{\@nameuse{nwixadds@##1}{##2}}% + \begin{thenowebchunks}\@input{\jobname.nwi}\end{thenowebchunks}}} + \@namedef{r@nw@notdef}{{0}{(never defined)}} +<<noweb.sty>>= +\def\nw@chunkunderlinedefs{% {list of labels with \nwixd, \nwixu} + \let\\=\relax\def\nw@comma{, } + \def\nwixd##1{\\\underline{\subpageref{##1}}\let\\\nw@comma}% + \def\nwixu##1{\\\subpageref{##1}\let\\\nw@comma}} +<<noweb.sty>>= +\def\nw@onechunk#1#2#3{% {name}{label of first definition}{list with \nwixd, \nwixu} + \@ifundefined{r@#2}{}{% + \indent\LA #1~{\nwtagstyle\subpageref{#2}}\RA + \if@nwlongchunks{~\nw@chunkunderlinedefs#3}\fi\par}} +<<noweb.sty>>= +\newenvironment{thenowebchunks}{\vskip3pt + \parskip=\z@\parindent=-10pt \advance\leftskip by 10pt + \advance\rightskip by 0pt plus10pt \@afterindenttrue + \def\\##1{\nw@onechunk##1}}{} +<<noweb.sty>>= +\newif\if@nwlongchunks +\@nwlongchunksfalse +\let\nwopt@longchunks\@nwlongchunkstrue +@ \iffalse +<<man page: [[\noweboptions]]>>= +.TP +.B longchunks +When expanding +.B "\\\\nowebchunks," +show page numbers of definitions and uses of each chunk. +@ \fi + +@ +\subsection{support for hypertext with {\tt hyper.sty}} +Initial support courtesy of Balasubramanian Narasimhan. +<<noweb.sty>>= +\newcommand\nwhyperreference[2]{% + \@ifundefined{hyperreference}% + {#2\global\let\nwhyperreference\@gobble}% + {\hyperreference{#1}{#2}\global\def\nwhyperreference\hyperreference}} +\newcommand\nwblindhyperanchor[1]{% + \@ifundefined{blindhyperanchor}% + {\global\let\nwblindhyperanchor\@gobble}% + {\blindhyperanchor{#1}\global\def\nwblindhyperanchor\blindhyperanchor}} +@ +\subsection{Support for hypertext translation to HTML} +<<noweb.sty>>= +\newcommand\nwanchorto{% + \begingroup\let\do\@makeother\dospecials + \catcode`\{=1 \catcode`\}=2 \nw@anchorto} +\newcommand\nw@anchorto[1]{\def\nw@next{#1}\endgroup\nw@anchortofin} +\newcommand\nw@anchortofin[1]{#1\footnote{See URL \texttt{\nw@next}.}} +\let\nwanchorname\@gobble +@ +\clearpage +\section{The {\tt nwmac} macros for use with plain {\TeX}} + +First we make [[@]] a letter so that we can use `private' macro names. +<<nwmac.tex>>= +\catcode`\@=11 +<<nwmac.tex>>= +% scale cmbx10 instead of using cmbx12 because {\LaTeX} does, so fonts exist +\font\twlbf=cmbx10 scaled \magstep1 +\font\frtbf=cmbx10 scaled \magstep2 +% These fonts don't work with xdvi! + +\advance\hoffset 0.5 true in +\advance\hsize -1.5 true in +\newdimen\textsize +\textsize=\hsize +\def\today{\ifcase\month\or + January\or February\or March\or April\or May\or June\or + July\or August\or September\or October\or November\or December\fi + \space\number\day, \number\year} +@ %def \textsize \today +<<nwmac.tex>>= +\long\def\ifundefined#1#2#3{% + \expandafter\ifx\csname#1\endcsname\relax + #2% + \else#3% + \fi} + +\ifundefined{myheadline} + {\headline={\hbox to \textsize{\tentt\firstmark\hfil\tenrm\today\hbox + to 4em{\hss\folio}}\hss}} + {\expandafter\headline\expandafter{\myheadline}} + +\ifundefined{myfootline} + {\footline={\hfil}} + {\expandafter\footline\expandafter{\myfootline}} +@ %def \ifundefined +<<nwmac.tex>>= +\def\semifilbreak{\vskip0pt plus1.5in\penalty-200\vskip0pt plus -1.5in} +\raggedbottom +@ %def \semifilbreak +<<nwmac.tex>>= +% +% \chapcenter macro to produce nice centered chapter titles +% +\def\chapcenter{\leftskip=0.5 true in plus 4em minus 0.5 true in + \rightskip=\leftskip + \parfillskip=0pt \spaceskip=.3333em \xspaceskip=.5em + \pretolerance=9999 \tolerance=9999 + \hyphenpenalty=9999 \exhyphenpenalty=9999} +@ %def \chapcenter +<<nwmac.tex>>= +% \startsection{LEVEL}{INDENT}{BEFORESKIP}{AFTERSKIP}{STYLE}{HEADING} +% #1 #2 #3 #4 #5 #6 +% +% LEVEL: depth; e.g. part=0 chapter=1 sectino=2... +% INDENT: indentation of heading from left margin +% BEFORESKIP: skip before header +% AFTERSKIP: skip after header +% STYLE: style of heading; e.g.\bf +% HEADING: heading of the sectino +% +\def\startsection#1#2#3#4#5#6{\par\vskip#3 plus 2in + \penalty-200\vskip 0pt plus -2in + \noindent{\leftskip=#2 \rightskip=0.5true in plus 4em minus 0.5 true in + \hyphenpenalty=9999 \exhyphenpenalty=9999 + #5#6\par}\vskip#4% + {\def\code##1{[[}\def\edoc##1{]]}\message{[#6]}} + \settocparms{#1} + \def\themodtitle{#6} +%%%% {\def\code{\string\code}\def\edoc{\string\edoc}% + \edef\next{\noexpand\write\cont{\tocskip + \tocline{\hskip\tocindent\tocstyle\relax\themodtitle} + {\noexpand\the\pageno}}}\next % write to toc + %} +} +@ %def \startsection +<<nwmac.tex>>= +\def\settocparms#1{ + \count@=#1 + \ifnum\count@<1 + \def\tocskip{\vskip3ptplus1in\penalty-100 + \vskip0ptplus-1in}% + \def\tocstyle{\bf} + \def\tocindent{0pt} + \else + \def\tocskip{} + \def\tocstyle{\rm} + \dimen@=2em \advance\count@ by \m@ne \dimen@=\count@\dimen@ + \edef\tocindent{\the\dimen@} + \fi +} +@ %def \settocparms +<<nwmac.tex>>= +\def\tocline#1#2{\line{{\ignorespaces#1}\leaders\hbox to .5em{.\hfil}\hfil + \hbox to1.5em{\hss#2}}} +@ %def \tocline +<<nwmac.tex>>= +\def\section#1{\par \vskip3ex\noindent {\bf #1}\par\nobreak\vskip1ex\nobreak} +\def\chapter#1{\vfil\eject\startsection{0}{0pt}{6ex}{3ex}{\frtbf\chapcenter}{#1}} +\def\section#1{\startsection{1}{0pt}{4ex}{2ex}{\twlbf}{#1}} +\def\subsection#1{\startsection{2}{0pt}{2ex}{1ex}{\bf}{#1}} +\def\subsubsection#1{\startsection{3}{0pt}{1ex}{0.5ex}{\it}{#1}} +\def\paragraph#1{\startsection{4}{0pt}{1.5ex}{0ex}{\it}{#1}} + +<<kernel>> + +\def\nwfilename#1{\vfil\eject\mark{#1}} + +\def\nwbegindocs#1{\filbreak} +\def\nwenddocs{\par} +\def\nwbegincode#1{\par\nobreak + \begingroup\setupcode\newlines\parindent=0pt\parskip=0pt + \let\oendmoddef=\endmoddef \let\oplusendmoddef=\plusendmoddef + \def\endmoddef{\oendmoddef\par}\def\plusendmoddef{\oplusendmoddef\par}% + \hsize=\codehsize\noindent\bchack} +\def\nwendcode{\endgroup} +{\catcode`\^^M=\active % make CR an active character + \gdef\bchack#1^^M{\relax#1}% +} +@ %def \section \chapter \section \subsection \subsubsection \paragraph +@ %def \nwbegindocs \nwenddocs \nwbegincode \nwendcode \nwfilename +<<nwmac.tex>>= +\edef\contentsfile{\jobname.toc } % file that gets table of contents info +\def\readcontents{\expandafter\input \contentsfile} + +\newwrite\cont +\openout\cont=\contentsfile +\write\cont{\string\catcode`\string\@=11}% a hack to make contents +@ %def \readcontents \cont +<<nwmac.tex>>= + % take stuff in plain.tex +\def\bye{% + \write\cont{}% ensure that the contents file isn't empty + \closeout\cont + \vfil\eject\pageno=-1 % new page causes contents to be really closed + \topofcontents\readcontents\botofcontents + \vfil\eject\end} +\def\topofcontents{\vfil\mark{{\bf Contents}}} +\def\botofcontents{} +@ %def \bye \topofcontents \botofcontents +<<nwmac.tex>>= +\let\em=\it +% used to produce an itemized (bulleted) list in plain {\TeX} +% such lists can be nested +% mostly useful with WEB + +% Usage: +% \itemize +% \item First thing +% \item second thing +% \enditemize + +\newcount\listlevel +\listlevel=0 +\newdimen\itemwidth +\itemwidth=3em + +\def\itemize{\begingroup\advance\listlevel by1 + \def\item{\par\noindent + \raise2pt\llap{$\scriptstyle\bullet$\ }\ignorespaces}% + \def\nameditem##1{\par\noindent + \llap{\rlap{##1}\hskip\itemwidth}\ignorespaces}% + \par\advance\leftskip by\itemwidth\advance\rightskip by0.5\itemwidth} +\def\enditemize{\par\endgroup\noindent\ignorespaces} + +\let\begindocument=\relax +@ %def \listlevel \itemwidth \itemize \enditemize +Finally we make [[@]] `other' again. +<<nwmac.tex>>= +\catcode`\@=12 +@ +\section{Chunks} \nowebchunks +\twocolumn[\section{Index}] +\nowebindex* +@ +\end{document} + + |