The moreverb package^{∗}

Robin Fairbairns (rf@cl.cam.ac.uk) after Angus Duggan, Rainer Schöpf and Victor Eijkhout

1996/06/23

Contents

1 This package 1 1.1 Tab expansion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.2 Line numbering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.3 Miscellenea . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

2 The code of the package 3 2.1 Initial code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 2.2 Writing to a file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 2.3 Tab expansion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

1 This package

This package uses the facilities provide by the verbatim package in the L^{A}TEX 2ε tools distribution to provide a number of things that were rejected as unnecessary in the development of that package. (Nevertheless, the tab-expansion code in this package responds to one of the FAQs of comp.text.tex)

The package provides things in three broad areas:

• Tab expansion and related stuff,

• Line numbering,

• Miscellaneous: writing verbatim to a file (for example, for later re-input) , and ‘boxed’ verbatim.

1.1 Tab expansion

The package enables you to specify the expected width of the tabulation, and also allows input of files containing tabs.

verbatimtab

\begin{verbatimtab}[⟨tab width⟩] reproduces its body verbatim, with the tabs expanded to the given width (the default value is 8).

\verbatimtabinput

\verbatimtabinput[⟨tab width⟩]{⟨file name⟩} is a file input version of the verbatimtab environment.

\verbatimtabsize

The size of the tabs is stored in \verbatimtabsize, and persists between uses of the environments. (I.e., an optional argument to one of them applies to all subsequent ones.) To replace the value other than by use of an optional argument, you need to say:

   \renewcommand\verbatimtabsize{⟨value⟩\relax}

There are no promises offered as to the performance if you omit the \relax!

1.2 Line numbering

Line numbering is often useful when reproducing code examples (useful, that is, for those of us who don’t want to pretty-print such snippets).

listing

\begin{listing}[⟨interval⟩]{⟨start line⟩} numbers the lines of its body. The argument ⟨start line⟩ specifies the starting line number. The optional argument ⟨interval⟩ specifies the number of lines between numbered lines: that is, every line whose number = 0 (mod ⟨interval⟩) will be numbered in the output. (In addition, line number 1 will always be numbered.) The default value of the ⟨interval⟩ is 1 (i.e., every line will be numbered).

listingcont

\begin{listingcont} continues from the place where the last listing left off. The style in which the label is set can be altered, for either environment, by

re-defining \listinglabel. Both environments also expand tabs.

‘*’ versions of both the listing environments are provided; these do the usual verbatim* thing of outputting spaces as ‘␣’, but don’t expand tabs.

listinginput

\listinginput[⟨interval⟩]{⟨start line⟩}{⟨filename⟩} is a file input version of listing. There is no ‘*’ form.

1.3 Miscellenea

verbatimwrite

\begin{verbatimwrite}{⟨filename⟩} writes all text in its body to a file, the name of which it is given as an argument.

boxedverbatim

\begin{boxedverbatim} puts the contents of a verbatim environment in a framing box. If you try to do this in a naïve way, you find that the verbatim lines have all become the width of the line, so that the box is, more often than not, a very poor fit to the text it surrounds.

verbatimcmd

The verbatimcmd environment was provided by the L^{A}TEX2.09 and early L^{A}TEX 2ε versions of this package. However, its capabilities are now provided by alltt, which is defined by the alltt package, now part of the L^{A}TEX base distribution, and so verbatimcmd has been withdrawn.

∗This file has version number v2.2c, last revised 1996/05/24

2 The code of the package

1 ⟨∗moreverb⟩

2.1 Initial code

Load the verbatim package if it’s not already loaded.

 2 \@ifundefined{verbatim@processline}{\RequirePackage{verbatim}}{}

2.2 Writing to a file

verbatimwrite \begin{verbatimwrite}{⟨filename⟩} writes all text in its body to a file, the name of which it is given as an argument. (This code was written by Rainer Schöpf.)

 3 \newwrite \verbatim@out
 4 \def\verbatimwrite#1{%
 5 \@bsphack
 6 \immediate\openout \verbatim@out #1
 7 \let\do\@makeother\dospecials
 8 \catcode`\^^M\active \catcode`\^^I=12
 9 \def\verbatim@processline{%
10  \immediate\write\verbatim@out
11  {\the\verbatim@line}}%
12 \verbatim@start}
13 \def\endverbatimwrite{%
14 \immediate\closeout\verbatim@out
15 \@esphack}

2.3 Tab expansion

We define a few auxiliary macros and counters for expanding tabs. They are used by the listing and verbatimtab environments.

16 \newcount\tab@position \newcount\tab@size

\verbatimtabsize used to be a counter, but that seems to me overkill (L^{A}TEX uses too many counters as it is…).

17 \def\verbatimtabsize{8\relax}

\@xobeytab \@xobeytab actually executes the positioning when a tab is encountered.

18 \def\@xobeytab{\leavevmode\penalty\@M
19 {\loop\ \global\advance\tab@position-1 \ifnum\tab@position>0 \repeat}}

