diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/jvlisting/jvlisting.dtx |
Initial commit
Diffstat (limited to 'macros/latex/contrib/jvlisting/jvlisting.dtx')
-rw-r--r-- | macros/latex/contrib/jvlisting/jvlisting.dtx | 642 |
1 files changed, 642 insertions, 0 deletions
diff --git a/macros/latex/contrib/jvlisting/jvlisting.dtx b/macros/latex/contrib/jvlisting/jvlisting.dtx new file mode 100644 index 0000000000..c1f038906a --- /dev/null +++ b/macros/latex/contrib/jvlisting/jvlisting.dtx @@ -0,0 +1,642 @@ +% \iffalse +% jvlisting.dtx - docstrip archive for the jvlisting macro package +%<*gobble> +\iffalse +%</gobble> +%<*install> +\input docstrip.tex + +\preamble + +Copyright (C) 2011 Jochen Voss <voss@seehuhn.de> + +This work may be distributed and/or modified under the conditions of +the LaTeX Project Public License, either version 1.3 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.3 or later is part of all distributions of LaTeX version +2005/12/01 or later. + +This work has the LPPL maintenance status `maintained' and the current +Maintainer of this work is Jochen Voss <voss@seehuhn.de>. + +This work consists of the files jvlisting.dtx, test.tex and the +derived files jvlisting.sty, jvlisting.ins and examples.tex. +\endpreamble +%</install> +%<*gobble> +\fi +%</gobble> +%<*driver> +\documentclass{ltxdoc} +\usepackage[text={6in,9in},centering]{geometry} +\usepackage{hyperref} +\usepackage{jvlisting} +\setlength{\parskip}{0pt plus.5ex} +\setlength{\listingskipamount}{.6ex plus.5ex minus.1ex} +\PageIndex +\NewListingEnvironment{xlist}{0}{\prelistingskip}% + {\listingfont\small\renewcommand{\baselinestretch}{0.95}}% + {\ListingTypesetLine}{\postlistingskip} +\begin{document} +\DocInput{jvlisting.dtx} +\end{document} +%</driver> +%<*examples> + +\documentclass{article} + +\usepackage[text={6in,9in},centering]{geometry} +\usepackage{jvlisting} +\setlength{\listingskipamount}{2\baselineskip} + +\begin{document} +%</examples> +%<*usage> +% \fi +\GetFileInfo{jvlisting.sty} +\title{The \textsf{jvlisting} package} +\date{\filedate\ \fileversion} +\author{Jochen Voss\\ \texttt{voss@seehuhn.de}\\ \texttt{http://seehuhn.de/}} +\maketitle + +\begin{abstract} + This package provides the \LaTeX\ environment \verb|listing|, an + alternative to the built-in \verb|verbatim| environment. The + \verb|listing| environment is specially tailored for including + listings of computer program source code into documents. The main + advantages over the original \verb|verbatim| environment are that + \verb|listing| environments automatically fix leading white-space + so that the environment and program listing can be indented with + the rest of the document source and that \verb|listing| + environments can easily be customised and extended. +\end{abstract} + +\tableofcontents + +\section{Basic Usage} + +The \verb|listing| environment allows to include source code of +computer programs in \LaTeX\ documents by including the code between +\verb|\begin{listing}| and \verb|\end{listing}|. + +\medskip + +\textbf{Example.} In order to typeset the listing of a simple Python +function (computing the cumulative sum of a list) you can use the +following code in your \LaTeX\ document. +\begin{xlist} + \begin{listing} + def cumsum(iterable): + return reduce(lambda res, x: res+[res[-1]+x], iterable, [0])[1:] + \end{listing} +\end{xlist} +\noindent +These commands result in the following output: +% \iffalse +%</usage> +%<*examples|usage> +% \fi + +\begin{listing} + def cumsum(iterable): + return reduce(lambda res, x: res+[res[-1]+x], iterable, [0])[1:] +\end{listing} +% \iffalse +%</examples|usage> +%<*usage> +% \fi + +\medbreak + +Differently from the \LaTeX\ \verb|verbatim| environment, the +\verb|listing| environment can be indented to match the surrounding +document source. The following will work as expected: +\begin{xlist} + \begin{figure}[h] + \begin{listing} + def cumsum(iterable): + return reduce(lambda res, x: res+[res[-1]+x], iterable, [0])[1:] + \end{listing} + \end{figure} +\end{xlist} +\noindent +The Python code will be typeset using the same indentation as in the +previous example, despite the fact that the code in the two +\verb|listing| environments has different indentation in the +\LaTeX\ source code. + +To make it easier to copy real program source code directly into your +\LaTeX\ file, the code in listings can be indented by TAB characters +instead of spaces. The TAB spacing is assumed to be 8 character +columns. + +In addition to the \LaTeX\ environment described above, there is also +a command \verb|\filelisting| to typeset source code contained in a +file. The command takes one argument, the name of the file to +include, and behaves very similar to the the \verb|listing| +environment. + +\medskip + +\textbf{Example.} In order to typeset the contents of a file +\verb|cumsum.py|, we could use the following command. +\begin{xlist} + \filelisting{cumsum.py} +\end{xlist} + +\bigbreak + +There are various parameters to customise how listings are typeset. +These parameters apply both to the \verb|listing| environment and +to the \verb|\filelisting| command. +\begin{itemize} +\item The amount of space inserted before and after a listing is + given by \verb|\listingskipamount|. The default value is + \verb|1ex|. Commands like the following can be used to adjust the + amount of space. + \begin{xlist} + \setlength{\listingskipamount}{1\baselineskip} + \end{xlist} +\item The indentation of the left margin of the typeset code is + determined by \verb|\listingindent|. The default value is + \verb|2em|. Commands like the following can be used to adjust + indentation. + \begin{xlist} + \setlength{\listingindent}{2cm} + \end{xlist} +\item The font used in the listing is controlled by the macro + \verb|\listingfont|. The default value is \verb|\normallistingfont| + which sets up a typewriter-like font. Example: The following + command can be used to obtain more compact listings by slightly + reducing the font size and the line spacing. + \begin{xlist} + \renewcommand{\listingfont}% + {\normallistingfont\small\renewcommand{\baselinestretch}{0.95}} + \end{xlist} +\item The penalty for page breaks inside a listing is given by + \verb|\listingpenalty|. The higher this value, the less attractive + page breaks inside the listing are to \LaTeX's page breaking + algorithm. The default value is 500. The following command can be + used to completely disable page breaks inside listings. + \begin{xlist} + \listingpenalty=10000 + \end{xlist} +\item The penalty for page breaks just before or after a listing is + given by \verb|\prelistingpenalty| (default value 100) and + \verb|\postlistingpenalty| (default value -50), respectively. +\end{itemize} + +\section{Extending the \textsf{listing} Environment} + +New \verb|listing|-like environments can be defined using the +\verb|\NewListingEnvironment| macro. This macro takes six arguments +and uses them to define a new \LaTeX\ environment. The arguments, in +order, are +\begin{enumerate} +\item The name of the new environment. +\item The number of extra arguments for the new environment + (normally~0). These extra arguments of the environment, if any, are + substituted into the initialisation commands (\textit{i.e.}\ into + the fourth argument of \verb|\NewListingEnvironment|); see the + \verb|copylisting| environment, below, for an example. +\item Commands to execute before the environment is entered + (\textit{e.g.}\ to add vertical white space). +\item Initialisation commands, executed inside the environment + (\textit{e.g.}\ font/margin setup). +\item The name of a macro (receiving one argument) which will be used + to typeset each line of input. +\item Commands to execute after the environment is completed. +\end{enumerate} + +\medskip + +\textbf{Example.} The \verb|listing| environment provided by the +\verb|jvlisting| package is defined using the following commands: +% \iffalse +%</usage> +%<*listingdef|usage> +% \fi + +% \begin{macrocode} +\let\listingfont=\normallistingfont +\newcommand{\ListingTypesetLine}[1]{\ifvmode\penalty\listingpenalty\noindent\fi + \hskip\listingindent\strut#1\par} +\newcommand{\prelistingskip}{\endgraf\ifdim\lastskip>\listingskipamount\else + \removelastskip\penalty\prelistingpenalty\vskip\listingskipamount\fi} +\newcommand{\postlistingskip}{\endgraf\penalty\postlistingpenalty + \vskip-\parskip\nobreak\vskip\listingskipamount\noindent} +\NewListingEnvironment{listing}{0}{\prelistingskip}% + {\listingfont\let\ListingStartHook\listingstarthook}{\ListingTypesetLine}% + {\postlistingskip\ignorespacesafterend} +% \end{macrocode} +% \iffalse +%</listingdef|usage> +%<*usage> +% \fi + +\medbreak + +\textbf{Example.} An \verb|nlisting| environment which generates +listings with additional line numbers can be defined as follows: +% \iffalse +%</usage> +%<*examples|usage> +% \fi + +% \begin{macrocode} +\newcounter{lineno} +\newcommand{\typesetnline}[1]{\addtocounter{lineno}{1}% + \noindent\hskip\listingindent\llap{{\it\scriptsize\arabic{lineno}: }}% + \strut #1\par\penalty\listingpenalty} +\NewListingEnvironment{nlisting}{0}{\prelistingskip}% + {\setcounter{lineno}{0}\listingfont}{\typesetnline}{\postlistingskip} +% \end{macrocode} +% \iffalse +%</examples|usage>> +%<*examples> +\begin{nlisting} + for i in [1, 2, 3]: + for j in ['a', 'b', 'c']: + print str(i)+j +\end{nlisting} +%</examples> +%<*usage> +% \fi + +\medbreak + +\textbf{Example.} The following code defines a new \verb|copylisting| +environment which does not only typeset the source code, but also +saves a copy in an external file. Here we need to be careful in case +the quote character \verb|`| can be present in the listing: by +default, \verb|\listingfont| makes \verb|`| an active character in +order to prevent problems with ligatures, but this fix causes damage +to the output of the \verb|\write| command. To work around this +problem, we can use \verb|\DisableLigatureFix| (defined by the +\verb|jvlisting| package for just this purpose) to temporarily disable +the ligature fix. +% \iffalse +%</usage> +%<*examples|usage> +% \fi + +% \begin{macrocode} +\newwrite\outfile +\newcommand{\copytypeset}[1]{\ListingTypesetLine{#1}% + {\DisableLigatureFix\immediate\write\outfile{#1}}} +\NewListingEnvironment{copylisting}{1}{\prelistingskip}% + {\immediate\openout\outfile=#1\listingfont}{\copytypeset}% + {\immediate\closeout\outfile\postlistingskip} +% \end{macrocode} +% \iffalse +%</examples|usage>> +%<*usage> +% \fi +Here we used the second argument to \verb|\NewListingEnvironment| to +indicate that the \verb|copylisting| environment should take an +additional parameter (the output file name). The new environment is +used as follows: +% \iffalse +%</usage> +%<*examples|usage> +% \fi + +% \begin{macrocode} +\begin{copylisting}{listing1.c} + #include <stdio.h> + + int + main() + { + puts("hello, world!"); + return 0; + } +\end{copylisting} +% \end{macrocode} +% \iffalse +%</examples|usage>> +%<*usage> +% \fi + +\section{Extending the \textsf{filelisting} Command} + +New \verb|filelisting|-like commands can be defined using the +\verb|\NewFileListingCommand| macro. This macro takes six arguments +and uses them to define a new macro. The arguments, in order, are +\begin{enumerate} +\item The name of the new command including the leading backslash. +\item The number of arguments for the new command (normally~1). These + arguments, including the first one which gives the file name, are + substituted into the third, fourth and sixth argument of + \verb|\NewFileListingCommand|); see the \verb|\prefixfilelisting| + command, below, for an example. +\item Commands to execute before the listing is started + (\textit{e.g.}\ to add vertical white space). +\item Initialisation commands, executed inside the scope of the + listing (\textit{e.g.}\ font/margin setup). +\item The name of a macro (receiving one argument) which will be used + to typeset each line of input. +\item Commands to execute after the listing is completed. +\end{enumerate} +The first argument of the newly defined macro always denotes the name +of the file to include. + +\medskip + +\textbf{Example.} Using the auxiliary functions for the +\verb|listing| environment, the built-in \verb|filelisting| command +can be defined as follows: +% \iffalse +%</usage> +%<*listingdef|usage> +% \fi + +% \begin{macrocode} +\NewFileListingCommand{\filelisting}{1}{\prelistingskip}% + {\listingfont}{\ListingTypesetLine}{\postlistingskip} +% \end{macrocode} +% \iffalse +%</listingdef|usage> +%<*usage> +% \fi + +\medbreak + +\textbf{Example.} The following command defines a macro to read a +file and to prefix every line of the resulting listing with a given +string. +% \iffalse +%</usage> +%<*examples|usage> +% \fi + +% \begin{macrocode} +\newcommand{\pfxtypeset}[1]{\noindent\hskip\listingindent\strut + \pfx#1\par\penalty\listingpenalty} +\NewFileListingCommand{\prefixfilelisting}{2}{\prelistingskip}% + {\listingfont\def\pfx{#2}}{\pfxtypeset}{\postlistingskip} +% \end{macrocode} +% \iffalse +%</examples|usage>> +%<*examples> +\prefixfilelisting{listing1.c}{c> } +%</examples> +%<*package> +% \fi + +% \StopEventually{} +% \section{Implementation} +% +% This section describes the internal implementation of the +% \verb|jvlisting| package. In order to avoid name clashes with other +% packages, the names of all internal macros defined in this package +% start with the prefix \verb|jvl@|. The following is the preamble +% for the package file. +% \begin{macrocode} +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{jvlisting}[2011/11/17 v0.7 Formatted Program Listings] +% \end{macrocode} + +% \subsection{Processing the Lines of Input} +% +% We start by provinding a macro \verb|\jvl@iterlines| which can be +% used to iterate over all lines of input until a line containing some +% marker is found. The marker is given as argument \verb|#1| to the +% \verb|\jvl@iterlines| macro. Each line is processed by prepending +% \verb|\jvl@dropempty| (for the first and last line) or +% \verb|\jvl@tryhook| (for all other lines). +% \begin{macrocode} +\def\jvl@iterlines#1{\expandafter\jvl@iterla\expandafter{#1}{\jvl@dropempty}} +{\obeylines\gdef\jvl@iterla#1#2#3 + {\def\jvl@testmarker##1#1{}% + \expandafter\def\expandafter\w\expandafter{\jvl@testmarker#3#1}% + \ifx\w\empty% + \def\next{#2{\jvl@iterla{#1}{\jvl@tryhook}}#3 + }% + \else% + % special treatment for the last line + \def\y##1#1##2#1{\jvl@dropempty{\jvl@end##2}##1 + }% + \def\next{\y#3#1}% + \fi\next}} +% \end{macrocode} + +% The next step in processing is to drop the first line (whatever +% comes directly after the opening \verb|begin| statement) and the +% last line (whatever comes directly before the closing \verb|end| +% statement), if these lines consist only of white space. +% \begin{macrocode} +\def\jvl@dropempty#1{\jvl@dropa{#1}{}} +{\obeylines\gdef\jvl@dropa#1#2#3{\ifx + #3\def\next{#1}% + \else% + \if#3 \def\next{\jvl@dropa{#1}{#2#3}}\else% + \def\next{\jvl@tryhook{#1}#2#3}\fi% + \fi\next}} +% \end{macrocode} + +% Next we try to apply the \verb|\ListingStartHook|. +% \begin{macrocode} +\def\jvl@tryhook#1{\ifx\ListingStartHook\undefined + \def\next{\jvl@countspaces{#1}}% + \else + \def\jvl@trya{\let\ListingStartHook\undefined\jvl@countspaces{#1}}% + \def\next{\ListingStartHook{\jvl@trya}}% + \fi + \next} +% \end{macrocode} + +% Next we determine the indentation level of the current line by +% expanding TAB characters and then counting spaces. The result is +% stored in the scratch counter \verb|@tempcnta|. +% \begin{macrocode} +\def\jvl@countspaces#1{\@tempcnta=0\jvl@counta{#1}} +{\catcode`\^^I=12 +\gdef\jvl@counta#1#2{\if^^I#2% + \advance\@tempcnta by8\divide\@tempcnta by8\multiply\@tempcnta by8 + \def\next{\jvl@counta{#1}}% + \else + \expandafter\if\noexpand#2 % + \advance\@tempcnta by1 + \def\next{\jvl@counta{#1}}% + \else + \def\next{\jvl@fixspaces{#1}#2}% + \fi + \fi\next}} +% \end{macrocode} + +% Using the value in \verb|@tempcnta|, we fix the indentation by first +% subtracting the common indentation level (stored in \verb|\jvl@idt|) +% and then inserting the required number of spaces (using +% \verb|\space|). +% \begin{macrocode} +\newcount\jvl@idt \jvl@idt=\m@ne +{\obeylines\gdef\jvl@fixspaces#1#2{\ifx + #2\else% + \ifnum\jvl@idt<0% + \jvl@idt=\@tempcnta% + \else% + \ifnum\@tempcnta<\jvl@idt\jvl@idt=\@tempcnta\fi% + \fi\fi\jvl@fixa{#1}#2}} +\def\jvl@fixa#1{\ifnum\@tempcnta>\jvl@idt + \advance\@tempcnta by\m@ne + \def\next{\jvl@fixa{#1}\space}% + \else + \def\next{\jvl@output{#1}}% + \fi\next} +% \end{macrocode} + +% Finally, we apply the output function \verb|\jvl@typeset| to the +% processed line and starting processing of the next line. +% \begin{macrocode} +{\obeylines\gdef\jvl@output#1#2 + {\jvl@typeset{#2}#1}} +% \end{macrocode} +% The symbol \verb|\jvl@typeset| will be defined inside the +% \verb|\begin{listing}| command; since neested listings are not +% possible, using a global name for the output function is no +% problem. + +% \subsection{Defining Listing Environments} +% +% In order to allow for verbatim printing, the macro +% \verb|jvl@fixparsing| switches off the special meaning of most +% characters. Some care is needed to avoid problems with spaces and +% hyphenation. +% \begin{macrocode} +{\catcode`\ =\active% +\gdef\jvl@obeyspaces{\frenchspacing\catcode`\ =\active\let \space}} +\def\jvl@fixparsing{\let\do\@makeother\dospecials\catcode`\^^I=12 + \jvl@obeyspaces\hyphenchar\font\m@ne} +% \end{macrocode} + +% Since the \verb|\hyphenchar| setting is global, we save save the +% value of \verb|hyphenchar| before entering the listing environment +% end restore the original setting at the end. +% \begin{macrocode} +\newcount\jvl@tmphyphenchar +\def\jvl@begingroup{\jvl@tmphyphenchar=\hyphenchar\font + \begingroup \parskip0pt \advance\leftskip by\@totalleftmargin} +\def\jvl@endgroup{\endgroup \hyphenchar\font=\jvl@tmphyphenchar} +% \end{macrocode} + +% Given the code above, we can now define the +% \verb|\NewListingEnvironment| macro. Some care is needed when +% constructing the marker for use in the \verb|\jvl@iterlines| macro, +% because the text we need to match uses category code 12 (``other'') +% for the characters \verb|\|, \verb|{| and~\verb|}|. +% \begin{macrocode} +\begingroup + \catcode`|=0 \catcode`[=1 \catcode`]=2 + \catcode`\{=12 \catcode`\}=12 \catcode`\\=12 + |gdef|jvl@makemarker#1[% + |expandafter|gdef|csname jvl@@#1marker|endcsname[\end{#1}]] +|endgroup +\def\NewListingEnvironment#1#2#3#4#5#6{\jvl@makemarker{#1}% + \expandafter\newcommand\csname #1\endcsname[#2]{#3\jvl@begingroup + #4\def\jvl@end{\end{#1}}\let\jvl@typeset=#5% + \jvl@fixparsing\obeylines + \expandafter\def\expandafter\jvl@start\expandafter{% + \expandafter\jvl@iterlines\csname jvl@@#1marker\endcsname}% + \let\next\jvl@start + \next}% + \expandafter\gdef\csname end#1\endcsname{\jvl@endgroup #6}} +% \end{macrocode} + +% \subsection{Reading Listings from File} +% +% When reading listings from a file, we get the lines terminated by +% \verb|^^M| characters. The following function is a replacement for +% \verb|\jvl@iterlines|, used to read lines from a file and to strip +% the trailing \verb|^^M| characters: +% \begin{macrocode} +\newread\jvl@fileinput +\def\jvl@iterfile{\read\jvl@fileinput to\l + \ifeof\jvl@fileinput + \let\next\relax + \else + \expandafter\jvl@iterfa\l + \let\next\jvl@iterfile + \fi\next} +{\catcode`\^^M=12 +\gdef\jvl@iterfa#1^^M{\jvl@iterfb{#1}}} +{\obeylines\gdef\jvl@iterfb#1{\jvl@tryhook{\relax}#1 + }} +% \end{macrocode} +% +% In analogy to \verb|\NewListingEnvironment|, the following macro is +% used to define new functions for listing file contents. +% \begin{macrocode} +\def\NewFileListingCommand#1#2#3#4#5#6{% + \ifnum#2<1 + \PackageError{jvlisting}{% + Invalid number of arguments: `#2' + }{% + The second argument to \protect\NewFileListingCommand\space must be at + least 1. + }% + \fi + \newcommand{#1}[#2]{#3\jvl@begingroup + #4\let\jvl@typeset=#5% + \jvl@fixparsing\catcode`\^^M=12 + \openin\jvl@fileinput=##1\jvl@iterfile\closein\jvl@fileinput + \jvl@endgroup#6% + \ignorespaces + }% +} +% \end{macrocode} + +% \subsection{Finishing Touches} +% +% The following definitions provide default values for the +% customisable parameters of the \verb|listing| environment. +% \begin{macrocode} +\newskip\listingskipamount \listingskipamount=1ex +\newdimen\listingindent \listingindent=2em +\newcount\prelistingpenalty \prelistingpenalty=100 +\newcount\listingpenalty \listingpenalty=500 +\newcount\postlistingpenalty \postlistingpenalty=-50 +% \end{macrocode} +% Finally, we define the default font for use in listings. Some care +% is needed to avoid problems with ligatures like \verb|?`|. We break +% such ligatures by making \verb|`| and active character. For use in +% file listings we also provide \verb|\DisableLigatureFix| to +% (temporarily) disable this fix. +% \begin{macrocode} +{\catcode`\`=\active\gdef`{\relax\lq}% +\gdef\DisableLigatureFix{\def`{\lq}}} +\def\normallistingfont{\normalfont\ttfamily\catcode`\`=\active} +% \end{macrocode} +% \iffalse +%</package> +%<*examples> + +\filelisting{listing1.c} + +\end{document} +%</examples> +%<*install> + +\keepsilent +\askforoverwritefalse + +\generate{% + \file{jvlisting.ins}{\from{jvlisting.dtx}{install}}% + \usedir{tex/latex/jvlisting}% + \file{jvlisting.sty}{\from{jvlisting.dtx}{package}% + \from{jvlisting.dtx}{listingdef}}% + \file{examples.tex}{\from{jvlisting.dtx}{examples}}% +} +\endbatchfile +%</install> +% \fi +% \endinput +% +% Local Variables: +% whitespace-style: (face trailing tabs lines-tail empty space-before-tab) +% whitespace-line-column: 78 +% End: |