DoX – Doc, only eXtended^{∗}

Didier Verna

        mailto:didier@didierverna.net
      http://www.lrde.epita.fr/˜ didier/
              v2.4 (2017/12/06)

Abstract

The doc package provides L^{A}TEX developers with means to describe the usage and the definition of new commands and environments. However, there is no simple way to extend this functionality to other items (options or counters for instance). DoX is designed to circumvent this limitation, and provides some improvements over the existing functionality as well.

The DoX package is Copyright \begin{matrix}c \\ ◯ \end{matrix} 2009, 2010, 2017 Didier Verna, and distributed under the terms of the LPPL license.

Contents

1 Installation 2 1.1 Extraction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.2 TDS-compliant layout . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.3 AUCTEX support . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

2 Usage 2

2.1 Initialization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 2.1.1 Requirements . . . . . . . . . . . . . . . . . . . . . . . . . . 2 2.1.2 Loading the package . . . . . . . . . . . . . . . . . . . . . . 3

2.2 Creating new documentation items . . . . . . . . . . . . . . . . . . 3 2.2.1 Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 2.2.2 Details . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 2.2.3 Options to \doxitem . . . . . . . . . . . . . . . . . . . . . . 4

2.3 Improvements over doc’s original api . . . . . . . . . . . . . . . . . 4 2.3.1 Additional (optional) argument . . . . . . . . . . . . . . . . 5 2.3.2 Available options . . . . . . . . . . . . . . . . . . . . . . . . 5 2.3.3 Global effect . . . . . . . . . . . . . . . . . . . . . . . . . . 5

3 AUCTEX support for new documentation items 5

4 Conclusion 6

DoX v2.4 (2017/12/06)

5 History 6 6 Implementation 6

∗DoX homepage: http://www.lrde.epita.fr/˜ didier/software/latex.php#dox

6.1 Preamble . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 6.2 DoX options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 6.3 DoX environments . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 6.4 DoX descriptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 6.5 API construction . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 6.6 Doc overrides . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

6.6.1 Macro facilities . . . . . . . . . . . . . . . . . . . . . . . . . 10 6.6.2 Environment facilities . . . . . . . . . . . . . . . . . . . . . 11

6.7 API creation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 6.8 Finale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

1 Installation

1.1 Extraction

If you are building DoX from the tarball you need to execute the following steps in order to extract the necessary files:

 [pdf]latex dox.ins
 [pdf]latex dox.dtx
 [pdf]latex dox.dtx

After that, you need to install the generated documentation and style files to a location where L^{A}TEX can find them.

1.2 TDS-compliant layout

For a TDS-compliant layout, the following locations are suggested:

 [TEXMF]/tex/latex/dox/dox.sty
 [TEXMF]/doc/latex/dox/dox.[pdf|dvi]

1.3 AUCTEX support

AUCTEX is a powerful major mode for editing TEX documents in [X]Emacs. In particular, it provides automatic completion of command names once they are known. DoX supports AUCTEX by providing a style file named dox.el which contains AUCTEX definitions for the relevant commands. This file should be installed in a place where AUCTEX can find it. Please refer to the AUCTEX documentation for more information on this. See also section 3.

2 Usage

2.1 Initialization

2.1.1 Requirements

In order to work properly, DoX requires the presence of some L^{A}TEX packages. You don’t have to load them explicitly though. As long as L^{A}TEX can locate them, they will be used automatically. DoX currently depends on kvoptions.

2.1.2 Loading the package

In order to load DoX, simply say \usepackage[⟨options⟩]{dox} in the preamble of your document. The package options will be discussed when appropriate.

2.2 Creating new documentation items

Note: we assume that you know about doc’s \DescribeMacro, \DescribeEnv and all other associated commands and environments.

\doxitem [⟨options⟩]{⟨name⟩}{⟨envname⟩}{⟨idxcat⟩} DoX provides a command named \doxitem to create new documentation items with functionalities equivalent to what doc provides for commands and environments. A whole api is created for every new item.

2.2.1 Example

Perhaps the simplest way to describe what it does is to give an example. Suppose you would like to describe package options explicitely. Here is what you need to do:

 \usepackage{dox}
 \doxitem{Option}{option}{options}

DoX then creates the following api for you:

   • \DescribeOption

• the option environment

   • \PrintDescribeOption
   • \PrintOptionName
   • \SpecialMainOptionIndex
   • \SpecialOptionIndex

In order to comply with doc’s original behavior, the commands

\PrintDescribeOption and \PrintOptionName will only be defined if they

do not already exist.

