Make listing formatting more hookable. Add colour support, and `splitverb'
authormdw <mdw>
Fri, 5 Sep 2003 16:09:30 +0000 (16:09 +0000)
committermdw <mdw>
Fri, 5 Sep 2003 16:09:30 +0000 (16:09 +0000)
environment.

sverb.dtx

index 8e55ce0..144b2b5 100644 (file)
--- a/sverb.dtx
+++ b/sverb.dtx
@@ -1,6 +1,6 @@
 % \begin{meta-comment}
 %
-% $Id: sverb.dtx,v 1.1 2002/02/03 20:49:03 mdw Exp $
+% $Id: sverb.dtx,v 1.2 2003/09/05 16:09:30 mdw Exp $
 %
 % Verbatim typesetting done properly (ahem)
 %
@@ -9,6 +9,10 @@
 %----- Revision history -----------------------------------------------------
 %
 % $Log: sverb.dtx,v $
+% Revision 1.2  2003/09/05 16:09:30  mdw
+% Make listing formatting more hookable.  Add colour support, and `splitverb'
+% environment.
+%
 % Revision 1.1  2002/02/03 20:49:03  mdw
 % Checkin for new build system.
 %
 % \begin{meta-comment} <Package preamble>
 %<+package>\NeedsTeXFormat{LaTeX2e}
 %<+package>\ProvidesPackage{sverb}
