6

I know dtx file is literate programming style file. I also know that I can compile it with pdflatex to generate pdf file. But I wonder could I just extract the tex code to a independent file? I think I can learn some thing from the tex source.

3
  • 1
    Note sure but this answer How can i pull an example out of a dtx file? may be of interest.
    – N.N.
    Sep 28, 2011 at 8:41
  • @Pythonee Do you want to extract the text of the documentation or the code which is documented? The two are different, as as Herbert has pointed out getting the code out is what the ideal of a .dtx file is.
    – Joseph Wright
    Sep 28, 2011 at 10:18
  • @Joseph Writht, I want to extract the text of documentation to another tex file. I just want to learn how to write manual like that. So I want to focus on tex code not the package implementation.
    – pythonee
    Sep 29, 2011 at 7:29

3 Answers 3

4

A DTX file is already a LaTeX file (sometimes called .tex file), however it uses some special things. It contains the description as comment lines and the package source code. It contains a "driver" preamble and body which includes the same file again with the % comment character disabled, so that the originally commented-out part is now read as normal LaTeX code. You can have a look at the description part simply by looking at the file, if you don't mind the comment style.

If you want to turn it into a normal LaTeX file, simply remove the comment % characters from the code and completely delete the implementation part. Then I would change the "driver" head part to not include the file but place the description body directly there by removing the \DocInput{..} and moving the \end{document} to the end of the file.

So basically change:

% \iffalse
%<*driver>
\documentclass{ltxdoc}
\usepackage{mypkg}
\EnableCrossrefs
\CodelineIndex
\RecordChanges
\begin{document}
  \DocInput{mypkg.dtx}
  \PrintChanges
  \PrintIndex
\end{document}
%</driver>
%\fi
% Description
% ...
% Implementation
%   \begin{macrocode}
%<*package>
code
%</package>
%   \end{macrocode}
% ...
% END of file

to:

\documentclass{ltxdoc}
\usepackage{mypkg}
\begin{document}
  Description
  ...
\end{document}

You can and should still use the ltxdoc class.

4

Usually package.dtx is accompanied by package.ins and running LaTeX on the latter extracts the code (commonly in package.sty, but in some cases other files are created).

In some cases package.ins is not present; in these cases,

pdflatex package.dtx

will typeset the documentation and extract the code; however sometimes it's necessary to run

tex package.dtx

for extracting the code (it's the case with H. Oberdiek's packages).

However, the purpose of package.dtx is not only to provide the package documentation, but also comments to the code.

If running LaTeX on package.dtx doesn't typeset the commented code, you can write a file ltxdoc.cfg in the working directory containing the line

\AlsoImplementation

and run LaTeX on package.dtx again.

3
  • In case e.g. of the dtx-file in the oberdiek bundle tex file.dtx unpacks the code while latex file.dtx generates the documentation. The dtx-files contains at the start more precise instructions. Sep 28, 2011 at 8:44
  • I get an error complaining that \AlsoImplementation is undefined when I try the ltxdoc.cfg trick. What am I doing wrong? I was trying to figure out how to extract the documentation for pullquote...
    – cfr
    Mar 17, 2014 at 4:32
  • @cfr Difficult to say without knowing where to find the .dtx file for experimenting.
    – egreg
    Mar 17, 2014 at 7:55
0