\@vobeytabs \@vobeytabs initialises use of \@xobeytab. Needs to be executed within a group, as mustn’t be allowed to leak out into the wide world.

20 \begingroup
21 \catcode`\^^I=\active
22 \gdef\@vobeytabs{\catcode`\^^I\active\let^^I\@xobeytab}%
23 \endgroup

\verbatim@tabexpand \verbatim@tabexpand⟨body of line⟩\@nil processes every character of a line by tail recursion, counting the characters and juggling things when a tab is encountered. (What used to be called ‘line imaging’…)

24 \def\verbatim@tabexpand#1{%
25 \ifx#1\@nil \expandafter\par \else
26  \ifx#1\@xobeysp \@xobeysp\advance\tab@position-1 \else
27  \ifx#1\@xobeytab \@xobeytab\else
28  #1\advance\tab@position-1
29  \fi\fi
30  \ifnum\tab@position=0 \tab@position\tab@size \fi
31  \expandafter\verbatim@tabexpand
32 \fi

33 }

listing  \begin{listing}[⟨interval⟩]{⟨start line⟩}

Defines a verbatim environment with numbered lines; the optional argument ⟨interval⟩ specifies the number of lines between numbered lines, and the argument ⟨start line⟩ specifies the starting line.

listingcont  \begin{listingcont}

Continues from the place where listing left off. The style in which the label is set can be altered by re-defining \listinglabel.

‘*’ versions of both environments are provided.

\listing@line \listing@line holds the current line number; its default value is 1, so one can merrily use listingcont throughout a document if there’s but one stream of verbatim text being written.

34 \newcount\listing@line \listing@line=1

\listing@step \listing@step is another case where a counter used to be used, to no very obvious utility, but using up a valuable count register. Again, the value is modal; the trailing \relax is necessary.

35 \def\listing@step{1\relax}

Adding an \hbox in front of the line causes a line break, so I^{1} go through this rigmarole to get the lines aligned nicely. I probably missed some obvious reason why \hboxes don’t work^{2}.

36 \def\listinglabel#1{\rlap{\small\rmfamily\the#1}\hskip2.5em}
37 \def\thelisting@line{%
38 \setbox0\hbox{\listinglabel\listing@line}%
39 \@tempcnta=\listing@line
40 \divide\@tempcnta\listing@step \multiply\@tempcnta\listing@step
41 \ifnum\listing@line=1
42  \unhbox0
43 \else
44  \ifnum\@tempcnta=\listing@line
45  \unhbox0

1The personal pronoun was present in the comments in the original version of this package; I’m not sure who it relates to — RF

2It’s because an \hbox in vertical mode makes a complete paragraph in its own right; this problem could be dealt with in the fullness of time, but just now…

46  \else
47  \hskip\wd0
48  \fi
49 \fi}

Define \listing simply to suck in parameters and then to use \listingcont

