Tuesday, January 11, 2011

A simpler .dtx template

Two things that annoyed me with making LaTeX packages using a .dtx file were the duplication of the copyright/license info and that nearly every line in the file was commented out. About the only thing that wasn't commented out was a small batch file that generated the output.

For the most part, both of those annoyances are unnecessary. The following is a simple template file for making a .sty file from a .dtx. Almost every place that the name of the package would appear has been replaced with \jobname. The exceptions are in the license at the top of the file (I am not a lawyer and so I'd rather not give an opinion on what it means to claim that \jobname.dtx and \jobname.sty are covered by the license) and then near the end where the SVN keyword Id has been expanded out.
% \iffalse The license starting three lines down applies to this file
%<*batchfile>
{\obeylines\obeyspaces \gdef\thepreamble{
Copyright (C) 2011 by YOUR NAME

This file may be distributed and/or modified under the
conditions of the LaTeX Project Public License, either
version 1.3c of this license or (at your option) any later
version.  The latest version of this license is in:

    http://www.latex-project.org/lppl.txt

and version 1.3c or later is part of all distributions of
LaTeX version 2005/12/01 or later.

This work has the LPPL maintenance status 'maintained'.

The Current Maintainer of this work is YOUR NAME.

This work consists of THISFILE.dtx and the derived file
THISFILE.sty.
}}
\begingroup
\input docstrip
\keepsilent
\usedir{tex/latex/\jobname}
\expandafter\preamble\thepreamble\endpreamble
\askforoverwritefalse
\generate{\file{\jobname.sty}{\from{\jobname.dtx}{}}}
\endgroup
\documentclass{ltxdoc}
\usepackage{\jobname}
\usepackage[margin=1.5in]{geometry}
\usepackage[pdfborder={0 0 0}]{hyperref}

\CheckSum{0}
\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         \~}

\DoNotIndex{\def}

\EnableCrossrefs
\CodelineIndex
\RecordChanges
\GetFileInfo{\jobname.sty}
\title{The \textsf{\jobname} package\thanks{This document
corresponds to \textsf{\jobname}~\fileversion, dated \filedate.}}
\author{YOUR NAME\\\texttt{YOU@YOUR.ADDRESS}}

\begin{document}
\maketitle

\phantomsection
\addcontentsline{toc}{section}{\abstractname}
\begin{abstract}
The \textsf{\jobname} package XXX.
\end{abstract}

\phantomsection
\addcontentsline{toc}{section}{\contentsname}
\tableofcontents

\section{Introduction}
The \textsf{\jobname} package XXX

\section{Usage}
XXX

\StopEventually{
        \typeout{**************************************************}
        \typeout{*}
        \typeout{* To finish the installation, you have to move the}
        \typeout{* following file into a directory searched by TeX:}
        \typeout{*}
        \typeout{* \space\space \jobname.sty}
        \typeout{*}
        \typeout{* Documentation is in \jobname.\ifpdf pdf\else dvi\fi.}
        \typeout{*}
        \typeout{* Happy TeXing!}
        \typeout{**************************************************}
        \end{document}
}
\clearpage
\DocInput{\jobname.dtx}
\clearpage
\phantomsection
\addcontentsline{toc}{section}{Change History}
\PrintChanges
\phantomsection
\addcontentsline{toc}{section}{Index}
\PrintIndex
\Finale
%</batchfile>
% \fi
%
% \section{Implementation}
% XXX This is the only part of the file where the main text is written
% with leading comments.
%
% \changes{v1.0}{2011/01/09}{Initial version}
%    \begin{macrocode}
\NeedsTeXFormat{LaTeX2e}[1999/12/01]
\RequirePackage{svn-prov}
\ProvidesPackageSVN
        {$Id: example.dtx 1 2011-01-11 07:21:05Z TH $}
        [v1.0 \revinfo\ SHORT DESCRIPTION.]

% YOUR PACKAGE CONTENTS HERE.
\endinput
%    \end{macrocode}
% \endinput
A quick description of how this works. It first saves the copyright/license text into a macro \thepreamble. Then the code between the begin and end group use docstrip to create \jobname.sty from \jobname.dtx. This works by stripping out all lines that start with comments and all lines between %<*batchfile> and %</batchfile> prepending the preamble text. So what results is the copyright/license text and the actual code of the package.

After \endgroup, we have the standard LaTeX documentation class, packages to use, the check sum, character, etc. that are normally used with the doc/ltxdoc package/class.

If the implementation is not going to be typeset, the code in \StopEventually will run, outputting some instruction. Otherwise, \DocInput{\jobname.dtx} executes. This causes the .dtx file to be input, but this time, % is ignored. If we look at the top of the file, there is an % \iffalse and just after the </batchfile> is the matching % \fi. Thus, all of that will be skipped by TeX.

And that brings us to the only part of the code that is prefixed with comments: the implementation documentation. As usual, the code appears between %    \begin{macrocode} and %    \end{macrocode}. Finally, the input is finished by % \endinput. After this, you can put something like
% vim: set ts=4 sts=4 expandtab:
which will be ignored by docstrip because it starts with a comment and by \DocInput because of the \endinput just before it.

After \DocInput is finished, this prints the change history and the index. Lastly, \Finale expands to the argument of \StopEventually, ending the document.

If you name the file example.dtx, it can be compiled as follows.
$ pdflatex example.dtx
$ makeindex -s gglo -o example.gls example.glo
$ makeindex -s gind example
$ pdflatex example.dtx
$ pdflatex example.dtx
Happy TeXing!

6 comments:

  1. If you write dtx files, check out also the gmdoc package.

    ReplyDelete
  2. I took a look at the documentation of the package. It's very long and I didn't see any obvious tutorials or basic getting started guides. I'm also unclear what advantageous it has over doc/docstrip/ltxdoc. Instead, the author devotes an unusual amount of space to discussing about gender.

    ReplyDelete
  3. Well, I can see three main advantages over "classical" doc:
    1. Simplified markup - no need for "macrocode" environment;
    2. Support for color and hyperlinks, e.g., in the index;
    3. Many nice little (or not-so-little) tools.
    And I agree that the comments on gender are crap, but the package is useful nevertheless:).

    ReplyDelete
  4. It's pretty helpful,i should recommended it to my freinds.
    thanks

    ReplyDelete
  5. Nice template. I enhanced it a bit. My version is available under
    https://github.com/ypid/typesetting/blob/master/docstrip-template/single-file-template.dtx
    The results are these two files:
    https://github.com/ypid/typesetting/blob/master/docstrip-template/single-file-template.sty
    https://raw.github.com/ypid/typesetting/master/docstrip-template/single-file-template.pdf

    But while writing a LaTeX package with it I have had some problems. The biggest
    one was that I could not use \DoNotIndex{\if}. LaTeX commands worked, but plain
    TeX macros did’t. So I created a .ins file and changed the .dtx file.
    I continued using \jobname where ever I could, because I also like this possibility.
    These files are also available in my git repo:
    https://github.com/ypid/typesetting/tree/master/docstrip-template

    And about the commented lines. A powerful editor like vim and some plugins (tComment) can help you with that^^

    @mbork To your argument number two … this is also possible with ltxdoc. Package: hypdoc

    Happy TeXing

    ReplyDelete
  6. Sorry for the bad line breaks. I forgot that this is not TeX^^

    ReplyDelete