A more specific guide + something to look out when you do this.

  1. Get a .dtx file somewhere. For example use dtxgen a.sty to generate the default "template" file.

    You get (among other things) a.dtx which looks like this

    % \iffalse meta-comment
    % vim: textwidth=75
    %<*internal>
    \iffalse
    %</internal>
    %<*readme>
    |
    -------:| -----------------------------------------------------------------
          a:| A new LaTeX package
     Author:| (not set)
     E-mail:| (not set)
    License:| Released under the LaTeX Project Public License v1.3c or later
        See:| http://www.latex-project.org/lppl.txt
    
    
    Short description:
    Some text about the package: probably the same as the abstract.
    %</readme>
    %<*internal>
    \fi
    \def\nameofplainTeX{plain}
    \ifx\fmtname\nameofplainTeX\else
      \expandafter\begingroup
    \fi
    %</internal>
    %<*install>
    \input docstrip.tex
    \keepsilent
    \askforoverwritefalse
    \preamble
    -------:| -----------------------------------------------------------------
          a:| A new LaTeX package
     Author:| (not set)
     E-mail:| (not set)
    License:| Released under the LaTeX Project Public License v1.3c or later
        See:| http://www.latex-project.org/lppl.txt
    
    \endpreamble
    \postamble
    
    [... more things ...]
    
  2. Copy (keep the original a.dtx!) to a.tex. the exact file name is important here, and keep it in the same folder.

  3. Compile it. (un)surprisingly, it can be compiled and the output looks roughly like this

    output image

  4. Done!

    However... here you probably mean "a TeX file write in the normal way".

    Remark / if it helps understanding the situation, you can write TeX file in extremely not-normal ways e.g. https://tex.stackexchange.com/a/104263/250119, which is possible because of its elaborate catcode system.

  5. so first remove all the % in the TeX file (don't do that in the dtx file!)

    \iffalse
    
    
    |
    -------:| -----------------------------------------------------------------
          a:| A new LaTeX package
     Author:| (not set)
     E-mail:| (not set)
    License:| Released under the LaTeX Project Public License v1.3c or later
        See:| http://www.latex-project.org/lppl.txt
    
    
    Short description:
    Some text about the package: probably the same as the abstract.
    
    
    \fi
    \def\nameofplainTeX{plain}
    \ifx\fmtname\nameofplainTeX\else
      \expandafter\begingroup
    \fi
    

    ...

    \ProvidesFile{a.dtx}
    
    
    
    
        [2022/03/29 v1.00 A new LaTeX package]
    
    
    \documentclass{ltxdoc}
    \usepackage[a4paper,margin=25mm,left=50mm,nohead]{geometry}
    \usepackage[numbered]{hypdoc}
    \usepackage{\jobname}
    \EnableCrossrefs
    \CodelineIndex
    \RecordChanges
    \begin{document}
      \DocInput{\jobname.dtx}
    \end{document}
    

    Okay, it looks a lot more like a normal document now, with some "irrelevant" code at the top.

  6. Remove redundant content. Remaining:

    \ProvidesFile{a.dtx} [2022/03/29 v1.00 A new LaTeX package]
    \documentclass{ltxdoc}
    \usepackage[a4paper,margin=25mm,left=50mm,nohead]{geometry}
    \usepackage[numbered]{hypdoc}
    \usepackage{\jobname}
    \EnableCrossrefs
    \CodelineIndex
    \RecordChanges
    \begin{document}
      \DocInput{\jobname.dtx}
    \end{document}
    

    Still compiles to the same output, good.

  7. Here basically (also remarked on in https://tex.stackexchange.com/a/530511/250119) \DocInput as a special command that is like \input but "ignore % signs". So replace the \DocInput line with the content of a.dtx and remove all % signs, except those that comes directly before \end{macrocode} you get the result:

    \ProvidesFile{a.dtx} [2022/03/29 v1.00 A new LaTeX package]
    \documentclass{ltxdoc}
    \usepackage[a4paper,margin=25mm,left=50mm,nohead]{geometry}
    \usepackage[numbered]{hypdoc}
    \usepackage{\jobname}
    \EnableCrossrefs
    \CodelineIndex
    \RecordChanges
    \begin{document}
     \iffalse meta-comment
     vim: textwidth=75
    <*internal>
    \iffalse
    </internal>
    <*readme>
    |
    -------:| -----------------------------------------------------------------
          a:| A new LaTeX package
     Author:| (not set)
     E-mail:| (not set)
    License:| Released under the LaTeX Project Public License v1.3c or later
        See:| http://www.latex-project.org/lppl.txt
    
    
    Short description:
    Some text about the package: probably the same as the abstract.
    </readme>
    <*internal>
    \fi
    \def\nameofplainTeX{plain}
    \ifx\fmtname\nameofplainTeX\else
      \expandafter\begingroup
    \fi
    </internal>
    <*install>
    \input docstrip.tex
    \keepsilent
    \askforoverwritefalse
    \preamble
    -------:| -----------------------------------------------------------------
          a:| A new LaTeX package
     Author:| (not set)
     E-mail:| (not set)
    License:| Released under the LaTeX Project Public License v1.3c or later
        See:| http://www.latex-project.org/lppl.txt
    
    \endpreamble
    \postamble
    
    Copyright (C) 2022 by (not set) <(not set)>
    
    This work may be distributed and/or modified under the
    conditions of the LaTeX Project Public License (LPPL), either
    version 1.3c of this license or (at your option) any later
    version.  The latest version of this license is in the file:
    
    http://www.latex-project.org/lppl.txt
    
    This work is "maintained" (as per LPPL maintenance status) by
    (not set).
    
    This work consists of the file a.dtx and a Makefile.
    Running "make" generates the derived files README, a.pdf and a.sty.
    Running "make inst" installs the files in the user's TeX tree.
    Running "make install" installs the files in the local TeX tree.
    
    \endpostamble
    
    \usedir{tex/latex/a}
    \generate{
      \file{\jobname.sty}{\from{\jobname.dtx}{package}}
    }
    </install>
    <install>\endbatchfile
    <*internal>
    \usedir{source/latex/a}
    \generate{
      \file{\jobname.ins}{\from{\jobname.dtx}{install}}
    }
    \nopreamble\nopostamble
    \usedir{doc/latex/a}
    \generate{
      \file{README.txt}{\from{\jobname.dtx}{readme}}
    }
    \ifx\fmtname\nameofplainTeX
      \expandafter\endbatchfile
    \else
      \expandafter\endgroup
    \fi
    </internal>
     \fi
    
     \iffalse
    <*driver>
    \ProvidesFile{a.dtx}
    </driver>
    <package>\NeedsTeXFormat{LaTeX2e}[1999/12/01]
    <package>\ProvidesPackage{a}
    <*package>
        [2022/03/29 v1.00 A new LaTeX package]
    </package>
    <*driver>
    \documentclass{ltxdoc}
    \usepackage[a4paper,margin=25mm,left=50mm,nohead]{geometry}
    \usepackage[numbered]{hypdoc}
    \usepackage{\jobname}
    \EnableCrossrefs
    \CodelineIndex
    \RecordChanges
    \begin{document}
      \DocInput{\jobname.dtx}
    \end{document}
    </driver>
     \fi
    
     \GetFileInfo{\jobname.dtx}
     \DoNotIndex{\newcommand,\newenvironment}
    
    \title{\textsf{a} --- A new LaTeX package\thanks{This file
       describes version \fileversion, last revised \filedate.}
    }
    \author{(not set)\thanks{E-mail: (not set)}}
    \date{Released \filedate}
    
    \maketitle
    
    \changes{v1.00}{2022/03/29}{First public release}
    
     \begin{abstract}
     ==== Put abstract text here. ====
     \end{abstract}
    
     \section{Usage}
    
     ==== Put descriptive text here. ====
    
     \DescribeMacro{\dummyMacro}
     This macro does nothing.\index{doing nothing|usage} It is merely an
     example.  If this were a real macro, you would put a paragraph here
     describing what the macro is supposed to do, what its mandatory and
     optional arguments are, and so forth.
    
     \DescribeEnv{dummyEnv}
     This environment does nothing.  It is merely an example.
     If this were a real environment, you would put a paragraph here
     describing what the environment is supposed to do, what its
     mandatory and optional arguments are, and so forth.
    
    \StopEventually{^^A
      \PrintChanges
      \PrintIndex
    }
    
     \section{Implementation}
    
        \begin{macrocode}
    <*package>
    
    %    \end{macrocode}
     \begin{macro}{\dummyMacro}
     This is a dummy macro.  If it did anything, we'd describe its
     implementation here.
        \begin{macrocode}
    \newcommand{\dummyMacro}{}
    %    \end{macrocode}
     \end{macro}
    
     \begin{environment}{dummyEnv}
     This is a dummy environment.  If it did anything, we'd describe its
     implementation here.
        \begin{macrocode}
    \newenvironment{dummyEnv}{
    }{
    %    \end{macrocode}
     \changes{v1.00a}{2022/03/29}{Added a spurious change log entry to
       show what a change \emph{within} an environment definition looks
       like.}
     Don't use || to introduce a code comment within a |macrocode|
     environment.  Instead, you should typeset all of your comments with
     LaTeX---doing so gives much prettier results.  For comments within a
     macro/environment body, just do an |\end{macrocode}|, include some
     commentary, and do another |\begin{macrocode}|.  It's that simple.
        \begin{macrocode}
    }
    %    \end{macrocode}
     \end{environment}
    
        \begin{macrocode}
    \endinput
    </package>
    %    \end{macrocode}
    \Finale
    \end{document}
    
  8. (optional) remove the \iffalse ... \fi part.

    You need some TeX knowledge to know which \fi it matches with (it matches the last one). The result starts with

    \ProvidesFile{a.dtx} [2022/03/29 v1.00 A new LaTeX package]
    \documentclass{ltxdoc}
    \usepackage[a4paper,margin=25mm,left=50mm,nohead]{geometry}
    \usepackage[numbered]{hypdoc}
    \usepackage{\jobname}
    \EnableCrossrefs
    \CodelineIndex
    \RecordChanges
    \begin{document}
     \GetFileInfo{\jobname.dtx}
     \DoNotIndex{\newcommand,\newenvironment}
    
    \title{\textsf{a} --- A new LaTeX package\thanks{This file
       describes version \fileversion, last revised \filedate.}
    }
    \author{(not set)\thanks{E-mail: (not set)}}
    \date{Released \filedate}
    ...
    

remark: obviously step 7 is not a general technique that can be applied to all dtx files (also remarked on at https://tex.stackexchange.com/a/16864/250119); however it works for this particular one.

remark: if you think commenting out the \end is weird, take a look at the code linked above for a comparison what TeX is capable of.

remark: this relies on makeindex utility to generate the index.

1
  • Side note, actually you're not meant to write TeX file like this (as evidenced by the need of %in macrocode environment). Use dtx file, or makedtx approach (separate documentation file and source code)
    – user202729
    Mar 28 at 19:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.