2.2.2 Details

Here is a more precise description of the arguments to \doxitem.

• ⟨name⟩ (Option in our example) is used to construct the names of the commands in the new api. It usually starts with an upcase letter.

• ⟨envname⟩ (option in our example) is the name of the created environment. Be sure to avoid name clashes here! If you start experimenting odd behavior, you’ve probably overridden an existing command with your new environment.^{1} • ⟨idxcat⟩ is the index category under which your items will appear. In our

1It is a pity that L^{A}TEX use the same namespace for commands and environments. The opening command for environment env should be named \beginenv and not just \env…

example, all indexed options will be listed under the “options:” index entry.

2.2.3 Options to \doxitem

The first (optional) argument to \doxitem may contain a comma-separated list of options. The following ones are currently implemented.

idxtype

We saw earlier that individual items appear under the idxcat index entry, but items also appear as standalone index entries, alphabetically sorted with their type in parenthesis. For instance, the final option would appear like this under the F index entry: “final (option)”.

By default, the index type is the same as the environment’s name (the ⟨envname⟩ argument). However, you can change this by providing a value to the idxtype option.

For instance, you may find the word “environment” too long for an index type. In that case, you may redefine the environment api like this:

 \doxitem[idxtype=env.]{Env}{environment}{environments}

macrolike

At some point, you may find that the “macro” category is too gross, and whish to further split it into different documentation items. A typical example of this would be to provide a specific category for L^{A}TEX lengths.

The difference with options or counters is that the names of your items are actually control sequences, and so they need to be typeset and indexed in a specific way.

As of version 2.2, DoX provides a macrolike boolean option which instructs \doxitem to create new documentation items expecting control sequences instead of plain text names. If you want to create explicit documentation for lengths for instance, you can do this:

 \doxitem[macrolike,idxtype=len.]{Length}{length}{lengths}

In turn this allows you do write things like that:

 \DescribeLength{\partopsep}
 \begin{length}{\partopsep}
   ...
 \end{length}

2.3 Improvements over doc’s original api

Please note that the improvements described in this section are also available in doc’s original command and environment api’s, because DoX redefines them.

2.3.1 Additional (optional) argument

Compared to doc, the api’s created by \doxitem are extended with a first optional argument containing a comma-separated list of options, such that, continuing with our initial example, the real prototypes are in fact the following:

 \DescribeOption[opt,...]{name}
 \begin{option}[opt,...]{name}
 %% ...
 \end{option}

2.3.2 Available options

The options currently supported are:

noprint Avoid printing ⟨name⟩ in the margin

noindex Avoid indexing ⟨name⟩

These options are useful if you don’t want printing or indexing locally for one particular item. Without them, one would need to locally \let the relevant commands to \@gobble which is very inconvenient.

There is also another advantage in using the noprint option: in doc’s original implementation, a margin paragraph will still be created just to be empty, hence wasting float resources. If you’re referencing a lot of items close to each other, this may lead to a “Too many unprocessed floats” error. With DoX, the \marginpar is avoided altogether.

2.3.3 Global effect

The macrolike, noprint and noindex options are also available to \usepackage.

Their effect then becomes global. Because these options are boolean, it is still possible to counteract their global effect locally. For instance, one could do:

 \usepackage[noprint]{dox}

and then later:

 \DescribeOption[noprint=false]{french}

3 AUCTEX support for new documentation items

Recent versions of AUCTEX (in fact, docTEX mode) are aware of the macro and environment environments and give them a fixed indentation level of 0, meaning no indentation at all even when they are nested. This is considered more convenient than the usual indentation for environments when editing dtx files. If you have created new documentation items for your package, you may want to let them behave the same way. For that, the DoX style file provides two Lisp functions to let AUCTEX know of your new environments: doxitem and doxitems. The first one registers a new environment by name with AUCTEX, and the second one takes an arbitrary number of environment names and does the same with them. The environment names can in fact be regular expressions, allowing you to combine several names together or build complex ones.

Since these functions are located in the style file itself, a good place to use them is in TeX-update-style-hook which will be called after the file is parsed and the relevant style files applied. Note that the effect of calling these functions is always buffer-local.

Here is an example to make all of this clearer. The following code sample is what I have at the end of fixme.dxt (another package of mine), in the local variables section:

 (add-hook 'TeX-update-style-hook
   (lambda () (doxitems "option" "counter" "lang" "face" "color")) nil t)
 (add-hook 'TeX-update-style-hook
   (lambda () (doxitem "\\(env\\|target\\)?layout")) nil t)

4 Conclusion

