% \begin{meta-comment} % % $Id: mdwtools.tex,v 1.4 1996/11/19 20:55:55 mdw Exp $ % % Common declarations for mdwtools.dtx files % % (c) 1996 Mark Wooding % %----- Revision history ----------------------------------------------------- % % $Log: mdwtools.tex,v $ % Revision 1.4 1996/11/19 20:55:55 mdw % Entered into RCS % % % \end{meta-comment} % % \begin{meta-comment} %% %% mdwtools common declarations %% Copyright (c) 1996 Mark Wooding %% %% This program is free software; you can redistribute it and/or modify %% it under the terms of the GNU General Public License as published by %% the Free Software Foundation; either version 2 of the License, or %% (at your option) any later version. %% %% This program is distributed in the hope that it will be useful, %% but WITHOUT ANY WARRANTY; without even the implied warranty of %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %% GNU General Public License for more details. %% %% You should have received a copy of the GNU General Public License %% along with this program; if not, write to the Free Software %% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. %% % \end{meta-comment} % % \begin{meta-comment} %<*mdwtools> \ProvidesFile{mdwtools.tex} [1996/05/10 1.4 Shared definitions for mdwtools .dtx files] % % \end{meta-comment} % % \CheckSum{668} %% \CharacterTable %% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z %% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z %% Digits \0\1\2\3\4\5\6\7\8\9 %% Exclamation \! Double quote \" Hash (number) \# %% Dollar \$ Percent \% Ampersand \& %% Acute accent \' Left paren \( Right paren \) %% Asterisk \* Plus \+ Comma \, %% Minus \- Point \. Solidus \/ %% Colon \: Semicolon \; Less than \< %% Equals \= Greater than \> Question mark \? %% Commercial at \@ Left bracket \[ Backslash \\ %% Right bracket \] Circumflex \^ Underscore \_ %% Grave accent \` Left brace \{ Vertical bar \| %% Right brace \} Tilde \~} %% % % \section{Introduction and user guide} % % This file is really rather strange; it gets |\input| by other package % documentation files to set up most of the environmental gubbins for them. % It handles almost everything, like loading a document class, finding any % packages, and building and formatting the title. % % It also offers an opportunity for users to customise my nice documentation, % by using a |mdwtools.cfg| file (not included). % % % \subsection{Declarations} % % A typical documentation file contains something like % \begin{listinglist} \listingsize \obeylines % |\input{mdwtools}| % \ % |\mdwdoc| % \end{listinglist} % The initial |\input| reads in this file and sets up the various commands % which may be needed. The final |\mdwdoc| actually starts the document, % inserting a title (which is automatically generated), a table of % contents etc., and reads the documentation file in (using the |\DocInput| % command from the \package{doc} package. % % \subsubsection{Describing packages} % % \DescribeMacro{\describespackage} % \DescribeMacro{\describesclass} % \DescribeMacro{\describesfile} % \DescribeMacro{\describesfile*} % The most important declarations are those which declare what the % documentation describes. Saying \syntax{"\\describespackage{}"} % loads the \ (if necessary) and adds it to the auto-generated % title, along with a footnote containing version information. Similarly, % |\describesclass| adds a document class name to the title (without loading % it -- the document itself must do this, with the |\documentclass| command). % For files which aren't packages or classes, use the |\describesfile| or % |\describesfile*| command (the $*$-version won't |\input| the file, which % is handy for files like |mdwtools.tex|, which are already input). % % \DescribeMacro{\author} % \DescribeMacro{\date} % \DescribeMacro{\title} % The |\author|, |\date| and |\title| declarations work slightly differently % to normal -- they ensure that only the \emph{first} declaration has an % effect. (Don't you play with |\author|, please, unless you're using this % program to document your own packages.) Using |\title| suppresses the % automatic title generation. % % \DescribeMacro{\docdate} % The default date is worked out from the version string of the package or % document class whose name is the same as that of the documentation file. % You can choose a different `main' file by saying % \syntax{"\\docdate{""}"}. % % \subsubsection{Contents handling} % % \DescribeMacro{\addcontents} % A documentation file always has a table of contents. Other % contents-like lists can be added by saying % \syntax{"\\addcontents{""}{""}"}. The \ % is the file extension of the contents file (e.g., \lit{lot} for the % list of tables); the \ is the command to actually typeset the % contents file (e.g., |\listoftables|). % % \subsubsection{Other declarations} % % \DescribeMacro{\implementation} % The \package{doc} package wants you to say % \syntax{"\\StopEventually{""}"}' before describing the package % implementation. Using |mdwtools.tex|, you just say |\implementation|, and % everything works. It will automatically read in the licence text (from % |gpl.tex|, and wraps some other things up. % % % \subsection{Other commands} % % The |mdwtools.tex| file includes the \package{syntax} and \package{sverb} % packages so that they can be used in documentation files. It also defines % some trivial commands of its own. % % \DescribeMacro{\<} % Saying \syntax{"\\<"">" is the same as "\\synt{""}"}; this % is a simple abbreviation. % % \DescribeMacro{\smallf} % Saying \syntax{"\\smallf" "/"} typesets a little fraction, % like this: \smallf 3/4. It's useful when you want to say that the default % value of a length is 2 \smallf 1/2\,pt, or something like that. % % % \subsection{Customisation} % % You can customise the way that the package documentation looks by writing % a file called |mdwtools.cfg|. You can redefine various commands (before % they're defined here, even; |mdwtools.tex| checks most of the commands that % it defines to make sure they haven't been defined already. % % \DescribeMacro{\indexing} % If you don't want the prompt about whether to generate index files, you % can define the |\indexing| command to either \lit{y} or \lit{n}. I'd % recommend that you use |\providecommand| for this, to allow further % customisation from the command line. % % \DescribeMacro{\mdwdateformat} % If you don't like my date format (maybe you're American or something), % you can redefine the |\mdwdateformat| command. It takes three arguments: % the year, month and date, as numbers; it should expand to something which % typesets the date nicely. The default format gives something like % `10 May 1996'. You can produce something rather more exotic, like % `10\textsuperscript{th} May \textsc{\romannumeral 1996}' by saying %\begin{listing} %\newcommand{\mdwdateformat}[3]{% % \number#3\textsuperscript{\numsuffix{#3}}\ % % \monthname{#2}\ % % \textsc{\romannumeral #1}% %} %\end{listing} % \DescribeMacro{\monthname} % \DescribeMacro{\numsuffix} % Saying \syntax{"\\monthname{""}"} expands to the name of the % numbered month (which can be useful when doing date formats). Saying % \syntax{"\\numsuffix{""}"} will expand to the appropriate suffix % (`th' or `rd' or whatever) for the \. You'll have to superscript % it yourself, if this is what you want to do. Putting the year number % in roman numerals is just pretentious |;-)|. % % \DescribeMacro{\mdwhook} % After all the declarations in |mdwtools.tex|, the command |\mdwhook| is % executed, if it exists. This can be set up by the configuration file % to do whatever you want. % % There are lots of other things you can play with; you should look at the % implementation section to see what's possible. % % \implementation % % \section{Implementation} % % \begin{macrocode} %<*mdwtools> % \end{macrocode} % % The first thing is that I'm not a \LaTeX\ package or anything official % like that, so I must enable `|@|' as a letter by hand. % % \begin{macrocode} \makeatletter % \end{macrocode} % % Now input the user's configuration file, if it exists. This is fairly % simple stuff. % % \begin{macrocode} \@input{mdwtools.cfg} % \end{macrocode} % % Well, that's the easy bit done. % % % \subsection{Initialisation} % % Obviously the first thing to do is to obtain a document class. Obviously, % it would be silly to do this if a document class has already been loaded, % either by the package documentation or by the configuration file. % % The only way I can think of for finding out if a document class is already % loaded is by seeing if the |\documentclass| command has been redefined % to raise an error. This isn't too hard, really. % % \begin{macrocode} \ifx\documentclass\@twoclasseserror\else \documentclass[a4paper]{ltxdoc} \ifx\doneclasses\mdw@undefined\else\doneclasses\fi \fi % \end{macrocode} % % As part of my standard environment, I'll load some of my more useful % packages. If they're already loaded (possibly with different options), % I'll not try to load them again. % % \begin{macrocode} \@ifpackageloaded{doc}{}{\usepackage{doc}} \@ifpackageloaded{syntax}{}{\usepackage[rounded]{syntax}} \@ifpackageloaded{sverb}{}{\usepackage{sverb}} % \end{macrocode} % % % \subsection{Some macros for interaction} % % I like the \LaTeX\ star-boxes, although it's a pain having to cope with % \TeX's space-handling rules. I'll define a new typing-out macro which % makes spaces more significant, and has a $*$-version which doesn't put % a newline on the end, and interacts prettily with |\read|. % % First of all, I need to make spaces active, so I can define things about % active spaces. % % \begin{macrocode} \begingroup\obeyspaces % \end{macrocode} % % Now to define the main macro. This is easy stuff. Spaces must be % carefully rationed here, though. % % I'll start a group, make spaces active, and make spaces expand to ordinary % space-like spaces. Then I'll look for a star, and pass either |\message| % (which doesn't start a newline, and interacts with |\read| well) or % |\immediate\write 16| which does a normal write well. % % \begin{macrocode} \gdef\mdwtype{% \begingroup\catcode`\ \active\let \space% \@ifstar{\mdwtype@i{\message}}{\mdwtype@i{\immediate\write\sixt@@n}}% } \endgroup % \end{macrocode} % % Now for the easy bit. I have the thing to do, and the thing to do it to, % so do that and end the group. % % \begin{macrocode} \def\mdwtype@i#1#2{#1{#2}\endgroup} % \end{macrocode} % % % \subsection{Decide on indexing} % % A configuration file can decide on indexing by defining the |\indexing| % macro to either \lit{y} or \lit{n}. If it's not set, then I'll prompt % the user. % % First of all, I want a switch to say whether I'm indexing. % % \begin{macrocode} \newif\ifcreateindex % \end{macrocode} % % Right: now I need to decide how to make progress. If the macro's not set, % then I want to set it, and start a row of stars. % % \begin{macrocode} \ifx\indexing\@@undefined \mdwtype{*****************************} \def\indexing{?} \fi % \end{macrocode} % % Now enter a loop, asking the user whether to do indexing, until I get % a sensible answer. % % \begin{macrocode} \loop \@tempswafalse \if y\indexing\@tempswatrue\createindextrue\fi \if Y\indexing\@tempswatrue\createindextrue\fi \if n\indexing\@tempswatrue\createindexfalse\fi \if N\indexing\@tempswatrue\createindexfalse\fi \if@tempswa\else \mdwtype*{* Create index files? (y/n) *} \read\sixt@@n to\indexing% \repeat % \end{macrocode} % % Now, based on the results of that, display a message about the indexing. % % \begin{macrocode} \mdwtype{*****************************} \ifcreateindex \mdwtype{* Creating index files *} \mdwtype{* This may take some time *} \else \mdwtype{* Not creating index files *} \fi \mdwtype{*****************************} % \end{macrocode} % % Now I can play with the indexing commands of the \package{doc} package % to do whatever it is that the user wants. % % \begin{macrocode} \ifcreateindex \CodelineIndex \EnableCrossrefs \else \CodelineNumbered \DisableCrossrefs \fi % \end{macrocode} % % And register lots of plain \TeX\ things which shouldn't be indexed. % This contains lots of |\if|\dots\ things which don't fit nicely in % conditionals, which is a shame. Still, it doesn't matter that much, % really. % % \begin{macrocode} \DoNotIndex{\def,\long,\edef,\xdef,\gdef,\let,\global} \DoNotIndex{\if,\ifnum,\ifdim,\ifcat,\ifmmode,\ifvmode,\ifhmode,% \iftrue,\iffalse,\ifvoid,\ifx,\ifeof,\ifcase,\else,\or,\fi} \DoNotIndex{\box,\copy,\setbox,\unvbox,\unhbox,\hbox,% \vbox,\vtop,\vcenter} \DoNotIndex{\@empty,\immediate,\write} \DoNotIndex{\egroup,\bgroup,\expandafter,\begingroup,\endgroup} \DoNotIndex{\divide,\advance,\multiply,\count,\dimen} \DoNotIndex{\relax,\space,\string} \DoNotIndex{\csname,\endcsname,\@spaces,\openin,\openout,% \closein,\closeout} \DoNotIndex{\catcode,\endinput} \DoNotIndex{\jobname,\message,\read,\the,\m@ne,\noexpand} \DoNotIndex{\hsize,\vsize,\hskip,\vskip,\kern,\hfil,\hfill,\hss} \DoNotIndex{\m@ne,\z@,\z@skip,\@ne,\tw@,\p@} \DoNotIndex{\dp,\wd,\ht,\vss,\unskip} % \end{macrocode} % % Last bit of indexing stuff, for now: I'll typeset the index in two columns % (the default is three, which makes them too narrow for my tastes). % % \begin{macrocode} \setcounter{IndexColumns}{2} % \end{macrocode} % % % \subsection{Selectively defining things} % % I don't want to tread on anyone's toes if they redefine any of these % commands and things in a configuration file. The following definitions % are fairly evil, but should do the job OK. % % \begin{macro}{\@gobbledef} % % This macro eats the following |\def|inition, leaving not a trace behind. % % \begin{macrocode} \def\@gobbledef#1#{\@gobble} % \end{macrocode} % % \end{macro} % % \begin{macro}{\tdef} % \begin{macro}{\tlet} % % The |\tdef| command is a sort of `tentative' definition -- it's like % |\def| if the control sequence named doesn't already have a definition. % |\tlet| does the same thing with |\let|. % % \begin{macrocode} \def\tdef#1{ \ifx#1\@@undefined% \expandafter\def\expandafter#1% \else% \expandafter\@gobbledef% \fi% } \def\tlet#1#2{\ifx#1\@@undefined\let#1=#2\fi} % \end{macrocode} % % \end{macro} % \end{macro} % % % \subsection{General markup things} % % Now for some really simple things. I'll define how to typeset package % names and environment names (both in the sans serif font, for now). % % \begin{macrocode} \tlet\package\textsf \tlet\env\textsf % \end{macrocode} % % I'll define the |\<|\dots|>| shortcut for syntax items suggested in the % \package{syntax} package. % % \begin{macrocode} \tdef\<#1>{\synt{#1}} % \end{macrocode} % % And because it's used in a few places (mainly for typesetting lengths), % here's a command for typesetting fractions in text. % % \begin{macrocode} \tdef\smallf#1/#2{\ensuremath{^{#1}\!/\!_{#2}}} % \end{macrocode} % % % \subsection{A table environment} % % \begin{environment}{tab} % % Most of the packages don't use the (obviously perfect) \package{mdwtab} % package, because it's big, and takes a while to load. Here's an % environment for typesetting centred tables. The first (optional) argument % is some declarations to perform. The mandatory argument is the table % preamble (obviously). % % \begin{macrocode} \@ifundefined{tab}{% \newenvironment{tab}[2][\relax]{% \par\vskip2ex% \centering% #1% \begin{tabular}{#2}% }{% \end{tabular}% \par\vskip2ex% } }{} % \end{macrocode} % % \end{environment} % % % \subsection{Commenting out of stuff} % % \begin{environment}{meta-comment} % % Using |\iffalse|\dots|\fi| isn't much fun. I'll define a gobbling % environment using the \package{sverb} stuff. % % \begin{macrocode} \ignoreenv{meta-comment} % \end{macrocode} % % \end{environment} % % % \subsection{Float handling} % % This gubbins will try to avoid float pages as much as possible, and (with % any luck) encourage floats to be put on the same pages as text. % % \begin{macrocode} \def\textfraction{0.1} \def\topfraction{0.9} \def\bottomfraction{0.9} \def\floatpagefraction{0.7} % \end{macrocode} % % Now redefine the default float-placement parameters to allow `here' floats. % % \begin{macrocode} \def\fps@figure{htbp} \def\fps@table{htbp} % \end{macrocode} % % % \subsection{Other bits of parameter tweaking} % % Make \env{grammar} environments look pretty, by indenting the left hand % sides by a large amount. % % \begin{macrocode} \grammarindent1in % \end{macrocode} % % I don't like being told by \TeX\ that my paragraphs are hard to linebreak: % I know this already. This lot should shut \TeX\ up about most problems. % % \begin{macrocode} \sloppy \hbadness\@M \hfuzz10\p@ % \end{macrocode} % % Also make \TeX\ shut up in the index. The \package{multicol} package % irritatingly plays with |\hbadness|. This is the best hook I could find % for playing with this setting. % % \begin{macrocode} \expandafter\def\expandafter\IndexParms\expandafter{% \IndexParms% \hbadness\@M% } % \end{macrocode} % % The other thing I really don't like is `Marginpar moved' warnings. This % will get rid of them, and lots of other \LaTeX\ warnings at the same time. % % \begin{macrocode} \let\@latex@warning@no@line\@gobble % \end{macrocode} % % Put some extra space between table rows, please. % % \begin{macrocode} \def\arraystretch{1.2} % \end{macrocode} % % Most of the code is at guard level one, so typeset that in upright text. % % \begin{macrocode} \setcounter{StandardModuleDepth}{1} % \end{macrocode} % % % \subsection{Contents handling} % % I use at least one contents file (the main table of contents) although % I may want more. I'll keep a list of contents files which I need to % handle. % % There are two things I need to do to contents files here: % \begin{itemize} % \item I must typeset the table of contents at the beginning of the % document; and % \item I want to typeset tables of contents in two columns (using the % \package{multicol} package). % \end{itemize} % % The list consists of items of the form % \syntax{"\\do{""}{""}"}, where \ is the % file extension of the contents file, and \ is the command to % typeset it. % % \begin{macro}{\docontents} % % This is where I keep the list of contents files. I'll initialise it to % just do the standard contents table. % % \begin{macrocode} \def\docontents{\do{toc}{\tableofcontents}} % \end{macrocode} % % \end{macro} % % \begin{macro}{\addcontents} % % By saying \syntax{"\\addcontents{""}{""}"}, a document % can register a new table of contents which gets given the two-column % treatment properly. This is really easy to implement. % % \begin{macrocode} \def\addcontents#1#2{% \toks@\expandafter{\docontents\do{#1}{#2}}% \edef\docontents{\the\toks@}% } % \end{macrocode} % % \end{macro} % % % \subsection{Finishing it all off} % % \begin{macro}{\finalstuff} % % The |\finalstuff| macro is a hook for doing things at the end of the % document. Currently, it inputs the licence agreement as an appendix. % % \begin{macrocode} \tdef\finalstuff{\appendix\part*{Appendix}\input{gpl}} % \end{macrocode} % % \end{macro} % % \begin{macro}{\implementation} % % The |\implementation| macro starts typesetting the implementation of % the package(s). If we're not doing the implementation, it just does % this lot and ends the input file. % % I define a macro with arguments inside the |\StopEventually|, which causes % problems, since the code gets put through an extra level of |\def|fing % depending on whether the implementation stuff gets typeset or not. I'll % store the code I want to do in a separate macro. % % \begin{macrocode} \def\implementation{\StopEventually{\attheend}} % \end{macrocode} % % Now for the actual activity. First, I'll do the |\finalstuff|. Then, if % \package{doc}'s managed to find the \package{multicol} package, I'll add % the end of the environment to the end of each contents file in the list. % Finally, I'll read the index in from its formatted |.ind| file. % % \begin{macrocode} \tdef\attheend{% \finalstuff% \ifhave@multicol% \def\do##1##2{\addtocontents{##1}{\protect\end{multicols}}}% \docontents% \fi% \PrintIndex% } % \end{macrocode} % % \end{macro} % % % \subsection{File version information} % % \begin{macro}{\mdwpkginfo} % % For setting up the automatic titles, I'll need to be able to work out % file versions and things. This macro will, given a file name, extract % from \LaTeX\ the version information and format it into a sensible string. % % First of all, I'll put the original string (direct from the % |\Provides|\dots\ command). Then I'll pass it to another macro which can % parse up the string into its various bits, along with the original % filename. % % \begin{macrocode} \def\mdwpkginfo#1{% \edef\@tempa{\csname ver@#1\endcsname}% \expandafter\mdwpkginfo@i\@tempa\@@#1\@@% } % \end{macrocode} % % Now for the real business. I'll store the string I build in macros called % \syntax{"\\""date", "\\""version" and % "\\""info"}, which store the file's date, version and % `information string' respectively. (Note that the file extension isn't % included in the name.) % % This is mainly just tedious playing with |\expandafter|. The date format % is defined by a separate macro, which can be modified from the % configuration file. % % \begin{macrocode} \def\mdwpkginfo@i#1/#2/#3 #4 #5\@@#6.#7\@@{% \expandafter\def\csname #6date\endcsname% {\protect\mdwdateformat{#1}{#2}{#3}}% \expandafter\def\csname #6version\endcsname{#4}% \expandafter\def\csname #6info\endcsname{#5}% } % \end{macrocode} % % \end{macro} % % \begin{macro}{\mdwdateformat} % % Given three arguments, a year, a month and a date (all numeric), build a % pretty date string. This is fairly simple really. % % \begin{macrocode} \tdef\mdwdateformat#1#2#3{\number#3\ \monthname{#2}\ \number#1} \def\monthname#1{% \ifcase#1\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% } \def\numsuffix#1{% \ifnum#1=1 st\else% \ifnum#1=2 nd\else% \ifnum#1=3 rd\else% \ifnum#1=21 st\else% \ifnum#1=22 nd\else% \ifnum#1=23 rd\else% \ifnum#1=31 st\else% th% \fi\fi\fi\fi\fi\fi\fi% } % \end{macrocode} % % \end{macro} % % \begin{macro}{\mdwfileinfo} % % Saying \syntax{"\\mdwfileinfo{""}{""}"} extracts the % wanted item of \ from the version information for file \. % % \begin{macrocode} \def\mdwfileinfo#1#2{\mdwfileinfo@i{#2}#1.\@@} \def\mdwfileinfo@i#1#2.#3\@@{\csname#2#1\endcsname} % \end{macrocode} % % \end{macro} % % % \subsection{List handling} % % There are several other lists I need to build. These macros will do % the necessary stuff. % % \begin{macro}{\mdw@ifitem} % % The macro \syntax{"\\mdw@ifitem""\\in""{""}"^^A % "{""}"} does \ if the \ matches any item in % the \; otherwise it does \. % % \begin{macrocode} \def\mdw@ifitem#1\in#2{% \@tempswafalse% \def\@tempa{#1}% \def\do##1{\def\@tempb{##1}\ifx\@tempa\@tempb\@tempswatrue\fi}% #2% \if@tempswa\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi% } % \end{macrocode} % % \end{macro} % % \begin{macro}{\mdw@append} % % Saying \syntax{"\\mdw@append""\\to"} adds the given \ % to the end of the given \. % % \begin{macrocode} \def\mdw@append#1\to#2{% \toks@{\do{#1}}% \toks\tw@\expandafter{#2}% \edef#2{\the\toks\tw@\the\toks@}% } % \end{macrocode} % % \end{macro} % % \begin{macro}{\mdw@prepend} % % Saying \syntax{"\\mdw@prepend""\\to"} adds the \ to the % beginning of the \. % % \begin{macrocode} \def\mdw@prepend#1\to#2{% \toks@{\do{#1}}% \toks\tw@\expandafter{#2}% \edef#2{\the\toks@\the\toks\tw@}% } % \end{macrocode} % % \end{macro} % % \begin{macro}{\mdw@add} % % Finally, saying \syntax{"\\mdw@add""\\to"} adds the \ % to the list only if it isn't there already. % % \begin{macrocode} \def\mdw@add#1\to#2{\mdw@ifitem#1\in#2{}{\mdw@append#1\to#2}} % \end{macrocode} % % \end{macro} % % % \subsection{Described file handling} % % I'l maintain lists of packages, document classes, and other files % described by the current documentation file. % % First of all, I'll declare the various list macros. % % \begin{macrocode} \def\dopackages{} \def\doclasses{} \def\dootherfiles{} % \end{macrocode} % % \begin{macro}{\describespackage} % % A document file can declare that it describes a package by saying % \syntax{"\\describespackage{""}"}. I add the package to % my list, read the package into memory (so that the documentation can % offer demonstrations of it) and read the version information. % % \begin{macrocode} \def\describespackage#1{% \mdw@ifitem#1\in\dopackages{}{% \mdw@append#1\to\dopackages% \usepackage{#1}% \mdwpkginfo{#1.sty}% }% } % \end{macrocode} % % \end{macro} % % \begin{macro}{\describesclass} % % By saying \syntax{"\\describesclass{""}"}, a document file % can declare that it describes a document class. I'll assume that the % document class is already loaded, because it's much too late to load % it now. % % \begin{macrocode} \def\describesclass#1{\mdw@add#1\to\doclasses\mdwpkginfo{#1.cls}} % \end{macrocode} % % \end{macro} % % \begin{macro}{\describesfile} % % Finally, other `random' files, which don't have the status of real \LaTeX\ % packages or document classes, can be described by saying \syntax{^^A % "\\describesfile{""}" or "\\describesfile*{""}"}. % The difference is that the starred version will not |\input| the file. % % \begin{macrocode} \def\describesfile{% \@ifstar{\describesfile@i\@gobble}{\describesfile@i\input}% } \def\describesfile@i#1#2{% \mdw@ifitem#2\in\dootherfiles{}{% \mdw@add#2\to\dootherfiles% #1{#2}% \mdwpkginfo{#2}% }% } % \end{macrocode} % % \end{macro} % % % \subsection{Author and title handling} % % I'll redefine the |\author| and |\title| commands so that I get told % whether I need to do it myself. % % \begin{macro}{\author} % % This is easy: I'll save the old meaning, and then redefine |\author| to % do the old thing and redefine itself to then do nothing. % % \begin{macrocode} \let\mdw@author\author \def\author{\let\author\@gobble\mdw@author} % \end{macrocode} % % \end{macro} % % \begin{macro}{\title} % % And oddly enough, I'll do exactly the same thing for the title, except % that I'll also disable the |\mdw@buildtitle| command, which constructs % the title automatically. % % \begin{macrocode} \let\mdw@title\title \def\title{\let\title\@gobble\let\mdw@buildtitle\relax\mdw@title} % \end{macrocode} % % \end{macro} % % \begin{macro}{\date} % % This works in a very similar sort of way. % % \begin{macrocode} \def\date#1{\let\date\@gobble\def\today{#1}} % \end{macrocode} % % \end{macro} % % \begin{macro}{\datefrom} % % Saying \syntax{"\\datefrom{""}"} sets the document date from % the given filename. % % \begin{macrocode} \def\datefrom#1{% \protected@edef\@tempa{\noexpand\date{\csname #1date\endcsname}}% \@tempa% } % \end{macrocode} % % \end{macro} % % \begin{macro}{\docfile} % % Saying \syntax{"\\docfile{""}"} sets up the file name from which % documentation will be read. % % \begin{macrocode} \def\docfile#1{% \def\@tempa##1.##2\@@{\def\@basefile{##1.##2}\def\@basename{##1}}% \edef\@tempb{\noexpand\@tempa#1\noexpand\@@}% \@tempb% } % \end{macrocode} % % I'll set up a default value as well. % % \begin{macrocode} \docfile{\jobname.dtx} % \end{macrocode} % % \end{macro} % % % \subsection{Building title strings} % % This is rather tricky. For each list, I need to build a legible looking % string. % % \begin{macro}{\mdw@addtotitle} % % By saying %\syntax{"\\mdw@addtotitle{""}{""}{""}{""}"} % I can add the contents of a list to the current title string in the % |\mdw@title| macro. % % \begin{macrocode} \tdef\mdw@addtotitle#1#2#3#4{% % \end{macrocode} % % Now to get to work. I need to keep one `lookahead' list item, and a count % of the number of items read so far. I'll keep the lookahead item in % |\@nextitem| and the counter in |\count@|. % % \begin{macrocode} \count@\z@% % \end{macrocode} % % Now I'll define what to do for each list item. The |\protect| command is % already set up appropriately for playing with |\edef| commands. % % \begin{macrocode} \def\do##1{% % \end{macrocode} % % The first job is to add the previous item to the title string. If this % is the first item, though, I'll just add the appropriate \lit{The } or % \lit{ and the } string to the title (this is stored in the |\@prefix| % macro). % % \begin{macrocode} \edef\mdw@title{% \mdw@title% \ifcase\count@\@prefix% \or\@nextitem% \else, \@nextitem% \fi% }% % \end{macrocode} % % That was rather easy. Now I'll set up the |\@nextitem| macro for the % next time around the loop. % % \begin{macrocode} \edef\@nextitem{% \protect#2{##1}% \protect\footnote{% The \protect#2{##1} #3 is currently at version % \mdwfileinfo{##1}{version}, dated \mdwfileinfo{##1}{date}.% }\space% }% % \end{macrocode} % % Finally, I need to increment the counter. % % \begin{macrocode} \advance\count@\@ne% }% % \end{macrocode} % % Now execute the list. % % \begin{macrocode} #1% % \end{macrocode} % % I still have one item left over, unless the list was empty. I'll add % that now. % % \begin{macrocode} \edef\mdw@title{% \mdw@title% \ifcase\count@% \or\@nextitem\space#3% \or\ and \@nextitem\space#4% \fi% }% % \end{macrocode} % % Finally, if $|\count@| \ne 0$, I must set |\@prefix| to \lit{ and the }. % % \begin{macrocode} \ifnum\count@>\z@\def\@prefix{ and the }\fi% } % \end{macrocode} % % \end{macro} % % \begin{macro}{\mdw@buildtitle} % % This macro will actually do the job of building the title string. % % \begin{macrocode} \tdef\mdw@buildtitle{% % \end{macrocode} % % First of all, I'll open a group to avoid polluting the namespace with % my gubbins (although the code is now much tidier than it has been in % earlier releases). % % \begin{macrocode} \begingroup% % \end{macrocode} % % The title building stuff makes extensive use of |\edef|. I'll set % |\protect| appropriately. (For those not in the know, % |\@unexpandable@protect| expands to `|\noexpand\protect\noexpand|', % which prevents expansion of the following macro, and inserts a |\protect| % in front of it ready for the next |\edef|.) % % \begin{macrocode} \let\@@protect\protect\let\protect\@unexpandable@protect% % \end{macrocode} % % Set up some simple macros ready for the main code. % % \begin{macrocode} \def\mdw@title{}% \def\@prefix{The }% % \end{macrocode} % % Now build the title. This is fun. % % \begin{macrocode} \mdw@addtotitle\dopackages\package{package}{packages}% \mdw@addtotitle\doclasses\package{document class}{document classes}% \mdw@addtotitle\dootherfiles\texttt{file}{files}% % \end{macrocode} % % Now I want to end the group and set the title from my string. The % following hacking will do this. % % \begin{macrocode} \edef\next{\endgroup\noexpand\title{\mdw@title}}% \next% } % \end{macrocode} % % \end{macro} % % % \subsection{Starting the main document} % % \begin{macro}{\mdwdoc} % % Once the document preamble has done all of its stuff, it calls the % |\mdwdoc| command, which takes over and really starts the documentation % going. % % \begin{macrocode} \def\mdwdoc{% % \end{macrocode} % % First, I'll construct the title string. % % \begin{macrocode} \mdw@buildtitle% \author{Mark Wooding}% % \end{macrocode} % % Set up the date string based on the date of the package which shares % the same name as the current file. % % \begin{macrocode} \datefrom\@basename% % \end{macrocode} % % Set up verbatim characters after all the packages have started. % % \begin{macrocode} \shortverb\|% \shortverb\"% % \end{macrocode} % % Start the document, and put the title in. % % \begin{macrocode} \begin{document} \maketitle% % \end{macrocode} % % This is nasty. It makes maths displays work properly in demo environments. % \emph{The \LaTeX\ Companion} exhibits the bug which this hack fixes. So % ner. % % \begin{macrocode} \abovedisplayskip\z@% % \end{macrocode} % % Now start the contents tables. After starting each one, I'll make it % be multicolumnar. % % \begin{macrocode} \def\do##1##2{% ##2% \ifhave@multicol\addtocontents{##1}{% \protect\begin{multicols}{2}% \hbadness\@M% }\fi% }% \docontents% % \end{macrocode} % % Input the main file now. % % \begin{macrocode} \DocInput{\@basefile}% % \end{macrocode} % % That's it. I'm done. % % \begin{macrocode} \end{document} } % \end{macrocode} % % \end{macro} % % % \subsection{And finally\dots} % % Right at the end I'll put a hook for the configuration file. % % \begin{macrocode} \ifx\mdwhook\@@undefined\else\expandafter\mdwhook\fi % \end{macrocode} % % That's all the code done now. I'll change back to `user' mode, where % all the magic control sequences aren't allowed any more. % % \begin{macrocode} \makeatother % % \end{macrocode} % % Oh, wait! What if I want to typeset this documentation? Aha. I'll cope % with that by comparing |\jobname| with my filename |mdwtools|. However, % there's some fun here, because |\jobname| contains category-12 letters, % while my letters are category-11. Time to play with |\string| in a messy % way. % % \begin{macrocode} %<*driver> \makeatletter \edef\@tempa{\expandafter\@gobble\string\mdwtools} \edef\@tempb{\jobname} \ifx\@tempa\@tempb \describesfile*{mdwtools.tex} \docfile{mdwtools.tex} \makeatother \expandafter\mdwdoc \fi \makeatother % % \end{macrocode} % % That's it. Done! % % \hfill Mark Wooding, \today % % \Finale % \endinput