4

When writing a dtx file, is it possible to typeset the code samples (i.e., everything enclosed in a macrocode environment) using the package?

For completeness, here's Joseph Wright's model dtx file:

% \iffalse meta-comment
% !TEX program  = pdfLaTeX
%<*internal>
\iffalse
%</internal>
%<*readme>
----------------------------------------------------------------
demopkg --- description text
E-mail: you@your.domain
Released under the LaTeX Project Public License v1.3c or later
See http://www.latex-project.org/lppl.txt
----------------------------------------------------------------

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
----------------------------------------------------------------
demopkg --- description text
E-mail: you@your.domain
Released under the LaTeX Project Public License v1.3c or later
See http://www.latex-project.org/lppl.txt
----------------------------------------------------------------

\endpreamble
\postamble

Copyright (C) 2009 by You <you@your.domain>

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
You.

This work consists of the file  demopkg.dtx
and the derived files           demopkg.ins,
                                demopkg.pdf and
                                demopkg.sty.

\endpostamble
\usedir{tex/latex/demopkg}
\generate{
  \file{\jobname.sty}{\from{\jobname.dtx}{package}}
}
%</install>
%<install>\endbatchfile
%<*internal>
\usedir{source/latex/demopkg}
\generate{
  \file{\jobname.ins}{\from{\jobname.dtx}{install}}
}
\nopreamble\nopostamble
\usedir{doc/latex/demopkg}
\generate{
  \file{README.txt}{\from{\jobname.dtx}{readme}}
}
\ifx\fmtname\nameofplainTeX
  \expandafter\endbatchfile
\else
  \expandafter\endgroup
\fi
%</internal>
%<*package>
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{demopkg}[2009/10/06 v1.0 description text]
%</package>
%<*driver>
\documentclass{ltxdoc}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage{\jobname}
\usepackage[numbered]{hypdoc}
\EnableCrossrefs
\CodelineIndex
\RecordChanges
\begin{document}
  \DocInput{\jobname.dtx}
\end{document}
%</driver>
% \fi
% 
%\GetFileInfo{\jobname.sty}
%
%\title{^^A
%  \textsf{demopkg} --- description text\thanks{^^A
%    This file describes version \fileversion, last revised \filedate.^^A
%  }^^A
%}
%\author{^^A
%  You\thanks{E-mail: you@your.domain}^^A
%}
%\date{Released \filedate}
%
%\maketitle
%
%\changes{v1.0}{2009/10/06}{First public release}
%
%\DescribeMacro{\examplemacro}
% Some text about an example macro called \cs{examplemacro}, which
% might have an optional argument \oarg{arg1} and mandatory one
% \marg{arg2}. 
%
%\StopEventually{^^A
%  \PrintChanges
%  \PrintIndex
%}
%
%    \begin{macrocode}
%<*package>
%    \end{macrocode}
%    
%\begin{macro}{\examplemacro}
%\changes{v1.0}{2009/10/06}{Some change from the previous version}
%    \begin{macrocode}
\newcommand*\examplemacro[2][]{%
  Some code here, probably
}
%    \end{macrocode}
%\end{macro} 
%
%    \begin{macrocode}
%</package>
%    \end{macrocode}
%\Finale
4