-%<+package>                [1996/05/08 1.3 Verbatim typesetting]
+%<+package>                [2003/09/04 1.4 Verbatim typesetting]
+%<+colour>\NeedsTeXFormat{LaTeX2e}
+%<+colour>\ProvidesPackage{svcolour}
+%<+colour>                [2003/09/04 1.4 Colour support for sverb]
+%<+color>\NeedsTeXFormat{LaTeX2e}
+%<+color>\ProvidesPackage{svcolor}
+%<+color>                [2003/09/04 1.4 Fix for people who can't spell]
+%<+split>\NeedsTeXFormat{LaTeX2e}
+%<+split>\ProvidesPackage{svsplit}
+%<+split>                [2003/09/04 1.4 Verbatim, but with line breaking]
 % \end{meta-comment}
 %
-% \CheckSum{651}
+% \CheckSum{1009}
 %% \CharacterTable
 %%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
 %%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
@@ -68,6 +81,8 @@
 %<*driver>
 \input{mdwtools}
 \describespackage{sverb}
+\describespackage{svcolour}
+\describespackage{svsplit}
 \mdwdoc
 %</driver>
 %
 %
 % \subsubsection{Configuring the \env{listing} environment}
 %
+% \DescribeMacro\listingsize
 % The text size used in the \env{listing} environment is set by the
-% |\listingsize| command.  By default, this is set to |\small|, although you
-% can redefine it in the document preamble, or it can be set in the document
-% class.
+% |\listingsize| command.  By default, this is set to |\footnotesize|,
+% although you can redefine it in the document preamble, or it can be set in
+% the document class.  You can put other declarations (e.g., colours) here if
+% you like.
 %
+% \DescribeMacro\listingindent
 % The amount by which the listing text is indented is controlled by the
 % |\listingindent| length parameter.  This is a fixed length, whose default
 % value is 1\,em.
 %
+% \DescribeMacro\listinghook
+% \DescribeMacro\svafter
+% \DescribeMacro\svline
+% \DescribeMacro\svdoline
+% \DescribeEnv{listinglist}
+% The |\listinghook| command is called by the \env{listing} environment (and
+% |\verbinput| and \env{demo}) to set up the formatting of the listing.  It
+% can do any setting up it likes, and may configure |\svline| and |\svafter|
+% as necessary.  The macro |\svline| is run once for each line of verbatim
+% text, with the line gathered into a box register, the number of which is
+% given as an argument.  The macro |\svafter| is called when processing has
+% finished.
+%
+% The default setting for |\listinghook| is (similar to)
+%\begin{listing}
+%\newcommand{\listinghook}{%
+%  \par%
+%  \begin{listinglist}%
+%  \listingsize%
+%  \renewcommand{\svline}{\listingline}%
+%  \renewcommand{\svafter}{\end{listinglist}}%
+%}
+%\end{listing}
+% (see the source for the true definition).  The default |\listingline| macro
+% just writes out the line using |\svdoline|, which is a simple no-nonsense
+% macro which just writes the text.  As an example, you could say
+%\begin{listing}
+%\renewcommand{\listingline}{\leavevmode\llap{\strut\vrule\space}\svdoline}
+%\end{listing}
+% to put a rule down the left-hand side of your listings.
+%
+% The \env{listinglist} environment is a relatively straightforward
+% \env{list}-based environment which sets pu the indentation of a listing.
+% Feel free to redefine it.
+%
 % \subsubsection{Choosing a different end-text}
 %
 % \DescribeEnv{listing*}
 % As with the other environments created by this package, there's a
 % $*$-variant which takes the end-text as an argument.
 %
+% \DescribeMacro\demohook
+% The |\demohook| does the same job for \env{demo} environments as
+% |\listinghook| does for \env{listing}s.  The default version just says
+%\begin{listing}
+%\newcommand{\demohook}{\setlength{\listingindent}{0pt}\listinghook}
+%\end{listing}
+% (near enough), which turns off the indentation for the listing (which would
+% otherwise look rather odd).
+%
 %
 % \section{Programmer interface}
 %
 % |\sv@safespc| which defines the active-space character to be a normal
 % whitespace-space when expanded.
 %
+% \section{Colour support}
+%
+% There's now a little colour support in \package{sverb}.  To use it, give
+% the \textsf{colour} (or \textsf{color}) package option, or load the
+% \package{svcolour} package.
+%
+% \DescribeMacro\svcolourline
+% Say \syntax{"\\svcolourline["<model>"]{"<colour>"}{"<box>"}"} to typeset
+% \<box> against a background of the given colour.  This is a good thing to
+% put in your |\listingline| command.
+%\begin{demo}{Coloured listings}
+%\renewcommand{\listingline}
+%  {\svcolourline[rgb]{1, 0.8, 0.9}}
+%Consider, for example, this more
+%complicated program.
+%\begin{listing}
+%#include <stdio.h>
+%
+%int main(void)
+%{
+%  puts("Hello, world!");
+%  return (0);
+%}
+%\end{listing}
+%\end{demo}
+% For coloured text rather than background, put a |\color| command in
+% |\listinghook| itself.
+%
+% \section{The \package{svsplit} package}
+%
+% A new toy!
+%
+% \DescribeEnv{splitverb}
+% \DescribeEnv{splitverb*}
+% \DescribeMacro\svsplitchars
+% The \env{splitverb} environment typesets verbatim material very slowly.  On
+% the plus side, however, it does know how to do simple line-breaking.  It
+% will break lines at spaces or tabs, or after any character listed in
+% |\svsplitchars|.  Continuation lines have the same initial intentation as
+% the original.  If a line has no `good' breaking point, it's broken as late
+% as possible, and a little hyphen is inserted.
+%\begin{demo}[w]{The \env{splitverb} environment}
+%\begin{multicols}{2}
+%\begin{splitverb}
+%The \package{url} package is rather fine at splitting up long URLs such as
+%  \url{http://www.excessus.demon.co.uk/tex}
+%though it can't do its thing in the midst of verbatim text.  It
+%also doesn't cope when
+%  allthespacesinalongphrasehavemysteriouslydisappeared!
+%\end{splitverb}
+%\end{multicols}
+%\end{demo}
+%
 % \implementation
 %
 % \section{Implementation}
 %<*package>
 %    \end{macrocode}
 %
+% \subsection{Options processing}
+%
+% Notice options, load package.
+%
+%    \begin{macrocode}
+\newif\ifsv@colour\sv@colourfalse
+\DeclareOption{colour}{\sv@colourtrue}
+\DeclareOption{color}{\sv@colourtrue}
+\ProcessOptions
+%    \end{macrocode}
+%
 % \subsection{Simple things}
 %
 % To help us build funny macros which involve strange and different category
 %    \end{macrocode}
 % \end{macro}
 %
+% \begin{macro}{\sv@addtobox}
+%
+% Add stuff to a horizontal box.
+%
+%    \begin{macrocode}
+\def\sv@addtobox#1#2{\setbox#1\hbox{\unhbox#1\box#2}}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\sv@emptybox}
+%
+% Clear out a horizontal box.
+%
+%    \begin{macrocode}
+\def\sv@emptybox#1{\setbox#1\hbox{}}
+%    \end{macrocode}
+%
+% \end{macro}
+%
 % \begin{macro}{\sv@startlisting}
 %
 % This macro sets everything up nicely for a \env{listing}-type verbatim
 %
 % \begin{macro}{\sv@vtab}
 %
-% Here we handle tabs inside verbatim environments.  We expect each line to
-% be typeset as a box, using something like
-%
-% \begin{listing}
-%\setbox0\hbox{#1}
-%\leavevmode
-%\box0
-%\par
-% \end{listing}
+% Here we handle tabs inside verbatim environments.  We expect to be inside
+% |\box|~0.  This is padded to the correct width and contributed to |\box|~2;
+% |\box|~0 is then cleared and re-entered.
 %
 % The idea is that you make tab active, and set it to this macro.  We stop
 % the current box, stretch it to the right width, and start another one
-% straight after, so nobody know the difference.  The code here is straight
+% straight after, so nobody knows the difference.  The code here is straight
 % from Appendix~D of \textit{The \TeX book}.
 %
 %    \begin{macrocode}
   \multiply\@tempdima\svtab%
   \advance\@tempdima\svtab%
   \wd\z@\@tempdima%
-  \leavevmode\box\z@%
+  \sv@addtobox\tw@\z@%
   \setbox\z@\hbox\bgroup%
 }
 %    \end{macrocode}
 % isn't actually all that hard.
 %
 %    \begin{macrocode}
-\def\verbinput#1{%
-  \begin{listinglist}%
-  \listingsize%
+\def\verbinput{\listinghook\@ifstar{\verbinput@\@input}{\verbinput@\input}}
+\def\verbinput@#1#2{%  
   \sv@startlisting%
   \setbox\z@\hbox\bgroup%
-  \input{#1}%
+  #1{#2}%
   \sv@stripspc%
   \egroup%
-  \ifdim\wd\z@=\z@%
-    \ifhmode\par\fi%
-  \else%
-    \leavevmode\box\z@\par%
-  \fi%
-  \end{listinglist}%
+  \sv@addtobox\tw@\z@%
+  \ifdim\wd\tw@=\z@\listingline\tw@\fi%
+  \svafter%
 }
 %    \end{macrocode}
 %
 %    \begin{macrocode}
 \def\vinput@cr{%
   \egroup%
-  \leavevmode\box\z@%
-  \par%
+  \sv@addtobox\tw@\z@%
+  \listingline\tw@%
+  \sv@emptybox\tw@%
   \setbox\z@\hbox\bgroup%
 }
 %    \end{macrocode}
 \lccode`\>=`\}
 \lccode`\|=`\\
 \lowercase{\endgroup
-\def\sv@readenv#1{%
-  \expandafter\expandafter\expandafter%
-    #1\expandafter\sv@readenv@i\@currenvir\@@%
-}
-\def\sv@readenv@i#1\@@{{|end<#1>}{\end{#1}}}
+\def\sv@readenv#1{\expandafter\sv@readenv@i\expandafter{\@currenvir}{#1}}
+\def\sv@readenv@i#1#2{#2{|end<#1>}{\end{#1}}}
 }
 %    \end{macrocode}
 %
 %
 %    \begin{macrocode}
 \def\sv@verbline#1{%
+  \sv@emptybox\tw@%
   \setbox\z@\hbox{#1\sv@stripspc}%
-  \ifdim\wd\z@=\z@%
-    \if@matched\ifhmode\par\relax\fi\else\leavevmode\par\relax\fi%
-  \else%
-    \leavevmode\box\z@\par\relax%
+  \sv@addtobox\tw@\z@%
+  \if1\ifdim\wd\tw@=\z@\if@matched0\else1\fi\else1\fi%
+    \svline\tw@\relax%
   \fi%
 }
 %    \end{macrocode}
 % to make sure (for example) that even text which contains |\end{listing}|
 % can be typeset.
 %
+% \begin{macro}{\listinghook}
+%
+% Set everything up as required.  This is here for customization.  The
+% underlying machinery doesn't mess with this directly, but assumes that
+% |\svline| and |\svafter| are set up appropriately.
+%
+%    \begin{macrocode}
+\def\listinghook{%
+  \par%
+  \begingroup
+  \listinglist%
+  \listingsize%
+  \let\svline\listingline%
+  \def\svafter{\endlistinglist\endgroup}%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
 % \begin{macro}{\listinglist}
 % \begin{environment}{listinglist}
 %
 %
 %    \begin{macrocode}
 \ifx\listingsize\@@undefined
-  \let\listingsize\small
+  \let\listingsize\footnotesize
 \fi
 %    \end{macrocode}
 %
 % \end{environment}
 % \end{macro}
 %
+% \begin{macro}{\svline}
+% \begin{macro}{\svdoline}
+% \begin{macro}{\listingline}
+%
+% The simple spit-out-a-line macro.
+%
+%    \begin{macrocode}
+\def\svdoline#1{\leavevmode\box#1\par}
+\let\svline\svdoline
+\let\listingline\svline
+%    \end{macrocode}
+%
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\svafter}
+%
+% This is called when the machinery finishes.  A default is set for safety's
+% sake.
+%
+%    \begin{macrocode}
+\let\svafter\relax
+%    \end{macrocode}
+%
+% \end{macro}
+%
 % \begin{environment}{listing}
 %
 % The \env{listing} environment is the only real verbatim-like environment we
 % First, we must define the |\listing| command.
 %
 %    \begin{macrocode}
-\def\listing{%
-  \listinglist%
-  \listingsize%
-  \sv@readenv\sv@listing%
-}
+\def\listing{\listinghook\sv@readenv\sv@listing}
 %    \end{macrocode}
 %
 % Now we define the |\@listing| command, which does most of the work.  We
 % base the \env{listing} environment on a \env{list}.
 %
 %    \begin{macrocode}
-\def\sv@listing#1#2{%
-  \sv@startlisting%
-  \sv@read{#1}\sv@verbline{\endlistinglist#2}%
-}
+\def\sv@listing#1#2{\sv@startlisting\sv@read{#1}\sv@verbline{\svafter#2}}
 %    \end{macrocode}
 %
 % Now we define the starred version.  The command name needs to include the
 %
 %    \begin{macrocode}
 \expandafter\def\csname listing*\endcsname{%
-  \listinglist%
-  \listingsize%
-  \begingroup%
-  \@noligs%
-  \def\@tempa##1{\endgroup\sv@listing{##1}{\end{listing*}}}%
-  \@tempa%
+  \listinghook\begingroup\@noligs\listing@star%
 }
+\def\listing@star#1{\endgroup\sv@listing{#1}{\end{listing*}}}
 %    \end{macrocode}
 %
 % \end{environment}
 % user to choose the end-text.
 %
 %    \begin{macrocode}
-\def\demo{\sv@readenv\sv@demo}
-\expandafter\def\csname demo*\endcsname#1{\sv@demo{#1}{\end{demo*}}}
+\def\demo{\let\@demohook\demohook\sv@readenv\sv@demo}
+\expandafter\def\csname demo*\endcsname#1%
+  {\let\@demohook\demohook\sv@demo{#1}{\end{demo*}}}
 %    \end{macrocode}
 %
 % \end{environment}
 %
+% \begin{macro}{\demohook}
+%
+% Like |\listinghook|.  So much so that we just call it, but first ensure
+% that the indent is zero (otherwise it looks really odd!).
+%
+%    \begin{macrocode}
+\def\demohook{\listingindent\z@\listinghook}
+%    \end{macrocode}
+%
+% \end{macro}
+%
 % \begin{macro}{\sv@dodemo}
 %
 % First, let's define some common bits of code in the stuff below.  The
     \noindent\hbox{}\hskip1em%
     \sv@demosmp%
     \catcode`\%14\relax%
-    \input{\sv@demoname}%
+    \@input{\sv@demoname}%
     \sv@demoemp%
 %    \end{macrocode}
 %
 %
 %    \begin{macrocode}
     \sv@demosmp%
-    \listingindent\z@%
-    \verbinput\sv@demoname%
+    \@demohook%
+    \verbinput@\@input\sv@demoname%
     \sv@demoemp%
     \par%
     \nointerlineskip%
 %
 % \end{macro}
 %
+% \subsection{Loading the colour package}
+%
+% If requested, we load the \package{svcolour} package here.  This ensures
+% that it can patch this code if it needs to.
+%
+%    \begin{macrocode}
+\ifsv@colour
+  \RequirePackage{svcolour}
+\fi
+%    \end{macrocode}
+%
 % That's all there is.  Have fun.
 %
 %    \begin{macrocode}
 %</package>
 %    \end{macrocode}
 %
+% \subsection{The \package{svcolour} package}
+%
+% This is in a separate package to avoid dragging in the \package{color}
+% package if it's unwanted.
+%
+% I prefer English spellings.  Here's a trivial redirection for Americans.
+%
+%    \begin{macrocode}
+%<*color>
+\DeclareOption*{\PassOptionsToPackage{\CurrentOption}{svcolour}}
+\ProcessOptions
+\RequirePackage{svcolour}
+%</color>
+%    \end{macrocode}
+%
+% And now we can start the thing properly.
+%
+%    \begin{macrocode}
+%<*colour>
+\RequirePackage{color}
+%    \end{macrocode}
+%
+% \begin{macro}{\@snarfcolour}
+%
+% Reading a colour specification is something we'll need to do a few times,
+% so an abstraction is useful.  Its single argument is a continuation to
+% which we pass a colour-spec acceptable to the |\color| command.  (This is
+% the same code as found in the \package{mdwtab} package.  Remember to keep
+% them in step.)
+%
+%    \begin{macrocode}
+\def\@snarfcolour#1{%
+  \@ifnextchar[{\@snarfcolour@i{#1}}{\@snarfcolour@ii{#1}{}}%
+}
+\def\@snarfcolour@i#1[#2]{\@snarfcolour@ii{#1}{[#2]}}
+\def\@snarfcolour@ii#1#2#3{#1{#2{#3}}}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\svcolourline}
+% \begin{macro}{\svcolorline}
+%
+% Snarf the option, and plot the coloured bar.  Note the penalties which are
+% meant to stick the glue and leaders onto the colour specials.
+%
+%    \begin{macrocode}
+\def\svcolourline{\@snarfcolour\svcl@i}
+\def\svcl@i#1#2{%
+  \skip@\wd#2%
+  \advance\skip@\parfillskip%
+  \advance\skip@.2em%
+  \strut%
+  \kern.2em%
+  \begingroup\color#1\nobreak\leaders\vrule\hskip\skip@\endgroup%
+  \nobreak\hskip-\skip@%
+  \kern.2em%
+  \box#2%
+  \nobreak\hskip-\rightskip\vadjust{}%
+  \par%
+}
+\let\svcolorline\svcolourline
+%    \end{macrocode}
+%
+% \end{macro}
+% \end{macro}
+%
+% Done!
+%
+%    \begin{macrocode}
+%</colour>
+%    \end{macrocode}
+%
+% \subsection{The \package{svsplit} package}
+%
+%    \begin{macrocode}
+%<*split>
+\RequirePackage{sverb}
+%    \end{macrocode}
+%
+% \begin{environment}{splitverb}
+% \begin{environment}{splitverb*}
+%
+% The basic environments are simple enough.
+%
+%    \begin{macrocode}
+\def\splitverb{\listinghook\sv@readenv\splitverb@}
+\expandafter\def\csname splitverb*\endcsname%
+  {\listinghook\begingroup\@noligs\svsplit@star}
+\def\svsplit@star#1{\endgroup\splitverb@{#1}{\end{splitverb*}}}
+%    \end{macrocode}
+%
+% \end{environment}
+% \end{environment}
+%
+% \begin{macro}{\splitverb@}
+%
+% Even this isn't so bad, really.
+%
+%    \begin{macrocode}
+\def\splitverb@#1#2{\sv@startlisting\sv@read{#1}\svsplit@line{\svafter#2}}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\svsplit@line}
+%
+% For the sake of readability (and maybe saving a few tokens), we define some
+% synonyms for \TeX's scratch registers.  |\svsplit@remain| will be a
+% |\global| register containing the remaining horizontal space on the line;
+% |\svsplit@indent| is a local register containing the amount of initial
+% whitespace on the line.
+%
+%    \begin{macrocode}
+\dimendef\svsplit@remain=1 
+\dimendef\svsplit@indent=2
+%    \end{macrocode}
+%
+% The switch |\svsplit@| is set if we've found a good place to split the
+% current line.
+%
+%    \begin{macrocode}
+\newif\ifsvsplit@
+%    \end{macrocode}
+%
+% And finally a delimiter.  This is the same one I use everywhere else.
+%
+%    \begin{macrocode}
+\def\q@delim{\q@delim}
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\begingroup
+\catcode`\~=\active \lccode`\~=32
+\catcode`\!=\active \lccode`\!=9
+\lowercase{\endgroup
+%    \end{macrocode}
+%
+% So far, so good.  The |\svsplit@line| macro is given a line of text.  We
+% initialize |\svtab| to be a \emph{single} space, |\svsplit@remain| to be
+% the text width, and |\svsplit@indent| to zero.  Then we embark on the first
+% loop, which attempts to find the width of the leading whitespace.
+%
+%    \begin{macrocode}
+\def\svsplit@line#1{%
+  \divide\svtab8%
+  \global\svsplit@remain\linewidth%
+  \svsplit@indent\z@%
+  \sv@emptybox\tw@%
+  \let\next@\svsplit@findindent%
+  \next@#1\q@delim%
+}
+%    \end{macrocode}
+%
+% A straightforward tail-recursive loop finds out how much whitespace there
+% is at the start of the current line.  Note that |\next@| is already set up
+% for the optimized case of continuing the loop.  Also, if we reach the end
+% then this is a blank line, so only emit something if we didn't see the
+% end-marker.  This is the only place we need to check for this.
+%
+%    \begin{macrocode}
+\def\svsplit@findindent#1{%
+  \ifx~#1%
+    \advance\svsplit@indent\svtab%
+  \else\ifx!#1%
+    \dimen@8\svtab%
+    \divide\svsplit@indent\dimen@%
+    \multiply\svsplit@indent\dimen@%
+    \advance\svsplit@indent\dimen@%
+  \else\ifx\q@delim#1%
+    \if@matched\else\svline\tw@\fi%
+    \let\next@\relax%
+  \else%
+    \def\next@{\svsplit@scanline{#1}}%
+  \fi\fi\fi%
+  \next@%
+}
+%    \end{macrocode}
+%
+% Now we have to actually scan the line to find breakpoints.  We build the
+% current unbreakable chunk in |\box|~0.  When we find a breakpoint, we close
+% the box, maybe stretch it to take into account trailing space, and attach
+% it to |\box|~2, which is gathering the current line.  If |\svsplit@remain|
+% hits zero then we flush |\box|~2 to the output and continue on the next
+% line with a (more-or-less) clean slate.
+%
+% If there's no breakpoint then we're hosed.  In that case, we just insert a
+% (|\normalfont|) hyphen and eject what we've got.
+%
+% Note that this assumes that the indentation will fit.  If not, then we're
+% deeply stuffed.
+%
+%    \begin{macrocode}
+\def\svsplit@scanline{%
+  \svsplit@false%
+  \let\next@\svsplit@char%
+  \setbox\z@\hbox\bgroup%
+    \kern\svsplit@indent%
+    \global\advance\svsplit@remain-\svsplit@indent%
+    \next@%
+}
+%    \end{macrocode}
+%
+% Scanning a character isn't so bad, if we take it a step at a time.
+%
+%    \begin{macrocode}
+\def\svsplit@char#1{%
+%    \end{macrocode}
+%
+% If the character is a space or a tab, then we call |\svsplit@space| which
+% knows about adding breakable whitespace.  For tabs, this involves computing
+% the correct tab size.
+%
+%    \begin{macrocode}
+    \ifx~#1%
+      \svsplit@space\svtab%
+    \else\ifx!#1%
+      \@tempdima\linewidth%
+      \advance\@tempdima-\svsplit@remain%
+      \@tempdimb\@tempdima%
+      \dimen@8\svtab%
+      \divide\@tempdimb\dimen@%
+      \multiply\@tempdimb\dimen@%
+      \advance\@tempdimb\dimen@%
+      \advance\@tempdimb-\@tempdima%
+      \svsplit@space\@tempdimb%
+%    \end{macrocode}
+%
+% We might have reached the end of the line.  If so, then we finish off.
+%
+%    \begin{macrocode}
+    \else\ifx\q@delim#1%
+      \let\next@\svsplit@done%
+%    \end{macrocode}
+%
+% Otherwise it's a normal character.  If there's not enough space then force
+% a break.  
+%
+%    \begin{macrocode}
+    \else%
+      \ifdim\svsplit@remain<2\svtab%
+        \ifsvsplit@\else\normalfont-\svsplit@break\fi%
+        \svsplit@eject%
+      \fi%
+%    \end{macrocode}
+%
+% Insert the character and decrement the distance-left register.
+%
+%    \begin{macrocode}
+      #1%
+      \global\advance\svsplit@remain-\svtab%
+%    \end{macrocode}
+%
+% Now we see if it's a breakable-after character and if so mark it as being
+% breakable.
+%
+%    \begin{macrocode}
+      \def\temp@##1#1##2\q@delim%
+        {\ifx\q@delim##2\q@delim\else\svsplit@break\fi}%
+      \expandafter\temp@\svsplitchars#1\q@delim%
+%    \end{macrocode}
+%
+% And with that, we're done.
+%
+%    \begin{macrocode}
+    \fi\fi\fi%
+    \next@%
+}
+%    \end{macrocode}
+%
+% Our next macro is the break-insertion subroutine, which is quite easy.
+%
+%    \begin{macrocode}
+\def\svsplit@break{%
+  \egroup%
+  \sv@addtobox\tw@\z@%
+  \svsplit@true%
+  \setbox\z@\hbox\bgroup%
+}
+%    \end{macrocode}
+%
+% Now we add space to the current box.  The argument is a dimen register.
+%
+%    \begin{macrocode}
+\def\svsplit@space#1{%
+    \ifdim\svsplit@remain>#1\kern#1\global\advance\svsplit@remain-#1\fi%
+    \svsplit@break%
+    \ifdim\svsplit@remain>#1\else\svsplit@eject\fi%
+}
+%    \end{macrocode}
+%
+% We now come to a slightly involved piece of code, which is how to flush out
+% a line, and then fix up the registers for the next line correctly.
+%
+%    \begin{macrocode}
+\def\svsplit@eject{%
+  \egroup%
+  \svline\tw@%
+  \sv@emptybox\tw@%
+  \svsplit@false%
+  \setbox\z@\hbox\bgroup%
+    \kern\svsplit@indent%
+    \global\svsplit@remain\linewidth%
+    \global\advance\svsplit@remain-\svsplit@indent%
+    \global\advance\svsplit@remain-\wd\z@%
+    \unhbox\z@%
+}
+%    \end{macrocode}
+%
+% Finally, how to finish the line and go home.
+%
+%    \begin{macrocode}
+\def\svsplit@done{%
+  \egroup%
+  \sv@addtobox\tw@\z@%
+  \svline\tw@%
+}
+%    \end{macrocode}
+%
+% End the |\lowercase| hack.
+%
+%    \begin{macrocode}
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% Finally, set the breakable characters to something plausible.
+%
+%    \begin{macrocode}
+\def\svsplitchars{:/.}
+%    \end{macrocode}
+%
+% And with that, we're done!
+%
+%    \begin{macrocode}
+%</split>
+%    \end{macrocode}
+%
 % \hfill Mark Wooding, \today
 %
 % \Finale