%% \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{program} [1998/07/30 1.0 Source program environment for LaTeX] \RequirePackage{keyval} % % Style for writing programs % %\begin{program}[number,stretch=1.1] % even if you do not have options better put [] (but in Latex's \newcommand) % Options: % number[=true] - numbers all the lines with \prognumstyle % firstline=xxx - sets the first line number % numberevery[=1]- put a number every n lines (first is always numbered) % box[=true] - puts the whole program in a minipage % valign[=t] - the valign to be passed to minipage % width=xxx - the width to be passed to minipage % style=xxx - the default style of text in env. Can be "math" or "tt" % Or, redefine \Programstyle{#1}{#2} so that #1 is the % style start and #2 is the style end % stretch=xxx - factor to stretch the distance between lines % % line breaks are verbatim. Put % to prevent a newline % !foo! writes foo with \formatname{foo}. Default \tt % |bar| writes bar with \formatvariable{bar}. Default \mathit % @foo@ writes foo with \formattext. Default \mbox % \tab idents future lines here % \stab{dim} puts a \tab forward of this location and backs up % \qtab = \quad\tab % \untab undoes the last undone \tab % \rjust{txt} puts txt right justified % \rcomment{txt} like \rjust but with \formatcomment{txt}. Default \mbox % \lab{txt} puts a label leftjustified with \formatlabel{txt} % \labspace{txt} use on first line to create indentation that clears labels % \nonumber omits the line number in this line. The line number is not % incremented % \donumber makes sure a line number is emitted % \bumpnumber{5} increments the line number by 5. Visible on current line % % This environment is built on top of Latex tabbing environment. As such the % tabbing commands work here as well. However, some tabbing commands will % interfere with the program environment. The command that you can use are: % \> advance to the next tab %\end{program} % % Define the options % % Define a boolean key with a default value if used without = \def\Prog@defboolkey#1[#2]{% \expandafter\newif\csname ifProg@#1\endcsname % Define the if \define@key{Prog}{#1}[#2]{\csname Prog@#1##1\endcsname}} \def\Prog@defvalkey#1[#2]{% \define@key{Prog}{#1}[#2]{\expandafter\def\csname Prog@#1\endcsname{##1}}} \def\Prog@defvalkeynodef#1{% \define@key{Prog}{#1}{\expandafter\def\csname Prog@#1\endcsname{##1}}} \Prog@defboolkey{number}[true] % numbers lines \Prog@defboolkey{box}[true] % it puts the program in a parbox \Prog@defboolkey{style}[math] % Can be math or tt \Prog@defvalkey{valign}[t] % how to align the minipage (if in box) \Prog@defvalkey{stretch}[1.0] % Factor to stretch the distance betwee lines \Prog@defvalkeynodef{width} \Prog@defvalkeynodef{firstline} \Prog@defvalkey{numberevery}[1]% Put a line number every n lines. % Set the defaults \setkeys{Prog}{box=true,number=false,firstline=1,numberevery=1, valign=t,style=math,stretch=1.0,width=\z@} % Set the global defaults % % User parameters % \def\ProgramStyle#1#2{\def\ProgramStyleStart{#1}% \def\ProgramStyleEnd{#1}} \def\Prog@stylett{\ProgramStyle{\tt}{}} \def\Prog@stylemath{\ProgramStyle{$}{$}} \Prog@stylemath % How to print line numbers \def\prognumstyle{\scriptsize\em} % The style for printing line nos \def\formatkeyword#1{\keepspaceafter{\underbar{\bfseries #1}}} \def\formatvariable#1{\keepspaceafter{\mbox{$\mathit{#1}$}}} \def\formatcomment#1{\mbox{#1}} \def\formattext#1{\keepspaceafter{\mbox{#1}}} \def\proglabelskip{1mm} \def\formatlabel#1{#1:\hskip\proglabelskip} \def\formatname#1{\keepspaceafter{\mbox{\ttfamily #1}}} \def\tab{{}\=\+{}}% \def\stab#1{\hskip #1\tab\hskip -#1} \def\qtab{\quad\tab}% \def\untab{{}\-{}}% \def\rjust#1{\`#1} \def\rcomment#1{\`\formatcomment{#1}}% \def\lab#1{\gdef\prog@label{\formatlabel{#1}}}% \def\labref#1{\mbox{#1}} \def\labspace#1{\phantom{\formatlabel{#1}}} \def\proglabelwidth{1em} %%%%%%%%%%%%%% \newcounter{programline} \newcounter{programlineskip} \newcounter{programid}\setcounter{programid}{0} %This is for hyperref to make the line numbers %unique in a document \def\theHprogramline{\arabic{programid}.\arabic{programline}} \let\exclmark=! {% Set |...| to print the ... as a variable \catcode`\|=\active\relax \let\prog@bar=|% \gdef|#1|{\formatvariable{#1}} % % Set ; to print a thick space after it in math mode % \let\prog@semicolon=; % \catcode`\;=\active\relax % \gdef;{\ifmmode\prog@semicolon\;\else\prog@semicolon\fi} % Set !...! to print the ... as a name \catcode`\!=\active\relax \gdef!#1!{\formatname{#1}} % Set @...@ to print the ... as text \catcode`\@=\active\relax \gdef@#1@{\formattext{#1}} } % Define prog@space \def\@tmp.{\futurelet\prog@space\relax}\@tmp. \relax % Keep a space after something \def\keepspaceafter#1{\def\@tmp{#1}% \futurelet\@next\@keepspaceafteri} \def\@keepspaceafteri{\ifx\@next\prog@space \def\@tmpi{\@tmp\ }% \else \def\@tmpi{\@tmp}\fi \@tmpi} % % The next few macros override macros from the Latex tabbing environment % \def\prog@numberthisline{1}% Default is line numbering \def\prog@nonumber{\gdef\prog@numberthisline{0}} \def\prog@donumber{\gdef\prog@numberthisline{1}} \def\prog@bumpnumber#1{\addtocounter{programline}{#1}} \def\prog@startline{% \ifProg@number \refstepcounter{programline}% Increment the program line before each line \fi \prog@origstartline} \def\prog@printlineno{\ifProg@number \hskip\proglabelwidth \ifnum\prog@numberthisline=1\relax \ifnum\theprogramlineskip=0\relax \llap{\prognumstyle\theprogramline}% \setcounter{programlineskip}{\Prog@numberevery}% \fi \addtocounter{programlineskip}{-1}% \else \addtocounter{programline}{-1}% \prog@donumber \fi \fi \hskip\labelsep % Now put the current label \ifx\prog@label\empty \else \setbox\z@\hbox{\prog@label}% \copy\z@ \hskip -\wd\z@ \global\let\prog@label=\empty \fi } \def\prog@startfield{% \prog@origstartfield \ProgramStyleStart} \def\prog@stopfield{% \ProgramStyleEnd \prog@origstopfield} % A new version of @stopline which ignores blank lines (lines with % width 0pt) and prints line numbers. To print a blank line, put "\ \\" on it! % \def\prog@stopline{% \unskip\@stopfield \if@rjfield \global\@rjfieldfalse \@tempdima\@totalleftmargin \advance\@tempdima\linewidth \hbox to\@tempdima{\@itemfudge\prog@printlineno\hskip\dimen\@curtabmar \box\@curline\hfil\box\@curfield}% \else \@addfield \ifdim\wd\@curline=0pt% \ifProg@number \addtocounter{programline}{-1}\fi \else \hbox{\@itemfudge\prog@printlineno\hskip\dimen\@curtabmar\box\@curline}% \fi \fi } \newcommand\program[1][]{% \stepcounter{programid}% \bgroup % Start a group so that we can undo easily most assignments % Process the optional arguments \def\Prog@width{\z@}% \setkeys{Prog}{#1}% \ifdim\Prog@width=\z@ \edef\Prog@width{\the\linewidth}% \fi % Line numbering \ifProg@number \prog@donumber \else \prog@nonumber \fi % Whether in a box \ifProg@box \begin{minipage}[\Prog@valign]{\Prog@width}% \fi % The distance between lines \setbox\strutbox\hbox{% \vrule\@height\Prog@stretch\ht\strutbox \@depth\Prog@stretch\dp\strutbox \@width\z@}% \setcounter{programline}{\Prog@firstline}% \addtocounter{programline}{-1}% Adjust for preincrement \let\prog@label=\empty \let\prog@origbar=|% \catcode`\|=\active\relax \catcode`\!=\active\relax \catcode`\@=\active\relax % Start a tabbing environment with obey lines \let\prog@origstartline=\@startline \let\@startline=\prog@startline \let\@stopline=\prog@stopline \let\prog@origstartfield=\@startfield \let\@startfield=\prog@startfield \let\prog@origstopfield=\@stopfield \let\@stopfield=\prog@stopfield \let\nonumber=\prog@nonumber \let\donumber=\prog@donumber \let\bumpnumber=\prog@bumpnumber \obeycr% All lines after this must end with a comment \tabbing% Everything after this is local to a field % \@gobblecr } \def\endprogram{% \endtabbing% \restorecr% \ifProg@box \end{minipage}% \fi \egroup }