Environment macrocode does a lot more than just being a verbatim environment. Replacing it by lstlisting is not trivial:

  • The indexing of macro names is lost.
  • Problematic is the last line with the end tokens (\end{macrocode} or \end{lstlisting}, because of the percent char in the first column.
  • The formatting of the docstrip tags is different. Also the percent char at the first column is automatically gobbled by macrocode.

The second issue can be solved by using option lastline to exclude the line with the end environment tokens to exclude the line, which would otherwise be set containing a percent char. The value for lastline could be set automatically via a script.

The third issue can be solved by putting docstrip tags in the environment body without other code lines. Then the starting percent char can be gobbled by option gobble. The fonts can be set to sans serif and the angle brackets can be replaced by \langle and \rangle via the literate feature.

Some style definitions for the preamble of the documentation driver file:

\usepackage{listings}
\lstdefinestyle{macrocode}{
  name=macrocode,
  language=[LaTeX]TeX,
  %basicstyle=\fontfamily{lmvtt}\selectfont\small,
  basicstyle=\ttfamily\small,
  columns=fullflexible,
  numbers=left,
  numberfirstline=1,
  firstnumber=auto,
  numberstyle=\scriptsize,
  numbersep=5pt,
}
\lstdefinestyle{docstrip}{
  style=macrocode,
  basicstyle=\sffamily\small,
  literate=<{$\langle$}1>{$\rangle$}1,
}

Usage in the code sections, the indentation with four spaces is no longer necessary:

%    \begin{lstlisting}[style=docstrip, lastline=1, gobble=1]
%<*package>
%    \end{lstlisting}
%\begin{lstlisting}[style=macrocode, lastline=3]
\newcommand*{\hello}[1]{%
  Hello #1!%
}
%\end{lstlisting}
% Some text.
%    \begin{lstlisting}[style=macrocode, lastline=7]
\newcommand*{\lorem}{%
  Lorem
  ipsum
  dolor
  sit
  amet.%
}
%    \end{lstlisting}
%    \begin{lstlisting}[style=docstrip, lastline=1, gobble=1]
%</package>
%    \end{lstlisting}
% End.
%\Finale

Full example:

% \iffalse meta-comment
% !TEX program  = pdfLaTeX
%<*internal>
\iffalse
%</internal>
%<*readme>
----------------------------------------------------------------
demopkg --- description text
E-mail: you@your.domain
Released under the LaTeX Project Public License v1.3c or later
See http://www.latex-project.org/lppl.txt
----------------------------------------------------------------

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
----------------------------------------------------------------
demopkg --- description text
E-mail: you@your.domain
Released under the LaTeX Project Public License v1.3c or later
See http://www.latex-project.org/lppl.txt
----------------------------------------------------------------

\endpreamble
\postamble

Copyright (C) 2009 by You <you@your.domain>

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
You.

This work consists of the file  demopkg.dtx
and the derived files           demopkg.ins,
                                demopkg.pdf and
                                demopkg.sty.

\endpostamble
\usedir{tex/latex/demopkg}
\generate{
  \file{\jobname.sty}{\from{\jobname.dtx}{package}}
}
%</install>
%<install>\endbatchfile
%<*internal>
\usedir{source/latex/demopkg}
\generate{
  \file{\jobname.ins}{\from{\jobname.dtx}{install}}
}
\nopreamble\nopostamble
\usedir{doc/latex/demopkg}
\generate{
  \file{README.txt}{\from{\jobname.dtx}{readme}}
}
\ifx\fmtname\nameofplainTeX
  \expandafter\endbatchfile
\else
  \expandafter\endgroup
\fi
%</internal>
%<*package>
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{demopkg}[2009/10/06 v1.0 description text]
%</package>
%<*driver>
\documentclass{ltxdoc}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage{listings}
\lstdefinestyle{macrocode}{
  name=macrocode,
  language=[LaTeX]TeX,
  %basicstyle=\fontfamily{lmvtt}\selectfont\small,
  basicstyle=\ttfamily\small,
  columns=fullflexible,
  numbers=left,
  numberfirstline=1,
  firstnumber=auto,
  numberstyle=\scriptsize,
  numbersep=5pt,
}
\lstdefinestyle{docstrip}{
  style=macrocode,
  basicstyle=\sffamily\small,
  literate=<{$\langle$}1>{$\rangle$}1,
}
%\let\macrocode\relax
\lstnewenvironment{macrocodeX}[1][]{%
  \lstset{style=macrocode,#1}%
}{}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage{\jobname}
\usepackage[numbered]{hypdoc}
\EnableCrossrefs
\CodelineIndex
\RecordChanges
\begin{document}
  \DocInput{\jobname.dtx}
\end{document}
%</driver>
% \fi
%
%\GetFileInfo{\jobname.sty}
%
%\title{^^A
%  \textsf{demopkg} --- description text\thanks{^^A
%    This file describes version \fileversion, last revised \filedate.^^A
%  }^^A
%}
%\author{^^A
%  You\thanks{E-mail: you@your.domain}^^A
%}
%\date{Released \filedate}
%
%\maketitle
%
%\changes{v1.0}{2009/10/06}{First public release}
%
%\DescribeMacro{\examplemacro}
% Some text about an example macro called \cs{examplemacro}, which
% might have an optional argument \oarg{arg1} and mandatory one
% \marg{arg2}.
%
%\StopEventually{^^A
%  \PrintChanges
%  \PrintIndex
%}
%
%    \begin{macrocode}
%<*package>
%    \end{macrocode}
%
%\begin{macro}{\examplemacro}
%\changes{v1.0}{2009/10/06}{Some change from the previous version}
%    \begin{macrocode}
\newcommand*\examplemacro[2][]{%
  Some code here, probably.
  Lorem
  ipsum
  dolor
  sit
  amet.%
}
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
%</package>
%    \end{macrocode}
%
%    \begin{lstlisting}[style=docstrip, lastline=1, gobble=1]
%<*package>
%    \end{lstlisting}
%\begin{lstlisting}[style=macrocode, lastline=3]
\newcommand*{\hello}[1]{%
  Hello #1!%
}
%\end{lstlisting}
% Some text.
%    \begin{lstlisting}[style=macrocode, lastline=7]
\newcommand*{\lorem}{%
  Lorem
  ipsum
  dolor
  sit
  amet.%
}
%    \end{lstlisting}
%    \begin{lstlisting}[style=docstrip, lastline=1, gobble=1]
%</package>
%    \end{lstlisting}
% End.
%\Finale

Result, which shows both the original macrocode and the version with lstlisting:

Result

Also environment macrocode can be redefined:

% Preamble of documentation driver:
\let\macrocode\relax
\lstnewenvironment{macrocode}[1][]{%
  \lstset{style=macrocode,#1}%
}{}

The optional argument takes the options for style and lastline, e.g.:

%    \begin{macrocode}[style=docstrip, lastline=1, gobble=1]
%<*package>
%    \end{macrocode}
%\begin{macrocode}[style=macrocode, lastline=3]
\newcommand*{\hello}[1]{%
  Hello #1!%
}
%\end{macrocode}
% Some text.
%    \begin{macrocode}[style=macrocode, lastline=7]
\newcommand*{\lorem}{%
  Lorem
  ipsum
  dolor
  sit
  amet.%
}
%    \end{macrocode}
%    \begin{macrocode}[style=docstrip, lastline=1, gobble=1]
%</package>
%    \end{macrocode}
%
  • Wow, I had no idea this would be so complicated. I only noticed two small issues that I'm not sure warrant a separate question: 1) The line numbers in the lstlisting environment protrude into the margin, but setting xleftmargin to 1.4em seems to fix that, though if anyone knows the exact number, I am all ears; and 2) adding a frame to a newenvironment (but not a newcommand enclosed in a macro environment (name in margin) leads to an interrupted frame for some reason. – ThomasH May 24 '16 at 16:43
  • @ThomasH 1) The width depends on the number of digits for the maximum line number, the font and font size for the line numbers. 2) I do not get interrupted frames, if I add frame=lrbt to stylemacrocode. Maybe a followup question with proper MWE makes sense. – Heiko Oberdiek May 24 '16 at 16:52

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.