50 \newcommand\listing[2][1]{%
51 \global\listing@line=#2\relax
52 \gdef\listing@step{#1\relax}
53 \listingcont}

\listingcont is the business end of the two environments.

54 \def\listingcont{%
55 \tab@size=\verbatimtabsize
56 \def\verbatim@processline{\tab@position\tab@size
57  \thelisting@line \global\advance\listing@line1
58  \expandafter\verbatim@tabexpand\the\verbatim@line\@nil}%
59 \@verbatim\frenchspacing\@vobeyspaces\@vobeytabs\verbatim@start}

Nothing special at the end of the two environments.

60 \let\endlisting=\endtrivlist
61 \let\endlistingcont=\endtrivlist

Now the same rigmarole for the ‘*’ versions.

62 \expandafter\newcommand\csname listing*\endcsname[2][1]{%
63 \global\listing@line=#2\relax
64 \gdef\listing@step{#1\relax}
65 \csname listingcont*\endcsname}
66 \@namedef{listingcont*}{%
67 \def\verbatim@processline{%
68  \thelisting@line \global\advance\listing@line1
69  \the\verbatim@line\par}%
70 \@verbatim\verbatim@start}

Nobbut a bit of hassle in the name definitions for the end of the environments

71 \expandafter\let\csname endlisting*\endcsname\endtrivlist
72 \expandafter\let\csname endlistingcont*\endcsname\endtrivlist

listinginput \listinginput[⟨interval⟩]{⟨start line⟩}{⟨filename⟩} is a file input version of listing.

73 \def\listinginput{%
74 \@ifnextchar[%]
75  {\@listinginput}%
76  {\@listinginput[1]}}
77 {\catcode`\~=\active \lccode`\~=`\^^M \lccode`\N=`\N
78 \lowercase{%
79 \gdef\@listinginput[#1]#2#3{\begingroup
80  \global\listing@line=#2
81  \gdef\listing@step{#1\relax}
82  \tab@size=\verbatimtabsize
83  \def\verbatim@processline{\tab@position\tab@size
84  \thelisting@line \global\advance\listing@line1
85  \expandafter\verbatim@tabexpand\the\verbatim@line\@nil}%
86  \@verbatim\frenchspacing\@vobeyspaces\@vobeytabs

 87  \def\verbatim@addtoline##1~{%
 88  \verbatim@line\expandafter{\the\verbatim@line##1}}%
 89  \openin\verbatim@in@stream=#3
 90  \ifeof\verbatim@in@stream
 91  \PackageWarning{moreverb}{No file #3.}%
 92  \else
 93  \verbtab@oktrue
 94  \loop
 95  \read\verbatim@in@stream to \verbtab@line
 96  \ifeof\verbatim@in@stream
 97  \verbtab@okfalse
 98  \else
 99  \expandafter\verbatim@addtoline\verbtab@line
100  \verbatim@processline
101  \verbatim@startline
102  \fi
103  \ifverbtab@ok\repeat
104  \closein\verbatim@in@stream\fi
105  \endtrivlist\endgroup\@doendpe}}}

verbatimcmd verbatimcmd was a verbatim environment with the exception of the escape and grouping characters \, {, }. This is (err) exactly the specification of the alltt environment, and that is in the alltt package that is now part of the base distribution.

106 \def\verbatimcmd{%
107 \PackageError{moreverb}{The verbatimcmd environment is obsolete%
108  \MessageBreak
109  Use alltt in its place}%

110 }

111 \let\endverbatimcmd\relax

boxedverbatim boxedverbatim puts the contents of a verbatim environment in a framing box. (Written by Victor Eijkhout.) Bug fix (supplied by David Carlisle) 1995/12/28, marked %%%DPC%%% First, redefine ‘processline’ to produce only a line as wide as the natural width

of the line

112 \def\boxedverbatim{%
113 \def\verbatim@processline{%
114  {\setbox0=\hbox{\the\verbatim@line}%
115  \hsize=\wd0 \the\verbatim@line\par}}%

Now save the verbatim code in a box

116 \@minipagetrue%%%DPC%%%
117 \@tempswatrue%%%DPC%%%
118 \setbox0=\vbox\bgroup \verbatim

119 }

At the end of the environment, we (umm) simply have to stick the results into a frame.

120 \def\endboxedverbatim{%
121 \endverbatim
122 \unskip\setbox0=\lastbox %%%DPC%%%

Now everything’s in the box, so we can close it…

123 \egroup

To change the code for centring, the net line needs a spot of hacking.

124 \fbox{\box0}% <<<=== change here for centering,...

125 }

verbatimtab \begin{verbatimtab}[⟨tab width⟩] is a verbatim environment which expands tab characters; the optional argument specifies the distance betwee tab stops.

126 \newcommand\verbatimtab[1][\verbatimtabsize]{%
127 \do@verbatimtab{#1}{%
128  \@verbatim\frenchspacing\@vobeyspaces\@vobeytabs\verbatim@start}%

129 }

130 \def\do@verbatimtab#1#2{%
131 \tab@size=#1
132 \def\verbatim@processline{\tab@position\tab@size
133  \expandafter\verbatim@tabexpand\the\verbatim@line\@nil}#2

134 }

135 \let\endverbatimtab=\endtrivlist

This conditional is used in \listinginput and \verbatimtabinput as well:

136 \newif\ifverbtab@ok

\verbatimtabinput \verbatimtabinput[⟨tab width⟩]{⟨file name⟩} is a file input version of the

verbatimtab environment.

We use the input stream acquired by the verbatim package; we did after all require it to be loaded. (One has to admit that the name of that stream isn’t actually part of the package’s defined interface, but on the other hand there’s no particular likelihood that it will ever change.)

We can’t use fancy features of \newcommand since the definition has to be inside a group, and hence global. So … ‘traditional’ code to provide a command with an optional argument:

137 \def\verbatimtabinput{%
138 \@ifnextchar[%]
139  {\@verbatimtabinput}%
140  {\@verbatimtabinput[\verbatimtabsize]}}
141 {\catcode`\~=\active \lccode`\~=`\^^M \lccode`\N=`\N
142 \lowercase{%
143 \gdef\@verbatimtabinput[#1]#2{\begingroup
144  \do@verbatimtab{#1}{%
145  \@verbatim\frenchspacing\@vobeyspaces\@vobeytabs}%
146  \def\verbatim@addtoline##1~{%
147  \verbatim@line\expandafter{\the\verbatim@line##1}}%
148  \openin\verbatim@in@stream=#2
149  \ifeof\verbatim@in@stream
150  \PackageWarning{moreverb}{No file #2.}
151  \else
152  \verbtab@oktrue
153  \loop
154  \read\verbatim@in@stream to \verbtab@line
155  \ifeof\verbatim@in@stream\verbtab@okfalse
156  \else

157  \expandafter\verbatim@addtoline\verbtab@line
158  \verbatim@processline
159  \verbatim@startline
160  \fi
161  \ifverbtab@ok\repeat
162  \closein\verbatim@in@stream
163  \fi
164 \endtrivlist\endgroup\@doendpe}}}

165 ⟨/moreverb⟩