If you want to see DoX in action, take a look at the documentation of the FiXme package (version 4.0 or later). In fact, I wrote DoX for it in the first place.

5 History

v2.4 Improve AUCTEX support.

Fix spurious spaces in index entries, reported by Eric Domenjoud.

v2.3 Support doc’s \saved@indexname internal command, thanks to Falk Hanisch.

v2.2 New macrolike option allowing to create control sequence based documentation items.

v2.1 New lisp functions doxitem[s] to register new documentation environments with AUCTEX.

v2.0 Optional argument to \doxitem (idxtype option to change the item’s index type). Optional argument to \Describe⟨Item⟩ and the ⟨item⟩ environment (noprint to avoid marginal printing and noindex to avoid indexing). Extend \DescribeMacro, \DescribeEnv and their corresponding environments with the same features.

v1.0 First public version.

6 Implementation

6.1 Preamble

 1 ⟨dox⟩\NeedsTeXFormat{LaTeX2e}

2 ⟨∗header⟩

 3 \ProvidesPackage{dox}[2017/12/06 v2.4 Extensions to the doc package]

4

5 ⟨/header⟩ 6 ⟨∗dox⟩

 7 \RequirePackage{kvoptions}
 8 \SetupKeyvalOptions{family=dox,prefix=dox@}

9

6.2 DoX options

These two options are available for use in \usepackage or in the generated item api’s:

10 \DeclareBoolOption{noprint}
11 \DeclareBoolOption{noindex}
This one is for \usepackage and \doxitem:
12 \DeclareBoolOption{macrolike}

This one is for \doxitem:

13 \DeclareStringOption{idxtype}

14

6.3 DoX environments

\@@doxenv  {⟨item⟩}{⟨name⟩}

In doc.sty, the macro and environment environments go through the \m@cro@ macro which implements specific parts by testing a boolean condition as its first argument. This mechanism is not extensible, so I have to hack away a more generic version that would work for any new dox item, only which looks pretty much like the original one (with the addition of options management).

