The moreverb package^{∗}

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

2002/04/03

Contents

1 This package 1 1.1 Tab expansion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.2 Line numbering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.3 Miscellanea . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 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.

Copyright statement

Program: moreverb.dtx

Copyright 1997 2002 Robin Fairbairns

This program may redistributed and/or modified under the terms of the LaTeX Project Public License Distributed from CTAN archives in file macros/latex/base/lppl.txt; either version 1.2 of the License, or (at your option) any later version.

∗This file has version number v2.2d.2, last revised 1997/12/07

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 Miscellanea

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 page, 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.

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 puts enough spaces in to get us to the next nominal tab stop

18 \def\@xobeytab{%
19 \loop
20  \toks@\expandafter{\the\toks@\@xobeysp}%
21  \advance\tab@position-1
22 \ifnum\tab@position>0 \repeat

23 }

\@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.

24 \begingroup
25 \catcode`\^^I=\active
26 \gdef\@vobeytabs{\catcode`\^^I\active\let^^I\@xobeytab}%
27 \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’…)

28 \def\verbatim@tabexpand#1{%
29 \ifx#1\@nil
30 %   \showthe\toks@
31  \the\toks@
32  \expandafter\par
33 \else
34  \ifx#1\@xobeytab
35  \@xobeytab
36  \else

We can safely put \@xobeysp into the token register, since it does precisely what we need

37  \toks@\expandafter{\the\toks@#1}%
38  \advance\tab@position\m@ne
39  \fi
40  \ifnum\tab@position=0 \tab@position\tab@size \fi
41  \expandafter\verbatim@tabexpand
42 \fi

43 }

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.

44 \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.

45 \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}.

46 \def\listinglabel#1{\llap{\small\rmfamily\the#1}\hskip\listingoffset\relax}
47 \def\thelisting@line{%
48 \setbox0\hbox{\listinglabel\listing@line}%
49 \@tempcnta=\listing@line
50 \divide\@tempcnta\listing@step \multiply\@tempcnta\listing@step
51 \ifnum\listing@line=\@ne
52  \unhbox0
53 \else
54  \ifnum\@tempcnta=\listing@line
55  \unhbox0
56  \else
57  \hskip\wd0
58  \fi
59 \fi}

\listingoffset \listingoffset is the separation between the line number and the actual line being listed; default value is 1.5em

60 \providecommand\listingoffset{1.5em}

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