15 \long\def\@@doxenv#1#2{%
16 \endgroup%
17 \topsep\MacroTopsep%
18 \trivlist%
19  \edef\saved@macroname{\string#2}%

Since version 2.1g, doc creates a \saved@indexname command which in used by \changes. We now support that as well. The expansion of this command depends on whether the documented item is macrolike or not, which we don’t know here (it’s only know by \doxitem). That’s why we need one specific command generating \saved@indexname the right way for every single item. These commands are named\@Save⟨item ⟩IndexName; they are technically part of the generated API, only not meant for public use.

20  \@nameuse{@Save#1IndexName}{\saved@macroname}%
21  \def\makelabel##1{\llap{##1}}%
22  \if@inlabel%
23  \let\@tempa\@empty%
24  \count@\macro@cnt%
25  \loop\ifnum\count@>\z@%
26  \edef\@tempa{\@tempa\hbox{\strut}}\advance\count@\m@ne%
27  \repeat%
28  \edef\makelabel##1{\llap{\vtop to\baselineskip{\@tempa\hbox{##1}\vss}}}%
29  \advance\macro@cnt\@ne%
30  \else%
31  \macro@cnt\@ne%

32  \fi%
33  \ifdox@noprint%
34  \item%
35  \else%
36  \edef\@tempa{%
37  \noexpand\item[%

The second notable modification to the original macro involves dynamically constructing the name of the print macro:

38  \expandafter\noexpand\csname Print#1Name\endcsname{\saved@macroname}]}%
39  \@tempa%
40  \fi%
41  \ifdox@noindex\else%
42  \global\advance\c@CodelineNo\@ne%

and the third one involves dynamically constructing the name of the index macro:

43  \@nameuse{SpecialMain#1Index}{#2}\nobreak%
44  \global\advance\c@CodelineNo\m@ne%
45  \fi%
46  \ignorespaces}

\@doxenv {⟨item⟩}[⟨options⟩] Handle optional arguments and call \@@doxenv. Because environments can be nested, we can’t rely on grouping for getting options default values. Hence, we need to reset the options at every call.

47 \def\@doxenv#1[#2]{%
48 \@nameuse{dox@noprint\dox@noprintdefault}%
49 \@nameuse{dox@noindex\dox@noindexdefault}%
50 \setkeys{dox}{#2}%
51 \begingroup%
52  \catcode`\\12%
53  \MakePrivateLetters%
54  \@@doxenv{#1}}

55

6.4 DoX descriptions

\@@doxdescribe  {⟨item⟩}{⟨name⟩}

The first closed group was the one opened to parse the ⟨name⟩ argument. The second one was opened to handle local options.

56 \def\@@doxdescribe#1#2{%
57  \endgroup%
58  \ifdox@noprint\else%
59  \marginpar{\raggedleft\@nameuse{PrintDescribe#1}{#2}}%
60  \fi%
61  \ifdox@noindex\else%
62  \@nameuse{Special#1Index}{#2}%
63  \fi%
64  \endgroup%
65 \@esphack\ignorespaces}
\@doxdescribe  {⟨item⟩}[⟨options⟩]

Handle optional arguments and call \@@doxdescribe.

66 \def\@doxdescribe#1[#2]{%

67 \leavevmode\@bsphack%
68 \begingroup%
69  \setkeys{dox}{#2}%
70  \begingroup%
71  \MakePrivateLetters%
72  \@@doxdescribe{#1}}

73

6.5 API construction

First, the two index name generation macros (macrolike or not).

\@doxsavemacrolikeindexname  {⟨saved macro name⟩}
74 \def\@doxsavemacrolikeindexname#1{%
75 \edef\saved@indexname{\expandafter\@gobble#1}}
\@doxsaveindexname  {⟨saved macro name⟩}
76 \def\@doxsaveindexname#1{\let\saved@indexname#1}

77

\@doxcreatespecialmainindex  {⟨item⟩}{⟨idxtype⟩}{⟨idxcat⟩}
\@doxcreatespecialmainmacrolikeindex  {⟨item⟩}{⟨idxtype⟩}{⟨idxcat⟩}

The “macrolike” version does something similar to doc’s \SpecialIndex@ macro, but simplified. Let’s just hope nobody will ever define \␣ or nonletter macros as macrolike DoX items…

78 \def\@doxcreatespecialmainindex#1#2#3{%
79 \expandafter\def\csname SpecialMain#1Index\endcsname##1{%
80  \@bsphack%
81  \special@index{##1\actualchar{\string\ttfamily\space##1} (#2)%
82  \encapchar main}%
83  \special@index{#3:\levelchar##1\actualchar{\string\ttfamily\space##1}%
84  \encapchar main}%
85  \@esphack}}
86 \def\@doxcreatespecialmainmacrolikeindex#1#2#3{%
87 \expandafter\def\csname SpecialMain#1Index\endcsname##1{%
88  \@SpecialIndexHelper@##1\@nil
89  \@bsphack%
90  \special@index{\@gtempa\actualchar
91  \string\verb\quotechar*\verbatimchar\bslash\@gtempa\verbatimchar
92  \space(#2)\encapchar main}%
93  \special@index{#3:\levelchar\@gtempa\actualchar%
94  \string\verb\quotechar*\verbatimchar\bslash\@gtempa\verbatimchar%
95  \encapchar main}%
96  \@esphack}}

97

\@doxcreatespecialindex  {⟨item⟩}{⟨idxtype⟩}{⟨idxcat⟩}
\@doxcreatespecialmacrolikeindex  {⟨item⟩}{⟨idxtype⟩}{⟨idxcat⟩}

Same comment as above.

98 \def\@doxcreatespecialindex#1#2#3{%
99 \expandafter\def\csname Special#1Index\endcsname##1{%
100  \@bsphack%

101  \index{##1\actualchar{\protect\ttfamily##1} (#2)\encapchar usage}%
102  \index{#3:\levelchar##1\actualchar{\protect\ttfamily##1}%
103  \encapchar usage}%
104  \@esphack}}
105 \def\@doxcreatespecialmacrolikeindex#1#2#3{%
106 \expandafter\def\csname Special#1Index\endcsname##1{%
107  \@SpecialIndexHelper@##1\@nil
108  \@bsphack%
109  \index{\@gtempa\actualchar
110  \string\verb\quotechar*\verbatimchar\bslash\@gtempa\verbatimchar
111  \space(#2)\encapchar usage}%
112  \index{#3:\levelchar\@gtempa\actualchar
113  \string\verb\quotechar*\verbatimchar\bslash\@gtempa\verbatimchar%
114  \encapchar usage}%
115  \@esphack}}

116

\@doxcreatedescribe  {⟨item⟩}
117 \def\@doxcreatedescribe#1{%
118 \expandafter\def\csname Describe#1\endcsname{%
119  \@ifnextchar[%]
120  {\@doxdescribe{#1}}{\@doxdescribe{#1}[]}}}

121

\@doxcreateenv  {⟨item⟩}{⟨envname⟩}
122 \def\@doxcreateenv#1#2{%
123 \expandafter\def\csname #2\endcsname{%
124  \@ifnextchar[%]
125  {\@doxenv{#1}}{\@doxenv{#1}[]}}
126 \expandafter\let\csname end#2\endcsname\endtrivlist}

127

6.6 Doc overrides

6.6.1 Macro facilities

Making \DescribeMacro work the DoX way is straightforward. The only precaution we need is to provide an alias to \SpecialUsageIndex because it should

 really be named \SpecialMacroIndex.
128 \let\SpecialMacroIndex\SpecialUsageIndex
129 \@doxcreatedescribe{Macro}

130

Making the macro environment work the DoX way is straightforward. The only precaution we need is to to provide a \SpecialMainMacroIndex macro that does the job originally done in doc’s \m@cro@.

131 \def\SpecialMainMacroIndex#1{%
132 \SpecialMainIndex{#1}\nobreak%
133 \DoNotIndex{#1}}
134 \let\@SaveMacroIndexName\@doxsavemacrolikeindexname
135 \@doxcreateenv{Macro}{macro}

136

6.6.2 Environment facilities

Making \DescribeEnv and the environment environment work the DoX way is even more straightforward.

137 \@doxcreatedescribe{Env}
138 \@doxcreateenv{Env}{environment}
139 \let\@SaveEnvIndexName\@doxsaveindexname

140

6.7 API creation

The whole user interface is created in one macro call.

\doxitem [⟨options⟩]{⟨name⟩}{⟨envname⟩}{⟨idxcat⟩}

141 \newcommand\doxitem[4][]{%
142 \@nameuse{dox@macrolike\dox@macrolikedefault}%
143 \def\dox@idxtype{#3}%
144 \setkeys{dox}{#1}
\Print...Name  {⟨name⟩}
145 \@ifundefined{Print#2Name}{%
146  \ifdox@macrolike
147  \expandafter\def\csname Print#2Name\endcsname##1{%
148  \strut\MacroFont\string ##1\ }
149  \else
150  \expandafter\def\csname Print#2Name\endcsname##1{%
151  \strut\MacroFont ##1\ }
152  \fi}{}
\SpecialMain...Index  {⟨name⟩}
153 \ifdox@macrolike
154  \def\@doxexpr{\@doxcreatespecialmainmacrolikeindex{#2}}%
155 \else
156  \def\@doxexpr{\@doxcreatespecialmainindex{#2}}%
157 \fi
158 \expandafter\@doxexpr\expandafter{\dox@idxtype}{#4}%
\PrintDescribe...  {⟨name⟩}
159 \@ifundefined{PrintDescribe#2}{%
160  \ifdox@macrolike
161  \expandafter\def\csname PrintDescribe#2\endcsname##1{%
162  \strut\MacroFont\string ##1\ }
163  \else
164  \expandafter\def\csname PrintDescribe#2\endcsname##1{%
165  \strut\MacroFont ##1\ }
166  \fi}{}
\Special...Index  {⟨name⟩}
167 \ifdox@macrolike
168  \def\@doxexpr{\@doxcreatespecialmacrolikeindex{#2}}%
169 \else
170  \def\@doxexpr{\@doxcreatespecialindex{#2}}%
171 \fi
172 \expandafter\@doxexpr\expandafter{\dox@idxtype}{#4}%

\Describe...  [⟨options⟩]{⟨name⟩}
173 \@doxcreatedescribe{#2}

item [⟨options⟩]{⟨name⟩}

174 \@doxcreateenv{#2}{#3}
\@Ssave...IndexName
175 \ifdox@macrolike
176  \expandafter\let\csname @Save#2IndexName\endcsname%
177  \@doxsavemacrolikeindexname%
178 \else
179  \expandafter\let\csname @Save#2IndexName\endcsname\@doxsaveindexname%
180 \fi}

6.8 Finale

We need to save the default value for every option because DoX environments need to reset them at every call.

181 \ProcessKeyvalOptions*
182 \ifdox@noprint
183 \def\dox@noprintdefault{true}
184 \else
185 \def\dox@noprintdefault{false}
186 \fi
187 \ifdox@noindex
188 \def\dox@noindexdefault{true}
189 \else
190 \def\dox@noindexdefault{false}
191 \fi
192 \ifdox@macrolike
193 \def\dox@macrolikedefault{true}
194 \else
195 \def\dox@macrolikedefault{false}
196 \fi

197

198 ⟨/dox⟩

Copyright \begin{matrix}c \\ ◯ \end{matrix} 2009, 2010, 2017 Didier Verna