61 \newcommand\listing[2][1]{%
62 \global\listing@line=#2\relax
63 \gdef\listing@step{#1\relax}
64 \listingcont}

\listingcont is the business end of the two environments.

65 \def\listingcont{%
66 \tab@size=\verbatimtabsize
67 \def\verbatim@processline{\tab@position\tab@size
68  \thelisting@line \global\advance\listing@line1
69  \toks@{}%
70  \expandafter\verbatim@tabexpand\the\verbatim@line\@nil}%
71 \@verbatim\frenchspacing\@vobeyspaces\@vobeytabs\verbatim@start}

Nothing special at the end of the two environments.

72 \let\endlisting=\endtrivlist
73 \let\endlistingcont=\endtrivlist

Now the same rigmarole for the ‘*’ versions.

74 \expandafter\newcommand\csname listing*\endcsname[2][1]{%
75 \global\listing@line=#2\relax
76 \gdef\listing@step{#1\relax}
77 \csname listingcont*\endcsname}
78 \@namedef{listingcont*}{%
79 \def\verbatim@processline{%
80  \thelisting@line \global\advance\listing@line1

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…

 81  \the\verbatim@line\par}%
 82 \@verbatim\verbatim@start}

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

 83 \expandafter\let\csname endlisting*\endcsname\endtrivlist
 84 \expandafter\let\csname endlistingcont*\endcsname\endtrivlist

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

 85 \def\listinginput{%
 86 \@ifnextchar[%]
 87  {\@listinginput}%
 88  {\@listinginput[1]}}
 89 \begingroup
 90 \catcode`\~=\active \lccode`\~=`\^^M \lccode`\N=`\N
 91 \lowercase{\endgroup
 92  \def\@listinginput[#1]#2#3{\begingroup
 93  \global\listing@line=#2
 94  \gdef\listing@step{#1\relax}
 95  \tab@size=\verbatimtabsize
 96  \def\verbatim@processline{\tab@position\tab@size
 97  \thelisting@line \global\advance\listing@line1
 98  \toks@{}%
 99  \expandafter\verbatim@tabexpand\the\verbatim@line\@nil}%
100  \@verbatim\frenchspacing\@vobeyspaces\@vobeytabs
101  \def\verbatim@addtoline##1~{%
102  \verbatim@line\expandafter{\the\verbatim@line##1}}%
103  \openin\verbatim@in@stream=#3
104  \ifeof\verbatim@in@stream
105  \PackageWarning{moreverb}{No file #3.}%
106  \else
107  \do@verbatimtabinput
108  \closein\verbatim@in@stream
109  \fi
110  \endtrivlist\endgroup
111  \@doendpe

112 }% 113 }

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.

114 \def\verbatimcmd{%
115 \PackageError{moreverb}{The verbatimcmd environment is obsolete}%
116  {Use alltt (from the LaTeX base package
117  alltt) in place of verbatimcmd}%

118 }

119 \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

120 \def\boxedverbatim{%
121 \def\verbatim@processline{%
122  {\setbox0=\hbox{\the\verbatim@line}%
123  \hsize=\wd0 \the\verbatim@line\par}}%

Now save the verbatim code in a box

124 \@minipagetrue%%%DPC%%%
125 \@tempswatrue%%%DPC%%%
126 \setbox0=\vbox\bgroup \verbatim

127 }

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

128 \def\endboxedverbatim{%
129 \endverbatim
130 \unskip\setbox0=\lastbox %%%DPC%%%

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

131 \egroup

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

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

133 }

verbatimtab \begin{verbatimtab}[⟨tab width⟩] is a verbatim environment which expands tab

characters; the optional argument specifies the distance between tab stops.

Executing \obeylines before looking for the optional argument prevents an empty first line of the environment becoming a \par token (this bug was reported by Werner Lemberg).

134 \newenvironment{verbatimtab}{\obeylines\@verbatimtab}{\endtrivlist}

Process the optional argument of the verbatimtab, now that we have protected ourselves from the dreaded \par tokens

135 \newcommand\@verbatimtab[1][\verbatimtabsize]{%
136 \do@verbatimtab{#1}{%
137  \@verbatim\frenchspacing\@vobeyspaces\@vobeytabs\verbatim@start}%

138 }

\do@verbatimtab Prepare a tabbing environment; #1 is the value of the tab size (generally, originally, an optional argument), #2 is the ‘startup commands’ to execute once an appropriate definition of \verbatim@processline has been established:

139 \def\do@verbatimtab#1#2{%
140 \tab@size=#1
141 \def\verbatim@processline{\tab@position\tab@size
142  \toks@{}%
143  \expandafter\verbatim@tabexpand\the\verbatim@line\@nil}%
144 #2%

145 }

\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 didn’t (originally) use fancy features of \newcommand since the definition was inside a group, and hence global. So … ‘traditional’ code to provide a command with an optional argument (which may no longer be necessary):

146 \def\verbatimtabinput{%
147 \@ifnextchar[%]
148  {\@verbatimtabinput}%
149  {\@verbatimtabinput[\verbatimtabsize]}}
150 \begingroup
151 \catcode`\~=\active \lccode`\~=`\^^M \lccode`\N=`\N
152 \lowercase{\endgroup
153 \def\@verbatimtabinput[#1]#2{\begingroup
154  \do@verbatimtab{#1}{%
155  \@verbatim\frenchspacing\@vobeyspaces\@vobeytabs}%
156  \def\verbatim@addtoline##1~{%
157  \verbatim@line\expandafter{\the\verbatim@line##1}}%
158  \openin\verbatim@in@stream=#2
159  \ifeof\verbatim@in@stream
160  \PackageWarning{moreverb}{No file #2.}
161  \else
162  \@addtofilelist{#2}%
163  \do@verbatimtabinput
164  \closein\verbatim@in@stream
165  \fi
166 \endtrivlist\endgroup\@doendpe}%

167 }

\do@verbatimtabinput Written-out (tail recursion) loop for reading the file

168 \def\do@verbatimtabinput{%
169 \read\verbatim@in@stream to \verbtab@line
170 \ifeof\verbatim@in@stream
171 \else
172  \expandafter\verbatim@addtoline\verbtab@line
173  \verbatim@processline
174  \verbatim@startline
175  \expandafter\do@verbatimtabinput
176 \fi

177 } 178 ⟨/moreverb⟩