|
@@ -1,4159 +1,7107 @@
|
|
|
% \iffalse
|
|
|
+%
|
|
|
+% NOTE: This file contains very long lines (upto approx 270 characters).
|
|
|
+% I haven't wrapped them since I won't do that by hand and haven't
|
|
|
+% written any program doing the work.
|
|
|
+%
|
|
|
+% If you want to read this .dtx file, you might get in trouble with
|
|
|
+% such long lines!
|
|
|
+%
|
|
|
+%
|
|
|
+% S O F T W A R E L I C E N S E
|
|
|
+% =================================
|
|
|
+%
|
|
|
+% The files listings.dtx and listings.ins and all files generated
|
|
|
+% from only these two files are referred as 'the listings package' or
|
|
|
+% simply 'the package'. A driver file is any file generated mainly from
|
|
|
+% lstdrvrs.dtx.
|
|
|
+%
|
|
|
+% Copyright.
|
|
|
+% The listings package is copyright 1996--1998 Carsten Heinz.
|
|
|
+% The driver files are copyright 1997, 1998 or 1997--1998 any
|
|
|
+% individual author listed in these files.
|
|
|
+%
|
|
|
+% Distribution.
|
|
|
+% The listings package as well as lstdrvrs.dtx and all driver files
|
|
|
+% are distributed freely. You are not allowed to take money for the
|
|
|
+% distribution, except for a nominal charge for copying etc..
|
|
|
+%
|
|
|
+% Use of the package.
|
|
|
+% The listings package is free for any non-commercial use. Commercial
|
|
|
+% use needs (i) explicit permission of the author of this package and
|
|
|
+% (ii) the payment of a license fee. This fee is to be determined in
|
|
|
+% each instance by the commercial user and the package author and is
|
|
|
+% to be payed as donation to the LaTeX3 project.
|
|
|
+%
|
|
|
+% No warranty.
|
|
|
+% The listings package as well as lstdrvrs.dtx and all driver files
|
|
|
+% are distributed without any warranty, express or implied, as to
|
|
|
+% merchantability or fitness for any particular purpose.
|
|
|
+%
|
|
|
+% Modification advice.
|
|
|
+% Permission is granted to change the listings package as well as
|
|
|
+% lstdrvrs.dtx. You are not allowed to distribute any changed version
|
|
|
+% of the package or any changed version of lstdrvrs.dtx, neither under
|
|
|
+% the same name nor under a different one. Tell the author of the
|
|
|
+% package about your local changes: other users will welcome removed
|
|
|
+% bugs, new features and additional programming languages.
|
|
|
+%
|
|
|
+% Contacts.
|
|
|
+% Send comments and ideas on the package, error reports and additional
|
|
|
+% programming languages to
|
|
|
+%
|
|
|
+% Carsten Heinz
|
|
|
+% Tellweg 6
|
|
|
+% 42275 Wuppertal
|
|
|
+% Germany
|
|
|
+%
|
|
|
+% or preferably to
|
|
|
+%
|
|
|
+% [email protected]
|
|
|
+%
|
|
|
+% Trademarks
|
|
|
+% appear throughout this documentation without any trademark symbol,
|
|
|
+% so you can't assume that a name is free. There is no intention of
|
|
|
+% infringement; the usage is to the benefit of the trademark owner.
|
|
|
+%
|
|
|
+% end of software license
|
|
|
+%
|
|
|
%<*driver>
|
|
|
\documentclass{ltxdoc}
|
|
|
|
|
|
-\usepackage{listings}[1997/09/29]
|
|
|
-\selectlisting{cpp}
|
|
|
-\selectlisting{fortran}
|
|
|
-\selectlisting{pascal}
|
|
|
+\usepackage[doc]{listings}[1998/11/09]
|
|
|
+\newif\iffancyvrb
|
|
|
+\IfFileExists{fancyvrb.sty}
|
|
|
+ {\fancyvrbtrue \usepackage{fancyvrb}}
|
|
|
+ {\fancyvrbfalse}
|
|
|
|
|
|
\EnableCrossrefs
|
|
|
\CodelineIndex
|
|
|
-\OldMakeindex % used for MakeIndex pre v2.9
|
|
|
+\OldMakeindex
|
|
|
+\OnlyDescription
|
|
|
|
|
|
\begin{document}
|
|
|
\DocInput{listings.dtx}
|
|
|
\end{document}
|
|
|
%</driver>
|
|
|
-%
|
|
|
-% listings package for LaTeX2e
|
|
|
-% (w)(c) 1996-1997 Carsten Heinz, all rights reserved.
|
|
|
-%
|
|
|
-%<+package>\NeedsTeXFormat{LaTeX2e}
|
|
|
-%<+package>\ProvidesPackage{listings}[1997/09/29 v0.17 by Carsten Heinz]
|
|
|
+% \fi ^^A balance the \iffancyvrb! :-)
|
|
|
% \fi
|
|
|
%
|
|
|
-% \CheckSum{2784}
|
|
|
-% \DoNotIndex{\@ifundefined,\@tempa,\ ,\@dottedtocline,\@empty,\@ne}
|
|
|
-% \DoNotIndex{\if@twocolumn,\if@restonecol,\@mkboth,\@restonecoltrue}
|
|
|
-% \DoNotIndex{\@restonecolfalse,\@starttoc,\z@}
|
|
|
-% \DoNotIndex{\[,\{,\},\],\1,\2,\3,\4,\5,\6,\7,\8,\9,\0}
|
|
|
-% \DoNotIndex{\`,\,,\!,\#,\$,\&,\',\(,\),\+,\.,\:,\;,\<,\=,\>,\?,\_}
|
|
|
-% \DoNotIndex{\active,\addtocontents,\advance,\begin,\backslash}
|
|
|
-% \DoNotIndex{\baselineskip,\begingroup,\bfseries,\bgroup,\catcode}
|
|
|
-% \DoNotIndex{\chapter,\chardef,\closein,\csname,\def,\divide,\do}
|
|
|
-% \DoNotIndex{\edef,\egroup,\else,\@empty,\end,\endcsname,\endgroup}
|
|
|
-% \DoNotIndex{\expandafter,\fi,\gdef,\global,\hbox,\hskip,\hss,\if}
|
|
|
-% \DoNotIndex{\ifcat,\ifdim,\ifeof,\iffalse,\ifnum,\iftrue,\ifx}
|
|
|
-% \DoNotIndex{\ignorespaces,\input,\itshape,\lccode,\let,\llap,\long}
|
|
|
-% \DoNotIndex{\loop,\lst@,\makeatletter,\makeatother,\MakeUppercase}
|
|
|
-% \DoNotIndex{\message,\multiply,\newcommand,\newenvironment,\newcount}
|
|
|
-% \DoNotIndex{\newdimen,\newif,\newread,\next,\noindent,\onecolumn}
|
|
|
-% \DoNotIndex{\openin,\par,\parshape,\parskip,\protect,\read,\relax}
|
|
|
-% \DoNotIndex{\removelastskip,\repeat,\section,\setbox,\space}
|
|
|
-% \DoNotIndex{\smallbreak,\string,\textwidth,\the,\thepage,\ttfamily}
|
|
|
-% \DoNotIndex{\twocolumn,\undefined,\vskip,\vspace}
|
|
|
-%
|
|
|
-%
|
|
|
-% \title{{LISTINGS.DTX} Version {0.17}}
|
|
|
-% \author{{\copyright} 1996--1997 by Carsten Heinz}
|
|
|
-% \date{}
|
|
|
+%
|
|
|
+% \makeatletter
|
|
|
+%^^A
|
|
|
+%^^A A modified `environment' environment
|
|
|
+%^^A
|
|
|
+%\def\aspect{^^A
|
|
|
+% \def\SpecialMainEnvIndex##1{^^A
|
|
|
+% \@bsphack ^^A
|
|
|
+% \index{aspects:\levelchar{\protect\ttfamily##1}\encapchar main}^^A
|
|
|
+% \@esphack}^^A
|
|
|
+% \begingroup \catcode`\\12 \MakePrivateLetters ^^A
|
|
|
+% \m@cro@ \iffalse}
|
|
|
+%\let\endaspect\endmacro
|
|
|
+%
|
|
|
+%^^A
|
|
|
+%^^A We define a sample environment. All material between
|
|
|
+%^^A \begin{lstsample} and \end{lstsample} is executed
|
|
|
+%^^A 'on the left side' and typeset verbatim on the right.
|
|
|
+%^^A
|
|
|
+%^^A The environment is *not* designed for purposes other than
|
|
|
+%^^A this documentation.
|
|
|
+% \lst@Environment{lstsample}[1]\is
|
|
|
+% {\gdef\lst@sample{#1}^^A
|
|
|
+% \lst@BeginWriteFile{listings.tmp}^^A
|
|
|
+% \def\lst@BOLGobble##1{}}^^A to gobble each first %
|
|
|
+% {\lst@EndWriteFile ^^A
|
|
|
+%^^A We execute the code resp. typset it verbatim (= empty language
|
|
|
+%^^A with \ttfamily).
|
|
|
+% \begin{center}
|
|
|
+% \small ^^A \lstCC@Let{`\^^M}\space ^^A
|
|
|
+% \begin{minipage}{0.45\linewidth}^^A
|
|
|
+% \MakePercentComment\lst@sample
|
|
|
+% \input{listings.tmp}\MakePercentIgnore^^A
|
|
|
+% \end{minipage}
|
|
|
+% \qquad
|
|
|
+% \begin{minipage}{0.45\linewidth}
|
|
|
+% \lstset{language={},style={},basicstyle=\ttfamily,baseem=0.51}^^A
|
|
|
+% \hbox to \linewidth{\lstbox\lstinputlisting{listings.tmp}\hss}
|
|
|
+% \end{minipage}
|
|
|
+% \end{center}}
|
|
|
+%
|
|
|
+%^^A
|
|
|
+%^^A We redefine the appearance of part, section, ...
|
|
|
+%^^A
|
|
|
+%\def\@part[#1]#2{\addcontentsline{toc}{part}{#1}%
|
|
|
+% {\parindent\z@ \raggedright \interlinepenalty\@M
|
|
|
+% \normalfont \huge \bfseries #2\markboth{}{}\par}%
|
|
|
+% \nobreak\vskip 3ex\@afterheading}
|
|
|
+%\renewcommand*\l@section[2]{%
|
|
|
+% \ifnum \c@tocdepth >\z@
|
|
|
+% \addpenalty\@secpenalty
|
|
|
+% \addvspace{.25em \@plus\p@}%
|
|
|
+% \setlength\@tempdima{1.5em}%
|
|
|
+% \begingroup
|
|
|
+% \parindent \z@ \rightskip \@pnumwidth
|
|
|
+% \parfillskip -\@pnumwidth
|
|
|
+% \leavevmode ^^A \bfseries
|
|
|
+% \advance\leftskip\@tempdima
|
|
|
+% \hskip -\leftskip
|
|
|
+% #1\nobreak\hfil \nobreak\hb@xt@\@pnumwidth{\hss #2}\par
|
|
|
+% \endgroup
|
|
|
+% \fi}
|
|
|
+%\renewcommand*\l@subsection{\@dottedtocline{2}{1.5em}{2.3em}}
|
|
|
+%\renewcommand*\l@subsubsection{\@dottedtocline{3}{3.8em}{3.2em}}
|
|
|
+%\renewcommand\paragraph{\@startsection{paragraph}{4}{\z@}%
|
|
|
+% {1.25ex \@plus1ex \@minus.2ex}%
|
|
|
+% {-1em}%
|
|
|
+% {\normalfont\normalsize\bfseries}}
|
|
|
+%
|
|
|
+%^^A
|
|
|
+%^^A Suppress warning
|
|
|
+%^^A
|
|
|
+% \let\lstenv@DroppedWarning\relax
|
|
|
+% \makeatother
|
|
|
+%
|
|
|
+%^^A
|
|
|
+%^^A The following definitions come in handy soon.
|
|
|
+%^^A There will be more in future.
|
|
|
+%^^A
|
|
|
+% \newcommand\lsthelper[4]{#1\ifx\empty#2\empty\typeout{^^JWarning: #1 has unknown email^^J}\else\space\texttt{<#2>}{}\fi}
|
|
|
+% \newcommand\lstthanks[2]{#1\ifx\empty#2\empty\typeout{^^JWarning: #1 has unknown email^^J}\fi}
|
|
|
+% \newcommand\lst{\texttt{lst}}
|
|
|
+% \lstdefinelanguage[doc]{Pascal}{^^A
|
|
|
+% keywords={alfa,and,array,begin,boolean,byte,case,char,const,div,^^A
|
|
|
+% do,downto,else,end,false,file,for,function,get,goto,if,in,^^A
|
|
|
+% integer,label,maxint,mod,new,not,of,or,pack,packed,page,program,^^A
|
|
|
+% procedure,put,read,readln,real,record,repeat,reset,rewrite,set,^^A
|
|
|
+% text,then,to,true,type,unpack,until,var,while,with,write,writeln},^^A
|
|
|
+% sensitive=false,^^A
|
|
|
+% doublecomment={(*}{*)}{\{}{\}},^^A
|
|
|
+% stringizer=[d]{'}}^^A
|
|
|
+% \lstset{defaultdialect=[doc]Pascal}
|
|
|
+% \lstset{language=Pascal}
|
|
|
+%
|
|
|
+%
|
|
|
+%^^A
|
|
|
+%^^A The long awaited beginning of documentation
|
|
|
+%^^A
|
|
|
+% \newbox\abstractbox
|
|
|
+% \setbox\abstractbox=\vbox{
|
|
|
+% \begin{abstract}
|
|
|
+% Listings.dtx is a source code printer for \LaTeX\ --- which always means \LaTeXe\ in this documentation.
|
|
|
+% You can typeset stand alone files as well as enter listings using an environment similar to \texttt{verbatim} as well as you can print fragments using a command similar to |\verb|.
|
|
|
+%^^A Since listings.dtx is a package and not a cross compiler, all listings are up to date without maintaining differences between (changed) source files and cross compiled files.
|
|
|
+% The package supports a wide spectrum of programming languages --- some come already with \texttt{lstdrvrs.dtx}.
|
|
|
+% Finally: Many parameters control the output.
|
|
|
+% \end{abstract}}
|
|
|
+%
|
|
|
+% \title{{Listings.dtx} Version {0.19}}
|
|
|
+% \author{Copyright 1996--1998 Carsten Heinz}
|
|
|
+% \date{\box\abstractbox}
|
|
|
%
|
|
|
% \makeatletter\@twocolumntrue\makeatother
|
|
|
% \maketitle
|
|
|
-% \tableofcontents
|
|
|
+% {\makeatletter\@starttoc{toc}}
|
|
|
+%\iftrue
|
|
|
% \vfill
|
|
|
-% \noindent \textbf{\uppercase{incompatible changes}}
|
|
|
-% have been made from version 0.16 to version 0.17. The commands
|
|
|
-% \cs{blanklisting}, \cs{clisting}, {\ldots} have been removed.
|
|
|
-% Languages are selected with the command \cs{selectlisting}.
|
|
|
-% The command \cs{labelstyle} has a new syntax and semantics.
|
|
|
-% These features are described on page \pageref{ssSelecting} and
|
|
|
-% \pageref{newlabelstyle}, respectively.
|
|
|
-% Sorry, but now it's possible to add languages without changing
|
|
|
-% the kernel \texttt{listings.sty}.
|
|
|
+% \noindent \textbf{Again incompatibilities!}
|
|
|
+% And there are certainly teething troubles since the complete kernel has been rewritten.
|
|
|
+% So read this manual with care.
|
|
|
+%\fi
|
|
|
% \onecolumn
|
|
|
%
|
|
|
%
|
|
|
-% \section{User's guide}
|
|
|
-%
|
|
|
-%
|
|
|
-% \subsection{Introduction}
|
|
|
+% \part{User's guide}
|
|
|
+%
|
|
|
+%
|
|
|
+% \section{Preface}
|
|
|
+%
|
|
|
+% The files \texttt{listings.dtx} and \texttt{listings.ins} and all files generated from only these two files are referred as 'the \textsf{listings} package' or simply 'the package'.
|
|
|
+% A driver file is any file generated mainly from \texttt{lstdrvrs.dtx}.
|
|
|
+%
|
|
|
+% \paragraph{Alternatives.}
|
|
|
+% The \textsf{listings} package is certainly not the final utility for typesetting source code listings.
|
|
|
+% Other programs do their jobs very well if you are not satiesfied with \textsf{listings}.
|
|
|
+% I should mention \textsf{a2ps} and the \textsf{LGrind} package.
|
|
|
+% Let me know if you're using none of these solutions; I'd like to extend my suggestions.
|
|
|
+%
|
|
|
+% \paragraph{Reading this manual.}
|
|
|
+% In any case you should read section ''\emph{\ref{uGettingStarted}. Getting started}'' step by step.
|
|
|
+% You either start from the scratch there or you get in touch with the new user interface and other changes.
|
|
|
+% That section is an introduction and doesn't cover all of the \textsf{listings} package, but the most common.
|
|
|
+% After reading it you are prepared for the main reference if you need more details, more control or more features.
|
|
|
+%
|
|
|
+% \paragraph{Sorry!}
|
|
|
+% On 1998/11/02 I decided to make major changes to the user interface, which were planned for version 0.2.
|
|
|
+% But it's better to get the interface stable as soon as possible.
|
|
|
+% In particular I must say sorry to all people I posted a pre-version of \textsf{listings} 0.19.
|
|
|
+%
|
|
|
+% \paragraph{Thanks.}
|
|
|
+% There are many people I have to thank for fruitful communication, posting their ideas, giving error reports (first bug finder is listed), adding programming languages to \texttt{lstdrvrs.dtx}, etc..
|
|
|
+% If you want to know that in detail, search for the names in the implementation part.
|
|
|
+%^^A
|
|
|
+%^^A Thanks for error reports (first bug finder only), new programming languages, etc.
|
|
|
+%^^A Special thanks for communication which lead to kernel extensions.
|
|
|
+%^^A
|
|
|
+% Special thanks go to (alphabetical order)
|
|
|
+% \begin{quote}
|
|
|
+% \hyphenpenalty=10000\relax \rightskip=0pt plus \linewidth\relax
|
|
|
+% \lstthanks{Andreas~Bartelt}{[email protected]},
|
|
|
+% \lstthanks{Jan~Braun}{[email protected]},
|
|
|
+% \lstthanks{Denis~Girou}{[email protected]},
|
|
|
+% \lstthanks{Arne~John~Glenstrup}{[email protected]},
|
|
|
+% \lstthanks{Rolf~Niepraschk}{[email protected]},
|
|
|
+% \lstthanks{Rui~Oliveira}{[email protected]} and
|
|
|
+% \lstthanks{Boris~Veytsman}{[email protected]}.
|
|
|
+% \end{quote}
|
|
|
+% Moreover I wish to thank
|
|
|
+% \begin{quote}
|
|
|
+% \hyphenpenalty=10000\relax \rightskip=0pt plus \linewidth\relax
|
|
|
+% \lstthanks{Bj{\o}rn~{\AA}dlandsvik}{[email protected]},
|
|
|
+% \lstthanks{Gaurav~Aggarwal}{[email protected]},
|
|
|
+% \lstthanks{Kai~Below}{[email protected]},
|
|
|
+% \lstthanks{Detlev~Dr\"oge}{[email protected]},
|
|
|
+% \lstthanks{Anders~Edenbrandt}{[email protected]},
|
|
|
+% \lstthanks{Harald~Harders}{[email protected]},
|
|
|
+% \lstthanks{Christian~Haul}{[email protected]},
|
|
|
+% \lstthanks{J\"urgen~Heim}{[email protected]},
|
|
|
+% \lstthanks{Dr.~Jobst~Hoffmann}{[email protected]},
|
|
|
+% \lstthanks{Knut~M\"uller}{[email protected]},
|
|
|
+% \lstthanks{Zvezdan~V.~Petkovic}{[email protected]},
|
|
|
+% \lstthanks{Michael~Piotrowski}{[email protected]},
|
|
|
+% \lstthanks{Ralf~Quast}{[email protected]},
|
|
|
+% \lstthanks{Aslak~Raanes}{[email protected]},
|
|
|
+% \lstthanks{Detlef~Reimers}{[email protected]},
|
|
|
+% \lstthanks{Magne~Rudshaug}{[email protected]},
|
|
|
+% \lstthanks{Andreas~Stephan}{[email protected]},
|
|
|
+% \lstthanks{Dominique~de~Waleffe}{[email protected]},
|
|
|
+% \lstthanks{Herbert~Weinhandl}{[email protected]},
|
|
|
+% \lstthanks{J\"orn~Wilms}{[email protected]} and
|
|
|
+% \lstthanks{Kai~Wollenweber}{[email protected]}.
|
|
|
+% \end{quote}
|
|
|
+%
|
|
|
+%^^A \lsthelper{Andreas Bartelt}{[email protected]}{1997/09/11}{single line comes out using \inputlisting inside \fbox}
|
|
|
+%^^A \lsthelper{Michael Piotrowski}{[email protected]}{1997/11/04}{! Use of \lstdrv@perl@TestCommentCut doesn't match its definition^^J\lst@line ->I^^JRF::LangID -- Statistical identification of language for IRF/1^^J^^J(POD ist Zeile '=irgendwas' bis Zeile '=cut')}
|
|
|
+%^^A \lsthelper{Bj{\o}rn {\AA}dlandsvik}{[email protected]}{1997/10/27}{listings.sty is incompatible to inputenc.sty}
|
|
|
+%
|
|
|
+%
|
|
|
+% \section{Software license}
|
|
|
+%
|
|
|
+% \paragraph{Copyright.}
|
|
|
+% The \textsf{listings} package is copyright 1996--1998 Carsten Heinz.
|
|
|
+% The driver files are copyright 1997, 1998 or 1997--1998 any individual author listed in these files.
|
|
|
+%
|
|
|
+% \paragraph{Distribution.}
|
|
|
+% The \textsf{listings} package as well as \texttt{lstdrvrs.dtx} and all driver files are distributed freely.
|
|
|
+% You are not allowed to take money for the distribution, except for a nominal charge for copying etc..
|
|
|
+%
|
|
|
+% \paragraph{Use of the package.}
|
|
|
+% The \textsf{listings} package is free for any non-commercial use.
|
|
|
+% Commercial use needs (i) explicit permission of the author of this package and (ii) the payment of a license fee.
|
|
|
+% This fee is to be determined in each instance by the commercial user and the package author and is to be payed as donation to the \LaTeX3 project.
|
|
|
+%
|
|
|
+% \paragraph{No warranty.}
|
|
|
+% The \textsf{listings} package as well as \texttt{lstdrvrs.dtx} and all driver files are distributed without any warranty, express or implied, as to merchantability or fitness for any particular purpose.
|
|
|
+%
|
|
|
+% \paragraph{Modification advice.}
|
|
|
+% Permission is granted to change the \textsf{listings} package as well as \texttt{lstdrvrs.dtx}.
|
|
|
+% You are not allowed to distribute any changed version of the package or any changed version of \texttt{lstdrvrs.dtx}, neither under the same name nor under a different one.
|
|
|
+% Tell the author of the package about your local changes: other users will welcome removed bugs, new features and additional programming languages.
|
|
|
+%
|
|
|
+% \paragraph{Contacts.}
|
|
|
+% Send comments and ideas on the package, error reports and additional programming languages to \emph{Carsten Heinz, Tellweg 6, 42275 Wuppertal, Germany} or preferably to \texttt{[email protected]}.
|
|
|
+%
|
|
|
+% \paragraph{Trademarks}
|
|
|
+% appear throughout this documentation without any trademark symbol, so you can't assume that a name is free.
|
|
|
+% There is no intention of infringement; the usage is to the benefit of the trademark owner.
|
|
|
+%
|
|
|
+%
|
|
|
+% \section{Getting started}\label{uGettingStarted}
|
|
|
+%
|
|
|
%
|
|
|
-% You have a problem? You wanna typeset source code of a programming
|
|
|
-% language within \LaTeXe{} like
|
|
|
-% \selectlisting{cpp}
|
|
|
-% \iffalse
|
|
|
-%<*sample>
|
|
|
-% \fi
|
|
|
-% \begin{listing}
|
|
|
- switch (direction)
|
|
|
- {// choose direction
|
|
|
- case backward : { ... break; }
|
|
|
- case backwarddown : { ... break; }
|
|
|
- case up : { ... break; }
|
|
|
- }
|
|
|
-
|
|
|
- for (int i=0; i<1000; i++)
|
|
|
- {// do something
|
|
|
- if (i == i) { i += 1; i--; }
|
|
|
- }
|
|
|
-% \end{listing}
|
|
|
-% \iffalse
|
|
|
-%</sample>
|
|
|
-% \fi
|
|
|
-% \noindent or
|
|
|
-% \labelstyle{\small\ttfamily}
|
|
|
-% \selectlisting{pascal}
|
|
|
-% \iffalse
|
|
|
-%<*sample>
|
|
|
-% \fi
|
|
|
-% \begin{listing}
|
|
|
- for i:=maxint downto 0 do
|
|
|
- begin
|
|
|
- { do nothing }
|
|
|
- end;
|
|
|
-
|
|
|
- WriteLn('Pascal keywords are');
|
|
|
- writeln('not case sensitive.');
|
|
|
-% \end{listing}
|
|
|
% \iffalse
|
|
|
-%</sample>
|
|
|
+% \subsection{Installation}
|
|
|
+%
|
|
|
+% \begin{enumerate}
|
|
|
+% \item You need \texttt{listings.dtx} and \texttt{listings.ins} to install the \textsf{listings} package.
|
|
|
+% \texttt{lstdrvrs.dtx} contains some language drivers.
|
|
|
+% Move \texttt{.dtx} and \texttt{.ins} files into a separate folder if you want to.
|
|
|
+% \item Remove all \texttt{lst???.sty} files if you update from an earlier version.
|
|
|
+% \item Run \texttt{listings.ins} through \TeX.
|
|
|
+% This creates the kernel \texttt{listings.sty} and two interface files \texttt{lst017.sty} and \texttt{lstfvrb.sty}.
|
|
|
+% If you have \texttt{lstdrvrs.dtx}, a configuration file \texttt{listings.cfg} and a couple of driver files are also generated.
|
|
|
+% \item Copy all created \texttt{.sty} and \texttt{.cfg} files to a directory searched by \TeX.
|
|
|
+% \end{enumerate}
|
|
|
% \fi
|
|
|
-% Obviously the verbatim environment doesn't fit. You might use the
|
|
|
-% tabbing environment or something like that. But you have to mark all
|
|
|
-% keywords yourself and doing the indention is also a heavy work. But
|
|
|
-% the most striking disadvantage is that you can't run your \LaTeXe-file
|
|
|
-% through your C++, Pascal or whatever else compiler.
|
|
|
-%
|
|
|
-% Fortunately there is another possibility. You might use a cross
|
|
|
-% compiler, e.g.\ you run a special compiler on your Pascal source
|
|
|
-% code to get a \TeX-file with marked keywords, etc. Then \TeX{}
|
|
|
-% produces a pretty output (usage of a well-designed cross compiler
|
|
|
-% granted). If your sources change, you would have to rerun the cross
|
|
|
-% compiler to get your \TeX-file right and have to compile this to get
|
|
|
-% your document. Again and again.
|
|
|
-%
|
|
|
-% By now these days have gone. The listings package goes around this by
|
|
|
-% reading the source code directly. Comments, strings and keywords can
|
|
|
-% be typeset in different styles as shown in the examples above. The
|
|
|
-% indention is taken from the sources. Hence, the programmer is
|
|
|
-% responsible for writing 'readable' code. The package only helps to
|
|
|
-% present it.
|
|
|
-%
|
|
|
-% This package is surely not the final utility for typesetting
|
|
|
-% listings. May be it's a matter of pureness whether to use a cross
|
|
|
-% compiler or the listings package. Hope you join it and help to get
|
|
|
-% this tool more powerful. Please report all errors and offer
|
|
|
-% improvements!
|
|
|
-%
|
|
|
%
|
|
|
-% \subsection{Installation}
|
|
|
%
|
|
|
-% The main files of this package are \texttt{listings.dtx} and
|
|
|
-% \texttt{listings.ins}. Run the latter file through \TeX{}. This
|
|
|
-% will create \texttt{listings.sty} and a couple of driver files
|
|
|
-% with the prefix \texttt{lst}, e.g.\ \texttt{lstfortran.sty},
|
|
|
-% but the exact name is system dependent.
|
|
|
-% Copy all created \texttt{.sty}-files to a directory searched by
|
|
|
-% \TeX{}. This completes the installation. Run \texttt{listings.dtx}
|
|
|
-% through \TeX{} to get the documentation \texttt{listings.dvi}.
|
|
|
-%
|
|
|
-% \textbf{Important note:} All files of the listings package are
|
|
|
-% distributed freely. You are not allowed to take money for the
|
|
|
-% distribution or use of these files, except for a nomial charge for
|
|
|
-% copying etc.
|
|
|
-% The files are distributed without any warranty; without even the
|
|
|
-% implied warranty of merchantability or fitness for a particular
|
|
|
-% purpose.
|
|
|
-% You are not allowed to change one of the files, except using a
|
|
|
-% clearly different filename.
|
|
|
-%
|
|
|
-% \textbf{Trademarks} appear throughout this documentation without any
|
|
|
-% trademark symbol. So you can't assume that a name is not trademarked.
|
|
|
-% There is no intention of infringement. The usage is to the benefit
|
|
|
-% of the trademark owner.
|
|
|
-%
|
|
|
-%
|
|
|
-% \subsection{Selecting a language}
|
|
|
-% \label{ssSelecting}\DescribeMacro\selectlisting
|
|
|
-% You choose a language with \cs{selectlisting}. The argument is (nearly)
|
|
|
-% one of the language names listed below. The driver files are loaded on
|
|
|
-% demand. The command also has an optional argument to select different
|
|
|
-% kinds of the same language, e.g.\
|
|
|
-% \begin{verbatim}
|
|
|
-% \selectlisting[1974]{cobol}\end{verbatim}
|
|
|
-% selects COBOL ANS-1974, whereas the default would be ANS-1985. All
|
|
|
-% languages currently supported are listed together with the available
|
|
|
-% options, where always the first option is default, i.e.\ selected
|
|
|
-% if none is given.
|
|
|
-% I also mention what the listings package is not capable of.
|
|
|
-% '\texttt{???}' in driver files indicate things I don't know.
|
|
|
-% \textbf{To help me}:
|
|
|
-% \emph{Please send me an e-mail with the languages and options you
|
|
|
-% use (i.e.\ are tested in a way), languages and options you want
|
|
|
-% to be corrected or want additionally.}
|
|
|
-% See section \ref{ssItsNotAllFine}.
|
|
|
-% Note: Language selection is local now.
|
|
|
+% \subsection{Package loading}
|
|
|
%
|
|
|
+% As usual in \LaTeX\ the package is loaded by |\usepackage[|\meta{options}|]{listings}|, where |[|\meta{options}|]| is optional.
|
|
|
+% Note that \textsf{listings} 0.19 needs more save stack size than any previous version.
|
|
|
+% The following options are available:
|
|
|
% \begin{description}
|
|
|
-% \item[Blank] \verb!\selectlisting{blank}!.
|
|
|
-%
|
|
|
-% This is the default language: no keywords and no comments are
|
|
|
-% detected (unless additional specified, see section
|
|
|
-% \ref{sOtherLanguages}).
|
|
|
-% \item[Ada] \verb!\selectlisting{ada}!.
|
|
|
-%
|
|
|
-% This package can't handle strings where the usual quotation marks
|
|
|
-% (double quotes) are replaced by percent characters.
|
|
|
-% \item[Algol] \verb!\selectlisting{algol}!,
|
|
|
-% options: \texttt{68}, \texttt{60}.
|
|
|
-%
|
|
|
-% Algol 60 seems to be ok. But there are problems concerning the
|
|
|
-% comments of Algol 68. First, comments enclosed by \rlap{/}c
|
|
|
-% are not supported. Second, if you use a sharp $\#$ within
|
|
|
-% \verb!co!...\verb!co! (and dito within \verb!comment!), there
|
|
|
-% \emph{must} be a matching second $\#$, or the output is not all
|
|
|
-% right.\footnote{The problem is the following: The sharp is a special
|
|
|
-% character, whereas \texttt{co} is a predefined word and consists
|
|
|
-% of letters. Comments enclosed by special characters are handled
|
|
|
-% easily, and even comments starting or ending with keywords are
|
|
|
-% possible (Algol 60). But a mixture of both (without matching sharp)
|
|
|
-% can only be handled by changing the kernel \texttt{listings.sty}.
|
|
|
-% Since that would slow down all other languages, I decided to do
|
|
|
-% it this way (matching sharp). I even don't know, if this way is
|
|
|
-% standard Algol 68 --- the books are not very detailed, or I haven't
|
|
|
-% found it.} The other way round, i.e.\ a lonely \texttt{comment}
|
|
|
-% within $\#$...$\#$ is harmless.
|
|
|
-% \item[C] \verb!\selectlisting{c}!.
|
|
|
-% \item[C++] \verb!\selectlisting{cpp}!,
|
|
|
-% options: \texttt{ansi}, \texttt{vc} (Visual C++).
|
|
|
-% \item[Cobol] \verb!\selectlisting{cobol}!,
|
|
|
-% options: \texttt{1985}, \texttt{1974}, \texttt{ibm}.
|
|
|
-%
|
|
|
-% Keywords are not marked, if their names are broken in two parts,
|
|
|
-% i.e.\ continued in the following line.
|
|
|
-% Sometimes portions of a string are not printed as a string.
|
|
|
-% This happens, if the double quote is not doubled to insert a quote,
|
|
|
-% e.g.\ \verb!""bad" cobol"! won't be printed correctly.
|
|
|
-% \item[Comal 80] \verb!\selectlisting{comal}!.
|
|
|
-% \item[Eiffel] \verb!\selectlisting{eiffel}!.
|
|
|
-% \item[Elan] \verb!\selectlisting{elan}!.
|
|
|
-% \item[Fortran] \verb!\selectlisting{fortran}!,
|
|
|
-% options: \texttt{90}, \texttt{77}.
|
|
|
-%
|
|
|
-% The keywords are assumed to be \emph{not} case sensitive.
|
|
|
-% \item[Java] \verb!\selectlisting{java}!.
|
|
|
-% \item[Lisp] \verb!\selectlisting{lisp}! (Common Lisp).
|
|
|
-% \item[Logo] \verb!\selectlisting{logo}!.
|
|
|
-% \item[Matlab] \verb!\selectlisting{matlab}!.
|
|
|
-%
|
|
|
-% Matlab uses the quote with two meanings. This package always assumes
|
|
|
-% the beginning or ending of a string, even if you use the quote as
|
|
|
-% transpose-conjugate operator.
|
|
|
-% \item[Modula-2] \verb!\selectlisting{modula}!.
|
|
|
-% \item[Oberon-2] \verb!\selectlisting{oberon}!.
|
|
|
-% \item[Pascal] \verb!\selectlisting{pascal}!.
|
|
|
-% \item[Pascal XSC] \verb!\selectlisting{pxsc}!.
|
|
|
-%
|
|
|
-% Tell me, if you want more words to be keywords.
|
|
|
-% \item[Turbo Pascal] \verb!\selectlisting{tp}!.
|
|
|
-%
|
|
|
-% Keywords are from version 6.0. Possibly too many keywords present.
|
|
|
-% \item[Perl] \verb!\selectlisting{perl}!.
|
|
|
-% \item[PL/I] \verb!\selectlisting{pli}!.
|
|
|
-% \item[Simula 67] \verb!\selectlisting{simula}!,
|
|
|
-% options: \texttt{67}, \texttt{cii}, \texttt{dec}, \texttt{ibm}.
|
|
|
-% \item[SQL-92] \verb!\selectlisting{sql}!.
|
|
|
-% \item[\TeX] \verb!\selectlisting{tex}!,
|
|
|
-% options: \texttt{plain}, \texttt{primitive}, \texttt{latex},
|
|
|
-% \texttt{allatex}.
|
|
|
+% \item[\texttt{0.17}]
|
|
|
+% Use this option to compile documents created with version 0.17 of the \textsf{listings} package.
|
|
|
+% Note that you can't use old driver files and that the option does not guarantee full compatibility.
|
|
|
+% If you want to polish up an old document, use this option together with new commands and keys.
|
|
|
+% There shouldn't be many problems, but I haven't made deep tests.
|
|
|
+% \item[\normalfont\texttt{index} and \texttt{procnames}] define the 'index' respectively 'procnames' aspect, whatever that means.
|
|
|
+% \item[\normalfont\texttt{ndkeywords} and \texttt{rdkeywords}] define second respectively third order keywords.
|
|
|
% \end{description}
|
|
|
+% Note: Each option slows down the package, so it becomes quite slow if you use all options, for example.
|
|
|
+% Note also that you can't activate any optional feature after package loading --- except you're a hacker and read the implementation part.
|
|
|
%
|
|
|
-%
|
|
|
-% \subsection{Typesetting a listing}
|
|
|
-%
|
|
|
-% \DescribeMacro\inputlisting
|
|
|
-% The main command for this purpose is \cs{inputlisting}. The syntax
|
|
|
-% is
|
|
|
+% Here is some kind of minimal file.
|
|
|
% \begin{verbatim}
|
|
|
-% \inputlisting[FIRST,LAST]{WHOLE FILENAME}\end{verbatim}
|
|
|
-% where \verb![FIRST,LAST]! is optional and determines the range of lines
|
|
|
-% to typeset. The default range is $[1,999999]$. If you specify negative
|
|
|
-% lines or an empty range, for example, you won't get any warning.
|
|
|
-% There is no default extension, so you must specify the whole filename.
|
|
|
-% The example
|
|
|
+% \documentclass{article}
|
|
|
+%
|
|
|
+% \usepackage{listings}
|
|
|
+% %\usepackage[ndkeywords,index]{listings}% with some options
|
|
|
+%
|
|
|
+% \begin{document}
|
|
|
+%
|
|
|
+% \lstset{language=Pascal}
|
|
|
+% % Any example may be inserted here.
|
|
|
+%
|
|
|
+% \end{document}\end{verbatim}
|
|
|
+% \label{uMinimalFile}It loads the \textsf{listings} package without any option, but shows how the package is loaded with index option and second order keywords.
|
|
|
+% Moreover we select Pascal as programming language.
|
|
|
+%
|
|
|
+% If you need more than one programming language in your document, I recommend the preamble command |\lstloadlanguages|, which loads the given programming languages only, e.g.\ |\lstloadlanguages{Pascal,Fortran,C++}|.
|
|
|
+% You find more details in section \ref{uLanguagesAndStyles}.
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Typesetting listings}
|
|
|
+%
|
|
|
+% You can print (a) stand alone files, (b) source code from \texttt{.tex} files or (c) code fragments within a paragraph.
|
|
|
+% The difference between (b) and (c) is something like between display and text formulas (|$$| and |$|).
|
|
|
+%
|
|
|
+% We begin with code fragments.
|
|
|
+% If you want '\lstinline!var i:integer;!', you can simply write '|\lstinline!var i:integer;!|'.
|
|
|
+% The exclamation marks delimit the code fragment.
|
|
|
+% They could be replaced by any character not in the code fragment, i.e.\ '|\lstinline$var i:integer;$|' would produce the same output.
|
|
|
+%
|
|
|
+% The \texttt{lstlisting} environment typesets the source code in between.
|
|
|
+% It has one parameter, which we leave empty for the moment.
|
|
|
+% \begin{lstsample}{}
|
|
|
+%\begin{lstlisting}{}
|
|
|
+%for i:=maxint to 0 do
|
|
|
+%begin
|
|
|
+% { do nothing }
|
|
|
+%end;
|
|
|
+%
|
|
|
+%Write('Keywords are case ');
|
|
|
+%WritE('insensitive here.');
|
|
|
+%\end{lstlisting}
|
|
|
+% \end{lstsample}
|
|
|
+% \noindent
|
|
|
+% Like most examples this shows the \LaTeX\ source code on the right and the result on the left.
|
|
|
+% If you insert the \LaTeX\ code in the minimal file and run it through \TeX, the listing uses the whole text width.
|
|
|
+%
|
|
|
+% Finally examples for stand alone files:
|
|
|
+% \begin{lstsample}{\lstset{baseem=0.5}}
|
|
|
+%\lstinputlisting{listings.tmp}
|
|
|
+% \end{lstsample}
|
|
|
+% \noindent
|
|
|
+% Do you wonder about the left hand side?
|
|
|
+% Well, the file \texttt{listings.tmp} contains the current example.
|
|
|
+% This is exactly the line you see on the right.
|
|
|
+% If you want this line to be typeset in Pascal mode, you get what you've got.
|
|
|
+% If you want the lines $3,4,\ldots,10$ of \texttt{testfile.pas}, write
|
|
|
% \begin{verbatim}
|
|
|
-% \inputlisting[3,10]{testfile.pas}\end{verbatim}
|
|
|
-% would print lines 3,4,\ldots,10 of \verb!testfile.pas!, if file and
|
|
|
-% lines are present.
|
|
|
-%
|
|
|
-% \DescribeEnv{listing}
|
|
|
-% There is also a listing environment. It typesets the source code
|
|
|
-% enclosed within \verb!\begin{listing}! and \verb!\end{listing}!.
|
|
|
-% If the source code starts right after \verb!\begin{listing}!, it is
|
|
|
-% dropped upto the end of line. Dito the source preceding and following
|
|
|
-% \verb!\end{listing}! directly, i.e.\ in the same line. You may don't
|
|
|
-% like this, but the lines
|
|
|
-% \begin{verbatim}
|
|
|
-% \selectlisting{fortran}
|
|
|
-% \begin{listing}DROPPED
|
|
|
-%* This is a test for the listing environment
|
|
|
-%C and not considered to be an example for
|
|
|
-% ! Fortran!
|
|
|
-% Program example
|
|
|
-% ...
|
|
|
-%DROPPED\end{listing}DROPPED\end{verbatim}
|
|
|
-% result in
|
|
|
-% \normallisting
|
|
|
-% \selectlisting{fortran}
|
|
|
-% \iffalse
|
|
|
-%<*sample>
|
|
|
-% \fi
|
|
|
-% \begin{listing}DROPPED
|
|
|
-* This is a test for the listing environment
|
|
|
-C and not considered to be an example for
|
|
|
- ! Fortran!
|
|
|
- Program example
|
|
|
- ...
|
|
|
-%DROPPED\end{listing}DROPPED
|
|
|
-% \iffalse
|
|
|
-%</sample>
|
|
|
-% \fi
|
|
|
+% \lstinputlisting[first=3,last=10]{testfile.pas}\end{verbatim}
|
|
|
+% But be sure that the first line does exist, or you will get a ''runaway argument'' error.
|
|
|
%
|
|
|
-% \DescribeMacro\listingfalse
|
|
|
-% Since typesetting listings with this package is possibly slow,
|
|
|
-% you can suppress the output with \cs{listingfalse}. Afterwards this
|
|
|
-% \DescribeMacro\listingtrue
|
|
|
-% package only prints the name of the source like
|
|
|
-% \selectlisting{pascal}\listingfalse
|
|
|
-% \inputlisting{testfile.pas}\listingtrue
|
|
|
-% \cs{listingtrue} reverses the effect.
|
|
|
-%
|
|
|
-% \DescribeMacro\tablength
|
|
|
-% If you use tabulators in your source codes, you have to tell this
|
|
|
-% package the number of characters between two tabulator stops.
|
|
|
-% Default value is 4. Changes are made by, e.g.,\
|
|
|
-% \begin{verbatim}
|
|
|
-% \tablength{8}\end{verbatim}
|
|
|
-% i.e. tabulator stops are set at the columns 1, 9, 17, 25 {\ldots}
|
|
|
-% Negative values are prohibited. They won't confuse this package,
|
|
|
-% since it gives an error message and proceeds with the old value of
|
|
|
-% tablength.
|
|
|
-%
|
|
|
-% \DescribeMacro\listoflistings
|
|
|
-% Two more commands should be mentioned here. Use \cs{listoflistings}
|
|
|
-% as you do \cs{listoftables} and \cs{listoffigures} and renew
|
|
|
-% \DescribeMacro\listlistingsname\cs{listlistingsname} to change the
|
|
|
-% default header 'Listings'. The list shows either the filename or
|
|
|
-% the optional argument of the listing environment, e.g.\
|
|
|
-% \begin{verbatim}
|
|
|
-% \inputlisting{Quicksort.pas}
|
|
|
-% \begin{listing}[Heapsort]
|
|
|
-% ...
|
|
|
-% \end{listing}\end{verbatim}
|
|
|
-% will show the names 'Quicksort.pas' and 'Heapsort'.
|
|
|
-%
|
|
|
-%
|
|
|
-% \subsection{Figure out the appearance}\label{ssFigureOutTheAppearance}
|
|
|
-% You have some possibilities to change how the output looks like.
|
|
|
-%
|
|
|
-% \DescribeMacro\keywordstyle
|
|
|
-% By default keywords\footnote{Let's talk about keywords: I tried to get
|
|
|
-% all keywords of the languages, but there are so many books with no
|
|
|
-% list of keywords. So I looked at the index, but some books print
|
|
|
-% keywords bold and predefined functions in italics, other books print
|
|
|
-% both in bold. So I had to guess, which words are keywords. Moreover
|
|
|
-% it's a great deal to find out whether the keywords are case sensitive
|
|
|
-% or not. Of course, there are really fine books (e.g.\ \cite{Ada}).
|
|
|
-% And I know that some languages don't have keywords, and so there
|
|
|
-% can't be a list of them. But even these languages have predefined
|
|
|
-% words --- which are not listed. Hence, for our purpose \emph{keywords}
|
|
|
-% are predefined words, fixed words, reserved words, real keywords and
|
|
|
-% all words you or I want to name so.} are typeset bold, comments in
|
|
|
-% italic shape and strings using no special style.
|
|
|
-% \DescribeMacro\commentstyle
|
|
|
-% You can change this with the commands \cs{keywordstyle},
|
|
|
-% \DescribeMacro\stringstyle
|
|
|
-% \cs{commentstyle} and \cs{stringstyle}, e.g.
|
|
|
-% \begin{verbatim}
|
|
|
-% \keywordstyle{\bfseries\itshape} % bold and italic
|
|
|
-% \commentstyle{\tt\small} % LaTeX 2.09 typewriter, small
|
|
|
-% \stringstyle{\ttfamily} % typewriter\end{verbatim}
|
|
|
-% will typeset the second example of the introduction as follows
|
|
|
-% \keywordstyle{\bfseries\itshape} \commentstyle{\tt\small}
|
|
|
-% \stringstyle{\ttfamily}
|
|
|
-% \selectlisting{pascal}
|
|
|
-% \iffalse
|
|
|
-%<*sample>
|
|
|
-% \fi
|
|
|
-% \begin{listing}
|
|
|
- for i:=maxint downto 0 do
|
|
|
- begin
|
|
|
- { do nothing }
|
|
|
- end;
|
|
|
-
|
|
|
- WriteLn('Pascal keywords are');
|
|
|
- writeln('not case sensitive.');
|
|
|
-% \end{listing}
|
|
|
-% \iffalse
|
|
|
-%</sample>
|
|
|
-% \fi
|
|
|
-% \normallisting
|
|
|
+% Problems could arise if you (try to) put a listing in a box, tabular environment or something similar.
|
|
|
+% The |\lstbox| command in section \ref{uTypesettingListings} might solve this.
|
|
|
+% If you use an extended character table in your listings, you must use the |extendedchars| key, see section \ref{uSomeSpecialKeys}.
|
|
|
%
|
|
|
-% \DescribeMacro\blankstringtrue
|
|
|
-% Once again blank spaces of a string have been printed \textvisiblespace.
|
|
|
-% Suppress this by using \cs{blankstringtrue} and switch to default
|
|
|
-% \DescribeMacro\blankstringfalse
|
|
|
-% with \cs{blankstringfalse}.
|
|
|
%
|
|
|
-% \DescribeMacro\labelstyle\label{newlabelstyle}
|
|
|
-% By default no line numbers are printed. You can change this with the
|
|
|
-% \cs{labelstyle} command. The syntax is
|
|
|
-% \begin{verbatim}
|
|
|
-% \labelstyle[step]{the style}\end{verbatim}
|
|
|
-% The style determines how the line numbers look like (\cs{ttfamily},
|
|
|
-% \cs{small}, and so on). Line numbers are printed all 'step' lines.
|
|
|
-% More precisely all line numbers are printed, which are divisible by
|
|
|
-% step. If step is zero, no line numbers will be typeset.
|
|
|
-% The step is an optional argument. If no step is specified, it is
|
|
|
-% assumed to be 1. Here some (exotic) examples:
|
|
|
-% \begin{verbatim}
|
|
|
-% \labelstyle[3]{\ttfamily\small} % line 3,6,9,..., small typewriter
|
|
|
-% \labelstyle{\small\oldstylenums}% small oldstyle numbers
|
|
|
-% \makeatletter
|
|
|
-% \labelstyle{\@roman} % roman numbers(!) each line
|
|
|
-% \labelstyle{\@Roman} % upper case roman numbers
|
|
|
-% \makeatother\end{verbatim}
|
|
|
-%
|
|
|
-% The C++ source line
|
|
|
-% \selectlisting{cpp}
|
|
|
-% \iffalse
|
|
|
-%<*sample>
|
|
|
-% \fi
|
|
|
-% \begin{listing}
|
|
|
- if (ThereIsALongLine) { ItExceedsASingleLineInTheListing(); }
|
|
|
-% \end{listing}
|
|
|
-% \iffalse
|
|
|
-%</sample>
|
|
|
-% \fi
|
|
|
-% \noindent\DescribeMacro\spreadlisting
|
|
|
-% gives rise to an overfull \verb!\hbox!. To avoid things like that
|
|
|
-% you can first spread the width taken by a listing, and second
|
|
|
-% \DescribeMacro\prelisting
|
|
|
-% change the fontsize. The commands \cs{spreadlisting}, \cs{prelisting}
|
|
|
-% \DescribeMacro\postlisting
|
|
|
-% and \cs{postlisting} have one argument each. For the example above
|
|
|
-% you should use
|
|
|
-% \begin{verbatim}
|
|
|
-% \spreadlisting{1in} % spread the width by 1in, 0.5in left and right
|
|
|
-% \prelisting{\small} % select new fontsize
|
|
|
-% \postlisting{} % nothing to do (default)\end{verbatim}
|
|
|
-% or something similar and get
|
|
|
-% \spreadlisting{1in}
|
|
|
-% \prelisting{\small}
|
|
|
-% \iffalse
|
|
|
-%<*sample>
|
|
|
-% \fi
|
|
|
-% \begin{listing}
|
|
|
- if (ThereIsALongLine) { ItExceedsASingleLineInTheListing(); }
|
|
|
-% \end{listing}
|
|
|
-% \iffalse
|
|
|
-%</sample>
|
|
|
-% \fi
|
|
|
-% \normallisting
|
|
|
-% You can use the pre-post-mechanism to add something right before a
|
|
|
-% listing starts or after it ends, e.g.\ \verb!\prelisting{\bigbreak}!
|
|
|
-% will lead to an empty line between a listing and the preceding text
|
|
|
-% (if on the same page).
|
|
|
-%
|
|
|
-% \DescribeMacro\normallisting
|
|
|
-% Changes made by the commands above are reset by \cs{normallisting}
|
|
|
-% (there are no arguments): Keywords are typeset bold, comments in
|
|
|
-% italic shape, stringstyle, labelstyle and pre- and postlisting are
|
|
|
-% empty, blank spaces in strings are printed \textvisiblespace, and
|
|
|
-% spreadlisting is set to 0pt. Nothing other is affected.
|
|
|
-%
|
|
|
-% \DescribeMacro\lstlineskip
|
|
|
-% The one and only argument of this command is a skip. It's the
|
|
|
-% \emph{additional} space between two lines in the output of a listing.
|
|
|
-% The default is 0pt.
|
|
|
-%
|
|
|
-% \DescribeMacro\lstbaseem
|
|
|
-% Here is one more command, which should be used in driver files only,
|
|
|
-% since the one and only parameter is language specific. But you can
|
|
|
-% use it for adjustment in your document. The parameter gives the witdh
|
|
|
-% one character takes in the output in units of 1em. The parameter is a
|
|
|
-% floating number and not a \TeX{} dimension, i.e.\ the unit em is
|
|
|
-% added by the listings package. If you specify \verb!\lstbaseem{1}!,
|
|
|
-% i.e.\ 1em, characters will never overlap. And the output produced
|
|
|
-% after \verb!\lstbaseem{0}! looks quite funny. Better try values near
|
|
|
-% $0.6$.
|
|
|
-%
|
|
|
-%
|
|
|
-% \subsection{Other languages}\label{sOtherLanguages}
|
|
|
-%
|
|
|
-% You have some possibilities to adapt this package to other languages.
|
|
|
-% For our purpose here the main characteristics of a language are
|
|
|
-% keywords, comments and strings.
|
|
|
-%
|
|
|
-% Let's say, we want to produce following output:
|
|
|
-% \selectlisting{blank}
|
|
|
-% \keywords{function,integer,begin,end,if,then,else,return,print}
|
|
|
-% \DeclareCommentLine//\relax
|
|
|
-% \begingroup\catcode`\"=12\stringizer{"}\endgroup
|
|
|
-% \stringstyle{\ttfamily}\blankstringfalse
|
|
|
-% \iffalse
|
|
|
-%<*sample>
|
|
|
-% \fi
|
|
|
-% \begin{listing}
|
|
|
-function Fib(integer n):integer;
|
|
|
-// Function returns the n-th Fibonacci.
|
|
|
-begin
|
|
|
- if (n<2) then return 1;
|
|
|
- else return Fib(n-1)+Fib(n-2);
|
|
|
-end;
|
|
|
-
|
|
|
-// Main program.
|
|
|
-begin
|
|
|
- print("Fib(10) = ",Fib(10), "\n");
|
|
|
-end.
|
|
|
-% \end{listing}
|
|
|
-% \iffalse
|
|
|
-%</sample>
|
|
|
-% \fi
|
|
|
-% You already know about \cs{stringstyle} and \cs{blankstringfalse}.
|
|
|
-% We assume \verb!\selectlisting{blank}!. And now comes all the rest
|
|
|
-% to print such a language mixture.
|
|
|
-% \DescribeMacro\keywords
|
|
|
-% To set the keywords use the \cs{keywords} command. After
|
|
|
-% \begin{verbatim}
|
|
|
-% \keywords{one,two,three,four,five,six,seven,eight,nine,ten,
|
|
|
-% eleven,twelve}\end{verbatim}
|
|
|
-% exactly these twelve keywords are present. As you see, each two
|
|
|
-% keywords are separated by a comma.
|
|
|
-% \DescribeMacro\morekeywords
|
|
|
-% If you want to add keywords only use \cs{morekeywords} like
|
|
|
+% \subsection{The ''key=value'' interface}
|
|
|
+%
|
|
|
+% The \textsf{listings} package uses \textsf{keyval.sty} from the \textsf{graphics} bundle by David Carlisle.
|
|
|
+% Each 'aspect' or 'parameter' you can control has an associated key.
|
|
|
+% To select a programming language, for example, you need the key |language|, the sign |=| and the name of the language as value.
|
|
|
+% The command |\lstset| gets this construction as argument.
|
|
|
+% You have seen this in the minimal file on page \pageref{uMinimalFile}.
|
|
|
+% You can set more than one parameter with a single |\lstset| if you separate two or more ''key=value'' constructions by commas:
|
|
|
% \begin{verbatim}
|
|
|
-% \morekeywords{maxreal,minreal} % add these keywords
|
|
|
-% \morekeywords{zero,MAXINT} % add also\end{verbatim}
|
|
|
-%
|
|
|
-% \DescribeMacro\sensitivetrue
|
|
|
-% Some languages are case sensitive, others are not. You can select
|
|
|
-% this with \cs{sensitivetrue} and \cs{sensitivefalse}, respectively.
|
|
|
-% \DescribeMacro\sensitivefalse
|
|
|
-% This package will then use the right keyword test.
|
|
|
-%
|
|
|
-% \DescribeMacro\stringizer
|
|
|
-% The command \cs{stringizer} changes the character, which begins and
|
|
|
-% ends a string. If your parameter consists of several characters,
|
|
|
-% each character can start a string. But the string must be terminated
|
|
|
-% with the same character. Using a letter, a digit or the underbar as
|
|
|
-% stringizer will not work. The Modula-2 option defines the stringizer
|
|
|
-% by
|
|
|
+% \lstset{language=Pascal,keywordstyle=\bfseries}\end{verbatim}
|
|
|
+% If the value itself contains a comma, you must enclose the value in braces:
|
|
|
% \begin{verbatim}
|
|
|
-% \catcode`\"=12
|
|
|
-% \stringizer{'"}\end{verbatim}
|
|
|
-% The catcode is changed (locally) for compatibility with
|
|
|
-% \verb!german.sty!. The double quote is defined active there, but
|
|
|
-% when we input a listing the double quote will have catcode 12
|
|
|
-% (=other). The stringizer command has an optional argument to select
|
|
|
-% whether the stringizer is doubled (default, e.g.\ Pascal) or preceded
|
|
|
-% by a backslash (e.g.\ C) to insert the stringizer itself at the current
|
|
|
-% position. The arguments are \verb!d! and \verb!b!, respectively, e.g.\
|
|
|
+% \lstset{keywords={one,two,three}}\end{verbatim}
|
|
|
+% |\lstset{keywords=one,two,three}| would set the one and only keyword |one| and gives an error message since the parameters |two| and |three| do not exist.
|
|
|
+%
|
|
|
+% Two final notes:
|
|
|
+% (1) Some keys has default values, e.g.\ |flexiblecolumns=true| turns flexible columns on, but |flexiblecolumns| without any |=true| would do the same since the value true is default for that key.
|
|
|
+% But you must use the value |false| if you want to turn them off.
|
|
|
+% (2) |\lstset| sets the values local to the current group.
|
|
|
+% Just forget it if you don't know what that means.
|
|
|
+% The command |\lstinputlisting| (as seen above) and the environment (as you see below) both have optional arguments.
|
|
|
+% If you use a key=value list as optional argument, these selections are valid for the particular listing only and the previous values are restored afterwards.
|
|
|
+% For example, if the current language is Pascal, but you want \texttt{testfile.f95} from line 3 on, write
|
|
|
% \begin{verbatim}
|
|
|
-% \stringizer[d]{'} % doubled stringizer inserts stringizer
|
|
|
-% \stringizer[b]{"} % backslashed stringizer inserts\end{verbatim}
|
|
|
-%
|
|
|
-% Let's come to comments. For our purpose a 'comment line' is a comment,
|
|
|
-% which starts with a character sequence and goes upto the end of a
|
|
|
-% line. 'Comments' start and end with given character sequences.
|
|
|
-% Comment lines need not to begin at the first column and comments
|
|
|
-% can start and end wherever you want.
|
|
|
-%
|
|
|
-% \DescribeMacro\DeclareCommentLine
|
|
|
-% \cs{DeclareCommentLine} has one parameter, which is terminated by
|
|
|
-% \cs{relax}, i.e.\
|
|
|
+% \lstinputlisting[first=3,language=Fortran]{testfile.f95}\end{verbatim}
|
|
|
+% Afterwards Pascal is still the current language.
|
|
|
+% Note that |\lstinline| has no optional parameter.
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Figure out the appearance}
|
|
|
+%
|
|
|
+% Keywords are typeset bold, comments in italic shape and spaces in strings appear as '\textvisiblespace' (without the two quotes).
|
|
|
+% You can change that default behaviour:
|
|
|
% \begin{verbatim}
|
|
|
-% \DeclareCommentLine //\relax\end{verbatim}
|
|
|
-% is legal. The parameter is a (nearly) arbitrary character sequence,
|
|
|
-% which separates a comment line. Using a letter, a digit or the
|
|
|
-% underbar will not work. And: When we input a listing, the characters
|
|
|
-% must have the same category codes. Refer section
|
|
|
-% \ref{SpecialCharacters} and \ref{ssSpecialCharacters}.
|
|
|
-% If you don't want any comment lines, let the parameter empty, but
|
|
|
-% don't forget the \cs{relax}!
|
|
|
-%
|
|
|
-% \DescribeMacro\DeclareSingleComment
|
|
|
-% Four types of comments are supported: \textbf{single} for languages
|
|
|
-% with one kind of comment, e.g.\ C or C++; \textbf{double} for
|
|
|
-% \DescribeMacro\DeclareDoubleComment
|
|
|
-% languages with two kinds of comments, e.g.\ Pascal comments enclosed
|
|
|
-% \DescribeMacro\DeclareNestedComment
|
|
|
-% within \verb!(*! and \verb!*)! and within \verb!{! and \verb!}!;
|
|
|
-% \textbf{nested} for languages with one kind of comment, which can be
|
|
|
-% \DescribeMacro\DeclarePairedComment
|
|
|
-% nested, e.g.\ Modula-2. A \textbf{paired} comment is a single comment,
|
|
|
-% but the two comment delimiters are the same and therefore occur paired.
|
|
|
-% The declaration of such comments is similar to comment lines.
|
|
|
-% The character sequences are separated by one blank space, e.g.\
|
|
|
+%\lstset{
|
|
|
+% basicstyle=\small, % print whole listing small
|
|
|
+% keywordstyle=\bfseries\underbar,% 'underlined' bold keywords
|
|
|
+% nonkeywordstyle={}, % nothing happens to other identifiers
|
|
|
+% commentstyle=\itshape, % default
|
|
|
+% stringstyle=\ttfamily, % typewriter font for strings
|
|
|
+% blankstring=true} % blank spaces are blank in strings\end{verbatim}
|
|
|
+% We typeset a previous example with these styles again.
|
|
|
+%\lstset{basicstyle=\small,
|
|
|
+% keywordstyle=\bfseries\underbar,nonkeywordstyle={},
|
|
|
+% commentstyle=\itshape,stringstyle=\ttfamily,blankstring=true}
|
|
|
+% \begin{lstsample}{}
|
|
|
+%\begin{lstlisting}{}
|
|
|
+%for i:=maxint to 0 do
|
|
|
+%begin
|
|
|
+% { do nothing }
|
|
|
+%end;
|
|
|
+%
|
|
|
+%Write('Keywords are case ');
|
|
|
+%WritE('insensitive here.');
|
|
|
+%\end{lstlisting}
|
|
|
+% \end{lstsample}
|
|
|
+% \noindent
|
|
|
+% The style definitions above use two kind of commands; on the one hand |\ttfamily| or |\bfseries| taking no arguments and on the other |\underline|, which gets exactly one argument.
|
|
|
+% The \emph{very last} token of |keywordstyle|, |nonkeywordstyle| and |labelstyle| (see below) \emph{may} be a macro getting exactly one argument, namely the (non)keyword or label.
|
|
|
+% All other tokens \emph{must not} take any arguments --- or you will get deep in trouble.
|
|
|
+% \lstset{style={},blankstring=false}
|
|
|
+%
|
|
|
+% \textbf{Warning:}
|
|
|
+% You shouldn't use striking styles too often, but 'too often' depends on how many keywords the source code contains, for example.
|
|
|
+% Your eyes would concentrate on the framed, bold red printed keywords only, and your brain must compensate this.
|
|
|
+% Reading such source code could be very exhausting.
|
|
|
+% If it were longer, the last example would be quite good in this sense.
|
|
|
+% Believe me.
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Line numbers}
|
|
|
+%
|
|
|
+% You want tiny line numbers each second line?
|
|
|
+% Here you are:
|
|
|
+% \begin{lstsample}{}
|
|
|
+%\lstset{labelstyle=\tiny,% <===
|
|
|
+% labelstep=2}% <===
|
|
|
+%\begin{lstlisting}{}
|
|
|
+%for i:=maxint to 0 do
|
|
|
+%begin
|
|
|
+% { do nothing }
|
|
|
+%end;
|
|
|
+%
|
|
|
+%Write('Keywords are case ');
|
|
|
+%WritE('insensitive here.');
|
|
|
+%\end{lstlisting}
|
|
|
+% \end{lstsample}
|
|
|
+% \noindent
|
|
|
+% |labelstep=0| turns line numbering off.
|
|
|
+% In the sequel we use |labelstyle=\tiny| and |labelstep=2|, even if it doesn't appear in the verbatim part.
|
|
|
+% And now we try to interrupt (continue) a listing.
|
|
|
+% For this purpose we use |{ }| as argument to the environment.
|
|
|
+% \begin{lstsample}{\lstset{labelstyle=\tiny,labelstep=2}}
|
|
|
+%\begin{lstlisting}{}
|
|
|
+%for i:=maxint to 0 do
|
|
|
+%begin
|
|
|
+% { do nothing }
|
|
|
+%end;
|
|
|
+%
|
|
|
+%\end{lstlisting}
|
|
|
+%
|
|
|
+%And we continue the listing:
|
|
|
+%
|
|
|
+%\begin{lstlisting}{ }% <===
|
|
|
+%Write('Keywords are case ');
|
|
|
+%WritE('insensitive here.');
|
|
|
+%\end{lstlisting}
|
|
|
+% \end{lstsample}
|
|
|
+% \noindent
|
|
|
+% Note that the empty line at the end of the first part is not printed, but it is responsible for correct line numbering.
|
|
|
+% |{ }| continued the previous '|{}|'-listing.
|
|
|
+% In general the argument is the name of the listing.
|
|
|
+% An empty (= |{}|) named listing always starts with line number one, no matter whether line numbers are printed or not.
|
|
|
+% A space (= |{ }|) named listing continues the last empty or space named one.
|
|
|
+% That's easy.
|
|
|
+% And this mechanism becomes easier if you use real names for your listings.
|
|
|
+% In that case all listings with the same name use a common line counter: the second (same named) listing continues automatically the first.
|
|
|
+% Even if there are other listings in between.
|
|
|
+% \begin{lstsample}{\lstset{labelstyle=\tiny,labelstep=2}}
|
|
|
+%\begin{lstlisting}{Test}% <===
|
|
|
+%for i:=maxint to 0 do
|
|
|
+%begin
|
|
|
+% { do nothing }
|
|
|
+%end;
|
|
|
+%
|
|
|
+%\end{lstlisting}
|
|
|
+%
|
|
|
+%And we continue the listing:
|
|
|
+%
|
|
|
+%\begin{lstlisting}{Test}% <===
|
|
|
+%Write('Keywords are case ');
|
|
|
+%WritE('insensitive here.');
|
|
|
+%\end{lstlisting}
|
|
|
+% \end{lstsample}
|
|
|
+% \noindent
|
|
|
+% The next |Test| listing goes on with line number {\makeatletter\lstno@Test}.
|
|
|
+% Note that listing names are case sensitive.
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Tabulators and form feeds}
|
|
|
+%
|
|
|
+% You might get some unexpected output if your source code contains a tabulator or form feed.
|
|
|
+% The package assumes tabulator stops at columns 9,17,25,33,\ldots, and a form feed prints an empty line.
|
|
|
+% This is predefined via
|
|
|
% \begin{verbatim}
|
|
|
-% \DeclareSingleComment /* */\relax
|
|
|
-% \DeclareDoubleComment (* *) { }\relax
|
|
|
-% \DeclareNestedComment (* *)\relax
|
|
|
-% \DeclarePairedComment #\relax\end{verbatim}
|
|
|
-% But hold on: When we input a listing, the characters must have the
|
|
|
-% same category codes. So the examples won't work without changing
|
|
|
-% them. See section \ref{ssSpecialCharacters}. If you don't want
|
|
|
-% comments, let the second parameter of \cs{DeclareSingleComment}
|
|
|
-% empty, i.e.\ type something like
|
|
|
-% \begin{verbatim*}
|
|
|
-% \DeclareSingleComment stuff \relax\end{verbatim*}
|
|
|
-% If a supported language already uses your favourite keywords,
|
|
|
-% stringizer and/or comments, you are free to select that language
|
|
|
-% and adjust only the wrong data.
|
|
|
-%
|
|
|
-%
|
|
|
-% \subsection{Troubleshooting}
|
|
|
-% After receiving an e-mail from Andreas Bartelt\footnote{
|
|
|
-% [email protected]} the idea comes up
|
|
|
-% to write this section. It is intend to help you handling unusual
|
|
|
-% situations.
|
|
|
-% \begin{itemize}
|
|
|
-% \item If you have problems using \cs{inputlisting} within \LaTeX{}
|
|
|
-% environments or commands, put the listing in a \cs{vbox}.
|
|
|
-% \item A source line might exceeds the textwidth, as shown in section
|
|
|
-% \ref{ssFigureOutTheAppearance}. Put the listing in a \cs{hbox}
|
|
|
-% to decrease the logical width like
|
|
|
+% \lstset{tabsize=8,formfeed=\bigbreak}\end{verbatim}
|
|
|
+% If you change the eight to the number $n$, you will get tabulator stops at columns $n+1,\allowbreak 2n+1,\allowbreak 3n+1,$ and so on.
|
|
|
+% If you want a new page every form feed, use |formfeed=\newpage|.
|
|
|
+% \lstset{tabsize=4}
|
|
|
+% \begin{lstsample}{}
|
|
|
+%\lstset{tabsize=4}
|
|
|
+%\begin{lstlisting}{}
|
|
|
+%123456789
|
|
|
+% { one tabulator }
|
|
|
+% { two tabs }
|
|
|
+%123 { 123 and two tabs }
|
|
|
+%\end{lstlisting}
|
|
|
+% \end{lstsample}
|
|
|
+% \lstset{tabsize=8}\noindent
|
|
|
+% Unfortunately both sides are typeset with |tabsize=4|.
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Indent the listing}
|
|
|
+%
|
|
|
+% The examples are typeset with centered \texttt{minipage}s.
|
|
|
+% That's the reason why you can't see that line numbers are printed in the margin (default).
|
|
|
+% Now we separate the 'minipage margin' and the minipage by a vertical rule:
|
|
|
+% \begin{lstsample}{\lstset{frame=l,frametextsep=0pt,labelstyle=\tiny,labelstep=2}}
|
|
|
+%Some text before
|
|
|
+%\begin{lstlisting}{}
|
|
|
+%for i:=maxint to 0 do
|
|
|
+%begin
|
|
|
+% { do nothing }
|
|
|
+%end;
|
|
|
+%\end{lstlisting}
|
|
|
+% \end{lstsample}
|
|
|
+% \noindent
|
|
|
+% The listing is lined up with the normal text.
|
|
|
+% You can change this if you want.
|
|
|
+% The parameter |indent| 'moves' the listing to the right (or left if the skip is negative).
|
|
|
+% \begin{lstsample}{\lstset{frame=l,frametextsep=0pt,labelstyle=\tiny,labelstep=2}}
|
|
|
+%Some text before
|
|
|
+%\lstset{indent=2em}% <===
|
|
|
+%\begin{lstlisting}{}
|
|
|
+%for i:=maxint to 0 do
|
|
|
+%begin
|
|
|
+% { do nothing }
|
|
|
+%end;
|
|
|
+%\end{lstlisting}
|
|
|
+%
|
|
|
+%\begin{lstlisting}{ }
|
|
|
+%Write('Keywords are case ');
|
|
|
+%WritE('insensitive here.');
|
|
|
+%\end{lstlisting}
|
|
|
+% \end{lstsample}
|
|
|
+% \noindent
|
|
|
+% Note that |\lstset{indent=2em}| also changes the indent for the second listings.
|
|
|
+% If you want to indent a single listing only, use the argument of |\lstset| as optional argument to the listing environment:
|
|
|
+% \begin{lstsample}{\lstset{frame=l,frametextsep=0pt,labelstyle=\tiny,labelstep=2}}
|
|
|
+%\begin{lstlisting}[indent=2em]{}
|
|
|
+%for i:=maxint to 0 do
|
|
|
+%begin
|
|
|
+% { do nothing }
|
|
|
+%end;
|
|
|
+%\end{lstlisting}
|
|
|
+%
|
|
|
+%\begin{lstlisting}{ }
|
|
|
+%Write('Keywords are case ');
|
|
|
+%WritE('insensitive here.');
|
|
|
+%\end{lstlisting}
|
|
|
+% \end{lstsample}
|
|
|
+% \noindent
|
|
|
+% Such local changes apply to all supported parameters.
|
|
|
+%
|
|
|
+% If you use environments like \texttt{itemize} or \texttt{enumerate}, there is 'natural' indention coming from these environments.
|
|
|
+% By default the \textsf{listings} package respects this.
|
|
|
+% But you might use |wholeline=true| (or |false|) to make your own decision.
|
|
|
+% \begin{lstsample}{\lstset{frame=l,frametextsep=0pt,labelstyle=\tiny,labelstep=2}}
|
|
|
+%\begin{itemize}
|
|
|
+%\item First item:
|
|
|
+%
|
|
|
+%\begin{lstlisting}{}
|
|
|
+%for i:=maxint to 0 do
|
|
|
+%begin
|
|
|
+% { do nothing }
|
|
|
+%end;
|
|
|
+%\end{lstlisting}
|
|
|
+%
|
|
|
+%\item Second item:
|
|
|
+%\lstset{wholeline=true}% <===
|
|
|
+%\begin{lstlisting}{ }
|
|
|
+%Write('Keywords are case ');
|
|
|
+%WritE('insensitive here.');
|
|
|
+%\end{lstlisting}
|
|
|
+%\end{itemize}
|
|
|
+% \end{lstsample}
|
|
|
+% \noindent
|
|
|
+% You can use |wholeline| together with |indent|, of course.
|
|
|
+% Refer section \ref{uListingAlignment} for a description of |spread|.
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Fixed and flexible columns}
|
|
|
+%
|
|
|
+% The first thing a reader notices is --- except different styles for keywords etc. --- the column alignment of a listing.
|
|
|
+% The problem: I don't like listings in typewriter fonts and other fonts need not to have a fixed width.
|
|
|
+% But we don't want
|
|
|
+% \begin{itemize}\item[]\begin{tabular}{@{}l}
|
|
|
+% if\ x=y\ then\ write('alignment')\\
|
|
|
+% \ \ \ \ \ \ \ else\ print('alignment');
|
|
|
+% \end{tabular}\end{itemize}
|
|
|
+% only because spaces are not wide enough.
|
|
|
+% There is a simple trick to avoid such things.
|
|
|
+% We make boxes of the same width and put one character in each box:
|
|
|
+% \def\docharfbox#1#2{\fbox{\hbox to#1em{\hss\vphantom{fy}#2\hss}}}
|
|
|
+% \def\docharbox#1#2{\hbox to#1em{\hss#2\hss}}
|
|
|
+% \begin{itemize}\item[]
|
|
|
+% \def\makeboxes#1{\docharfbox1#1\ifx#1\relax\else\expandafter\makeboxes\fi}
|
|
|
+% \makeboxes if\ x=y\ then\ write\relax\space\ldots\\
|
|
|
+% \makeboxes \ \ \ \ \ \ \ else \ print\relax\space\ldots
|
|
|
+% \end{itemize}
|
|
|
+% Going this way the alignment of columns can't be disturbed.
|
|
|
+% \def\makeboxes#1{\docharbox{0.45}#1\ifx#1\relax\else\expandafter\makeboxes\fi}
|
|
|
+% But if the boxes are not wide enough, we get '\makeboxes if\ x=y\ then\relax\ldots', and choosing the width so that the widest character fits in leads to
|
|
|
+% \def\makeboxes#1{\docharbox{1}#1\ifx#1\relax\else\expandafter\makeboxes\fi}
|
|
|
+% '\makeboxes if\ x=y\ then\ write\relax\ldots'.
|
|
|
+% Both are not acceptable.
|
|
|
+% Since all input will be cut up in units, we can put each unit in a box, which width is multiplied by the number of characters we put in, of course.
|
|
|
+% The result is
|
|
|
+% \def\makeboxes#1#2{\docharfbox{#1}{#2}\ifx#2\relax\else\expandafter\makeboxes\fi}
|
|
|
+% \makeboxes{1.4}{i\hss f}{.7}{\ }{.7}{x}{.7}{=}{.7}{y}{.7}{\ }{2.8}{t\hss h\hss e\hss n}{.7}{\ }{3.5}{w\hss r\hss i\hss t\hss e}{.7}\relax\space.
|
|
|
+% Since we put wide and thin characters in the same box, the width of a single character box need not to be the width of the widest character.
|
|
|
+% The empirical value {\makeatletter\lst@baseemfixed}em (which is called 'base em' later) is a compromise between overlapping characters and the number of boxes not exceeding the text width, i.e.\ how many characters fit a line without getting an overfull |\hbox|.
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
+% But overlapping characters are a problem if you use many upper case letters, e.g.\ \docharbox{3}{W\hss O\hss M\hss E\hss N} --- blame me and not the women, in fact \docharbox{1.8}{M\hss E\hss N} doesn't look better.
|
|
|
+% To go around this problem the \textsf{listings} package supports more 'flexible columns' in contrast to the fixed columns above.
|
|
|
+% Arne John Glenstrup (whose idea the format is) pointed out that he had good experience with flexible columns and assembler listings.
|
|
|
+% The differences can be summed up as follows: The fixed column format ruins the nice spacing intended by the font designer, and the flexible format ruins the column alignment (possibly) intended by the programmer.
|
|
|
+% We illustrate that:
|
|
|
+% \lstset{style={},language={}}
|
|
|
+% \def\sample{\begin{lstlisting}{}^^J\ WOMEN\ \ are^^J \ \ \ \ \ \ \ MEN^^J WOMEN are^^J better MEN^^J \end{lstlisting}}
|
|
|
+% \begin{center}\begin{tabular}{c@{\qquad\quad}c@{\qquad\quad}c}
|
|
|
+% verbatim&fixed columns&flexible columns\\
|
|
|
+% &with {\makeatletter\lst@baseemfixed}em&with {\makeatletter\lst@baseemflexible}em\\ \noalign{\medskip}
|
|
|
+% \setkeys{lst}{basicstyle=\ttfamily,baseem=0.51}\lstbox\sample&\lstset{flexiblecolumns=false}\lstbox\sample&\lstset{flexiblecolumns=true}\lstbox\sample\lstset{flexiblecolumns=false}
|
|
|
+% \end{tabular}\end{center}
|
|
|
+% Hope this helps.
|
|
|
+% Note the varying numbers of spaces between 'WOMEN' and 'are' and look at the different outputs.
|
|
|
+% The flexible column format typesets all characters at their natural width.
|
|
|
+% In particular characters never overlap.
|
|
|
+% If a word needs more space than reserved ('WOMEN'), the rest of the line moves to the right.
|
|
|
+% Sometimes a following word needs less space than reserved, or there are spaces following each other.
|
|
|
+% Such 'surplus' space is used to fix the column alignment:
|
|
|
+% The blank space in the third line have been printed properly, but the two blanks in the first line have been printed as one blank space.
|
|
|
+% We can show all this more drastic if we reduce the width of a single character box:
|
|
|
+% \begin{center}\lstset{baseem={0.3,0.0}}\begin{tabular}{c@{\qquad\quad}c@{\qquad\quad}c}
|
|
|
+% &{\makeatletter\lst@baseemfixed}em&{\makeatletter\lst@baseemflexible}em\\ \noalign{\medskip}
|
|
|
+% \setkeys{lst}{basicstyle=\ttfamily,baseem=0.51}\lstbox\sample&\lstset{flexiblecolumns=false}\lstbox\sample&\lstset{flexiblecolumns=true}\lstbox\sample\lstset{flexiblecolumns=false}
|
|
|
+% \end{tabular}\end{center}
|
|
|
+% In flexible column mode the first 'MEN' moves to the left since the blanks before are $7\cdot 0.0$em$=0$em wide.
|
|
|
+% Even in flexible mode you shouldn't reduce 'base em' to less than 0.33333em ($\approx$ width of a single space).
|
|
|
+% \endgroup
|
|
|
+%
|
|
|
+% You want to know how to select the flexible column format and how to reset to fixed columns?
|
|
|
+% Try |flexiblecolumns=true| and |flexiblecolumns=false|.
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Selecting other languages}\label{uSelectingOtherLanguages}
|
|
|
+%
|
|
|
+% You already know that |language=|\meta{language name} selects programming languages --- at least Pascal and Fortran.
|
|
|
+% But that's not the whole truth.
|
|
|
+% Both languages know different dialects (= version or implementation), for example Fortran 77 and Fortran 90.
|
|
|
+% You can choose such special versions with the optional argument of |language|.
|
|
|
+% Write
|
|
|
% \begin{verbatim}
|
|
|
-% \hbox to 3.5in{
|
|
|
-% \vbox{\inputlisting{testfile.pas}}
|
|
|
-% \hss}\end{verbatim}
|
|
|
-% The \cs{hss} avoids an overfull \cs{hbox}. You can use that
|
|
|
-% construction together with \cs{fbox} to get something like
|
|
|
-% \iffalse
|
|
|
-%<*sample>
|
|
|
-% \fi
|
|
|
-% \setbox0=\vbox{\begin{listing}
|
|
|
-function Fib(integer n):integer;
|
|
|
-// Function returns the n-th Fibonacci.
|
|
|
-begin
|
|
|
- if (n<2) then return 1;
|
|
|
- else return Fib(n-1)+Fib(n-2);
|
|
|
-end;
|
|
|
-% \end{listing}
|
|
|
-% }
|
|
|
-% \iffalse
|
|
|
-%</sample>
|
|
|
-% \fi
|
|
|
-% $$\fbox{\hbox to 3.5in{\box0\hss}}$$
|
|
|
-% \item The example just presented uses \cs{inputlisting} within an
|
|
|
-% argument of a command like \cs{fbox}. It's not possible with the
|
|
|
-% listing environment! To go around this type
|
|
|
+% \lstset{language=[77]Fortran}% Fortran 77
|
|
|
+% \lstset{language=[XSC]Pascal}% Pascal XSC\end{verbatim}
|
|
|
+% to select Fortran 77 and Pascal XSC, respectively.
|
|
|
+%
|
|
|
+% We give a list of all languages and dialects supported by \texttt{lstdrvrs.dtx}.
|
|
|
+% Use the given names as (optional) values to |language|.
|
|
|
+% An 'empty' language is also defined: |\lstset{language={}}| detects no keywords, no comments, no strings, \ldots
|
|
|
+% \begin{center}
|
|
|
+% \begin{tabular}{ll}
|
|
|
+% Ada & Lisp \\
|
|
|
+% Algol (|68|,|60|) & Logo \\
|
|
|
+% C (|ANSI|,|Objective|)& Matlab \\
|
|
|
+% Cobol (|1985|,|1974|,|ibm|) & Mercury \\
|
|
|
+% Comal 80 & Modula-2 \\
|
|
|
+% C++ (|ANSI|,|Visual|) & Oberon-2 \\
|
|
|
+% csh & Pascal (|Standard|,|XSC|,|Borland6|) \\
|
|
|
+% Delphi & Perl \\
|
|
|
+% Eiffel & PL/I \\
|
|
|
+% Elan & Prolog \\
|
|
|
+% Euphoria & Simula (|67|,|CII|,|DEC|,|IBM|) \\
|
|
|
+% Fortran (|95|,|90|,|77|) & SQL \\
|
|
|
+% IDL & TeX (|plain|,|primitive|,|LaTeX|,|alLaTeX|) \\
|
|
|
+% HTML & VHDL \\
|
|
|
+% Java
|
|
|
+% \end{tabular}
|
|
|
+% \end{center}
|
|
|
+% The configuration file \texttt{listings.cfg} defines each first dialect as default dialect, i.e.\ |\lstset{language=C}| selects ANSI C.
|
|
|
+% After
|
|
|
% \begin{verbatim}
|
|
|
-% \setbox0=\vbox{
|
|
|
-% \begin{listing}
|
|
|
-%function Fib(integer n):integer;
|
|
|
-%...
|
|
|
-% \end{listing}
|
|
|
-% }% not on the same line as \end{listing}!\end{verbatim}
|
|
|
-% and then \verb!$$\fbox{\hbox to 3.5in{\box0\hss}}$$! to get
|
|
|
-% the example.
|
|
|
-% \end{itemize}
|
|
|
+% \lstset{defaultdialect=[Objective]C}\end{verbatim}
|
|
|
+% Objective-C becomes default dialect for C, but the language is \emph{not} selected with that command.
|
|
|
%
|
|
|
+% \medskip
|
|
|
+% Remark: The driver files define the languages with |\lstdefinelanguage|.
|
|
|
+% The languages have all 'bugs' coming from the language commands, e.g.\ in Ada and Matlab it is still possible that the package assumes a string where none exists.
|
|
|
+% See \texttt{lstdrvrs.dtx} for more remarks on special programming languages.
|
|
|
%
|
|
|
-% \subsection{It's not all fine}\label{ssItsNotAllFine}
|
|
|
%
|
|
|
-% Please be patient of my English.
|
|
|
+% \section{Main reference}
|
|
|
%
|
|
|
-% Not all languages have been tested fully, since I don't know all
|
|
|
-% languages well. Hope I haven't forgotten any important feature.
|
|
|
-% Tell me, if you want additional languages or more options for a
|
|
|
-% language already present. What's about Delphi, Prolog or Reduce?
|
|
|
-% \begin{itemize}
|
|
|
-% \item If you use italic cmr fonts (comments), the dollar \${} comes
|
|
|
-% out as \pounds. Change italic to slanted (\cs{slshape})
|
|
|
-% or don't use cmr fonts.
|
|
|
-% \item If you use \cs{DeclarePairedComment}, the first comment delimiter
|
|
|
-% appears not in commentstyle, e.g.\ \#\textit{ comment \#}.
|
|
|
-% \end{itemize}
|
|
|
-% You're not lucky about the listings package? You found errors?
|
|
|
-% Damn and blast it or contact me:
|
|
|
+% \newcommand\UTODO[1]{}
|
|
|
+% \newenvironment{TODO}{\begin{quote}\footnotesize To do:}{\end{quote}}
|
|
|
+% \newenvironment{macrosyntax}
|
|
|
+% {\list{}{\itemindent-\leftmargin\labelsep=0pt\relax %
|
|
|
+% \def\makelabel##1{\lstmklab##1,\relax}}}
|
|
|
+% {\endlist}
|
|
|
+% \def\lstmklab#1,#2\relax{%
|
|
|
+% \ifx\empty#2\empty %
|
|
|
+% \lstmklabb#1,,\relax %
|
|
|
+% \else
|
|
|
+% \lstmklabb#1,#2\relax %
|
|
|
+% \fi}
|
|
|
+% \def\lstmklabb#1,#2,\relax{%
|
|
|
+% \llap{\scriptsize\itshape#2}%
|
|
|
+% \rlap{\hskip-\itemindent\hskip\labelwidth\hskip\linewidth#1}}
|
|
|
+%
|
|
|
+% In this section we list all user environments, commands and keys together with their parameters and possible values.
|
|
|
+% Sometimes there are examples or more detailed information at the end of the subsections.
|
|
|
+% All user macros have the prefix \lst.
|
|
|
+% This avoids naming conflicts with other packages or document classes.
|
|
|
+%
|
|
|
+% In the sequel the label \emph{changed} indicates any change in behaviour or syntax of a command, environment or key, so read these items carefully.
|
|
|
+% Keys strongly related to special programming languages have the label \emph{lang.spec.}.
|
|
|
+% Usually they are available only if you have loaded the corresponding programming language.
|
|
|
+% All other labels should be clear.
|
|
|
+% The numbers in the right margin give the version number of introduction (either as internal or as user macro/key).
|
|
|
+%
|
|
|
+% Note that commands, environments and keys can be distinguished easily:
|
|
|
+% A command begins with a backslash and a key is presented in ''|key=|\meta{value}'' fashion.
|
|
|
+% All the rest are environments, which is in fact a single one.
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Typesetting listings}\label{uTypesettingListings}
|
|
|
+%
|
|
|
+% \begin{macrosyntax}
|
|
|
+% \item[0.1,changed] |\lstinputlisting[|\meta{key=value list}|]{|\meta{file name}|}|
|
|
|
+%
|
|
|
+% typesets the source code file using the active language and style (locally modified by the key=value list).
|
|
|
+% Empty lines at the end of listing are dropped.
|
|
|
+%
|
|
|
+% The keys |first| and |last| determines the printed line range.
|
|
|
+% Default is \emph{always} 1--9999999, where 'always' means that you can't set |first| and |last| globally.
|
|
|
+% If you don't want a whole file, you must specify the line range.
|
|
|
+% The example |\lstinputlisting[first=3,last=10]{testfile.pas}| would print lines 3,4,\ldots,10 of \texttt{testfile.pas} if file and lines are present.
|
|
|
+%
|
|
|
+% The boolean key |print| controls whether or not |\lstinputlisting| typesets a listing:
|
|
|
+% |print=false| speed up things for draft versions of your document and |print=true| typesets the stand alone files.
|
|
|
+%
|
|
|
+% Note: The keys |first|, |last| and |print| only apply to |\lstinputlisting|.
|
|
|
+%^^A
|
|
|
+%^^A TODO: That's not true.
|
|
|
+%^^A The key |first| also applies to lstlisting.
|
|
|
+%^^A It sets the line number of the first line.
|
|
|
+%^^A
|
|
|
+%
|
|
|
+% \item[0.15,changed] |lstlisting[|\meta{key=value list}|]{|\meta{name}|}|
|
|
|
+%
|
|
|
+% typesets source code between |\begin{lstlisting}{|\meta{name}|}| (+ line break) and |\end{lstlisting}|, but empty lines at the end of listing are dropped.
|
|
|
+% Characters on the same line as the end of environment are \emph{not} dropped, i.e.\ source code right before and \LaTeX\ code after the end of environment is typeset respectively executed.
|
|
|
+% If \meta{name} is not empty and the listing is not continued, the name appears in the list of listings.\\
|
|
|
+% Same named listings have common line counter, i.e.\ the second (same named) listing continues the first, the third continues the second, and so on.
|
|
|
+% There are two exceptions: An empty named listing always starts with line number 1 and is continued with listings named |{ }| (single blank space).
|
|
|
+%
|
|
|
+% The key |resetlineno| (given without any value) sets the line number of the first line to 1.
|
|
|
+% You can also specify a number, e.g.\ |resetlineno=10|.
|
|
|
+% |advancelineno=|\meta{number} advances the number of the first line by \meta{number}.
|
|
|
+% These two keys take also effect on |{}| and |{ }| named listings.
|
|
|
+%
|
|
|
+% Note: The keys |resetlineno| and |advancelineno| only apply to the environment and must be used in the optional key=value list.
|
|
|
+%
|
|
|
+% \item[0.18,new] |\lstinline|
|
|
|
+%
|
|
|
+% works like |\verb|, but uses the active language and style, of course.
|
|
|
+% You can write '|\lstinline!var i:integer;!|' and get '\lstinline!var i:integer;!'.
|
|
|
+% Note that these listings always use flexible columns and that |\lstinline| has no optional key=value list.
|
|
|
+%\UTODO{implement optional key=value list}
|
|
|
+%
|
|
|
+% \item[0.18,new] |\lstbox[|\meta{b$\vert$c$\vert$t}|]|
|
|
|
+%
|
|
|
+% is used right before |\lstinputlisting| or a listing environment.
|
|
|
+% Without |\lstbox| the listing uses a new paragraph and the complete line width, even if the listing is one character wide.
|
|
|
+% |\lstbox| returns the listing as a |\hbox|, which has the necessary width only (line numbers possibly not included).
|
|
|
+% Use this command within explicit |\hbox|es, |$$|\ldots|$$|, etc..
|
|
|
+% The optional argument gives the vertical position of the listing: bottom, center (default) or top.
|
|
|
+% \end{macrosyntax}
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{List of listings}
|
|
|
+%
|
|
|
+% \begin{macrosyntax}
|
|
|
+% \item[0.16] |\listoflistings|
|
|
|
+%
|
|
|
+% prints a list of listings.
|
|
|
+% The names are the file names or names of the listings.
|
|
|
+%
|
|
|
+% \item[0.16] |\listlistingsname|
|
|
|
+%
|
|
|
+% contains the header name, which is 'Listings' by default.
|
|
|
+% You may adjust it via |\renewcommand\listlistingsname{whatever}|.
|
|
|
+%
|
|
|
+% \item[0.19,new] |\lstname|
|
|
|
+%
|
|
|
+% contains the name of the current (last) listing in \emph{printable} form.
|
|
|
+% After |pre=\subsubsection{\lstname}| each listing begins a new subsubsection, which name is the listing name.
|
|
|
+% The key |pre| is described in section \ref{uSomeSpecialKeys}.
|
|
|
+% You can also use it to index all listings, but then you must expand the content first.
|
|
|
+% Simply write |\expandafter\index\expandafter{\lstname}| (as value to |pre| if you want).
|
|
|
+%
|
|
|
+% \item[0.19,new] |\lstintname|
|
|
|
+%
|
|
|
+% contains the name of the current (last) listing possibly in nonprintable form.
|
|
|
+% Use this macro inside |\label| and |\ref| for example.
|
|
|
+% But be aware that a reference counter must be defined --- or the label is the current section, subsection, and so on.
|
|
|
+% You might use it like this:
|
|
|
% \begin{verbatim}
|
|
|
-% [email protected]\end{verbatim}
|
|
|
+% \lstset{pre=\caption{\lstname}\label{lst\lstintname}}
|
|
|
%
|
|
|
+% \begin{figure}
|
|
|
+% \begin{lstlisting}{Empty}
|
|
|
+% \end{lstlisting}
|
|
|
+% \end{figure}
|
|
|
+%
|
|
|
+% Figure \ref{lstEmpty} shows an empty listing.\end{verbatim}
|
|
|
+% Here \emph{all} listings get a caption and a label (unless |pre| is redefined).
|
|
|
+% \end{macrosyntax}
|
|
|
%
|
|
|
-% \StopEventually{}
|
|
|
%
|
|
|
+% \subsection{Basic style keys}\label{uBasicStyleKeys}
|
|
|
%
|
|
|
-% \section{How the package works}
|
|
|
+% \begin{macrosyntax}
|
|
|
+% \item[0.18,new] |basicstyle=|\meta{basic style and size}
|
|
|
+% \item[0.11] |keywordstyle=|\meta{style for keywords}
|
|
|
+% \item[0.19,new,optional] |ndkeywordstyle=|\meta{style for second keywords}
|
|
|
+% \item[0.19,new,optional] |rdkeywordstyle=|\meta{style for third keywords}
|
|
|
+% \item[0.18,new] |nonkeywordstyle=|\meta{style}
|
|
|
+% \item[0.11] |commentstyle=|\meta{style}
|
|
|
+% \item[0.12] |stringstyle=|\meta{style}
|
|
|
+% \item[0.16] |labelstyle=|\meta{style}
|
|
|
%
|
|
|
-% What happens when a user calls \cs{inputlisting}? First we set up a
|
|
|
-% bit (execute prelisting, open input file, do other initialization)
|
|
|
-% and at the end we have to close the input file for example.
|
|
|
+% Each value of these keys determines the font and size (or more general style) in which special parts of a listing appear.
|
|
|
+% The \emph{last} token of the (non,nd,rd) keyword and label style might be an one-parameter command like |\textbf| or |\underline|.
|
|
|
%
|
|
|
+% \item[0.16,bug] |labelstep=|\meta{step}
|
|
|
%
|
|
|
-% \subsection{The main idea}\label{TheMainIdea}
|
|
|
-% The interesting part is the loop between: The source file is read,
|
|
|
-% processed and typeset line by line. Before looking closer we have to
|
|
|
-% deal with the alignment of columns, since this influences processing
|
|
|
-% and typesetting. The problem: I don't like listings, which are
|
|
|
-% printed with typewriter fonts. But only in these fonts all characters
|
|
|
-% have the same width. So we have to handle different widths.
|
|
|
-% The Pascal source lines
|
|
|
+% No line numbers are printed if \meta{step} is zero.
|
|
|
+% Otherwise all lines with ''line number $\equiv 0$ modulo \meta{step}'' get a label, which appearance is controlled by the label style.
|
|
|
+%
|
|
|
+% Bug: If a comment (or string) goes over several lines, the line numbers (if on) also have comment (string) style.
|
|
|
+% The easiest work-around is possibly the use of |\normalfont| in |\lstlabelstyle|.
|
|
|
+%
|
|
|
+% \item[0.12] |blankstring=|\meta{true$\vert$false}
|
|
|
+%
|
|
|
+% let blank spaces in strings appear as blank spaces respectively as \textvisiblespace.
|
|
|
+% The latter is predefined.
|
|
|
+%
|
|
|
+% \item[0.12] |tabsize=|\meta{number}
|
|
|
+%
|
|
|
+% sets tabulator stops at columns $n+1$, $2n+1$, $3n+1$, etc. if $n=$\meta{number}.
|
|
|
+% Each tabulator in a listing moves the current column to the next tabulator stop.
|
|
|
+% It is initialized with |tabsize=8|.
|
|
|
+%
|
|
|
+% \item[0.19,new] |formfeed=|\meta{token sequence}
|
|
|
+%
|
|
|
+% Whenever a listing contains a form feed \meta{token sequence} is executed.
|
|
|
+% It is initialized with |formfeed=\bigbreak|.
|
|
|
+% \end{macrosyntax}
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Fixed and flexible columns}
|
|
|
+%
|
|
|
+% \begin{macrosyntax}
|
|
|
+% \item[0.18,new] |flexiblecolumns=|\meta{true$\vert$false}
|
|
|
+%
|
|
|
+% selects the flexible respectively the fixed column format.
|
|
|
+%
|
|
|
+% \item[0.16,addon] |baseem=|\meta{width in units of em}\quad or\quad|baseem={|\meta{fixed}|,|\meta{flexible mode}|}|
|
|
|
+%
|
|
|
+% sets the width of a single character box for fixed and flexible mode (both to the same value or individually).
|
|
|
+% It's pre-defined via |baseem={|{\makeatletter\lst@baseemfixed}|,|{\makeatletter\lst@baseemflexible}|}|.
|
|
|
+% \end{macrosyntax}
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Listing alignment}\label{uListingAlignment}
|
|
|
+%
|
|
|
+% \begin{macrosyntax}
|
|
|
+% \item[0.19,new] |indent=|\meta{dimension}
|
|
|
+%
|
|
|
+% indents each listing by \meta{dimension}, which is initialized with 0pt.
|
|
|
+% This command is the best way to move line numbers (and the listing) to the right.
|
|
|
+%
|
|
|
+% \item[0.19,new] |wholeline=|\meta{true$\vert$false}
|
|
|
+%
|
|
|
+% prevents or lets the package use indention from list environments like \texttt{enumerate} or \texttt{itemize}.
|
|
|
+%
|
|
|
+% \item[0.16,bug,addon] |spread=|\meta{dimension}\quad or\quad|spread={|\meta{inner}|,|\meta{outer}|}|
|
|
|
+%
|
|
|
+% defines \emph{additional} line width for listings, which may avoid overfull |\hbox|es if a listing has long lines.
|
|
|
+% The inner and outer spread is given explicitly or is equally shared.
|
|
|
+% It is initialized via |spread=0pt|.
|
|
|
+% For one sided documents 'inner' and 'outer' have the effect of 'left' and 'right'.
|
|
|
+% Note that |\lstbox| doesn't use this spread but |indent| (which is always 'left').
|
|
|
+%
|
|
|
+% Bug (two sided documents):
|
|
|
+% At top of page it's possible that the package uses inner instead of outer spread or vice versa.
|
|
|
+% This happens when \TeX\ finally moves one or two source code lines to the next page, but hasn't decided it when the \textsf{listings} package processes them.
|
|
|
+% Work-around: interrupt the listing and/or use an explicit |\newpage|.
|
|
|
+%
|
|
|
+% \item[0.17] |lineskip=|\meta{additional space between lines}
|
|
|
+%
|
|
|
+% specifies the additional space between lines in listings.
|
|
|
+% You may write |lineskip=-1pt plus 1pt minus 0.5pt| for example, but 0pt is the default.
|
|
|
+%
|
|
|
+% \item[0.19,new] |outputpos=|\meta{c$\vert$l$\vert$r}
|
|
|
+%
|
|
|
+% controls horizontal orientation of smallest output units (keywords, identifiers, etc.).
|
|
|
+% The arguments work as follows, where vertical bars visualize the effect:
|
|
|
+% $\vert$\hbox to 4.2em{\hss l\hss i\hss s\hss t\hss i\hss n\hss g\hss }$\vert$,
|
|
|
+% $\vert$\hbox to 4.2em{l\hss i\hss s\hss t\hss i\hss n\hss g\hss }$\vert$ and
|
|
|
+% $\vert$\hbox to 4.2em{\hss l\hss i\hss s\hss t\hss i\hss n\hss g}$\vert$
|
|
|
+% in fixed column mode resp.\
|
|
|
+% $\vert$\hbox to 3.15em{\hss listing\hss}$\vert$,
|
|
|
+% $\vert$\hbox to 3.15em{listing\hss}$\vert$ and
|
|
|
+% $\vert$\hbox to 3.15em{\hss listing}$\vert$
|
|
|
+% with flexible columns (using pre-defined |baseem|).
|
|
|
+% By default the output is centered.
|
|
|
+% To make all things clear: You may write |outputpos=c|, |outputpos=l| or |outputpos=r|.
|
|
|
+% \end{macrosyntax}
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Escaping to \LaTeX}
|
|
|
+%
|
|
|
+% \textbf{Note:} {\itshape Any escape to \LaTeX\ may disturb the column alignment since the package can't control the spacing there.}
|
|
|
+% \begin{macrosyntax}
|
|
|
+% \item[0.18,new] |texcl=|\meta{true$\vert$false}
|
|
|
+%
|
|
|
+% activates or deactivates \LaTeX\ comment lines, see the example below.
|
|
|
+%
|
|
|
+% \item[0.19,new] |mathescape=|\meta{true$\vert$false}
|
|
|
+%
|
|
|
+% activates or deactivates special behaviour of the dollar sign.
|
|
|
+% If activated, a dollar sign acts as \TeX's text math shift (not display style!).
|
|
|
+%
|
|
|
+% \item[0.19,new] |escapechar=|\meta{single character} (or empty)
|
|
|
+%
|
|
|
+% The given character escapes the user to \LaTeX:
|
|
|
+% All code between two such characters is interpreted as \LaTeX\ code.
|
|
|
+% Note that \TeX's special characters must be entered with a preceding backslash, e.g.\ |escapechar=\%|.
|
|
|
+% \end{macrosyntax}
|
|
|
+% Some examples clarify these commands.
|
|
|
+% Since |texcl| only makes sense with comment lines, we will use C++ comment lines here (without saying how to define them).
|
|
|
+% Note that only the first example runs through a C++ compiler if the source code is placed in a separate file.
|
|
|
+% All \LaTeX\ escapes are local here, but you can also use |\lstset|.
|
|
|
+% \lstset{commentline=//}
|
|
|
+% \begin{lstsample}{}
|
|
|
+%\begin{lstlisting}[texcl]{}
|
|
|
+%// calculate $a_{ij}$
|
|
|
+% A[i][j] = A[j][j]/A[i][j];
|
|
|
+%\end{lstlisting}
|
|
|
+% \end{lstsample}
|
|
|
+%
|
|
|
+% \begin{lstsample}{}
|
|
|
+%\begin{lstlisting}[mathescape]{}
|
|
|
+%// calculate $a_{ij}$
|
|
|
+% $a_{ij} = a_{jj}/a_{ij}$;
|
|
|
+%\end{lstlisting}
|
|
|
+% \end{lstsample}
|
|
|
+%
|
|
|
+% \begin{lstsample}{}
|
|
|
+%\lstset{escapechar=\%}
|
|
|
+%\begin{lstlisting}{}
|
|
|
+%// calc%ulate $a_{ij}$%
|
|
|
+% %$a_{ij} = a_{jj}/a_{ij}$%;
|
|
|
+%\end{lstlisting}
|
|
|
+% \end{lstsample}
|
|
|
+% \lstset{commentline={}}
|
|
|
+% \noindent
|
|
|
+% In the first example the whole comment line is typset in '\LaTeX\ mode' --- except the comment line indicators |//|.
|
|
|
+% Note that |texcl| uses comment style.
|
|
|
+% In the second example the comment line upto $a_{ij}$ have been typeset in comment style and by the \textsf{listings} package.
|
|
|
+% The '$a_{ij}$' itself is typeset in '\TeX\ math mode' without comment style.
|
|
|
+% About the half comment line of the third example have been typeset by this package.
|
|
|
+% The rest is in '\LaTeX\ mode' without comment style.
|
|
|
+%
|
|
|
+% To avoid problems with the current and future version of this package:
|
|
|
+% \begin{enumerate}
|
|
|
+% \item Don't use any command of the \textsf{listings} package when you have escaped to \LaTeX.
|
|
|
+% \item Any environment must start and end inside the same escape.
|
|
|
+% \item You might use |\def|, |\edef|, etc., but do not assume that the definitions are present later --- except they are |\global|.
|
|
|
+% \item |\if \else \fi|, groups, math shifts |$| and |$$|, \ldots\ must be balanced each escape.
|
|
|
+% \item \ldots
|
|
|
+% \end{enumerate}
|
|
|
+% Expand that list yourself and mail me about new items.
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Some special keys}\label{uSomeSpecialKeys}
|
|
|
+%
|
|
|
+% \begin{macrosyntax}
|
|
|
+% \item[0.18,new] |extendedchars=|\meta{true$\vert$false}
|
|
|
+%
|
|
|
+% allows or prohibits extended characters in listings, i.e.\ characters with codes 128--255.
|
|
|
+% If you use extended characters, you should load the \texttt{inputenc} or \texttt{fontenc} package!
|
|
|
+%
|
|
|
+% \item[0.19,new,lang.spec.]|printpod=|\meta{true$\vert$false}
|
|
|
+%
|
|
|
+% prints or drops PODs in Perl.
|
|
|
+%
|
|
|
+% \item[0.12,addon] |pre=[|\meta{continue}|]{|\meta{commands to execute}|}|
|
|
|
+% \item[0.12,addon] |post=[|\meta{continue}|]{|\meta{commands to execute}|}|
|
|
|
+%
|
|
|
+% The given control sequences are executed before and after typesetting resp.\ when continuing a listing, but in all cases inside a group.
|
|
|
+% The commands are not executed if you use |\lstbox| or |\lstinline| (since the user given pre and post commands are assumed to be unsave inside |\hbox|).
|
|
|
+% By default \meta{continue} is empty.
|
|
|
+% The other arguments are pre-set empty.
|
|
|
+% \end{macrosyntax}
|
|
|
+%
|
|
|
+% \begin{lstsample}{}
|
|
|
+%\lstset{flexiblecolumns}
|
|
|
+%\lstset{pre=[%
|
|
|
+% We continue the listing.
|
|
|
+% ]A simple prelisting example.}
|
|
|
+%\begin{lstlisting}{}
|
|
|
+%{ Get listings.dtx. Now! }
|
|
|
+%\end{lstlisting}
|
|
|
+%
|
|
|
+%\begin{lstlisting}{ }
|
|
|
+%{ You have it already? Good. }
|
|
|
+%\end{lstlisting}
|
|
|
+%
|
|
|
+%\begin{lstlisting}{ }
|
|
|
+%{ Tell your friends about it. }
|
|
|
+%\end{lstlisting}
|
|
|
+% \end{lstsample}
|
|
|
+%\lstset{style={}}
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Languages and styles}\label{uLanguagesAndStyles}
|
|
|
+%
|
|
|
+% \begin{macrosyntax}
|
|
|
+% \item[0.17,changed] |language=[|\meta{dialect}|]|\meta{language name}
|
|
|
+%
|
|
|
+% activates a (dialect of a) programming language.
|
|
|
+% All arguments are case \emph{insensitive} here.
|
|
|
+%
|
|
|
+% \item[0.19,new] |\lstloadlanguages{|\meta{list of languages}|}|
|
|
|
+%
|
|
|
+% can only be used in the preamble.
|
|
|
+% It loads all specified languages, where each language is given in the form |[|\meta{dialect}|]|\meta{language}.
|
|
|
+% List of languages means a comma separated list.
|
|
|
+%
|
|
|
+% \item[0.18,new] |style=|\meta{style name}
|
|
|
+%
|
|
|
+% activates a style.
|
|
|
+% The arguments is case \emph{insensitive}.
|
|
|
+%
|
|
|
+% \item[0.19,new] |\lstdefinestyle{|\meta{style name}|}{|\meta{key=value list}|}|
|
|
|
+%
|
|
|
+% stores the key=value list: You can select the style via |style| using te style name as argument.
|
|
|
+% \end{macrosyntax}
|
|
|
+% After package loading a 'standard' style and an 'empty' language are active.
|
|
|
+% The style is defined as follows.
|
|
|
% \begin{verbatim}
|
|
|
-% if x=y then write('alignment')
|
|
|
-% else print('alignment');\end{verbatim}
|
|
|
-% shouldn't come out as
|
|
|
-% \begin{center}\hfill
|
|
|
-% \begin{tabular}{l}
|
|
|
-% if\ x=y\ then\ write('alignment')\\
|
|
|
-% \ \ \ \ \ \ \ else\ print('alignment');
|
|
|
-% \end{tabular}
|
|
|
-% \hfill or \hfill
|
|
|
-% \begin{tabular}{l@{\space}l@{\space}l}
|
|
|
-% \textbf{if} x=y&\textbf{then}&\textbf{write}('alignment')\\
|
|
|
-% &\textbf{else}&print('alignment');
|
|
|
-% \end{tabular}\hfill
|
|
|
-% \end{center}
|
|
|
-% only because blank spaces are not wide enough or because a bold
|
|
|
-% letter is wider than a normal one.
|
|
|
-% There is a simple trick to avoid things like that. We make boxes of
|
|
|
-% the same width and put one character in each box:
|
|
|
-% \begin{center}
|
|
|
-% \vbox{\def\makeboxes#1{\fbox{\hbox to 1em{\hss\vphantom{fy}#1\ignorespaces%
|
|
|
-% \hss}}\ifx#1\relax\else\expandafter\makeboxes\fi}
|
|
|
-% \makeboxes if\ x=y\ then\ write\relax\space\ldots\\
|
|
|
-% \makeboxes \ \ \ \ \ \ \ else \ print\relax\space\ldots}
|
|
|
-% \end{center}
|
|
|
-% Going this way the alignment of columns can't be disturbed. But if
|
|
|
-% the boxes are not wide enaugh, we get
|
|
|
-% \begin{center}
|
|
|
-% \def\makeboxes#1{\hbox{\hbox to 0.45em{\hss\vphantom{fy}#1\ignorespaces%
|
|
|
-% \hss}}\ifx#1\relax\else\expandafter\makeboxes\fi}
|
|
|
-% \begin{tabular}{l}
|
|
|
-% \makeboxes if\ x=y\ then\ write\relax\space\ldots
|
|
|
-% \end{tabular}
|
|
|
-% \end{center}
|
|
|
-% And choosing the width so that the widest character fits in, leads to
|
|
|
-% \begin{center}
|
|
|
-% \def\makeboxes#1{\hbox to 1em{\hss\vphantom{fy}#1\hss}\ignorespaces%
|
|
|
-% \ifx#1\relax\else\expandafter\makeboxes\fi}
|
|
|
-% \begin{tabular}{l}
|
|
|
-% \makeboxes if\ x=y\ then\ write\relax\space\ldots
|
|
|
-% \end{tabular}
|
|
|
-% \end{center}
|
|
|
-% Both are not acceptable. So there is more to do. Each input line
|
|
|
-% will be cut up in units. Since we want to scan for keywords, this
|
|
|
-% is no extra work. In the example the units are
|
|
|
-% \begin{center}\begin{tabular}{ccccccc}
|
|
|
-% if, & x, & =, & y, & then, & write, & \ldots
|
|
|
-% \end{tabular}\end{center}
|
|
|
-% and the blank spaces between. We put each unit in a box, which width
|
|
|
-% is multiplied by the number of characters we put in, of course. The
|
|
|
-% result is
|
|
|
+% \lstdefinestyle{}
|
|
|
+% {basicstyle={},
|
|
|
+% keywordstyle=\bfseries,nonkeywordstyle={},
|
|
|
+% commentstyle=\itshape,
|
|
|
+% stringstyle={},
|
|
|
+% labelstyle={},labelstep=0
|
|
|
+% }\end{verbatim}
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Language definitions}
|
|
|
+%
|
|
|
+% \begin{macrosyntax}
|
|
|
+% \item[0.19,new] |\lstdefinelanguage[|\meta{dialect}|]{|\meta{language}|}{|\meta{key=value list}|}|
|
|
|
+%
|
|
|
+% defines a programming language.
|
|
|
+% Use any 'language' key=value list and the definition is yours.
|
|
|
+%
|
|
|
+% \item[0.19,new] |\lstdefinedrvlanguage[|\meta{dialect}|]{|\meta{language}|}{|\meta{key=value list}|}|
|
|
|
+%
|
|
|
+% defines a programming language only if the user has requested the language.
|
|
|
+% Thus this command can only be used in driver files.
|
|
|
+%
|
|
|
+% \item[0.19,new] |defaultdialect=[|\meta{dialect}|]|\meta{language}
|
|
|
+%
|
|
|
+% defines a default dialect for a language, that means a dialect which is selected whenever you leave out the optional dialect.
|
|
|
+% If you have defined a default dialect other than empty, for example |defaultdialect=[iama]fool|, you can't select the 'empty' dialect, even not with |language=[]fool|.
|
|
|
+%
|
|
|
+% Note that a configuration file possibly defines some default dialects.
|
|
|
+%
|
|
|
+% \item[0.18,new] |\lstalias{|\meta{alias}|}{|\meta{language}|}|
|
|
|
+%
|
|
|
+% defines an alias for a programming language.
|
|
|
+% Any dialect of \meta{alias} selects in fact the same dialect of \meta{language}.
|
|
|
+% It's also possible to define an alias for one dialect: |\lstalias[|\meta{dialect alias}|]{|\meta{alias}|}[|\meta{dialect}|]{|\meta{language}|}|.
|
|
|
+% Here all four parameters are \emph{non}optional.
|
|
|
+% An alias with empty \meta{dialect} will select the default dialect.
|
|
|
+% Note that aliases can't be nested: The two aliases |\lstalias{foo1}{foo2}| and |\lstalias{foo2}{foo3}| redirect |foo1| not to |foo3|.
|
|
|
+%
|
|
|
+% Note that a configuration file possibly defines some aliases.
|
|
|
+%
|
|
|
+% \item[0.18,new] |\lststorekeywords|\meta{macro}|{|\meta{keywords}|}|
|
|
|
+%
|
|
|
+% stores \meta{keywords} in \meta{macro} for use with keyword keys.
|
|
|
+% This command can't be used in a language definition since it is a command and not a key.
|
|
|
+% \end{macrosyntax}
|
|
|
+%
|
|
|
+% Now come all the language keys, which might be used in the key=value list of |\lstdefinelanguage|.
|
|
|
+% Note: {\itshape If you want to enter {\upshape|\|, |{|, |}|, |%|, |#|} or {\upshape|&|} inside or as an argument here, you must do it with a preceding backslash!}
|
|
|
+%
|
|
|
+% \begin{macrosyntax}
|
|
|
+% \item[0.11] |keywords={|\meta{keywords}|}|
|
|
|
+% \item[0.11] |morekeywords={|\meta{additional keywords}|}|
|
|
|
+% \item[0.18,new] |deletekeywords={|\meta{keywords to remove}|}|
|
|
|
+%
|
|
|
+% \item[0.19,new,optional] |ndkeywords={|\meta{second keywords}|}|
|
|
|
+% \item[0.19,new,optional] |morendkeywords={|\meta{additional second keywords}|}|
|
|
|
+% \item[0.19,new,optional] |deletendkeywords={|\meta{second keywords to remove}|}|
|
|
|
+%
|
|
|
+% \item[0.19,new,optional] |rdkeywords={|\meta{third keywords}|}|
|
|
|
+% \item[0.19,new,optional] |morerdkeywords={|\meta{additional third keywords}|}|
|
|
|
+% \item[0.19,new,optional] |deleterdkeywords={|\meta{third keywords to remove}|}|
|
|
|
+%
|
|
|
+% Each 'keyword' argument (here and below) is a list of keywords separated by commas.
|
|
|
+% You might use macros defined with |\lststorekeywords| as elements (i.e.\ also separated by commas).
|
|
|
+% |keywords={save,Test,test}| defines three keywords (if keywords are case sensitive).
|
|
|
+% If you want to remove them all, simply write |keywords={}| --- in |\lstset|'s argument, in an optional argument or in a language definition.
|
|
|
+% The characters |\|, |{|, and |}| (entered as |\\|, |\{| and |\}|) are \emph{not} allowed within a keyword.
|
|
|
+% You might use each of
|
|
|
+%^^A
|
|
|
+%^^A We need some definitions here.
|
|
|
+%^^A
|
|
|
+%\makeatletter ^^A
|
|
|
+%\def\lstspec#1{^^A
|
|
|
+% \ifx\relax#1\else ^^A
|
|
|
+% {\lstset{keywords=#1}\setbox\@tempboxa\hbox{\lstinline a#1a}}^^A
|
|
|
+% \lst@ifspec\lstinline a#1a\fi ^^A
|
|
|
+% \expandafter\lstspec ^^A
|
|
|
+% \fi}^^A
|
|
|
+%\lst@AddToHook{Output}{\lstspectest}^^A
|
|
|
+%\gdef\lstspecfalse{\global\let\lst@ifspec\iffalse}^^A
|
|
|
+%\gdef\lstspectest{^^A
|
|
|
+% \global\let\lst@ifspec=\iftrue ^^A
|
|
|
+% \ifx\lst@thestyle\lst@keywordstyle\else ^^A
|
|
|
+% \lstspecfalse ^^A
|
|
|
+% \fi}^^A
|
|
|
+%\makeatother ^^A
|
|
|
+% {\lstset{language={}}^^A
|
|
|
+% \lstspec !"\#$\%\&'()*+-./:;<=>?[]^`\relax.}
|
|
|
+%^^A
|
|
|
+%^^A a comma also works!
|
|
|
+%^^A
|
|
|
+%^^A End of test.
|
|
|
+%^^A
|
|
|
+% But note that you must enter |\#|, |\%| and |\&| instead of |#|, |%| and |&|.
|
|
|
+%
|
|
|
+% \item[0.14] |sensitive=|\meta{true$\vert$false}
|
|
|
+%
|
|
|
+% makes the keywords (first, second and third) case sensitive resp.\ insensitive.
|
|
|
+%^^A It would be nice to have |\lst|\meta{\texttt{nd}$\vert$\texttt{rd}}|sensitive|\meta{\texttt{true}\textbar\texttt{false}}?
|
|
|
+% This key affect the keywords only in the phase of typesetting.
|
|
|
+% In all other situations keywords are case sensitive, i.e.\ |deletekeywords={save,Test}| removes 'save' and 'Test', but neither 'SavE' nor 'test'.
|
|
|
+%
|
|
|
+% \item[0.19,new] |alsoletters={|\meta{character sequence}|}|
|
|
|
+% \item[0.19,new] |alsodigits={|\meta{character sequence}|}|
|
|
|
+% \item[0.19,new] |alsoother={|\meta{character sequence}|}|
|
|
|
+%
|
|
|
+% These keys support the 'special character' auto-detection of the keyword commands.
|
|
|
+% For our purpose here, identifiers are out of letters (|A|--|Z|,|a|--|z|,|_|,|@|,|$|) and digits (|0|--|9|), but an identifier must begin with a letter.
|
|
|
+% If you write |keywords={one-two,\#include}|, the minus becomes necessarily a digit and the sharp a letter since the keywords can't be detected otherwise.
|
|
|
+% The three keys overwrite such default behaviour.
|
|
|
+% Each character of the sequence becomes a letter, digit and other, respectively.
|
|
|
+% Note that the auto-detection might fail if you remove keywords and always fails if you use special characters not listed above.
|
|
|
+%^^A
|
|
|
+%^^A TODO: This is mainly due to improper \lst@ReplaceIn inside ..MakeKeywordArg..
|
|
|
+%^^A
|
|
|
+%
|
|
|
+% \item[0.19,new] |stringtest=|\meta{true$\vert$false}
|
|
|
+%
|
|
|
+% enables or disables string tests:
|
|
|
+% If activated, line exceeding strings issue warnings and the package exits string mode.
|
|
|
+%
|
|
|
+% \item[0.12,addon] |stringizer=[|\meta{b$\vert$d$\vert$m$\vert$bd}|]{|\meta{character sequence}|}|
|
|
|
+%
|
|
|
+% Each character might start a string or character literal.
|
|
|
+% 'Stringizers' match each other, i.e.\ starting and ending delimiters are the same.
|
|
|
+% The optional argument controls how the stringzier(s) itself is/are represented in a string or character literal:
|
|
|
+% It is preceded by a |b|ackslash, |d|oubled (or both is allowed via |bd|) or it is |m|atlabed.
|
|
|
+% The latter one is a special type for Ada and Matlab and possibly more languages, where the stringizers are also used for other purposes.
|
|
|
+% In general the stringizer is also doubled, but a string does not start after a letter or a right parenthesis.
|
|
|
+%
|
|
|
+% \item[0.19,new,lang.spec.] |texcs={|\meta{list of control sequences \textup(without backslashes\textup)}|}|
|
|
|
+%
|
|
|
+% defines control sequences for \TeX\ and \LaTeX.
|
|
|
+%
|
|
|
+% \item[0.18,new,lang.spec.] |cdirectives={|\meta{list of compiler directives}|}|
|
|
|
+%
|
|
|
+% defines compiler directives in C, C++ and Objective-C.
|
|
|
+% \end{macrosyntax}
|
|
|
+% If you have already defined any of the following comments and you want to remove it, let all arguments to the comment key empty.
|
|
|
+% \begin{macrosyntax}
|
|
|
+% \item[0.13,changed] |commentline=|\meta{1or2 chars}
|
|
|
+%
|
|
|
+% The characters (\emph{in the given order}) start a comment line, which in general starts with the comment separator and ends at end of line.
|
|
|
+% If the character sequence |//| starts a comment line (like in C++, Comal 80 or Java), |commentline=//| is the correct declaration.
|
|
|
+% For Matlab it would be |commentline=\%| --- note the preceding backslash.
|
|
|
+%
|
|
|
+% \item[0.18,new] |fixedcommentline=[|\meta{n=preceding columns}|]{|\meta{character sequence}|}|
|
|
|
+%
|
|
|
+% Each given character becomes a 'fixed comment line' separator: It starts a comment line if and only if it is in column $n+1$.
|
|
|
+% Fortran 77 declares its comments via |fixedcommentline={*Cc}| ($n=0$ is default).
|
|
|
+%
|
|
|
+% \item[0.13,changed] |singlecomment={|\meta{1or2 chars}|}{|\meta{1or2 chars}|}|
|
|
|
+% \item[0.13,changed] |doublecomment={|\meta{1or2 chars}|}{|\meta{1or2 chars}|}{|\meta{1or2 chars}|}{|\meta{1or2 chars}|}|
|
|
|
+%
|
|
|
+% Here we have two or four comment separators.
|
|
|
+% The first starts and the second ends a comment, and similarly the third and fourth separator for double comments.
|
|
|
+% If you need three such comments use |singlecomment| and |doublecomment| at the same time.
|
|
|
+% C, Java, PL/I, Prolog and SQL all define single comments via |singlecomment={/*}{*/}|, and Algol does it with |singlecomment={\#}{\#}|, which means that the sharp delimits both beginning and end of a single comment.
|
|
|
+%
|
|
|
+% \item[0.13,changed] |nestedcomment={|\meta{1or2 chars}|}{|\meta{1or2 chars}|}|
|
|
|
+%
|
|
|
+% is similar to |singlecomment|, but comments can be nested.
|
|
|
+% Identical arguments are not allowed --- think a while about it!
|
|
|
+% Modula-2 and Oberon-2 use |nestedcomment={(*}{*)}|.
|
|
|
+%
|
|
|
+% \item[0.17,lang.spec.] |keywordcomment={|\meta{keywords}|}|
|
|
|
+% \item[0.17,lang.spec.] |doublekeywordcommentsemicolon={|\meta{keywords}|}{|\meta{keywords}|}{|\meta{keywords}|}|
|
|
|
+%
|
|
|
+% A (paired) keyword comment begins with a keyword and ends with the same keyword.
|
|
|
+% Consider |keywordcomment={comment,co}|.
|
|
|
+% Then '\textbf{comment}\allowbreak\ldots\textbf{comment}' and '\textbf{co}\ldots\textbf{co}' are comments.\\
|
|
|
+%^^A
|
|
|
+% Defining a double keyword comment (semicolon) needs three keyword lists, e.g.\ |{end}{else,end}{comment}|.
|
|
|
+% A semicolon always ends such a comment.
|
|
|
+% Any keyword of the first argument begins a comment and any keyword of the second argument ends it (and a semicolon also); a comment starting with any keyword of the third argument is terminated with the next semicolon only.
|
|
|
+% In the example all possible comments are '\textbf{end}\ldots\textbf{else}', '\textbf{end}\ldots\textbf{end}' (does not start a comment again) and '\textbf{comment}\ldots;' and '\textbf{end}\ldots;'.
|
|
|
+% Maybe a curious definition, but Algol and Simula use such comments.\\
|
|
|
+%^^A
|
|
|
+% Note: The keywords here need not to be a subset of the defined keywords.
|
|
|
+% They won't appear in keyword style if they aren't.
|
|
|
+% \end{macrosyntax}
|
|
|
+%
|
|
|
+%
|
|
|
+% \section{Experimental features}
|
|
|
+%
|
|
|
+% This section describes the more or less unestablished parts of the \textsf{listings} package.
|
|
|
+% It's unlikely that they are removed, but they are liable to (heavy) changes and maybe improvements.
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Interface to \textsf{fancyvrb}}
|
|
|
+%
|
|
|
+% The \textsf{fancyvrb} package --- fancy verbatims --- from Timothy van Zandt provides macros for reading, writing and typesetting verbatim code.
|
|
|
+% It has some remarkable features the \textsf{listings} package doesn't have --- some are also possible with \textsf{listings}, but you must find somebody who implements them ; -- ).
|
|
|
+% The \textsf{fancyvrb} package is available from \texttt{CTAN: macros/latex/contrib/supported/fancyvrb}.
|
|
|
+%
|
|
|
+% \begin{macrosyntax}
|
|
|
+% \item [0.19,new]|fancyvrb=|\meta{true$\vert$false}
|
|
|
+%
|
|
|
+% activates or deactivates the interface.
|
|
|
+% This defines an appropiate version of |\FancyVerbFormatLine| to make the two packages work together.
|
|
|
+% If active, the verbatim code read by the \textsf{fancyvrb} package is typeset by the \textsf{listings} package, i.e.\ with emphasized keywords, strings, comments, and so on.
|
|
|
+% --- You should know that |\FancyVerbFormatLine| is responsible for the typesetting a single code line.
|
|
|
+%
|
|
|
+% If \textsf{fancyvrb} and \textsf{listings} provide similar functionality, use \textsf{fancyvrb}'s.
|
|
|
+%
|
|
|
+% Note that this is the first interface.
|
|
|
+% It works only with |Verbatim|, neither with |BVerbatim| nor |LVerbatim|.
|
|
|
+% And you shouldn't use \textsf{defineactive}. (As I can see it doesn't matter since it does nothing at all.)
|
|
|
+% I hope to remove some restrictions in future.
|
|
|
+% \end{macrosyntax}
|
|
|
+%
|
|
|
+% \iffancyvrb
|
|
|
+% \begin{lstsample}{}
|
|
|
+%\lstset{commentline=\ }% :-)
|
|
|
+%
|
|
|
+%\begin{Verbatim}[commandchars=\\\{\}]
|
|
|
+%First verbatim line.
|
|
|
+%\fbox{Second} verbatim line.
|
|
|
+%\end{Verbatim}
|
|
|
+%
|
|
|
+%\lstset{fancyvrb}
|
|
|
+%\begin{Verbatim}[commandchars=\\\{\}]
|
|
|
+%First verbatim line.
|
|
|
+%\fbox{Second} verbatim line.
|
|
|
+%\end{Verbatim}
|
|
|
+%\lstset{fancyvrb=false}
|
|
|
+% \end{lstsample}
|
|
|
+% \noindent
|
|
|
+% The last two lines are wider than the first two since |baseem| equals not the width of a single typewriter character.
|
|
|
+% \else
|
|
|
% \begin{center}
|
|
|
-% \def\makeboxes#1#2{\fbox{\hbox to #1em{\hss\vphantom{fy}#2\hss}\ignorespaces%
|
|
|
-% }\ifx#2\relax\else\expandafter\makeboxes\fi}
|
|
|
-% \begin{tabular}{l}
|
|
|
-% \makeboxes2{i\hss f}1{\ }1{x}1{=}1{y}1{\ }4{t\hss h\hss e\hss n}%
|
|
|
-% 1{\ }5{w\hss r\hss i\hss t\hss e}1\relax\space\ldots
|
|
|
-% \end{tabular}
|
|
|
+% \textsf{fancyvrb} seems to be unavailable on your platform, thus the example couldn't be printed here.
|
|
|
% \end{center}
|
|
|
-% Now we are ready to choose the base width of a box --- that's
|
|
|
-% \cs{lstbaseem}. Consider the 'write'. The 'w' needs more space than
|
|
|
-% base width, but the 'i' needs less. This will compensate each other,
|
|
|
-% because we put them in the same box. In general: Since wide characters
|
|
|
-% use space actually reserved for thin characters, the base width need
|
|
|
-% not to be the width of the widest character. This would be 1em
|
|
|
-% (a \cs{quad}). At the moment most languages use the empirical value
|
|
|
-% 0.6em. It's a compromise between overlapping characters and the
|
|
|
-% number of boxes exceeding not the textwidth, i.e.\ how many
|
|
|
-% characters fit a line without getting an overfull \verb!\hbox!.
|
|
|
+% \fi
|
|
|
%
|
|
|
-%
|
|
|
-% \subsection{Line processing}
|
|
|
-% Let's discuss the line processing. The job is to classify comments,
|
|
|
-% strings and other source code, where we search for keywords. We do
|
|
|
-% that in several steps.
|
|
|
-% \begin{itemize}
|
|
|
-% \item First we pay attention on comments, which started in preceding
|
|
|
-% lines, e.g.\
|
|
|
-% \begin{verbatim}
|
|
|
-% comment } for i:=1 to maxint do ...\end{verbatim}
|
|
|
-% In that case we look for the end of comment and output the comment.
|
|
|
-% If there is other source code left, we run the line processing on
|
|
|
-% that code.
|
|
|
-% \item If no comment is in work, we look for one and split the input
|
|
|
-% into comment and other source code. Since the other code comes
|
|
|
-% first, we give it to a routine, which cuts it into the units
|
|
|
-% described above (tokenizing). The output takes place there.
|
|
|
-% \item Afterwards we have to output the comment. But when we look for
|
|
|
-% a comment, we don't take notice of other things. Consider
|
|
|
-% \begin{verbatim}
|
|
|
-% writeln('This is a string { and not a comment }');\end{verbatim}
|
|
|
-% We cut this line at the left brace into other code and comment.
|
|
|
-% After typesetting the other code we notice, that a string started,
|
|
|
-% but hasn't been finished. Our first classification was wrong.
|
|
|
-% We use the comment as new input and simply run the line processing
|
|
|
-% again to continue the string.
|
|
|
-% \item If all strings are finished, we can output the comment, since
|
|
|
-% it's really a comment.
|
|
|
-% \end{itemize}
|
|
|
-% This is a sketch of line processing. For more detailed information
|
|
|
-% see section \ref{ssLineProcessing}, where the implementation is
|
|
|
-% described.
|
|
|
-%
|
|
|
-% One question about the third item is left: Why do we cut off a
|
|
|
-% comment, even if we don't know that it is a comment? It's a matter
|
|
|
-% of modularity and extension. Consider the alternative: The tokenize
|
|
|
-% routine below (where we cut the classified input into the smallest
|
|
|
-% units) would have to look for the start and end of comment.
|
|
|
-% To support different languages we have to write either more than one
|
|
|
-% tokenize routine or one, which handles comments of all languages.
|
|
|
-% Adding another language means extending tokenizing or writing a new
|
|
|
-% routine, which looks only for the particular comment. But finding a
|
|
|
-% comment has nearly nothing to do with looking for delimiters (blank
|
|
|
-% space, comma, plus, bracket, etc.). So we write exactly one tokenize
|
|
|
-% macro and separate this from finding a comment.
|
|
|
-%
|
|
|
-%
|
|
|
-% \subsection{Tokenizing}
|
|
|
-% The next step is breaking up the parts produced by line processing
|
|
|
-% into the units mentioned above. We gather all characters, until
|
|
|
-% reaching a nonletter. Then we output the collected characters using
|
|
|
-% a routine, which selects the right style (comment, keyword, string).
|
|
|
-% Afterwards we handle the nonletter:
|
|
|
-%
|
|
|
-% If it is a stringizer, we switch a string boolean to indicate whether
|
|
|
-% we are in string mode or not. This boolean is also used by the line
|
|
|
-% processing.
|
|
|
-%
|
|
|
-% If we found a tabulator, we go to the next tabulator stop. The output
|
|
|
-% routines are responsible for knowing the number of blanks we need.
|
|
|
-%
|
|
|
-% If it's any other nonletter, we gather all coming nonletter (upto the
|
|
|
-% next letter, of course) and output these nonletter. Then we start
|
|
|
-% with a letter again, \ldots
|
|
|
-%
|
|
|
-%
|
|
|
-% \subsection{Special characters}\label{SpecialCharacters}
|
|
|
-% As you know some characters have a special meaning to \TeX, e.g.\ the
|
|
|
-% subscript \verb!_! or the backslash \verb!\!. \TeX{} realizes this
|
|
|
-% using so called category codes (catcodes). \TeX{} knows sixteen
|
|
|
-% different ones:
|
|
|
-% \begin{center}\begin{tabular}{rll}
|
|
|
-% 0 & escape delimiter (backslash)& \verb!\catcode`\\=0!\\
|
|
|
-% 1 & beginning of a group ($\{$)& \verb!\catcode`\{=1!\\
|
|
|
-% 2 & ending of a group ($\}$) & \verb!\catcode`\}=2!\\
|
|
|
-% 3 & mathematics shift ($\$$) & \verb!\catcode`\$=3!\\
|
|
|
-% 4 & tabulator ($\&$) & \verb!\catcode`\&=4!\\
|
|
|
-% 5 & end of line (carriage return)& \verb!\catcode`\^^M=5!\\
|
|
|
-% 6 & macro parameter (\verb!#!) & \verb!\catcode`\#=6!\\
|
|
|
-% 7 & superscript (\verb!^!) & \verb!\catcode`\^=7!\\
|
|
|
-% 8 & subscript (\verb!_!) & \verb!\catcode`\_=8!\\
|
|
|
-% 9 & ignore & \verb!\catcode`\^^@=9!\\
|
|
|
-% 10 & blank space & \verb!\catcode`\ =10!\\
|
|
|
-% 11 & letter & A..Z,a..z\\
|
|
|
-% 12 & other & \\
|
|
|
-% 13 & active (e.g.\ \verb!~!) & \\
|
|
|
-% 14 & comment & \verb!\catcode`\%=14!\\
|
|
|
-% 15 & invalid characters &
|
|
|
-% \end{tabular}\end{center}
|
|
|
-% When \TeX{} reads a character, it looks up the associated catcode and
|
|
|
-% treats the character accordingly, e.g.\ an active character stands
|
|
|
-% for a command without a leading backslash (like \verb!~! or the
|
|
|
-% double quote in \verb!german.sty!).
|
|
|
-%
|
|
|
-% We can't change catcodes of characters, which \TeX{} has already
|
|
|
-% read. But we are able to change them before. After
|
|
|
-% \verb!\catcode`\A=10! an upper 'A' has the same effect as a blank
|
|
|
-% space! Consider the \TeX source
|
|
|
-% \begin{verbatim}
|
|
|
-% \def\uppera{A} % saving upper 'A'; we shouldn't use \upperA. Why?
|
|
|
-% \catcode`\A=10 % 'A' becomes blank space. That's the reason!
|
|
|
-% MayAbeAaAcuriousAexample. \upperaAnd it work's.\end{verbatim}
|
|
|
-% The output is
|
|
|
-% \begin{verbatim}
|
|
|
-% May be a curious example. And it work's.\end{verbatim}
|
|
|
-% First we save the 'A'. Changing the catcode has no effect on the
|
|
|
-% definition in the first line, since \TeX{} has read it before. All
|
|
|
-% coming 'A' are blank spaces.
|
|
|
-%
|
|
|
-% We want to input and typeset characters 'as they are'. But the
|
|
|
-% subscript or the macro parameter character are not printable. So it
|
|
|
-% is necessary to change catcodes. We make these characters active.
|
|
|
-% We also change catcodes of printable characters, e.g.\ a digit
|
|
|
-% (normally other) will be treated as a letter, since indentifiers like
|
|
|
-% \verb!x1!, \verb!y2! are legal. Then it is possible to gather all
|
|
|
-% characters upto a nonletter to cut up a unit!
|
|
|
-%
|
|
|
-% We change catcodes for input and output. That's clear. But we also
|
|
|
-% do it to define some commands. One example: In Pascal we have to look
|
|
|
-% for \verb!{!. Let's say, we compare it with a left brace from a
|
|
|
-% source file. This only works, if both have the same meaning.
|
|
|
-% And when we declare the comment, \TeX{} must know the associated
|
|
|
-% catcode, since it can't be changed later.
|
|
|
-% Hence, we have to change it also at the time of defining the macros.
|
|
|
-%
|
|
|
-% There is at least one more thing to say: Catcodes aren't easy to
|
|
|
-% work with.
|
|
|
-%
|
|
|
-%
|
|
|
-% \section{General \TeX{}niques}
|
|
|
-%
|
|
|
-% \subsection{Macro parameter parsing}
|
|
|
-% A macro has at most nine parameters. They are numbered consecutively
|
|
|
-% and are referenced by $\#1,\ldots,\#9$. In the definition they appear
|
|
|
-% after the macro name, e.g.\
|
|
|
-% \begin{verbatim}
|
|
|
-% \def\macro#1#2#3{\textbf{#1}\texttt{#2}\textit{#3}}\end{verbatim}
|
|
|
-% has three parameters. \verb!\macro the! and \verb!\macro{t}{h}{e}!
|
|
|
-% both lead to the output '\textbf{t}\texttt{h}\textit{e}'.
|
|
|
-% Parameters with more than one character must be enclosed in braces.
|
|
|
-% If you call the macro with less than three parameters, you will get
|
|
|
-% an error message (hopefully most times), since the three parameters
|
|
|
-% are the calling syntax of the macro. That's all well known.
|
|
|
-%
|
|
|
-% But \TeX's macro processor is more powerful. Nearly any character
|
|
|
-% sequence and parameter mixture can be used for the calling syntax,
|
|
|
-% e.g.\
|
|
|
-% \begin{verbatim}
|
|
|
-% \def\macro z=(#1,#2){ ... }\end{verbatim}
|
|
|
-% The call \verb!\macro{10}{0}! is illegal, but \verb!\macro z=(10,0)!
|
|
|
-% is ok. The parameters are '10' and '0', respectively.
|
|
|
%
|
|
|
-% This mechanism can be used to check whether a character sequence
|
|
|
-% is a substring of another sequence --- which will be used to
|
|
|
-% extract comments and keywords, but this comes later. Consider
|
|
|
+% \subsection{Listings inside arguments}\label{uListingsInsideArguments}
|
|
|
+%
|
|
|
+% There are some things to consider if you want to use |\lstinline| or the listing environment inside arguments.
|
|
|
+% Since \TeX\ reads the argument before the '\lst-macro' is executed, this package can't do anything to preserve the input:
|
|
|
+% Spaces shrink to one space, the tabulator and the end of line are converted to spaces, the comment character is not printable, and so on.
|
|
|
+% Hence, you must work a little bit more.
|
|
|
+% You have to put a backslash in front of each of the following four characters: |\{}%|.
|
|
|
+% Moreover you must protect spaces in the same manner if: (i) there are two or more spaces following each other or (ii) the space is the first character in the line.
|
|
|
+% That's not enough: Each line must be terminated with a 'line feed' |^^J|.
|
|
|
+% Finally you can't escape to \LaTeX\ inside such listings.
|
|
|
+%
|
|
|
+% The easiest examples are with |\lstinline| since we need no line feed.
|
|
|
% \begin{verbatim}
|
|
|
-% \def\macro #1substring#2\relax{ ... }\end{verbatim}
|
|
|
-% If we call this macro, we should always add \verb!substring\relax!
|
|
|
-% at the end, since the sequence belongs to the syntax of the macro:
|
|
|
+%\footnote{\lstinline!var i:integer;! and
|
|
|
+% \lstinline!protected\ \ spaces! and
|
|
|
+% \fbox{\lstinline!\\\{\}\%!}}\end{verbatim}
|
|
|
+% yields\lstset{language=Pascal}\footnote{\lstinline!var i:integer;! and \lstinline!protected\ \ spaces! and \fbox{\lstinline!\\\{\}\%!}} if the current language is Pascal.
|
|
|
+% The environment possibly needs a preceding |\lstbox|, as the following examples show.
|
|
|
+%
|
|
|
+%{\let\smallbreak\relax\lstset{language={}}
|
|
|
+% \begin{lstsample}{}
|
|
|
+%\fbox{\lstbox
|
|
|
+%\begin{lstlisting}{}^^J
|
|
|
+%\ !"#$\%&'()*+,-./^^J
|
|
|
+%0123456789:;<=>?^^J
|
|
|
+%@ABCDEFGHIJKLMNO^^J
|
|
|
+%PQRSTUVWXYZ[\\]^_^^J
|
|
|
+%`abcdefghijklmno^^J
|
|
|
+%pqrstuvwxyz\{|\}~^^J
|
|
|
+%\end{lstlisting}}
|
|
|
+% \end{lstsample}
|
|
|
+%
|
|
|
+% \lstset{language={}}
|
|
|
+% \begin{lstsample}{}
|
|
|
+%\fbox{\lstbox
|
|
|
+%\begin{lstlisting}{}^^J
|
|
|
+%We need no protection here,^^J
|
|
|
+%\ but\ \ in\ \ this\ \ line.^^J
|
|
|
+%\end{lstlisting}}
|
|
|
+% \end{lstsample}
|
|
|
+%}
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Frames}
|
|
|
+%
|
|
|
+% \begin{macrosyntax}
|
|
|
+% \item [0.19,new] |frame=|\meta{any subset of \textup{\texttt{tlrbTLRB}}}
|
|
|
+%
|
|
|
+% The characters |tlrbTLRB| are attached to lines at the |t|op of a listing, on the |l|eft, |r|ight and at the |b|ottom.
|
|
|
+% There are two lines if you use upper case letters.
|
|
|
+% If you want a single frame around a listing, write |frame=tlrb| or |frame=bltr| for example (but as optional argument or argument to |\lstset|, of course).
|
|
|
+% If you want double lines at the top and on the left and no other lines, write |frame=TL|.
|
|
|
+% Note that frames reside outside the listing's space.
|
|
|
+% Use |spread| if you want to shrink frames (to |\linewidth| for example) and use |indent| if you want to move line number inside frames.
|
|
|
+%
|
|
|
+% \item [0.19,new] |framerulewidth=|\meta{dimension}
|
|
|
+% \item [0.19,new] |framerulesep=|\meta{dimension}
|
|
|
+%
|
|
|
+% These keys control the width of the rules and the space between double rules.
|
|
|
+% The predefined values are {\makeatletter\lst@framewidth} width and {\makeatletter\lst@framesep} separation.
|
|
|
+%
|
|
|
+%\iffalse
|
|
|
+% \item [0.19,new] |frametextsep=|\meta{dimension}
|
|
|
+%
|
|
|
+% controls the space between frame and listing, but currently only between the listing and vertical frame lines.
|
|
|
+% The predefined value is {\makeatletter\lst@frametextsep}.
|
|
|
+%\fi
|
|
|
+% \end{macrosyntax}
|
|
|
+% |frame| does not work with |\lstbox| or |fancyvrb=true|!
|
|
|
+% And there are certainly more problems with other commands.
|
|
|
+% Take the time to report in.
|
|
|
+%
|
|
|
+% \begin{lstsample}{}
|
|
|
+%\begin{lstlisting}[frame=tLBr]{}
|
|
|
+%for i:=maxint to 0 do
|
|
|
+%begin
|
|
|
+% { do nothing }
|
|
|
+%end;
|
|
|
+%\end{lstlisting}
|
|
|
+% \end{lstsample}
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Export of identifiers}
|
|
|
+%
|
|
|
+%^^A \lsthelper{Aslak Raanes}{[email protected]}{1997/11/24}{export function names}
|
|
|
+% It would be nice to export function or procedure names, for example to index them automatically or to use them in |\listoflistings| instead of a listing name.
|
|
|
+% In general that's a dream so far.
|
|
|
+% The problem is that programming languages use various syntaxes for function and procedure declaration or definition.
|
|
|
+% A general interface is completely out of the scope of this package --- that's the work of a compiler and not of a pretty printing tool.
|
|
|
+% However, it is possible for particular languages: in Pascal each function or procedure definition and variable declaration is preceded by a particular keyword.
|
|
|
+% \begin{macrosyntax}
|
|
|
+% \item [0.19,new,optional] |index={|\meta{identifiers}|}|
|
|
|
+%
|
|
|
+% \meta{identifiers} is a comma-separated list of identifiers.
|
|
|
+% Each appearance of such an identifier is indexed.
|
|
|
+%
|
|
|
+% \item [0.19,new,optional] |indexmacro=|\meta{'one parameter' macro}
|
|
|
+%
|
|
|
+% The specified macro gets exactly one parameter, namely the identifier, and must do the indexing.
|
|
|
+% It is predefined as |indexmacro=\lstindexmacro|, which definition is
|
|
|
% \begin{verbatim}
|
|
|
-% \macro This is our first call.substring\relax\end{verbatim}
|
|
|
-% Here the second parameter of the macro will be empty, but using
|
|
|
+% \newcommand\lstindexmacro[1]{\index{{\ttfamily#1}}}\end{verbatim}
|
|
|
+% \item[0.19,new,optional] |prockeywords={|\meta{keywords}|}|
|
|
|
+%
|
|
|
+% \meta{keywords} is a comma-separated list of keywords, which indicate a function or procedure definition.
|
|
|
+% Any identifier following such a keyword appears in 'procname' style.
|
|
|
+% For Pascal you might use
|
|
|
% \begin{verbatim}
|
|
|
-% \macro This is a substring example.substring\relax\end{verbatim}
|
|
|
-% the second parameter is not empty, since the first 'substring'
|
|
|
-% terminates the first parameter and lets the second begin after
|
|
|
-% (upto the closing \cs{relax}). The character sequence 'substring'
|
|
|
-% is a substring of the preceding character sequence, if and only if
|
|
|
-% the second parameter is not empty.
|
|
|
+% prockeywords={program,procedure,function}\end{verbatim}
|
|
|
%
|
|
|
-% Later we let the preceding character sequence be a list of keywords
|
|
|
-% to test whether a character sequence is a keyword or not.
|
|
|
-% Or we let the preceding character sequence be the current soure line
|
|
|
-% and replace 'substring' by '//' to look for a C++ comment line.
|
|
|
+% \item[0.19,new,optional] |procnamestyle=|\meta{style for procedure names}
|
|
|
%
|
|
|
+% defines the style in which procedure and function names appear.
|
|
|
%
|
|
|
-% \subsection{Quick 'if parameter empty'}
|
|
|
-% There are many situations where you have to look whether a macro
|
|
|
-% parameter is empty or not. Let's say, we want to test the first
|
|
|
-% parameter, which is refered by $\#1$. The \emph{natural} way would
|
|
|
-% be something like
|
|
|
-% \begin{verbatim}
|
|
|
-% \def\test{#1}%
|
|
|
-% \ifx \test\empty %
|
|
|
-% % #1 is empty
|
|
|
-% \else %
|
|
|
-% % #1 is not empty
|
|
|
-% \fi %\end{verbatim}
|
|
|
-% where \cs{empty} is defined by \verb!\def\empty{}!, of course.
|
|
|
-% And now the \emph{mad} way:
|
|
|
-% \begin{verbatim}
|
|
|
-% \ifx \empty#1\empty %
|
|
|
-% % #1 is empty
|
|
|
-% \else %
|
|
|
-% % #1 is not empty
|
|
|
-% \fi %\end{verbatim}
|
|
|
-% Having an empty parameter the \cs{empty} left from $\#1$ is compared
|
|
|
-% with the \cs{empty} on the right. Since they are the same, it's all ok.
|
|
|
-% If the parameter is not empty, the \cs{empty} on the left is compared
|
|
|
-% with the first token of the parameter. Assuming this token is not
|
|
|
-% equivalent to \cs{empty} the \cs{else} section is executed as desired.
|
|
|
-% The paramater must not be the macro \cs{empty}, e.g.
|
|
|
-%
|
|
|
-% The mad way works, if and only if the first token of the parameter is
|
|
|
-% not equivalent to \cs{empty}. You must check, if this meets your
|
|
|
-% purpose. The two \cs{empty}s might be replaced by any other macro,
|
|
|
-% which is not equivalent to the first token of the parameter.
|
|
|
-% But the definition of that macro shouldn't be too complex, since
|
|
|
-% this slows down the \cs{ifx}. Consider
|
|
|
-% \begin{verbatim}
|
|
|
-% \def\test{#1}\ifx \test\empty \else \fi % natural\end{verbatim}
|
|
|
-% and
|
|
|
+% \item[0.19,new,optional] |indexprocnames=|\meta{true$\vert$false}
|
|
|
+%
|
|
|
+% If activated, procedure and function names are also indexed (if used with |index| option).
|
|
|
+% \end{macrosyntax}
|
|
|
+%
|
|
|
+%
|
|
|
+% \section{Troubleshooting}
|
|
|
+%
|
|
|
+% The known bugs have already been described.
|
|
|
+% This section deals with problems concerning not only the \textsf{listings} package.
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Problems with \texttt{.fd} files}
|
|
|
+%
|
|
|
+% You probably get the following error message with a different font definition file:
|
|
|
% \begin{verbatim}
|
|
|
-% \ifx \empty#1\empty \else \fi % mad\end{verbatim}
|
|
|
-% The mad version needs about $45\%$ of the natural's time.
|
|
|
+%! LaTeX Error: Command textparagraph unavailable in encoding T1.
|
|
|
%
|
|
|
+%See the LaTeX manual or LaTeX Companion for explanation.
|
|
|
+%Type H <return> for immediate help.
|
|
|
+% ...
|
|
|
%
|
|
|
-% \section{Implementation}
|
|
|
+%l.68 \P
|
|
|
+% rovidesFile{omscmr.fd}
|
|
|
+%?\end{verbatim}
|
|
|
+% So, what happened?
|
|
|
+% (a) The \textsf{listings} package redefines the character table to print listings.
|
|
|
+% (b) \LaTeX\ loads the font definition files on demand.
|
|
|
+% (a) plus (b) gives the error: \LaTeX\ loads the \texttt{.fd} files with modified character table.
|
|
|
+% And that goes wrong.
|
|
|
+% The work-around is quite easy: Input the \texttt{.fd} file before typesetting the listing.
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Language definitions}
|
|
|
+%
|
|
|
+% Language definitions and also some style definitions tend to have long definition parts.
|
|
|
+% This is why we tend to forget commas between the key=value elements.
|
|
|
+% If you select a language and get a |Missing = inserted for \ifnum| error, this is surely due to a missing comma after |keywords=|value.
|
|
|
+% If you encounter unexspected characters after selecting a language (or style), you have either forgotten a comma or you have given to many arguments to a key, for example |commentline={--}{!}|.
|
|
|
+%
|
|
|
+%
|
|
|
+% \section{Forthcoming}
|
|
|
%
|
|
|
-% Before considering the implementation, here some conventions I used:
|
|
|
% \begin{itemize}
|
|
|
-% \item The names of all public macros (the user commands) have lower
|
|
|
-% case letters. (That's not true: \cs{DeclareCommentLine}, \ldots,
|
|
|
-% but consistent with the third item.)
|
|
|
-% \item The name of all private macros and variables have prefixes:
|
|
|
-% \verb!lst@! for a general macro or variable, \verb!lstdrv@! when
|
|
|
-% it is defined in a driver file, and \verb!lstenv@! if it is
|
|
|
-% defined for the listing environment.
|
|
|
-% \item To distinguish procedure-like macros from macros holding data,
|
|
|
-% the name of procedure macros use upper case letters with each
|
|
|
-% beginning word, e.g.\ \verb!\lst@ProcessLine!. (The only exception
|
|
|
-% is the 'procedure-macro' \verb!\lst@ifoneof!.)
|
|
|
+% \item I'd like to support more languages, for example Maple, Mathematica, PostScript, Reduce and so on.
|
|
|
+% Fortunately my lifetime is limited, so other people may do that work.
|
|
|
+% Write a language definition and (e-)mail it to me (with a proposal in which file to place the definition).
|
|
|
+%
|
|
|
+% \item There will possibly a boolean |blanklisting=|\meta{true$\vert$false} or a $*$-version of the environment.
|
|
|
+%
|
|
|
+% \item 'procnames' is already interesting, but marks (and indexes) only the function definitions so far.
|
|
|
+% It would be quite easy to mark also the following function calls:
|
|
|
+% Write another 'keyword class' which is empty at the very beginning (and can be reset with a key); each function definition appends a 'keyword' which will appear in 'procnamestyle'.
|
|
|
+% But this would be another 'keyword test' within an inner loop.
|
|
|
+% \item I plan to put all language definitions in a single file.
|
|
|
% \end{itemize}
|
|
|
%
|
|
|
%
|
|
|
-% \subsection{Registers and variables}\label{ssRegisters}
|
|
|
-% The current version needs 1 read register, 5 counters, 2 dimensions
|
|
|
-% and 1 token register. The counter \verb!\@tempcnta! and the dimension
|
|
|
-% \verb!\@tempdima! are also used, see the index.
|
|
|
+% \StopEventually{}
|
|
|
+%
|
|
|
+%
|
|
|
+% \part{Implementation}
|
|
|
%
|
|
|
-% \begin{macro}{\lst@inputfile}
|
|
|
-% \begin{macro}{\lst@ifendinput}
|
|
|
-% \begin{macro}{\iflisting}
|
|
|
-% \verb!\iflisting! is described in the user's guide. The input file
|
|
|
-% is \verb!\lst@inputfile!. The output of the file terminates, if and
|
|
|
-% only if the boolean \verb!\lst@ifendinput! is true.
|
|
|
+% \CheckSum{5520}
|
|
|
+% \DoNotIndex{\[,\{,\},\],\1,\2,\3,\4,\5,\6,\7,\8,\9,\0}
|
|
|
+% \DoNotIndex{\`,\,,\!,\#,\$,\&,\',\(,\),\+,\.,\:,\;,\<,\=,\>,\?,\_}
|
|
|
+% \DoNotIndex{\@@end,\@@par,\@currenvir,\@depth,\@dottedtocline,\@ehc}
|
|
|
+% \DoNotIndex{\@empty,\@firstoftwo,\@gobble,\@gobbletwo,\@gobblefour,\@height}
|
|
|
+% \DoNotIndex{\@ifnextchar,\@ifundefined,\@namedef,\@ne,\@secondoftwo}
|
|
|
+% \DoNotIndex{\@spaces,\@starttoc,\@undefined,\@whilenum,\@width}
|
|
|
+% \DoNotIndex{\A,\active,\addtocontents,\advance,\aftergroup,\batchmode}
|
|
|
+% \DoNotIndex{\begin,\begingroup,\bfseries,\bgroup,\box,\bigbreak,\bullet}
|
|
|
+% \DoNotIndex{\c@page,\catcode,\contentsname,\csname,\def,\divide,\do,\dp}
|
|
|
+% \DoNotIndex{\edef,\egroup,\else,\end,\endcsname,\endgroup,\endinput}
|
|
|
+% \DoNotIndex{\endlinechar,\escapechar,\everypar,\expandafter,\f@family}
|
|
|
+% \DoNotIndex{\fi,\footnotesize,\gdef,\global,\hbox,\hss,\ht}
|
|
|
+% \DoNotIndex{\if,\ifdim,\iffalse,\ifnum,\ifodd,\iftrue,\ifx}
|
|
|
+% \DoNotIndex{\ignorespaces,\index,\input,\itshape,\kern}
|
|
|
+% \DoNotIndex{\lccode,\l@ngrel@x,\leftskip,\let,\linewidth,\llap}
|
|
|
+% \DoNotIndex{\long,\lowercase,\m@ne,\makeatletter,\mathchardef}
|
|
|
+% \DoNotIndex{\message,\multiply,\NeedsTeXFormat,\newbox,\new@command}
|
|
|
+% \DoNotIndex{\newcommand,\newcount,\newdimen,\newtoks,\noexpand}
|
|
|
+% \DoNotIndex{\noindent,\normalbaselines,\normalbaselineskip}
|
|
|
+% \DoNotIndex{\offinterlineskip,\par,\parfillskip,\parshape}
|
|
|
+% \DoNotIndex{\parskip,\ProcessOptions,\protect,\ProvidesPackage}
|
|
|
+% \DoNotIndex{\read,\relax,\removelastskip,\rightskip,\rlap,\setbox}
|
|
|
+% \DoNotIndex{\smallbreak,\smash,\space,\string,\strut,\strutbox}
|
|
|
+% \DoNotIndex{\the,\thepage,\ttdefault,\ttfamily,\tw@,\typeout,\uppercase}
|
|
|
+% \DoNotIndex{\vbox,\vcenter,\vrule,\vtop,\wd,\xdef,\z@,\zap@space}
|
|
|
+% \DoNotIndex{\char,\closeout,\immediate,\newwrite,\openout,\write}
|
|
|
+% \DoNotIndex{\vskip}
|
|
|
+%
|
|
|
+% \DoNotIndex{\define@key,\setkeys}
|
|
|
+%
|
|
|
+% \DoNotIndex{\textasciicircum,\textasciitilde,\textasteriskcentered}
|
|
|
+% \DoNotIndex{\textbackslash,\textbar,\textbraceleft,\textbraceright}
|
|
|
+% \DoNotIndex{\textdollar,\textendash,\textgreater,\textless}
|
|
|
+% \DoNotIndex{\textunderscore,\textvisiblespace}
|
|
|
+%
|
|
|
+% \DoNotIndex{\filename@area,\filename@base,\filename@ext}
|
|
|
+% \DoNotIndex{\filename@parse,\IfFileExists,\InputIfFileExists}
|
|
|
+% \DoNotIndex{\DeclareOption,\MessageBreak}
|
|
|
+% \DoNotIndex{\GenericError,\GenericInfo,\GenericWarning}
|
|
|
+%
|
|
|
+% \DoNotIndex{\blankstringfalse,\blankstringtrue,\commentstyle}
|
|
|
+% \DoNotIndex{\DeclareCommentLine,\DeclareDoubleComment}
|
|
|
+% \DoNotIndex{\DeclareNestedComment,\DeclarePairedComment}
|
|
|
+% \DoNotIndex{\DeclareSingleComment,\inputlisting,\inputlisting@,\keywords}
|
|
|
+% \DoNotIndex{\keywordstyle,\labelstyle,\listingfalse,\listingtrue}
|
|
|
+% \DoNotIndex{\morekeywords,\normallisting,\postlisting,\prelisting}
|
|
|
+% \DoNotIndex{\selectlisting,\sensitivefalse,\sensitivetrue}
|
|
|
+% \DoNotIndex{\spreadlisting,\stringizer,\stringstyle,\tablength}
|
|
|
+%
|
|
|
+% \DoNotIndex{\lst@AddToHook@,\lst@Aspect@,\is,\lst@AspectGobble}
|
|
|
+% \DoNotIndex{\lst@DeleteKeysIn@,\lst@Environment@}
|
|
|
+% \DoNotIndex{\lst@IfNextChars@,\lst@IfNextChars@@,\lst@KCOutput@}
|
|
|
+% \DoNotIndex{\lst@MakeActive@,\lst@MSkipUptoFirst@,\lst@ReplaceIn@}
|
|
|
+% \DoNotIndex{\lst@LocateLanguage@,\lst@SKS@,\lstalias@,\lstalias@@}
|
|
|
+% \DoNotIndex{\lstbaseem@,\lstbox@,\lstCC@ECUse@,\lstCC@Escape@}
|
|
|
+% \DoNotIndex{\lstCC@CBC@,\lstCC@CBC@@,\lstCC@CommentLine@}
|
|
|
+% \DoNotIndex{\lstCC@EndKeywordComment@,\lstCC@FixedCL@}
|
|
|
+% \DoNotIndex{\lstCC@ProcessEndPOD@,\lstCC@SpecialUseAfter@}
|
|
|
+% \DoNotIndex{\lstCC@Stringizer@,\lstdrvlanguage@,\lstenv@AddArg@}
|
|
|
+% \DoNotIndex{\lstenv@Process@,\lstenv@ProcessJ@,\lstinputlisting@}
|
|
|
+% \DoNotIndex{\lstoutputpos@,\lstresetlineno@,\lstresetlineno@@}
|
|
|
+% \DoNotIndex{\lstspread@}
|
|
|
+% \DoNotIndex{\lstnestedcomment@,\lstpost@,\lstpre@,\lststringizer@}
|
|
|
+%
|
|
|
+%
|
|
|
+% \section{Overture}
|
|
|
+%
|
|
|
+% The version 0.19 kernel needs 1 token register, 6 counters and 5 dimensions.
|
|
|
+% The macros, boxes and counters |\@temp?a| and |\@temp?b| and the dimension |\@tempdima| are also used, see the index.
|
|
|
+% And I shouldn't forget |\@gtempa|.
|
|
|
+% Furthermore, the required \textsf{keyval} package allocates one token register.
|
|
|
+% The \textsf{fancyvrb} interface needs one box.
|
|
|
+%
|
|
|
+% Before considering the implementation, here some conventions I used:
|
|
|
+% \begin{itemize}
|
|
|
+% \item All public macros have lower case letters and the prefix \lst.
|
|
|
+% \item The name of all private macros and variables use the prefixes (possibly not up to date):
|
|
|
+% \begin{itemize}
|
|
|
+% \item |lst@| for a general macro or variable,
|
|
|
+% \item |lstenv@| if it is defined for the listing |env|ironment,
|
|
|
+% \item |lstCC@| for |c|haracter |c|lass macros,
|
|
|
+% \item |lsts@| for |s|aved character meanings,
|
|
|
+% \item |lstf@| for frame declaration,
|
|
|
+% \item |\lsthk@|\meta{name of hook} holds hook material,
|
|
|
+% \item a language may define (|Pre| for prepare, |SCT| for select char table)
|
|
|
+% \begin{itemize}
|
|
|
+% \item[] |\lstPre@|\meta{language}
|
|
|
+% \item[] |\lstPre@|\meta{language}|@|\meta{dialect}
|
|
|
+% \item[] |\lstSCT@|\meta{language}
|
|
|
+% \item[] |\lstSCT@|\meta{language}|@|\meta{dialect}
|
|
|
+% \end{itemize}
|
|
|
+% where the first two are executed (if they exist) one time each listing (before selecting character table, but after executing the hook Before\-Select\-Char\-Table).
|
|
|
+% The other two macros are called possibly more than once, namely whenever the package selects the character table.
|
|
|
+% The specialized \meta{dialect} versions are called after the more general \meta{language} macros.
|
|
|
+% \item |lstk@| is reserved for keyword tests,
|
|
|
+%
|
|
|
+% \item |\lstlang@|\meta{language}|@|\meta{dialect} contains a language definition,
|
|
|
+% \item |\lststy@|\meta{the style} contains style definition,
|
|
|
+%
|
|
|
+% \item |\lstloc@|\meta{language} keeps location (= file name without extension) of a language definition if it's not |lst|\meta{language},
|
|
|
+% \item |\lsta@|\meta{language}|@|\meta{dialect} contains alias,
|
|
|
+% \item |\lstaa@|\meta{language} contains alias for all dialects of a language,
|
|
|
+% \item |\lstdd@|\meta{language} contains default dialect of a language (if present).
|
|
|
+% \end{itemize}
|
|
|
+% \item If a submacro does the main work, e.g.\ |\lstinputlisting@| does it for |\lstinputlisting|, we use the suffix |@|.
|
|
|
+% \item To distinguish procedure-like macros from macros holding data, the name of procedure macros use upper case letters with each beginning word, e.g.\ |\lst@AddTo|.
|
|
|
+% \end{itemize}
|
|
|
+%
|
|
|
+% The kernel starts with identification and option declaration and processing.
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%<*kernel>
|
|
|
+\NeedsTeXFormat{LaTeX2e}
|
|
|
+\ProvidesPackage{listings}[1998/11/09 v0.19 by Carsten Heinz]
|
|
|
+\RequirePackage{keyval}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\DeclareOption{0.17}{\@namedef{[email protected]}{}}
|
|
|
+\DeclareOption{index}{\@namedef{lst@index}{}}
|
|
|
+\DeclareOption{procnames}{\@namedef{lst@prockeywords}{}}
|
|
|
+\DeclareOption{ndkeywords}{\@namedef{lst@ndkeywords}{}}
|
|
|
+\DeclareOption{rdkeywords}{\@namedef{lst@rdkeywords}{}}
|
|
|
+\DeclareOption{doc}{\@namedef{lst@doc}{}}
|
|
|
+\ProcessOptions
|
|
|
+%</kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% Note that |doc| option is designed for this documentation only.
|
|
|
+% \endgroup
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%<*info>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+% \begin{macro}{\lst@InfoInfo}
|
|
|
+% \begin{macro}{\lst@InfoWarning}
|
|
|
+% \begin{macro}{\lst@InfoError}
|
|
|
+% Each macro gets one argument, which is printed (\texttt{.log} and/or screen) as info, warning or error.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@InfoInfo#1{%
|
|
|
+ \GenericInfo %
|
|
|
+ {(Listings) \@spaces\@spaces\space\space}%
|
|
|
+ {Listings Info: #1}}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@InfoWarning#1{%
|
|
|
+ \GenericWarning %
|
|
|
+ {(Listings) \@spaces\@spaces\@spaces\space}%
|
|
|
+ {Listings Warning: #1}}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@InfoError#1{%
|
|
|
+ \GenericError %
|
|
|
+ {(Listings) \@spaces\@spaces\@spaces\space}%
|
|
|
+ {Listings Error: #1}%
|
|
|
+ {See the package documentation for explanation.}%
|
|
|
+ {You're using a debug version of listings.sty.^^J%
|
|
|
+ Contact your system administrator to install nondebug one.}}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}\end{macro}\end{macro}
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%</info>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+%
|
|
|
+%
|
|
|
+% \section{General problems and \TeX{}niques}
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Quick 'if parameter empty'}
|
|
|
+%
|
|
|
+% There are many situations where you have to look whether or not a macro parameter is empty.
|
|
|
+% Let's say, we want to test |#1|.
|
|
|
+% The \emph{natural} way would be something like
|
|
|
+% \begin{verbatim}
|
|
|
+% \def\test{#1}%
|
|
|
+% \ifx \test\empty %
|
|
|
+% % #1 is empty
|
|
|
+% \else %
|
|
|
+% % #1 is not empty
|
|
|
+% \fi %\end{verbatim}
|
|
|
+% where |\empty| is defined by |\def\empty{}|, of course.
|
|
|
+% And now the \emph{mad} way:
|
|
|
+% \begin{verbatim}
|
|
|
+% \ifx \empty#1\empty %
|
|
|
+% % #1 is empty
|
|
|
+% \else %
|
|
|
+% % #1 is not empty
|
|
|
+% \fi %\end{verbatim}
|
|
|
+% If the parameter is empty, the |\empty| left from |#1| is compared with the |\empty| on the right.
|
|
|
+% All is fine since they are the same.
|
|
|
+% If the parameter is not empty, the |\empty| on the left is compared with the first token of the parameter.
|
|
|
+% Assuming this token is not equivalent to |\empty| the |\else| section is executed, as desired.
|
|
|
+%
|
|
|
+% The mad way works if and only if the first token of the parameter is not equivalent to |\empty|.
|
|
|
+% You must check if this meets your purpose.
|
|
|
+% The two |\empty|s might be replaced by any other macro, which is not equivalent to the first token of the parameter.
|
|
|
+% But the definition of that macro shouldn't be too complex since this would slow down the |\ifx|.
|
|
|
+% In the examples above the mad version needs about $45\%$ of the natural's time.
|
|
|
+% Note that this \TeX{}nique lost its importance from version 0.18 on.
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Replacing characters}\label{iReplacingCharacters}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%<*kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+% In this section we define the macro
|
|
|
+% \begin{macrosyntax}
|
|
|
+% \item |\lst@ReplaceIn|\meta{macro}|{|\meta{replacement list $c_1m_1$\ldots$c_nm_n$}|}|
|
|
|
+% \end{macrosyntax}
|
|
|
+% Each character $c_i$ inside the given macro is replaced by the macro $m_i$.
|
|
|
+% In fact, $c_i$ may be a character sequence (enclosed in braces and possibly containing macros), but $m_i$ must be a single macro which is not equivalent to |\empty| --- use |\relax| instead.
|
|
|
+% |\lst@ReplaceIn\lst@arg{_\textunderscore {--}\textendash}| is allowed but not |\lst@ReplaceIn\lst@arg{\textunderscore_\textendash{--}}|.
|
|
|
+% These restrictions can be dropped, see the TODO part below.
|
|
|
+%
|
|
|
+% We derive the main macro from \LaTeX's |\zap@space|:
|
|
|
+% \begin{verbatim}
|
|
|
+% \def\zap@space#1 #2{%
|
|
|
+% #1%
|
|
|
+% \ifx#2\@empty\else\expandafter\zap@space\fi
|
|
|
+% #2}\end{verbatim}
|
|
|
+% It is called like this:
|
|
|
+% \begin{verbatim}
|
|
|
+% \zap@space Some characters with(out) sense and \@empty
|
|
|
+% \expandafter\zap@space\lst@arg{} \@empty
|
|
|
+% \edef\lst@arg{\expandafter\zap@space\lst@arg{} \@empty}\end{verbatim}
|
|
|
+% Note that |{}|\textvisiblespace\ produces a space holding up the syntax of |\zap@space|: it's defined with a space between the two parameters.
|
|
|
+% If we want to replace a space by a visible space, we could use
|
|
|
+% \begin{verbatim}
|
|
|
+% \def\lst@temp#1 #2{%
|
|
|
+% #1%
|
|
|
+% \ifx#2\@empty\else %
|
|
|
+% \noexpand\textvisiblespace %
|
|
|
+% \expandafter\lst@temp %
|
|
|
+% \fi #2}\end{verbatim}
|
|
|
+% The additional |\noexpand\textvisiblespace| inserts visible spaces where spaces have been.
|
|
|
+% We want to replace several characters and thus have to save our intermediate results.
|
|
|
+% So we will follow the third '|\edef|' example.
|
|
|
+% But there is some danger: After replacing the first character, the macro $m_1$ will expand inside the next |\edef|.
|
|
|
+% Knowing that letters don't expand, we simply say that $m_1$ is a letter.
|
|
|
+% Such changes must be local, so \ldots
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@ReplaceIn}
|
|
|
+% we open a group, store the original macro contents in |\@gtempa| and start a loop.
|
|
|
+% Afterwards we close the group and assign the modified character string to our given macro.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@ReplaceIn#1#2{%
|
|
|
+ \bgroup \global\let\@gtempa#1%
|
|
|
+ \lst@ReplaceIn@#2\@empty\@empty %
|
|
|
+ \egroup \let#1\@gtempa}
|
|
|
+% \end{macrocode}
|
|
|
+% If we haven't reached the end of the list (the two |\@empty|s), we let the macro $m_i$ be a letter and define an appropiate macro to replace the character (sequence) |#2| by the macro |#3|.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@ReplaceIn@#1#2{%
|
|
|
+ \ifx\@empty#2\else %
|
|
|
+ \let#2=a%
|
|
|
+ \def\lst@temp##1#1##2{##1%
|
|
|
+ \ifx\@empty##2\else %
|
|
|
+ #2\expandafter\lst@temp %
|
|
|
+ \fi ##2}%
|
|
|
+% \end{macrocode}
|
|
|
+% Now we call that macro using |\xdef| (since the changes in |\@gtempa| must exist after closing a group).
|
|
|
+% Finally we continue the loop.
|
|
|
+% \begin{macrocode}
|
|
|
+ \xdef\@gtempa{\expandafter\lst@temp\@gtempa#1\@empty}%
|
|
|
+ \expandafter\lst@ReplaceIn@ %
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{TODO}
|
|
|
+% This |\lst@ReplaceIn| is currently sufficient.
|
|
|
+% If we need to replace character sequences by character sequences (instead of single macros), we have to make some minor changes.
|
|
|
+% The main difference is that we build the new contents inside |\lst@temp| instead of using |\edef|.
|
|
|
+% Note that the improved version is much slower than the macros above.\vspace*{-\baselineskip}
|
|
|
+% \begin{verbatim}
|
|
|
+%\def\lst@ReplaceIn#1#2{\lst@ReplaceIn@#1#2\@empty\@empty}
|
|
|
+%\def\lst@ReplaceIn@#1#2#3{%
|
|
|
+% \ifx\@empty#3\else %
|
|
|
+% \def\lst@temp##1#2##2{%
|
|
|
+% \ifx\@empty##2%
|
|
|
+% \lst@lAddTo#1{##1}%
|
|
|
+% \else %
|
|
|
+% \lst@lAddTo#1{##1#3}%
|
|
|
+% \expandafter\lst@temp %
|
|
|
+% \fi ##2}%
|
|
|
+% \let\@tempa#1\let#1\@empty %
|
|
|
+% \expandafter\lst@temp\@tempa#2\@empty %
|
|
|
+% \expandafter\lst@ReplaceIn@\expandafter#1%
|
|
|
+% \fi}\end{verbatim}
|
|
|
+% \removelastskip
|
|
|
+% Even here you will have a problem replacing a single brace, if it has the meaning of opening or closing a group:
|
|
|
+% You can't enter it as an argument!
|
|
|
+% \end{TODO}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@DeleteKeysIn}
|
|
|
+% We define another macro, which looks quite similar to |\lst@ReplaceIn|.
|
|
|
+% The arguments are two macros containing a comma separated keyword list.
|
|
|
+% All keywords in the second list are removed from the first.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@DeleteKeysIn#1#2{%
|
|
|
+ \bgroup \global\let\@gtempa#1%
|
|
|
+ \let\lst@dollar=A\let\lst@minus=B\let\lst@underscore=C%
|
|
|
+ \expandafter\lst@DeleteKeysIn@#2,\relax,%
|
|
|
+ \egroup \let#1\@gtempa}
|
|
|
+% \end{macrocode}
|
|
|
+% To terminate the loop we remove the very last |\lst@DeleteKeysIn@| with |\@gobble|.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@DeleteKeysIn@#1,{%
|
|
|
+ \ifx\relax#1\@empty %
|
|
|
+ \expandafter\@gobble %
|
|
|
+ \else %
|
|
|
+ \ifx\@empty#1\@empty\else %
|
|
|
+ \def\lst@temp##1,#1##2{##1\ifx\@empty##2\else %
|
|
|
+ \ifx,##2\else #1\fi \expandafter\lst@temp\fi ##2}%
|
|
|
+ \xdef\@gtempa{%
|
|
|
+ \expandafter\lst@temp\expandafter,\@gtempa,#1\@empty}%
|
|
|
+ \fi %
|
|
|
+ \fi %
|
|
|
+ \lst@DeleteKeysIn@}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%</kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Looking ahead for character sequences}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%<*kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+% \begin{macro}{\lst@IfNextChars}
|
|
|
+% The macro |\@ifnextchar|\meta{single character}|{|\meta{then part}|}{|\meta{else part}|}| from the \LaTeX{} kernel is well known:
|
|
|
+% Whether or not the character behind the three arguments --- usually a character from the 'user input stream' --- equals the given single character the 'then' or 'else' part is executed.
|
|
|
+% We define a macro which looks for an arbitrary character sequence stored in a macro:{}
|
|
|
+% \begin{macrosyntax}
|
|
|
+% \item |\lst@IfNextChars|\meta{macro}|{|\meta{then part}|}{|\meta{else part}|}|
|
|
|
+% \end{macrosyntax}
|
|
|
+% Note an important difference:
|
|
|
+% \LaTeX's |\@ifnextchar| doesn't remove the character behind the arguments, but we remove the characters until it is possible to decide whether the 'then' or 'else' part must be executed.
|
|
|
+% However, we save these characters in a macro called |\lst@eaten|, so they can be inserted if necessary.
|
|
|
+%
|
|
|
+% We save the arguments and call the macro which does the comparisons.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@IfNextChars#1#2#3{%
|
|
|
+ \let\lst@tofind#1\def\@tempa{#2}\def\@tempb{#3}%
|
|
|
+ \let\lst@eaten\@empty \lst@IfNextChars@}
|
|
|
+% \end{macrocode}
|
|
|
+% This macro reads the next character from the input and compares it with the next character from |\lst@tofind|.
|
|
|
+% We append |#1| to the eaten characters and get the character we are looking for (via |\lst@IfNextChars@@|).
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@IfNextChars@#1{%
|
|
|
+ \lst@lAddTo\lst@eaten{#1}%
|
|
|
+ \expandafter\lst@IfNextChars@@\lst@tofind\relax %
|
|
|
+ \ifx #1\lst@temp %
|
|
|
+% \end{macrocode}
|
|
|
+% If the characters are the same, we either execute |\@tempa| or continue the test.
|
|
|
+% \begin{macrocode}
|
|
|
+ \ifx\lst@tofind\@empty %
|
|
|
+ \let\lst@next\@tempa %
|
|
|
+ \else %
|
|
|
+ \let\lst@next\lst@IfNextChars@ %
|
|
|
+ \fi %
|
|
|
+ \expandafter\lst@next %
|
|
|
+ \else %
|
|
|
+% \end{macrocode}
|
|
|
+% If the characters are different, we have to call |\@tempb|.
|
|
|
+% \begin{macrocode}
|
|
|
+ \expandafter\@tempb %
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% Finally comes the subsubmacro |\lst@IfNextChars@@| used above, which assigns the next character to |\lst@temp| and the rest upto |\relax| to |\lst@tofind|.
|
|
|
+% If the implementation is not clear, read the last sentence again.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@IfNextChars@@#1#2\relax{\let\lst@temp#1\def\lst@tofind{#2}}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@IfNextCharsArg}
|
|
|
+% The difference between |\lst@IfNextChars| and the macro here is that the first parameter is a character sequence and not a macro.
|
|
|
+% Moreover, the character sequence is made active here.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@IfNextCharsArg#1#2#3{%
|
|
|
+ \lst@MakeActive{#1}\let\lst@tofind\lst@arg %
|
|
|
+ \def\@tempa{#2}\def\@tempb{#3}%
|
|
|
+ \let\lst@eaten\@empty \lst@IfNextChars@}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%</kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Catcode changes of characters already read}\label{iCatcodeChangesOfCharactersAlreadyRead}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%<*kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+% Here we define two important macros:
|
|
|
+% \begin{macrosyntax}
|
|
|
+% \item |\lst@MakeActive{|\meta{character sequence}|}|
|
|
|
+%
|
|
|
+% stores the character sequence in |\lst@arg|, but all characters become active.
|
|
|
+% The string must \emph{not} contain a begin group, end group or escape character (|{}\|); it may contain a left brace, right brace or backslash with other meaning (=catcodes).
|
|
|
+% This command would be quite surplus if \meta{character sequence} is not already read by \TeX{} (since such catcodes can be changed easily).
|
|
|
+% It is explicitly allowed that the charcaters have been read, e.g.\ in |\def\test{\lst@MakeActive{ABC}}| |\test|!
|
|
|
+%
|
|
|
+% Note that |\lst@MakeActive| changes |\lccode|s 0--9 without restoring them.
|
|
|
+% \item |\lst@IfNextCharActive{|\meta{then part}|}{|\meta{else part}|}|
|
|
|
+%
|
|
|
+% executes 'then' part if next character behind the arguments is active, and the 'else' part otherwise.
|
|
|
+% \end{macrosyntax}
|
|
|
+% \TeX{} knows sixteen different catcodes, which say whether a character is a letter, a space, a math shift character, subscript character, and so on.
|
|
|
+% A character gets its catcode right after reading it and \TeX{} has no primitive command to change a catcode of characters already read.
|
|
|
+% Consider for example |\def\mathmode#1{$#1$}|.
|
|
|
+% After that definition there is no chance to say: ''\emph{Print} the two dollar signs and the argument between instead of entering math mode''.
|
|
|
+% And if we write |\mathmode{a_i}| and have just entered the macro |\mathmode|, the argument |a_i| is read and it's too late to change the meaning of the subscript character to a printable underbar, for example.
|
|
|
+% But that's not the whole truth: We can change character-catcodes of an argument.
|
|
|
+% In fact, we replace the characters by characters with same ASCII codes but different catcodes.
|
|
|
+% It's not the same but suffices since the result is the same.
|
|
|
+% Here we treat the very special case that all characters become active.
|
|
|
+% A prototype macro would be
|
|
|
+% \begin{verbatim}
|
|
|
+% \def\MakeActive#1{\lccode`\~=`#1\lowercase{\def\lst@arg{~}}}|\end{verbatim}
|
|
|
+% But this macro handles a single character only:
|
|
|
+% The |\lowercase| changes the ASCII code of |~| to that of |#1| since we have said that |~| is the lower case version of |#1|.
|
|
|
+% Fortunately the |\lowercase| doesn't change the catcode, so we have an active version of |#1|.
|
|
|
+% Note that |~| is usually active.
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@MakeActive}
|
|
|
+% We won't do this character by character.
|
|
|
+% To increase speed we change nine characters at the same time (if nine characters are left).
|
|
|
+% We get the argument, empty |\lst@arg| and begin a loop:
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@MakeActive#1{%
|
|
|
+ \let\lst@arg\@empty \lst@MakeActive@#1%
|
|
|
+ \relax\relax\relax\relax\relax\relax\relax\relax\relax}
|
|
|
+% \end{macrocode}
|
|
|
+% There are nine |\relax|es since |\lst@MakeActive@| has nine parameters and we don't want any problems in the case that |#1| is empty.
|
|
|
+% We need nine active characters now instead of a single |~|.
|
|
|
+% We make these catcode changes local and define the coming macro |\global|.
|
|
|
+% \begin{macrocode}
|
|
|
+\begingroup
|
|
|
+\catcode`\^^@=\active \catcode`\^^A=\active \catcode`\^^B=\active %
|
|
|
+\catcode`\^^C=\active \catcode`\^^D=\active \catcode`\^^E=\active %
|
|
|
+\catcode`\^^F=\active \catcode`\^^G=\active \catcode`\^^H=\active %
|
|
|
+% \end{macrocode}
|
|
|
+% First we |\let| the next operation be |\relax|.
|
|
|
+% This aborts our loop for processing all characters (default and possibly changed later).
|
|
|
+% Then we look if we have at least one character.
|
|
|
+% If this is not the case, the loop terminates and all is done.
|
|
|
+% \begin{macrocode}
|
|
|
+\gdef\lst@MakeActive@#1#2#3#4#5#6#7#8#9{\let\lst@next\relax %
|
|
|
+ \ifx#1\relax %
|
|
|
+ \else \lccode`\^^@=`#1%
|
|
|
+% \end{macrocode}
|
|
|
+% Otherwise we say that |^^@|=chr(0) is the lower case version of the first character.
|
|
|
+% Then we test the second character.
|
|
|
+% If there is none, we append the lower case |^^@| to |\lst@arg|.
|
|
|
+% Otherwise we say that |^^A|=chr(1) is the lower case version of the second character and we test the next argument, and so on.
|
|
|
+% \begin{macrocode}
|
|
|
+ \ifx#2\relax %
|
|
|
+ \lowercase{\lst@lAddTo\lst@arg{^^@}}%
|
|
|
+ \else \lccode`\^^A=`#2%
|
|
|
+ \ifx#3\relax %
|
|
|
+ \lowercase{\lst@lAddTo\lst@arg{^^@^^A}}%
|
|
|
+ \else \lccode`\^^B=`#3%
|
|
|
+ \ifx#4\relax %
|
|
|
+ \lowercase{\lst@lAddTo\lst@arg{^^@^^A^^B}}%
|
|
|
+ \else \lccode`\^^C=`#4%
|
|
|
+ \ifx#5\relax %
|
|
|
+ \lowercase{\lst@lAddTo\lst@arg{^^@^^A^^B^^C}}%
|
|
|
+ \else \lccode`\^^D=`#5%
|
|
|
+ \ifx#6\relax %
|
|
|
+ \lowercase{\lst@lAddTo\lst@arg{^^@^^A^^B^^C^^D}}%
|
|
|
+ \else \lccode`\^^E=`#6%
|
|
|
+ \ifx#7\relax %
|
|
|
+ \lowercase{\lst@lAddTo\lst@arg{^^@^^A^^B^^C^^D^^E}}%
|
|
|
+ \else \lccode`\^^F=`#7%
|
|
|
+ \ifx#8\relax %
|
|
|
+ \lowercase{\lst@lAddTo\lst@arg{^^@^^A^^B^^C^^D^^E^^F}}%
|
|
|
+ \else \lccode`\^^G=`#8%
|
|
|
+ \ifx#9\relax %
|
|
|
+ \lowercase{\lst@lAddTo\lst@arg{^^@^^A^^B^^C^^D^^E^^F^^G}}%
|
|
|
+% \end{macrocode}
|
|
|
+% If nine characters are present, we append (lower case versions of) nine active characters and call this macro again via redefining |\lst@next|.
|
|
|
+% \begin{macrocode}
|
|
|
+ \else \lccode`\^^H=`#9%
|
|
|
+ \lowercase{\lst@lAddTo\lst@arg{^^@^^A^^B^^C^^D^^E^^F^^G^^H}}%
|
|
|
+ \let\lst@next\lst@MakeActive@ %
|
|
|
+ \fi \fi \fi \fi \fi \fi \fi \fi \fi %
|
|
|
+ \lst@next}
|
|
|
+\endgroup
|
|
|
+% \end{macrocode}
|
|
|
+% This |\endgroup| restores the catcodes of chr(0)--chr(8), but not the catcodes of the characters inside |\lst@MakeActive@| since they are already read.
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@IfNextCharActive}
|
|
|
+% The implementation is easy now: We compare the character |#3| with its active version |\lowercase{~}|.
|
|
|
+% Note that the right brace between |\ifx~| and |#3| ends the |\lowercase|.
|
|
|
+% The |\egroup| before restores the |\lccode|.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@IfNextCharActive#1#2#3{%
|
|
|
+ \bgroup \lccode`\~=`#3\lowercase{\egroup %
|
|
|
+ \ifx~}#3%
|
|
|
+ \def\lst@next{#1#3}%
|
|
|
+ \else %
|
|
|
+ \def\lst@next{#2#3}%
|
|
|
+ \fi \lst@next}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%</kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{An application to \ref{iCatcodeChangesOfCharactersAlreadyRead}}\label{iAnApplicationTo}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%<*kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+% We need a brief look on how the listing processing works.
|
|
|
+% Right before processing a listing we redefine all characters, for example to preserve successive spaces or to give the tabulator a different meaning.
|
|
|
+% More precisely, each character becomes active in the sense of \TeX, but that's not so important now.
|
|
|
+% After the listing we switch back to the original meanings and all is fine.
|
|
|
+% If an environment is used inside an argument the listing is already read when the environment is executed and we can do nothing to preserve the characters.
|
|
|
+% However, (under certain circumstances) the environment can be used inside an argument --- that's at least what I've said in the user's guide.
|
|
|
+% And now we have to work for it coming true.
|
|
|
+% We define the macro
|
|
|
+% \begin{macrosyntax}
|
|
|
+% \item |\lstenv@AddArg{|\meta{\TeX{} material (already read)}|}|
|
|
|
+% \end{macrosyntax}
|
|
|
+% which \emph{appends} a 'verbatim' version of the argument to |\lstenv@arg|, but all appended characters are active.
|
|
|
+% Since it's not a character to character conversion, 'verbatim' needs to be explained.
|
|
|
+% All characters can be typed in as they are, except |\|, |{|, |}| and |%|.
|
|
|
+% If you want one of these, you must write |\\|, |\{|, |\}| or |\%| instead.
|
|
|
+% If two spaces should follow each other, the second (third, fourth, \ldots) space must be entered as |\|\textvisiblespace.
|
|
|
+%
|
|
|
+% \begin{macro}{\lstenv@AddArg}
|
|
|
+% We call a submacro (similar to |\zap@space|) to preserve single spaces.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstenv@AddArg#1{\lstenv@AddArg@#1 \@empty}
|
|
|
+% \end{macrocode}
|
|
|
+% We will need an active space:
|
|
|
+% \begin{macrocode}
|
|
|
+\begingroup \lccode`\~=`\ \relax \lowercase{%
|
|
|
+% \end{macrocode}
|
|
|
+% We make all characters upto the first space (with catcode 10) active and append these (plus an active space) to |\lstenv@arg|.
|
|
|
+% If we haven't found the end |\@empty| of the input, we continue the process.
|
|
|
+% \begin{macrocode}
|
|
|
+\gdef\lstenv@AddArg@#1 #2{%
|
|
|
+ \lst@MakeActive{#1}%
|
|
|
+ \ifx\@empty#2\expandafter%
|
|
|
+ \lst@lAddTo\expandafter\lstenv@arg\expandafter{\lst@arg}%
|
|
|
+ \else \expandafter%
|
|
|
+ \lst@lAddTo\expandafter\lstenv@arg\expandafter{\lst@arg~}%
|
|
|
+ \expandafter\lstenv@AddArg@ %
|
|
|
+ \fi #2}
|
|
|
+% \end{macrocode}
|
|
|
+% Finally we end the |\lowercase| and close a group.
|
|
|
+% \begin{macrocode}
|
|
|
+}\endgroup
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%</kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{How to define \lst-aspects}\label{iHowToDefineLstAspects}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%<*kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+% This section contains commands used in defining the style and language aspects.
|
|
|
+% There are two command classes: one extends the internal capabilities, and the other actually defines the aspects.
|
|
|
+% \begin{macrosyntax}
|
|
|
+% \item |\lst@Aspect{|\meta{aspect name}|}{|\meta{definition}|}|
|
|
|
+%
|
|
|
+% is the one and only command in the latter class.
|
|
|
+% It defines the aspect using the \textsf{keyval} package.
|
|
|
+%
|
|
|
+% \item |\lst@AddToHook||{|\meta{name of hook}|}{|\meta{\TeX{} material}|}|
|
|
|
+%
|
|
|
+% \item |\lst@AddToHookAtTop||{|\meta{name of hook}|}{|\meta{\TeX{} material}|}|
|
|
|
+%
|
|
|
+% Both add \TeX{} material at predefined points.
|
|
|
+% The first command appends the code, whereas the second places it in front of existing hook material.
|
|
|
+% \end{macrosyntax}
|
|
|
+% The following hooks are supported (possibly not up to date):
|
|
|
+% \begin{center}\begin{tabular}{rp{0.6\linewidth}}
|
|
|
+% name of hook & point/aim of execution\\ \hline
|
|
|
+% |InitVars| & initializes variables each listing\\
|
|
|
+% |ExitVars| & deinits variables each listing\\
|
|
|
+% |OnExit| & executed at the very end of typesetting\\
|
|
|
+% |EveryLine| & called at the beginning of each line\\
|
|
|
+% |EOL| & executed after printing a source code line\\
|
|
|
+% |InitVarsEOL| & prepares variables for the next line\\
|
|
|
+% |EndGroup| & executed whenever the package closes a group (end of comment or string, e.g.)\\
|
|
|
+% |Output| & called before a printing unit with letters and digits is typeset\\
|
|
|
+% |OutputOther| & called before any other printing unit is typeset\\
|
|
|
+% |BeforeSelectCharTable| & executed before the package changes the character table\\
|
|
|
+% |SelectCharTable| & executed after the package has selected the standard character table\\
|
|
|
+% &\\
|
|
|
+% |SetStyle| & called before |\lststy@|\meta{style}\\
|
|
|
+% |SetLanguage| & called before |\lstlang@|\meta{language}|@|\meta{dialect}\\
|
|
|
+% \end{tabular}\end{center}
|
|
|
+% For example, the hooks make keywords case insensitive (if necessary) before the package processes a listing and call the keyword style before a keyword is printed.
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@Aspect}
|
|
|
+% The command defines the aspect only if not already present.
|
|
|
+% |\lst@ifnew| becomes true (if and) only if a new aspect is defined.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@Aspect#1{%
|
|
|
+ \@ifundefined{KV@lst@#1}%
|
|
|
+ {\let\lst@ifnew\iftrue}{\let\lst@ifnew\iffalse}%
|
|
|
+ \lst@ifnew %
|
|
|
+%<info> \lst@InfoInfo{New aspect `#1'}%
|
|
|
+ \else %
|
|
|
+%<info> \lst@InfoWarning{Gobble aspect `#1'}%
|
|
|
+ \expandafter\@gobblefour %
|
|
|
+ \fi %
|
|
|
+ \lstdefine@key{lst}{#1}}
|
|
|
+% \end{macrocode}
|
|
|
+% Now come renamed copies from two \textsf{keyval} macros, but the key definitions are made globally.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstdefine@key#1#2{%
|
|
|
+ \@ifnextchar[{\lstKV@def{#1}{#2}}{\global\@namedef{KV@#1@#2}####1}}
|
|
|
+\def\lstKV@def#1#2[#3]{%
|
|
|
+ \global\@namedef{KV@#1@#2@default\expandafter}\expandafter %
|
|
|
+ {\csname KV@#1@#2\endcsname{#3}}%
|
|
|
+ \global\@namedef{KV@#1@#2}##1}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\let\lst@ifnew\iftrue % init
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@AddToHook}
|
|
|
+% \begin{macro}{\lst@AddToHookAtTop}
|
|
|
+% The definitions are mainly in terms of |\lst@AddTo| and |\lst@AddToAtTop|.
|
|
|
+% But we test whether the hook already exists.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@AddToHook#1{%
|
|
|
+ \lst@ifnew %
|
|
|
+ \@ifundefined{lsthk@#1}{%
|
|
|
+%<info> \lst@InfoInfo{New hook `#1'}%
|
|
|
+ \expandafter\gdef\csname lsthk@#1\endcsname{}}{}%
|
|
|
+ \def\lst@next{\lst@AddToHook@\lst@AddTo{#1}}%
|
|
|
+ \expandafter\lst@next %
|
|
|
+ \else %
|
|
|
+ \expandafter\@gobble %
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% The submacro makes it possible to use \texttt{if}s inside the second argument (which is the third here).
|
|
|
+% \begin{macrocode}
|
|
|
+\long\def\lst@AddToHook@#1#2#3{%
|
|
|
+ \expandafter#1\csname lsthk@#2\endcsname{#3}}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{TODO}
|
|
|
+% The usage of |\lst@ifnew| is still unsatisfactory:
|
|
|
+% Defining an aspect and its hooks twice doesn't add the \TeX\ material a second time, but defining hooks and then the aspect would do so.
|
|
|
+% \end{TODO}
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@AddToHookAtTop#1{%
|
|
|
+ \lst@ifnew %
|
|
|
+ \@ifundefined{lsthk@#1}{%
|
|
|
+%<info> \lst@InfoInfo{New hook `#1'}%
|
|
|
+ \expandafter\gdef\csname lsthk@#1\endcsname{}}{}%
|
|
|
+ \def\lst@next{\lst@AddToHook@\lst@AddToAtTop{#1}}%
|
|
|
+ \expandafter\lst@next %
|
|
|
+ \else %
|
|
|
+ \expandafter\@gobble %
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}\end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@AddTo}
|
|
|
+% \begin{macro}{\lst@AddToAtTop}
|
|
|
+% These macros add the second argument to the macro |#1|.
|
|
|
+% But the definition is global!
|
|
|
+% \begin{macrocode}
|
|
|
+\long\def\lst@AddTo#1#2{%
|
|
|
+ \expandafter\gdef\expandafter#1\expandafter{#1#2}}
|
|
|
+% \end{macrocode}
|
|
|
+% We need a couple of |\expandafter|s now.
|
|
|
+% Simply note that we have\\
|
|
|
+% {\small\hspace*{2em}
|
|
|
+% |\expandafter\gdef\expandafter#1\expandafter{\lst@temp|$\langle$\textit{contents of }|#1|$\rangle$|}|
|
|
|
+% }\\
|
|
|
+% after the first phase of expansion.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@AddToAtTop#1#2{\def\lst@temp{#2}%
|
|
|
+ \expandafter\expandafter\expandafter\gdef %
|
|
|
+ \expandafter\expandafter\expandafter#1%
|
|
|
+ \expandafter\expandafter\expandafter{\expandafter\lst@temp#1}}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}\end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@lAddTo}
|
|
|
+% A local version of |\lst@AddTo|.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@lAddTo#1#2{\expandafter\def\expandafter#1\expandafter{#1#2}}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
+% \noindent Since some hooks are unused and never defined by the hook macros above, we define them here:
|
|
|
+% \begin{macrocode}
|
|
|
+\global\let\lsthk@OutputOther\@empty
|
|
|
+\global\let\lsthk@SetStyle\@empty
|
|
|
+\global\let\lsthk@SetLanguage\@empty
|
|
|
+\global\let\lsthk@PreSet\@empty
|
|
|
+\global\let\lsthk@PostSet\@empty
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%</kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Interfacing with \textsf{keyval}}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%<*kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+% The \textsf{keyval} package passes the value via the one and only paramater |#1| to the definition part of the aspect macro.
|
|
|
+% The following commands may be used to analyse the value.
|
|
|
+% \begin{macrosyntax}
|
|
|
+% \item |\lstKV@SetIfKey|\meta{macro}|{#1}|
|
|
|
+%
|
|
|
+% \meta{macro} becomes true (more precisely |\iftrue|) if the first character of |#1| equals |t| or |T|.
|
|
|
+% It becomes false otherwise.
|
|
|
+%
|
|
|
+% \item |\lstKV@OptArg|\meta{submacro}|[|\meta{default arg.}|]{#1}|
|
|
|
+%
|
|
|
+% calls \meta{submacro} with |#1| and with inserted |[|\meta{default arg.}|]| if |#1| has no optional argument.
|
|
|
+% \end{macrosyntax}
|
|
|
+%
|
|
|
+% \begin{macro}{\lstKV@SetIfKey}
|
|
|
+% We simply test the first character of |#2|.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstKV@SetIfKey#1#2{\lstKV@SetIfKey@#1#2\relax}
|
|
|
+\def\lstKV@SetIfKey@#1#2#3\relax{\lowercase{%
|
|
|
+ \expandafter\let\expandafter#1%
|
|
|
+ \csname \ifx #2t}iftrue\else iffalse\fi\endcsname}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lstKV@OptArg}
|
|
|
+% We read the arguments and insert default if necesary, what else?
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstKV@OptArg#1[#2]#3{\lstKV@OptArg@{#1}{#2}#3\@}
|
|
|
+\def\lstKV@OptArg@#1#2{%
|
|
|
+ \@ifnextchar[{\lstKV@OptArg@@{#1}}%
|
|
|
+ {\lstKV@OptArg@@{#1}[#2]}}
|
|
|
+\def\lstKV@OptArg@@#1[#2]#3\@{#1[#2]{#3}}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lstset}
|
|
|
+% Finally this main user interface macro:
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstset#1{\lsthk@PreSet\setkeys{lst}{#1}\lsthk@PostSet}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%</kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Internal modes}\label{iInternalModes}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%<*kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+% \begin{macro}{\lst@mode}
|
|
|
+% \begin{macro}{\lst@EnterMode}
|
|
|
+% \begin{macro}{\lst@LeaveMode}
|
|
|
+% While typesetting a listing we will enter 'modes' to distinguish comments from strings, comment lines from single comments, \TeX\ comment lines from fixed comment lines, and so on.
|
|
|
+% The counter |\lst@mode| keeps the current mode number.
|
|
|
+% \begin{macrocode}
|
|
|
+\newcount\lst@mode
|
|
|
+% \end{macrocode}
|
|
|
+% Each mode opens a group level, stores the mode number and execute mode specific tokens.
|
|
|
+% Moreover we keep all these changes in mind (locally).
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@EnterMode#1#2{%
|
|
|
+ \bgroup \lst@mode=#1\relax #2%
|
|
|
+ \lst@lAddTo\lst@entermodes{\lst@EnterMode{#1}{#2}}}
|
|
|
+% \end{macrocode}
|
|
|
+% Leaving a mode simply closes the group and calls the hook |\lsthk@EndGroup|.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@LeaveMode{\egroup\lsthk@EndGroup}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@AddToHook{InitVars}{\let\lst@entermodes\@empty}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}\end{macro}\end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@NewMode}
|
|
|
+% defines a new mode number.
|
|
|
+% We simply use |\mathchardef| and advance the number in |\lst@newmode|, which is a macro --- we don't waste another counter.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@NewMode#1{%
|
|
|
+ \ifx\@undefined#1%
|
|
|
+ \global\mathchardef#1=\lst@newmode\relax %
|
|
|
+ \lst@mode=\lst@newmode\relax \advance\lst@mode\@ne %
|
|
|
+ \edef\lst@newmode{\the\lst@mode}%
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% We start with number 0.
|
|
|
+% The negative range is reserved for nested comments.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@newmode{0}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@nomode}
|
|
|
+% \begin{macro}{\lst@Pmode}
|
|
|
+% The very first mode initializes |\lst@mode| (every listing).
|
|
|
+% The other mode indicates active listing processing.
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@NewMode\lst@nomode
|
|
|
+\lst@AddToHook{InitVars}{\lst@modefalse \lst@mode\lst@nomode}
|
|
|
+\lst@NewMode\lst@Pmode
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}\end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@modetrue}
|
|
|
+% \begin{macro}{\lst@modefalse}
|
|
|
+% If |\lst@ifmode| is true, no mode change is allowed --- except leaving the mode.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@modetrue{\let\lst@ifmode\iftrue}
|
|
|
+\def\lst@modefalse{\let\lst@ifmode\iffalse}
|
|
|
+% \end{macrocode}
|
|
|
+% Note: |\lst@ifmode| is \emph{not} obsolete since |\lst@mode|$\neq$|\lst@nomode| does \emph{not} imply |\lst@ifmode|$=$|\iftrue|.
|
|
|
+% And even the other implication is not true.
|
|
|
+% It will happen that we enter a mode without setting |\lst@ifmode| true, and we'll set it true without assigning any mode!
|
|
|
+% \end{macro}\end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@InterruptModes}
|
|
|
+% \begin{macro}{\lst@ReenterModes}
|
|
|
+% Since we kept all mode changes in mind, it is possible two interrupt and re-enter the current mode.
|
|
|
+% This is useful for \TeX\ comment lines, for example.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@InterruptModes{%
|
|
|
+ \ifx\lst@entermodes\@empty\else %
|
|
|
+ \global\let\lst@reenter\lst@entermodes %
|
|
|
+ \lst@LeaveAllModes %
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% The last |\ifx| is not necessay since empty |\lst@entermodes| implies that we don't leave any mode.
|
|
|
+% But we need the |\ifx| in the following macro since empty |\lst@reenter| doesn't tell us anything about the current mode.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@ReenterModes{%
|
|
|
+ \ifx\lst@reenter\@empty\else %
|
|
|
+ \lst@LeaveAllModes \lst@reenter %
|
|
|
+ \global\let\lst@reenter\@empty %
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@AddToHook{InitVars}{\global\let\lst@reenter\@empty}
|
|
|
+% \end{macrocode}
|
|
|
+% Note that these macros can't be nested:
|
|
|
+% If you 'interrupt modes', enter some modes and say 'interrupt modes' again, then two 're-enter modes' will \emph{not} take you back in front of the first 'interrupt modes'.
|
|
|
+% \end{macro}\end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@LeaveAllModes}
|
|
|
+% This is some kind of emergency macro.
|
|
|
+% Since any mode is terminated by closing a group, leaving all modes means closing groups until the mode equals |\lst@nomode|.
|
|
|
+% We'll need that macro to end a listing correctly.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@LeaveAllModes{%
|
|
|
+ \ifnum\lst@mode=\lst@nomode %
|
|
|
+ \expandafter\lsthk@EndGroup %
|
|
|
+ \else %
|
|
|
+ \expandafter\egroup\expandafter\lst@LeaveAllModes %
|
|
|
+ \fi}
|
|
|
+\lst@AddToHook{ExitVars}{\lst@LeaveAllModes}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@egroupmode}
|
|
|
+% We allocate a 'processing mode' and define a general purpose 'egroup' mode: close a group at end of line.
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@NewMode\lst@egroupmode
|
|
|
+\lst@AddToHook{EOL}
|
|
|
+ {\ifnum\lst@mode=\lst@egroupmode \lst@LeaveMode \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%</kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Styles and languages}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%<*kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+% \begin{macro}{\lst@Normalize}
|
|
|
+% normalizes the contents of the macro |#1| by making all characters lower case and stripping off spaces.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@Normalize#1{%
|
|
|
+ \lowercase\expandafter{\expandafter\edef\expandafter#1%
|
|
|
+ \expandafter{\expandafter\zap@space#1 \@empty}}}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lstdefinestyle}
|
|
|
+% The internal macro name of a style is |\lststy@|\emph{the style} (normalized).
|
|
|
+% If called, it simply sets the keys to given values.
|
|
|
+% \begin{macrocode}
|
|
|
+\newcommand\lstdefinestyle[2]{%
|
|
|
+ \def\lst@temp{lststy@#1}\lst@Normalize\lst@temp %
|
|
|
+ \global\@namedef\lst@temp{\setkeys{lst}{#2}}}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{aspect}{style}
|
|
|
+% We give an error message if the necessary macro doesn't exist.
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@Aspect{style}
|
|
|
+ {\def\lst@temp{lststy@#1}\lst@Normalize\lst@temp %
|
|
|
+ \@ifundefined\lst@temp %
|
|
|
+ {\PackageError{Listings}{Style `#1' undefined}%
|
|
|
+ {You might have misspelt the name here or before.^^J%
|
|
|
+ Type <RETURN> to proceed without changing the style.}}%
|
|
|
+% \end{macrocode}
|
|
|
+% Otherwise we execute the hook and call the macro.
|
|
|
+% \begin{macrocode}
|
|
|
+ {\lsthk@SetStyle \csname\lst@temp\endcsname %
|
|
|
+%<info> \lst@InfoInfo{\expandafter\string %
|
|
|
+%<info> \csname\lst@temp\endcsname\space called}%
|
|
|
+ }}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{TODO}
|
|
|
+% It's easy to crash the listings package with |style| (and also with |language|).
|
|
|
+% Define |\lstdefinestyle{crash}{style=crash}| and write |\lstset{style=crash}|.
|
|
|
+% \TeX's capacity will exceed (parameter stack size), sorry.
|
|
|
+% Only bad girls use such recursive calls, but only good girls use this package.
|
|
|
+% Thus this problem is of minor interest.
|
|
|
+% \end{TODO}
|
|
|
+% \end{aspect}
|
|
|
+%
|
|
|
+% \begin{macro}{\lstdefinelanguage}
|
|
|
+% Nearly |\lstdefinestyle|:
|
|
|
+% \begin{macrocode}
|
|
|
+\newcommand\lstdefinelanguage[3][]{%
|
|
|
+ \def\@tempa{#2@#1}\lst@Normalize\@tempa %
|
|
|
+ \global\@namedef{lstlang@\@tempa}{\lstset{#3}}}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lstdefinedrvlanguage}
|
|
|
+% The driver file \texttt{lstpascal.sty} contains a couple of Pascal dialects.
|
|
|
+% It is unnecessary to hold all these dialects in memory if the user selects Standard Pascal only.
|
|
|
+% There are different scopes:
|
|
|
+% \begin{itemize}
|
|
|
+% \item[--] All code outside any (style or language) definition is executed.
|
|
|
+% Definitions should be |\global| since a driver file is input inside a group.
|
|
|
+% Note also that |@| is a letter and |"| has catcode 12 (other).
|
|
|
+% \item[--] All languages declared with |\lstdefinelanguage| are defined.
|
|
|
+% \item[--] A language declared with |\lstdefinedrvlanguage| is defined if and only if the user has requested that language.
|
|
|
+% \end{itemize}
|
|
|
+% We either do the definition or drop it:
|
|
|
+% \begin{macrocode}
|
|
|
+\newcommand\lstdefinedrvlanguage[3][]{%
|
|
|
+ \def\@tempa{lstlang@#2@#1}\lst@Normalize\@tempa %
|
|
|
+ \ifx\@tempa\lst@requested %
|
|
|
+ \global\@namedef{\@tempa}{\lstset{#3}}%
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{TODO}
|
|
|
+% The command syntax is liable to changes.
|
|
|
+% I conjecture that it will be something like the following.
|
|
|
+% \begin{macrosyntax}
|
|
|
+% \item[0.2] |\lstdefinedrvlanguage|[|[|\meta{dialect}|]|]|{|\meta{language}|}|\\
|
|
|
+% \qquad[|[|\meta{base dialect}|]|]|{|\meta{base language (e.g.\ empty)}|}|\\
|
|
|
+% \qquad|{|\meta{key=value list}|}|\\
|
|
|
+% \qquad[|[|\meta{list of extras (keywordcomments,texcs,etc.)}|]|]
|
|
|
+% \end{macrosyntax}
|
|
|
+% To make 'extras' user assessible (without loading a language) a command |\lstloadextras| would be nice.
|
|
|
+% In any case such a macro is needed to load the extras for the supported languages.
|
|
|
+% All in all there should be the following files in future: The kernel |listings.sty|, the language definitions in |lstdrvrs.sty| (or |lstdef.sty|?) and extras in a file |lstextra.sty|.
|
|
|
+% \end{TODO}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lstloadlanguages}
|
|
|
+% We iterate through the list and locate and load each language.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstloadlanguages#1{\lstloadlanguages@#1,\relax,}
|
|
|
+\def\lstloadlanguages@#1,{%
|
|
|
+ \ifx\relax#1\@empty \else %
|
|
|
+ \lstKV@OptArg\lstloadlanguages@@[]{#1}%
|
|
|
+ \expandafter\lstloadlanguages@ %
|
|
|
+ \fi}
|
|
|
+\def\lstloadlanguages@@[#1]#2{%
|
|
|
+ \lst@LocateLanguage[#1]{#2}%
|
|
|
+ \@ifundefined{\lst@requested}%
|
|
|
+ {{\catcode`\^^M=9\catcode`\"=12\makeatletter %
|
|
|
+ \input{\[email protected]}}}%
|
|
|
+ {}}
|
|
|
+\@onlypreamble\lstloadlanguages
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{aspect}{language}
|
|
|
+% If the language macro |\lstlang@|\emph{language}|@|\emph{dialect} doesn't exist, we must load the driver file.
|
|
|
+% In that case the character |@| becomes a letter and we change the catcode of the double quote for compatibility with \texttt{german.sty}.
|
|
|
+% Moreover we make the EOL character being ignored (which removes unwanted spaces if we've forgotten |%| at end of line).
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@Aspect{language}{\lstKV@OptArg\lstlanguage@[]{#1}}
|
|
|
+\def\lstlanguage@[#1]#2{%
|
|
|
+ \lst@LocateLanguage[#1]{#2}%
|
|
|
+ \@ifundefined{\lst@requested}%
|
|
|
+ {{\catcode`\^^M=9\catcode`\"=12\makeatletter %
|
|
|
+ \input{\[email protected]}}}{}%
|
|
|
+% \end{macrocode}
|
|
|
+% We give an error message, if the language/dialect is undefined now.
|
|
|
+% \begin{macrocode}
|
|
|
+ \@ifundefined{\lst@requested}%
|
|
|
+ {\PackageError{Listings}%
|
|
|
+ {\ifx\@empty\lst@dialect@\else \lst@dialect@\space of \fi %
|
|
|
+ \lst@language@\space undefined}{The driver file is not
|
|
|
+ loadable or doesn't support the language.^^J%
|
|
|
+ Type <RETURN> to proceed without changing the language.}}%
|
|
|
+% \end{macrocode}
|
|
|
+% Otherwise we execute the hook and select the language.
|
|
|
+% \begin{macrocode}
|
|
|
+ {\lsthk@SetLanguage %
|
|
|
+%<info> \lst@InfoInfo{\expandafter\string %
|
|
|
+%<info> \csname\lst@requested\endcsname\space called}%
|
|
|
+ \csname\lst@requested\endcsname %
|
|
|
+ \def\lst@language{#1}\lst@Normalize\lst@language %
|
|
|
+ \def\lst@dialect{#2}\lst@Normalize\lst@dialect}}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{aspect}
|
|
|
+%
|
|
|
+% \begin{aspect}{defaultdialect}
|
|
|
+% We simply store the dialect.
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@Aspect{defaultdialect}{\lstKV@OptArg\lstdefaultdialect@[]{#1}}
|
|
|
+\def\lstdefaultdialect@[#1]#2{%
|
|
|
+ \def\lst@temp{#2}\lst@Normalize\lst@temp %
|
|
|
+ \global\@namedef{lstdd@\lst@temp}{#1}}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{aspect}
|
|
|
+%
|
|
|
+% Languages might have a user name and a different internal name.
|
|
|
+% Moreover we don't always use the standard driver file |lst|\meta{language}|.sty|.
|
|
|
+% If the user writes |language=[fuu]foo|, this could mean that we select (internally) dialect |faa| of language |fee|, which is located in driver file |fii.sty|.
|
|
|
+% We define the following macros:
|
|
|
+% \begin{macrosyntax}
|
|
|
+% \item |\lst@DriverLocation{|\meta{language}|}{|\meta{file name without extension}|}|
|
|
|
+%
|
|
|
+% Afterwards the package inputs the given driver file to load the language.
|
|
|
+%
|
|
|
+% \item |\lst@LocateLanguage[|\meta{dialect}|]{|\meta{language}|}|
|
|
|
+%
|
|
|
+% returns the driver file name in |\lst@driver| and |\lst@requested| contains name of driver macro (i.e.\ with prefix |lstlang@|, without backslash).
|
|
|
+% The macro automatically chooses aliases.
|
|
|
+% \end{macrosyntax}
|
|
|
+% All language and dialect arguments are standardized, i.e.\ we make them free of spaces and lower case.
|
|
|
+%
|
|
|
+% \begin{macro}{\lstalias}
|
|
|
+% The names are stored in |\lsta@|\emph{language}|@|\emph{dialect} and |\lstaa@|\emph{language}.
|
|
|
+% \begin{macrocode}
|
|
|
+\newcommand\lstalias{\@ifnextchar[{\lstalias@}{\lstalias@@}}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstalias@[#1]#2[#3]#4{%
|
|
|
+ \def\lst@temp{lsta@#2@#1}\lst@Normalize\lst@temp %
|
|
|
+ \global\@namedef{\lst@temp}{#4@#3}}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstalias@@#1#2{%
|
|
|
+ \def\lst@temp{lstaa@#1}\lst@Normalize\lst@temp %
|
|
|
+ \global\@namedef{\lst@temp}{#2}}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@DriverLocation}
|
|
|
+% We simply define a macro containing the file name.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@DriverLocation#1#2{%
|
|
|
+ \def\lst@temp{lstloc@#1}\lst@Normalize\lst@temp %
|
|
|
+ \expandafter\gdef\csname\lst@temp\endcsname{#2}%
|
|
|
+ \expandafter\lst@Normalize\csname\lst@temp\endcsname}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@LocateLanguage}
|
|
|
+% First we test for a language alias, \ldots
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@LocateLanguage[#1]#2{%
|
|
|
+ \def\lst@language@{#2}\lst@Normalize\lst@language@ %
|
|
|
+ \@ifundefined{lstaa@\lst@language@}{}%
|
|
|
+ {\edef\lst@language@{\csname lstaa@\lst@language@\endcsname}%
|
|
|
+ \lst@Normalize\lst@language@}%
|
|
|
+% \end{macrocode}
|
|
|
+% then we set the default dialect if necessary.
|
|
|
+% \begin{macrocode}
|
|
|
+ \def\lst@dialect@{#1}%
|
|
|
+ \ifx\@empty\lst@dialect@ %
|
|
|
+ \@ifundefined{lstdd@\lst@language@}{}%
|
|
|
+ {\expandafter\let\expandafter\lst@dialect@ %
|
|
|
+ \csname lstdd@\lst@language@\endcsname}%
|
|
|
+ \fi %
|
|
|
+ \lst@Normalize\lst@dialect@ %
|
|
|
+% \end{macrocode}
|
|
|
+% Now we are ready for an alias for a language dialect.
|
|
|
+% \begin{macrocode}
|
|
|
+ \edef\lst@requested{\lst@language@ @\lst@dialect@}%
|
|
|
+ \@ifundefined{lsta@\lst@requested}{}%
|
|
|
+ {\expandafter\let\expandafter\lst@requested %
|
|
|
+ \csname lsta@\lst@requested\endcsname %
|
|
|
+ \lst@Normalize\lst@requested}%
|
|
|
+% \end{macrocode}
|
|
|
+% Finally we get the driver file name and set the default dialect.
|
|
|
+% \begin{macrocode}
|
|
|
+ \expandafter\lst@LocateLanguage@\lst@requested\relax}
|
|
|
+\def\lst@LocateLanguage@#1@#2\relax{%
|
|
|
+ \edef\lst@driver{\@ifundefined{lstloc@#1}{lst#1}%
|
|
|
+ {\csname lstloc@#1\endcsname}}%
|
|
|
+ \ifx\@empty#2\@empty %
|
|
|
+ \@ifundefined{lstdd@#1}%
|
|
|
+ {\def\lst@dialect@{#2}}%
|
|
|
+ {\expandafter\let\expandafter\lst@dialect@ %
|
|
|
+ \csname lstdd@#1\endcsname}%
|
|
|
+ \fi %
|
|
|
+ \edef\lst@requested{lstlang@#1@\lst@dialect@}%
|
|
|
+ \lst@Normalize\lst@requested}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%</kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+%
|
|
|
+%
|
|
|
+% \section{Typesetting a listing}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%<*kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+% \begin{macro}{\lst@lineno}
|
|
|
+% This counter keeps the current line number.
|
|
|
+% A register is global if and only if the allocation line shows |% \global|.
|
|
|
+% \begin{macrocode}
|
|
|
+\newcount\lst@lineno \global\lst@lineno\@ne % \global
|
|
|
+% \end{macrocode}
|
|
|
+% The counter is initialized and advances every line (which means |\everypar|).
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@AddToHook{InitVars}
|
|
|
+ {\global\lst@lineno\@ne %
|
|
|
+ \expandafter\everypar\expandafter{\the\everypar %
|
|
|
+ \global\advance\lst@lineno\@ne}}
|
|
|
+% \end{macrocode}
|
|
|
+% And we (try to) ensure correct line numbers for continued listings.
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@AddToHook{ExitVars}
|
|
|
+ {\ifx\lst@NewLine\relax\else %
|
|
|
+ \global\advance\lst@lineno-2\relax %
|
|
|
+ \setbox\@tempboxa\vbox{\lst@NewLine}%
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{TODO}
|
|
|
+% We only try to.
|
|
|
+% If there is source code before |\end{lstlisting}|, it goes wrong: the line number is one too less.
|
|
|
+% \end{TODO}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@PrintFileName}
|
|
|
+% makes use of |\lst@ReplaceIn|:
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@PrintFileName#1{%
|
|
|
+ \def\lst@arg{#1}%
|
|
|
+ \lst@ReplaceIn\lst@arg{_\textunderscore $\textdollar -\textendash}%
|
|
|
+ \lst@arg}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@SetName}
|
|
|
+% As proposed by \lsthelper{Boris Veytsman}{[email protected]}{1998/03/22}{listing name accessible for user} the name of a listing (file name or argument to the environment) is user accessible now.
|
|
|
+% It is set using this macro:
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@SetName#1{%
|
|
|
+ \gdef\lst@intname{#1}\global\let\lstintname\lst@intname %
|
|
|
+ \let\lst@arg\lst@intname %
|
|
|
+ \lst@ReplaceIn\lst@arg{_\textunderscore $\textdollar -\textendash}%
|
|
|
+ \global\let\lstname\lst@arg}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%</kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{List of listings}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%<*kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+% \begin{macro}{\listoflistings}
|
|
|
+% Instead of imitating |\listoffigures| we make some local adjustments and call |\tableofcontents|.
|
|
|
+% This has the advantage that redefinitions (e.g.\ without any |\MakeUppercase| inside) also take effect on the list of listings.
|
|
|
+% \begin{macrocode}
|
|
|
+\newcommand\listoflistings{\bgroup %
|
|
|
+ \let\contentsname\listlistingsname %
|
|
|
+ \let\lst@temp\@starttoc \def\@starttoc##1{\lst@temp{lol}}%
|
|
|
+ \tableofcontents \egroup}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\listlistingsname}
|
|
|
+% Simply the header name:
|
|
|
+% \begin{macrocode}
|
|
|
+\newcommand\listlistingsname{Listings}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@AddToLOL}
|
|
|
+% adds an entry to the list of listings.
|
|
|
+% The first parameter is the name of the listing and the second is unused so far.
|
|
|
+% \begin{macrocode}
|
|
|
+\newcommand\lst@AddToLOL[2]{%
|
|
|
+ \ifx\@empty#1\@empty \else %
|
|
|
+ \addtocontents{lol}{\protect\lstlolline{#1}{#2}%
|
|
|
+ {\lst@language}{\thepage}}%
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lstlolline}
|
|
|
+% prints one 'lol' line.
|
|
|
+% Using |\lst@PrintFileFile| removes a bug first reported by \lsthelper{Magne Rudshaug}{[email protected]}{1998/01/09}{_ and list of listings}.
|
|
|
+% \begin{macrocode}
|
|
|
+\newcommand\lstlolline[4]{%
|
|
|
+ \@dottedtocline{1}{1.5em}{2.3em}{\lst@PrintFileName{#1}}{#4}}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%</kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Init and EOL}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%<*kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+% We need some macros to initialize registers and variables before typesetting a listing and for the update every line.
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@Init}
|
|
|
+% The argument |#1| (assigned at the end) is either |\relax| or |\lstenv@backslash| since the backslash has a special meaning for the environment.
|
|
|
+% The line number is used as current label (proposed by \lsthelper{Boris Veytsman}{[email protected]}{1998/03/25}{make line numbers referenced via \label and \ref}).
|
|
|
+% The end of line character chr(13)=|^^M| controls the processing, see the definition of |\lst@MProcessListing| below.
|
|
|
+% The vertical space in the macro code is for clarity.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@Init#1{%
|
|
|
+ \begingroup \normalbaselines \smallbreak %
|
|
|
+ \def\@currentlabel{\the\lst@lineno}%
|
|
|
+ \lst@prelisting %
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+ \lsthk@BeforeSelectCharTable %
|
|
|
+ \normalbaselines \everypar{\lsthk@EveryLine}%
|
|
|
+ \lsthk@InitVars \lsthk@InitVarsEOL %
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+ \csname lstPre@\lst@language\endcsname %
|
|
|
+ \csname lstPre@\lst@language @\lst@dialect\endcsname %
|
|
|
+ \lstCC@Let{"000D}\lst@MProcessListing %
|
|
|
+ \let\lstCC@Backslash#1%
|
|
|
+ \lst@EnterMode{\lst@Pmode}{\lst@SelectCharTable}}
|
|
|
+% \end{macrocode}
|
|
|
+% Note: From version 0.19 on 'listing processing' is implemented as an internal mode, namely a mode with special character table.
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@AddToHook{InitVars}
|
|
|
+ {\rightskip\z@ \leftskip\z@ \parfillskip=0pt plus 1fil %
|
|
|
+ \let\par\@@par}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@DeInit}
|
|
|
+% Here we output the remaining characters, update some variables and do some other things.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@DeInit{%
|
|
|
+ \lst@PrintToken \lst@EOLUpdate \par\removelastskip %
|
|
|
+ \lsthk@ExitVars %
|
|
|
+ \smallbreak\lst@postlisting %
|
|
|
+ \endgroup}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@EOLUpdate}
|
|
|
+% This macro seems to be obsolete since in version 0.19 it degenerates to
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@EOLUpdate{\lsthk@EOL \lsthk@InitVarsEOL}%
|
|
|
+% \end{macrocode}
|
|
|
+% But in future it might come in handy again.
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@MProcessListing}
|
|
|
+% This is what we have to do at EOL while processing a listing.
|
|
|
+% We output all remaining characters and update the variables.
|
|
|
+% We call |\endinput| if the next line number is greater than the last printing line.
|
|
|
+% Finally we gobble characters to come to beginning of line.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@MProcessListing{%
|
|
|
+ \lst@PrintToken \lst@EOLUpdate %
|
|
|
+ \ifnum\lst@lastline<\lst@lineno \expandafter\endinput \fi %
|
|
|
+ \lst@BOLGobble}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@BOLGobble}
|
|
|
+% But this is initially |\relax|.
|
|
|
+% \begin{macrocode}
|
|
|
+\let\lst@BOLGobble\relax
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%</kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{The input command}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%<*kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+% \begin{TODO}
|
|
|
+% There is a conflict concerning |\lst@firstline|: It contains either the line number of the first code line or line number.
|
|
|
+% This must be clarified before |lstlisting| can use the keys |first| and |last|.
|
|
|
+% \end{TODO}
|
|
|
+%
|
|
|
+% \begin{aspect}{print}
|
|
|
+% \begin{aspect}{first}
|
|
|
+% \begin{aspect}{last}
|
|
|
+% These aspects affect the input command only, not the environment.
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@Aspect{print}[t]{\lstKV@SetIfKey\lst@ifprint{#1}}
|
|
|
+\lst@Aspect{first}{\def\lst@firstline{#1}}
|
|
|
+\lst@Aspect{last}{\def\lst@lastline{#1}}
|
|
|
+\lstset{print=true}% init
|
|
|
+% \end{macrocode}
|
|
|
+% \end{aspect}\end{aspect}\end{aspect}
|
|
|
+%
|
|
|
+% \begin{macro}{\lstinputlisting}
|
|
|
+% We define the main command.
|
|
|
+% First we take care of the optional paramater and set it to $[1,9999999]$ if none is given.
|
|
|
+% \begin{macrocode}
|
|
|
+\newcommand\lstinputlisting[2][]{%
|
|
|
+ \begingroup %
|
|
|
+ \def\lst@firstline{1}\def\lst@lastline{9999999}\lstset{#1}%
|
|
|
+ \IfFileExists{#2}{\lst@InputListing{#2}}%
|
|
|
+ {\filename@parse{#2}%
|
|
|
+ \edef\reserved@a{\noexpand\lst@MissingFileError
|
|
|
+ {\filename@area\filename@base}%
|
|
|
+ {\ifx\filename@ext\relax tex\else\filename@ext\fi}}%
|
|
|
+ \reserved@a}%
|
|
|
+ \endgroup %
|
|
|
+ \lsthk@OnExit}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@MissingFileError}
|
|
|
+% is a derivation of \LaTeX's |\@missingfileerror|:
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@MissingFileError#1#2{%
|
|
|
+ \typeout{^^J! Package Listings Error: File `#1.#2' not found.^^J^^J%
|
|
|
+ Type X to quit or <RETURN> to proceed,^^J%
|
|
|
+ or enter new name. (Default extension: #2)^^J}%
|
|
|
+ \message{Enter file name: }%
|
|
|
+ {\endlinechar\m@ne \global\read\m@ne to\@gtempa}%
|
|
|
+% \end{macrocode}
|
|
|
+% Typing |x| or |X| exits.
|
|
|
+% \begin{macrocode}
|
|
|
+ \ifx\@gtempa\@empty \else %
|
|
|
+ \def\reserved@a{x}\ifx\reserved@a\@gtempa\batchmode\@@end\fi
|
|
|
+ \def\reserved@a{X}\ifx\reserved@a\@gtempa\batchmode\@@end\fi
|
|
|
+% \end{macrocode}
|
|
|
+% In all other cases we try the new file name (with default extension).
|
|
|
+% \begin{macrocode}
|
|
|
+ \filename@parse\@gtempa %
|
|
|
+ \edef\filename@ext{%
|
|
|
+ \ifx\filename@ext\relax#2\else\filename@ext\fi}%
|
|
|
+ \edef\reserved@a{\noexpand\IfFileExists %
|
|
|
+ {\filename@area\filename@base.\filename@ext}%
|
|
|
+ {\noexpand\lst@InputListing %
|
|
|
+ {\filename@area\filename@base.\filename@ext}}%
|
|
|
+ {\noexpand\lst@MissingFileError
|
|
|
+ {\filename@area\filename@base}{\filename@ext}}}%
|
|
|
+ \expandafter\reserved@a %
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@InputListing}
|
|
|
+% The one and only argument is the file name.
|
|
|
+% We either add this name to the list of listings or the name plus a bullet to indicate that the listing has been skipped.
|
|
|
+% Note that |\lst@Init| takes |\relax| as an argument.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@InputListing#1{%
|
|
|
+ \lst@SetName{#1}%
|
|
|
+ \lst@ifprint %
|
|
|
+ \lst@AddToLOL{#1}{}%
|
|
|
+ \lst@Init\relax \lst@SkipUptoFirst \input{#1}\lst@DeInit %
|
|
|
+ \else %
|
|
|
+ \lst@AddToLOL{#1$^\bullet$}{}%
|
|
|
+ \begin{center}%
|
|
|
+ \footnotesize --- Listing of #1 has been skipped. ---
|
|
|
+ \end{center}%
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@SkipUptoFirst}
|
|
|
+% The end of line character either processes the listing or is responsible for skipping lines upto first printing line.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@SkipUptoFirst{%
|
|
|
+ \ifnum\lst@lineno=\lst@firstline\else %
|
|
|
+% \end{macrocode}
|
|
|
+% To skip input lines we begin a new group level (which makes our changes local) and prohibit mode changes.
|
|
|
+% We redefine the end of line character and all output macros becomes equivalent to |\relax|, i.e.\ nothing is typeset.
|
|
|
+% \begin{macrocode}
|
|
|
+ \bgroup \lst@modetrue %
|
|
|
+ \let\lst@Output\relax \let\lst@OutputOther\relax %
|
|
|
+ \let\lst@GotoTabStop\relax %
|
|
|
+ \lstCC@Let{"000D}\lst@MSkipUptoFirst %
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@MSkipUptoFirst}
|
|
|
+% At the moment we use a fast and not 'everything is looking good' way.
|
|
|
+% When |\lst@MSkipUptoFirst| is executed, one input line has already been skipped.
|
|
|
+% We end the group opened in |\lst@SkipUptoFirst|.
|
|
|
+% This restores the definition of the end of line character chr(13).
|
|
|
+% Then we look whether to skip more lines or not.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@MSkipUptoFirst{\egroup %
|
|
|
+ \global\advance\lst@lineno\@ne %
|
|
|
+ \ifnum\lst@lineno=\lst@firstline\else %
|
|
|
+ \expandafter\lst@MSkipUptoFirst@ %
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% The argument of |\lst@MSkipUptoFirst@| ends with the next active chr(13), which means that the next input line is read.
|
|
|
+% Again we look whether to skip more lines or not.
|
|
|
+% \begin{macrocode}
|
|
|
+\begingroup \lccode`\~=`\^^M%
|
|
|
+\lowercase{\gdef\lst@MSkipUptoFirst@#1~}{%
|
|
|
+ \global\advance\lst@lineno\@ne %
|
|
|
+ \ifnum\lst@lineno=\lst@firstline\else %
|
|
|
+ \expandafter\lst@MSkipUptoFirst@ %
|
|
|
+ \fi}
|
|
|
+\endgroup
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{TODO}
|
|
|
+% This definition gives rise to a ''runaway argument'' if first line doesn't exist (no |^^M| is found).
|
|
|
+%
|
|
|
+% We could define |\lst@MSkipUptoFirst| exactly as |\lst@MProcessListing|, except that we start the normal line processing if we reach the first printing line.
|
|
|
+% In that case all comments and strings are processed, but not output.
|
|
|
+% Everything looks good, even if the first printing line is in the middle of a comment.
|
|
|
+% We need to do the following things:
|
|
|
+% \begin{enumerate}
|
|
|
+% \item Install an \texttt{if} to choose between speed and good looking, which must be noticed in |\lst@SkipUptoFirst|.
|
|
|
+% There we must (locally) switch to |\lsttexcloff|.
|
|
|
+% \item Call |\lst@BeginDropOutput{\lst@nomode}| in |\lst@SkipUptoFirst| instead of |\bgroup\lst@modetrue| and assigning |\relax|es.
|
|
|
+% \item Define |\lst@MSkipUptoFirstExact| by copying |\lst@MProcessListing| and renaming it.
|
|
|
+% Replace the |\ifnum| by\vspace*{-0.5\baselineskip}
|
|
|
+% \begin{verbatim}
|
|
|
+%\ifnum\lst@lineno=lst@firstline %
|
|
|
+% \lst@LeaveMode \global\lst@column\z@ \global\lst@pos\z@ %
|
|
|
+%\fi\end{verbatim}
|
|
|
+% \item Make the fine tuning if necessary.
|
|
|
+% \end{enumerate}
|
|
|
+% \end{TODO}
|
|
|
+% \end{macro}
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%</kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{The environment}\label{iTheEnvironment}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%<*kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+% \begin{macro}{\lst@Environment}
|
|
|
+% This is the first attempt to provide a general macro, which defines the \lst-environments.
|
|
|
+% The syntax comes from \LaTeX's |\newenvironment|:
|
|
|
+% \begin{macrosyntax}
|
|
|
+% \item |\lst@Environment{|\meta{name}|}[|\meta{number of parameters}|][|\meta{opt.~default~arg.}|]\is|\\
|
|
|
+% |{|\meta{begin code}|}|\\
|
|
|
+% |{|\meta{end code}|}|
|
|
|
+% \end{macrosyntax}
|
|
|
+% Note the additional |\is|.
|
|
|
+% I should mention that such environments could also be used in command fashion
|
|
|
+% \begin{verbatim}
|
|
|
+% \lstlisting{my name}
|
|
|
+% Here comes the listing.
|
|
|
+% \endlstlisting\end{verbatim}
|
|
|
+% But now the implementation.
|
|
|
+% We define undefined environments only:
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@Environment#1#2\is#3#4{%
|
|
|
+ \@ifundefined{#1}{\lst@Environment@{#1}{#2}{#3}{#4}}%
|
|
|
+ {%
|
|
|
+%<info> \lst@InfoWarning{Multiple environment `#1'}%
|
|
|
+ }}
|
|
|
+% \end{macrocode}
|
|
|
+% A lonely 'end environment' produces an error:
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@Environment@#1#2#3#4{%
|
|
|
+ \global\@namedef{end#1}{\lstenv@Error{#1}}%
|
|
|
+% \end{macrocode}
|
|
|
+% The 'main' environment macro defines the environment name (for later use) and calls a submacro (getting all arguments).
|
|
|
+% We open a group and redefine the (active) EOL character to be |\relax|.
|
|
|
+% This ensures |\@ifnextchar[| not to read characters of the listing --- it reads the active EOL instead.
|
|
|
+% \begin{macrocode}
|
|
|
+ \global\@namedef{#1}{%
|
|
|
+ \def\lstenv@name{#1}%
|
|
|
+ \begingroup \lstCC@Let{"000D}\relax %
|
|
|
+ \csname#1@\endcsname}%
|
|
|
+% \end{macrocode}
|
|
|
+% The submacro is defined via |\new@command|.
|
|
|
+% We misuse |\l@ngrel@x| to make the definition |\global|.
|
|
|
+% The submacro defines the first and last line, which are possibly changed by the user's \meta{begin code} |#3|.
|
|
|
+% \begin{macrocode}
|
|
|
+ \let\l@ngrel@x\global %
|
|
|
+ \expandafter\new@command\csname#1@\endcsname#2%
|
|
|
+ {\def\lst@firstline{1}\def\lst@lastline{9999999}%
|
|
|
+ #3%
|
|
|
+% \end{macrocode}
|
|
|
+% The definition of the string which terminates the environment (|end{lstlisting}| or |endlstlisting|, for example) needs some care since the braces must not have catcodes 1 and 2 (or |\lst@MakeActive| fails).
|
|
|
+% We enter them as |\{| and |\}| (with preceding |\noexpand|s).
|
|
|
+% \begin{macrocode}
|
|
|
+ \ifx\@currenvir\lstenv@name %
|
|
|
+ \edef\lst@temp{end\noexpand\{\lstenv@name\noexpand\}}%
|
|
|
+ \else %
|
|
|
+ \edef\lst@temp{end\lstenv@name}%
|
|
|
+ \fi %
|
|
|
+ \expandafter\lst@MakeActive\expandafter{\lst@temp}%
|
|
|
+ \let\lstenv@endstring\lst@arg %
|
|
|
+% \end{macrocode}
|
|
|
+% We redefine (locally) 'end environment' inside the 'begin environment' macro since ending is legal now.
|
|
|
+% Note that the redefinition also works inside a \TeX\ comment line.
|
|
|
+% \begin{macrocode}
|
|
|
+ \@namedef{end#1}{\lst@DeInit #4\endgroup \lsthk@OnExit}%
|
|
|
+% \end{macrocode}
|
|
|
+% Finally the 'begin environment' macro starts the processing.
|
|
|
+% \begin{macrocode}
|
|
|
+ \lstenv@Process}}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lstenv@Error}
|
|
|
+% have been used above.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstenv@Error#1{\PackageError{Listings}{Extra \string\end#1}%
|
|
|
+ {I'm ignoring this, since I wasn't doing a \csname#1\endcsname.}}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lstenv@backslash}
|
|
|
+% We have the problem of finding end of environment, and we've already defined the 'end environment' string.
|
|
|
+% Coming to a backslash we either end the listing or process a backslash and insert the eaten characters again.
|
|
|
+% (Eaten means that these characters have been read (and removed) from the input to test for |\lstenv@endstring|.)
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstenv@backslash{%
|
|
|
+ \lst@IfNextChars\lstenv@endstring %
|
|
|
+ {\lstenv@End}%
|
|
|
+ {\lsts@backslash \lst@eaten}}%
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lstenv@End}
|
|
|
+% This macro is called by the backslash macro and terminates a listing environment:
|
|
|
+% We call the 'end environment' macro as a command or using |\end|.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstenv@End{%
|
|
|
+ \ifx\@currenvir\lstenv@name %
|
|
|
+ \edef\lst@next{\noexpand\end{\lstenv@name}}%
|
|
|
+ \else %
|
|
|
+ \def\lst@next{\csname end\lstenv@name\endcsname}%
|
|
|
+ \fi %
|
|
|
+ \lst@next}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lstenv@Process}
|
|
|
+% First some initialization, then call a submacro.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstenv@Process{%
|
|
|
+ \lst@Init\lstenv@backslash %
|
|
|
+ \global\lst@lineno\lst@firstline\relax %
|
|
|
+ \let\lstenv@ifdropped\iffalse \lstenv@Process@}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstenv@droppedtrue{\let\lstenv@ifdropped\iftrue}
|
|
|
+% \end{macrocode}
|
|
|
+% We execute either |\lstenv@ProcessM| or |\lstenv@ProcessJ| according to whether we find an active EOL or a nonactive |^^J|.
|
|
|
+% \begin{macrocode}
|
|
|
+\begingroup \lccode`\~=`\^^M%
|
|
|
+\lowercase{\gdef\lstenv@Process@#1{%
|
|
|
+ \ifx~#1%
|
|
|
+ \expandafter\lstenv@ProcessM %
|
|
|
+ \else\ifx^^J#1%
|
|
|
+ \expandafter\expandafter\expandafter\lstenv@ProcessJ %
|
|
|
+ \else %
|
|
|
+ \lstenv@droppedtrue %
|
|
|
+ \expandafter\expandafter\expandafter\lstenv@Process@ %
|
|
|
+ \fi \fi}
|
|
|
+}\endgroup
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lstenv@DroppedWarning}
|
|
|
+% gives a warning if characters have been dropped.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstenv@DroppedWarning{%
|
|
|
+ \lstenv@ifdropped %
|
|
|
+ \PackageWarning{Listings}{Text dropped after begin of listing}%
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lstenv@ProcessM}
|
|
|
+% There is nothing to do if we've found an active EOL, except giving a warning if necessary.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstenv@ProcessM{\lstenv@DroppedWarning \lst@BOLGobble}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lstenv@ProcessJ}
|
|
|
+% Now comes the horrible scenario: A listing inside an argument.
|
|
|
+% We've already worked in section \ref{iAnApplicationTo} for this.
|
|
|
+% Here we must get the listing, i.e.\ all characters upto 'end environment'.
|
|
|
+% We must distinguish the cases 'command fashion' and 'environment'.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstenv@ProcessJ{%
|
|
|
+ \lstenv@DroppedWarning %
|
|
|
+ \lst@DontEscapeToLaTeX %
|
|
|
+ \let\lstenv@arg\@empty %
|
|
|
+ \ifx\@currenvir\lstenv@name %
|
|
|
+ \expandafter\lstenv@ProcessJEnv %
|
|
|
+ \else %
|
|
|
+% \end{macrocode}
|
|
|
+% The first case is pretty simple: The code is terminated by |\end|\meta{name of environment}.
|
|
|
+% Thus we expand that control sequence before defining a temporary macro, which gets all characters upto that control sequence.
|
|
|
+% Inside the temporary macro we assign the argument and call a submacro doing the rest.
|
|
|
+% \begin{macrocode}
|
|
|
+ \expandafter\def\expandafter\lst@temp\expandafter##1%
|
|
|
+ \csname end\lstenv@name\endcsname{%
|
|
|
+ \lstenv@AddArg{##1}\lstenv@ProcessJ@}%
|
|
|
+% \end{macrocode}
|
|
|
+% Back to the definition of |\lstenv@ProcessJ| we call the temporary macro.
|
|
|
+% \begin{macrocode}
|
|
|
+ \expandafter\lst@temp %
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% We must append an active backslash and the 'end string' to |\lstenv@arg|.
|
|
|
+% So all other processing won't notice that the code has been inside an argument.
|
|
|
+% But the EOL character is chr(10)=|^^J| now and not chr(13).
|
|
|
+% Finally we execute |\lstenv@arg| to typeset the listing.
|
|
|
+% Note that we need |\lccode`\A=`\A| to preserve the argument of |\lstCC@Let| --- but obviously we could also write |\lstCC@Let{10}|\ldots
|
|
|
+% \begin{macrocode}
|
|
|
+\begingroup \lccode`\~=`\\ \lccode`\A=`\A
|
|
|
+\lowercase{\gdef\lstenv@ProcessJ@{%
|
|
|
+ \expandafter\lst@lAddTo\expandafter\lstenv@arg %
|
|
|
+ \expandafter{\expandafter\ \expandafter~\lstenv@endstring}%
|
|
|
+ \lstCC@Let{"000A}\lst@MProcessListing \def\lst@BOLGobble##1{}%
|
|
|
+ \expandafter\lst@BOLGobble\lstenv@arg}
|
|
|
+}\endgroup
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lstenv@ProcessJEnv}
|
|
|
+% Here we get all characters upto an |\end| (and the following argument).
|
|
|
+% If the following argument equals |\lstenv@name|, we have found the end of environment and start typesetting.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstenv@ProcessJEnv#1\end#2{\def\lst@temp{#2}%
|
|
|
+ \ifx\lstenv@name\lst@temp %
|
|
|
+ \lstenv@AddArg{#1}%
|
|
|
+ \expandafter\lstenv@ProcessJ@ %
|
|
|
+ \else %
|
|
|
+% \end{macrocode}
|
|
|
+% Otherwise we append the characters including the eaten |\end| and the eaten argument to current |\lstenv@arg|.
|
|
|
+% And we look again for the end of environment.
|
|
|
+% \begin{macrocode}
|
|
|
+ \lstenv@AddArg{#1\\end\{#2\}}%
|
|
|
+ \expandafter\lstenv@ProcessJEnv %
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{environment}{lstlisting}
|
|
|
+% The awkward work is done, here we deal with continued line numbering.
|
|
|
+% \lsthelper{Boris Veytsman}{[email protected]}{1998/03/25}{continue line numbering: a.c b.c a.c} proposed to continue line numbers according to listing names.
|
|
|
+% Thus we must save the name and either make a LOL item or define the first line number.
|
|
|
+% Note that the macro |\lstno@| will be undefined or equivalent to |\relax|, so we always start with line number 1 in case of an empty name.
|
|
|
+% Moreover we first test if the user has forgotten the name argument.
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@Environment{lstlisting}[2][]\is
|
|
|
+ {\lstenv@TestEOLChar{#2}%
|
|
|
+ \expandafter\ifx\csname lstno@\lst@intname\endcsname \relax %
|
|
|
+ \ifx\lst@intname\@empty\else \lst@AddToLOL{#2}{}\fi %
|
|
|
+ \else %
|
|
|
+ \edef\lst@firstline{\csname lstno@\lst@intname\endcsname}%
|
|
|
+ \let\lst@prelisting\lst@@prelisting %
|
|
|
+ \let\lst@postlisting\lst@@postlisting %
|
|
|
+ \fi %
|
|
|
+ \lstset{#1}}
|
|
|
+% \end{macrocode}
|
|
|
+% At the end of environment we simply save the current line number.
|
|
|
+% If the listing name is empty, we use a space instead of the name.
|
|
|
+% This leaves the macro |\lstno@| undefined.
|
|
|
+% \begin{macrocode}
|
|
|
+ {\ifx\lst@intname\@empty %
|
|
|
+ \expandafter\xdef\csname lstno@ \endcsname{\the\lst@lineno}%
|
|
|
+ \else %
|
|
|
+ \expandafter\xdef\csname lstno@\lst@intname\endcsname %
|
|
|
+ {\the\lst@lineno}%
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{environment}
|
|
|
+%
|
|
|
+% \begin{macro}{\lstenv@TestEOLChar}
|
|
|
+% \begin{macro}{\lstenv@EOLCharError}
|
|
|
+% Here we test for the two possible EOL characters.
|
|
|
+% \begin{macrocode}
|
|
|
+\begingroup \lccode`\~=`\^^M\lowercase{%
|
|
|
+\gdef\lstenv@TestEOLChar#1{%
|
|
|
+ \lst@SetName{}%
|
|
|
+ \ifx~#1\lstenv@EOLCharError \else %
|
|
|
+ \ifx^^J#1\lstenv@EOLCharError \else %
|
|
|
+ \lst@SetName{#1}%
|
|
|
+ \fi %
|
|
|
+ \fi}
|
|
|
+}\endgroup
|
|
|
+% \end{macrocode}
|
|
|
+% A simple error message.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstenv@EOLCharError{%
|
|
|
+ \PackageError{Listings}
|
|
|
+ {Oops! It seems you've forgotten the argument to\MessageBreak %
|
|
|
+ a listing environment. Assuming empty argument}%
|
|
|
+ {Type <RETURN> to proceed.}}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}\end{macro}
|
|
|
+%
|
|
|
+% \begin{aspect}{advancelineno}
|
|
|
+% \begin{aspect}{resetlineno}
|
|
|
+% The last two aspects in this section simply advance/reset the first line.
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@Aspect{advancelineno}
|
|
|
+ {\global\lst@lineno\lst@firstline\relax %
|
|
|
+ \global\advance\lst@lineno#1\relax %
|
|
|
+ \edef\lst@firstline{\the\lst@lineno}}
|
|
|
+\lst@Aspect{resetlineno}[1]{\def\lst@firstline{#1}}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{aspect}\end{aspect}
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%</kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Inline listings}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%<*kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+% \begin{macro}{\lstinline}
|
|
|
+% We redefine some macros here since they are possibly not save inside |\hbox|.
|
|
|
+% Furthermore we use flexible columns and suppress \TeX\ comment lines.
|
|
|
+% After doing initialization we redefine |\everypar| and the new line macro.
|
|
|
+% We don't want them.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstinline{\hbox\bgroup %
|
|
|
+ \let\smallbreak\relax %
|
|
|
+ \let\lst@prelisting\relax \let\lst@postlisting\relax %
|
|
|
+ \let\lst@ifflexible\iftrue \lst@DontEscapeToLaTeX %
|
|
|
+ \def\lst@firstline{1}\def\lst@lastline{1}%
|
|
|
+ \lst@Init\relax \everypar{}\global\let\lst@NewLine\relax %
|
|
|
+ \lst@IfNextCharActive\lst@InlineM\lst@InlineJ}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@InlineM}
|
|
|
+% \begin{macro}{\lst@InlineJ}
|
|
|
+% treat the cases of 'normal' inlines and inline listings inside an argument.
|
|
|
+% In the first case the given character ends the inline listing and EOL (within such a listing) immediately ends it and produces an error message.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@InlineM#1{%
|
|
|
+ \lstCC@Def{`#1}{\lst@DeInit\egroup}%
|
|
|
+ \lstCC@Def{"000D}{\lst@DeInit\egroup %
|
|
|
+ \PackageError{Listings}{lstinline ended by EOL}\@ehc}}
|
|
|
+% \end{macrocode}
|
|
|
+% In the other case we get all characters upto |#1| (via temporary macro), make these characters active, execute (typeset) them and end the listing.
|
|
|
+% That's all about it.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@InlineJ#1{%
|
|
|
+ \def\lst@temp##1#1{%
|
|
|
+ \let\lstenv@arg\@empty \lstenv@AddArg{##1}%
|
|
|
+ \lstenv@arg \lst@DeInit\egroup}%
|
|
|
+ \lst@temp}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}\end{macro}
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%</kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{The box command}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%<*kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+% \begin{macro}{\lstbox}
|
|
|
+% The macro opens the |\hbox| right at the beginning and indicate its usage.
|
|
|
+% Then we adjust some \lst-parameters:
|
|
|
+% We switch to |\lstlistingtrue| since the command is intend to be used with small listings only;
|
|
|
+% |\smallbreak|s preceding and following each listing are removed by redefining |\smallbreak|.
|
|
|
+% \begin{macrocode}
|
|
|
+\newcommand\lstbox{%
|
|
|
+ \hbox\bgroup %
|
|
|
+ \let\lst@ifbox\iftrue %
|
|
|
+ \let\smallbreak\relax %
|
|
|
+ \let\lst@prelisting\relax \let\lst@postlisting\relax %
|
|
|
+ \let\lst@@prelisting\relax\let\lst@@postlisting\relax %
|
|
|
+ \lst@outerspread\z@ \lst@innerspread\z@ %
|
|
|
+ \@ifnextchar[{\lstbox@}{\lstbox@[c]}}
|
|
|
+% \end{macrocode}
|
|
|
+% Here we have to choose the right box --- in fact |\vcenter| isn't a box.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstbox@[#1]{%
|
|
|
+ \hbox to\z@\bgroup %
|
|
|
+ $\if#1t\vtop \else \if#1b\vbox \else \vcenter \fi\fi %
|
|
|
+ \bgroup}%
|
|
|
+% \end{macrocode}
|
|
|
+% We need to
|
|
|
+% \begin{macrocode}
|
|
|
+\let\lst@ifbox\iffalse
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@EndBox}
|
|
|
+% And the counterpart: We have to close some groups (and use |\hss| inside the |\hbox| to $0$pt).
|
|
|
+% The outer |\hbox| gets its correct width using a |\vrule|.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@EndBox{%
|
|
|
+ \egroup $\hss \egroup %
|
|
|
+ \vrule width\lst@maxwidth height\z@ depth\z@ %
|
|
|
+ \egroup}
|
|
|
+% \end{macrocode}
|
|
|
+% But that macro is called (if and) only if we've begun a |\lstbox| before.
|
|
|
+% Note that we are possibly inside a \lst-environment here, so we have to execute |\lst@EndBox| either now or after closing the environment group.
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@AddToHook{OnExit}
|
|
|
+ {\lst@ifbox %
|
|
|
+ \global\advance\lst@maxwidth-\lst@innerspread %
|
|
|
+ \global\advance\lst@maxwidth-\lst@outerspread %
|
|
|
+ \ifx\@currenvir\lstenv@name %
|
|
|
+ \expandafter\expandafter\expandafter\aftergroup %
|
|
|
+ \fi %
|
|
|
+ \expandafter\lst@EndBox %
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@maxwidth}
|
|
|
+% is to be allocated:
|
|
|
+% \begin{macrocode}
|
|
|
+\newdimen\lst@maxwidth % \global
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@AddToHook{InitVars}{\global\lst@maxwidth\z@}
|
|
|
+% \end{macrocode}
|
|
|
+% Determine width of just printed line and update |\lst@maxwidth|.
|
|
|
+% Here we assume that all characters of the line have been output.
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@AddToHook{InitVarsEOL}
|
|
|
+ {\@tempdima \lst@column\lst@width %
|
|
|
+ \advance\@tempdima -\lst@pos\lst@width %
|
|
|
+ \ifdim\lst@lostspace<\z@ \advance\@tempdima -\lst@lostspace \fi %
|
|
|
+ \ifdim\@tempdima>\lst@maxwidth \global\lst@maxwidth\@tempdima \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%</kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+%
|
|
|
+%
|
|
|
+% \section{First \lst-aspects and related macros}
|
|
|
+%
|
|
|
+% In fact we've already defined some aspects, e.g.\ |language| and |style|.
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Keywords}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%<*kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+% \begin{TODO}
|
|
|
+% The internal keyword managing should be reorganised, so that is also handles the special characters $<,>,\vert,\sim$.
|
|
|
+% \end{TODO}
|
|
|
+% We have to decide whether or not a given character sequence is a reserved word.
|
|
|
+% For example, if the character sequence is |key|, we define a macro
|
|
|
+% \begin{verbatim}
|
|
|
+% \def\lst@temp#1,key,#2\relax{...}\end{verbatim}
|
|
|
+% Afterwards we call the macro with the following arguments:
|
|
|
+% \begin{itemize}
|
|
|
+% \item[] |,|all current keywords|,key,\relax|
|
|
|
+% \end{itemize}
|
|
|
+% The additional |,key,\relax| holds up the syntax of |\lst@temp|.
|
|
|
+% When \TeX{} passes the arguments, the second is empty if and only if |key| is not a current keyword.
|
|
|
+% So we know whether or not to select keyword style.
|
|
|
+%
|
|
|
+% Since \TeX{} always passes two arguments to |\lst@temp|, the whole 'input' |\lst@keywords,#1,\relax| is split in two parts.
|
|
|
+% So there is no need to sort the keywords by probability.
|
|
|
+% Alternatively you could do so and make a loop for the keyword tests, which terminates right after finding a keyword.
|
|
|
+% You might think and guess that's faster than the \TeX{}nique used here.
|
|
|
+% If your source code uses the three or four most common keywords only, you are right.
|
|
|
+% In fact the very first versions 0.1 and 0.11 have used something like loops (even something faster), which in general is slower than this here.
|
|
|
+% \begin{TODO}
|
|
|
+% There exists a faster way.
|
|
|
+% For each keyword we make |\lstk@|\emph{the keyword} equivalent to keyword style.
|
|
|
+% |\csname lstk@|\emph{test word}|\endcsname| expands to |\relax| if the control sequence is undefined and to keyword style otherwise.
|
|
|
+% That's the complete keyword test!
|
|
|
+% It works very well, but needs more of \TeX{}'s memory.
|
|
|
+% Therefore we should define also 'memory saving' and/or 'speeding up' option.
|
|
|
+%
|
|
|
+% Note: A keyword or character string in this state might contain |\lst@underscore| and |\lst@minus| (and possibly more macro names), which will expand inside |\csname|\ldots|\endcsname|.
|
|
|
+% Hence the definition of |\lstk@|\emph{the keyword} needs some care.
|
|
|
+% An easy trick: During keyword definition and keyword testing the macros should expand to |_| and |-|, respectively.
|
|
|
+% But the reassignments of |_|, |-|, \ldots\ also need time, so the implemented way is possibly faster \ldots
|
|
|
+% \end{TODO}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@SetStyleFor}
|
|
|
+% |\relax| terminates the argument here since it is faster than enclosing it in braces.
|
|
|
+% All the rest should be clear from the discussion above.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@SetStyleFor#1\relax{%
|
|
|
+ \def\lst@temp##1,#1,##2\relax{%
|
|
|
+ \ifx\@empty##2\@empty \let\lst@thestyle\lst@nonkeywordstyle %
|
|
|
+ \else \let\lst@thestyle\lst@keywordstyle\fi}%
|
|
|
+ \expandafter\lst@temp\expandafter,\lst@keywords,#1,\relax}%
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@SetStyleForNonSensitive}
|
|
|
+% We implement a case insensitive version.
|
|
|
+% Use of two |\uppercase|s normalize the argument.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@SetStyleForNonSensitive#1\relax{%
|
|
|
+ \uppercase{\def\lst@temp##1,#1},##2\relax{%
|
|
|
+ \ifx\@empty##2\@empty \let\lst@thestyle\lst@nonkeywordstyle %
|
|
|
+ \else \let\lst@thestyle\lst@keywordstyle\fi}%
|
|
|
+ \uppercase{%
|
|
|
+ \expandafter\lst@temp\expandafter,\lst@keywords,#1},\relax}%
|
|
|
+% \end{macrocode}
|
|
|
+% Note: This macro and the coming |\lst@IfOneOfNonSensitive| both assume that the keywords in |\lst@keywords| are already upper case!
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% The code above must be activated, of course:
|
|
|
+% We detect keywords if and only if we haven't entered a special mode (comment, string, etc.).
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@AddToHook{Output}
|
|
|
+ {\lst@ifmode %
|
|
|
+ \let\lst@thestyle\relax %
|
|
|
+ \else %
|
|
|
+ \expandafter\lst@SetStyleFor\the\lst@token\relax %
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@IfOneOf}
|
|
|
+% \begin{macro}{\lst@IfOneOfNonSensitive}
|
|
|
+% These macros are very familiar with the keyword tests.
|
|
|
+% Roughly speaking the fixed |\lst@keywords| is replaced by an arbitrary macro.
|
|
|
+% The first argument has the same meaning and is terminated by |\relax|, whereas the second must be a macro name.
|
|
|
+% If and only if that macro (= keyword list) contains the first argument, the third parameter is executed (and the fourth otherwise).
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@IfOneOf#1\relax#2{%
|
|
|
+ \def\lst@temp##1,#1,##2\relax{%
|
|
|
+ \ifx \@empty##2\@empty \expandafter\@secondoftwo %
|
|
|
+ \else \expandafter\@firstoftwo \fi}%
|
|
|
+ \expandafter\lst@temp\expandafter,#2,#1,\relax}%
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@IfOneOfNonSensitive#1\relax#2{%
|
|
|
+ \uppercase{\def\lst@temp##1,#1},##2\relax{%
|
|
|
+ \ifx \@empty##2\@empty \expandafter\@secondoftwo %
|
|
|
+ \else \expandafter\@firstoftwo \fi}%
|
|
|
+ \uppercase\expandafter{%
|
|
|
+ \expandafter\lst@temp\expandafter,#2,#1},\relax}%
|
|
|
+% \end{macrocode}
|
|
|
+% Instead of |\lst@SetStyleFor key\relax|, we could also write
|
|
|
+% \begin{verbatim}
|
|
|
+% \lst@IfOneOf key\relax \lst@keywords %
|
|
|
+% {\let\lst@thestyle\lst@keywordstyle}
|
|
|
+% {\let\lst@thestyle\lst@nonkeywordstyle}\end{verbatim}
|
|
|
+% \end{macro}\end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lststorekeywords}
|
|
|
+% Note that this command stores the keywords globally.
|
|
|
+% \begin{macrocode}
|
|
|
+\newcommand\lststorekeywords[2]{\gdef#1{#2}}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{aspect}{sensitive}
|
|
|
+% Announcement and init:
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@Aspect{sensitive}[t]{\lstKV@SetIfKey\lst@ifsensitive{#1}}
|
|
|
+\lst@AddToHook{SetLanguage}{\let\lst@ifsentitive\iftrue}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{aspect}
|
|
|
+%
|
|
|
+% \noindent
|
|
|
+% Now we consider the aspects getting keywords from the user.
|
|
|
+% They work up the keywords a little bit, namely using |\lst@Make|\ldots|KeywordArg|.
|
|
|
+%
|
|
|
+% \begin{aspect}{keywords}
|
|
|
+% \lsthelper{Ralf Quast}{[email protected]}{1998/01/08}{name \keywords incompatible with AMS classes} reported a naming conflict with AMS classes.
|
|
|
+% Usage of \textsf{keyval} package removes it.
|
|
|
+% The easy definition:
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@Aspect{keywords}
|
|
|
+ {\lst@MakeSpecKeywordArg{#1}\let\lst@keywords\lst@arg}
|
|
|
+% \end{macrocode}
|
|
|
+% We have to delete all current keywords before selecting a new language --- otherwise keywords from the previous language would be present if the user specifies no keywords.
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@AddToHook{SetLanguage}{\let\lst@keywords\@empty}
|
|
|
+% \end{macrocode}
|
|
|
+% If the user wants case insensitive keywords, she'll get it:
|
|
|
+% We assign the correct test macros and make all keywords upper case.
|
|
|
+% Note that these changes are local.
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@AddToHook{BeforeSelectCharTable}
|
|
|
+ {\lst@ifsensitive\else %
|
|
|
+ \let\lst@SetStyleFor\lst@SetStyleForNonSensitive %
|
|
|
+ \let\lst@IfOneOf\lst@IfOneOfNonSensitive %
|
|
|
+ \lst@MakeMacroUppercase\lst@keywords %
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{aspect}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@MakeMacroUppercase}
|
|
|
+% This macro makes the contents of a given macro (if present) upper case.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@MakeMacroUppercase#1{%
|
|
|
+ \ifx#1\@undefined\else \uppercase\expandafter{%
|
|
|
+ \expandafter\def\expandafter#1\expandafter{#1}}%
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{aspect}{morekeywords}
|
|
|
+% Add keywords or append control sequence with argument:
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@Aspect{morekeywords}
|
|
|
+ {\lst@MakeMoreSpecKeywordArg{,#1}%
|
|
|
+ \expandafter\lst@lAddTo\expandafter\lst@keywords %
|
|
|
+ \expandafter{\lst@arg}}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{aspect}
|
|
|
+%
|
|
|
+% \begin{aspect}{deletekeywords}
|
|
|
+% The 'submacro' |\lst@DeleteKeysIn| has been defined in section \ref{iReplacingCharacters}.
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@Aspect{deletekeywords}
|
|
|
+ {\lst@MakeKeywordArg{#1}%
|
|
|
+ \lst@DeleteKeysIn\lst@keywords\lst@arg}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{aspect}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@MakeKeywordArg}
|
|
|
+% \begin{macro}{\lst@MakeSpecKeywordArg}
|
|
|
+% \begin{macro}{\lst@MakeMoreSpecKeywordArg}
|
|
|
+% The keyword commands don't save their parameters as they are.
|
|
|
+% All spaces are removed and underscores, dollars and minuses are replaced by |\lst@underscore|, |\lst@dollar| and |\lst@minus|.
|
|
|
+% The first thing prepares keyword tests and the second the output.
|
|
|
+% The macro |\lst@arg| holds the parameter free of spaces, underscores and minuses.
|
|
|
+% Use of |\zap@space| was proposed by \lsthelper{Rolf Niepraschk}{[email protected]}{1997/04/24}{use \zap@space}.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@MakeKeywordArg#1{\edef\lst@arg{\zap@space#1 \@empty}%
|
|
|
+ \lst@ReplaceIn\lst@arg{_\lst@underscore $\lst@dollar -\lst@minus}}
|
|
|
+% \end{macrocode}
|
|
|
+% The following two macros also scan for special characters like \#, $<$ and $>$.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@MakeSpecKeywordArg{%
|
|
|
+ \let\lst@ialsodigit\@empty \let\lst@ialsoletter\@empty %
|
|
|
+ \lst@MakeMoreSpecKeywordArg}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@MakeMoreSpecKeywordArg#1{\edef\lst@arg{\zap@space#1 \@empty}%
|
|
|
+ \lstCC@lettertrue %
|
|
|
+ \expandafter\lst@SpecialKeywordScan\lst@arg\relax %
|
|
|
+ \lst@ReplaceIn\lst@arg{_\lst@underscore $\lst@dollar -\lst@minus}}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}\end{macro}\end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@SpecialKeywordScan}
|
|
|
+% How does this scan work?
|
|
|
+% Whenever we encounter a non-letter or non-digit in a keyword, we call |\lst@SKSAdd| to store that character.
|
|
|
+% If we reach the end of keyword list, we terminate the loop by gobbling one token after the latest |\fi|.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@SpecialKeywordScan#1{%
|
|
|
+ \ifx\relax#1%
|
|
|
+ \expandafter\@gobble %
|
|
|
+ \else %
|
|
|
+% \end{macrocode}
|
|
|
+% If the current character is a comma, the next character must be (or become) a letter since it starts a keyword.
|
|
|
+% This switch is turned false after reading the next character.
|
|
|
+% \begin{macrocode}
|
|
|
+ \ifx,#1%
|
|
|
+ \lstCC@lettertrue %
|
|
|
+ \else %
|
|
|
+ \ifnum`#1<"40\relax %
|
|
|
+ \ifnum`#1<"30\relax \lst@SKSAdd#1\else %
|
|
|
+ \ifnum`#1>"39\relax \lst@SKSAdd#1\else %
|
|
|
+% \end{macrocode}
|
|
|
+% If we've found a digit, we do a special test to decide whether the digit becomes a letter or not.
|
|
|
+% \begin{macrocode}
|
|
|
+ \lst@SKS@#1%
|
|
|
+ \fi \fi %
|
|
|
+ \else %
|
|
|
+ \ifnum`#1<"5B\relax \else %
|
|
|
+ \ifnum`#1="5F\relax \else %
|
|
|
+ \ifnum`#1<"61\relax \lst@SKSAdd#1\else %
|
|
|
+ \ifnum`#1<"7B\relax \else %
|
|
|
+ \ifnum`#1<"80\relax \lst@SKSAdd#1 %
|
|
|
+ \fi \fi \fi \fi \fi %
|
|
|
+ \fi %
|
|
|
+ \lstCC@letterfalse %
|
|
|
+ \fi %
|
|
|
+ \fi \lst@SpecialKeywordScan}
|
|
|
+% \end{macrocode}
|
|
|
+% The special test for digits: Since any digit is already a digit it needs only to become a letter if necessary.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@SKS@#1{\lstCC@ifletter \lst@SKSAdd#1\fi}
|
|
|
+% \end{macrocode}
|
|
|
+% The macros |\lst@ialsoletter| and |\lst@ialsodigit| contain the characters.
|
|
|
+% If not already contained in the appropiate macro, we append the character.
|
|
|
+% Refer |\lst@SelectStyleFor| how we scan for a substring (of length 1).
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@SKSAdd#1{%
|
|
|
+ \lstCC@ifletter %
|
|
|
+ \def\lst@temp##1#1##2\relax{%
|
|
|
+ \ifx\@empty##2\@empty %
|
|
|
+ \lst@lAddTo\lst@ialsoletter{#1}%
|
|
|
+ \fi}%
|
|
|
+ \expandafter\lst@temp\lst@ialsoletter#1\relax %
|
|
|
+ \else %
|
|
|
+ \def\lst@temp##1#1##2\relax{%
|
|
|
+ \ifx\@empty##2\@empty %
|
|
|
+ \lst@lAddTo\lst@ialsodigit{#1}%
|
|
|
+ \fi}%
|
|
|
+ \expandafter\lst@temp\lst@ialsodigit#1\relax %
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\let\lst@ialsoletter\@empty \let\lst@ialsodigit\@empty % init
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{aspect}{alsoletter}
|
|
|
+% \begin{aspect}{alsodigit}
|
|
|
+% \begin{aspect}{alsoother}
|
|
|
+% For now three easy definitions --- easy since I don't explain the last hook.
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@Aspect{alsoletter}{\def\lst@alsoletter{#1}}
|
|
|
+\lst@Aspect{alsodigit}{\def\lst@alsodigit{#1}}
|
|
|
+\lst@Aspect{alsoother}{\def\lst@alsoother{#1}}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@AddToHook{SetLanguage}
|
|
|
+ {\let\lst@alsoletter\@empty %
|
|
|
+ \let\lst@alsodigit\@empty %
|
|
|
+ \let\lst@alsoother\@empty}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@AddToHook{SelectCharTable}
|
|
|
+ {\lstCC@ChangeBasicClass\lstCC@ProcessOther\lst@alsoother %
|
|
|
+ \lstCC@ChangeBasicClass\lstCC@ProcessDigit\lst@ialsodigit %
|
|
|
+ \lstCC@ChangeBasicClass\lstCC@ProcessDigit\lst@alsodigit %
|
|
|
+ \lstCC@ChangeBasicClass\lstCC@ProcessLetter\lst@ialsoletter %
|
|
|
+ \lstCC@ChangeBasicClass\lstCC@ProcessLetter\lst@alsoletter}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{aspect}\end{aspect}\end{aspect}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@minus}
|
|
|
+% What is the |\ifx|\ldots{} in |\lst@minus| good for?
|
|
|
+% If you use typewriter fonts, it ensures that |----| is typeset |----| and not $-$$-$$-$$-$ as in version 0.17.
|
|
|
+% Bug encountered by \lsthelper{Dr. Jobst Hoffmann}{[email protected]}{1998/03/30}{\lst@minus\ and typewriter fonts}.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@minus{\ifx\f@family\ttdefault-{}\else$-$\fi}
|
|
|
+\def\lst@dollar{\ifx\f@family\ttdefault\textdollar\else\textdollar\fi}
|
|
|
+\def\lst@asterisk{\ifx\f@family\ttdefault*\else\textasteriskcentered\fi}
|
|
|
+\def\lst@less{\ifx\f@family\ttdefault<\else\textless\fi}
|
|
|
+\def\lst@greater{\ifx\f@family\ttdefault>\else\textgreater\fi}
|
|
|
+\def\lst@backslash{\ifx\f@family\ttdefault\char92\else\textbackslash\fi}
|
|
|
+\def\lst@underscore{%
|
|
|
+ \ifx\f@family\ttdefault\char95\else\textunderscore\fi}
|
|
|
+\def\lst@lbrace{\ifx\f@family\ttdefault\char123\else\textbraceleft\fi}
|
|
|
+\def\lst@bar{\ifx\f@family\ttdefault|\else\textbar\fi}
|
|
|
+\def\lst@rbrace{\ifx\f@family\ttdefault\char125\else\textbraceright\fi}
|
|
|
+% \end{macrocode}
|
|
|
+% |\ttdefault| is defined |\long|, so the |\ifx| doesn't work since |\f@family| isn't defined |\long|!
|
|
|
+% We go around this problem by redefining |\ttdefault| locally:
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@AddToHook{BeforeSelectCharTable}{\edef\ttdefault{\ttdefault}}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{aspect}{basicstyle}
|
|
|
+% \begin{aspect}{keywordstyle}
|
|
|
+% \begin{aspect}{nonkeywordstyle}
|
|
|
+% We shouldn't forget these style aspects.
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@Aspect{basicstyle}{\def\lst@basicstyle{#1}}
|
|
|
+\lst@Aspect{keywordstyle}{\def\lst@keywordstyle{#1}}
|
|
|
+\lst@Aspect{nonkeywordstyle}{\def\lst@nonkeywordstyle{#1}}
|
|
|
+% \end{macrocode}
|
|
|
+% \lsthelper{Anders Edenbrandt}{[email protected]}{1997/04/22}{preload of .fd files} found a bug with \texttt{.fd} files.
|
|
|
+% Here's my solution: Since we will change catcodes, these files can't be read on demand --- it would yield to obscure error messages.
|
|
|
+% The |\setbox| sequence ensures (most times) that they are read before.
|
|
|
+% We simply typeset distinct characters from each \texttt{.fd} file.
|
|
|
+% Note: We never output that box.
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@AddToHook{BeforeSelectCharTable}
|
|
|
+ {\lst@basicstyle %
|
|
|
+ \setbox\@tempboxa\hbox{\lst@loadfd %
|
|
|
+ {\lst@keywordstyle \lst@loadfd}%
|
|
|
+ {\lst@nonkeywordstyle \lst@loadfd}}}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{aspect}\end{aspect}\end{aspect}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@loadfd}
|
|
|
+% These are hopefully all necessary characters.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@loadfd{a0\lst@asterisk\lst@less}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{aspect}{ndkeywords}
|
|
|
+% \begin{aspect}{ndkeywordstyle}
|
|
|
+% \begin{aspect}{morendkeywords}
|
|
|
+% \begin{aspect}{deletendkeywords}
|
|
|
+% We define a second keyword class in the same manner if the user wants it.
|
|
|
+% \begin{macrocode}
|
|
|
+\@ifundefined{lst@ndkeywords}{}{%
|
|
|
+\let\lst@ndkeywords\@empty \let\lst@ndkeywordstyle\@empty % init
|
|
|
+\lst@Aspect{ndkeywords}
|
|
|
+ {\lst@MakeSpecKeywordArg{#1}\let\lst@ndkeywords\lst@arg}
|
|
|
+\lst@AddToHook{SetLanguage}{\let\lst@ndkeywords\@empty}
|
|
|
+\lst@AddToHook{BeforeSelectCharTable}
|
|
|
+ {\lst@ifsensitive\else %
|
|
|
+ \lst@MakeMacroUppercase\lst@ndkeywords %
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@Aspect{ndkeywordstyle}{\def\lst@ndkeywordstyle{#1}}
|
|
|
+\lst@AddToHook{BeforeSelectCharTable}
|
|
|
+ {\setbox\@tempboxa\hbox{{\lst@ndkeywordstyle \lst@loadfd}}}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@Aspect{morendkeywords}
|
|
|
+ {\lst@MakeMoreSpecKeywordArg{,#1}%
|
|
|
+ \expandafter\lst@lAddTo\expandafter\lst@ndkeywords %
|
|
|
+ \expandafter{\lst@arg}}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@Aspect{deletendkeywords}
|
|
|
+ {\lst@MakeKeywordArg{#1}%
|
|
|
+ \lst@DeleteKeysIn\lst@ndkeywords\lst@arg}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@AddToHook{Output}
|
|
|
+ {\lst@ifmode\else %
|
|
|
+ \expandafter\lst@IfOneOf\the\lst@token\relax \lst@ndkeywords %
|
|
|
+ {\let\lst@thestyle\lst@ndkeywordstyle}{}%
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% Finally we end the argument from |\@ifundefined|.
|
|
|
+% \begin{macrocode}
|
|
|
+}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{aspect}\end{aspect}\end{aspect}\end{aspect}
|
|
|
+%
|
|
|
+% \begin{aspect}{rdkeywords}
|
|
|
+% \begin{aspect}{rdkeywordstyle}
|
|
|
+% \begin{aspect}{morerdkeywords}
|
|
|
+% \begin{aspect}{deleterdkeywords}
|
|
|
+% That's the power of \lst-aspects: An optional third keyword class.
|
|
|
+% \begin{macrocode}
|
|
|
+\@ifundefined{lst@rdkeywords}{}{%
|
|
|
+\let\lst@rdkeywords\@empty \let\lst@rdkeywordstyle\@empty % init
|
|
|
+\lst@Aspect{rdkeywords}
|
|
|
+ {\lst@MakeSpecKeywordArg{#1}\let\lst@rdkeywords\lst@arg}
|
|
|
+\lst@AddToHook{SetLanguage}{\let\lst@rdkeywords\@empty}
|
|
|
+\lst@AddToHook{BeforeSelectCharTable}
|
|
|
+ {\lst@ifsensitive\else %
|
|
|
+ \lst@MakeMacroUppercase\lst@rdkeywords %
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@Aspect{rdkeywordstyle}{\def\lst@rdkeywordstyle{#1}}
|
|
|
+\lst@AddToHook{BeforeSelectCharTable}
|
|
|
+ {\setbox\@tempboxa\hbox{{\lst@rdkeywordstyle \lst@loadfd}}}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@Aspect{morerdkeywords}
|
|
|
+ {\lst@MakeMoreSpecKeywordArg{,#1}%
|
|
|
+ \expandafter\lst@lAddTo\expandafter\lst@rdkeywords %
|
|
|
+ \expandafter{\lst@arg}}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@Aspect{deleterdkeywords}
|
|
|
+ {\lst@MakeKeywordArg{#1}%
|
|
|
+ \lst@DeleteKeysIn\lst@rdkeywords\lst@arg}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@AddToHook{Output}
|
|
|
+ {\lst@ifmode\else %
|
|
|
+ \expandafter\lst@IfOneOf\the\lst@token\relax \lst@rdkeywords %
|
|
|
+ {\let\lst@thestyle\lst@rdkeywordstyle}{}%
|
|
|
+ \fi}
|
|
|
+}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{aspect}\end{aspect}\end{aspect}\end{aspect}
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Export of indentifiers}
|
|
|
+%
|
|
|
+% \begin{aspect}{index}
|
|
|
+% We implement this aspect in the same manner.
|
|
|
+% \begin{macrocode}
|
|
|
+\@ifundefined{lst@index}{}{%
|
|
|
+\lst@Aspect{index}{\lst@MakeSpecKeywordArg{#1}\let\lst@index\lst@arg}
|
|
|
+\lst@AddToHook{BeforeSelectCharTable}
|
|
|
+ {\lst@ifsensitive\else %
|
|
|
+ \lst@MakeMacroUppercase\lst@index %
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@AddToHook{Output}
|
|
|
+ {\lst@ifmode\else %
|
|
|
+ \expandafter\lst@IfOneOf\the\lst@token\relax \lst@index %
|
|
|
+ {\expandafter\lst@indexmacro\expandafter{\the\lst@token}}{}%
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@Aspect{indexmacro}{\let\lst@indexmacro#1}
|
|
|
+\newcommand\lstindexmacro[1]{\index{{\ttfamily#1}}}
|
|
|
+\let\lst@index\@empty \let\lst@indexmacro\lstindexmacro % init
|
|
|
+}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{aspect}
|
|
|
+%
|
|
|
+% \begin{aspect}{procnamestyle}
|
|
|
+% \begin{aspect}{prockeywords}
|
|
|
+% \begin{aspect}{indexprocnames}
|
|
|
+% The 'idea' here is the usage of a global |\lst@ifprocname| indicating a preceding 'procedure keyword'.
|
|
|
+% All the other is known stuff.
|
|
|
+% \begin{macrocode}
|
|
|
+\@ifundefined{lst@prockeywords}{}{%
|
|
|
+\lst@Aspect{prockeywords}{%
|
|
|
+ \lst@MakeSpecKeywordArg{#1}\let\lst@prockeywords\lst@arg}
|
|
|
+\lst@Aspect{procnamestyle}{\def\lst@procnamestyle{#1}}
|
|
|
+\lst@Aspect{indexprocnames}[t]{\lstKV@SetIfKey\lst@ifindexproc{#1}}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@AddToHook{BeforeSelectCharTable}
|
|
|
+ {\setbox\@tempboxa\hbox{\lst@procnamestyle\lst@loadfd}%
|
|
|
+ \lst@ifsensitive\else %
|
|
|
+ \lst@MakeMacroUppercase\lst@prockeywords %
|
|
|
+ \fi %
|
|
|
+ \lst@ifindexproc \ifx\lst@indexmacro\@undefined %
|
|
|
+ \let\lst@indexmacro\@gobble %
|
|
|
+ \fi \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@AddToHook{Output}
|
|
|
+ {\lst@ifmode\else %
|
|
|
+ \lst@ifprocname %
|
|
|
+ \let\lst@thestyle\lst@procnamestyle %
|
|
|
+ \expandafter\lst@indexmacro\expandafter{\the\lst@token}%
|
|
|
+ \lst@procnamefalse %
|
|
|
+ \else \expandafter%
|
|
|
+ \lst@IfOneOf\the\lst@token\relax \lst@prockeywords %
|
|
|
+ {\lst@procnametrue}{}%
|
|
|
+ \fi %
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@procnametrue{\global\let\lst@ifprocname\iftrue}
|
|
|
+\def\lst@procnamefalse{\global\let\lst@ifprocname\iffalse}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\let\lst@prockeywords\@empty % init
|
|
|
+\lstset{procnamestyle={},indexprocnames=false}% init
|
|
|
+\lst@procnamefalse % init
|
|
|
+}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{aspect}\end{aspect}\end{aspect}
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%</kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Labels}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%<*kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+% \lsthelper{Rolf Niepraschk}{[email protected]}{1997/04/24}{labels} asked for this feature.
|
|
|
+%
|
|
|
+% \begin{aspect}{labelstyle}
|
|
|
+% \begin{aspect}{labelsep}
|
|
|
+% \begin{aspect}{labelstep}
|
|
|
+% The usual stuff:
|
|
|
+% Definition with check for legal step count, \ldots
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@Aspect{labelstyle}{\def\lst@labelstyle{#1}}
|
|
|
+\lst@Aspect{labelsep}{\def\lst@labelsep{#1}}
|
|
|
+\lst@Aspect{labelstep}%
|
|
|
+ {\ifnum #1>\m@ne %
|
|
|
+ \def\lst@labelstep{#1}%
|
|
|
+ \else %
|
|
|
+ \PackageError{Listings}{Nonnegative integer expected}%
|
|
|
+ {You can't use `#1' as step count for labels.^^J%
|
|
|
+ I'll forget it and proceed.}%
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% and load of \texttt{.fd} files (if necessary).
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@AddToHook{BeforeSelectCharTable}
|
|
|
+ {\setbox\@tempboxa\hbox{\lst@stringstyle \lst@loadfd}}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{aspect}\end{aspect}\end{aspect}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@skiplabels}
|
|
|
+% But there are more things to do.
|
|
|
+% \begin{macrocode}
|
|
|
+\newcount\lst@skiplabels % \global
|
|
|
+% \end{macrocode}
|
|
|
+% We calculate how many lines must skip their label.
|
|
|
+% The formula is
|
|
|
+% $$|\lst@skiplabels|=
|
|
|
+% \textrm{\emph{first printing line}}\bmod|\lst@labelstep|.$$
|
|
|
+% Note that we use a nonpositive representative for |\lst@skiplabels|.
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@AddToHook{BeforeSelectCharTable}
|
|
|
+ {\ifnum\lst@labelstep>\z@ %
|
|
|
+ \global\lst@skiplabels\lst@firstline\relax %
|
|
|
+ \global\divide\lst@skiplabels\lst@labelstep %
|
|
|
+ \global\multiply\lst@skiplabels-\lst@labelstep %
|
|
|
+ \global\advance\lst@skiplabels\lst@firstline\relax %
|
|
|
+ \ifnum\lst@skiplabels>\z@ %
|
|
|
+ \global\advance\lst@skiplabels -\lst@labelstep\relax %
|
|
|
+ \fi %
|
|
|
+% \end{macrocode}
|
|
|
+% If |\lst@labelstep| is nonpositive (in fact zero), no labels are printed:
|
|
|
+% \begin{macrocode}
|
|
|
+ \else %
|
|
|
+ \let\lst@SkipOrPrintLabel\relax %
|
|
|
+ \fi}
|
|
|
+\lst@AddToHook{EveryLine}{\lst@SkipOrPrintLabel}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@SkipOrPrintLabel}
|
|
|
+% But default is this.
|
|
|
+% We use the fact that |\lst@skiplabels| is nonpositive.
|
|
|
+% The counter advances every line and if that counter is zero, we print a line number and decrement the counter by |\lst@labelstep|.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@SkipOrPrintLabel{%
|
|
|
+ \ifnum\lst@skiplabels=\z@ %
|
|
|
+ \global\advance\lst@skiplabels-\lst@labelstep\relax %
|
|
|
+ \llap{\lst@labelstyle{\the\lst@lineno}\kern\lst@labelsep}%
|
|
|
+ \fi %
|
|
|
+ \global\advance\lst@skiplabels\@ne}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%</kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Parshape and lineskip}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%<*kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+% \begin{macro}{\lst@innerspread}
|
|
|
+% \begin{macro}{\lst@outerspread}
|
|
|
+% Just allocate these dimensions.
|
|
|
+% \begin{macrocode}
|
|
|
+\newdimen\lst@innerspread \newdimen\lst@outerspread
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}\end{macro}
|
|
|
+%
|
|
|
+% \begin{aspect}{wholeline}
|
|
|
+% \begin{aspect}{indent}
|
|
|
+% \begin{aspect}{spread}
|
|
|
+% Usual stuff.
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@Aspect{wholeline}[t]{\lstKV@SetIfKey\lst@ifwholeline{#1}}
|
|
|
+\lst@Aspect{indent}{\def\lst@indent{#1}}
|
|
|
+\lst@Aspect{spread}{\lstspread@#1,,\relax}
|
|
|
+% \end{macrocode}
|
|
|
+% \lsthelper{Harald Haders}{[email protected]}{1998/03/30}{inner- and outerspread} had the idea of two spreads (inner and outer).
|
|
|
+% We either divide the dimension by two or assign the two dimensions to inner- and outerspread.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstspread@#1,#2,#3\relax{%
|
|
|
+ \lst@innerspread#1\relax %
|
|
|
+ \ifx\@empty#2\@empty %
|
|
|
+ \divide\lst@innerspread\tw@\relax %
|
|
|
+ \lst@outerspread\lst@innerspread %
|
|
|
+ \else %
|
|
|
+ \lst@outerspread#2\relax %
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\lstset{wholeline=false,indent=\z@,spread=\z@}% init
|
|
|
+% \end{macrocode}
|
|
|
+% \end{aspect}\end{aspect}\end{aspect}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@parshape}
|
|
|
+% The definition itself is easy.
|
|
|
+% Note that we use this parshape every line (in fact every paragraph).
|
|
|
+% Furthermore we must repeat the parshape if we close a group level --- or the shape is forgotten.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@parshape{%
|
|
|
+ \parshape\@ne %
|
|
|
+ \ifodd\c@page -\lst@innerspread\else -\lst@outerspread\fi %
|
|
|
+ \linewidth}
|
|
|
+\lst@AddToHookAtTop{EveryLine}{\lst@parshape}
|
|
|
+\lst@AddToHookAtTop{EndGroup}{\lst@parshape}
|
|
|
+% \end{macrocode}
|
|
|
+% We calculate the line width and (inner/outer) indent for a listing.
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@AddToHook{BeforeSelectCharTable}
|
|
|
+ {\advance\linewidth\lst@innerspread %
|
|
|
+ \advance\linewidth\lst@outerspread %
|
|
|
+ \advance\linewidth-\lst@indent\relax %
|
|
|
+ \advance\lst@innerspread-\lst@indent\relax %
|
|
|
+ \advance\lst@outerspread-\lst@indent\relax %
|
|
|
+ \lst@ifwholeline %
|
|
|
+ \advance\linewidth\@totalleftmargin %
|
|
|
+ \else %
|
|
|
+ \advance\lst@innerspread-\@totalleftmargin %
|
|
|
+ \advance\lst@outerspread-\@totalleftmargin %
|
|
|
+ \fi %
|
|
|
+ \if@twoside\else \lst@outerspread\lst@innerspread \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{aspect}{lineskip}
|
|
|
+% Finally we come to this attribute --- the introduction is due to communication with \lsthelper{Andreas Bartelt}{[email protected]}{1997/09/11}{problem with redefed \parskip; \lstlineskip introduced}.
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@Aspect{lineskip}{\def\lst@lineskip{#1}}
|
|
|
+\lst@AddToHook{BeforeSelectCharTable}{\parskip\lst@lineskip\relax}
|
|
|
+\lstset{lineskip=\z@}% init
|
|
|
+% \end{macrocode}
|
|
|
+% \end{aspect}
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%</kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Frames}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%<*kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+%
|
|
|
+% \begin{aspect}{framerulewidth}
|
|
|
+% \begin{aspect}{framerulesep}
|
|
|
+% \begin{aspect}{frametextsep}
|
|
|
+% We only have to store the arguments.
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@Aspect{framerulewidth}{\def\lst@framewidth{#1}}
|
|
|
+\lst@Aspect{framerulesep}{\def\lst@framesep{#1}}
|
|
|
+\lst@Aspect{frametextsep}{\def\lst@frametextsep{#1}}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\lstset{framerulewidth=.4pt,framerulesep=2pt,frametextsep=3pt}% init
|
|
|
+% \end{macrocode}
|
|
|
+% \end{aspect}\end{aspect}\end{aspect}
|
|
|
+%
|
|
|
+% \begin{aspect}{frame}
|
|
|
+% The main aspect saves the argument, resets all supported types |tlrbTLRB| to |\relax| and defines the user specified frame.
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@Aspect{frame}
|
|
|
+ {\def\lst@frame{#1}%
|
|
|
+ \lstframe@\relax tlrbTLRB\relax %
|
|
|
+ \lstframe@\@empty#1\relax}
|
|
|
+% \end{macrocode}
|
|
|
+% This submacro defines the macros to be equivalent to |#1| (which is |\relax| or |\@empty|).
|
|
|
+% The second argument is the list of characters terminated by |\relax|.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstframe@#1#2{%
|
|
|
+ \ifx\relax#2\else %
|
|
|
+ \expandafter\let\csname lstf@#2\endcsname#1%
|
|
|
+ \expandafter\lstframe@\expandafter#1%
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\lstset{frame={}}% init
|
|
|
+% \end{macrocode}
|
|
|
+% \end{aspect}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@framev}
|
|
|
+% \begin{macro}{\lst@frameV}
|
|
|
+% These macros typeset one or two vertical rules:
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@framev{\hbox{\strut\vrule width\lst@framewidth}}
|
|
|
+\def\lst@frameV{\hbox{\strut %
|
|
|
+ \vrule width\lst@framewidth\kern\lst@framesep %
|
|
|
+ \vrule width\lst@framewidth}}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}\end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@framelr}
|
|
|
+% We typeset left and right frame rule every line (if not made |\relax|).
|
|
|
+% Note that |\lst@framel| is possibly redefined and thus equivalent to |\lst@frameL|.
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@AddToHook{EveryLine}{\lst@framelr}
|
|
|
+\def\lst@framelr{%
|
|
|
+ \llap{\lst@framel\kern\lst@indent\kern\lst@frametextsep}%
|
|
|
+ \rlap{\kern\linewidth\kern\lst@frametextsep\lst@framer}}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@frameh}
|
|
|
+% This is the main macro for horizontal lines.
|
|
|
+% The first parameter gives the size of the left and right corner.
|
|
|
+% The other two parameters typeset these corners (and get the size parameter).
|
|
|
+% Now: We move to the correct horizontal position, set the left corner, the horizontal line and the right corner.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@frameh#1#2#3{%
|
|
|
+ \hbox to\z@{%
|
|
|
+ \kern\ifodd\c@page -\lst@innerspread\else -\lst@outerspread\fi %
|
|
|
+ \kern-\lst@indent %
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+ \kern-\lst@frametextsep %
|
|
|
+ \ifx\lstf@L\@empty %
|
|
|
+ \llap{#2#1}%
|
|
|
+ \else \ifx\lstf@l\@empty %
|
|
|
+ \llap{#20}%
|
|
|
+ \fi \fi %
|
|
|
+ \vrule\@width\lst@frametextsep %
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+ \vrule\@width\lst@indent %
|
|
|
+ \vrule\@width\linewidth\@height\lst@framewidth %
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+ \vrule\@width\lst@frametextsep %
|
|
|
+ \ifx\lstf@R\@empty %
|
|
|
+ \rlap{#3#1}%
|
|
|
+ \else \ifx\lstf@r\@empty %
|
|
|
+ \rlap{#30}%
|
|
|
+ \fi \fi %
|
|
|
+ \hss}}
|
|
|
+% \end{macrocode}
|
|
|
+% Note: There are no paramaters with numbers 20 and 30.
|
|
|
+% It's |#2| respectively |#3| with size argument 0.
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@framet}
|
|
|
+% \begin{macro}{\lst@frameb}
|
|
|
+% \begin{macro}{\lst@frameT}
|
|
|
+% \begin{macro}{\lst@frameB}
|
|
|
+% Now we can derive the 'top' and 'bottom' frame macros quite easily:
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@framet{\lst@frameh0\lst@frameTL\lst@frameTR}%
|
|
|
+\let\lst@frameb\lst@framet
|
|
|
+\def\lst@frameT{%
|
|
|
+ \lst@frameh1\lst@frameTL\lst@frameTR %
|
|
|
+ \vskip\lst@framesep %
|
|
|
+ \lst@frameh0\lst@frameTL\lst@frameTR}
|
|
|
+\def\lst@frameB{%
|
|
|
+ \lst@frameh0\lst@frameBL\lst@frameBR %
|
|
|
+ \vskip\lst@framesep %
|
|
|
+ \lst@frameh1\lst@frameBL\lst@frameBR}
|
|
|
+% \end{macrocode}
|
|
|
+% These macros are executed where needed.
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@AddToHook{BeforeSelectCharTable}
|
|
|
+ {\ifx\lstf@T\@empty %
|
|
|
+ \offinterlineskip\par\noindent\lst@frameT %
|
|
|
+ \else \ifx\lstf@t\@empty %
|
|
|
+ \offinterlineskip\par\noindent\lst@framet %
|
|
|
+ \else %
|
|
|
+ \let\lst@framet\relax %
|
|
|
+ \fi \fi %
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{TODO}
|
|
|
+% Replace |\offinterlineskip| by |\nointerlineskip|?
|
|
|
+% \end{TODO}
|
|
|
+% We look which frame types we have on the left and on the right.
|
|
|
+% \begin{macrocode}
|
|
|
+ \let\lst@framel\relax \let\lst@framer\relax %
|
|
|
+ \ifx\lstf@L\@empty %
|
|
|
+ \let\lst@framel\lst@frameV %
|
|
|
+ \else %
|
|
|
+ \ifx\lstf@l\relax\else \let\lst@framel\lst@framev \fi %
|
|
|
+ \fi %
|
|
|
+ \ifx\lstf@R\@empty %
|
|
|
+ \let\lst@framer\lst@frameV %
|
|
|
+ \else %
|
|
|
+ \ifx\lstf@r\relax\else \let\lst@framer\lst@framev \fi %
|
|
|
+ \fi %
|
|
|
+% \end{macrocode}
|
|
|
+% We can speed up things if there are no vertical frames.
|
|
|
+% \begin{macrocode}
|
|
|
+ \ifx\lst@framel\relax \ifx\lst@framer\relax %
|
|
|
+ \let\lst@framelr\relax %
|
|
|
+ \fi \fi %
|
|
|
+% \end{macrocode}
|
|
|
+% Finally we close the space between the horizontal rule and the first line (the 'depth' of the current line).
|
|
|
+% \begin{macrocode}
|
|
|
+ \ifx\lst@framelr\relax\else \ifx\lst@framet\relax\else %
|
|
|
+ {\setbox\strutbox\hbox{%
|
|
|
+ \vrule\@height0pt\@depth.3\normalbaselineskip\@width\z@}%
|
|
|
+ \kern\ifodd\c@page-\lst@innerspread\else-\lst@outerspread\fi %
|
|
|
+ \lst@framelr}%
|
|
|
+ \fi \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% The frame at the bottom:
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@AddToHook{ExitVars}
|
|
|
+ {\ifx\lstf@B\@empty %
|
|
|
+ \offinterlineskip\everypar{}\par\noindent\lst@frameB %
|
|
|
+ \else \ifx\lstf@b\@empty %
|
|
|
+ \offinterlineskip\everypar{}\par\noindent\lst@framet %
|
|
|
+ \fi \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}\end{macro}\end{macro}\end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@frameTL}
|
|
|
+% \begin{macro}{\lst@frameTR}
|
|
|
+% \begin{macro}{\lst@frameBL}
|
|
|
+% \begin{macro}{\lst@frameBR}
|
|
|
+% The 'corner' macros are left.
|
|
|
+% All save the vertical rule in a temporary box to zero the depth or height of that box.
|
|
|
+% Then we typeset the vertical and horizontal rule (in reversed order).
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@frameTL#1{%
|
|
|
+ \@tempdima\lst@framesep \advance\@tempdima\lst@framewidth %
|
|
|
+ \multiply\@tempdima#1\relax %
|
|
|
+ \setbox\@tempboxa\hbox to\z@{%
|
|
|
+ \vrule\@width\lst@framewidth\@height\z@\@depth\@tempdima\hss}%
|
|
|
+ \dp\@tempboxa\z@ %
|
|
|
+ \advance\@tempdima\lst@framewidth %
|
|
|
+ \box\@tempboxa \vrule\@width\@tempdima\@height\lst@framewidth}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@frameTR#1{%
|
|
|
+ \@tempdima\lst@framesep \advance\@tempdima\lst@framewidth %
|
|
|
+ \multiply\@tempdima#1\relax %
|
|
|
+ \setbox\@tempboxa\hbox to\z@{\hss %
|
|
|
+ \vrule\@width\lst@framewidth\@height\z@\@depth\@tempdima}%
|
|
|
+ \dp\@tempboxa\z@ %
|
|
|
+ \advance\@tempdima\lst@framewidth %
|
|
|
+ \vrule\@width\@tempdima\@height\lst@framewidth \box\@tempboxa}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@frameBL#1{%
|
|
|
+ \@tempdima\lst@framesep \advance\@tempdima\lst@framewidth %
|
|
|
+ \multiply\@tempdima#1\relax %
|
|
|
+ \advance\@tempdima\lst@framewidth %
|
|
|
+ \setbox\@tempboxa\hbox to\z@{%
|
|
|
+ \vrule\@width\lst@framewidth\@height\@tempdima\hss}%
|
|
|
+ \ht\@tempboxa\z@ %
|
|
|
+ \box\@tempboxa \vrule\@width\@tempdima\@height\lst@framewidth}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@frameBR#1{%
|
|
|
+ \@tempdima\lst@framesep \advance\@tempdima\lst@framewidth %
|
|
|
+ \multiply\@tempdima#1\relax %
|
|
|
+ \advance\@tempdima\lst@framewidth %
|
|
|
+ \setbox\@tempboxa\hbox to\z@{\hss %
|
|
|
+ \vrule\@width\lst@framewidth\@height\@tempdima}%
|
|
|
+ \ht\@tempboxa\z@ %
|
|
|
+ \vrule\@width\@tempdima\@height\lst@framewidth \box\@tempboxa}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}\end{macro}\end{macro}\end{macro}
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%</kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Pre and post listing}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%<*kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+% \begin{aspect}{pre}
|
|
|
+% \begin{aspect}{post}
|
|
|
+% A rather trivial section.
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@Aspect{pre}{\lstKV@OptArg\lstpre@[]{#1}}
|
|
|
+\lst@Aspect{post}{\lstKV@OptArg\lstpost@[]{#1}}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstpre@[#1]#2{%
|
|
|
+ \def\lst@prelisting{#2}\def\lst@@prelisting{#1}}
|
|
|
+\def\lstpost@[#1]#2{%
|
|
|
+ \def\lst@postlisting{#2}\def\lst@@postlisting{#1}}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\lstset{pre={},post={}}% init
|
|
|
+% \end{macrocode}
|
|
|
+% \end{aspect}\end{aspect}
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%</kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{\TeX\ comment lines}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%<*kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+% Communication with \lsthelper{J\"orn Wilms}{[email protected]}{1997/07/07}{\TeX\ comments} is responsible for this feature.
|
|
|
+% Some characters have a special functionality in \TeX{}, e.g.\ the underbar or the dollar sign.
|
|
|
+% These meanings are unwanted while typesetting normal source code, i.e.\ we have to define our own character table.
|
|
|
+% But for the comment lines we must interrupt the current processing and switch back to the original meanings.
|
|
|
+% And at the end we must restore all previous things.
|
|
|
+%
|
|
|
+% \begin{aspect}{texcl}
|
|
|
+% Announcing the aspect:
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@Aspect{texcl}[t]{\lstKV@SetIfKey\lst@iftexcl{#1}}
|
|
|
+\lstset{texcl=false}% init
|
|
|
+% \end{macrocode}
|
|
|
+% Things at EOL are easy, but we must allocate new modes for (\TeX) comment lines first.
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@NewMode\lst@TeXCLmode
|
|
|
+\lst@NewMode\lst@CLmode
|
|
|
+\lst@AddToHook{EOL}
|
|
|
+ {\ifnum\lst@mode=\lst@TeXCLmode %
|
|
|
+ \lst@LeaveAllModes \lst@ReenterModes %
|
|
|
+ \fi %
|
|
|
+ \ifnum\lst@mode=\lst@CLmode \lst@LeaveMode \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{aspect}
|
|
|
+%
|
|
|
+% \begin{macro}{\lstCC@BeginCommentLine}
|
|
|
+% \begin{macro}{\lstCC@@BeginCommentLine}
|
|
|
+% The first macro starts comment lines indicated by a single character (like |%| in \TeX), whereas the second does this for comment lines indicated by two characters (like |//| in C++).
|
|
|
+% According to the macro naming these two macros belong more or less to section \ref{iCharacterClasses}.
|
|
|
+% But we present them here because of \TeX\ comment lines.
|
|
|
+%
|
|
|
+% We print preceding characters (if any), begin the comment and output the comment separator.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstCC@BeginCommentLine#1{%
|
|
|
+ \lst@NewLine \lst@PrintToken %
|
|
|
+ \lst@EnterMode{\lst@CLmode}{\lst@modetrue\lst@commentstyle}%
|
|
|
+ #1\relax %
|
|
|
+% \end{macrocode}
|
|
|
+% If the user don't want \TeX\ comment lines, there is nothing more to do.
|
|
|
+% Otherwise we have to print the comment separator and interrupt the normal processing.
|
|
|
+% \begin{macrocode}
|
|
|
+ \lst@iftexcl %
|
|
|
+ \lst@PrintToken %
|
|
|
+ \lst@LeaveMode \lst@InterruptModes %
|
|
|
+ \lst@EnterMode{\lst@TeXCLmode}{\lst@modetrue\lst@commentstyle}%
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% Now comes the same, but we process a 'two character'-separator.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstCC@@BeginCommentLine#1#2{%
|
|
|
+ \lst@NewLine \lst@PrintToken %
|
|
|
+ \lst@EnterMode{\lst@CLmode}{\lst@modetrue\lst@commentstyle}%
|
|
|
+ #1\relax#2\relax %
|
|
|
+ \lst@iftexcl %
|
|
|
+ \lst@PrintToken %
|
|
|
+ \lst@LeaveMode \lst@InterruptModes %
|
|
|
+ \lst@EnterMode{\lst@TeXCLmode}{\lst@modetrue\lst@commentstyle}%
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}\end{macro}
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%</kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+%
|
|
|
+%
|
|
|
+% \section{Doing output}
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Output aspects and helpers}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%<*kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+% \begin{aspect}{flexiblecolumns}
|
|
|
+% Do you have any idea what to write here?
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@Aspect{flexiblecolumns}[t]{\lstKV@SetIfKey\lst@ifflexible{#1}}
|
|
|
+\lstset{flexiblecolumns=false}% init
|
|
|
+% \end{macrocode}
|
|
|
+% We assign the correct output macros defined below.
|
|
|
+% As you can see there are three main macros, which handle letters, all other printing characters and tabulator stops.
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@AddToHook{BeforeSelectCharTable}
|
|
|
+ {\lst@ifflexible %
|
|
|
+ \let\lst@Output\lst@OutputFlexible %
|
|
|
+ \let\lst@OutputOther\lst@OutputOtherFlexible %
|
|
|
+ \let\lst@GotoTabStop\lst@GotoTabStopFlexible %
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{aspect}
|
|
|
+%
|
|
|
+% \begin{aspect}{baseem}
|
|
|
+% We look whether or not the user gives two numbers, i.e.\ we test for a comma.
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@Aspect{baseem}{\lstbaseem@#1,,\relax}
|
|
|
+% \end{macrocode}
|
|
|
+% Here we check for legal arguments \ldots
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstbaseem@#1,#2,#3\relax{%
|
|
|
+ \def\lst@next{\PackageError{Listings}%
|
|
|
+ {Nonnegative number(s) expected}%
|
|
|
+ {Separate one or two such numbers by a comma, next time.^^J%
|
|
|
+ Now type <RETURN> to proceed.}}%
|
|
|
+ \ifdim #1em<\z@\else %
|
|
|
+ \def\lst@baseemfixed{#1}%
|
|
|
+ \let\lst@baseemflexible\lst@baseemfixed %
|
|
|
+% \end{macrocode}
|
|
|
+% and do the comma test.
|
|
|
+% \begin{macrocode}
|
|
|
+ \ifx\@empty#2\@empty %
|
|
|
+ \let\lst@next\relax %
|
|
|
+ \else \ifdim #2em<\z@\else %
|
|
|
+ \def\lst@baseemflexible{#2}%
|
|
|
+ \let\lst@next\relax %
|
|
|
+ \fi \fi %
|
|
|
+ \fi \lst@next}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\lstset{baseem={0.6,0.45}}% init
|
|
|
+% \end{macrocode}
|
|
|
+% \end{aspect}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@width}
|
|
|
+% The dimension holds the width of a single character box while typesetting a listing.
|
|
|
+% \begin{macrocode}
|
|
|
+\newdimen\lst@width
|
|
|
+\lst@AddToHook{InitVars}
|
|
|
+ {\lst@width=\lst@ifflexible\lst@baseemflexible %
|
|
|
+ \else\lst@baseemfixed\fi em\relax}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{aspect}{tabsize}
|
|
|
+% We check for a legal argument before saving it.
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@Aspect{tabsize}
|
|
|
+ {\ifnum#1>\z@ %
|
|
|
+ \def\lst@tabsize{#1}%
|
|
|
+ \else %
|
|
|
+ \PackageError{Listings}{Strict positive integer expected}
|
|
|
+ {You can't use `#1' as tabulator length.^^J%
|
|
|
+ Type <RETURN> to forget it and to proceed.}%
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% Default tabsize is 8 as proposed by \lsthelper{Rolf Niepraschk}{[email protected]}{1997/04/24}{tabsize=8}.
|
|
|
+% \begin{macrocode}
|
|
|
+\lstset{tabsize=8}% init
|
|
|
+% \end{macrocode}
|
|
|
+% \end{aspect}
|
|
|
+%
|
|
|
+% Before looking at the output macros, we have to introduce some registers.
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@token}
|
|
|
+% \begin{macro}{\lst@length}
|
|
|
+% The token register contains the current character string, for example |char| if we have just read these characters and a whitespace before.
|
|
|
+% The counter |\lst@length| holds the length of the string and that's 4 in the example.
|
|
|
+% \begin{macrocode}
|
|
|
+\newtoks\lst@token \newcount\lst@length
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@AddToHook{InitVarsEOL}{\lst@token{}\lst@length\z@}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}\end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@lastother}
|
|
|
+% This is not a \TeX{} register.
|
|
|
+% This macro is equivalent to the last 'other' character, other in the sense of section \ref{iCharacterClasses}.
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@AddToHook{InitVarsEOL}{\let\lst@lastother\@empty}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@column}
|
|
|
+% \begin{macro}{\lst@pos}
|
|
|
+% With the two counters it is possible to determine the current column.
|
|
|
+% It's the sum of |\lst@column| and |\lst@length| plus one minus |\lst@pos| --- |\lst@pos| will be nonpositive.
|
|
|
+% It seems to be troublesome to decide whether a new line has just begun or not, i.e.\ if the current column number is one.
|
|
|
+% And that's true.
|
|
|
+% \begin{macrocode}
|
|
|
+\newcount\lst@column \newcount\lst@pos % \global
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@AddToHook{InitVarsEOL}{\global\lst@pos\z@ \global\lst@column\z@}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}\end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@lostspace}
|
|
|
+% The output macros have to keep track of the difference between the real and desired (current) line width; the latter one given by 'current column times |\lst@width|'.
|
|
|
+% More precisely, |\lst@lostspace| equals 'current column times |\lst@width|' minus 'width of so far printed line'.
|
|
|
+% Whenever this dimension is positive we can insert space to fix the column alignment.
|
|
|
+% \begin{macrocode}
|
|
|
+\newdimen\lst@lostspace % \global
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@AddToHook{InitVarsEOL}{\global\lst@lostspace\z@}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@UseLostSpace}
|
|
|
+% This is a service macro for the fixed and flexible column output.
|
|
|
+% We insert space and reset it (if and) only if |\lst@lostspace| is positive.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@UseLostSpace{%
|
|
|
+ \ifdim\lst@lostspace>\z@ %
|
|
|
+ \kern\lst@lostspace \global\lst@lostspace\z@ %
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@InsertLostSpace}
|
|
|
+% \begin{macro}{\lst@InsertHalfLostSpace}
|
|
|
+% Ditto, but insert always (even if negative).
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@InsertLostSpace{\kern\lst@lostspace \global\lst@lostspace\z@}
|
|
|
+\def\lst@InsertHalfLostSpace{%
|
|
|
+ \global\[email protected]\lst@lostspace \kern\lst@lostspace}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}\end{macro}
|
|
|
+%
|
|
|
+% \begin{aspect}{outputpos}
|
|
|
+% Note that there are two |\relax|es \ldots
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@Aspect{outputpos}{\lstoutputpos@#1\relax\relax}
|
|
|
+% \end{macrocode}
|
|
|
+% or an empty argument would be bad here.
|
|
|
+% We simply test for |l|, |c| and |r|.
|
|
|
+% If none of them is given, we issue a warning and assume |r| --- it's default since it looks most bad to me.
|
|
|
+% The fixed column format makes use of |\lst@lefthss| and |\lst@righthss|, whereas the flexible needs only |\lst@leftinsert|.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstoutputpos@#1#2\relax{%
|
|
|
+ \ifx #1l%
|
|
|
+ \let\lst@lefthss\relax \let\lst@righthss\hss %
|
|
|
+ \let\lst@leftinsert\relax %
|
|
|
+ \else\ifx #1c%
|
|
|
+ \let\lst@lefthss\hss \let\lst@righthss\hss %
|
|
|
+ \let\lst@leftinsert\lst@InsertHalfLostSpace %
|
|
|
+ \else %
|
|
|
+ \let\lst@lefthss\hss \let\lst@righthss\relax %
|
|
|
+ \let\lst@leftinsert\lst@InsertLostSpace %
|
|
|
+ \ifx #1r\else \PackageWarning{Listings}%
|
|
|
+ {Unknown positioning for output boxes}%
|
|
|
+ \fi %
|
|
|
+ \fi\fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\lstset{outputpos=c}% init
|
|
|
+% \end{macrocode}
|
|
|
+% \end{aspect}
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%</kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Dropping empty lines}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%<*kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+% \begin{macro}{\lst@NewLineMacro}
|
|
|
+% This macro is assigned to |\lst@NewLine|, which is executed whenever the (next) line is not empty.
|
|
|
+% Once called, it deactivates itself.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@NewLineMacro{%
|
|
|
+ \global\let\lst@NewLine\relax \par\noindent\hbox{}}
|
|
|
+\lst@AddToHook{InitVars}{\global\let\lst@NewLine\lst@NewLineMacro}
|
|
|
+% \end{macrocode}
|
|
|
+% What we have said about |\lst@NewLine| is not the whole truth.
|
|
|
+% Most times we'll assign |\lst@NewLineMacro|, but sometimes we append |\par\noindent\hbox{}| to prepare a new line, namely in the case that the last line has been empty.
|
|
|
+% Then |\lst@NewLine| deactivates itself and begins two, three or more (empty) lines.
|
|
|
+% This drops empty lines at the end of a listing.
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@AddToHook{EOL}
|
|
|
+ {\ifx\lst@NewLine\relax %
|
|
|
+ \global\let\lst@NewLine\lst@NewLineMacro %
|
|
|
+ \else %
|
|
|
+ \lst@AddTo\lst@NewLine{\par\noindent\hbox{}}%
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%</kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Fixed columns}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%<*kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+% \begin{macro}{\lst@OutputOther}
|
|
|
+% This macro outputs a character string with nonletters.
|
|
|
+% If there is anything to output, we possibly start a new line.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@OutputOther{%
|
|
|
+ \ifnum\lst@length=\z@\else %
|
|
|
+ \lst@NewLine \lst@UseLostSpace %
|
|
|
+% \end{macrocode}
|
|
|
+% The box must take |\lst@length| characters, each |\lst@width| wide.
|
|
|
+% \begin{macrocode}
|
|
|
+ \hbox to \lst@length\lst@width{%
|
|
|
+ \lst@lefthss %
|
|
|
+ \lsthk@OutputOther %
|
|
|
+ \expandafter\lst@FillOutputBox\the\lst@token\relax %
|
|
|
+ \lst@righthss}%
|
|
|
+% \end{macrocode}
|
|
|
+% Finally we hold up the current column, empty the token and close the starting 'if token not empty'.
|
|
|
+% \begin{macrocode}
|
|
|
+ \global\advance\lst@pos -\lst@length %
|
|
|
+ \lst@token{}\lst@length\z@ %
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@Output}
|
|
|
+% We reset |\lst@lastother| and use |\lst@thestyle|.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@Output{%
|
|
|
+ \let\lst@lastother\relax %
|
|
|
+ \ifnum\lst@length=\z@\else %
|
|
|
+ \lst@NewLine \lst@UseLostSpace %
|
|
|
+ \hbox to \lst@length\lst@width{%
|
|
|
+ \lst@lefthss %
|
|
|
+ \lsthk@Output \lst@thestyle{%
|
|
|
+ \expandafter\lst@FillOutputBox\the\lst@token\relax}%
|
|
|
+ \lst@righthss}%
|
|
|
+ \global\advance\lst@pos -\lst@length %
|
|
|
+ \lst@token{}\lst@length\z@ %
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% Note that |\lst@lastother| becomes equivalent to |\relax| and not equivalent to |\@empty| as in all other places (e.g.\ InitVarsEOL).
|
|
|
+% I don't know whether this will be important in future or not.
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@FillOutputBox}
|
|
|
+% Filling up a box is easy.
|
|
|
+% If we come to the end (the |\relax| from above), we do nothing.
|
|
|
+% Otherwise we output the argument, insert dynamic space and call the macro again.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@FillOutputBox#1{%
|
|
|
+ \ifx\relax#1\else #1\hss\expandafter\lst@FillOutputBox \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@GotoTabStop}
|
|
|
+% For fixed column format we only need to advance |\lst@lostspace| (which is inserted by the output macros above) and update the column.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@GotoTabStop{%
|
|
|
+ \global\advance\lst@lostspace \lst@length\lst@width %
|
|
|
+ \global\advance\lst@column\lst@length \lst@length\z@}%
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%</kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Flexible columns}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%<*kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+% \begin{macro}{\lst@OutputOtherFlexible}
|
|
|
+% If there is something to output, we first insert the space lost by the flexible column format.
|
|
|
+% Then we typeset the box and update the lost space.
|
|
|
+% Note that we don't use any |\hss| here.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@OutputOtherFlexible{%
|
|
|
+ \ifnum\lst@length=\z@\else %
|
|
|
+ \lst@NewLine \lst@UseLostSpace %
|
|
|
+ \setbox\@tempboxa\hbox{\lsthk@OutputOther\the\lst@token}%
|
|
|
+ \lst@CalcLostSpaceAndOutput %
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@OutputFlexible}
|
|
|
+% Nothing is new here.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@OutputFlexible{%
|
|
|
+ \let\lst@lastother\relax %
|
|
|
+ \ifnum\lst@length=\z@\else %
|
|
|
+ \lst@NewLine \lst@UseLostSpace %
|
|
|
+ \setbox\@tempboxa\hbox{%
|
|
|
+ \lsthk@Output \lst@thestyle{\the\lst@token}}%
|
|
|
+ \lst@CalcLostSpaceAndOutput %
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@GotoTabStopFlexible}
|
|
|
+% Here we look whether or not the line already contains printing characters.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@GotoTabStopFlexible{%
|
|
|
+ \ifx\lst@NewLine\relax %
|
|
|
+% \end{macrocode}
|
|
|
+% If some characters are already printed, we output a box, which has the width of a blank space.
|
|
|
+% Possibly more space is inserted, but that's upto the current value of |\lst@lostspace|.
|
|
|
+% \begin{macrocode}
|
|
|
+ \setbox\@tempboxa\hbox{\lst@outputblank}\@tempdima\wd\@tempboxa%
|
|
|
+ \setbox\@tempboxa\hbox{}\wd\@tempboxa\@tempdima %
|
|
|
+ \lst@CalcLostSpaceAndOutput %
|
|
|
+ \global\lst@pos\z@ %
|
|
|
+ \else %
|
|
|
+% \end{macrocode}
|
|
|
+% Otherwise (no printed characters) we do the same as for fixed columns.
|
|
|
+% \begin{macrocode}
|
|
|
+ \global\advance\lst@lostspace \lst@length\lst@width %
|
|
|
+ \global\advance\lst@column\lst@length \lst@length\z@ %
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@CalcLostSpaceAndOutput}
|
|
|
+% The update of |\lst@lostspace| is simple, refer its definition above (difference between \ldots).
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@CalcLostSpaceAndOutput{%
|
|
|
+ \global\advance\lst@lostspace \lst@length\lst@width %
|
|
|
+ \global\advance\lst@lostspace-\wd\@tempboxa %
|
|
|
+% \end{macrocode}
|
|
|
+% Moreover we keep track of |\lst@pos| and reset some variables.
|
|
|
+% \begin{macrocode}
|
|
|
+ \global\advance\lst@pos -\lst@length %
|
|
|
+ \lst@token{}\lst@length\z@ %
|
|
|
+% \end{macrocode}
|
|
|
+% Before |\@tempboxa| is output, we insert appropiate space if there is enough lost space.
|
|
|
+% \begin{macrocode}
|
|
|
+ \ifdim\lst@lostspace>\z@ \lst@leftinsert \fi %
|
|
|
+ \box\@tempboxa}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%</kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Dropping the whole output}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%<*kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+% \begin{macro}{\lst@BeginDropOutput}
|
|
|
+% It's sometimes useful to process a part of a listing as usual, but to drop the output.
|
|
|
+% This macro does the main work and gets one argument, namely the internal mode it enters.
|
|
|
+% We save |\lst@NewLine|, restore it |\aftergroup| and redefine the output macros.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@BeginDropOutput#1{%
|
|
|
+ \let\lst@BDOsave\lst@NewLine %
|
|
|
+ \lst@EnterMode{#1}%
|
|
|
+ {\lst@modetrue %
|
|
|
+ \let\lst@Output\lst@EmptyOutput %
|
|
|
+ \let\lst@OutputOther\lst@EmptyOutputOther %
|
|
|
+ \let\lst@GotoTabStop\lst@EmptyGotoTabStop %
|
|
|
+ \aftergroup\lst@BDORestore}}
|
|
|
+% \end{macrocode}
|
|
|
+% Restoring |\lst@NewLine| is quite easy:
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@BDORestore{\global\let\lst@NewLine\lst@BDOsave}
|
|
|
+% \end{macrocode}
|
|
|
+% Note that there is no |\lst@EndDropOutput| since this macro would be equivalent to |\lst@LeaveMode|.
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@EmptyOutputOther}
|
|
|
+% \begin{macro}{\lst@EmptyOutput}
|
|
|
+% \begin{macro}{\lst@EmptyGotoTabStop}
|
|
|
+% Here we only keep track of registers (possibly) needed by other processing macros.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@EmptyOutputOther{%
|
|
|
+ \global\advance\lst@pos -\lst@length %
|
|
|
+ \lst@token{}\lst@length\z@}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@EmptyOutput{\let\lst@lastother\relax \lst@EmptyOutputOther}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@EmptyGotoTabStop{%
|
|
|
+ \global\advance\lst@column\lst@length \lst@length\z@}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}\end{macro}\end{macro}
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%</kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Writing to an external file}
|
|
|
+%
|
|
|
+% The macros are defined (if and) only if the |doc| option is used.
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%<*kernel>
|
|
|
+\@ifundefined{lst@doc}{}{%
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+%
|
|
|
+% \begin{macro}{\lstdoc@out}
|
|
|
+% The file we will write to.
|
|
|
+% \begin{macrocode}
|
|
|
+\newwrite\lstdoc@out
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@BeginWriteFile}
|
|
|
+% redefines some macros to meet our purpose.
|
|
|
+% The file with name |#1| is opened at the end of the macro.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@BeginWriteFile#1{%
|
|
|
+ \begingroup %
|
|
|
+ \lsthk@SetLanguage %
|
|
|
+ \let\lstCC@ifec\iffalse %
|
|
|
+ \let\lst@Output\lstdoc@Output %
|
|
|
+ \let\lst@OutputOther\lstdoc@Output %
|
|
|
+ \let\lst@GotoTabStop\lstdoc@GotoTabStop %
|
|
|
+ \let\lstCC@ProcessSpace\lstdoc@ProcessSpace %
|
|
|
+ \let\lst@MProcessListing\lstdoc@MProcessListing %
|
|
|
+ \let\smallbreak\relax %
|
|
|
+ \let\lst@prelisting\relax \let\lst@postlisting\relax %
|
|
|
+ \let\lst@@prelisting\relax \let\lst@@postlisting\relax %
|
|
|
+ \let\lstCC@Use\lstdoc@Use %
|
|
|
+ \let\lst@DeInit\lstdoc@DeInit %
|
|
|
+ \immediate\openout\lstdoc@out=#1\relax}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@EndWriteFile}
|
|
|
+% closes the file and restores original macro meanings.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@EndWriteFile{\immediate\closeout\lstdoc@out \endgroup}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lstdoc@Output}
|
|
|
+% keeps only track of horizontal position.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstdoc@Output{\global\advance\lst@pos -\lst@length \lst@length\z@}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lstdoc@ProcessSpace}
|
|
|
+% \begin{macro}{\lstdoc@GotoTabStop}
|
|
|
+% We append the appropiate number of spaces.
|
|
|
+% Note that |\lstCC@Append| increases |\lst@length| by 1, thus we need -2.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstdoc@ProcessSpace{\lstCC@Append{ }}
|
|
|
+\def\lstdoc@GotoTabStop{%
|
|
|
+ \@whilenum \lst@length>\z@ \do %
|
|
|
+ {\lstCC@Append{ }\advance\lst@length-2\relax}}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}\end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lstdoc@MProcessListing}
|
|
|
+% writes one line to external file.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstdoc@MProcessListing{%
|
|
|
+ \immediate\write\lstdoc@out{\the\lst@token}%
|
|
|
+ \lst@token{}\lst@length\z@ %
|
|
|
+ \lst@BOLGobble}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lstdoc@DeInit}
|
|
|
+% We write the rest to file and end processing.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstdoc@DeInit{%
|
|
|
+ \ifnum\lst@length=\z@\else %
|
|
|
+ \immediate\write\lstdoc@out{\the\lst@token}%
|
|
|
+ \fi %
|
|
|
+ \egroup \smallbreak\lst@postlisting \endgroup}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lstdoc@Use}
|
|
|
+% Any processed character appends the character itself to |\lst@token| (but with catcode 12 or 10).
|
|
|
+% The original |\lstCC@Use| is defined in section \ref{iCharacterTables}.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstdoc@Use#1#2#3{%
|
|
|
+ \ifnum#2=\z@ %
|
|
|
+ \expandafter\@gobbletwo %
|
|
|
+ \else %
|
|
|
+ \catcode#2=\active \lccode`\~=#2\lccode`\/=#2%
|
|
|
+ \lowercase{\def~{\lstCC@Append{/}}}%
|
|
|
+ \fi %
|
|
|
+ \lstdoc@Use#1}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+}% of \@ifundefined{lst@doc}{}{%
|
|
|
+%</kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Keyword comments}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%<*keywordcomments>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+% \begin{aspect}{keywordcomment}
|
|
|
+% \begin{aspect}{doublekeywordcommentsemicolon}
|
|
|
+% The same stuff as for the other comment commands.
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@Aspect{keywordcomment}
|
|
|
+ {\lst@MakeKeywordArg{#1}\let\lst@KCkeywords\lst@arg %
|
|
|
+ \let\lst@DefKC\lstCC@KeywordComment}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@Aspect{doublekeywordcommentsemicolon}{\lstDKCS@#1}
|
|
|
+\gdef\lstDKCS@#1#2#3%
|
|
|
+ {\lst@MakeKeywordArg{#1}\let\lst@KCAkeywordsB\lst@arg %
|
|
|
+ \lst@MakeKeywordArg{#2}\let\lst@KCAkeywordsE\lst@arg %
|
|
|
+ \lst@MakeKeywordArg{#3}\let\lst@KCBkeywordsB\lst@arg %
|
|
|
+ \let\lst@DefKC\lstCC@DoubleKeywordCommentS}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@AddToHook{SelectCharTable}{\lst@DefKC}
|
|
|
+\lst@AddToHook{BeforeSelectCharTable}
|
|
|
+ {\lst@ifsensitive\else %
|
|
|
+ \lst@MakeMacroUppercase\lst@KCkeywords %
|
|
|
+ \lst@MakeMacroUppercase\lst@KCAkeywordsB %
|
|
|
+ \lst@MakeMacroUppercase\lst@KCAkeywordsE %
|
|
|
+ \lst@MakeMacroUppercase\lst@KCBkeywordsB %
|
|
|
+ \fi}
|
|
|
+\lst@AddToHook{SetLanguage}{%
|
|
|
+ \let\lst@DefKC\relax \let\lst@KCkeywords\@undefined %
|
|
|
+ \let\lst@KCAkeywordsB\@undefined \let\lst@KCAkeywordsE\@undefined %
|
|
|
+ \let\lst@KCBkeywordsB\@undefined}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{aspect}\end{aspect}
|
|
|
+%
|
|
|
+% \begin{macro}{\lstCC@KeywordComment}
|
|
|
+% For this type of keyword comments we save the old output macro and install a new one.
|
|
|
+% Note that |\lstCC@KeywordComment| is executed after selecting the character table via |\lst@DefKC|.
|
|
|
+% \begin{macrocode}
|
|
|
+\gdef\lstCC@KeywordComment{%
|
|
|
+ \let\lst@Output@\lst@Output \let\lst@Output\lst@KCOutput}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@KCOutput}
|
|
|
+% And now we look how the output works here.
|
|
|
+% It starts as all the time.
|
|
|
+% But if the current character sequence in |\lst@token| is one of the given keywords, we call a macro which starts and ends keyword comments.
|
|
|
+% |\lst@next| is redefined there.
|
|
|
+% After doing all this, we output the token as usual and go on.
|
|
|
+% \begin{macrocode}
|
|
|
+\gdef\lst@KCOutput{%
|
|
|
+ \ifnum\lst@length=\z@\else %
|
|
|
+ \let\lst@next\relax %
|
|
|
+ \expandafter\lst@IfOneOf \the\lst@token\relax \lst@KCkeywords %
|
|
|
+ {\lst@KCOutput@\lst@BeginKC}{}%
|
|
|
+ \lst@Output@ \lst@next %
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@KCOutput@}
|
|
|
+% Now we are in the situation that the current token is attached to a keyword comment.
|
|
|
+% By default |\lst@next| becomes equivalent to the first argument, which is either |\lst@BeginKC| or |\lst@BeginDKCA| or |\lst@BeginDKCB|.
|
|
|
+% Moreover we save the current token.
|
|
|
+% \begin{macrocode}
|
|
|
+\gdef\lst@KCOutput@#1{\let\lst@next#1%
|
|
|
+ \expandafter\def\expandafter\lst@save\expandafter{\the\lst@token}%
|
|
|
+% \end{macrocode}
|
|
|
+% If we are not in 'keyword comment mode', nothing else is done here.
|
|
|
+% But if we are, we must end the comment.
|
|
|
+% The problem: Closing the comment group also ruins the current character string in |\lst@token|.
|
|
|
+% The solution: We define a global macro to restore the token and |\lst@length|.
|
|
|
+% |\@gtempa| becomes
|
|
|
+% \begin{itemize}\item[]
|
|
|
+% |\lst@token{|\meta{current character string}|}\lst@length|\meta{current length}|\relax|
|
|
|
+% \end{itemize}
|
|
|
+% \begin{macrocode}
|
|
|
+ \lst@ifmode \ifnum\lst@mode=\lst@KCmode %
|
|
|
+ \xdef\@gtempa{%
|
|
|
+ \noexpand\lst@token{\the\lst@token}%
|
|
|
+ \noexpand\lst@length\the\lst@length\relax}%
|
|
|
+% \end{macrocode}
|
|
|
+% This macro is executed after closing the comment group.
|
|
|
+% We redefine |\lst@next| just to |\relax|.
|
|
|
+% \begin{macrocode}
|
|
|
+ \aftergroup\@gtempa \lst@LeaveMode \let\lst@next\relax %
|
|
|
+ \fi \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@BeginKC}
|
|
|
+% We call |\lstCC@BeginComment| and define |\lst@KCkeywords| to be the current token (possibly made upper case) since we want a matching keyword.
|
|
|
+% Note: It's a local definition, i.e.\ after ending the comment all comment starting keywords are restored.
|
|
|
+% \begin{macrocode}
|
|
|
+\gdef\lst@BeginKC{%
|
|
|
+ \lstCC@BeginComment\lst@KCmode \let\lst@KCkeywords\lst@save %
|
|
|
+ \lst@ifsensitive\else \lst@MakeMacroUppercase\lst@KCkeywords \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lstCC@DoubleKeywordCommentS}
|
|
|
+% Let's look at the next macro collection.
|
|
|
+% The first macro is the same as the first from above --- except that we must install a different semicolon, which is done at the very beginning.
|
|
|
+% \begin{macrocode}
|
|
|
+\gdef\lstCC@DoubleKeywordCommentS{%
|
|
|
+ \lstCC@EndKeywordComment{"003B}%
|
|
|
+ \let\lst@Output@\lst@Output \let\lst@Output\lst@DKCOutput}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@DKCOutput}
|
|
|
+% The second macro is also the same as above, but if we haven't found a keyword from the |KCA| list, we try the |KCB| list.
|
|
|
+% \begin{macrocode}
|
|
|
+\gdef\lst@DKCOutput{%
|
|
|
+ \ifnum\lst@length=\z@\else %
|
|
|
+ \let\lst@next\relax %
|
|
|
+ \expandafter\lst@IfOneOf \the\lst@token\relax\lst@KCAkeywordsB %
|
|
|
+ {\lst@KCOutput@\lst@BeginDKCA}{%
|
|
|
+ \expandafter\lst@IfOneOf \the\lst@token\relax\lst@KCBkeywordsB %
|
|
|
+ {\lst@KCOutput@\lst@BeginDKCB}{}}%
|
|
|
+ \lst@Output@ \lst@next %
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@BeginDKCA}
|
|
|
+% \begin{macro}{\lst@BeginDKCB}
|
|
|
+% To begin a keyword comment, we assign appropiate lists of keywords, which might end the comment.
|
|
|
+% \begin{macrocode}
|
|
|
+\gdef\lst@BeginDKCA{\lstCC@BeginComment\lst@KCmode %
|
|
|
+ \let\lst@KCAkeywordsB\lst@KCAkeywordsE \let\lst@KCBkeywordsB\@empty}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\gdef\lst@BeginDKCB{\lstCC@BeginComment\lst@KCmode %
|
|
|
+ \let\lst@KCAkeywordsB\@empty \let\lst@KCBkeywordsB\@empty}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}\end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lstCC@EndKeywordComment}
|
|
|
+% Above we've installed a 'end keyword comment' semicolon.
|
|
|
+% Before reading further you should be familiar with section \ref{iCharacterTables}.
|
|
|
+% Roughly speaking we define commands there, which annouces the source code character $0041_{\mathrm{hex}}$='A' to be the upper case letter 'A'.
|
|
|
+% The macro here announces a character to end keyword comments.
|
|
|
+% \begin{macrocode}
|
|
|
+\gdef\lstCC@EndKeywordComment#1{%
|
|
|
+ \lccode`\~=#1\lowercase{\lstCC@EndKeywordComment@~}{#1}}
|
|
|
+% \end{macrocode}
|
|
|
+% Looking at the submacro, |#1| is an active character with ASCII code |#2|.
|
|
|
+% We must save a previous meaning of |#1| --- or we couldn't output the character since we've forgotten it.
|
|
|
+% Afterwards we can redefine it: If we are in comment mode and furthermore in keyword comment mode, the 'end keyword comment' character ends the comment, as desired.
|
|
|
+% Note that we output the old meaning of the character first.
|
|
|
+% \begin{macrocode}
|
|
|
+\gdef\lstCC@EndKeywordComment@#1#2{%
|
|
|
+ \expandafter\let\csname lstCC@EKC#2\endcsname#1%
|
|
|
+ \def#1{%
|
|
|
+ \ifnum\lst@mode=\lst@KCmode %
|
|
|
+ \let\lstCC@next\lstCC@EndComment %
|
|
|
+ \else %
|
|
|
+ \let\lstCC@next\relax %
|
|
|
+ \fi %
|
|
|
+ \csname lstCC@EKC#2\endcsname \lstCC@next}}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%</keywordcomments>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+%
|
|
|
+%
|
|
|
+% \section{Character classes}\label{iCharacterClasses}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%<*kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+% \TeX{} knows sixteen category codes.
|
|
|
+% We define our own character classes here.
|
|
|
+% Each input character becomes active in the sense of \TeX{} and characters of different classes expand to different meanings.
|
|
|
+% We use the following ones:
|
|
|
+% \begin{itemize}
|
|
|
+% \item letters --- characters identifiers are of;
|
|
|
+% \item digits --- characters for identifiers or numerical constants;
|
|
|
+% \item spaces --- characters treated as blank spaces;
|
|
|
+% \item tabulators --- characters treated as tabulators;
|
|
|
+% \item stringizers --- characters beginning and ending strings;
|
|
|
+% \item comment indicators --- characters or character sequences beginning and ending comments;
|
|
|
+% \item special classes support particular programming languages;
|
|
|
+% \item others --- all other characters.
|
|
|
+% \end{itemize}
|
|
|
+% How these classes work together?
|
|
|
+% The digit '3' appends the digit to the current character string, e.g.\ |ear| becomes |ear3|.
|
|
|
+% The next nonletter causes the output of the gathered characters.
|
|
|
+% Then we collect all coming nonletters until reaching a letter again.
|
|
|
+% This causes the output of the nonletters, and so on.
|
|
|
+%
|
|
|
+% But there are more details.
|
|
|
+% Stringizers and comment indicators change the processing mode until the string or the comment is over.
|
|
|
+% For example, no keyword tests are done within a string or comment.
|
|
|
+% A tabulator immediately outputs the gathered characters, without looking whether they are letters or not.
|
|
|
+% Afterwards it is possible to determine the tabulator skip.
|
|
|
+% And there is one thing concerning spaces:
|
|
|
+% Many spaces following each other disturb the column alignment since they are not wide enough.
|
|
|
+% Hence, when column alignment is on, we output the space(s) preceding a space.
|
|
|
+%
|
|
|
+% The above classes can be divided into three types:
|
|
|
+% \begin{itemize}
|
|
|
+% \item The 'letter', 'digit' and 'other' class all put characters into the 'output queue' (using |\lstCC@Append| or |\lstCC@AppendOther|, see below).
|
|
|
+% \item Stringizer, comment indicators and special classes don't affect the output queue directly.
|
|
|
+% For example, before a character becomes a stringizer, the 'letter', 'digit' or 'other' meaning is saved.
|
|
|
+% Now the stringizer accesses the output queue via this saved meaning.
|
|
|
+% \item Spaces and tabulators don't put any character into the output queue, but may affect the queue to do their job, as mentioned above.
|
|
|
+% Instances of these classes are not overwritten (in contrast to letters, digits and others).
|
|
|
+% \end{itemize}
|
|
|
+% Some easy implementation before looking closer \ldots
|
|
|
+%
|
|
|
+% \begin{macro}{\lstCC@Append}
|
|
|
+% This macro appends the argument to the current character string and increases the counter |\lst@length|.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstCC@Append#1{\advance\lst@length\@ne %
|
|
|
+ \expandafter\lst@token\expandafter{\the\lst@token#1}}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lstCC@AppendOther}
|
|
|
+% Nearly the same, but we save the argument (a single character or a single macro) in |\lst@lastother|.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstCC@AppendOther#1{\advance\lst@length\@ne \let\lst@lastother#1%
|
|
|
+ \expandafter\lst@token\expandafter{\the\lst@token#1}}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lstCC@ifletter}
|
|
|
+% This \texttt{if} indicates whether the last character has been a letter or not.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstCC@lettertrue{\let\lstCC@ifletter\iftrue}
|
|
|
+\def\lstCC@letterfalse{\let\lstCC@ifletter\iffalse}
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@AddToHook{InitVars}{\lstCC@letterfalse}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@PrintToken}
|
|
|
+% This macro outputs the current character string in letter or nonletter mode.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lst@PrintToken{%
|
|
|
+ \lstCC@ifletter %
|
|
|
+ \lst@Output\lstCC@letterfalse %
|
|
|
+ \else %
|
|
|
+ \lst@OutputOther \let\lst@lastother\@empty %
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%</kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Character tables}\label{iCharacterTables}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%<*kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+% Before looking at interesting character classes we do some rather tedious coding.
|
|
|
+% Consider a source file of a programming language now.
|
|
|
+% For example, the character $41_{\mathrm{hex}}=65_{\mathrm{dec}}$ usually belongs to the letter class and represents the letter 'A'.
|
|
|
+% The listings package says |\lstCC@Use\lstCC@ProcessLetter|\ldots|{"41}{A}|\ldots\ to make this clear.
|
|
|
+% Roughly speaking it expands to |\def A{\lstCC@ProcessLetter A}|, but the first 'A' is active and the second not.
|
|
|
+%
|
|
|
+% \begin{macro}{\lstCC@Def}
|
|
|
+% \begin{macro}{\lstCC@Let}
|
|
|
+% For speed we won't used these helpers too often.
|
|
|
+% The letter 'A' definition from above could be achieved via |\lstCC@Def{"41}{\lstCC@ProcessLetter A}|.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstCC@Def#1{\catcode#1=\active\lccode`\~=#1\lowercase{\def~}}
|
|
|
+\def\lstCC@Let#1{\catcode#1=\active\lccode`\~=#1\lowercase{\let~}}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}\end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@SelectCharTable}
|
|
|
+% Each input character becomes active and gets the correct meaning here.
|
|
|
+% We change locally the catcode of the double quote for compatibility with \texttt{german.sty}.
|
|
|
+% Note that some macros take one argument and others a series of arguments which is terminated by |{"00}{}| (or an equivalent expression).
|
|
|
+% \begin{macrocode}
|
|
|
+\begingroup \catcode`\"=12
|
|
|
+\gdef\lst@SelectCharTable{%
|
|
|
+ \lstCC@Tabulator{"09}%
|
|
|
+ \lstCC@Space{"20}%
|
|
|
+ \lstCC@Use \lstCC@ProcessOther %
|
|
|
+ {"21}!{"22}"{"23}\#{"25}\%{"26}\&{"27}'{"28}({"29})%
|
|
|
+ {"2A}\lst@asterisk{"2B}+{"2C},{"2D}\lst@minus{"2E}.%
|
|
|
+ {"2F}/{"3A}:{"3B};{"3C}\lst@less{"3D}={"3E}\lst@greater{"3F}?%
|
|
|
+ {"5B}[{"5C}\lst@backslash{"5D}]{"5E}\textasciicircum{"60}{`}%
|
|
|
+ {"7B}\lst@lbrace{"7C}\lst@bar{"7D}\lst@rbrace %
|
|
|
+ {"7E}\textasciitilde{"7F}-%
|
|
|
+ \z@\@empty %
|
|
|
+ \lstCC@Use \lstCC@ProcessDigit %
|
|
|
+ {"30}0{"31}1{"32}2{"33}3{"34}4{"35}5{"36}6{"37}7{"38}8{"39}9%
|
|
|
+ \z@\@empty %
|
|
|
+ \lstCC@Use \lstCC@ProcessLetter %
|
|
|
+ {"24}\lst@dollar{"40}@%
|
|
|
+ {"41}A{"42}B{"43}C{"44}D{"45}E{"46}F{"47}G{"48}H{"49}I{"4A}J%
|
|
|
+ {"4B}K{"4C}L{"4D}M{"4E}N{"4F}O{"50}P{"51}Q{"52}R{"53}S{"54}T%
|
|
|
+ {"55}U{"56}V{"57}W{"58}X{"59}Y{"5A}Z{"5F}\lst@underscore %
|
|
|
+ {"61}a{"62}b{"63}c{"64}d{"65}e{"66}f{"67}g{"68}h{"69}i{"6A}j%
|
|
|
+ {"6B}k{"6C}l{"6D}m{"6E}n{"6F}o{"70}p{"71}q{"72}r{"73}s{"74}t%
|
|
|
+ {"75}u{"76}v{"77}w{"78}x{"79}y{"7A}z%
|
|
|
+ \z@\@empty %
|
|
|
+% \end{macrocode}
|
|
|
+% Define extended characters 128--255.
|
|
|
+% \begin{macrocode}
|
|
|
+ \lstCC@ifec \lstCC@DefEC \fi %
|
|
|
+% \end{macrocode}
|
|
|
+% Finally we call some (hook) macros and initialize the backslash if necessary.
|
|
|
+% \begin{macrocode}
|
|
|
+ \lsthk@SelectCharTable %
|
|
|
+ \csname lstSCT@\lst@language\endcsname %
|
|
|
+ \csname lstSCT@\lst@language @\lst@dialect\endcsname %
|
|
|
+ \ifx\lstCC@Backslash\relax\else %
|
|
|
+ \lccode`\~="5C\lowercase{\let\lsts@backslash~}%
|
|
|
+ \lstCC@Let{"5C}\lstCC@Backslash %
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lstCC@DefEC}
|
|
|
+% Currently each character in the range 128--255 is treated as a letter.
|
|
|
+% \begin{macrocode}
|
|
|
+\catcode`\^^@=12
|
|
|
+\gdef\lstCC@DefEC{%
|
|
|
+ \lstCC@ECUse \lstCC@ProcessLetter %
|
|
|
+ ^^80^^81^^82^^83^^84^^85^^86^^87^^88^^89^^8a^^8b^^8c^^8d^^8e^^8f%
|
|
|
+ ^^90^^91^^92^^93^^94^^95^^96^^97^^98^^99^^9a^^9b^^9c^^9d^^9e^^9f%
|
|
|
+ ^^a0^^a1^^a2^^a3^^a4^^a5^^a6^^a7^^a8^^a9^^aa^^ab^^ac^^ad^^ae^^af%
|
|
|
+ ^^b0^^b1^^b2^^b3^^b4^^b5^^b6^^b7^^b8^^b9^^ba^^bb^^bc^^bd^^be^^bf%
|
|
|
+ ^^c0^^c1^^c2^^c3^^c4^^c5^^c6^^c7^^c8^^c9^^ca^^cb^^cc^^cd^^ce^^cf%
|
|
|
+ ^^d0^^d1^^d2^^d3^^d4^^d5^^d6^^d7^^d8^^d9^^da^^db^^dc^^dd^^de^^df%
|
|
|
+ ^^e0^^e1^^e2^^e3^^e4^^e5^^e6^^e7^^e8^^e9^^ea^^eb^^ec^^ed^^ee^^ef%
|
|
|
+ ^^f0^^f1^^f2^^f3^^f4^^f5^^f6^^f7^^f8^^f9^^fa^^fb^^fc^^fd^^fe^^ff%
|
|
|
+ ^^00}
|
|
|
+\endgroup
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{aspect}{extendedchars}
|
|
|
+% The user aspect.
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@Aspect{extendedchars}[t]{\lstKV@SetIfKey\lstCC@ifec{#1}}
|
|
|
+\lstset{extendedchars=false}% init
|
|
|
+% \end{macrocode}
|
|
|
+% \end{aspect}
|
|
|
+%
|
|
|
+% \begin{macro}{\lstCC@Use}
|
|
|
+% Now we define the |\lstCC@|\ldots|Use| macros used above.
|
|
|
+% We either define the character with code |#2| to be |#1#3| (where |#1| is |\lstCC@ProcessLetter| for example) or we gobble the two token after |\fi| to terminate the loop.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstCC@Use#1#2#3{%
|
|
|
+ \ifnum#2=\z@ %
|
|
|
+ \expandafter\@gobbletwo %
|
|
|
+ \else %
|
|
|
+ \catcode#2=\active \lccode`\~=#2\lowercase{\def~}{#1#3}%
|
|
|
+ \fi %
|
|
|
+ \lstCC@Use#1}
|
|
|
+% \end{macrocode}
|
|
|
+% Limitation: Each second argument to |\lstCC@Use| (beginning with the third one) must be exactly one character or one control sequence.
|
|
|
+% The reason is not the definition here.
|
|
|
+% |\lst@AppendOther| says |\let\lst@lastother#1| and that works with the mentioned limitation only.
|
|
|
+% I'll get over this since |\let| is faster than |\def|, and that's the motivation.
|
|
|
+% \emph{Caution}: Don't change that |\let| to a definition with |\def|.
|
|
|
+% All |\ifx\lst@lastother|\ldots{} in all character classes wouldn't work any more!
|
|
|
+% And rewriting all this would slow down the package.
|
|
|
+% Beware of that.
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lstCC@ECUse}
|
|
|
+% Here we have two arguments only, namely |\lstCC@ProcessLetter|,\ldots\ and the character (and no character code).
|
|
|
+% Reaching end of list (|^^00|) we terminate the loop.
|
|
|
+% Otherwise we do the same as in |\lstCC@Use| if the character is not active.
|
|
|
+% But if the character is active, we save the meaning before redefinition.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstCC@ECUse#1#2{%
|
|
|
+ \ifnum`#2=\z@ %
|
|
|
+ \expandafter\@gobbletwo %
|
|
|
+ \else %
|
|
|
+ \ifnum\catcode`#2=\active %
|
|
|
+ \lccode`\~=`#2\lccode`\/=`#2\lowercase{\lstCC@ECUse@#1~/}%
|
|
|
+ \else %
|
|
|
+ \catcode`#2=\active \lccode`\~=`#2\lowercase{\def~}{#1#2}%
|
|
|
+ \fi %
|
|
|
+ \fi %
|
|
|
+ \lstCC@ECUse#1}
|
|
|
+% \end{macrocode}
|
|
|
+% As mentioned, we save the meaning before redefinition.
|
|
|
% \begin{macrocode}
|
|
|
-%<*package>
|
|
|
-\newif\iflisting
|
|
|
-\newread\lst@inputfile
|
|
|
-\def\lst@endinputtrue{\let\lst@ifendinput\iftrue}
|
|
|
-\def\lst@endinputfalse{\let\lst@ifendinput\iffalse}
|
|
|
+\def\lstCC@ECUse@#1#2#3{%
|
|
|
+ \expandafter\let\csname lsts@EC#3\endcsname #2%
|
|
|
+ \edef#2{\noexpand#1\expandafter\noexpand\csname lsts@EC#3\endcsname}}
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}\end{macro}\end{macro}
|
|
|
+% \end{macro}
|
|
|
%
|
|
|
-% \begin{macro}{\lst@lastno}
|
|
|
-% \begin{macro}{\lst@lineno}
|
|
|
-% The user specified last line and the current input line are kept
|
|
|
-% in two counters:
|
|
|
+% \begin{macro}{\lstCC@Tabulator}
|
|
|
+% \begin{macro}{\lstCC@Space}
|
|
|
+% The similar space and tabulator macros have one argument only (no loop and no macro or character).
|
|
|
% \begin{macrocode}
|
|
|
-\newcount\lst@lastno \newcount\lst@lineno
|
|
|
+\def\lstCC@Tabulator#1{\lstCC@Let{#1}\lstCC@ProcessTabulator}
|
|
|
+\def\lstCC@Space#1{\lstCC@Let{#1}\lstCC@ProcessSpace}
|
|
|
% \end{macrocode}
|
|
|
% \end{macro}\end{macro}
|
|
|
%
|
|
|
-% \begin{macro}{\lst@ifcomment}
|
|
|
-% \begin{macro}{\lst@ifstring}
|
|
|
-% \begin{macro}{\lst@commentdepth}
|
|
|
-% Comments (not whole comment lines) and strings are indicated by
|
|
|
-% following booleans. The current comment depth uses a counter.
|
|
|
+% \begin{macro}{\lstCC@ChangeBasicClass}
|
|
|
+% Finally we define a macro (collection) with the ability of moving a basic \emph{instance} of class to another class, e.g. making the digit '0' be a letter.
|
|
|
+% The word 'basic' means any instance defined with |\lstCC@Use| or |\lstCC@ECUse|.
|
|
|
+% The first argument of |\lstCC@ChangeBasicClass| gives the new class and the second argument is a macro containing a character sequence.
|
|
|
+% These characters are changed.
|
|
|
+% First we make all these characters active and call a submacro.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstCC@ChangeBasicClass#1#2{%
|
|
|
+ \ifx\@empty#2\else %
|
|
|
+ \expandafter\lst@MakeActive\expandafter{#2}%
|
|
|
+ \expandafter\lstCC@CBC@\expandafter#1\lst@arg\@empty %
|
|
|
+ \fi}
|
|
|
+% \end{macrocode}
|
|
|
+% The submacro terminates (gobble two token after |\fi|) if it reaches |\@empty|.
|
|
|
+% Otherwise another submacro redfines the character.
|
|
|
+% Note that we expand the old meaning before calling the second submacro and that the second |\lstCC@CBC@@| is used as 'meaning' delimiter.
|
|
|
% \begin{macrocode}
|
|
|
-\newcount\lst@commentdepth
|
|
|
-\def\lst@commenttrue{\let\lst@ifcomment\iftrue}
|
|
|
-\def\lst@commentfalse{\let\lst@ifcomment\iffalse}
|
|
|
-\def\lst@stringtrue{\let\lst@ifstring\iftrue}
|
|
|
-\def\lst@stringfalse{\let\lst@ifstring\iffalse}
|
|
|
+\def\lstCC@CBC@#1#2{%
|
|
|
+ \ifx\@empty#2%
|
|
|
+ \expandafter\@gobbletwo %
|
|
|
+ \else %
|
|
|
+ \expandafter\lstCC@CBC@@#2\lstCC@CBC@@#1#2%
|
|
|
+ \fi %
|
|
|
+ \lstCC@CBC@#1}
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}\end{macro}\end{macro}
|
|
|
-%
|
|
|
-% \begin{macro}{\lst@width}
|
|
|
-% \begin{macro}{\lst@length}
|
|
|
-% \begin{macro}{\lst@pos}
|
|
|
-% The dimension \verb!\lst@width! holds the width of a single character
|
|
|
-% box and is set to \verb!\lst@baseem em!, when we output a listing.
|
|
|
-% The counter \verb!\lst@length! holds the length of the current
|
|
|
-% character string we want to output.
|
|
|
-% \verb!\lst@pos! holds the current column number to handle tabulators.
|
|
|
% \begin{macrocode}
|
|
|
-\newdimen\lst@width \newcount\lst@length \newcount\lst@pos
|
|
|
+\def\lstCC@CBC@@#1#2\lstCC@CBC@@#3#4{\def#4{#3#2}}
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}\end{macro}\end{macro}
|
|
|
+% \end{macro}
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%</kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+%
|
|
|
%
|
|
|
-% \begin{macro}{\lst@halfspread}
|
|
|
-% That's the half of spreadlisting's argument.
|
|
|
+% \subsection{Letters, digits and others}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%<*kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+% \begin{macro}{\lstCC@ProcessLetter}
|
|
|
+% To process a letter we look at the last character.
|
|
|
+% If it hasn't been a letter, we output the preceding other characters first and switch to letter mode.
|
|
|
+% Finally we append the current letter |#1|.
|
|
|
% \begin{macrocode}
|
|
|
-\newdimen\lst@halfspread
|
|
|
+\def\lstCC@ProcessLetter#1{%
|
|
|
+ \lstCC@ifletter\else \lst@OutputOther\lstCC@lettertrue \fi %
|
|
|
+ \lstCC@Append{#1}}
|
|
|
% \end{macrocode}
|
|
|
% \end{macro}
|
|
|
%
|
|
|
-% \begin{macro}{\lst@line} \begin{macro}{\lst@comment}
|
|
|
-% \begin{macro}{\lst@commentline}
|
|
|
-% Some variables need no allocation here, since they are macros, e.g.\
|
|
|
-% most user commands save their parameter within a macro. The most
|
|
|
-% important 'data' macros are \verb!\lst@line!, \verb!\lst@comment!
|
|
|
-% and \verb!\lst@commentline!. They hold the current line, comment and
|
|
|
-% comment line for line processing.
|
|
|
-% \end{macro}\end{macro}\end{macro}
|
|
|
+% \begin{macro}{\lstCC@ProcessOther}
|
|
|
+% 'Other' characters are the other way round.
|
|
|
+% If the last character has been a letter, the preceding letters are output and we switch to nonletter mode.
|
|
|
+% Finally we append the current other character.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstCC@ProcessOther#1{%
|
|
|
+ \lstCC@ifletter \lst@Output\lstCC@letterfalse \fi %
|
|
|
+ \lstCC@AppendOther{#1}}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
%
|
|
|
-% \begin{macro}{\lst@other}
|
|
|
-% This version gather non-alphanumeric characters before their output.
|
|
|
-% Since these characters might expand, we need a token register to
|
|
|
-% gather them, where they surely do not expand.
|
|
|
+% \begin{macro}{\lstCC@ProcessDigit}
|
|
|
+% A digit simply appends the character to the current character string.
|
|
|
+% But we must use the right macro.
|
|
|
+% This allow digits to be part of an identifier or a numerical constant.
|
|
|
% \begin{macrocode}
|
|
|
-\newtoks\lst@other
|
|
|
+\def\lstCC@ProcessDigit#1{%
|
|
|
+ \lstCC@ifletter \lstCC@Append{#1}\else \lstCC@AppendOther{#1}\fi}
|
|
|
% \end{macrocode}
|
|
|
% \end{macro}
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%</kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
%
|
|
|
%
|
|
|
-% \subsection{Comments}\label{ssComments}
|
|
|
+% \subsection{Tabulators and spaces}
|
|
|
%
|
|
|
-% First we discuss comment lines (CL). Let's say, we have a C++ source
|
|
|
-% line with a comment, which is separated by '//'. To cut the line into
|
|
|
-% code and comment we use a macro like this:
|
|
|
-% \DescribeMacro\lst@CutCL
|
|
|
-% \begin{verbatim}
|
|
|
-% \def\lst@CutCL#1//#2\relax{%
|
|
|
-% \def\lst@line{#1}\def\lst@commentline{//#2}}\end{verbatim}
|
|
|
-% The parameter definition ensures that the first parameter holds the
|
|
|
-% code and our second paramater the comment upto a \cs{relax}, which
|
|
|
-% marks the end of the source. We (re)define the input and comment line,
|
|
|
-% where we must add the separator '//' again. That's easy.
|
|
|
-% \DescribeMacro\lst@CommentLine
|
|
|
-% But if we call this macro using a line without any '//', \TeX{}
|
|
|
-% detects a syntax error, since the line doesn't meet the definition.
|
|
|
-% Hence, we can't use the cut macro to look for a comment line,
|
|
|
-% but this:
|
|
|
-% \begin{verbatim}
|
|
|
-% \def\lst@CommentLine{%
|
|
|
-% \expandafter\lst@TestCL\lst@line//\relax}\end{verbatim}
|
|
|
-% Additional '//' and '\cs{relax}' hold up the syntax of the cut macro.
|
|
|
-% That's the point. We use an \cs{expandafter}, because we need the
|
|
|
-% \emph{content} of \verb!\lst@line! and not the macro token itself as
|
|
|
-% parameter. So the test macro is called (or expanded) after the
|
|
|
-% content is written behind.
|
|
|
-%
|
|
|
-% \DescribeMacro\lst@TestCL
|
|
|
-% Why we don't use the cut macro here? Our additional '//' would be
|
|
|
-% added to the comment! Therefore:
|
|
|
-% \begin{verbatim}
|
|
|
-% \def\lst@TestCL#1//#2\relax{%
|
|
|
-% \ifx\empty#2\empty %
|
|
|
-% \let\lst@commentline\empty %
|
|
|
-% \else %
|
|
|
-% \expandafter\lst@CutCL\lst@line\relax %
|
|
|
-% \fi}\end{verbatim}
|
|
|
-% If you compare the definition of \verb!\lst@TestCL! here and the
|
|
|
-% call above, you will see: The second parameter is empty, if and only
|
|
|
-% if there is no comment (no double slash). So we are able to call
|
|
|
-% the cut macro without additional '//' if we've found a comment.
|
|
|
-%
|
|
|
-% \begin{macro}{\DeclareCommentLine}
|
|
|
-% \begin{macro}{\lst@CommentLine}
|
|
|
-% \begin{macro}{\lst@TestCL}
|
|
|
-% \begin{macro}{\lst@CutCL}
|
|
|
-% Now comes the real implementation. It's different from the C++
|
|
|
-% example, but it only seems to. The one and only parameter of
|
|
|
-% \cs{DeclareCommentLine} is the comment line separator.
|
|
|
-% First we test, if comment lines are desired. If not we let the main
|
|
|
-% macro be empty. Otherwise we define three macros similar to the
|
|
|
-% example. But: To distinguish their parameters from the comment line
|
|
|
-% separator $\#1$, we have to double the '$\#$': The $n$th parameter
|
|
|
-% of a macro within a macro is $\#\#n$. If you know this, following
|
|
|
-% is clear: It's the same as the simplified example.
|
|
|
+% \begingroup
|
|
|
% \begin{macrocode}
|
|
|
-\def\DeclareCommentLine#1\relax{%
|
|
|
- \ifx\@empty#1\@empty \let\lst@CommentLine\@empty %
|
|
|
- \else
|
|
|
- \def\lst@CommentLine{\expandafter\lst@TestCL\lst@line#1\relax}%
|
|
|
- \def\lst@TestCL##1#1##2\relax{%
|
|
|
- \ifx\@empty##2\@empty \let\lst@commentline\@empty %
|
|
|
- \else \expandafter\lst@CutCL\lst@line\relax %
|
|
|
- \fi}%
|
|
|
- \def\lst@CutCL##1#1##2\relax{%
|
|
|
- \def\lst@line{##1}\def\lst@commentline{#1##2}}%
|
|
|
- \fi}
|
|
|
+%<*kernel>
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}\end{macro}\end{macro}\end{macro}
|
|
|
-%
|
|
|
-% \begin{macro}{\lst@DefineSingleComment}
|
|
|
-% \begin{macro}{\lst@SOC}
|
|
|
-% \begin{macro}{\lst@EOC}
|
|
|
-% For single comments we use the same cut mechanism as above, except
|
|
|
-% that we use it for the start of comment (SOC) and for the end of
|
|
|
-% comment (EOC): We define six macros here. Additional the comment
|
|
|
-% boolean is switched by the cut macros. The last two parameters of
|
|
|
-% \verb!lst@DefineSingleComment! are the character sequences for the
|
|
|
-% beginning and ending of a single comment, of course. The first
|
|
|
-% parameter is used as suffix for the macro names.
|
|
|
-% \begin{macrocode}
|
|
|
-\def\lst@DefineSingleComment[#1]#2 #3\relax{%
|
|
|
- \ifx\@empty#3\@empty %
|
|
|
- \expandafter\let\csname lst@SOC#1\endcsname\relax %
|
|
|
- \expandafter\let\csname lst@EOC#1\endcsname\relax %
|
|
|
- \else %
|
|
|
- \expandafter\def\csname lst@SOC#1\endcsname{\expandafter %
|
|
|
- \expandafter\csname lst@TestSOC#1\endcsname \lst@line#2\relax}%
|
|
|
- \expandafter\def\csname lst@TestSOC#1\endcsname##1#2##2\relax{%
|
|
|
- \ifx\@empty##2\@empty\else \expandafter %
|
|
|
- \expandafter\csname lst@CutSOC#1\endcsname \lst@line\relax %
|
|
|
- \fi}%
|
|
|
- \expandafter\def\csname lst@CutSOC#1\endcsname##1#2##2\relax{%
|
|
|
- \lst@commenttrue \def\lst@line{##1}\def\lst@comment{#2##2}}%
|
|
|
- \expandafter\def\csname lst@EOC#1\endcsname{\expandafter %
|
|
|
- \expandafter\csname lst@TestEOC#1\endcsname \lst@line#3\relax}%
|
|
|
-% \end{macrocode}
|
|
|
-% \begin{macrocode}
|
|
|
- \expandafter\def\csname lst@TestEOC#1\endcsname ##1#3##2\relax{%
|
|
|
- \ifx\@empty##2\@empty %
|
|
|
-% \end{macrocode}
|
|
|
-% Here we are in the situation that we look for the end of comment but
|
|
|
-% haven't found one. Since we are in comment mode, the whole line is
|
|
|
-% the comment and the line gets empty.
|
|
|
-% \begin{macrocode}
|
|
|
- \let\lst@comment\lst@line \let\lst@line\@empty %
|
|
|
- \else \expandafter %
|
|
|
- \expandafter\csname lst@CutEOC#1\endcsname\lst@line\relax%
|
|
|
- \fi}%
|
|
|
- \expandafter\def\csname lst@CutEOC#1\endcsname##1#3##2\relax{%
|
|
|
- \lst@commentfalse \def\lst@line{##2}\def\lst@comment{##1#3}}%
|
|
|
- \fi}
|
|
|
+% \endgroup
|
|
|
+% Here we have to take care of two things:
|
|
|
+% First dropping empty lines at the end of a listing, and second the flexible column format.
|
|
|
+% In both cases we use |\lst@lostspace| for the implementation.
|
|
|
+% Whenever this dimension is positive we insert that space before |\lst@token| is output.
|
|
|
+%
|
|
|
+% We've defined |\lst@EOLUpdate| to drop empty lines at the end of a listing.
|
|
|
+% |\lst@NewLine| isn't executed or reset in that case.
|
|
|
+% Instead we append control sequences.
|
|
|
+% But: Lines containing tabulators and spaces only should also be viewed as empty.
|
|
|
+% In order to achieve this tabulators and spaces at the beginning of a line advance |\lst@lostspace| and don't output any characters.
|
|
|
+% The space is inserted if there comes a letter for example.
|
|
|
+% If there are only tabulators and spaces, the line is 'empty' since we haven't done any output.
|
|
|
+%
|
|
|
+% We have to do more for flexible columns.
|
|
|
+% The whitespaces can fix the column alignment:
|
|
|
+% If the real line is wider than it should be (|\lst@lostspace|$<$0pt), a tabulator is at least one space wide; all the other width is used to make |\lst@lostspace| more positive.
|
|
|
+% Spaces do the same: If there are two or more spaces, at least one space is printed; the others fix the column alignment.
|
|
|
+% If we process a string, all spaces are output, of course.
|
|
|
+%
|
|
|
+% \begin{macro}{\lstCC@ProcessTabulator}
|
|
|
+% A tabulator outputs the preceding characters.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstCC@ProcessTabulator{%
|
|
|
+ \lst@PrintToken %
|
|
|
+% \end{macrocode}
|
|
|
+% Then we must calculate how many columns we need to reach the next tabulator stop.
|
|
|
+% Each printed character decrements the counter |\lst@pos|.
|
|
|
+% Hence we can simply add |\lst@tabsize| until |\lst@pos| is strict positive.
|
|
|
+% That's all.
|
|
|
+% We assign it to |\lst@length|, reset |\lst@pos| \ldots
|
|
|
+% \begin{macrocode}
|
|
|
+ \global\advance\lst@column -\lst@pos %
|
|
|
+ \@whilenum \lst@pos<\@ne \do %
|
|
|
+ {\global\advance\lst@pos\lst@tabsize}%
|
|
|
+ \lst@length\lst@pos \global\lst@pos\z@ %}
|
|
|
+% \end{macrocode}
|
|
|
+% and go to the tabulator stop, e.g.\ |\lst@length| columns forward:
|
|
|
+% \begin{macrocode}
|
|
|
+ \lst@GotoTabStop}
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}\end{macro}\end{macro}
|
|
|
+% \end{macro}
|
|
|
%
|
|
|
-% \begin{macro}{\DeclareSingleComment}
|
|
|
-% That's an abbreviation of the macro just defined, but where the
|
|
|
-% suffix-parameter is empty.
|
|
|
-% \begin{macrocode}
|
|
|
-\def\DeclareSingleComment{\lst@DefineSingleComment[]}
|
|
|
+% \begin{macro}{\lstCC@AppendSpecialSpace}
|
|
|
+% Sometimes we have special spaces:
|
|
|
+% If there are at least two spaces, i.e.\ if the last character have been a space, we output preceding characters and advance |\lst@lostspace| to avoid alignment problems.
|
|
|
+% Otherwise we append a space to the current character string.
|
|
|
+% We'll need that macro soon.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstCC@AppendSpecialSpace{%
|
|
|
+ \ifx\lst@lastother\lst@outputblank %
|
|
|
+ \lst@OutputOther %
|
|
|
+ \global\advance\lst@lostspace\lst@width %
|
|
|
+ \global\advance\lst@pos\m@ne %
|
|
|
+ \else %
|
|
|
+ \lstCC@AppendOther\lst@outputblank %
|
|
|
+ \fi}
|
|
|
% \end{macrocode}
|
|
|
% \end{macro}
|
|
|
%
|
|
|
-% \begin{macro}{\DeclarePairedComment}
|
|
|
-% First we define a single comment. Then we adjust one cut macro:
|
|
|
-% The SOC delimiter is defined to belong to the line and not to the
|
|
|
-% comment.
|
|
|
+% \begin{macro}{\lst@outputblank}
|
|
|
+% It's better not to forget this.
|
|
|
% \begin{macrocode}
|
|
|
-\def\DeclarePairedComment#1\relax{%
|
|
|
- \lst@DefineSingleComment[]#1 #1\relax %
|
|
|
- \def\lst@CutSOC##1#1##2\relax{%
|
|
|
- \lst@commenttrue \def\lst@line{##1#1}\def\lst@comment{##2}}}%
|
|
|
+\def\lst@outputblank{\ }
|
|
|
% \end{macrocode}
|
|
|
% \end{macro}
|
|
|
%
|
|
|
-% \begin{macro}{\DeclareDoubleComment}
|
|
|
-% We define a single comment and another one with slightly different
|
|
|
-% names (additional \verb!@!). Then we compose the two single comments.
|
|
|
+% \begin{macro}{\lstCC@ProcessSpace}
|
|
|
+% If the last character has been a letter, we output the current character string and append one space.
|
|
|
% \begin{macrocode}
|
|
|
-\def\DeclareDoubleComment#1 #2 #3 #4\relax{%
|
|
|
- \lst@DefineSingleComment[]#1 #2\relax %
|
|
|
- \lst@DefineSingleComment[@]#3 #4\relax %
|
|
|
- \lst@HookComment#1 #3 \lst@TestSOC@\lst@EOC@\lst@SavedEOC}%
|
|
|
-% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
-%
|
|
|
-% \begin{macro}{\lst@HookComment}
|
|
|
-% The purpose of this macro is to compose a SOC/EOC pair already
|
|
|
-% defined with another SOC/EOC pair, which need not to be defined yet.
|
|
|
-% The job is to coincide start and end of comment: We have to look
|
|
|
-% whether the first, the second or none comment starts, and must
|
|
|
-% select the right macro to find the corresponding end of comment.
|
|
|
-% The first and second parameter are the SOC delimiters of the first
|
|
|
-% (defined) and second SOC/EOC pair, respectively. Therefor they are
|
|
|
-% separated by blank spaces. The third and fourth parameters are the
|
|
|
-% \verb!TestSOC! and \verb!EOC! macros of the second SOC/EOC pair.
|
|
|
-% Parameter five is a macro name used to save a EOC macro. That's done
|
|
|
-% in the second line:
|
|
|
-% \begin{macrocode}
|
|
|
-\def\lst@HookComment#1 #2 #3#4#5{%
|
|
|
- \let#5\lst@EOC %
|
|
|
- \def\lst@TestSOC##1#1##2\relax{%
|
|
|
-% \end{macrocode}
|
|
|
-% Now $\#\#1$ holds the code of the line and $\#\#2$ (possibly) the
|
|
|
-% comment. But we have to look whether the other comment type starts
|
|
|
-% before this here or not. So we call the test macro of the other
|
|
|
-% comment first. If we've found one, we let \verb!\lst@EOC! be the
|
|
|
-% macro, which looks for the end of that comment.
|
|
|
-% \begin{macrocode}
|
|
|
- #3##1#2\relax %
|
|
|
- \lst@ifcomment \let\lst@EOC#4%
|
|
|
-% \end{macrocode}
|
|
|
-% Otherwise we do the test for this comment. If there is a comment,
|
|
|
-% we cut up the line and let \verb!\lst@EOC! be the macro, which
|
|
|
-% looks for the end of this comment.
|
|
|
+\def\lstCC@ProcessSpace{%
|
|
|
+ \lstCC@ifletter %
|
|
|
+ \lst@Output\lstCC@letterfalse %
|
|
|
+ \lstCC@AppendOther\lst@outputblank %
|
|
|
+% \end{macrocode}
|
|
|
+% Otherwise we look whether we are in string mode or not.
|
|
|
+% In the first case we must append a space; in the second case we must test if the hitherto line is empty.
|
|
|
% \begin{macrocode}
|
|
|
- \else %
|
|
|
- \ifx\@empty##2\@empty \else %
|
|
|
- \expandafter\lst@CutSOC\lst@line\relax %
|
|
|
- \let\lst@EOC#5%
|
|
|
- \fi %
|
|
|
- \fi}}
|
|
|
+ \else \ifnum\lst@mode=\lst@stringmode %
|
|
|
+ \lstCC@AppendOther\lst@outputblank %
|
|
|
+ \else \ifx\lst@NewLine\relax %
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
-%
|
|
|
-% \begin{macro}{\DeclareNestedComment}
|
|
|
-% For nested comments we do it the same way: We declare a single
|
|
|
-% comment and adjust some macros. Testing for an end of comment is
|
|
|
-% nearly the same as for single comments.
|
|
|
+% If the line is not empty we either advance |\lst@lostspace| or append a space to the current character string.
|
|
|
% \begin{macrocode}
|
|
|
-\def\DeclareNestedComment#1 #2\relax{%
|
|
|
- \lst@DefineSingleComment[]#1 #2\relax %
|
|
|
- \def\lst@TestEOC##1#2##2\relax{%
|
|
|
+ \lstCC@AppendSpecialSpace %
|
|
|
+ \else \ifnum\lst@length=\z@ %
|
|
|
% \end{macrocode}
|
|
|
-% The only difference is that we have to count how many (new) comments
|
|
|
-% start in the comment. And this is done here, the rest is the same as
|
|
|
-% above.
|
|
|
+% If the line is empty so far, we advance |\lst@lostspace|.
|
|
|
+% Otherwise we append the space.
|
|
|
% \begin{macrocode}
|
|
|
- \lst@CountSOC##1#1\relax %
|
|
|
- \ifx\@empty##2\@empty %
|
|
|
- \let\lst@comment\lst@line \let\lst@line\@empty %
|
|
|
+ \global\advance\lst@lostspace\lst@width %
|
|
|
+ \global\advance\lst@pos\m@ne %
|
|
|
\else %
|
|
|
- \expandafter\lst@CutEOC\lst@line\relax %
|
|
|
- \fi}%
|
|
|
+ \lstCC@AppendSpecialSpace %
|
|
|
+ \fi %
|
|
|
+ \fi \fi \fi}
|
|
|
% \end{macrocode}
|
|
|
-% An end of comment lets the comment depth decrease. If we reach 0,
|
|
|
-% we set the comment boolean false. That's not new, since this happens
|
|
|
-% always with not nested comments.
|
|
|
+% Note that this version works for fixed and flexible column output.
|
|
|
+% \end{macro}
|
|
|
+% \begingroup
|
|
|
% \begin{macrocode}
|
|
|
- \def\lst@CutEOC##1#2##2\relax{%
|
|
|
- \advance\lst@commentdepth by -1\relax %
|
|
|
- \ifnum 0=\lst@commentdepth \lst@commentfalse\fi %
|
|
|
- \def\lst@line{##2}\def\lst@comment{##1#2}}%
|
|
|
+%</kernel>
|
|
|
% \end{macrocode}
|
|
|
-% Now we have to do something for increasing the comment depth. We
|
|
|
-% count how many new comments start within a comment. To move through
|
|
|
-% a comment we use the same separation mechanism as all the time. The
|
|
|
-% second parameter is empty, if and only if there is no (more) start
|
|
|
-% of comment. While it is not empty we increase the comment depth and
|
|
|
-% call this macro again with the current rest of the comment.
|
|
|
+% \endgroup
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Stringizer}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
% \begin{macrocode}
|
|
|
- \def\lst@CountSOC##1#1##2\relax{%
|
|
|
- \ifx\@empty##2\@empty\else %
|
|
|
- \advance\lst@commentdepth by 1%
|
|
|
- \def\@tempa{\lst@CountSOC##2\relax}%
|
|
|
+%<*kernel>
|
|
|
% \end{macrocode}
|
|
|
-% Note: \verb!\@tempa! is executed after the closing \verb!\fi! to call
|
|
|
-% the macro again.
|
|
|
+% \endgroup
|
|
|
+% \begin{macro}{\lst@legalstringizer}
|
|
|
+% Currently there are three different stringizer types: 'd'oubled, 'b'ackslashed and 'm'atlabed.
|
|
|
+% The naming of the first two is due to how the stringizer is represented in a string.
|
|
|
+% Pascal doubles it, i.e.\ the string |'| is represented by four single quotes |''''|, where the first and last enclose the string and the two middle quotes represent the desired stringizer.
|
|
|
+% In C++ we would write |"\""|: A backslash indicates that the next double quote belongs to the string and is not the end of string.
|
|
|
+% The matlabed version is described below.
|
|
|
+% I introduced it after communication with \lsthelper{Zvezdan V. Petkovic}{[email protected]}{1997/11/26}{'single stringizer' not a stringizer in Ada (and Matlab)}.
|
|
|
% \begin{macrocode}
|
|
|
- \expandafter\@tempa %
|
|
|
- \fi}}
|
|
|
+\def\lst@legalstringizer{d,b,m,bd,db}
|
|
|
% \end{macrocode}
|
|
|
+% Furthermore we have the two mixed types |bd| and |db|, which in fact equal |b|.
|
|
|
% \end{macro}
|
|
|
%
|
|
|
-% \begin{macro}{\DeclareCLPercent}
|
|
|
-% This command is equivalent to \verb!\DeclareCommentLine %\relax!,
|
|
|
-% where the percent has the catcode we need when we input a listing.
|
|
|
+% \begin{aspect}{stringizer}
|
|
|
+% Here we test whether the user type is supported or not (leading to an error message).
|
|
|
+% In the first case we (re-) define |\lst@DefStrings|.
|
|
|
% \begin{macrocode}
|
|
|
-{\catcode`\%=12 \gdef\DeclareCLPercent{\DeclareCommentLine %\relax}}
|
|
|
+\lst@Aspect{stringizer}{\lstKV@OptArg\lststringizer@[d]{#1}}
|
|
|
+\def\lststringizer@[#1]#2%
|
|
|
+ {\lst@IfOneOf#1\relax \lst@legalstringizer %
|
|
|
+ {\def\lst@DefStrings{\lstCC@Stringizer[#1]#2\@empty}}%
|
|
|
+ {\PackageError{Listings}{Illegal stringizer type `#1'}%
|
|
|
+ {Available types are \lst@legalstringizers.}}}
|
|
|
+\lst@AddToHook{SetLanguage}{\let\lst@DefStrings\@empty}
|
|
|
+\lst@AddToHook{SelectCharTable}{\lst@DefStrings}
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
+% The just added hook defines the strings after selecting the standard character table.
|
|
|
+% This adjusts the character table to the user's demands.
|
|
|
+% \end{aspect}
|
|
|
%
|
|
|
-% \begin{macro}{\DeclareDoubleCommentPascal}
|
|
|
-% Dito for Pascal comments.
|
|
|
+% \begin{macro}{\lstCC@Stringizer}
|
|
|
+% This macro is similar to |\lstCC@ECUse|, but we build the 'use'd name before defining the characters \ldots
|
|
|
% \begin{macrocode}
|
|
|
-\begingroup \catcode`\[=1 \catcode`\]=2
|
|
|
-\catcode`\{=\active \catcode`\}=\active \catcode`\*=\active
|
|
|
-\gdef\DeclareDoubleCommentPascal[\DeclareDoubleComment (* *) { }\relax]
|
|
|
-\endgroup
|
|
|
+\def\lstCC@Stringizer[#1]{%
|
|
|
+ \expandafter\lstCC@Stringizer@ %
|
|
|
+ \csname lstCC@ProcessStringizer@#1\endcsname}
|
|
|
+\def\lstCC@Stringizer@#1#2{%
|
|
|
+ \ifx\@empty#2%
|
|
|
+ \expandafter\@gobbletwo %
|
|
|
+% \end{macrocode}
|
|
|
+% which is terminated by |\@empty|.
|
|
|
+% Otherwise we save the old meaning in |\lsts@s|\meta{the character} (with catcode 12) and redefine it.
|
|
|
+% \begin{macrocode}
|
|
|
+ \else %
|
|
|
+ \catcode`#2=\active \lccode`\~=`#2\lccode`\/=`#2%
|
|
|
+ \lowercase{%
|
|
|
+ \expandafter\let\csname lsts@s/\endcsname~%
|
|
|
+ \def~{#1/}}%
|
|
|
+ \fi %
|
|
|
+ \lstCC@Stringizer@#1}
|
|
|
% \end{macrocode}
|
|
|
+% And now we define all 'process stringizer' macros.
|
|
|
% \end{macro}
|
|
|
%
|
|
|
-%
|
|
|
-% \subsection{Keywords}\label{ssKeywords}
|
|
|
-%
|
|
|
-% \begin{macro}{\lst@CaseSensitiveKeywords}
|
|
|
-% We have to decide whether a given character sequence is a reserved
|
|
|
-% word or not. Doing this test is very familiar with the cut mechanism
|
|
|
-% for comments. To test, if \verb!key! is a keyword, we define a macro
|
|
|
-% \begin{verbatim}
|
|
|
-% \def\lst@test#1,key,#2\relax{...}\end{verbatim}
|
|
|
-% Afterwards we call the macro with the parameters
|
|
|
-% \begin{center}\begin{tabular}{l@{}l}
|
|
|
-% all current keywords&\verb!,key,\relax!
|
|
|
-% \end{tabular}\end{center}
|
|
|
-% When \TeX{} passes the arguments, the second parameter is empty,
|
|
|
-% if and only if \verb!key! is not a current keyword. So we are able to
|
|
|
-% decide whether to make a normal box, or a box with keywordstyle.
|
|
|
+% \begin{macro}{\lstCC@ProcessStringizer@d}
|
|
|
+% 'd' means no extra work.
|
|
|
+% Reaching the (first) stringizer enters string mode and coming to the next leaves it, and so on.
|
|
|
+% Then the character sequence |''''| produces the right output:
|
|
|
+% The second quote leaves string mode, but we enter it immediately since the stringizer is doubled.
|
|
|
+% And now the implementation.
|
|
|
+% First we output any preceding letters.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstCC@ProcessStringizer@d#1{%
|
|
|
+ \lstCC@ifletter \lst@Output\lstCC@letterfalse \fi %
|
|
|
+% \end{macrocode}
|
|
|
+% If we already process a string, we execute the saved meaning and look whether the last other (that's the stringizer) is the matching stringizer --- a single quote must not end a string starting with a double quote.
|
|
|
+% The macro |\lstCC@EndString| is defined at the end of this section.
|
|
|
% \begin{macrocode}
|
|
|
-\def\lst@CaseSensitiveKeywords#1\relax{%
|
|
|
- \def\lst@test##1,#1,##2\relax{%
|
|
|
- \ifx \@empty##2\@empty \lst@MakeBox{}%
|
|
|
- \else \lst@MakeBox{\lst@keywordstyle}%
|
|
|
- \fi}%
|
|
|
+ \ifnum\lst@mode=\lst@stringmode %
|
|
|
+ \csname lsts@s#1\endcsname %
|
|
|
+ \ifx\lst@lastother\lstCC@closestring %
|
|
|
+ \lstCC@EndString %
|
|
|
+ \fi %
|
|
|
+ \else %
|
|
|
+ \lst@OutputOther %
|
|
|
% \end{macrocode}
|
|
|
-% We only need to call the macro defined right before. \verb!,#1,\relax!
|
|
|
-% holds up the syntax of the macro.
|
|
|
+% If we don't process a string, we test whether or not a string is allowed.
|
|
|
+% |\lstCC@BeginString| enters string mode and defines the closing stringizer.
|
|
|
+% This 'begin string' macro gets one argument, hence we expand the control sequence name before executing the macro (if necessary).
|
|
|
% \begin{macrocode}
|
|
|
- \expandafter\lst@test\lst@keywords,#1,\relax}%
|
|
|
+ \lst@ifmode\else %
|
|
|
+ \expandafter\expandafter\expandafter\lstCC@BeginString %
|
|
|
+ \fi %
|
|
|
+ \csname lsts@s#1\endcsname %
|
|
|
+ \fi}
|
|
|
% \end{macrocode}
|
|
|
-% Since \TeX{} always passes two arguments to the test macro, \TeX{}
|
|
|
-% splits the whole 'input' \verb!\lst@keywords,#1,\relax! in two parts.
|
|
|
-% So there is no need to sort the keywords by probability.\footnote{If
|
|
|
-% you sort the keywords by probability and make a loop for the keyword
|
|
|
-% tests, which terminates right after finding a keyword, you might think
|
|
|
-% that's faster than the \TeX{}nique used here. Well, if your source
|
|
|
-% code uses the three or four most common keywords only, you are right.
|
|
|
-% Most cases it will be slow. In fact the versions 0.1 and 0.11 have
|
|
|
-% used something like loops, even something faster, but which is much
|
|
|
-% slower than this here.}
|
|
|
% \end{macro}
|
|
|
%
|
|
|
-% \begin{macro}{\lst@NonCaseSensitiveKeywords}
|
|
|
-% Now we implement the test for keywords, which are not case sensitive.
|
|
|
-% We use two \cs{uppercase} to normalize the test string and the keywords.
|
|
|
-% For the keywords we need some expandafters, so that the keywords are
|
|
|
-% expanded before making the characters upper case.
|
|
|
-% \begin{macrocode}
|
|
|
-\def\lst@NonCaseSensitiveKeywords#1\relax{%
|
|
|
- \uppercase{\def\lst@test##1,#1,##2\relax{%
|
|
|
- \ifx \@empty##2\@empty \lst@MakeBox{}%
|
|
|
- \else \lst@MakeBox{\lst@keywordstyle}%
|
|
|
- \fi}}%
|
|
|
- \expandafter\uppercase\expandafter{%
|
|
|
- \expandafter\lst@test\lst@keywords,#1,\relax}}%
|
|
|
+% \begin{macro}{\lstCC@ProcessStringizer@b}
|
|
|
+% 'b' means an extra if: Only if the last other is not a backslash (5-th line) the stringizer can close the string.
|
|
|
+% The rest is the same as above.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstCC@ProcessStringizer@b#1{%
|
|
|
+ \lstCC@ifletter \lst@Output\lstCC@letterfalse \fi %
|
|
|
+ \ifnum\lst@mode=\lst@stringmode %
|
|
|
+ \let\lst@temp\lst@lastother \csname lsts@s#1\endcsname %
|
|
|
+ \ifx\lst@temp\lst@backslash\else %!def of "005C
|
|
|
+ \ifx\lst@lastother\lstCC@closestring %
|
|
|
+ \lstCC@EndString %
|
|
|
+ \fi \fi %
|
|
|
+ \else %
|
|
|
+ \lst@OutputOther %
|
|
|
+ \lst@ifmode\else %
|
|
|
+ \expandafter\expandafter\expandafter\lstCC@BeginString %
|
|
|
+ \fi %
|
|
|
+ \csname lsts@s#1\endcsname %
|
|
|
+ \fi}
|
|
|
% \end{macrocode}
|
|
|
% \end{macro}
|
|
|
%
|
|
|
-% \begin{macro}{\lst@IfOneOf}
|
|
|
-% \begin{macro}{\lst@ifoneof}
|
|
|
-% We define two macros, which are very familiar with the keyword tests.
|
|
|
-% The first macro is a case sensitive version of the second one. The
|
|
|
-% first parameter is terminated by \cs{relax}, the other three are not.
|
|
|
-% If the first parameter is found in the second parameter (a keyword
|
|
|
-% list) the third parameter is executed. Otherwise we perform the forth.
|
|
|
-% The implementation is clear.
|
|
|
+% \begin{macro}{\lstCC@ProcessStringizer@bd}
|
|
|
+% \begin{macro}{\lstCC@ProcessStringizer@db}
|
|
|
+% are just the same and the same as |\lstCC@ProcessStringizer@b|:
|
|
|
% \begin{macrocode}
|
|
|
-\def\lst@IfOneOf#1\relax#2{%
|
|
|
- \def\lst@test##1,#1,##2\relax{%
|
|
|
- \ifx \@empty##2\@empty \expandafter\@secondoftwo %
|
|
|
- \else \expandafter\@firstoftwo %
|
|
|
- \fi}%
|
|
|
- \lst@test,#2,#1,\relax}%
|
|
|
-\def\lst@ifoneof#1\relax#2{%
|
|
|
- \uppercase{\def\lst@test##1,#1,##2\relax{%
|
|
|
- \ifx \@empty##2\@empty \expandafter\@secondoftwo %
|
|
|
- \else \expandafter\@firstoftwo %
|
|
|
- \fi}}%
|
|
|
- \uppercase{\lst@test,#2,#1,\relax}}%
|
|
|
+\let\lstCC@ProcessStringizer@bd\lstCC@ProcessStringizer@b
|
|
|
+\let\lstCC@ProcessStringizer@db\lstCC@ProcessStringizer@bd
|
|
|
% \end{macrocode}
|
|
|
% \end{macro}\end{macro}
|
|
|
%
|
|
|
-%
|
|
|
-% \subsection{Commands}\label{ssCommands}
|
|
|
-% \begin{macro}{\selectlisting}
|
|
|
-% This command loads the specified driver file and selects the language.
|
|
|
-% We give an error message, if the driver file doesn't support the
|
|
|
-% necessary macro.
|
|
|
+% \begin{macro}{\lstCC@ProcessStringizer@m}
|
|
|
+% 'm'atlabed is designed for programming languages where stringizers (for character or string literals) are also used for other purposes, like Matlab or Ada.
|
|
|
+% Here we enter string mode only if the last character has not been a letter and has not been a right parenthesis.
|
|
|
+% Hence, we have to move the |\lstCC@ifletter| and change the main |\else| part.
|
|
|
+% By the way: The stringizer is doubled in a string.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstCC@ProcessStringizer@m#1{%
|
|
|
+ \ifnum\lst@mode=\lst@stringmode %
|
|
|
+ \lstCC@ifletter \lst@Output\lstCC@letterfalse \fi %
|
|
|
+ \csname lsts@s#1\endcsname %
|
|
|
+ \ifx\lst@lastother\lstCC@closestring %
|
|
|
+ \lstCC@EndString %
|
|
|
+ \fi %
|
|
|
+ \else %
|
|
|
+% \end{macrocode}
|
|
|
+% And now the real 'm' changes:
|
|
|
% \begin{macrocode}
|
|
|
-\newcommand\selectlisting[2][]{%
|
|
|
- \@ifundefined{lstdrv@#2@}{\input{lst#2.sty}}{}%
|
|
|
- \@ifundefined{lstdrv@#2@}{%
|
|
|
- \PackageError{Listings}{Driver file for `#2' corrupt}{%
|
|
|
- The driver file doesn't define \string\lstdrv@#2@.}}{%
|
|
|
- \@ifundefined{lstdrv@#2@#1}{%
|
|
|
- \PackageError{Listings}{Option `#1' not supported}{%
|
|
|
- The driver file doesn't define \string\lstdrv@#2@#1.}}{%
|
|
|
- \csname lstdrv@#2@#1\endcsname \def\lst@curr{#2}\def\lst@opt{#1}}}}
|
|
|
+ \lstCC@ifletter %
|
|
|
+ \lst@Output\lstCC@letterfalse %
|
|
|
+ \else %
|
|
|
+ \lst@OutputOther %
|
|
|
+ \let\lstCC@next\relax %
|
|
|
+ \ifx\lst@lastother)\else \lst@ifmode\else %
|
|
|
+ \let\lstCC@next\lstCC@BeginString %
|
|
|
+ \fi \fi %
|
|
|
+ \expandafter\expandafter\expandafter\lstCC@next %
|
|
|
+ \fi %
|
|
|
+ \csname lsts@s#1\endcsname %
|
|
|
+ \fi}
|
|
|
% \end{macrocode}
|
|
|
% \end{macro}
|
|
|
%
|
|
|
-% \begin{macro}{\lst@ifselect}
|
|
|
-% \begin{macro}{\lst@ifoption}
|
|
|
-% These two private macros are similar to \LaTeXe{}'s \verb!\@ifundefined!,
|
|
|
-% except that the selected language and option are tested, of course.
|
|
|
+% \begin{aspect}{stringstyle}
|
|
|
+% \begin{aspect}{blankstring}
|
|
|
+% We insert some easy definitions.
|
|
|
% \begin{macrocode}
|
|
|
-\def\lst@ifselect#1{\def\lst@test{#1}%
|
|
|
- \ifx\lst@curr\lst@test \expandafter\@firstoftwo %
|
|
|
- \else \expandafter\@secondoftwo \fi}
|
|
|
-\def\lst@ifoption#1{\def\lst@test{#1}%
|
|
|
- \ifx\lst@opt\lst@test \expandafter\@firstoftwo %
|
|
|
- \else \expandafter\@secondoftwo \fi}
|
|
|
+\lst@Aspect{stringstyle}{\def\lst@stringstyle{#1}}
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}\end{macro}
|
|
|
-%
|
|
|
-% \begin{macro}{\keywordstyle}
|
|
|
-% \begin{macro}{\commentstyle}
|
|
|
-% \begin{macro}{\stringstyle}
|
|
|
-% \begin{macro}{\labelstyle}
|
|
|
-% The following user commands save the parameter in (private) macros.
|
|
|
-% The labelstyle command checks for a legal step count for labels.
|
|
|
-% \begin{macrocode}
|
|
|
-\newcommand\keywordstyle[1]{\def\lst@keywordstyle{#1}}
|
|
|
-\newcommand\commentstyle[1]{\def\lst@commentstyle{#1}}
|
|
|
-\newcommand\stringstyle[1]{\def\lst@stringstyle{#1}}
|
|
|
-\newcommand\labelstyle[2][1]{\def\lst@labelstyle{#2}%
|
|
|
- \ifnum #1>-1 \def\lst@labelstep{#1}\else %
|
|
|
- \PackageError{Listings}{Nonnegative integer expected}{%
|
|
|
- You can't use `#1' as step count for labels.^^J%
|
|
|
- I'll forget it and proceed.}\fi}
|
|
|
+% Thanks to \lsthelper{Knut M\"uller}{[email protected]}{1997/04/28}{\blankstringtrue} for reporting problem with |\blankstringtrue|.
|
|
|
+% The problem has gone.
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@Aspect{blankstring}[t]{\lstKV@SetIfKey\lst@ifblankstring{#1}}
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}\end{macro}\end{macro}\end{macro}
|
|
|
-%
|
|
|
-% \begin{macro}{\tablength}
|
|
|
-% \begin{macro}{\lstbaseem}
|
|
|
-% \begin{macro}{\lstlineskip}
|
|
|
-% \cs{tablength} and \cs{lstbaseem} also look, if the arguments are
|
|
|
-% legal.
|
|
|
% \begin{macrocode}
|
|
|
-\newcommand\tablength[1]{\ifnum#1>0 \def\lst@tablength{#1}\else %
|
|
|
- \PackageError{Listings}{Strict positive integer expected}{%
|
|
|
- You can't use `#1' as tablength.^^J I'll forget it and proceed.}\fi}
|
|
|
-\newcommand\lstbaseem[1]{\ifdim #1em>0pt \def\lst@baseem{#1}\else %
|
|
|
- \PackageError{Listings}{Strict positive number expected}{%
|
|
|
- You can't use `#1' as baseem.^^J I'll forget it and proceed.}\fi}
|
|
|
-\newcommand\lstlineskip[1]{\def\lst@lineskip{#1}}
|
|
|
+\lstset{blankstring=false}% init
|
|
|
+\lst@AddToHook{BeforeSelectCharTable}
|
|
|
+ {\setbox\@tempboxa\hbox{\lst@stringstyle \lst@loadfd}}
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}\end{macro}\end{macro}
|
|
|
+% \end{aspect}\end{aspect}
|
|
|
%
|
|
|
-% \begin{macro}{\prelisting}
|
|
|
-% \begin{macro}{\postlisting}
|
|
|
-% \begin{macro}{\spreadlisting}
|
|
|
-% \begin{macro}{\keywords}
|
|
|
-% \begin{macro}{\morekeywords}
|
|
|
-% \begin{macro}{\stringizer}
|
|
|
-% More 'parameter-saving' commands:
|
|
|
-% \begin{macrocode}
|
|
|
-\newcommand\prelisting[1]{\def\lst@prelisting{#1}}
|
|
|
-\newcommand\postlisting[1]{\def\lst@postlisting{#1}}
|
|
|
-\newcommand\spreadlisting[1]{\lst@halfspread#1\relax %
|
|
|
- \lst@halfspread 0.5\lst@halfspread\relax}
|
|
|
-\newcommand\keywords[1]{%
|
|
|
- \edef\lst@keywords{,\zap@space#1 \@empty}}
|
|
|
-\newcommand\morekeywords[1]{%
|
|
|
- \edef\lst@keywords{\lst@keywords,\zap@space#1 \@empty}}
|
|
|
-\newcommand\stringizer[2][d]{%
|
|
|
- \@ifundefined{lst@#1TestStringizer}{%
|
|
|
- \PackageError{Listings}{Illegal stringizer option `#1'}{%
|
|
|
- Available options are 'b' and 'd'.}}{%
|
|
|
- \expandafter\let\expandafter\lst@TestStringizer %
|
|
|
- \csname lst@#1TestStringizer\endcsname \def\lst@stringizer{#2}}}
|
|
|
+% \begin{macro}{\lst@stringmode}
|
|
|
+% It's time for a new mode allocation:
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@NewMode\lst@stringmode
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}\end{macro}\end{macro}\end{macro}
|
|
|
-% \end{macro}\end{macro}
|
|
|
+% \end{macro}
|
|
|
%
|
|
|
-% \begin{macro}{\blankstringtrue}
|
|
|
-% \begin{macro}{\blankstringfalse}
|
|
|
-% \begin{macro}{\sensitivetrue}
|
|
|
-% \begin{macro}{\sensitivefalse}
|
|
|
-% The user switches assign the right macros.
|
|
|
-% \begin{macrocode}
|
|
|
-\newcommand\blankstringtrue{%
|
|
|
- \let\lst@MakeStringBox\lst@MakeBox}
|
|
|
-\newcommand\blankstringfalse{%
|
|
|
- \let\lst@MakeStringBox\lst@MakeSpecialStringBox}
|
|
|
-\newcommand\sensitivetrue{%
|
|
|
- \let\lst@KeywordOrNot\lst@CaseSensitiveKeywords}
|
|
|
-\newcommand\sensitivefalse{%
|
|
|
- \let\lst@KeywordOrNot\lst@NonCaseSensitiveKeywords}
|
|
|
+% \begin{macro}{\lstCC@BeginString}
|
|
|
+% \begin{macro}{\lstCC@EndString}
|
|
|
+% To activate string mode we do te usual things, but here we also assign the correct closing stringizer and |\lst@outputblank|.
|
|
|
+% Note that you know that |\lst@NewLine| deactivates itself.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstCC@BeginString#1{%
|
|
|
+ \lst@NewLine %
|
|
|
+ \lst@EnterMode{\lst@stringmode}{\lst@modetrue\lst@stringstyle}%
|
|
|
+ #1%
|
|
|
+ \let\lstCC@closestring\lst@lastother %
|
|
|
+ \lst@ifblankstring\else \let\lst@outputblank\textvisiblespace \fi}
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}\end{macro}\end{macro}\end{macro}
|
|
|
-%
|
|
|
-% \begin{macro}{\normallisting}
|
|
|
-% The default style is set using the previous commands:
|
|
|
+% We terminate that mode selection after printing the collected other characters --- at least the closing stringizer.
|
|
|
+% And we reset some registers.
|
|
|
% \begin{macrocode}
|
|
|
-\newcommand\normallisting{%
|
|
|
- \keywordstyle{\bfseries}\commentstyle{\itshape}%
|
|
|
- \stringstyle{}\labelstyle[0]{}%
|
|
|
- \prelisting{}\postlisting{}%
|
|
|
- \spreadlisting{0pt}\blankstringfalse}
|
|
|
+\def\lstCC@EndString{%
|
|
|
+ \lst@OutputOther \lst@LeaveMode \lst@token{}\lst@length\z@}
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
+% \end{macro}\end{macro}
|
|
|
%
|
|
|
-% \begin{macro}{\listoflistings}
|
|
|
-% At the end of this section we define commands for the list of
|
|
|
-% listings. It's a derivation of \cs{listoffigures}.
|
|
|
-% \begin{macrocode}
|
|
|
-\newcommand\listoflistings{%
|
|
|
- \ifx\chapter\undefined %
|
|
|
- \expandafter\section \else \expandafter\chapter %
|
|
|
- \fi *{\listlistingsname %
|
|
|
- \@mkboth{\MakeUppercase\listlistingsname}%
|
|
|
- {\MakeUppercase\listlistingsname}}%
|
|
|
- \@starttoc{lol}}
|
|
|
-\newcommand\listlistingsname{Listings}
|
|
|
+% \begin{aspect}{stringtest}
|
|
|
+% We |\let| the test macro |\relax| if necessary.
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@Aspect{stringtest}[t]{\lstKV@SetIfKey\lst@ifstringtest{#1}}
|
|
|
+\lst@AddToHook{SetLanguage}{\let\lst@ifstringtest\iftrue}
|
|
|
+\lst@AddToHook{BeforeSelectCharTable}
|
|
|
+ {\lst@ifstringtest\else \let\lst@TestStringMode\relax \fi}
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
-%
|
|
|
-% \begin{macro}{\lst@ListOfListingsEntry}
|
|
|
-% And at the very end a command to add an entry to the list. The first
|
|
|
-% parameter is the name of the listing, and the second is reserved for
|
|
|
-% the line range, I think, but not used so far.
|
|
|
+% Default definition of the test macro:
|
|
|
% \begin{macrocode}
|
|
|
-\newcommand\lst@ListOfListingsEntry[2]{%
|
|
|
- \ifx \@empty#1\@empty \else %
|
|
|
- \addtocontents{lol}{\protect\ListOfListingsLine{#1}{#2}%
|
|
|
- {\lst@curr}{\thepage}}%
|
|
|
- \fi}
|
|
|
-\newcommand\ListOfListingsLine[4]{%
|
|
|
- \@dottedtocline{1}{1.5em}{2.3em}{#1}{#4}}
|
|
|
+\def\lst@TestStringMode{%
|
|
|
+ \ifnum\lst@mode=\lst@stringmode %
|
|
|
+ \PackageWarning{Listings}{String constant exceeds line}%
|
|
|
+ \lst@LeaveMode \lst@token{}\lst@length\z@ %
|
|
|
+ \fi}
|
|
|
+\lst@AddToHook{EOL}{\lst@TestStringMode}
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
+% \end{aspect}
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%</kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
%
|
|
|
%
|
|
|
-% \subsection{Typesetting a listing}
|
|
|
-% \begin{macro}{\inputlisting}
|
|
|
-% Now we define the main command. The first parameter is optional and
|
|
|
-% set to $[1,999999]$, if none is given. The second parameter is the
|
|
|
-% filename. If the file doesn't exist, we give an error message.
|
|
|
-% Otherwise we process the listing. But all this only happens,
|
|
|
-% if listings are desired.
|
|
|
+% \subsection{Comments}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
% \begin{macrocode}
|
|
|
-\newcommand\inputlisting[2][1,999999]{%
|
|
|
- \lst@ListOfListingsEntry{#2}{}%
|
|
|
- \iflisting %
|
|
|
- \batchmode \openin\lst@inputfile#2 \errorstopmode %
|
|
|
- \ifeof\lst@inputfile %
|
|
|
- \PackageError{Listings}{File `#2' not found}{%
|
|
|
- You must tell me the right name or I can't do the job.}%
|
|
|
- \else %
|
|
|
- \message{(#2}\lst@ProcessListing[#1]\message{)}%
|
|
|
- \fi \closein\lst@inputfile %
|
|
|
- \else %
|
|
|
- \begin{center}%
|
|
|
- --- Listing of #2 has been skipped. ---
|
|
|
- \end{center}%
|
|
|
- \fi}
|
|
|
+%<*kernel>
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
+% \endgroup
|
|
|
+% \begin{aspect}{commentstyle}
|
|
|
+% Again we start with an easy definition.
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@Aspect{commentstyle}{\def\lst@commentstyle{#1}}
|
|
|
+\lst@AddToHook{BeforeSelectCharTable}
|
|
|
+ {\setbox\@tempboxa\hbox{\lst@commentstyle \lst@loadfd}}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{aspect}
|
|
|
%
|
|
|
-% \begin{macro}{\lst@ProcessListing}
|
|
|
-% The two parameters of this command are the first and last output
|
|
|
-% line, respectively. First we set up a bit and skip the lines of the
|
|
|
-% listing upto the first printing line.
|
|
|
+% \begin{macro}{\lstCC@BeginComment}
|
|
|
+% \begin{macro}{\lstCC@@BeginComment}
|
|
|
+% \begin{macro}{\lstCC@EndComment}
|
|
|
+% These macros start and end a comment, respectively.
|
|
|
+% The |@@| version also eat (and output) one or two characters.
|
|
|
+% In that case the characters belong to the comment indicator.
|
|
|
+% |\relax| ensures that the characters are really eaten, i.e.\ the characters can't end the current comment or start a new one.
|
|
|
+% Note again that |\lst@NewLine| deactivates itself.
|
|
|
% \begin{macrocode}
|
|
|
-\def\lst@ProcessListing[#1,#2]{%
|
|
|
- \lst@Begin{#1}%
|
|
|
- \lst@lastno #2%
|
|
|
- \@whilenum #1>\lst@lineno \do %
|
|
|
- {\read\lst@inputfile to\lst@line %
|
|
|
- \advance\lst@lineno\@ne}%
|
|
|
+\def\lstCC@BeginComment#1{%
|
|
|
+ \lst@NewLine \lst@PrintToken %
|
|
|
+ \lst@EnterMode{#1}{\lst@modetrue\lst@commentstyle}}
|
|
|
% \end{macrocode}
|
|
|
-% The following loop terminates, if the end of file or the specified
|
|
|
-% last line is reached. In the loop we read and process the listing
|
|
|
-% line by line.
|
|
|
% \begin{macrocode}
|
|
|
- \lst@endinputfalse %
|
|
|
- \loop %
|
|
|
- \read\lst@inputfile to\lst@line %
|
|
|
- \ifeof\lst@inputfile \lst@endinputtrue \fi %
|
|
|
- \ifnum\lst@lastno<\lst@lineno\lst@endinputtrue\fi %
|
|
|
- \lst@ifendinput\else %
|
|
|
- \expandafter\lst@RemovePar\lst@line\par\relax %
|
|
|
- \lst@AllLineProcessing %
|
|
|
- \repeat %
|
|
|
- \lst@End}
|
|
|
+\def\lstCC@@BeginComment#1#2#3{%
|
|
|
+ \lst@NewLine \lst@PrintToken %
|
|
|
+ \lst@EnterMode{#1}{\lst@modetrue\lst@commentstyle}%
|
|
|
+ \lst@mode\lst@nomode #2\relax#3\relax \lst@mode#1\relax}
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
-%
|
|
|
-% \begin{macro}{\lst@RemovePar}
|
|
|
-% The next macro removes (together with the special call above) a
|
|
|
-% \cs{par} from the input line. So we need only one \cs{long}
|
|
|
-% definition, namely this here.
|
|
|
% \begin{macrocode}
|
|
|
-\long\def\lst@RemovePar#1\par#2\relax{\def\lst@line{#1}}
|
|
|
+\def\lstCC@EndComment{%
|
|
|
+ \lst@PrintToken \lst@LeaveMode \let\lst@lastother\@empty}
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
+% \end{macro}\end{macro}\end{macro}
|
|
|
%
|
|
|
-% \begin{macro}{\listing}
|
|
|
-% Now we define the environment for typesetting listings. To read the
|
|
|
-% \TeX-file line by line we have to make the end of line character
|
|
|
-% \verb!^^M! active. If no output is desired, we typeset a message and
|
|
|
-% read the listing without doing any output.
|
|
|
-% Ending the environment is very easy.
|
|
|
-% \begin{macrocode}
|
|
|
-\newenvironment{listing}{%
|
|
|
- \iflisting\else
|
|
|
- \begin{center}%
|
|
|
- --- Listing has been skipped. ---
|
|
|
- \end{center}%
|
|
|
+% \begin{macro}{\lstCC@TestCArg}
|
|
|
+% Comment commands allow a single character like |!| or two characters like |//|.
|
|
|
+% The calling syntax of this testing macro is
|
|
|
+% \begin{macrosyntax}
|
|
|
+% \item |\lstCC@TestCArg|\meta{characters to test}|\@empty\relax|\meta{macro}
|
|
|
+% \end{macrosyntax}
|
|
|
+% \meta{macro} is called after doing the test and gets three arguments:
|
|
|
+% The given two characters as active characters (where the second equals |\@empty| if and only if a single character is given), and the third is a catcode 12 version of the first character.
|
|
|
+% \begin{macrocode}
|
|
|
+\begingroup \catcode`\^^@=\active
|
|
|
+\gdef\lstCC@TestCArg#1#2#3\relax#4{%
|
|
|
+ \lccode`\~=`#1\lccode`\/=`#1%
|
|
|
+ \ifx\@empty#2%
|
|
|
+ \lowercase{\def\lst@temp{~\@empty/}}%
|
|
|
+ \else \lccode`\^^@=`#2%
|
|
|
+ \lowercase{\def\lst@temp{~^^@/}}%
|
|
|
\fi %
|
|
|
- \lst@Begin{1}\catcode`\^^M=\active %
|
|
|
- \lstenv@SkipLineAndProcess}{}
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
-%
|
|
|
-% \begin{macro}{\lstenv@SkipLineAndProcess}
|
|
|
-% We will use a mechanism used in the new implementation of \LaTeX's
|
|
|
-% \verb!verbatim! environments. I don't explain it here. It is
|
|
|
-% described in section 3.4 of \cite{verbatim}.
|
|
|
+% If neither |#2| nor |#3| equals |\@empty|, the user has given more than two characters:
|
|
|
% \begin{macrocode}
|
|
|
-\begingroup
|
|
|
-\catcode`\!=\active \catcode`\(=\active \catcode`\)=\active
|
|
|
-\lccode`\!=`\\ \lccode`\(=`\{ \lccode`\)=`\}
|
|
|
-\catcode`\~=\active \lccode`\~=`\^^M
|
|
|
-\lowercase{
|
|
|
+ \ifx\@empty#2\else \ifx\@empty#3\else \lstCC@TestCArgError \fi\fi %
|
|
|
% \end{macrocode}
|
|
|
-% The effect of \cs{lowercase} is that all \verb+!+, \verb!(!, \verb!)!
|
|
|
-% and \verb!~! of the argument are converted to \verb!\!, \verb!{!,
|
|
|
-% \verb!}! and \verb!^^M!.
|
|
|
-% The macro \verb!\lstenv@SkipLineAndProcess! skips the rest of the
|
|
|
-% line, tests the optional argument and begins the loop of processing.
|
|
|
% \begin{macrocode}
|
|
|
-\gdef\lstenv@SkipLineAndProcess#1~{%
|
|
|
- \lstenv@TestOptional#1[]~\lstenv@ReadAndProcess}
|
|
|
+ \expandafter #4\lst@temp}
|
|
|
+\endgroup
|
|
|
% \end{macrocode}
|
|
|
% \end{macro}
|
|
|
%
|
|
|
-% \begin{macro}{\lstenv@TestOptional}
|
|
|
-% The second parameter is empty, if and only if there is no optional
|
|
|
-% argument.
|
|
|
+% \begin{macro}{\lstCC@TestCArgError}
|
|
|
% \begin{macrocode}
|
|
|
-\gdef\lstenv@TestOptional#1[#2]#3~{%
|
|
|
- \ifx\@empty#2\@empty\else \lst@ListOfListingsEntry{#2}{}\fi}
|
|
|
+\def\lstCC@TestCArgError{%
|
|
|
+ \PackageError{Listings}{At most 2 characters allowed}%
|
|
|
+ {The package doesn't provide more than two characters here.^^J%
|
|
|
+ I'll simply use the first two only and proceed.}}
|
|
|
% \end{macrocode}
|
|
|
% \end{macro}
|
|
|
%
|
|
|
-% \begin{macro}{\lstenv@ReadAndProcess}
|
|
|
-% The macro \verb!\lstenv@ReadAndProcess! gets the input upto the next
|
|
|
-% end of line character. We append \verb!\end{listing}\relax!
|
|
|
-% to hold up the syntax of \verb!\lstenv@Process!.
|
|
|
+% \begin{macro}{\lstCC@next}
|
|
|
+% \begin{macro}{\lstCC@bnext}
|
|
|
+% \begin{macro}{\lstCC@enext}
|
|
|
+% We initialize some macros used in the sequel.
|
|
|
% \begin{macrocode}
|
|
|
-\gdef\lstenv@ReadAndProcess#1~{\lstenv@Process#1!end(listing)\relax}
|
|
|
+\lst@AddToHook{BeforeSelectCharTable}
|
|
|
+ {\let\lstCC@next\relax \let\lstCC@bnext\relax\let\lstCC@enext\relax}
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
+% \end{macro}\end{macro}\end{macro}
|
|
|
%
|
|
|
-% \begin{macro}{\lstenv@Process}
|
|
|
-% The second parameter of this macro is empty, if and only if the end
|
|
|
-% of the environment is not reached. If the listing goes on, we define
|
|
|
-% the current line, do the line processing and define the next macro.
|
|
|
-% If the listing is over, we define the right macro to be done next.
|
|
|
-% \begin{macrocode}
|
|
|
-\gdef\lstenv@Process#1!end(listing)#2\relax{%
|
|
|
- \ifx \@empty#2\@empty %
|
|
|
- \iflisting \def\lst@line{#1}\lst@AllLineProcessing \fi %
|
|
|
- \let\lst@next\lstenv@ReadAndProcess %
|
|
|
- \else %
|
|
|
- \def\lst@next{\lst@End\end{listing}}%
|
|
|
- \fi \lst@next}
|
|
|
-}\endgroup
|
|
|
+% \begin{macro}{\lst@DefSC}
|
|
|
+% \begin{macro}{\lst@DefNC}
|
|
|
+% \begin{macro}{\lst@DefDC}
|
|
|
+% \begin{macro}{\lst@DefCL}
|
|
|
+% \begin{macro}{\lst@DefFCL}
|
|
|
+% These macros are redefined by comment aspects.
|
|
|
+% The comments are reset every language selection, and every listing we define the comment characters after selecting the standard character table.
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@AddToHook{SetLanguage}
|
|
|
+ {\let\lst@DefSC\relax \let\lst@DefNC\relax \let\lst@DefDC\relax %
|
|
|
+ \let\lst@DefCL\relax \let\lst@DefFCL\relax}
|
|
|
+\lst@AddToHook{SelectCharTable}
|
|
|
+ {\lst@DefSC \lst@DefNC \lst@DefDC \lst@DefCL \lst@DefFCL}
|
|
|
% \end{macrocode}
|
|
|
+% \end{macro}\end{macro}\end{macro}\end{macro}
|
|
|
% \end{macro}
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%</kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
%
|
|
|
-% \begin{macro}{\lst@Begin}
|
|
|
-% \begin{macro}{\lst@End}
|
|
|
-% Let's look what's to do to begin and end a listing, respectively.
|
|
|
-% We insert a small skip, the user defined \verb!\lst@prelisting!
|
|
|
-% and \verb!\lst@postlisting! and initialize some variables.
|
|
|
-% Of course, we use a new group level, so that outer blocks are not
|
|
|
-% affected by the changes made here.
|
|
|
+%
|
|
|
+% \subsubsection{Comment lines}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
% \begin{macrocode}
|
|
|
-\newcommand\lst@Begin[1]{%
|
|
|
- \smallbreak\bgroup\lst@prelisting %
|
|
|
- \parskip\lst@lineskip %
|
|
|
- \lst@stringfalse \lst@commentdepth0 \lst@commentfalse %
|
|
|
- \let\lst@comment\@empty \let\lst@commentline\@empty %
|
|
|
- \lst@lineno\@ne %
|
|
|
+%<*kernel>
|
|
|
% \end{macrocode}
|
|
|
-% The following two lines ensure, that \TeX{} doesn't read font
|
|
|
-% information from other files when catcodes are changed.
|
|
|
+% \endgroup
|
|
|
+% \begin{aspect}{commentline}
|
|
|
+% We define the user aspect:
|
|
|
% \begin{macrocode}
|
|
|
- \setbox0\hbox{{\lst@keywordstyle}{\lst@commentstyle}%
|
|
|
- {\lst@stringstyle}{{\lst@labelstyle0}}}%
|
|
|
+\lst@Aspect{commentline}{\def\lst@DefCL{\lstCC@CommentLine{#1}}}
|
|
|
% \end{macrocode}
|
|
|
-% The textwidth for a listing is spread using a parshape command
|
|
|
-% every paragraph. If \verb!\lst@labelstep! is zero, no labels (=line
|
|
|
-% numbers) are printed.
|
|
|
+% \end{aspect}
|
|
|
+%
|
|
|
+% \begin{macro}{\lstCC@CommentLine}
|
|
|
+% Comment lines become undefined if the one and only argument is empty.
|
|
|
% \begin{macrocode}
|
|
|
- \@tempdima\textwidth \advance\@tempdima by 2\lst@halfspread %
|
|
|
- \expandafter\ifnum \lst@labelstep=0 %
|
|
|
- \everypar{\parshape 1 -\lst@halfspread \@tempdima}%
|
|
|
- \else %
|
|
|
+\def\lstCC@CommentLine#1{%
|
|
|
+ \ifx\@empty#1\@empty\else %
|
|
|
+ \lstCC@TestCArg#1\@empty\relax\lstCC@CommentLine@ %
|
|
|
+ \fi}
|
|
|
% \end{macrocode}
|
|
|
-% The parameter is the number of the first printing line. We calculate
|
|
|
-% how many lines it will take to set the first label (a line number)
|
|
|
-% and assign it to \verb!\@tempcnta!.
|
|
|
+% The next submacro actually defines the comment characters.
|
|
|
+% We save the old meaning --- or we couldn't use the original meaning any more.
|
|
|
% \begin{macrocode}
|
|
|
- \@tempcnta#1\divide\@tempcnta\lst@labelstep %
|
|
|
- \multiply\@tempcnta-\lst@labelstep \advance\@tempcnta#1\relax %
|
|
|
- \ifnum\@tempcnta>0 \advance\@tempcnta-\lst@labelstep \fi %
|
|
|
+\def\lstCC@CommentLine@#1#2#3{%
|
|
|
+ \expandafter\let\csname lsts@CL#3\endcsname#1%
|
|
|
% \end{macrocode}
|
|
|
-% Defining \cs{everypar} is easy now and some other things also.
|
|
|
+% The redefinitions:
|
|
|
+% If a single character indicates a comment, the next operation is either |\relax| (since no mode change is allowed) or |\lstCC@BeginCommentLine|.
|
|
|
+% And we execute the saved character meaning.
|
|
|
% \begin{macrocode}
|
|
|
- \everypar{\parshape 1 -\lst@halfspread \@tempdima %
|
|
|
- \ifnum \@tempcnta=0 %
|
|
|
- \advance\@tempcnta-\lst@labelstep \llap{%
|
|
|
- \bgroup\lst@labelstyle\the\lst@lineno\relax\egroup\ }%
|
|
|
+ \ifx\@empty#2%
|
|
|
+ \def#1{%
|
|
|
+ \lst@ifmode \let\lstCC@next\relax \else %
|
|
|
+ \let\lstCC@next\lstCC@BeginCommentLine %
|
|
|
\fi %
|
|
|
- \advance\@tempcnta\@ne}%
|
|
|
- \fi %
|
|
|
- \expandafter\lst@width\lst@baseem em %
|
|
|
- \lst@ChangeCatcodes %
|
|
|
+ \expandafter\lstCC@next \csname lsts@CL#3\endcsname}%
|
|
|
+ \else %
|
|
|
% \end{macrocode}
|
|
|
-% Finally we call the language's own prepare macro.
|
|
|
+% Comment lines indicated by a sequence of two characters are just the same.
|
|
|
+% But: We enter comment mode (if and) only if the next character equals |#2|.
|
|
|
+% And we use a different macro to enter comment mode.
|
|
|
% \begin{macrocode}
|
|
|
- \edef\next{lstdrv@\lst@curr @PrepareListing}%
|
|
|
- \expandafter\csname\next\endcsname}
|
|
|
+ \def#1##1{%
|
|
|
+ \let\lstCC@next\relax %
|
|
|
+ \lst@ifmode\else \ifx##1#2%
|
|
|
+ \let\lstCC@next\lstCC@@BeginCommentLine %
|
|
|
+ \fi \fi %
|
|
|
+ \expandafter\lstCC@next \csname lsts@CL#3\endcsname##1}%
|
|
|
+ \fi}
|
|
|
% \end{macrocode}
|
|
|
-% The ending of a listing is not very exciting.
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{aspect}{fixedcommentline}
|
|
|
+% \begin{macro}{\lst@FCLmode}
|
|
|
+% Another user aspect \ldots
|
|
|
% \begin{macrocode}
|
|
|
-\def\lst@End{\lst@postlisting\catcode`\%=\lst@ccPercent %
|
|
|
- \par\removelastskip\egroup \smallbreak\ignorespaces}
|
|
|
+\lst@Aspect{fixedcommentline}{\lstKV@OptArg\lstfcommentline@[0]{#1}}
|
|
|
+\def\lstfcommentline@[#1]#2%
|
|
|
+ {\def\lst@DefFCL{\lstCC@FixedCL[#1]#2\@empty}}
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}\end{macro}
|
|
|
-%
|
|
|
-%
|
|
|
-% \subsection{Line processing}\label{ssLineProcessing}
|
|
|
-%
|
|
|
-% \begin{macro}{\lst@AllLineProcessing}
|
|
|
-% Here comes the single line processing. First we collect the line
|
|
|
-% processing in one macro: Some initialization, pre-processing,
|
|
|
-% processing and post-processing, but only if the line is not empty.
|
|
|
-% We increase the current line number also.
|
|
|
+% and a mode allocation.
|
|
|
% \begin{macrocode}
|
|
|
-\def\lst@AllLineProcessing{%
|
|
|
- \ifx \lst@line\@empty \par\noindent\hbox{}\else
|
|
|
- \let\lst@text\@empty \lst@length0 \global\lst@pos0 %
|
|
|
- \let\lst@lastother\@empty %
|
|
|
- \par\noindent \lst@PrePL \lst@ProcessLine \lst@PostPL %
|
|
|
- \fi \advance\lst@lineno\@ne}
|
|
|
+\lst@NewMode\lst@FCLmode
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
+% \end{macro}\end{aspect}
|
|
|
%
|
|
|
-% \begin{macro}{\lst@PrePLDefault}
|
|
|
-% \begin{macro}{\lst@PostPLDefault}
|
|
|
-% Before considering the main macro we define the defaults for
|
|
|
-% \verb!\lst@PrePL! and \verb!\lst@PostPL!. The latter gives a
|
|
|
-% warning, if a string exceeds a line.
|
|
|
+% \begin{macro}{\lstCC@FixedCL}
|
|
|
+% Note that we can't use |\lstCC@TestCArg| here since the argument might consist of more than two characters.
|
|
|
+% We enter a loop which is terminated by |\@empty|.
|
|
|
% \begin{macrocode}
|
|
|
-\let\lst@PrePLDefault\relax
|
|
|
-\def\lst@PostPLDefault{%
|
|
|
- \lst@ifstring %
|
|
|
- \PackageWarning{Listings}{string constant exceeds line}%
|
|
|
- \lst@stringfalse %
|
|
|
+\def\lstCC@FixedCL[#1]#2{%
|
|
|
+ \ifx\@empty#2\else %
|
|
|
+ \lccode`\~=`#2\lccode`\/=`#2%
|
|
|
+ \lowercase{\lstCC@FixedCL@~/}{#1}%
|
|
|
+ \def\lstCC@next{\lstCC@FixedCL[#1]}%
|
|
|
+ \expandafter\lstCC@next %
|
|
|
\fi}
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}\end{macro}
|
|
|
+% But now comes the same as above: We save the old meaning of |#1| and redefine it.
|
|
|
+% We enter comment mode (if and) only if the character is in column |#3|+1.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstCC@FixedCL@#1#2#3{%
|
|
|
+ \expandafter\let\csname lsts@FCL#2\endcsname#1%
|
|
|
+ \def#1{\let\lstCC@next\relax %
|
|
|
+ \lst@ifmode\else %
|
|
|
+ \@tempcnta\lst@column %
|
|
|
+ \advance\@tempcnta\lst@length %
|
|
|
+ \advance\@tempcnta-\lst@pos %
|
|
|
+ \ifnum\@tempcnta=#3%
|
|
|
+ \let\lstCC@next\lstCC@BeginCommentLine %
|
|
|
+ \fi %
|
|
|
+ \fi %
|
|
|
+ \expandafter\lstCC@next \csname lsts@FCL#2\endcsname}}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%</kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
%
|
|
|
-% \begin{macro}{\lst@ProcessLine}
|
|
|
-% Now the main macro for line processing. There is no parameter,
|
|
|
-% because the data is given by \verb!\lst@line!. We construct a loop
|
|
|
-% by defining the macro \cs{next} to call this macro again. But this
|
|
|
-% definition might changes soon to terminate line processing.
|
|
|
+%
|
|
|
+% \subsubsection{Single and double comments}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
% \begin{macrocode}
|
|
|
-\def\lst@ProcessLine{\let\next\lst@ProcessLine %
|
|
|
+%<*kernel>
|
|
|
% \end{macrocode}
|
|
|
-% Since a comment might exceeds a line, we have to handle this case
|
|
|
-% first. We try to find the end of comment, which saves the comment
|
|
|
-% in \verb!\lst@comment! and might changes the boolean
|
|
|
-% \verb!\lst@ifcomment!.
|
|
|
+% \endgroup
|
|
|
+% \begin{aspect}{singlecomment}
|
|
|
+% \begin{aspect}{doublecomment}
|
|
|
+% Define the user commands \ldots
|
|
|
% \begin{macrocode}
|
|
|
- \lst@ifcomment \lst@EOC %
|
|
|
+\lst@Aspect{singlecomment}{\def\lst@DefSC{\lstCC@SingleComment#1{}}}
|
|
|
+\lst@Aspect{doublecomment}{\def\lst@DefDC{\lstCC@DoubleComment#1{}{}{}}}
|
|
|
% \end{macrocode}
|
|
|
-% To output the comment we use a little trick (concerning the naming
|
|
|
-% of a macro). The tokenize macro below not only cuts up the input for
|
|
|
-% scanning keywords. In comment mode it will cut the input in the same
|
|
|
-% way, but always uses commentstyle for the output. Therefore we
|
|
|
-% switch to comment mode locally and call the macro.
|
|
|
+% \end{aspect}\end{aspect}
|
|
|
+%
|
|
|
+% \begin{macro}{\lst@SCmode}
|
|
|
+% \begin{macro}{\lst@DCmodeA}
|
|
|
+% \begin{macro}{\lst@DCmodeB}
|
|
|
+% and allocate new internal modes.
|
|
|
% \begin{macrocode}
|
|
|
- {\lst@commenttrue \expandafter\lst@Tokenize\lst@comment\relax}%
|
|
|
+\lst@NewMode\lst@SCmode \lst@NewMode\lst@DCmodeA\lst@NewMode\lst@DCmodeB
|
|
|
% \end{macrocode}
|
|
|
-% We empty the comment just output. If the comment goes on, i.e.\ the
|
|
|
-% comment was the whole line, line processing is over, i.e.\ there is
|
|
|
-% nothing to do next: We redefine the macro \cs{next}.
|
|
|
+% \end{macro}\end{macro}\end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lstCC@SingleComment}
|
|
|
+% \begin{macro}{\lstCC@DoubleComment}
|
|
|
+% All must be done twice here, for the beginning and end of a comment.
|
|
|
+% The use of additional arguments like |{SC}\lst@SCmode| make it possible to define single and double comments with the same macros.
|
|
|
% \begin{macrocode}
|
|
|
- \let\lst@comment\@empty \lst@ifcomment \let\next\relax \fi %
|
|
|
- \else %
|
|
|
+\def\lstCC@SingleComment#1#2{%
|
|
|
+ \ifx\@empty#1\@empty\else %
|
|
|
+ \lstCC@TestCArg#1\@empty\relax\lstCC@CommentB{SC}\lst@SCmode %
|
|
|
+ \lstCC@TestCArg#2\@empty\relax\lstCC@CommentE{SC}\lst@SCmode %
|
|
|
+ \fi}
|
|
|
% \end{macrocode}
|
|
|
-% If no comment is in progress, the macro tries to find one and cuts
|
|
|
-% off a comment line, if possible (or a part of the line as a comment
|
|
|
-% line).
|
|
|
-% \begin{macrocode}
|
|
|
- \lst@SOC \lst@CommentLine %
|
|
|
-% \end{macrocode}
|
|
|
-% Now \verb!\lst@line! has been cut to the noncomment rest.
|
|
|
-% We have to find the keywords. \cs{relax} is used as a brake:
|
|
|
-% It marks the end and will terminate tokenizing.
|
|
|
-% \begin{macrocode}
|
|
|
- {\lst@commentfalse \expandafter\lst@Tokenize\lst@line\relax}%
|
|
|
-% \end{macrocode}
|
|
|
-% If a string has begun in \verb!\lst@Tokenize!, but not finished,
|
|
|
-% the potential comment above belongs to the string. What's to do? The
|
|
|
-% input line gets the comment and the next character is typeset. Then
|
|
|
-% we call this macro without being in danger classifing the comment as
|
|
|
-% a comment again, because the first character is missing now. But
|
|
|
-% hold on: The comment might be empty and so the input line. To handle
|
|
|
-% this we use two \cs{relax} as brake and might redefine \cs{next}.
|
|
|
-% \verb!\lst@PostPL! might gives a warning to the user.
|
|
|
-% \begin{macrocode}
|
|
|
- \lst@ifstring %
|
|
|
- \lst@commentfalse %
|
|
|
- \expandafter\expandafter\expandafter\lst@TypesetChar %
|
|
|
- \expandafter\lst@commentline\lst@comment\relax\relax %
|
|
|
- \let\lst@comment\@empty \let\lst@commentline\@empty %
|
|
|
- \ifx \lst@line\@empty \let\next\relax \fi %
|
|
|
- \else %
|
|
|
+% Note the order: We define 'begin comment' and afterwards 'end comment'.
|
|
|
+% This becomes important if |#1| equals |#2|, for example.
|
|
|
+% Each such comment definition saves the old character meaning, which is executed after doing all comment specific.
|
|
|
+% If we define 'end comment' first and then 'begin comment', |#1| would start a comment and then execute the old definition, which is 'end comment'.
|
|
|
+% Since we are in comment mode now (and since |#1| equals |#2|), 'end comment' leaves comment mode immediately.
|
|
|
+% That would be very bad!
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstCC@DoubleComment#1#2#3#4{%
|
|
|
+ \ifx\@empty#1\@empty\else %
|
|
|
+ \lstCC@TestCArg#1\@empty\relax\lstCC@CommentB{DCA}\lst@DCmodeA %
|
|
|
+ \lstCC@TestCArg#3\@empty\relax\lstCC@CommentB{DCB}\lst@DCmodeB %
|
|
|
+ \lstCC@TestCArg#2\@empty\relax\lstCC@CommentE{DCA}\lst@DCmodeA %
|
|
|
+ \lstCC@TestCArg#4\@empty\relax\lstCC@CommentE{DCB}\lst@DCmodeB %
|
|
|
+ \fi}
|
|
|
% \end{macrocode}
|
|
|
-% If no string is in work, it's all fine. We output the comment line,
|
|
|
-% if present. In that case there is no other comment.
|
|
|
+% \end{macro}\end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lstCC@CommentB}
|
|
|
+% is not different from |\lstCC@CommentLine@| at all:
|
|
|
+% The save name |#3| there is replaced by |B#4#3| and instead of |\lst@CLmode| we use |#5|.
|
|
|
% \begin{macrocode}
|
|
|
- \ifx\lst@commentline\@empty \else %
|
|
|
- \lst@commenttrue %
|
|
|
- \expandafter\expandafter\expandafter\lst@Tokenize %
|
|
|
- \expandafter\lst@commentline\lst@comment\relax %
|
|
|
- \lst@commentfalse %
|
|
|
+\def\lstCC@CommentB#1#2#3#4#5{%
|
|
|
+ \expandafter\let\csname lsts@B#4#3\endcsname#1%
|
|
|
+ \ifx\@empty#2%
|
|
|
+ \def#1{%
|
|
|
+ \lst@ifmode \let\lstCC@bnext\relax \else %
|
|
|
+ \def\lstCC@bnext{\lstCC@BeginComment#5}%
|
|
|
\fi %
|
|
|
+ \lstCC@bnext \csname lsts@B#4#3\endcsname}%
|
|
|
+ \else %
|
|
|
+ \def#1##1{%
|
|
|
+ \let\lstCC@bnext\relax %
|
|
|
+ \lst@ifmode\else \ifx##1#2%
|
|
|
+ \def\lstCC@bnext{\lstCC@@BeginComment#5}%
|
|
|
+ \fi \fi %
|
|
|
+ \expandafter\lstCC@bnext \csname lsts@B#4#3\endcsname##1}%
|
|
|
+ \fi}
|
|
|
% \end{macrocode}
|
|
|
-% For comments this macro calls itself to find the end of comment.
|
|
|
-% As this is the default, we only have to assign the comment to
|
|
|
-% \verb!\lst@line! --- the implizit parameter of this macro.
|
|
|
-% If there is no comment, we redefine \cs{next}.
|
|
|
-% \begin{macrocode}
|
|
|
- \lst@ifcomment \let\lst@line\lst@comment %
|
|
|
- \else \let\next\relax %
|
|
|
- \fi %
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lstCC@CommentE}
|
|
|
+% Here we insert |\ifnum\lst@mode=#5| (6-th line), where |#5| is |\lst@SCmode| for example.
|
|
|
+% This ensures that comment delimiters match each other.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstCC@CommentE#1#2#3#4#5{%
|
|
|
+ \expandafter\let\csname lsts@E#4#3\endcsname#1%
|
|
|
+ \ifx\@empty#2%
|
|
|
+ \def#1{%
|
|
|
+ \def\lstCC@enext{\csname lsts@E#4#3\endcsname}%
|
|
|
+ \lst@ifmode \ifnum\lst@mode=#5%
|
|
|
+ \def\lstCC@enext{\csname lsts@E#4#3\endcsname %
|
|
|
+ \lstCC@EndComment}%
|
|
|
+ \fi \fi %
|
|
|
+ \lstCC@enext}%
|
|
|
+ \else %
|
|
|
+ \def#1##1{%
|
|
|
+ \def\lstCC@enext{\csname lsts@E#4#3\endcsname ##1}%
|
|
|
+ \lst@ifmode \ifnum\lst@mode=#5\ifx##1#2%
|
|
|
+ \def\lstCC@enext{\csname lsts@E#4#3\endcsname ##1%
|
|
|
+ \lstCC@EndComment}%
|
|
|
+ \fi \fi \fi %
|
|
|
+ \lstCC@enext}%
|
|
|
+ \fi}
|
|
|
% \end{macrocode}
|
|
|
-% We have to close some ifs and do the next thing.
|
|
|
+% \end{macro}
|
|
|
+% \begingroup
|
|
|
% \begin{macrocode}
|
|
|
- \fi %
|
|
|
- \fi\next}
|
|
|
+%</kernel>
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
+% \endgroup
|
|
|
%
|
|
|
-% \begin{macro}{\lst@TypesetChar}
|
|
|
-% The following macro has been used in the last macro. It typesets the
|
|
|
-% next character and removes it from the input line.
|
|
|
+%
|
|
|
+% \subsubsection{Nested comments}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
% \begin{macrocode}
|
|
|
-\def\lst@TypesetChar#1#2\relax{\def\lst@line{#2}\lst@OutputChar#1}
|
|
|
+%<*kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+% \begin{aspect}{nestedcomment}
|
|
|
+% The user aspect \ldots
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@Aspect{nestedcomment}{\lstnestedcomment@#1}
|
|
|
+\def\lstnestedcomment@#1#2%
|
|
|
+ {\def\@tempa{#1}\def\@tempb{#2}%
|
|
|
+ \ifx\@tempa\@tempb \ifx\@tempa\@empty\else %
|
|
|
+ \PackageError{Listings}{Identical delimitors}%
|
|
|
+ {These delimitors make no sense with nested comments.}%
|
|
|
+ \fi \fi %
|
|
|
+ \def\lst@DefNC{\lstCC@NestedComment{#1}{#2}}}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{aspect}
|
|
|
+%
|
|
|
+% \begin{macro}{\lstCC@NestedComment}
|
|
|
+% and the internal macro.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstCC@NestedComment#1#2{%
|
|
|
+ \ifx\@empty#1\@empty\else %
|
|
|
+ \lstCC@TestCArg#2\@empty\relax\lstCC@NCommentE %
|
|
|
+ \lstCC@TestCArg#1\@empty\relax\lstCC@NCommentB %
|
|
|
+ \fi}
|
|
|
% \end{macrocode}
|
|
|
+% Note the order: We define 'end comment' and afterwards 'begin comment'.
|
|
|
% \end{macro}
|
|
|
%
|
|
|
-% \begin{macro}{\lst@ProcessWhitespaces}
|
|
|
-% This macro processes all whitespaces (blank spaces and tabulators here)
|
|
|
-% from the beginning of \verb!\lst@line! upto the first non-whitespace.
|
|
|
-% The macro assumes that \verb!\lst@text! is already output.
|
|
|
-% \begin{macrocode}
|
|
|
-\def\lst@ProcessWhitespaces{%
|
|
|
- \expandafter\lst@TestWhitespace\lst@line\relax}
|
|
|
+% \begin{macro}{\lstCC@NCommentB}
|
|
|
+% The redefinition of the character is different now.
|
|
|
+% Since we define nested comments, we have to count the comment depth.
|
|
|
+% If we already process a nested comment, we increase that depth by making |\lst@mode| more negative.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstCC@NCommentB#1#2#3{%
|
|
|
+ \let\lsts@BNC #1%
|
|
|
+ \ifx\@empty#2%
|
|
|
+ \def#1{%
|
|
|
+ \let\lstCC@bnext\relax %
|
|
|
+ \lst@ifmode %
|
|
|
+ \ifnum\lst@mode<\z@ %
|
|
|
+ \advance\lst@mode\m@ne %
|
|
|
+ \fi %
|
|
|
+ \else %
|
|
|
+ \def\lstCC@bnext{\lstCC@BeginComment\m@ne}%
|
|
|
+ \fi %
|
|
|
+ \lstCC@bnext \lsts@BNC}%
|
|
|
+ \else %
|
|
|
+ \def#1##1{%
|
|
|
+ \let\lstCC@bnext\relax %
|
|
|
+ \lst@ifmode %
|
|
|
+ \ifnum\lst@mode<\z@ \ifx##1#2%
|
|
|
+ \advance\lst@mode\m@ne %
|
|
|
+ \fi \fi %
|
|
|
+ \else %
|
|
|
+ \ifx##1#2%
|
|
|
+ \def\lstCC@bnext{\lstCC@@BeginComment\m@ne}%
|
|
|
+ \fi %
|
|
|
+ \fi %
|
|
|
+ \lstCC@bnext \lsts@BNC ##1}%
|
|
|
+ \fi}
|
|
|
% \end{macrocode}
|
|
|
+% \begin{TODO}
|
|
|
+% The third argument (|\catcode| 12 version of the first) is unused so far --- also in |\lst@NCommentE|.
|
|
|
+% If we are in need of 'double' nested comments, we will use this argument for the save name, as we've already done it for normal double comments (and comment lines).
|
|
|
+% \end{TODO}
|
|
|
% \end{macro}
|
|
|
%
|
|
|
-% \begin{macro}{\lst@EndTestWhitespace}
|
|
|
-% To end the whitespace test we get the line upto the closing \cs{relax}
|
|
|
-% and assign it to \verb!\lst@line!.
|
|
|
-% \begin{macrocode}
|
|
|
-\def\lst@EndTestWhitespace#1\relax{\def\lst@line{#1}}
|
|
|
+% \begin{macro}{\lstCC@NCommentE}
|
|
|
+% If we are in nested comment mode, we either end the comment or decrease the comment depth by making |\lst@mode| less negative.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\lstCC@NCommentE#1#2#3{%
|
|
|
+ \let\lsts@ENC #1%
|
|
|
+ \ifx\@empty#2%
|
|
|
+ \def#1{%
|
|
|
+ \let\lstCC@enext\relax %
|
|
|
+ \lst@ifmode \ifnum\lst@mode<\z@ %
|
|
|
+ \ifnum\lst@mode=\m@ne %
|
|
|
+ \let\lstCC@enext\lstCC@EndComment %
|
|
|
+ \else %
|
|
|
+ \advance\lst@mode\@ne %
|
|
|
+ \fi
|
|
|
+ \fi \fi %
|
|
|
+ \lsts@ENC \lstCC@enext}%
|
|
|
+ \else %
|
|
|
+ \def#1##1{%
|
|
|
+ \def\lstCC@enext{\lsts@ENC ##1}%
|
|
|
+ \ifx##1#2%
|
|
|
+ \lst@ifmode \ifnum\lst@mode<\z@ %
|
|
|
+ \ifnum\lst@mode=\m@ne %
|
|
|
+ \def\lstCC@enext{%
|
|
|
+ \lsts@ENC ##1\lstCC@EndComment}%
|
|
|
+ \else %
|
|
|
+ \advance\lst@mode\@ne %
|
|
|
+ \fi
|
|
|
+ \fi \fi %
|
|
|
+ \fi %
|
|
|
+ \lstCC@enext}%
|
|
|
+ \fi}
|
|
|
% \end{macrocode}
|
|
|
% \end{macro}
|
|
|
-%
|
|
|
-% \begin{macro}{\lst@TestWhitespace}
|
|
|
-% The real work is done here. We test for a whitespace, do the output
|
|
|
-% and decide what's to be done next.
|
|
|
+% \begingroup
|
|
|
% \begin{macrocode}
|
|
|
-\def\lst@TestWhitespace#1{\let\next\lst@TestWhitespace %
|
|
|
- \ifcat #1&\lst@GotoNextTabStop %
|
|
|
- \else \if #1\lst@outputblank \lst@OutputChar#1%
|
|
|
- \else
|
|
|
- \ifx#1\relax \let\lst@line\@empty \let\next\relax %
|
|
|
- \else \def\next{\lst@EndTestWhitespace#1}%
|
|
|
- \fi %
|
|
|
- \fi \fi \next}
|
|
|
+%</kernel>
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
-% The line processing is complete. Now we will try to scan keywords.
|
|
|
+% \endgroup
|
|
|
%
|
|
|
%
|
|
|
-% \subsection{Tokenizing}\label{ssTokenizing}
|
|
|
-% We define two tokenize macros. The first determines potential
|
|
|
-% keywords by collecting characters upto a nonletter. After outputting
|
|
|
-% the potential keyword the second macro is called to gather all
|
|
|
-% characters upto the next letter. Then these characters are output
|
|
|
-% and the first macro is called again. That's how the two macros work
|
|
|
-% together.
|
|
|
+% \subsection{Escape characters}
|
|
|
%
|
|
|
-% \begin{macro}{\lst@Tokenize}
|
|
|
-% The tokenize macro gets code upto \cs{relax} and scans for keywords
|
|
|
-% and strings. In fact it only cuts up potential keywords, which are
|
|
|
-% tested right before their output. We define the next operation first:
|
|
|
+% \begingroup
|
|
|
% \begin{macrocode}
|
|
|
-\def\lst@Tokenize#1{\let\lst@next\lst@Tokenize%
|
|
|
+%<*kernel>
|
|
|
% \end{macrocode}
|
|
|
-% An incoming letter is gathered. If we found a nonletter, we output
|
|
|
-% the preceding text. The keyword test takes place there.
|
|
|
+% \endgroup
|
|
|
+% The introduction of this character class is due to a communication with \lsthelper{Rui Oliveira}{[email protected]}{1998/06/05}{escape characters}.
|
|
|
+%
|
|
|
+% \begin{macro}{\lstCC@Escape}
|
|
|
+% gets three arguments all in all.
|
|
|
+% The first is the escape character, the second is executed when the escape starts and the third right before ending it.
|
|
|
+% We use the same grouping mechanism as for \TeX\ comment lines.
|
|
|
% \begin{macrocode}
|
|
|
- \ifcat #1a%
|
|
|
- \edef\lst@text{\lst@text#1}\advance\lst@length\@ne %
|
|
|
- \else %
|
|
|
- \lst@Output %
|
|
|
+\def\lstCC@Escape#1{\lccode`\~=`#1\lowercase{\lstCC@Escape@~}}
|
|
|
+\def\lstCC@Escape@#1#2#3{%
|
|
|
+ \def#1{%
|
|
|
+ \lst@NewLine\lst@UseLostSpace \lst@PrintToken %
|
|
|
+ \lst@InterruptModes %
|
|
|
+ \lst@EnterMode{\lst@TeXmode}{\lst@modetrue}%
|
|
|
% \end{macrocode}
|
|
|
-% If the other character is a tabulator, we go to the next tab stop.
|
|
|
+% After doing the grouping we must define the character to end the escape.
|
|
|
% \begin{macrocode}
|
|
|
- \ifcat #1&\lst@GotoNextTabStop %
|
|
|
- \else %
|
|
|
+ \catcode`#1=\active %
|
|
|
+ \def#1{#3\lst@LeaveAllModes \lst@ReenterModes}%
|
|
|
+ #2}}
|
|
|
% \end{macrocode}
|
|
|
-% Getting to the terminator \cs{relax} ends tokenizing by defining
|
|
|
-% next operation empty, here \cs{relax}. Otherwise our next operation
|
|
|
-% is 'tokenizing' nonletter characters.
|
|
|
% \begin{macrocode}
|
|
|
- \ifx#1\relax \let\lst@next\relax %
|
|
|
- \else \let\lst@next\lst@TokenizeOther %
|
|
|
+\lst@NewMode\lst@TeXmode
|
|
|
% \end{macrocode}
|
|
|
-% If we are in comment mode, we have not to look for strings and gather
|
|
|
-% the nonletter character. Otherwise we look for stringizer. Then come
|
|
|
-% some closing \cs{fi}s and the next operation.
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{aspect}{escapechar}
|
|
|
+% This aspect defines |\lst@DefEsc|, which is executed after selecting the standard character table.
|
|
|
% \begin{macrocode}
|
|
|
- \lst@ifcomment \lst@length\z@ \lst@AppendOther#1%
|
|
|
- \else \lst@TestStringizer#1\fi %
|
|
|
- \fi %
|
|
|
- \fi \fi \lst@next}
|
|
|
+\lst@Aspect{escapechar}
|
|
|
+ {\ifx\@empty#1\@empty %
|
|
|
+ \let\lst@DefEsc\relax %
|
|
|
+ \else %
|
|
|
+ \def\lst@DefEsc{\lstCC@Escape{#1}\@empty\@empty}%
|
|
|
+ \fi}
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
+% \begin{macrocode}
|
|
|
+\lstset{escapechar={}}% init
|
|
|
+\lst@AddToHook{SelectCharTable}{\lst@DefEsc}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{aspect}
|
|
|
%
|
|
|
-% \begin{macro}{\lst@TokenizeOther}
|
|
|
-% This macro looks like \verb!lst@Tokenize! except that we have to
|
|
|
-% insert some \verb!\lst@OutputOther!.
|
|
|
+% \begin{aspect}{mathescape}
|
|
|
+% A switch tested after character table selection.
|
|
|
+% We use |\lstCC@Escape| with math shifts as arguments.
|
|
|
% \begin{macrocode}
|
|
|
-\def\lst@TokenizeOther#1{%
|
|
|
- \let\lst@next\lst@TokenizeOther %
|
|
|
- \ifcat #1a%
|
|
|
- \lst@OutputOther \let\lst@lastother\@empty %
|
|
|
- \def\lst@text{#1}\lst@length\@ne %
|
|
|
- \let\lst@next\lst@Tokenize %
|
|
|
- \else \ifcat #1&%
|
|
|
- \lst@OutputOther \lst@GotoNextTabStop %
|
|
|
- \else %
|
|
|
- \ifx#1\relax \lst@OutputOther \let\lst@next\relax %
|
|
|
+\lst@Aspect{mathescape}[t]{\lstKV@SetIfKey\lst@ifmathescape{#1}}
|
|
|
+\lstset{mathescape=false}% init
|
|
|
% \end{macrocode}
|
|
|
-% Now comes something new. If we find two successive blank spaces, we
|
|
|
-% output all preceding other characters first. This avoid alignment
|
|
|
-% problems when too many blanks follow each other.
|
|
|
-% The rest is unchanged.
|
|
|
% \begin{macrocode}
|
|
|
- \else \ifx\lst@lastother\lst@inputblank\if#1\lst@inputblank %
|
|
|
- \lst@OutputOther \fi\fi %
|
|
|
- \lst@ifcomment \lst@AppendOther#1%
|
|
|
- \else \lst@TestStringizer#1%
|
|
|
- \fi \fi %
|
|
|
- \fi \fi \lst@next}
|
|
|
+\lst@AddToHook{SelectCharTable}
|
|
|
+ {\lst@ifmathescape \lstCC@Escape{\$}{$}{$}\fi}
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
+% \end{aspect}
|
|
|
%
|
|
|
-% \begin{macro}{\lst@AppendOther}
|
|
|
-% This macro simply appends a character to the token register
|
|
|
-% \verb!\lst@other!.
|
|
|
+% \begin{macro}{\lst@DontEscapeToLaTeX}
|
|
|
+% This macro came in handy.
|
|
|
% \begin{macrocode}
|
|
|
-\def\lst@AppendOther#1{\advance\lst@length\@ne %
|
|
|
- \expandafter\lst@other\expandafter{\the\lst@other#1}}
|
|
|
+\def\lst@DontEscapeToLaTeX{%
|
|
|
+ \let\lst@iftexcl\iffalse %
|
|
|
+ \let\lst@DefEsc\relax %
|
|
|
+ \let\lst@ifmathescape\iffalse}
|
|
|
% \end{macrocode}
|
|
|
% \end{macro}
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%</kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+%
|
|
|
+%
|
|
|
+% \section{More \texttt{lst}-aspects and classes}
|
|
|
+%
|
|
|
%
|
|
|
-% \begin{macro}{\lst@bTestStringizer}
|
|
|
-% Here we do the stringizer tests. If a string already started, we
|
|
|
-% gather the current character and look for the closing stringizer.
|
|
|
-% If we've found it, we output \verb!\lst@other! and switch the
|
|
|
-% string boolean, but only if the preceding other character is not
|
|
|
-% a backslash (which inserts a stringizer at the current position
|
|
|
-% of the string).
|
|
|
+% \subsection{Form feeds}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
% \begin{macrocode}
|
|
|
-\def\lst@bTestStringizer#1{%
|
|
|
- \lst@ifstring \lst@AppendOther#1%
|
|
|
- \expandafter\ifx\lst@closing@stringizer#1%
|
|
|
- \ifx\lst@lastother\lst@inputbackslash \else %
|
|
|
- \lst@OutputOther \global\lst@stringfalse %
|
|
|
- \fi \fi %
|
|
|
- \def\lst@lastother{#1}%
|
|
|
+%<*kernel>
|
|
|
% \end{macrocode}
|
|
|
-% If we are not in string mode, we compare the current character with
|
|
|
-% all given stringizers and gather the character afterwards, since
|
|
|
-% the string boolean might changes and we might output the preceding
|
|
|
-% characters with a different style.
|
|
|
+% \endgroup
|
|
|
+% \begin{aspect}{formfeed}
|
|
|
+% We begin with the announcement --- the introduction is due to communication with \lsthelper{Jan Braun}{[email protected]}{1998/04/27}{\lstformfeed}.
|
|
|
% \begin{macrocode}
|
|
|
- \else %
|
|
|
- \def\lst@lastother{#1}%
|
|
|
- \expandafter\lst@DoStringizerTest\lst@stringizer\relax %
|
|
|
- \lst@AppendOther#1%
|
|
|
- \fi}
|
|
|
+\lst@Aspect{formfeed}{\def\lst@formfeed{#1}}
|
|
|
+\lstset{formfeed=\bigbreak}% init
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@AddToHook{SelectCharTable}{\lstCC@Let{`\^^L}\lstCC@FormFeed}
|
|
|
+% \end{macrocode}
|
|
|
+% \end{aspect}
|
|
|
%
|
|
|
-% \begin{macro}{\lst@dTestStringizer}
|
|
|
-% Nearly the same:
|
|
|
+% \begin{macro}{\lstCC@FormFeed}
|
|
|
+% Here we either execute some macros or append them to |\lst@NewLine|.
|
|
|
% \begin{macrocode}
|
|
|
-\def\lst@dTestStringizer#1{\def\lst@lastother{#1}%
|
|
|
- \lst@ifstring \lst@AppendOther#1%
|
|
|
- \ifx\lst@closing@stringizer\lst@lastother %
|
|
|
- \lst@OutputOther \global\lst@stringfalse %
|
|
|
- \fi %
|
|
|
+\def\lstCC@FormFeed{%
|
|
|
+ \lst@PrintToken %
|
|
|
+ \ifx\lst@NewLine\relax %
|
|
|
+ \lst@EOLUpdate \lst@formfeed %
|
|
|
\else %
|
|
|
- \expandafter\lst@DoStringizerTest\lst@stringizer\relax %
|
|
|
- \lst@AppendOther#1%
|
|
|
+ \lst@lAddTo\lst@NewLine{\lst@EOLUpdate \lst@formfeed}%
|
|
|
\fi}
|
|
|
% \end{macrocode}
|
|
|
% \end{macro}
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%</kernel>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
%
|
|
|
-% \begin{macro}{\lst@DoStringizerTest}
|
|
|
-% Now we consider a stringizer test. Reaching \cs{relax} results in
|
|
|
-% doing nothing and so terminating the tests.
|
|
|
+%
|
|
|
+% \subsection{\TeX\ control sequences}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%<*tex>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+% \begin{aspect}{texcs}
|
|
|
+% In general, it's the same as |keywords|, but control sequences are case sensitive, have a preceding backslash, \ldots
|
|
|
% \begin{macrocode}
|
|
|
-\def\lst@DoStringizerTest#1{%
|
|
|
- \ifx#1\relax \else %
|
|
|
+\lst@Aspect{texcs}{\def\lst@texcs{#1}}
|
|
|
+\lst@AddToHook{SetLanguage}{\let\lst@texcs\@empty}
|
|
|
% \end{macrocode}
|
|
|
-% Otherwise we compare the current character and the current stringizer.
|
|
|
-% If they are equal, we output the preceding characters, switch the
|
|
|
-% string boolean and save the stringizer as closing stringizer.
|
|
|
% \begin{macrocode}
|
|
|
- \expandafter\ifx\lst@lastother#1\relax %
|
|
|
- \lst@OutputOther \global\lst@stringtrue %
|
|
|
- \gdef\lst@closing@stringizer{#1}%
|
|
|
- \fi %
|
|
|
+\lst@AddToHook{Output}
|
|
|
+ {\lst@ifmode\else \ifx\lst@lastother\lst@backslash %
|
|
|
+ \expandafter\lst@IfOneOf\the\lst@token\relax \lst@texcs %
|
|
|
+ {\let\lst@thestyle\lst@keywordstyle}%
|
|
|
+ {\let\lst@thestyle\relax}%
|
|
|
+ \fi \fi}
|
|
|
% \end{macrocode}
|
|
|
-% At the end we call this macro again. The macro terminates reaching
|
|
|
-% the \cs{relax}!
|
|
|
+% \end{aspect}
|
|
|
+% \begingroup
|
|
|
% \begin{macrocode}
|
|
|
- \expandafter\lst@DoStringizerTest %
|
|
|
- \fi}%
|
|
|
+%</tex>
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
+% \endgroup
|
|
|
%
|
|
|
%
|
|
|
-% \subsection{Output}\label{ssOutput}
|
|
|
-% \begin{macro}{\lst@Output}
|
|
|
-% It's time to do text output. First we look, if there is anything to
|
|
|
-% output.
|
|
|
+% \subsection{Compiler directives in C}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
% \begin{macrocode}
|
|
|
-\def\lst@Output{%
|
|
|
- \ifx\lst@text\@empty\else %
|
|
|
+%<*c>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
+% \begin{aspect}{cdirectives}
|
|
|
+% First some usual stuff:
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@Aspect{cdirectives}
|
|
|
+ {\lst@MakeKeywordArg{,#1}\let\lst@cdirectives\lst@arg}
|
|
|
+\lst@AddToHook{SetLanguage}{\let\lst@cdirectives\relax}
|
|
|
+% \end{macrocode}
|
|
|
+% If the user has defined directives, we redefine the character |#| (but save the old meaning before):
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@AddToHook{SelectCharTable}
|
|
|
+ {\ifx\lst@cdirectives\relax\else %
|
|
|
+ \lccode`\~=`\#\lowercase{\let\lsts@CCD~\def~}%
|
|
|
+ {\lst@ifmode\else %
|
|
|
+% \end{macrocode}
|
|
|
+% We enter 'directive mode' only if we are in column 1.
|
|
|
+% Note that 'directive mode' is |\lst@egroupmode| without setting |\lst@ifmode| true.
|
|
|
+% \begin{macrocode}
|
|
|
+ \@tempcnta\lst@column %
|
|
|
+ \advance\@tempcnta\lst@length %
|
|
|
+ \advance\@tempcnta-\lst@pos %
|
|
|
+ \ifnum\@tempcnta=\z@ %
|
|
|
+ \lst@EnterMode{\lst@egroupmode}%
|
|
|
+ {\expandafter\lst@lAddTo\expandafter\lst@keywords%
|
|
|
+ \expandafter{\lst@cdirectives}}%
|
|
|
+ \fi %
|
|
|
+ \fi %
|
|
|
+ \ifnum\lst@mode=\lst@egroupmode %
|
|
|
+ {\lst@keywordstyle\lsts@CCD\lst@PrintToken}%
|
|
|
+ \else \lsts@CCD %
|
|
|
+ \fi}%
|
|
|
+ \fi}
|
|
|
% \end{macrocode}
|
|
|
-% Then we decide, whether to make a stringbox (using stringstyle) or
|
|
|
-% a box for a comment (using commentstyle as explicit parameter).
|
|
|
+% \end{aspect}
|
|
|
+% \begingroup
|
|
|
% \begin{macrocode}
|
|
|
- \lst@ifstring \lst@MakeStringBox{\lst@stringstyle}\else %
|
|
|
- \lst@ifcomment\lst@MakeBox{\lst@commentstyle}\else %
|
|
|
+%</c>
|
|
|
% \end{macrocode}
|
|
|
-% If we output neither a string nor a comment, we look for a keyword.
|
|
|
-% The output takes place in the macro \verb!\lst@KeywordsOrNot!
|
|
|
-% (see section \ref{sLanguageDriverFiles}). \cs{relax} terminates the
|
|
|
-% text parameter.
|
|
|
+% \endgroup
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{PODs in Perl}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
% \begin{macrocode}
|
|
|
- \expandafter\lst@KeywordOrNot\lst@text\relax %
|
|
|
- \fi \fi %
|
|
|
+%<*perl>
|
|
|
% \end{macrocode}
|
|
|
-% Finally we hold up the current column, empty the text and close the
|
|
|
-% starting 'if text not empty'.
|
|
|
+% \endgroup
|
|
|
+% \begin{aspect}{printpod}
|
|
|
+% We begin with two user commands, which I introduced after communication with \lsthelper{Michael Piotrowski}{[email protected]}{1997/11/11}{\lstprintpodtrue/false}.
|
|
|
% \begin{macrocode}
|
|
|
- \global\advance\lst@pos by -\lst@length %
|
|
|
- \let\lst@text\@empty \lst@length0 %
|
|
|
- \fi}
|
|
|
+\lst@Aspect{printpod}[t]{\lstKV@SetIfKey\lst@ifprintpod{#1}}
|
|
|
+\lstset{printpod=false}% init
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
+% \end{aspect}
|
|
|
%
|
|
|
-% \begin{macro}{\lst@OutputOther}
|
|
|
-% To output the characters from the token register \verb!\lst@other!,
|
|
|
-% we assign these characters to a macro. The rest is the same as in
|
|
|
-% \verb!\lst@Output!, except that we need no keyword tests and make
|
|
|
-% a normal box instead.
|
|
|
+% \begin{macro}{\lst@PODmode}
|
|
|
+% Define a new mode and use |\global| since we are (possibly) in a driver file and thus inside a group.
|
|
|
% \begin{macrocode}
|
|
|
-\def\lst@OutputOther{%
|
|
|
- \expandafter\def\expandafter\lst@text\expandafter{\the\lst@other}%
|
|
|
- \ifx\lst@text\@empty\else %
|
|
|
- \lst@ifstring \lst@MakeStringBox{\lst@stringstyle}\else %
|
|
|
- \lst@ifcomment\lst@MakeBox{\lst@commentstyle}\else %
|
|
|
- \lst@MakeBox{}%
|
|
|
- \fi \fi %
|
|
|
- \global\advance\lst@pos by -\lst@length %
|
|
|
- \lst@other{}\let\lst@text\@empty \lst@length0 %
|
|
|
- \fi}
|
|
|
+\global\lst@NewMode\lst@PODmode
|
|
|
% \end{macrocode}
|
|
|
% \end{macro}
|
|
|
%
|
|
|
-% \begin{macro}{\lst@MakeBox}
|
|
|
-% Consider the different boxes now. A box must take \verb!\lst@length!
|
|
|
-% characters: the width is \verb!\lst@length!$\cdot$\verb!\lst@width!.
|
|
|
-% The macro parameter possibly selects another style. We insert dynamic
|
|
|
-% space at the beginning (and at the ending) to center the text and we
|
|
|
-% fill the box. Again \cs{relax} is a brake.
|
|
|
+% \begin{macro}{\lstCC@PODcut}
|
|
|
+% We'll need the active character string |cut|:
|
|
|
% \begin{macrocode}
|
|
|
-\def\lst@MakeBox#1{%
|
|
|
- \hbox to \lst@length\lst@width{#1\hss %
|
|
|
- \expandafter\lst@FillBox\lst@text\relax \hss}}
|
|
|
+\lst@MakeActive{cut}\global\let\lstCC@PODcut\lst@arg %
|
|
|
% \end{macrocode}
|
|
|
% \end{macro}
|
|
|
%
|
|
|
-% \begin{macro}{\lst@FillBox}
|
|
|
-% Filling up a box is easy. If we found the end of the text, we do
|
|
|
-% nothing. Otherwise we output the character and insert dynamic space.
|
|
|
-% Since the underbar is not a printable character in \TeX{}, we have
|
|
|
-% to treat it special. By the way: We make the underbar having the
|
|
|
-% letter catcode here; we don't want subscripts. After all this is
|
|
|
-% done, we call the fillbox macro again.
|
|
|
-% Note: The macro is called after the closing \cs{fi}!
|
|
|
+% \begin{macro}{\lstCC@ProcessPOD}
|
|
|
+% And now the POD character class; only |=| will belong to it.
|
|
|
+% If we are in column 1 \ldots
|
|
|
% \begin{macrocode}
|
|
|
-\begingroup
|
|
|
-\catcode`\_=11
|
|
|
-\gdef\lst@FillBox#1{%
|
|
|
- \ifx\relax#1\else %
|
|
|
- \ifx#1_\textunderscore \else #1\fi \hss %
|
|
|
- \expandafter\lst@FillBox %
|
|
|
- \fi}
|
|
|
-\endgroup
|
|
|
+\gdef\lstCC@ProcessPOD{%
|
|
|
+ \let\lstCC@next\relax %
|
|
|
+ \@tempcnta\lst@column %
|
|
|
+ \advance\@tempcnta\lst@length %
|
|
|
+ \advance\@tempcnta-\lst@pos %
|
|
|
+ \ifnum\@tempcnta=\z@ %
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
-%
|
|
|
-% \begin{macro}{\lst@MakeSpecialStringBox}
|
|
|
-% A stringbox is nearly the same: We only let the 'normal blank' be
|
|
|
-% '\textvisiblespace'.
|
|
|
+% and if we are already in POD mode, we either end it or proceed according to whether next characters are |cut| or not.
|
|
|
% \begin{macrocode}
|
|
|
-\def\lst@MakeSpecialStringBox#1{%
|
|
|
- \hbox to\lst@length\lst@width{\let\lst@outputblank\textvisiblespace%
|
|
|
- #1\hss \expandafter\lst@FillBox\lst@text\relax \hss}}
|
|
|
+ \ifnum\lst@mode=\lst@PODmode %
|
|
|
+ \def\lstCC@next{\lst@IfNextChars\lstCC@PODcut %
|
|
|
+ {\lstCC@ProcessEndPOD}%
|
|
|
+ {\lsts@POD\lst@eaten}}%
|
|
|
+ \else %
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
-%
|
|
|
-% \begin{macro}{\lst@OutputChar}
|
|
|
-% We define one more macro to save time. It outputs a single character.
|
|
|
-% The implementation should be clear.
|
|
|
+% If we are in column 1 and not in POD mode, we either start a usual comment or drop the output.
|
|
|
% \begin{macrocode}
|
|
|
-\def\lst@OutputChar#1{\global\advance\lst@pos by -1%
|
|
|
- \hbox to \lst@width{\hss %
|
|
|
- \lst@ifstring \def\lst@text{#1}\lst@length\@ne %
|
|
|
- \lst@MakeStringBox{\lst@stringstyle}%
|
|
|
- \else \lst@ifcomment \lst@commentstyle#1\hss %
|
|
|
- \else #1\hss %
|
|
|
- \fi \fi}}
|
|
|
+ \lst@ifprintpod %
|
|
|
+ \lstCC@BeginComment\lst@PODmode %
|
|
|
+ \else %
|
|
|
+ \lst@BeginDropOutput\lst@PODmode %
|
|
|
+ \fi %
|
|
|
+ \let\lstCC@next\lsts@POD %
|
|
|
+ \fi %
|
|
|
+ \fi \lstCC@next}%
|
|
|
% \end{macrocode}
|
|
|
% \end{macro}
|
|
|
%
|
|
|
-% \begin{macro}{\lst@GotoNextTabStop}
|
|
|
-% At the end of this section we consider tabulators. As seen, each
|
|
|
-% typeset character decrements the counter \verb!\lst@pos!. To go to
|
|
|
-% the next tabulator stop, we must first determine how many blanks are
|
|
|
-% needed. We simply add \verb!\lst@tablength! until \verb!\lst@pos!
|
|
|
-% is strict positive.
|
|
|
+% \begin{macro}{\lstCC@ProcessEndPOD}
|
|
|
+% If the character behind |=cut| is neither |^^M| nor |^^J|, we don't end the POD.
|
|
|
% \begin{macrocode}
|
|
|
-\def\lst@GotoNextTabStop{%
|
|
|
- \@whilenum \lst@pos<1 \do %
|
|
|
- {\global\advance\lst@pos\lst@tablength}%
|
|
|
+\gdef\lstCC@ProcessEndPOD#1{%
|
|
|
+ \let\lstCC@next\lstCC@ProcessEndPOD@ %
|
|
|
+ \ifnum`#1=`\^^M\else \ifnum`#1=`\^^J\else %
|
|
|
+ \def\lstCC@next{\lsts@POD\lst@eaten#1}%
|
|
|
+ \fi \fi %
|
|
|
+ \lstCC@next}
|
|
|
% \end{macrocode}
|
|
|
-% Now we make a box having the width of \verb!\lst@pos! characters and
|
|
|
-% set \verb!\lst@pos! to zero.
|
|
|
+% The ending actions depend on |\lst@ifprintpod|: Print |=cut| (or not) and end the POD.
|
|
|
% \begin{macrocode}
|
|
|
- \hbox to \lst@pos\lst@width{\hss}\lst@pos0}%
|
|
|
+\gdef\lstCC@ProcessEndPOD@{%
|
|
|
+ \lst@ifprintpod \lsts@POD\lst@eaten\lst@PrintToken \fi %
|
|
|
+ \lst@LeaveMode}
|
|
|
% \end{macrocode}
|
|
|
% \end{macro}
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%</perl>
|
|
|
+% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
%
|
|
|
%
|
|
|
-% \subsection{Special characters}\label{ssSpecialCharacters}
|
|
|
-% Some definitions of special characters:
|
|
|
+% \subsection{Special use of \texttt{\#} in Perl}
|
|
|
+%
|
|
|
+% \begingroup
|
|
|
% \begin{macrocode}
|
|
|
-\def\lst@leftbrace{$\{$}
|
|
|
-\def\lst@rightbrace{$\}$}
|
|
|
-\def\lst@less{$<$}
|
|
|
-\def\lst@greater{$>$}
|
|
|
-\def\lst@verticalbar{$|$}
|
|
|
-\def\lst@minus{$-$}
|
|
|
-\def\lst@multiply{$*$}
|
|
|
+%<*perl>
|
|
|
% \end{macrocode}
|
|
|
-%
|
|
|
-% \begin{macro}{\lst@MakeDigitsLetter}
|
|
|
-% This macro is similar to \cs{makeatletter}.
|
|
|
+% \endgroup
|
|
|
+% \begin{macro}{\lstCC@SpecialUseAfter}
|
|
|
+% We need |#| not to begin a comment in Perl if it follows |$|.
|
|
|
+% We'll define a special use of |#| after |$| via |\lstCC@SpecialUseAfter{\$}{\#}{\lstCC@ProcessOther\#}| where the third argument is executed coming to |$#|.
|
|
|
+% Note that the submacro gets two of the three arguments.
|
|
|
% \begin{macrocode}
|
|
|
-\def\lst@MakeDigitsLetter{\catcode`\0=11\catcode`\1=11%
|
|
|
- \catcode`\2=11\catcode`\3=11\catcode`\4=11\catcode`\5=11%
|
|
|
- \catcode`\6=11\catcode`\7=11\catcode`\8=11\catcode`\9=11}
|
|
|
+\gdef\lstCC@SpecialUseAfter#1{%
|
|
|
+ \lccode`\~=`#1\lccode`\/=`#1\lowercase{\lstCC@SpecialUseAfter@~/}}
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
-%
|
|
|
-% \begin{macro}{\lst@DefineCatcodes}
|
|
|
-% At the moment only the catcode of $-$ is language specific.
|
|
|
-% This macro stores such values.
|
|
|
+% We save the old meaning of the first character (|$|) and redefine it to check for the character |#3|.
|
|
|
% \begin{macrocode}
|
|
|
-\def\lst@DefineCatcodes#1{%
|
|
|
- \def\lst@ChangeMoreCatcodes{\catcode`\-=#1}}
|
|
|
+\gdef\lstCC@SpecialUseAfter@#1#2#3#4{%
|
|
|
+ \expandafter\let\csname lsts@SUA#2\endcsname#1%
|
|
|
+ \def#1##1{%
|
|
|
+ \ifnum`##1=`#3%
|
|
|
+ \def\lstCC@next{\csname lsts@SUA#3\endcsname\relax #4}%
|
|
|
+ \else %
|
|
|
+ \def\lstCC@next{\csname lsts@SUA#3\endcsname ##1}%
|
|
|
+ \fi %
|
|
|
+ \lstCC@next}}
|
|
|
% \end{macrocode}
|
|
|
% \end{macro}
|
|
|
-%
|
|
|
-% \begin{macro}{\lst@ChangeCatcodes}
|
|
|
-% Now begins the horrible part: It is necessary to change many
|
|
|
-% catcodes. Since we need backslash and braces with other meanings,
|
|
|
-% we replace them by the slash $/$, $($ and $)$. Other characters like
|
|
|
-% \$ and \& need not to be replaced, because we don't need them for
|
|
|
-% defining macros, but $\backslash$, $\{$ and $\}$ are essential for
|
|
|
-% doing that.
|
|
|
+% \begingroup
|
|
|
% \begin{macrocode}
|
|
|
-\begingroup
|
|
|
-\catcode `/=0 \catcode `(= 1 \catcode `)=2 % new \, { and }
|
|
|
-\catcode`\<=\active \catcode`\>=\active \catcode`\|=\active
|
|
|
-\catcode`\-=\active \catcode`\*=\active
|
|
|
-\catcode`\{=\active \catcode`\}=\active \catcode`\\=\active
|
|
|
-% \end{macrocode}
|
|
|
-% From now on we must use the slash and $()$ instead of backslash and
|
|
|
-% braces. Since the blank space will also be an active character, we
|
|
|
-% must terminate each line with a comment character. Otherwise \TeX{}
|
|
|
-% would think, we want to typeset something before beginning the
|
|
|
-% document.
|
|
|
-% \SpecialEscapechar/
|
|
|
-% \begin{macrocode}
|
|
|
-/gdef/lst@inputbackslash(\)%
|
|
|
-/catcode`/ =/active%
|
|
|
-/gdef/lst@inputblank( )%
|
|
|
-/gdef/lst@outputblank(/ )%
|
|
|
-% \end{macrocode}
|
|
|
-% The following macro changes catcodes and the definition of active
|
|
|
-% characters at the time we input a listing.
|
|
|
-% \SpecialEscapechar/
|
|
|
-% \begin{macrocode}
|
|
|
-/gdef/lst@ChangeCatcodes(%
|
|
|
-/catcode`/ =/active/def (/lst@outputblank)%
|
|
|
-/catcode`/\=/active/def\($/backslash$)%
|
|
|
-/catcode`/{=/active/def{(/lst@leftbrace)%
|
|
|
-/catcode`/}=/active/def}(/lst@rightbrace)%
|
|
|
-/catcode`/<=/active/def<(/lst@less)%
|
|
|
-/catcode`/>=/active/def>(/lst@greater)%
|
|
|
-/catcode`/|=/active/def|(/lst@verticalbar)%
|
|
|
-/catcode`/-=/active/def-(/lst@minus)%
|
|
|
-/catcode`/*=/active/def*(/lst@multiply)%
|
|
|
-/chardef~="7E%
|
|
|
-% \end{macrocode}
|
|
|
-% A tabulator (ASCII code 9=ord(I)$-$64) gets the catcode of a
|
|
|
-% \TeX{}-tabulator.
|
|
|
-% \SpecialEscapechar/
|
|
|
-% \begin{macrocode}
|
|
|
-/catcode`/^^I=4%
|
|
|
-% \end{macrocode}
|
|
|
-% Some characters are treated as other characters (12) or as letters
|
|
|
-% (11).
|
|
|
-% \SpecialEscapechar/
|
|
|
-% \begin{macrocode}
|
|
|
-/catcode`/$=11/catcode`/_=11/lst@MakeDigitsLetter%
|
|
|
-/catcode`/&=12/catcode`/^=12/catcode`/"=12/catcode`/#=12%
|
|
|
-/chardef/lst@ccPercent=/catcode`/%/catcode`/%=12% save catcode
|
|
|
-/lst@ChangeMoreCatcodes/makeatletter)%
|
|
|
-/endgroup
|
|
|
-% \end{macrocode}
|
|
|
-% All changed catcodes (time of definition) are restored by ending the
|
|
|
-% group.
|
|
|
-% \end{macro}
|
|
|
-%
|
|
|
-%
|
|
|
-% \subsection{Initialization}\label{ssInitialization}
|
|
|
-% Defaults are selected and the options are processed.
|
|
|
-% \begin{macrocode}
|
|
|
-\normallisting
|
|
|
-\listingtrue
|
|
|
-\tablength{4}
|
|
|
-\lstlineskip{0pt}
|
|
|
-\selectlisting{blank}
|
|
|
-\ProcessOptions
|
|
|
-%</package>
|
|
|
+%</perl>
|
|
|
% \end{macrocode}
|
|
|
+% \endgroup
|
|
|
%
|
|
|
%
|
|
|
-% \section{Language driver files}\label{sLanguageDriverFiles}
|
|
|
-% Each driver file contains language specific data:
|
|
|
-% \begin{itemize}
|
|
|
-% \item keywords,
|
|
|
-% \item whether the language is case sensitive or not,
|
|
|
-% \item information about comment lines and other comments,
|
|
|
-% \item the stringizer,
|
|
|
-% \item baseem --- the width of a single character box,
|
|
|
-% \item the catcode of the minus $-$,
|
|
|
-% \item \verb!\lst@PrePL! and \verb!\lst@PostPL! are executed before and
|
|
|
-% after the real line processing takes place: \verb!\lst@PrePL! is
|
|
|
-% intend to manipulate the input, e.g.\ Fortran uses it to detect
|
|
|
-% comment lines beginning with '$*$' or 'C' and Eiffel's string
|
|
|
-% concatenate mechanism is done there, and e.g.\ \verb!\lst@PostPL!
|
|
|
-% might gives a warning, if a string exceeds a line.
|
|
|
-% \end{itemize}
|
|
|
-% The package selects a language by calling \verb!\lstdrv@#1@!, where
|
|
|
-% \verb!#1! is replaced by the language. Additionally the language option
|
|
|
-% (empty or not) is used as suffix, e.g.\ \verb!\lstdrv@cobol@1974!.
|
|
|
-% That macro must support the described things.
|
|
|
-%
|
|
|
-% Some driver files use own data. To setup things like that the macro
|
|
|
-% \verb!\lstdrv@#1@PrepareListing! is called \emph{after} all init
|
|
|
-% of the kernel is done (changing catcodes, e.g.). Here \verb!#1!
|
|
|
-% is replaced by the language again. If no special setup is needed,
|
|
|
-% a driver file need not to define that macro.
|
|
|
-%
|
|
|
-% The implemented languages follow as examples.
|
|
|
-% '\texttt{???}' in driver files indicate things I don't know.
|
|
|
-%
|
|
|
-%
|
|
|
-% \subsection{Blank listing}
|
|
|
-% \begin{macro}{\lstdrv@blank@}
|
|
|
-% For a blank listing we let all empty. \cs{makeatletter} lets \verb!@!
|
|
|
-% be a letter here. Otherwise we can't access \verb!\lstdrv@blank@!.
|
|
|
-% \begin{macrocode}
|
|
|
-%<*blank>
|
|
|
-\begingroup \makeatletter %
|
|
|
-\gdef\lstdrv@blank@{%
|
|
|
- \keywords{}%
|
|
|
- \sensitivetrue %
|
|
|
- \DeclareCommentLine\relax %
|
|
|
- \DeclareSingleComment stuff \relax %
|
|
|
- \stringizer{}\lstbaseem{0.6}%
|
|
|
- \lst@DefineCatcodes{\active}%
|
|
|
- \let\lst@PrePL \lst@PrePLDefault %
|
|
|
- \let\lst@PostPL\lst@PostPLDefault}%
|
|
|
-\endgroup %
|
|
|
-%</blank>
|
|
|
-% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
-%
|
|
|
-%
|
|
|
-% \subsection{Ada}
|
|
|
-% \begin{macro}{\lstdrv@ada@}
|
|
|
-% Keywords, comments, \ldots{}
|
|
|
-% The catcode of the double quote is changed for compatibility with
|
|
|
-% \texttt{german.sty}.
|
|
|
-% \begin{macrocode}
|
|
|
-%<*ada>
|
|
|
-\begingroup \makeatletter %
|
|
|
-\catcode`\"=12 \catcode`\-=\active %
|
|
|
-\gdef\lstdrv@ada@{%
|
|
|
- \keywords{abort,abs,accept,access,all,and,array,at,begin,body,%
|
|
|
- case,constant,declare,delay,delta,digits,do,else,elsif,end,%
|
|
|
- entry,exception,exit,for,function,generic,goto,if,in,is,%
|
|
|
- limited,loop,mod,new,not,null,of,or,others,out,package,pragma,%
|
|
|
- private,procedure,raise,range,record,rem,renames,return,%
|
|
|
- reverse,select,separate,subtype,task,terminate,then,type,%
|
|
|
- use,when,while,with,xor}%
|
|
|
- \sensitivefalse %
|
|
|
- \DeclareCommentLine --\relax %
|
|
|
- \DeclareSingleComment stuff \relax %
|
|
|
- \stringizer[d]{"'}\lstbaseem{0.6}% ??? stringizer doubled
|
|
|
- \lst@DefineCatcodes{\active}%
|
|
|
- \let\lst@PrePL \lst@PrePLDefault %
|
|
|
- \let\lst@PostPL\lst@PostPLDefault}%
|
|
|
-\endgroup %
|
|
|
-%</ada>
|
|
|
-% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
-%
|
|
|
-%
|
|
|
-% \subsection{Algol}
|
|
|
-% \begin{macro}{\lstdrv@algol@}
|
|
|
-% The main driver macro.
|
|
|
-% \begin{macrocode}
|
|
|
-%<*algol>
|
|
|
-\begingroup \makeatletter %
|
|
|
-\catcode`\#=12 %
|
|
|
-\gdef\lstdrv@algol@{% ??? should 'i' be a keyword
|
|
|
- \keywords{abs,and,arg,begin,bin,bits,bool,by,bytes,case,channel,%
|
|
|
- char,co,comment,compl,conj,divab,do,down,elem,elif,else,empty,%
|
|
|
- end,entier,eq,esac,exit,false,fi,file,flex,for,format,from,%
|
|
|
- ge,goto,gt,heap,if,im,in,int,is,isnt,le,leng,level,loc,long,%
|
|
|
- lt,lwb,minusab,mod,modab,mode,ne,nil,not,od,odd,of,op,or,ouse,%
|
|
|
- out,over,overab,par,plusab,plusto,pr,pragmat,prio,proc,re,real,%
|
|
|
- ref,repr,round,sema,shl,short,shorten,shr,sign,skip,string,%
|
|
|
- structthen,timesab,to,true,union,up,upb,void,while}%
|
|
|
- \sensitivefalse % ???
|
|
|
- \DeclareCommentLine\relax %
|
|
|
- \DeclarePairedComment #\relax %
|
|
|
- \stringizer{}\lstbaseem{0.6}%
|
|
|
- \lst@DefineCatcodes{\active}%
|
|
|
- \let\lst@PrePL \lst@PrePLDefault %
|
|
|
- \let\lst@PostPL\lst@PostPLDefault}%
|
|
|
-% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
-%
|
|
|
-% \begin{macro}{\lstdrv@algol@68}
|
|
|
-% \begin{macro}{\lstdrv@algol@60}
|
|
|
-% Macros for the optional argument:
|
|
|
-% \begin{macrocode}
|
|
|
-\global\@namedef{lstdrv@algol@68}{\lstdrv@algol@}%
|
|
|
-\global\@namedef{lstdrv@algol@60}{\lstdrv@algol@ %
|
|
|
- \keywords{array,begin,Boolean,code,comment,div,do,else,end,false,%
|
|
|
- for,goto,if,integer,label,own,power,procedure,real,step,string,%
|
|
|
- switch,then,true,until,value,while}%
|
|
|
- \DeclareSingleComment stuff \relax}%
|
|
|
-\endgroup %
|
|
|
-% \end{macrocode}
|
|
|
-% \end{macro}\end{macro}
|
|
|
-%
|
|
|
-% \begin{macro}{\lstdrv@algol@PrepareListing}
|
|
|
-% To implement comments beginning with \verb!comment! or \verb!co!
|
|
|
-% we must go deep inside this package again. We need an additional
|
|
|
-% 'ifcomment' and define Algol's Prepare\-Listing to override the
|
|
|
-% default output macros.
|
|
|
-% \begin{macrocode}
|
|
|
-\begingroup \makeatletter %
|
|
|
-\gdef\lstdrv@algol@commenttrue{%
|
|
|
- \global\let\lstdrv@algol@ifcomment\iftrue}%
|
|
|
-\gdef\lstdrv@algol@commentfalse{%
|
|
|
- \global\let\lstdrv@algol@ifcomment\iffalse %
|
|
|
- \global\let\lstdrv@algol@closingcomment\@empty}%
|
|
|
-\gdef\lstdrv@algol@PrepareListing{%
|
|
|
- \lstdrv@algol@commentfalse %
|
|
|
- \let\lst@OutputOther\lstdrv@algol@OutputOther %
|
|
|
- \lst@ifoption{60}{\let\lst@Output\lstdrv@algol@Output@ %
|
|
|
- \let\lst@AppendOther\lstdrv@algol@AppendOther}%
|
|
|
- {\let\lst@Output\lstdrv@algol@Output}}%
|
|
|
-% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
-%
|
|
|
-% \begin{macro}{\lstdrv@algol@OutputOther}
|
|
|
-% This macro is a simple derivation of \verb!\lst@OutputOther!. The only
|
|
|
-% difference is that we test Algol's additional 'ifcomment' (4th line).
|
|
|
-% \begin{macrocode}
|
|
|
-\gdef\lstdrv@algol@OutputOther{%
|
|
|
- \expandafter\def\expandafter\lst@text\expandafter{\the\lst@other}%
|
|
|
- \ifx\lst@text\@empty\else %
|
|
|
- \lstdrv@algol@ifcomment\lst@MakeBox{\lst@commentstyle}\else %
|
|
|
- \lst@ifstring \lst@MakeStringBox{\lst@stringstyle}\else %
|
|
|
- \lst@ifcomment\lst@MakeBox{\lst@commentstyle}\else %
|
|
|
- \lst@MakeBox{}%
|
|
|
- \fi \fi \fi %
|
|
|
- \global\advance\lst@pos by -\lst@length %
|
|
|
- \lst@other{}\let\lst@text\@empty \lst@length0 %
|
|
|
- \fi}%
|
|
|
-% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
+% \section{Epilogue}
|
|
|
%
|
|
|
-% \begin{macro}{\lstdrv@algol@Output}
|
|
|
-% Here we also install an additional 'ifcomment'. If we are in comment
|
|
|
-% mode, we look whether the comment is over or not.
|
|
|
+% \begingroup
|
|
|
% \begin{macrocode}
|
|
|
-\gdef\lstdrv@algol@Output{%
|
|
|
- \ifx\lst@text\@empty\else %
|
|
|
- \lstdrv@algol@ifcomment %
|
|
|
- \ifx\lst@text\lstdrv@algol@closingcomment %
|
|
|
- \lstdrv@algol@commentfalse %
|
|
|
- \lst@MakeBox{\lst@keywordstyle}%
|
|
|
- \else \lst@MakeBox{\lst@commentstyle}%
|
|
|
- \fi \else %
|
|
|
+%<*kernel>
|
|
|
% \end{macrocode}
|
|
|
-% The next three lines are unchanged.
|
|
|
+% \endgroup
|
|
|
+% Most initialization has already been done, see all |% init| marked lines.
|
|
|
+% Here is more:
|
|
|
% \begin{macrocode}
|
|
|
- \lst@ifstring \lst@MakeStringBox{\lst@stringstyle}\else %
|
|
|
- \lst@ifcomment\lst@MakeBox{\lst@commentstyle}\else %
|
|
|
- \expandafter\lst@KeywordOrNot\lst@text\relax %
|
|
|
+\lstset{labelsep=5pt,sensitive=true}
|
|
|
+\lstdefinelanguage{}{}
|
|
|
+\lstdefinestyle{}
|
|
|
+ {basicstyle={},%
|
|
|
+ keywordstyle=\bfseries,nonkeywordstyle={},%
|
|
|
+ commentstyle=\itshape,stringstyle={},%
|
|
|
+ labelstyle={},labelstep=0}
|
|
|
+\lst@mode=\z@
|
|
|
+\lstset{language={},style={}}
|
|
|
% \end{macrocode}
|
|
|
-% After the keyword (or non-keyword) is output, we look if a comment
|
|
|
-% starts: If the current text equals \verb!co! or \verb!comment!, we
|
|
|
-% enter comment mode and set the closing comment delimiter.
|
|
|
+% Finally we load compatibility mode, a patch file and the configuration file.
|
|
|
% \begin{macrocode}
|
|
|
- \expandafter\lst@ifoneof\lst@text\relax{comment,co}%
|
|
|
- {\global\let\lstdrv@algol@closingcomment\lst@text}{}%
|
|
|
+\@ifundefined{[email protected]}{}{\input{lst017.sty}}
|
|
|
+\InputIfFileExists{lstpatch.sty}{}{}
|
|
|
+\InputIfFileExists{listings.cfg}{}{}
|
|
|
% \end{macrocode}
|
|
|
-% The rest is unchanged.
|
|
|
+% \begingroup
|
|
|
% \begin{macrocode}
|
|
|
- \fi \fi \fi %
|
|
|
- \global\advance\lst@pos by -\lst@length %
|
|
|
- \let\lst@text\@empty \lst@length0 %
|
|
|
- \fi}%
|
|
|
+%</kernel>
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
+% \endgroup
|
|
|
+%
|
|
|
+%
|
|
|
+% \section{Interfaces to other packages}
|
|
|
+%
|
|
|
+%
|
|
|
+% \subsection{Compatibility mode}
|
|
|
%
|
|
|
-% \begin{macro}{\lstdrv@algol@Output@}
|
|
|
-% Now we come to Algol 60. First comes the same as above. But:
|
|
|
-% An empty 'closingcomment' indicates that no \verb!end! and no
|
|
|
-% \verb!else! closes a comment, i.e.\ we look first whether 'end
|
|
|
-% of comment' tests are legal or not.
|
|
|
+% \begingroup
|
|
|
% \begin{macrocode}
|
|
|
-\gdef\lstdrv@algol@Output@{%
|
|
|
- \ifx\lst@text\@empty\else %
|
|
|
- \lstdrv@algol@ifcomment %
|
|
|
- \ifx\@empty\lstdrv@algol@closingcomment %
|
|
|
- \lst@MakeBox{\lst@commentstyle}%
|
|
|
- \else %
|
|
|
- \expandafter\lst@ifoneof\lst@text\relax{else,end}%
|
|
|
- {\lstdrv@algol@commentfalse %
|
|
|
- \lst@MakeBox{\lst@keywordstyle}}%
|
|
|
- {\lst@MakeBox{\lst@commentstyle}}%
|
|
|
- \fi \else %
|
|
|
-% \end{macrocode}
|
|
|
-% The next three lines are unchanged.
|
|
|
-% \begin{macrocode}
|
|
|
- \lst@ifstring \lst@MakeStringBox{\lst@stringstyle}\else %
|
|
|
- \lst@ifcomment\lst@MakeBox{\lst@commentstyle}\else %
|
|
|
- \expandafter\lst@KeywordOrNot\lst@text\relax %
|
|
|
-% \end{macrocode}
|
|
|
-% After the keyword (or non-keyword) is output, we look if a comment
|
|
|
-% starts: If the current text equals \verb!comment!, we enter the
|
|
|
-% comment mode and let \verb!\lstdrv@algol@closingcomment! empty;
|
|
|
-% if the text equals \verb!end!, we let 'closingcomment' not empty,
|
|
|
-% i.e.\ the comment may closes with \verb!else! or \verb!end!
|
|
|
-% (see above).
|
|
|
-% \begin{macrocode}
|
|
|
- \expandafter\lst@ifoneof\lst@text\relax{comment,end}%
|
|
|
- {\lstdrv@simula@commenttrue %
|
|
|
- \expandafter\lst@ifoneof\lst@text\relax{end}%
|
|
|
- {\gdef\lstdrv@simula@closingcomment{a}}{}}%
|
|
|
- {}% empty else from 'ifoneof'
|
|
|
-% \end{macrocode}
|
|
|
-% The rest is unchanged.
|
|
|
-% \begin{macrocode}
|
|
|
- \fi \fi \fi %
|
|
|
- \global\advance\lst@pos by -\lst@length %
|
|
|
- \let\lst@text\@empty \lst@length0 %
|
|
|
- \fi}%
|
|
|
+%<*0.17>
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
-%
|
|
|
-% \begin{macro}{\lstdrv@algol@AppendOther@}
|
|
|
-% A semicolon also ends a comment. Hence:
|
|
|
+% \endgroup
|
|
|
+% We give a warning first.
|
|
|
% \begin{macrocode}
|
|
|
-\gdef\lstdrv@algol@AppendOther#1{%
|
|
|
- \lstdrv@algol@ifcomment \if;#1%
|
|
|
- \lst@OutputOther \lstdrv@algol@commentfalse %
|
|
|
- \fi \fi %
|
|
|
- \advance\lst@length\@ne %
|
|
|
- \expandafter\lst@other\expandafter{\the\lst@other#1}}%
|
|
|
-\endgroup %
|
|
|
-%</algol>
|
|
|
+\message{^^J%
|
|
|
+*** You have requested compatibility mode `0.17'.^^J%
|
|
|
+*** This mode is for documents created for version 0.17 only.^^J%
|
|
|
+*** I T\@spaces I S\@spaces N O T\@spaces F U L L Y\@spaces %
|
|
|
+C O M P A T I B L E.^^J^^J}
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
%
|
|
|
%
|
|
|
-% \subsection{C}
|
|
|
-% \begin{macro}{\lstdrv@c@}
|
|
|
-% Since $*$ will be an active character when we input a listing, we
|
|
|
-% have to change the catcode here.
|
|
|
+% \paragraph{Language names.}
|
|
|
+%
|
|
|
+% Since some programming languages changed their names, we define aliases here.
|
|
|
% \begin{macrocode}
|
|
|
-%<*c>
|
|
|
-\begingroup \makeatletter %
|
|
|
-\catcode`\"=12 \catcode`\*=\active %
|
|
|
-\gdef\lstdrv@c@{%
|
|
|
- \keywords{auto,break,case,char,const,continue,default,do,double,%
|
|
|
- else,enum,extern,float,for,goto,if,int,long,register,return,%
|
|
|
- short,signed,sizeof,static,struct,switch,typedef,union,%
|
|
|
- unsigned,void,volatile,while}%
|
|
|
- \sensitivetrue %
|
|
|
- \DeclareCommentLine\relax %
|
|
|
- \DeclareSingleComment /* */\relax %
|
|
|
- \stringizer[b]{"}\lstbaseem{0.6}%
|
|
|
- \lst@DefineCatcodes{\active}%
|
|
|
- \let\lst@PrePL \lstdrv@c@PrePL %
|
|
|
- \let\lst@PostPL\lst@PostPLDefault}%
|
|
|
-\endgroup %
|
|
|
+\lstalias[]{blank}[]{}
|
|
|
+\lstalias{cpp}{C++}
|
|
|
+\lstalias[vc]{C++}[Visual]{C++}
|
|
|
+\lstalias{comal}{Comal 80}
|
|
|
+\lstalias{modula}{Modula-2}
|
|
|
+\lstalias{oberon}{Oberon-2}
|
|
|
+\lstalias[]{pxsc}[XSC]{Pascal}
|
|
|
+\lstalias[]{tp}[Borland6]{Pascal}
|
|
|
+\lstalias{pli}{PL/I}
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
%
|
|
|
-% \begin{macro}{\lstdrv@c@PrePL}
|
|
|
-% \begin{macro}{\lstdrv@c@directives}
|
|
|
-% We only test for C compiler directives.
|
|
|
+%
|
|
|
+% \paragraph{User commands.}
|
|
|
+%
|
|
|
+% Old commands in terms of keys:
|
|
|
% \begin{macrocode}
|
|
|
-\begingroup \makeatletter %
|
|
|
-\gdef\lstdrv@c@PrePL{%
|
|
|
- \expandafter\lstdrv@c@TestSharp\lst@line\relax\relax}%
|
|
|
-\gdef\lstdrv@c@directives{,define,elif,else,endif,error,if,ifdef,%
|
|
|
- ifndef,line,include,pragma,undef}%
|
|
|
+\def\inputlisting{%
|
|
|
+ \@ifnextchar[\inputlisting@{\inputlisting@[1,999999]}}
|
|
|
+\def\inputlisting@[#1,#2]{\lstinputlisting[first=#1,last=#2]}
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}\end{macro}
|
|
|
-%
|
|
|
-% \begin{macro}{\lstdrv@c@TestSharp}
|
|
|
-% To implement C (and C++) directives the catcode of $\#$ must be
|
|
|
-% changed from 'parameter symbol for macros' to 'letter'.
|
|
|
% \begin{macrocode}
|
|
|
-\catcode`\&=6 \catcode`\#=12 %
|
|
|
-\gdef\lstdrv@c@TestSharp&1&2\relax{%
|
|
|
- \if#&1\def\lst@line{&2}%
|
|
|
+\newcommand\selectlisting[2][]{\lstset{language=[#1]#2}}
|
|
|
+\def\listingtrue{\lstset{print=true}}
|
|
|
+\def\listingfalse{\lstset{print=false}}
|
|
|
+\def\tablength#1{\lstset{tabsize=#1}}\tablength{4}% init
|
|
|
+\def\keywordstyle#1{\lstset{keywordstyle={#1}}}
|
|
|
+\def\commentstyle#1{\lstset{commentstyle={#1}}}
|
|
|
+\def\stringstyle#1{\lstset{stringstyle={#1}}}
|
|
|
+\def\labelstyle#1{\lstset{labelstyle={#1}}}
|
|
|
+\newcommand\stringizer[2][d]{\lstset{stringizer=[#1]#2}}
|
|
|
+\def\blankstringtrue{\lstset{blankstring=true}}
|
|
|
+\def\blankstringfalse{\lstset{blankstring=false}}
|
|
|
+\def\spreadlisting#1{\lstset{spread={#1}}}
|
|
|
+\def\prelisting#1{\def\lst@pre{#1}}
|
|
|
+\def\postlisting#1{\def\lst@post{#1}}
|
|
|
+\def\normallisting{%
|
|
|
+ \lstset{style={},spread=\z@,pre={},post={}}}
|
|
|
+\def\keywords#1{\lstset{keywords={#1}}}
|
|
|
+\def\morekeywords#1{\lstset{morekeywords={#1}}}
|
|
|
+\def\sensitivetrue{\lstset{sensitive=true}}
|
|
|
+\def\sensitivefalse{\lstset{sensitive=false}}
|
|
|
+\let\lst@stringblank\textvisiblespace
|
|
|
% \end{macrocode}
|
|
|
-% If the first character of a line is a sharp, we first output that
|
|
|
-% sharp using the keywordstyle. All compiler directives become the
|
|
|
-% current keywords and we output the line, which gets empty afterwards.
|
|
|
+% We define the (new) old environment.
|
|
|
% \begin{macrocode}
|
|
|
- {\lst@keywordstyle\lst@OutputChar#}%
|
|
|
- {\let\lst@keywords\lstdrv@c@directives \lst@ProcessLine}%
|
|
|
- \let\lst@line\@empty %
|
|
|
- \fi}%
|
|
|
-\endgroup %
|
|
|
-%</c>
|
|
|
+\lst@Environment{listing}[1][]\is
|
|
|
+ {\ifx\@empty#1\@empty\else \lst@AddToLOL{#1}{}\fi}
|
|
|
+ {}
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
%
|
|
|
%
|
|
|
-% \subsection{C++}
|
|
|
-% \begin{macro}{\lstdrv@cpp@}
|
|
|
-% Since C++ is an extension of C (from the point of view here), we load
|
|
|
-% the C driver file and use the definition there.
|
|
|
-% \begin{macrocode}
|
|
|
-%<*cpp>
|
|
|
-\selectlisting{c}%
|
|
|
-\begingroup \makeatletter %
|
|
|
-\catcode`\_=11 %
|
|
|
-\gdef\lstdrv@cpp@{\lstdrv@c@ %
|
|
|
- \morekeywords{asm,bad_cast,bad_typeid,bool,catch,class,const_cast,%
|
|
|
- delete,dynamic_cast,false,friend,inline,namespace,new,operator,%
|
|
|
- private,protected,public,reinterpret_cast,static_cast,template,%
|
|
|
- this,throw,true,try,type_info,typeid,using,virtual,xalloc,%
|
|
|
- __multiple_inheritance,__single_inheritance,%
|
|
|
- __virtual_inheritance}%
|
|
|
- \DeclareCommentLine //\relax}%
|
|
|
-\global\let\lstdrv@cpp@ansi \lstdrv@cpp %
|
|
|
-\gdef\lstdrv@cpp@vc{\lstdrv@cpp %
|
|
|
- \morekeywords{__asm,__based,__cdecl,__declspec,dllexport,dllimport,%
|
|
|
- __except,__fastcall,__finally,__inline,__int8,__int16,__int32,%
|
|
|
- __int64,naked,__stdcall,thread,__try,__leave}}%
|
|
|
-\endgroup %
|
|
|
-%</cpp>
|
|
|
-% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
-%
|
|
|
-%
|
|
|
-% \subsection{Cobol}
|
|
|
-% \begin{macro}{\lstdrv@cobol@keys}
|
|
|
-% \begin{macro}{\lstdrv@cobol@keys@eightyfive}
|
|
|
-% \begin{macro}{\lstdrv@cobol@keys@ibm}
|
|
|
-% The keywords first:
|
|
|
-% \begin{macrocode}
|
|
|
-%<*cobol>
|
|
|
-\begingroup \makeatletter %
|
|
|
-\catcode`\-=11 \lst@MakeDigitsLetter %
|
|
|
-\gdef\lstdrv@cobol@keys{ACCEPT,ACCESS,ADD,ADVANCING,AFTER,ALL,%
|
|
|
- ALPHABETIC,ALSO,ALTER,ALTERNATE,AND,ARE,AREA,AREAS,ASCENDING,%
|
|
|
- ASSIGN,AT,AUTHOR,BEFORE,BINARY,BLANK,BLOCK,BOTTOM,BY,CALL,CANCEL,%
|
|
|
- CD,CF,CH,CHARACTER,CHARACTERS,CLOCK-UNITS,CLOSE,COBOL,CODE,%
|
|
|
- CODE-SET,COLLATING,COLUMN,COMMA,COMMUNICATION,COMP,COMPUTE,%
|
|
|
- CONFIGURATION,CONTAINS,CONTROL,CONTROLS,CONVERTING,COPY,CORR,%
|
|
|
- CORRESPONDING,COUNT,CURRENCY,DATA,DATE,DATE-COMPILED,DATE-WRITTEN,%
|
|
|
- DAY,DE,DEBUG-CONTENTS,DEGUB-ITEM,DEBUG-LINE,DEBUG-NAME,DEBUG-SUB1,%
|
|
|
- DEBUG-SUB2,DEBUG-SUB3,DEBUGGING,DECIMAL-POINT,DECLARATIVES,DELETE,%
|
|
|
- DELIMITED,DELIMITER,DEPENDING,DESCENDING,DESTINATION,DETAIL,%
|
|
|
- DISABLE,DISPLAY,DIVIDE,DIVISION,DOWN,DUPLICATES,DYNAMIC,EGI,ELSE,%
|
|
|
- EMI,ENABLE,END,END-OF-PAGE,ENTER,ENVIRONMENT,EOP,EQUAL,ERROR,ESI,%
|
|
|
- EVERY,EXCEPTION,EXIT,EXTEND,FD,FILE,FILE-CONTROL,FILLER,FINAL,%
|
|
|
- FIRST,FOOTING,FOR,FROM,GENERATE,GIVING,GO,GREATER,GROUP,HEADING,%
|
|
|
- HIGH-VALUE,HIGH-VALUES,I-O,I-O-CONTROL,IDENTIFICATION,IF,IN,INDEX,%
|
|
|
- INDEXED,INDICATE,INITIAL,INITIATE,INPUT,INPUT-OUTPUT,INSPECT,%
|
|
|
- INSTALLATION,INTO,INVALID,IS,JUST,JUSTIFIED,KEY,LABEL,LAST,LEADING,%
|
|
|
- LEFT,LENGTH,LESS,LIMIT,LIMITS,LINAGE,LINAGE-COUNTER,LINE,%
|
|
|
- LINE-COUNTER,LINES,LINKAGE,LOCK,LOW-VALUE,LOW-VALUES,MEMORY,MERGE,%
|
|
|
- MESSAGE,MODE,MODULES,MOVE,MULTIPLE,MULTIPLY,NATIVE,NEGATIVE,NEXT,%
|
|
|
- NO,NOT,NUMBER,NUMERIC,OBJECT-COMPUTER,OCCURS,OF,OFF,OMITTED,ON,%
|
|
|
- OPEN,OPTIONAL,OR,ORGANIZATION,OUTPUT,OVERFLOW,PAGE,PAGE-COUNTER,%
|
|
|
- PERFORM,PF,PH,PIC,PICTURE,PLUS,POINTER,POSITION,PRINTING,POSITIVE,%
|
|
|
- PRINTING,PROCEDURE,PROCEDURES,PROCEED,PROGRAM,PROGRAM-ID,QUEUE,%
|
|
|
- QUOTE,QUOTES,RANDOM,RD,READ,RECEIVE,RECORD,RECORDING,RECORDS,%
|
|
|
- REDEFINES,REEL,REFERENCES,RELATIVE,RELEASE,REMAINDER,REMOVAL,%
|
|
|
- RENAMES,REPLACING,REPORT,REPORTING,REPORTS,RERUN,RESERVE,RESET,%
|
|
|
- RETURN,REVERSED,REWIND,REWRITE,RF,RH,RIGHT,ROUNDED,RUN,SAME,SD,%
|
|
|
- SEARCH,SECTION,SECURITY,SEGMENT,SEGMENT-LIMIT,SELECT,SEND,SENTENCE,%
|
|
|
- SEPARATE,SEQUENCE,SEQUENTIAL,SET,SIGN,SIZE,SORT,SORT-MERGE,SOURCE,%
|
|
|
- SOURCE-COMPUTER,SPACE,SPACES,SPECIAL-NAMES,STANDARD,START,STATUS,%
|
|
|
- STOP,STRING,SUB-QUEUE-1,SUB-QUEUE-2,SUB-QUEUE-3,SUBTRACT,SUM,%
|
|
|
- SYMBOLIC,SYNC,SYNCHRONIZED,TABLE,TALLYING,TAPE,TERMINAL,TERMINATE,%
|
|
|
- TEXT,THAN,THROUGH,THRU,TIME,TIMES,TO,TOP,TRAILING,TYPE,UNIT,%
|
|
|
- UNSTRING,UNTIL,UP,UPON,USAGE,USE,USING,VALUE,VALUES,VARYING,WHEN,%
|
|
|
- WITH,WORDS,WORKING-STORAGE,WRITE,ZERO,ZEROES,ZEROS}%
|
|
|
-\gdef\lstdrv@cobol@keys@eightyfive{ALPHABET,ALPHABETIC-LOWER,%
|
|
|
- ALPHABETIC-UPPER,ALPHANUMERIC,ALPHANUMERIC-EDITED,ANY,CLASS,COMMON,%
|
|
|
- CONTENT,CONTINUE,DAY-OF-WEEK,END-ADD,END-CALL,END-COMPUTE,%
|
|
|
- END-DELETE,END-DIVIDE,END-EVALUATE,END-IF,END-MULTIPLY,END-PERFORM,%
|
|
|
- END-READ,END-RECEIVE,END-RETURN,END-REWRITE,END-SEARCH,END-START,%
|
|
|
- END-STRING,END-SUBTRACT,END-UNSTRING,END-WRITE,EVALUATE,EXTERNAL,%
|
|
|
- FALSE,GLOBAL,INITIALIZE,NUMERIC-EDITED,ORDER,OTHER,PACKED-DECIMAL,%
|
|
|
- PADDING,PURGE,REFERENCE,RELOAD,REPLACE,STANDARD-1,STANDARD-2,TEST,%
|
|
|
- THEN,TRUE}%
|
|
|
-\gdef\lstdrv@cobol@keys@ibm{ADDRESS,BEGINNING,COMP-3,COMP-4,%
|
|
|
- COMPUTATIONAL,COMPUTATIONAL-3,COMPUTATIONAL-4,DISPLAY-1,EGCS,EJECT,%
|
|
|
- ENDING,ENTRY,GOBACK,ID,MORE-LABELS,NULL,NULLS,PASSWORD,RECORDING,%
|
|
|
- RETURN-CODE,SERVICE,SKIP1,SKIP2,SKIP3,SORT-CONTROL,SORT-RETURN,%
|
|
|
- SUPPRESS,TITLE,WHEN-COMPILED}%
|
|
|
-\endgroup %
|
|
|
-% \end{macrocode}
|
|
|
-% \end{macro}\end{macro}\end{macro}
|
|
|
-%
|
|
|
-% \begin{macro}{\lstdrv@cobol@}
|
|
|
-% Now the main driver macro:
|
|
|
-% \begin{macrocode}
|
|
|
-\begingroup \makeatletter %
|
|
|
-\catcode`\"=12%
|
|
|
-\gdef\lstdrv@cobol@{%
|
|
|
- \keywords{\lstdrv@cobol@keys,\lstdrv@cobol@keys@eightyfive}%
|
|
|
- \sensitivefalse % ???
|
|
|
- \DeclareCommentLine\relax %
|
|
|
- \DeclareSingleComment stuff \relax %
|
|
|
- \stringizer[d]{"}\lstbaseem{0.65}%
|
|
|
- \lst@DefineCatcodes{11}%
|
|
|
- \let\lst@PrePL\lstdrv@cobol@PrePL %
|
|
|
- \let\lst@PostPL\relax}%
|
|
|
-% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
-%
|
|
|
-% \begin{macro}{\lstdrv@cobol@1985}
|
|
|
-% \begin{macro}{\lstdrv@cobol@1974}
|
|
|
-% \begin{macro}{\lstdrv@cobol@ibm}
|
|
|
-% And macros for the optional argument:
|
|
|
-% \begin{macrocode}
|
|
|
-\global\@namedef{lstdrv@cobol@1985}{\lstdrv@cobol@}%
|
|
|
-\global\@namedef{lstdrv@cobol@1974}{\lstdrv@cobol@ %
|
|
|
- \keywords{\lstdrv@cobol@keys}}%
|
|
|
-\gdef\lstdrv@cobol@ibm{\lstdrv@cobol@ %
|
|
|
- \morekeywords{\lstdrv@cobol@keys@ibm}}%
|
|
|
-\endgroup %
|
|
|
-% \end{macrocode}
|
|
|
-% \end{macro}\end{macro}\end{macro}
|
|
|
+% \paragraph{Comments.}
|
|
|
%
|
|
|
-% \begin{macro}{\lstdrv@cobol@PrePL}
|
|
|
-% \begin{macro}{\lstdrv@cobol@TestComment}
|
|
|
-% Comments are handled with the \verb!\lst@PrePL! mechanism. We simply
|
|
|
-% look, if the seventh character is an asterix (and output the comment
|
|
|
-% if necessary).
|
|
|
-% \begin{macrocode}
|
|
|
-\begingroup \makeatletter %
|
|
|
-\gdef\lstdrv@cobol@PrePL{\expandafter\lstdrv@cobol@TestComment %
|
|
|
- \lst@line\relax\relax\relax\relax\relax\relax\relax\relax}%
|
|
|
-\catcode`\*=\active %
|
|
|
-\gdef\lstdrv@cobol@TestComment#1#2#3#4#5#6#7#8\relax{%
|
|
|
- \ifx #7*%
|
|
|
- \lst@commenttrue \expandafter\lst@Tokenize\lst@line\relax %
|
|
|
- \let\lst@line\@empty \lst@commentfalse %
|
|
|
- \fi}%
|
|
|
-\endgroup %
|
|
|
-%</cobol>
|
|
|
+% The implementation of old comment commands in terms of the new ones is all the same:
|
|
|
+% If the last argument is empty, we remove the comment; otherwise we execute the new key with correct syntax.
|
|
|
+% \begin{macrocode}
|
|
|
+\def\DeclareCommentLine#1\relax{%
|
|
|
+ \ifx\@empty#1\@empty %
|
|
|
+ \let\lst@DefCL\relax %
|
|
|
+ \else %
|
|
|
+ \lstset{commentline=#1}%
|
|
|
+ \fi}
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}\end{macro}
|
|
|
-%
|
|
|
-%
|
|
|
-% \subsection{Comal 80}
|
|
|
-% \begin{macro}{\lstdrv@comal@}
|
|
|
-% Only the lonely driver macro.
|
|
|
-% \begin{macrocode}
|
|
|
-%<*comal>
|
|
|
-\begingroup \makeatletter %
|
|
|
-\catcode`\"=12 %
|
|
|
-\gdef\lstdrv@comal@{%
|
|
|
- \keywords{AND,AUTO,CASE,DATA,DEL,DIM,DIV,DO,ELSE,ENDCASE,ENDIF,%
|
|
|
- ENDPROC,ENDWHILE,EOD,EXEC,FALSE,FOR,GOTO,IF,INPUT,INT,LIST,%
|
|
|
- LOAD,MOD,NEW,NEXT,NOT,OF,OR,PRINT,PROC,RANDOM,RENUM,REPEAT,%
|
|
|
- RND,RUN,SAVE,SELECT,STOP,TAB,THEN,TRUE,UNTIL,WHILE,ZONE}%
|
|
|
- \sensitivefalse % ???
|
|
|
- \DeclareCommentLine //\relax %
|
|
|
- \DeclareSingleComment stuff \relax %
|
|
|
- \stringizer{"}\lstbaseem{0.65}%
|
|
|
- \lst@DefineCatcodes{\active}%
|
|
|
- \let\lst@PrePL \lst@PrePLDefault %
|
|
|
- \let\lst@PostPL\lst@PostPLDefault}%
|
|
|
-\endgroup %
|
|
|
-%</comal>
|
|
|
-% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
-%
|
|
|
-%
|
|
|
-% \subsection{Eiffel}
|
|
|
-% \begin{macro}{\lstdrv@eiffel@}
|
|
|
-% The same procedure \ldots
|
|
|
-% \begin{macrocode}
|
|
|
-%<*eiffel>
|
|
|
-\begingroup \makeatletter %
|
|
|
-\catcode`\"=12 \catcode`\-=\active %
|
|
|
-\gdef\lstdrv@eiffel@{%
|
|
|
- \keywords{alias,all,and,as,BIT,BOOLEAN,CHARACTER,check,class,%
|
|
|
- creation,Current,debug,deferred,do,DOUBLE,else,elseif,end,%
|
|
|
- ensure,expanded,export,external,false,feature,from,frozen,if,%
|
|
|
- implies,indexing,infix,inherit,inspect,INTEGER,invariant,is,%
|
|
|
- like,local,loop,NONE,not,obsolete,old,once,or,POINTER,prefix,%
|
|
|
- REAL,redefine,rename,require,rescue,Result,retry,select,%
|
|
|
- separate,STRING,strip,then,true,undefine,unique,until,variant,%
|
|
|
- when,xor}%
|
|
|
- \sensitivetrue %
|
|
|
- \DeclareCommentLine --\relax %
|
|
|
- \DeclareSingleComment stuff \relax %
|
|
|
- \stringizer{"}\lstbaseem{0.6}%
|
|
|
- \lst@DefineCatcodes{\active}%
|
|
|
- \let\lst@PrePL \lstdrv@eiffel@PrePL %
|
|
|
- \let\lst@PostPL\relax}%
|
|
|
-\endgroup %
|
|
|
+% \begin{macrocode}
|
|
|
+\def\DeclareSingleComment#1 #2\relax{%
|
|
|
+ \ifx\@empty#2\@empty %
|
|
|
+ \let\lst@DefSC\relax \let\lst@DefDC\relax %
|
|
|
+ \else %
|
|
|
+ \lstset{singlecomment={#1}{#2}}%
|
|
|
+ \fi}
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
-%
|
|
|
-% Not the same procedure: Since '$\%$' continues a string, we need a
|
|
|
-% different comment character and let the percent be other (catcode)
|
|
|
-% to look for it.
|
|
|
% \begin{macrocode}
|
|
|
-\begingroup \makeatletter %
|
|
|
-\catcode`\&=14 \catcode`\%=12 &
|
|
|
+\def\DeclarePairedComment#1\relax{
|
|
|
+ \ifx\@empty#1\@empty %
|
|
|
+ \let\lst@DefSC\relax \let\lst@DefDC\relax %
|
|
|
+ \else %
|
|
|
+ \lstset{singlecomment={#1}{#1}}%
|
|
|
+ \fi}
|
|
|
% \end{macrocode}
|
|
|
-% \begin{macro}{\lstdrv@eiffel@PrePL}
|
|
|
-% \begin{macro}{\lstdrv@eiffel@TestPercent}
|
|
|
-% If a string started on a preceding line, we test for the percent.
|
|
|
-% Refer how we cut a line into a comment and other source code.
|
|
|
% \begin{macrocode}
|
|
|
-\gdef\lstdrv@eiffel@PrePL{&
|
|
|
- \lst@ifstring &
|
|
|
- \expandafter\lstdrv@eiffel@TestPercent\lst@line%\relax &
|
|
|
- \fi}&
|
|
|
-\gdef\lstdrv@eiffel@TestPercent#1%#2\relax{&
|
|
|
- \ifx\@empty#2\@empty \lst@PostPLDefault &
|
|
|
- \else \expandafter\lstdrv@eiffel@CutPercent\lst@line\relax&
|
|
|
- \fi}&
|
|
|
+\def\DeclareNestedComment#1 #2\relax{%
|
|
|
+ \ifx\@empty#2\@empty %
|
|
|
+ \let\lst@DefSC\relax \let\lst@DefDC\relax %
|
|
|
+ \else %
|
|
|
+ \lstset{nestedcomment={#1}{#2}}%
|
|
|
+ \fi}
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}\end{macro}
|
|
|
-%
|
|
|
-% \begin{macro}{\lstdrv@eiffel@CutPercent}
|
|
|
-% To output the characters in front of the percent we temporary switch
|
|
|
-% the string boolean. Atferwards we redefine the input line, so that
|
|
|
-% the normal line processing continues the string.
|
|
|
% \begin{macrocode}
|
|
|
-\gdef\lstdrv@eiffel@CutPercent#1%#2\relax{&
|
|
|
- \lst@stringfalse \lst@Tokenize#1\relax &
|
|
|
- \lst@stringtrue \def\lst@line{%#2}}&
|
|
|
-\endgroup %
|
|
|
-%</eiffel>
|
|
|
-% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
-%
|
|
|
-%
|
|
|
-% \subsection{Elan}
|
|
|
-% \begin{macro}{\lstdrv@elan@keys}
|
|
|
-% Since we need digits as letters, the keywords first:
|
|
|
-% \begin{macrocode}
|
|
|
-%<*elan>
|
|
|
-\begingroup \makeatletter %
|
|
|
-\lst@MakeDigitsLetter %
|
|
|
-\gdef\lstdrv@elan@keys{ABS,AND,BOOL,CAND,CASE,CAT,COLUMNS,CONCR,CONJ,%
|
|
|
- CONST,COR,DECR,DEFINES,DET,DIV,DOWNTO,ELIF,ELSE,END,ENDIF,ENDOP,%
|
|
|
- ENDPACKET,ENDPROC,ENDREP,ENDSELECT,FALSE,FI,FILE,FOR,FROM,IF,INCR,%
|
|
|
- INT,INV,LEAVE,LENGTH,LET,MOD,NOT,OF,OP,OR,OTHERWISE,PACKET,PROC,%
|
|
|
- REAL,REP,REPEAT,ROW,ROWS,SELECT,SIGN,STRUCT,SUB,TEXT,THEN,TRANSP,%
|
|
|
- TRUE,TYPE,UNTIL,UPTO,VAR,WHILE,WITH,XOR,%
|
|
|
- maxint,sign,abs,min,max,random,initializerandom,subtext,code,%
|
|
|
- replace,text,laenge,pos,compress,change,maxreal,smallreal,floor,pi,%
|
|
|
- e,ln,log2,log10,sqrt,exp,tan,tand,sin,sind,cos,cosd,arctan,arctand,%
|
|
|
- int,real,lastconversionok,put,putline,line,page,get,getline,input,%
|
|
|
- output,sequentialfile,maxlinelaenge,reset,eof,close,complexzero,%
|
|
|
- complexone,complexi,complex,realpart,imagpart,dphi,phi,vector,norm,%
|
|
|
- replace,matrix,idn,row,column,sub,replacerow,replacecolumn,%
|
|
|
- replaceelement,transp,errorsstop,stop}%
|
|
|
-\endgroup %
|
|
|
+\def\DeclareDoubleComment#1 #2 #3 #4\relax{%
|
|
|
+ \ifx\@empty#4\@empty %
|
|
|
+ \let\lst@DefSC\relax \let\lst@DefDC\relax %
|
|
|
+ \else %
|
|
|
+ \lstset{doublecomment={#1}{#2}{#3}{#4}}%
|
|
|
+ \fi}
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
-%
|
|
|
-% \begin{macro}{\lstdrv@elan@}
|
|
|
-% Now we define the main driver macro:
|
|
|
+% \begingroup
|
|
|
% \begin{macrocode}
|
|
|
-\begingroup \makeatletter %
|
|
|
-\catcode`\"=12 %
|
|
|
-\gdef\lstdrv@elan@{%
|
|
|
- \keywords{\lstdrv@elan@keys}%
|
|
|
- \sensitivetrue %
|
|
|
- \DeclareCommentLine\relax %
|
|
|
- \DeclareSingleComment stuff \relax %
|
|
|
- \stringizer[d]{"}\lstbaseem{0.65}%
|
|
|
- \lst@DefineCatcodes{\active}%
|
|
|
- \let\lst@PrePL \lst@PrePLDefault %
|
|
|
- \let\lst@PostPL\lst@PostPLDefault}%
|
|
|
-\endgroup %
|
|
|
-%</elan>
|
|
|
+%</0.17>
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
+% \endgroup
|
|
|
+%
|
|
|
%
|
|
|
+% \subsection{\textsf{fancyvrb}}
|
|
|
%
|
|
|
-% \subsection{Fortran}
|
|
|
-% \begin{macro}{\lstdrv@fortran@keys}
|
|
|
-% Common 'keywords' of Fortran 90 and Fortran 77:
|
|
|
+% \lsthelper{Denis Girou}{[email protected]}{1998/07/26}{fancyvrb} asked whether \textsf{fancyvrb} and \textsf{listings} could work together.
|
|
|
+% Here's the first try.
|
|
|
+% \begingroup
|
|
|
% \begin{macrocode}
|
|
|
-%<*fortran>
|
|
|
-\begingroup \makeatletter %
|
|
|
-\gdef\lstdrv@fortan@keys{ACCESS,ASSIGN,BACKSPACE,BLANK,BLOCK,CALL,%
|
|
|
- CHARACTER,CLOSE,COMMON,COMPLEX,CONTINUE,DATA,DIMENSION,DIRECT,DO,%
|
|
|
- DOUBLE,ELSE,END,ENTRY,EOF,EQUIVALENCE,ERR,EXIST,EXTERNAL,FILE,%
|
|
|
- FMT,FORM,FORMAT,FORMATTED,FUNCTION,GO,TO,IF,IMPLICIT,INQUIRE,%
|
|
|
- INTEGER,INTRINSIC,IOSTAT,LOGICAL,NAMED,NEXTREC,NUMBER,OPEN,OPENED,%
|
|
|
- PARAMETER,PAUSE,PRECISION,PRINT,PROGRAM,READ,REAL,REC,RECL,%
|
|
|
- RETURN,REWIND,SEQUENTIAL,STATUS,STOP,SUBROUTINE,THEN,TYPE,%
|
|
|
- UNFORMATTED,UNIT,WRITE}%
|
|
|
-\endgroup %
|
|
|
+%<*kernel>
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
-%
|
|
|
-% \begin{macro}{\lstdrv@fortran@}
|
|
|
-% The driver macro:
|
|
|
-% \begin{macrocode}
|
|
|
-\begingroup \makeatletter %
|
|
|
-\catcode`\"=12 %
|
|
|
-\gdef\lstdrv@fortran@{%
|
|
|
- \keywords{\lstdrv@fortan@keys,ACTION,ADVANCE,ALLOCATE,ALLOCATABLE,%
|
|
|
- ASSIGNMENT,CASE,CONTAINS,CYCLE,DEALLOCATE,DEFAULT,DELIM,EXIT,%
|
|
|
- IN,NONE,IN,OUT,INTENT,INTERFACE,IOLENGTH,KIND,LEN,MODULE,NAME,%
|
|
|
- NAMELIST,NMT,NULLIFY,ONLY,OPERATOR,OPTIONAL,OUT,PAD,POINTER,%
|
|
|
- POSITION,PRIVATE,PUBLIC,READWRITE,RECURSIVE,RESULT,SELECT,%
|
|
|
- SEQUENCE,SIZE,STAT,TARGET,USE,WHERE,WHILE,%
|
|
|
- BLOCKDATA,DOUBLEPRECISION,ELSEIF,ENDBLOCKDATA,ENDDO,ENDFILE,%
|
|
|
- ENDFUNCTION,ENDIF,ENDINTERFACE,ENDMODULE,ENDPROGRAM,ENDSELECT,%
|
|
|
- ENDSUBROUTINE,ENDTYPE,ENDWHERE,GOTO,INOUT,SELECTCASE}%
|
|
|
- \sensitivefalse %% not Fortran standard %%
|
|
|
- \DeclareCommentLine !\relax %
|
|
|
- \DeclareSingleComment stuff \relax %
|
|
|
- \stringizer{"}\lstbaseem{0.6}%
|
|
|
- \lst@DefineCatcodes{\active}%
|
|
|
- \let\lst@PrePL \lstdrv@fortran@PrePL %
|
|
|
- \let\lst@PostPL\lst@PostPLDefault}%
|
|
|
-% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
-%
|
|
|
-% \begin{macro}{\lstdrv@fortran@90}
|
|
|
-% \begin{macro}{\lstdrv@fortran@77}
|
|
|
-% Macros for the optional argument:
|
|
|
-% \begin{macrocode}
|
|
|
-\global\@namedef{lstdrv@fortran@90}{\lstdrv@fortran@}%
|
|
|
-\global\@namedef{lstdrv@fortran@77}{\lstdrv@fortran@ %
|
|
|
- \keywords{\lstdrv@fortan@keys,SAVE}%
|
|
|
- \DeclareCommentLine\relax}%
|
|
|
-\endgroup %
|
|
|
+% \endgroup
|
|
|
+% \begin{aspect}{fancyvrb}
|
|
|
+% We set the boolean and input the interface file (first time only).
|
|
|
+% \begin{macrocode}
|
|
|
+\lst@Aspect{fancyvrb}[t]{%
|
|
|
+ \lstKV@SetIfKey\lst@iffancyvrb{#1}%
|
|
|
+ \lstfancyvrb@}
|
|
|
+\def\lstfancyvrb@{\input{lstfvrb.sty}\lstfancyvrb@}
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}\end{macro}
|
|
|
-%
|
|
|
-% \begin{macro}{\lstdrv@fortran@PrePL}
|
|
|
-% \begin{macro}{\lstdrv@fortran@TestComment}
|
|
|
-% Again something different: We use the \verb!\lst@PrePL! mechanism to
|
|
|
-% handle '$*$' and 'C' comments. The defined test macro tests, if the
|
|
|
-% first character of the input line is a star or an upper or lower case
|
|
|
-% c. We output the line as comment and empty the input,
|
|
|
-% if necessary. That's all.
|
|
|
-% \begin{macrocode}
|
|
|
-\begingroup \makeatletter %
|
|
|
-\gdef\lstdrv@fortran@PrePL{%
|
|
|
- \expandafter\lstdrv@fortran@TestComment\lst@line\relax}%
|
|
|
-\catcode`\*=\active %
|
|
|
-\gdef\lstdrv@fortran@TestComment#1#2\relax{\lst@commentfalse %
|
|
|
- \ifx #1*\lst@commenttrue %
|
|
|
- \else\if #1c\lst@commenttrue %% not Fortran standard %%
|
|
|
- \else\if #1C\lst@commenttrue %
|
|
|
- \fi \fi \fi %
|
|
|
- \lst@ifcomment %
|
|
|
- \expandafter\lst@Tokenize\lst@line\relax %
|
|
|
- \let\lst@line\@empty \lst@commentfalse %
|
|
|
- \fi}%
|
|
|
-\endgroup %
|
|
|
-%</fortran>
|
|
|
+% \end{aspect}
|
|
|
+% \begingroup
|
|
|
+% \begin{macrocode}
|
|
|
+%</kernel>
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}\end{macro}
|
|
|
%
|
|
|
-%
|
|
|
-% \subsection{Java}
|
|
|
-% \begin{macro}{\lstdrv@java@}
|
|
|
-% Nothing new.
|
|
|
-% \begin{macrocode}
|
|
|
-%<*java>
|
|
|
-\begingroup \makeatletter %
|
|
|
-\catcode`\"=12 \catcode`\*=\active %
|
|
|
-\gdef\lstdrv@java@{%
|
|
|
- \keywords{abstract,boolean,break,byte,case,catch,char,class,const,%
|
|
|
- continue,default,do,double,else,extends,final,finally,float,%
|
|
|
- for,goto,if,implements,import,instanceof,int,interface,long,%
|
|
|
- native,new,null,package,private,protected,public,return,short,%
|
|
|
- static,super,switch,synchronized,this,throw,throws,transient,%
|
|
|
- try,void,volatile,while,true,false}%
|
|
|
- \sensitivetrue %
|
|
|
- \DeclareCommentLine //\relax %
|
|
|
- \DeclareSingleComment /* */\relax %
|
|
|
- \stringizer{"}\lstbaseem{0.6}%
|
|
|
- \lst@DefineCatcodes{\active}%
|
|
|
- \let\lst@PrePL \lst@PrePLDefault %
|
|
|
- \let\lst@PostPL\lst@PostPLDefault}%
|
|
|
-\endgroup %
|
|
|
-%</java>
|
|
|
-% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
-%
|
|
|
-%
|
|
|
-% \subsection{Lisp}
|
|
|
-% \begin{macro}{\lstdrv@lisp@}
|
|
|
-% The keywords are the 'one-word' functions and macros of Common Lisp,
|
|
|
-% i.e.\ words not containing a minus. And I left out the \texttt{caaaar},
|
|
|
-% \ldots{} functions.
|
|
|
-% \begin{macrocode}
|
|
|
-%<*lisp>
|
|
|
-\begingroup \makeatletter %
|
|
|
-\catcode`\"=12 \catcode`\-=11 %
|
|
|
-\gdef\lstdrv@lisp@{%
|
|
|
- \keywords{abort,abs,acons,acos,acosh,adjoin,alphanumericp,alter,%
|
|
|
- append,apply,apropos,aref,arrayp,ash,asin,asinh,assoc,atan,%
|
|
|
- atanh,atom,bit,boole,boundp,break,butlast,byte,catenate,%
|
|
|
- ceiling,cerror,char,character,characterp,choose,chunk,cis,%
|
|
|
- close,clrhash,coerce,collect,commonp,compile,complement,%
|
|
|
- complex,complexp,concatenate,conjugate,cons,consp,constantp,%
|
|
|
- continue,cos,cosh,cotruncate,count,delete,denominator,%
|
|
|
- describe,directory,disassemble,documentation,dpb,dribble,%
|
|
|
- ed,eighth,elt,enclose,endp,eq,eql,equal,equalp,error,eval,%
|
|
|
- evalhook,evenp,every,exp,expand,export,expt,fboundp,fceiling,%
|
|
|
- fdefinition,ffloor,fifth,fill,find,first,float,floatp,floor,%
|
|
|
- fmakunbound,format,fourth,fround,ftruncate,funcall,functionp,%
|
|
|
- gatherer,gcd,generator,gensym,gentemp,get,getf,gethash,%
|
|
|
- identity,imagpart,import,inspect,integerp,intern,intersection,%
|
|
|
- tively,isqrt,keywordp,last,latch,lcm,ldb,ldiff,length,list,%
|
|
|
- listen,listp,load,log,logand,logbitp,logcount,logeqv,logior,%
|
|
|
- lognand,lognor,lognot,logtest,logxor,macroexpand,makunbound,%
|
|
|
- map,mapc,mapcan,mapcar,mapcon,maphash,mapl,maplist,mask,max,%
|
|
|
- member,merge,min,mingle,minusp,mismatch,mod,namestring,%
|
|
|
- nbutlast,nconc,nintersection,ninth,not,notany,notevery,%
|
|
|
- nreconc,nreverse,nsublis,nsubst,nth,nthcdr,null,numberp,%
|
|
|
- numerator,nunion,oddp,open,packagep,pairlis,pathname,pathnamep,%
|
|
|
- phase,plusp,position,positions,pprint,previous,princ,print,%
|
|
|
- proclaim,provide,random,rassoc,rational,rationalize,rationalp,%
|
|
|
- read,readtablep,realp,realpart,reduce,rem,remhash,remove,%
|
|
|
- remprop,replace,require,rest,revappend,reverse,room,round,%
|
|
|
- rplaca,rplacd,sbit,scan,schar,search,second,series,set,seventh,%
|
|
|
- shadow,signal,signum,sin,sinh,sixth,sleep,some,sort,split,%
|
|
|
- sqrt,streamp,string,stringp,sublis,subseq,subseries,subsetp,%
|
|
|
- subst,substitute,subtypep,svref,sxhash,symbolp,tailp,tan,tanh,%
|
|
|
- tenth,terpri,third,truename,truncate,typep,unexport,unintern,%
|
|
|
- union,until,values,vector,vectorp,warn,write,zerop,%
|
|
|
- and,assert,case,ccase,cond,ctypecase,decf,declaim,defclass,%
|
|
|
- defconstant,defgeneric,defmacro,defmethod,defpackage,%
|
|
|
- defparameter,defsetf,defstruct,deftype,defun,defvar,do,dolist,%
|
|
|
- dotimes,ecase,encapsulated,etypecase,flet,formatter,gathering,%
|
|
|
- incf,iterate,labels,let,locally,loop,macrolet,mapping,or,pop,%
|
|
|
- producing,prog,psetf,psetq,push,pushnew,remf,return,rotatef,%
|
|
|
- setf,shiftf,step,time,trace,typecase,unless,untrace,when}%
|
|
|
- \sensitivetrue % ???
|
|
|
- \DeclareCommentLine;\relax %
|
|
|
- \DeclareSingleComment stuff \relax %
|
|
|
- \stringizer[b]{"}\lstbaseem{0.6}%
|
|
|
- \lst@DefineCatcodes{11}%
|
|
|
- \let\lst@PrePL \lst@PrePLDefault %
|
|
|
- \let\lst@PostPL\lst@PostPLDefault}%
|
|
|
-\endgroup %
|
|
|
-%</lisp>
|
|
|
-% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
-%
|
|
|
-%
|
|
|
-% \subsection{Logo}
|
|
|
-% \begin{macro}{\lstdrv@logo@}
|
|
|
-% I don't know where I have the keywords from and what kind of Logo
|
|
|
-% it is. Help me!
|
|
|
-% \begin{macrocode}
|
|
|
-%<*logo>
|
|
|
-\begingroup \makeatletter %
|
|
|
-\gdef\lstdrv@logo@{% ??? end,unix
|
|
|
- \keywords{and,atan,arctan,both,break,bf,bl,butfirst,butlast,cbreak,%
|
|
|
- close,co,continue,cos,count,clearscreen,cs,debquit,describe,%
|
|
|
- diff,difference,ed,edit,either,emptyp,equalp,er,erase,errpause,%
|
|
|
- errquit,fifp,filefprint,fifty,fileftype,fip,fileprint,fird,%
|
|
|
- fileread,fity,filetype,fiwd,fileword,f,first,or,fp,fprint,fput,%
|
|
|
- fty,ftype,full,fullscreen,go,bye,goodbye,gprop,greaterp,help,%
|
|
|
- if,iff,iffalse,ift,iftrue,nth,item,keyp,llast,lessp,list,local,%
|
|
|
- lput,make,max,maximum,memberp,memtrace,min,minimum,namep,not,%
|
|
|
- numberp,oflush,openr,openread,openw,openwrite,op,output,pause,%
|
|
|
- plist,pots,pow,pprop,pps,pr,print,product,quotient,random,rc,%
|
|
|
- readchar,rl,readlist,remprop,repcount,repeat,request,rnd,run,%
|
|
|
- se,sentence,sentencep,setc,setcolor,setipause,setqpause,po,%
|
|
|
- show,sin,split,splitscreen,sqrt,stop,sum,test,text,textscreen,%
|
|
|
- thing,to,tone,top,toplevel,type,untrace,wait,word,wordp,%
|
|
|
- yaccdebug,is,mod,remainder,trace,zerop,%
|
|
|
- back,bk,bto,btouch,fd,forward,fto,ftouch,getpen,heading,hit,%
|
|
|
- hitoot,ht,hideturtle,loff,lampoff,lon,lampon,lt,left,lot,%
|
|
|
- lotoot,lto,ltouch,penc,pencolor,pd,pendown,pe,penerase,penmode,%
|
|
|
- pu,penup,px,penreverse,rt,right,rto,rtouch,scrunch,seth,%
|
|
|
- setheading,setscrun,setscrunch,setxy,shownp,st,showturtle,%
|
|
|
- towardsxy,clean,wipeclean,xcor,ycor,tur,turtle,display,dpy}%
|
|
|
- \sensitivefalse % ???
|
|
|
- \DeclareCommentLine\relax %
|
|
|
- \DeclareSingleComment stuff \relax %
|
|
|
- \stringizer{}\lstbaseem{0.6}%
|
|
|
- \lst@DefineCatcodes{\active}%
|
|
|
- \let\lst@PrePL \lst@PrePLDefault %
|
|
|
- \let\lst@PostPL\lst@PostPLDefault}%
|
|
|
-\endgroup %
|
|
|
-%</logo>
|
|
|
-% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
-%
|
|
|
-%
|
|
|
-% \subsection{Matlab}
|
|
|
-% \begin{macro}{\lstdrv@matlab@keys}
|
|
|
-% \begin{macro}{\lstdrv@matlab@}
|
|
|
-% Once more \ldots
|
|
|
-% \begin{macrocode}
|
|
|
-%<*matlab>
|
|
|
-\begingroup \makeatletter %
|
|
|
-\lst@MakeDigitsLetter %
|
|
|
-\gdef\lstdrv@matlab@keys{gt,lt,gt,lt,amp,%
|
|
|
- abs,acos,acosh,acot,acoth,acsc,acsch,all,angle,ans,any,asec,asech,%
|
|
|
- asin,asinh,atan,atan2,atanh,auread,auwrite,axes,axis,balance,bar,%
|
|
|
- bessel,besselk,bessely,beta,betainc,betaln,blanks,bone,break,%
|
|
|
- brighten,capture,cart2pol,cart2sph,caxis,cd,cdf2rdf,cedit,ceil,%
|
|
|
- chol,cla,clabel,clc,clear,clf,clock,close,colmmd,Colon,colorbar,%
|
|
|
- colormap,ColorSpec,colperm,comet,comet3,compan,compass,computer,%
|
|
|
- cond,condest,conj,contour,contour3,contourc,contrast,conv,conv2,%
|
|
|
- cool,copper,corrcoef,cos,cosh,cot,coth,cov,cplxpair,cputime,cross,%
|
|
|
- csc,csch,csvread,csvwrite,cumprod,cumsum,cylinder,date,dbclear,%
|
|
|
- dbcont,dbdown,dbquit,dbstack,dbstatus,dbstep,dbstop,dbtype,dbup,%
|
|
|
- ddeadv,ddeexec,ddeinit,ddepoke,ddereq,ddeterm,ddeunadv,deblank,%
|
|
|
- dec2hex,deconv,del2,delete,demo,det,diag,diary,diff,diffuse,dir,%
|
|
|
- disp,dlmread,dlmwrite,dmperm,dot,drawnow,echo,eig,ellipj,ellipke,%
|
|
|
- else,elseif,end,engClose,engEvalString,engGetFull,engGetMatrix,%
|
|
|
- engOpen,engOutputBuffer,engPutFull,engPutMatrix,engSetEvalCallback,%
|
|
|
- engSetEvalTimeout,engWinInit,eps,erf,erfc,erfcx,erfinv,error,%
|
|
|
- errorbar,etime,etree,eval,exist,exp,expint,expm,expo,eye,fclose,%
|
|
|
- feather,feof,ferror,feval,fft,fft2,fftshift,fgetl,fgets,figure,%
|
|
|
- fill,fill3,filter,filter2,find,findstr,finite,fix,flag,fliplr,%
|
|
|
- flipud,floor,flops,fmin,fmins,fopen,for,format,fplot,fprintf,fread,%
|
|
|
- frewind,fscanf,fseek,ftell,full,function,funm,fwrite,fzero,gallery,%
|
|
|
- gamma,gammainc,gammaln,gca,gcd,gcf,gco,get,getenv,getframe,ginput,%
|
|
|
- global,gplot,gradient,gray,graymon,grid,griddata,gtext,hadamard,%
|
|
|
- hankel,help,hess,hex2dec,hex2num,hidden,hilb,hist,hold,home,hostid,%
|
|
|
- hot,hsv,hsv2rgb,i,if,ifft,ifft2,imag,image,imagesc,Inf,info,input,%
|
|
|
- int2str,interp1,interp2,interpft,inv,invhilb,isempty,isglobal,%
|
|
|
- ishold,isieee,isinf,isletter,isnan,isreal,isspace,issparse,isstr,j,%
|
|
|
- jet,keyboard,kron,lasterr,lcm,legend,legendre,length,lin2mu,line,%
|
|
|
- linspace,load,log,log10,log2,loglog,logm,logspace,lookfor,lower,ls,%
|
|
|
- lscov,lu,magic,matClose,matDeleteMatrix,matGetDir,matGetFp,%
|
|
|
- matGetFull,matGetMatrix,matGetNextMatrix,matGetString,matlabrc,%
|
|
|
- matlabroot,matOpen,matPutFull,matPutMatrix,matPutString,max,mean,%
|
|
|
- median,menu,mesh,meshc,meshgrid,meshz,mexAtExit,mexCallMATLAB,%
|
|
|
- mexdebug,mexErrMsgTxt,mexEvalString,mexFunction,mexGetFull,%
|
|
|
- mexGetMatrix,mexGetMatrixPtr,mexPrintf,mexPutFull,mexPutMatrix,%
|
|
|
- mexSetTrapFlag,min,more,movie,moviein,mu2lin,mxCalloc,%
|
|
|
- mxCopyCharacterToPtr,mxCopyComplex16ToPtr,mxCopyInteger4ToPtr,%
|
|
|
- mxCopyPtrToCharacter,mxCopyPtrToComplex16,mxCopyPtrToInteger4,%
|
|
|
- mxCopyPtrToReal8,mxCopyReal8ToPtr,mxCreateFull,mxCreateSparse,%
|
|
|
- mxCreateString,mxFree,mxFreeMatrix,mxGetIr,mxGetJc,mxGetM,mxGetN,%
|
|
|
- mxGetName,mxGetNzmax,mxGetPi,mxGetPr,mxGetScalar,mxGetString,%
|
|
|
- mxIsComplex,mxIsFull,mxIsNumeric,mxIsSparse,mxIsString,%
|
|
|
- mxIsTypeDouble,mxSetIr,mxSetJc,mxSetM,mxSetN,mxSetName,mxSetNzmax,%
|
|
|
- mxSetPi,mxSetPr,NaN,nargchk,nargin,nargout,newplot,nextpow2,nnls,%
|
|
|
- nnz,nonzeros,norm,normest,null,num2str,nzmax,ode23,ode45,orient,%
|
|
|
- orth,pack,pascal,patch,path,pause,pcolor,pi,pink,pinv,plot,plot3,%
|
|
|
- pol2cart,polar,poly,polyder,polyeig,polyfit,polyval,polyvalm,pow2,%
|
|
|
- print,printopt,prism,prod,pwd,qr,qrdelete,qrinsert,quad,quad8,quit,%
|
|
|
- quiver,qz,rand,randn,randperm,rank,rat,rats,rbbox,rcond,real,%
|
|
|
- realmax,realmin,refresh,rem,reset,reshape,residue,return,rgb2hsv,%
|
|
|
- rgbplot,rootobject,roots,rose,rosser,rot90,rotate,round,rref,%
|
|
|
- rrefmovie,rsf2csf,save,saxis,schur,sec,sech,semilogx,semilogy,set,%
|
|
|
- setstr,shading,sign,sin,sinh,size,slice,sort,sound,spalloc,sparse,%
|
|
|
- spaugment,spconvert,spdiags,specular,speye,spfun,sph2cart,sphere,%
|
|
|
- spinmap,spline,spones,spparms,sprandn,sprandsym,sprank,sprintf,spy,%
|
|
|
- sqrt,sqrtm,sscanf,stairs,startup,std,stem,str2mat,str2num,strcmp,%
|
|
|
- strings,strrep,strtok,subplot,subscribe,subspace,sum,surf,surface,%
|
|
|
- surfc,surfl,surfnorm,svd,symbfact,symmmd,symrcm,tan,tanh,tempdir,%
|
|
|
- tempname,terminal,text,tic,title,tmp,toc,toeplitz,trace,trapz,tril,%
|
|
|
- triu,type,uicontrol,uigetfile,uimenu,uiputfile,unix,unwrap,upper,%
|
|
|
- vander,ver,version,view,viewmtx,waitforbuttonpress,waterfall,%
|
|
|
- wavread,wavwrite,what,whatsnew,which,while,white,whitebg,who,whos,%
|
|
|
- wilkinson,wk1read,wk1write,xlabel,xor,ylabel,zeros,zlabel,zoom}%
|
|
|
-\endgroup %
|
|
|
+% \begin{macrocode}
|
|
|
+%<*fancyvrb>
|
|
|
% \end{macrocode}
|
|
|
+% We will use |@|-protected names:
|
|
|
% \begin{macrocode}
|
|
|
-\begingroup \makeatletter %
|
|
|
-\catcode`\"=12 %
|
|
|
-\gdef\lstdrv@matlab@{%
|
|
|
- \keywords{\lstdrv@matlab@keys}%
|
|
|
- \sensitivetrue %
|
|
|
- \DeclareCLPercent %
|
|
|
- \DeclareSingleComment stuff \relax %
|
|
|
- \stringizer{'}\lstbaseem{0.6}%
|
|
|
- \lst@DefineCatcodes{\active}%
|
|
|
- \let\lst@PrePL \lst@PrePLDefault %
|
|
|
- \let\lst@PostPL\lst@PostPLDefault}%
|
|
|
-\endgroup %
|
|
|
-%</matlab>
|
|
|
+\begingroup \makeatletter
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}\end{macro}
|
|
|
-%
|
|
|
-%
|
|
|
-% \subsection{Modula-2}
|
|
|
-% \begin{macro}{\lstdrv@modula@}
|
|
|
-% And once again \ldots
|
|
|
-% \begin{macrocode}
|
|
|
-%<*modula>
|
|
|
-\begingroup \makeatletter %
|
|
|
-\catcode`\"=12 \catcode`\*=\active %
|
|
|
-\gdef\lstdrv@modula@{%
|
|
|
- \keywords{AND,ARRAY,BEGIN,BY,CASE,CONST,DIV,DO,ELSE,ELSIF,END,EXIT,%
|
|
|
- EXPORT,FOR,FROM,IF,IMPLEMENTATION,IMPORT,IN,MOD,MODULE,NOT,OF,%
|
|
|
- OR,POINTER,PROCEDURE,QUALIFIED,RECORD,REPEAT,RETURN,SET,THEN,%
|
|
|
- TYPE,UNTIL,VAR,WHILE,WITH,ABS,BITSET,BOOLEAN,CAP,CARDINAL,CHAR,%
|
|
|
- CHR,DEC,EXCL,FALSE,FLOAT,HALT,HIGH,INC,INCL,INTEGER,LONGCARD,%
|
|
|
- LONGINT,LONGREAL,MAX,MIN,NIL,ODD,ORD,PROC,REAL,SIZE,TRUE,TRUNC,%
|
|
|
- VAL}%
|
|
|
- \sensitivetrue %
|
|
|
- \DeclareCommentLine\relax %
|
|
|
- \DeclareNestedComment (* *)\relax %
|
|
|
- \stringizer[d]{'"}\lstbaseem{0.65}%
|
|
|
- \lst@DefineCatcodes{\active}%
|
|
|
- \let\lst@PrePL \lst@PrePLDefault %
|
|
|
- \let\lst@PostPL\lst@PostPLDefault}%
|
|
|
-\endgroup %
|
|
|
-%</modula>
|
|
|
-% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
-%
|
|
|
-%
|
|
|
-% \subsection{Oberon-2}
|
|
|
-% \begin{macro}{\lstdrv@oberon@}
|
|
|
-% 'Nearly' Modula-2:
|
|
|
-% \begin{macrocode}
|
|
|
-%<*oberon>
|
|
|
-\begingroup \makeatletter %
|
|
|
-\catcode`\"=12 \catcode`\*=\active %
|
|
|
-\gdef\lstdrv@oberon@{%
|
|
|
- \keywords{ARRAY,BEGIN,BOOLEAN,BY,CASE,CHAR,CONST,DIV,DO,ELSE,ELSIF,%
|
|
|
- END,EXIT,FALSE,FOR,IF,IMPORT,IN,INTEGER,IS,LONGINT,LONGREAL,%
|
|
|
- LOOP,MOD,MODULE,NIL,OF,OR,POINTER,PROCEDURE,REAL,RECORD,REPEAT,%
|
|
|
- RETURN,SET,SHORTINT,THEN,TO,TRUE,TYPE,UNTIL,VAR,WHILE,WITH,%
|
|
|
- ABS,ASH,CAP,CHR,COPY,DEC,ENTIER,EXCL,HALT,INC,INCL,LEN,LONG,%
|
|
|
- MAX,MIN,NEW,ODD,ORD,SHORT,SIZE}
|
|
|
- \sensitivetrue %
|
|
|
- \DeclareCommentLine\relax %
|
|
|
- \DeclareNestedComment (* *)\relax %
|
|
|
- \stringizer[d]{'"}\lstbaseem{0.65}%
|
|
|
- \lst@DefineCatcodes{\active}%
|
|
|
- \let\lst@PrePL \lst@PrePLDefault %
|
|
|
- \let\lst@PostPL\lst@PostPLDefault}%
|
|
|
-\endgroup %
|
|
|
-%</oberon>
|
|
|
-% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
-%
|
|
|
-%
|
|
|
-% \subsection{Pascal}
|
|
|
-% \begin{macro}{\lstdrv@pascal@}
|
|
|
-% Since we already defined pascal comments in section \ref{ssComments},
|
|
|
-% no catcodes must be changed here.
|
|
|
-% \begin{macrocode}
|
|
|
-%<*pascal>
|
|
|
-\begingroup \makeatletter %
|
|
|
-\gdef\lstdrv@pascal@{%
|
|
|
- \keywords{alfa,and,array,begin,boolean,byte,case,char,const,div,do,%
|
|
|
- downto,else,end,false,file,for,function,get,goto,if,in,integer,%
|
|
|
- label,maxint,mod,new,not,of,or,pack,packed,page,program,%
|
|
|
- procedure,put,read,readln,real,record,repeat,reset,rewrite,set,%
|
|
|
- text,then,to,true,type,unpack,until,var,while,with,write,%
|
|
|
- writeln}%
|
|
|
- \sensitivefalse %
|
|
|
- \DeclareCommentLine\relax %
|
|
|
- \DeclareDoubleCommentPascal %
|
|
|
- \stringizer[d]{'}\lstbaseem{0.6}%
|
|
|
- \lst@DefineCatcodes{\active}%
|
|
|
- \let\lst@PrePL \lst@PrePLDefault %
|
|
|
- \let\lst@PostPL\lst@PostPLDefault}%
|
|
|
-\endgroup %
|
|
|
-%</pascal>
|
|
|
+% \endgroup
|
|
|
+% \begin{macro}{\lstFV@Def}
|
|
|
+% \begin{macro}{\lstFV@Let}
|
|
|
+% \begin{macro}{\lstFV@Use}
|
|
|
+% \begin{macro}{\lstFV@ECUse}
|
|
|
+% \begin{macro}{\lstFV@Tabulator}
|
|
|
+% \begin{macro}{\lstFV@Space}
|
|
|
+% \begin{macro}{\lstFV@Stringizer@}
|
|
|
+% These are copies of the |\lstCC@|\ldots\ macros, but all catcode changes are removed.
|
|
|
+% \begin{macrocode}
|
|
|
+\gdef\lstFV@Def#1{\lccode`\~=#1\lowercase{\def~}}%
|
|
|
+\gdef\lstFV@Let#1{\lccode`\~=#1\lowercase{\let~}}%
|
|
|
+% \end{macrocode}
|
|
|
+% \begin{macrocode}
|
|
|
+\gdef\lstFV@Use#1#2#3{%
|
|
|
+ \ifnum#2=\z@ %
|
|
|
+ \expandafter\@gobbletwo %
|
|
|
+ \else %
|
|
|
+ \lccode`\~=#2\lowercase{\def~}{#1#3}%
|
|
|
+ \fi %
|
|
|
+ \lstFV@Use#1}%
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
-%
|
|
|
-%
|
|
|
-% \subsection{Pascal XSC}
|
|
|
-% \begin{macro}{\lstdrv@pxsc@}
|
|
|
-% Tell me, if you want more words to be keywords.
|
|
|
% \begin{macrocode}
|
|
|
-%<*pxsc>
|
|
|
-\selectlisting{pascal}%
|
|
|
-\begingroup \makeatletter %
|
|
|
-\gdef\lstdrv@pxsc@{\lstdrv@pascal@ %
|
|
|
- \morekeywords{dynamic,external,forward,global,module,nil,operator,%
|
|
|
- priority,sum,type,use,dispose,mark,page,release,cimatrix,%
|
|
|
- cinterval,civector,cmatrix,complex,cvector,dotprecision,%
|
|
|
- imatrix,interval,ivector,rmatrix,rvector,string,im,inf,re,sup,%
|
|
|
- chr,comp,eof,eoln,expo,image,ival,lb,lbound,length,loc,mant,%
|
|
|
- maxlength,odd,ord,pos,pred,round,rval,sign,substring,succ,%
|
|
|
- trunc,ub,ubound}}%
|
|
|
-\endgroup %
|
|
|
-%</pxsc>
|
|
|
-% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
-%
|
|
|
-%
|
|
|
-% \subsection{Turbo Pascal}
|
|
|
-% \begin{macro}{\lstdrv@tp@}
|
|
|
-% The keywords are the reserved words and predefined functions and
|
|
|
-% procedures of Turbo Pascal 6.0, I think. It's a long list \ldots
|
|
|
-% \begin{macrocode}
|
|
|
-%<*tp>
|
|
|
-\selectlisting{pascal}%
|
|
|
-\begingroup \makeatletter %
|
|
|
-\gdef\lstdrv@tp@{\lstdrv@pascal@ %
|
|
|
- \morekeywords{asm,constructor,destructor,implementation,inline,%
|
|
|
- interface,nil,object,shl,shr,string,unit,uses,xor,%
|
|
|
- Abs,Addr,ArcTan,Chr,Concat,Copy,Cos,CSeg,DiskFree,DiskSize,%
|
|
|
- DosExitCode,DosVersion,DSeg,EnvCount,EnvStr,Eof,Eoln,Exp,%
|
|
|
- FExpand,FilePos,FileSize,Frac,FSearch,GetBkColor,GetColor,%
|
|
|
- GetDefaultPalette,GetDriverName,GetEnv,GetGraphMode,GetMaxMode,%
|
|
|
- GetMaxX,GetMaxY,GetModeName,GetPaletteSize,GetPixel,GetX,GetY,%
|
|
|
- GraphErrorMsg,GraphResult,Hi,ImageSize,InstallUserDriver,%
|
|
|
- InstallUserFont,Int,IOResult,KeyPressed,Length,Lo,MaxAvail,%
|
|
|
- MemAvail,MsDos,Odd,Ofs,Ord,OvrGetBuf,OvrGetRetry,ParamCount,%
|
|
|
- ParamStr,Pi,Pos,Pred,Ptr,Random,ReadKey,Round,SeekEof,SeekEoln,%
|
|
|
- Seg,SetAspectRatio,Sin,SizeOf,Sound,SPtr,Sqr,Sqrt,SSeg,Succ,%
|
|
|
- Swap,TextHeight,TextWidth,Trunc,TypeOf,UpCase,WhereX,WhereY,%
|
|
|
- Append,Arc,Assign,AssignCrt,Bar,Bar3D,BlockRead,BlockWrite,%
|
|
|
- ChDir,Circle,ClearDevice,ClearViewPort,Close,CloseGraph,ClrEol,%
|
|
|
- ClrScr,Dec,Delay,Delete,DelLine,DetectGraph,Dispose,DrawPoly,%
|
|
|
- Ellipse,Erase,Exec,Exit,FillChar,FillEllipse,FillPoly,%
|
|
|
- FindFirst,FindNext,FloodFill,Flush,FreeMem,FSplit,GetArcCoords,%
|
|
|
- GetAspectRatio,GetDate,GetDefaultPalette,GetDir,GetCBreak,%
|
|
|
- GetFAttr,GetFillSettings,GetFTime,GetImage,GetIntVec,%
|
|
|
- GetLineSettings,GetMem,GetPalette,GetTextSettings,GetTime,%
|
|
|
- GetVerify,GetViewSettings,GoToXY,Halt,HighVideo,Inc,InitGraph,%
|
|
|
- Insert,InsLine,Intr,Keep,Line,LineRel,LineTo,LowVideo,Mark,%
|
|
|
- MkDir,Move,MoveRel,MoveTo,MsDos,New,NormVideo,NoSound,OutText,%
|
|
|
- OutTextXY,OvrClearBuf,OvrInit,OvrInitEMS,OvrSetBuf,PackTime,%
|
|
|
- PieSlice,PutImage,PutPixel,Randomize,Rectangle,Release,Rename,%
|
|
|
- RestoreCrtMode,RmDir,RunError,Sector,Seek,SetActivePage,%
|
|
|
- SetAllPalette,SetBkColor,SetCBreak,SetColor,SetDate,SetFAttr,%
|
|
|
- SetFillPattern,SetFillStyle,SetFTime,SetGraphBufSize,%
|
|
|
- SetGraphMode,SetIntVec,SetLineStyle,SetPalette,SetRGBPalette,%
|
|
|
- SetTextBuf,SetTextJustify,SetTextStyle,SetTime,SetUserCharSize,%
|
|
|
- SetVerify,SetViewPort,SetVisualPage,SetWriteMode,Sound,Str,%
|
|
|
- SwapVectors,TextBackground,TextColor,TextMode,Truncate,%
|
|
|
- UnpackTime,Val,Window}}%
|
|
|
-\endgroup %
|
|
|
-%</tp>
|
|
|
+\gdef\lstFV@ECUse#1#2{%
|
|
|
+ \ifnum`#2=\z@ %
|
|
|
+ \expandafter\@gobbletwo %
|
|
|
+ \else %
|
|
|
+ \ifnum\catcode`#2=\active %
|
|
|
+ \lccode`\~=`#2\lccode`\/=`#2\lowercase{\lstCC@ECUse@#1~/}%
|
|
|
+ \else %
|
|
|
+ \lccode`\~=`#2\lowercase{\def~}{#1#2}%
|
|
|
+ \fi %
|
|
|
+ \fi %
|
|
|
+ \lstFV@ECUse#1}%
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
-%
|
|
|
-%
|
|
|
-% \subsection{Perl}
|
|
|
-% \begin{macro}{\lstdrv@perl@keys}
|
|
|
-% First the keywords, \ldots
|
|
|
% \begin{macrocode}
|
|
|
-%<*perl>
|
|
|
-\begingroup \makeatletter %
|
|
|
-\lst@MakeDigitsLetter %
|
|
|
-\gdef\lstdrv@perl@keys{abs,accept,alarm,atan2,bind,binmode,bless,%
|
|
|
- caller,chdir,chmod,chomp,chop,chown,chr,chroot,close,closedir,%
|
|
|
- connect,continue,cos,crypt,dbmclose,dbmopen,defined,delete,die,do,%
|
|
|
- dump,each,else,elsif,endgrent,endhostent,endnetent,endprotoent,%
|
|
|
- endpwent,endservent,eof,eval,exec,exists,exit,exp,fcntl,fileno,%
|
|
|
- flock,for,foreach,fork,format,formline,getc,getgrent,getgrgid,%
|
|
|
- getgrnam,gethostbyaddr,gethostbyname,gethostent,getlogin,%
|
|
|
- getnetbyaddr,getnetbyname,getnetent,getpeername,getpgrp,getppid,%
|
|
|
- getpriority,getprotobyname,getprotobynumber,getprotoent,getpwent,%
|
|
|
- getpwnam,getpwuid,getservbyname,getservbyport,getservent,%
|
|
|
- getsockname,getsockopt,glob,gmtime,goto,grep,hex,if,import,index,%
|
|
|
- int,ioctl,join,keys,kill,last,lc,lcfirst,length,link,listen,local,%
|
|
|
- localtime,log,lstat,m,map,mkdir,msgctl,msgget,msgrcv,msgsnd,my,%
|
|
|
- next,no,oct,open,opendir,ord,pack,package,pipe,pop,pos,print,%
|
|
|
- printf,prototype,push,q,qq,quotemeta,qw,qx,rand,read,readdir,%
|
|
|
- readlink,recv,redo,ref,rename,require,reset,return,reverse,%
|
|
|
- rewinddir,rindex,rmdir,s,scalar,seek,seekdir,select,semctl,semget,%
|
|
|
- semop,send,setgrent,sethostent,setnetent,setpgrp,setpriority,%
|
|
|
- setprotoent,setpwent,setservent,setsockopt,shift,shmctl,shmget,%
|
|
|
- shmread,shmwrite,shutdown,sin,sleep,socket,socketpair,sort,splice,%
|
|
|
- split,sprintf,sqrt,srand,stat,study,sub,substr,symlink,syscall,%
|
|
|
- sysopen,sysread,system,syswrite,tell,telldir,tie,tied,time,times,%
|
|
|
- tr,truncate,uc,ucfirst,umask,undef,unless,unlink,unpack,unshift,%
|
|
|
- untie,until,use,utime,values,vec,wait,waitpid,wantarray,warn,while,%
|
|
|
- write,y}%
|
|
|
-\endgroup %
|
|
|
+\gdef\lstFV@Tabulator#1{\lstFV@Let{#1}\lstCC@ProcessTabulator}%
|
|
|
+\gdef\lstFV@Space#1{\lstFV@Let{#1}\lstCC@ProcessSpace}%
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
+% \begin{macrocode}
|
|
|
+\gdef\lstFV@Stringizer@#1#2{%
|
|
|
+ \ifx\@empty#2%
|
|
|
+ \expandafter\@gobbletwo %
|
|
|
+ \else %
|
|
|
+ \lccode`\~=`#2\lccode`\/=`#2%
|
|
|
+ \lowercase{%
|
|
|
+ \expandafter\let\csname lsts@s/\endcsname~%
|
|
|
+ \def~{#1/}}%
|
|
|
+ \fi %
|
|
|
+ \lstFV@Stringizer@#1}%
|
|
|
+% \end{macrocode}
|
|
|
+% \end{macro}\end{macro}\end{macro}\end{macro}
|
|
|
+% \end{macro}\end{macro}\end{macro}
|
|
|
%
|
|
|
-% \begin{macro}{\lstdrv@perl@}
|
|
|
-% {\ldots} and now the main driver file macro.
|
|
|
+% \begin{macro}{\lstFV@FancyVerbFormatLine}
|
|
|
+% This macro will be assigned to |\FancyVerbFormatLine|: We convert the argument and typeset it.
|
|
|
% \begin{macrocode}
|
|
|
-\begingroup \makeatletter %
|
|
|
-\catcode`\"=12 \catcode`\#=12 %
|
|
|
-\gdef\lstdrv@perl@{%
|
|
|
- \keywords{\lstdrv@perl@keys}%
|
|
|
- \sensitivetrue %
|
|
|
- \DeclareCommentLine#\relax %
|
|
|
- \DeclareSingleComment stuff \relax %
|
|
|
- \stringizer[b]{"'}\lstbaseem{0.6}%
|
|
|
- \lst@DefineCatcodes{\active}%
|
|
|
- \let\lst@PrePL \lstdrv@perl@PrePL %
|
|
|
- \let\lst@PostPL\relax}%
|
|
|
+\gdef\lstFV@FancyVerbFormatLine#1{%
|
|
|
+ \let\lstenv@arg\@empty\lstenv@AddArg{#1}%
|
|
|
+ \lstenv@arg \lst@PrintToken\lst@EOLUpdate}%
|
|
|
% \end{macrocode}
|
|
|
+% \begin{TODO}
|
|
|
+% This old macro is overwritten below.
|
|
|
+% \end{TODO}
|
|
|
% \end{macro}
|
|
|
%
|
|
|
-% \begin{macro}{\lstdrv@perl@ifPOD}
|
|
|
-% \begin{macro}{\lstdrv@perl@PrepareListing}
|
|
|
-% We use a switch to indicate PODs. Every (Perl) listing
|
|
|
-% \verb!\lst@Begin! calls the macro \verb!\lstdrv@perl@PrepareListing!
|
|
|
-% to reset the switch.
|
|
|
+% \begin{macro}{\lstfancyvrb@}
|
|
|
+% The command assigns some new macros (if it's not already done).
|
|
|
% \begin{macrocode}
|
|
|
-\gdef\lstdrv@perl@PODtrue{\let\lstdrv@perl@ifPOD\iftrue}%
|
|
|
-\gdef\lstdrv@perl@PODfalse{\let\lstdrv@perl@ifPOD\iffalse}%
|
|
|
-\gdef\lstdrv@perl@PrepareListing{\lstdrv@perl@PODfalse}%
|
|
|
+\gdef\lstfancyvrb@{%
|
|
|
+ \ifx\FV@VerbatimBegin\lstFV@VerbatimBegin\else %
|
|
|
+ \let\lstFV@OldVB\FV@VerbatimBegin %
|
|
|
+ \let\lstFV@OldVE\FV@VerbatimEnd %
|
|
|
+ \let\FV@VerbatimBegin\lstFV@VerbatimBegin %
|
|
|
+ \let\FV@VerbatimEnd\lstFV@VerbatimEnd %
|
|
|
+ \fi %
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}\end{macro}
|
|
|
-%
|
|
|
-% \begin{macro}{\lstdrv@perl@PrePL}
|
|
|
-% \begin{macro}{\lstdrv@perl@TestComment}
|
|
|
-% \begin{macro}{\lstdrv@perl@TestCommentCut}
|
|
|
-% \begin{macro}{\lstdrv@perl@TestSharp}
|
|
|
-% Nothing else is really new now.
|
|
|
-% \begin{macrocode}
|
|
|
-\gdef\lstdrv@perl@PrePL{%
|
|
|
- \lst@ifstring %
|
|
|
- \lst@stringfalse \lst@ProcessWhitespaces \lst@stringtrue %
|
|
|
- \else\lstdrv@perl@ifPOD %
|
|
|
- \expandafter\lstdrv@perl@TestCommentCut\lst@line=cut\relax %
|
|
|
- \else \expandafter\lstdrv@perl@TestComment\lst@line\relax\relax %
|
|
|
- \fi \fi}%
|
|
|
-\gdef\lstdrv@perl@TestCommentCut#1=cut#2\relax{%
|
|
|
- \lst@commenttrue \expandafter\lst@Tokenize\lst@line\relax %
|
|
|
- \let\lst@line\@empty \lst@commentfalse %
|
|
|
- \ifx\@empty#2\@empty\else \lstdrv@perl@PODfalse \fi}%
|
|
|
-% \end{macrocode}
|
|
|
-% We have to change some catcodes, to look for the sharp. In particular
|
|
|
-% we need a new 'macro parameter symbol' ($\&$).
|
|
|
-% \begin{macrocode}
|
|
|
-\catcode`\$=11 \catcode`\&=6 \catcode`\#=12 %
|
|
|
-\gdef\lstdrv@perl@TestComment&1&2\relax{%
|
|
|
- \ifx &1=%
|
|
|
- \lstdrv@perl@PODtrue \lst@commenttrue %
|
|
|
- \expandafter\lst@Tokenize\lst@line\relax %
|
|
|
- \let\lst@line\@empty \lst@commentfalse %
|
|
|
+% And we assign the correct |\FancyVerbFormatLine| macro.
|
|
|
+% \begin{macrocode}
|
|
|
+ \lst@iffancyvrb %
|
|
|
+ \ifx\FancyVerbFormatLine\lstFV@FancyVerbFormatLine\else %
|
|
|
+ \let\lstFV@FVFL\FancyVerbFormatLine %
|
|
|
+ \let\FancyVerbFormatLine\lstFV@FancyVerbFormatLine %
|
|
|
+ \fi %
|
|
|
\else %
|
|
|
- \expandafter\lstdrv@perl@TestSharp\lst@line $#\relax %
|
|
|
+ \ifx\lstFV@FVFL\@undefined\else %
|
|
|
+ \let\FancyVerbFormatLine\lstFV@FVFL %
|
|
|
+ \fi %
|
|
|
\fi}%
|
|
|
% \end{macrocode}
|
|
|
-% The \cs{lowercase} mechanism mentioned some time before to replace
|
|
|
-% each \verb!$#! with \verb!$#!, where the latter \verb!#! has letter
|
|
|
-% catcode. This avoids wrong comment detection.
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lstFV@VerbatimBegin}
|
|
|
+% We initialize things if necessary.
|
|
|
% \begin{macrocode}
|
|
|
-\catcode`\~=11 \lccode`\~=`\#%
|
|
|
-\lowercase{%
|
|
|
-\gdef\lstdrv@perl@TestSharp&1$#&2\relax{%
|
|
|
- \ifx \@empty&2\@empty \else %
|
|
|
- \expandafter\lstdrv@perl@ReplaceSharp\lst@line\relax %
|
|
|
- \expandafter\lstdrv@perl@TestSharp\lst@line $#\relax %
|
|
|
- \fi}%
|
|
|
-\gdef\lstdrv@perl@ReplaceSharp&1$#&2\relax{\def\lst@line{&1$~&2}}%
|
|
|
-}\endgroup %
|
|
|
-%</perl>
|
|
|
+\gdef\lstFV@VerbatimBegin{%
|
|
|
+ \lstFV@OldVB %
|
|
|
+ \ifx\FancyVerbFormatLine\lstFV@FancyVerbFormatLine %
|
|
|
+ \lst@DontEscapeToLaTeX %
|
|
|
+ \let\smallbreak\relax \let\normalbaselines\relax %
|
|
|
+ \let\lst@prelisting\relax \let\lst@postlisting\relax %
|
|
|
+ \def\lst@firstline{1}\def\lst@lastline{999999}%
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}\end{macro}\end{macro}\end{macro}
|
|
|
-%
|
|
|
-%
|
|
|
-% \subsection{PL/I}
|
|
|
-% \begin{macro}{\lstdrv@pli@keys}
|
|
|
-% \begin{macro}{\lstdrv@pli@}
|
|
|
-% Same procedure \ldots
|
|
|
-% \begin{macrocode}
|
|
|
-%<*pli>
|
|
|
-\begingroup \makeatletter %
|
|
|
-\lst@MakeDigitsLetter %
|
|
|
-\gdef\lstdrv@pli@keys{ABS,ATAN,AUTOMATIC,AUTO,ATAND,BEGIN,BINARY,BIN,%
|
|
|
- BIT,BUILTIN,BY,CALL,CHARACTER,CHAR,CHECK,COLUMN,COL,COMPLEX,CPLX,%
|
|
|
- COPY,COS,COSD,COSH,DATA,DATE,DECIMAL,DEC,DECLARE,DCL,DO,EDIT,ELSE,%
|
|
|
- END,ENDFILE,ENDPAGE,ENTRY,EXP,EXTERNAL,EXT,FINISH,FIXED,%
|
|
|
- FIXEDOVERFLOW,FOFL,FLOAT,FORMAT,GET,GO,GOTO,IF,IMAG,INDEX,INITIAL,%
|
|
|
- INIT,INTERNAL,INT,LABEL,LENGTH,LIKE,LINE,LIST,LOG,LOG2,LOG10,MAIN,%
|
|
|
- MAX,MIN,MOD,NOCHECK,NOFIXEDOVERFLOW,NOFOFL,NOOVERFLOW,NOOFL,NOSIZE,%
|
|
|
- NOUNDERFLOW,NOUFL,NOZERODIVIDE,NOZDIV,ON,OPTIONS,OVERFLOW,OFL,PAGE,%
|
|
|
- PICTURE,PROCEDURE,PROC,PUT,READ,REPEAT,RETURN,RETURNS,ROUND,SIN,%
|
|
|
- SIND,SINH,SIZE,SKIP,SQRT,STATIC,STOP,STRING,SUBSTR,SUM,SYSIN,%
|
|
|
- SYSPRINT,TAN,TAND,TANH,THEN,TO,UNDERFLOW,UFL,VARYING,WHILE,WRITE,%
|
|
|
- ZERODIVIDE,ZDIV}%
|
|
|
-\endgroup %
|
|
|
-\begingroup \makeatletter %
|
|
|
-\catcode`\*=\active %
|
|
|
-\gdef\lstdrv@pli@{%
|
|
|
- \keywords{\lstdrv@pli@keys}%
|
|
|
- \sensitivefalse %
|
|
|
- \DeclareCommentLine\relax %
|
|
|
- \DeclareSingleComment /* */\relax %
|
|
|
- \stringizer{'}\lstbaseem{0.6}%
|
|
|
- \lst@DefineCatcodes{\active}%
|
|
|
- \let\lst@PrePL \lst@PrePLDefault %
|
|
|
- \let\lst@PostPL\lst@PostPLDefault}%
|
|
|
-\endgroup %
|
|
|
-%</pli>
|
|
|
+% \begin{macrocode}
|
|
|
+ \let\lstCC@Use\lstFV@Use %
|
|
|
+ \let\lstCC@ECUse\lstFV@ECUse %
|
|
|
+ \let\lstCC@Tabulator\lstFV@Tabulator %
|
|
|
+ \let\lstCC@Space\lstFV@Space %
|
|
|
+ \let\lstCC@Stringizer@\lstFV@Stringizer@ %
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}\end{macro}
|
|
|
-%
|
|
|
-%
|
|
|
-% \subsection{Simula}
|
|
|
-% \begin{macro}{\lstdrv@simula@}
|
|
|
-% Same as all the time.
|
|
|
-% \begin{macrocode}
|
|
|
-%<*simula>
|
|
|
-\begingroup \makeatletter %
|
|
|
-\catcode`\"=12 %
|
|
|
-\gdef\lstdrv@simula@{%
|
|
|
- \keywords{activate,after,array,at,before,begin,boolean,character,%
|
|
|
- class,comment,delay,detach,do,else,end,external,false,for,go,%
|
|
|
- goto,if,in,inner,inspect,integer,is,label,name,new,none,notext,%
|
|
|
- otherwise,prior,procedure,qua,reactivate,real,ref,resume,%
|
|
|
- simset,simulation,step,switch,text,then,this,to,true,until,%
|
|
|
- value,virtual,when,while}%
|
|
|
- \sensitivefalse %
|
|
|
- \DeclareCommentLine\relax %
|
|
|
- \DeclareSingleComment stuff \relax %
|
|
|
- \stringizer{"'}\lstbaseem{0.65}%
|
|
|
- \lst@DefineCatcodes{\active}%
|
|
|
- \let\lst@PrePL \lst@PrePLDefault %
|
|
|
- \let\lst@PostPL\lst@PostPLDefault}%
|
|
|
-% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
-%
|
|
|
-% \begin{macro}{\lstdrv@simula@67}
|
|
|
-% \begin{macro}{\lstdrv@simula@cii}
|
|
|
-% \begin{macro}{\lstdrv@simula@dec}
|
|
|
-% \begin{macro}{\lstdrv@simula@ibm}
|
|
|
-% Macros for the options:
|
|
|
-% \begin{macrocode}
|
|
|
-\global\@namedef{lstdrv@simula@67}{\lstdrv@simula@}%
|
|
|
-\global\@namedef{lstdrv@simula@cii}{\lstdrv@simula@%
|
|
|
- \morekeywords{and,equiv,exit,impl,not,or,stop}}%
|
|
|
-\global\@namedef{lstdrv@simula@dec}{\lstdrv@simula@%
|
|
|
- \morekeywords{and,eq,eqv,ge,gt,hidden,imp,le,long,lt,ne,not,%
|
|
|
- options,or,protected,short}}%
|
|
|
-\global\@namedef{lstdrv@simula@ibm}{\lstdrv@simula@dec}%
|
|
|
-\endgroup %
|
|
|
+% \begin{macrocode}
|
|
|
+ \def\lst@next{%
|
|
|
+ \lst@Init\relax %
|
|
|
+ \everypar{}\global\let\lst@NewLine\relax}%
|
|
|
+ \expandafter\lst@next %
|
|
|
+ \fi}%
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}\end{macro}\end{macro}\end{macro}
|
|
|
+% \end{macro}
|
|
|
%
|
|
|
-% \begin{macro}{\lstdrv@simula@PrepareListing}
|
|
|
-% \begin{macro}{\lstdrv@simula@OutputOther}
|
|
|
-% \begin{macro}{\lstdrv@simula@Output@}
|
|
|
-% \begin{macro}{\lstdrv@simula@AppendOther@}
|
|
|
-% Refer the section about Algol how comments are implemented.
|
|
|
-% \begin{macrocode}
|
|
|
-\begingroup \makeatletter %
|
|
|
-\gdef\lstdrv@simula@commenttrue{%
|
|
|
- \global\let\lstdrv@simula@ifcomment\iftrue}%
|
|
|
-\gdef\lstdrv@simula@commentfalse{%
|
|
|
- \global\let\lstdrv@simula@ifcomment\iffalse %
|
|
|
- \global\let\lstdrv@simula@closingcomment\@empty}%
|
|
|
-\gdef\lstdrv@simula@PrepareListing{%
|
|
|
- \lstdrv@simula@commentfalse %
|
|
|
- \let\lst@OutputOther\lstdrv@simula@OutputOther %
|
|
|
- \let\lst@Output\lstdrv@simula@Output@ %
|
|
|
- \let\lst@AppendOther\lstdrv@simula@AppendOther}%
|
|
|
-% \end{macrocode}
|
|
|
-% \begin{macrocode}
|
|
|
-\gdef\lstdrv@simula@OutputOther{%
|
|
|
- \expandafter\def\expandafter\lst@text\expandafter{\the\lst@other}%
|
|
|
- \ifx\lst@text\@empty\else %
|
|
|
- \lstdrv@simula@ifcomment\lst@MakeBox{\lst@commentstyle}\else %
|
|
|
- \lst@ifstring \lst@MakeStringBox{\lst@stringstyle}\else %
|
|
|
- \lst@ifcomment\lst@MakeBox{\lst@commentstyle}\else %
|
|
|
- \lst@MakeBox{}%
|
|
|
- \fi \fi \fi %
|
|
|
- \global\advance\lst@pos by -\lst@length %
|
|
|
- \lst@other{}\let\lst@text\@empty \lst@length0 %
|
|
|
- \fi}%
|
|
|
+% \begin{macro}{\lstFV@VerbatimEnd}
|
|
|
+% A (particular) box and macro must exist after |\lst@DeInit|.
|
|
|
+% We store them globally.
|
|
|
+% \begin{macrocode}
|
|
|
+\gdef\lstFV@VerbatimEnd{%
|
|
|
+ \ifx\FancyVerbFormatLine\lstFV@FancyVerbFormatLine %
|
|
|
+ \global\setbox\lstFV@gtempboxa\box\@tempboxa %
|
|
|
+ \global\let\@gtempa\FV@ProcessLine %
|
|
|
+ \lst@DeInit %
|
|
|
+ \let\FV@ProcessLine\@gtempa %
|
|
|
+ \setbox\@tempboxa\box\lstFV@gtempboxa %
|
|
|
+ \fi %
|
|
|
+ \lstFV@OldVE}%
|
|
|
% \end{macrocode}
|
|
|
% \begin{macrocode}
|
|
|
-\gdef\lstdrv@simula@Output@{%
|
|
|
- \ifx\lst@text\@empty\else %
|
|
|
- \lstdrv@simula@ifcomment %
|
|
|
- \ifx\@empty\lstdrv@simula@closingcomment %
|
|
|
- \lst@MakeBox{\lst@commentstyle}%
|
|
|
- \else %
|
|
|
- \expandafter\lst@ifoneof\lst@text\relax %
|
|
|
- {else,end,otherwise,when}%
|
|
|
- {\lstdrv@simula@commentfalse %
|
|
|
- \lst@MakeBox{\lst@keywordstyle}}%
|
|
|
- {\lst@MakeBox{\lst@commentstyle}}%
|
|
|
- \fi \else %
|
|
|
- \lst@ifstring \lst@MakeStringBox{\lst@stringstyle}\else %
|
|
|
- \lst@ifcomment\lst@MakeBox{\lst@commentstyle}\else %
|
|
|
- \expandafter\lst@KeywordOrNot\lst@text\relax %
|
|
|
- \expandafter\lst@ifoneof\lst@text\relax{comment,end}%
|
|
|
- {\lstdrv@simula@commenttrue %
|
|
|
- \expandafter\lst@ifoneof\lst@text\relax{end}%
|
|
|
- {\gdef\lstdrv@simula@closingcomment{a}}{}}%
|
|
|
- {}% empty else from 'ifoneof'
|
|
|
- \fi \fi \fi %
|
|
|
- \global\advance\lst@pos by -\lst@length %
|
|
|
- \let\lst@text\@empty \lst@length0 %
|
|
|
- \fi}%
|
|
|
+\newbox\lstFV@gtempboxa %
|
|
|
% \end{macrocode}
|
|
|
+% \end{macro}
|
|
|
+%
|
|
|
+% \begin{macro}{\lstFV@FancyVerbFormatLine}
|
|
|
+% A slightly different definition now: |\lstenv@AddArg{#1}| has been replaced by |\lstFV@Convert#1@|.
|
|
|
+% The '@' terminates the input |#1|.
|
|
|
% \begin{macrocode}
|
|
|
-\gdef\lstdrv@simula@AppendOther#1{%
|
|
|
- \lstdrv@simula@ifcomment \if;#1%
|
|
|
- \lst@OutputOther \lstdrv@simula@commentfalse %
|
|
|
- \fi \fi %
|
|
|
- \advance\lst@length\@ne %
|
|
|
- \expandafter\lst@other\expandafter{\the\lst@other#1}}%
|
|
|
-\endgroup %
|
|
|
-%</simula>
|
|
|
+\gdef\lstFV@FancyVerbFormatLine#1{%
|
|
|
+ \let\lst@arg\@empty\lstFV@Convert#1@%
|
|
|
+ \lst@arg \lst@PrintToken\lst@EOLUpdate}%
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}\end{macro}\end{macro}\end{macro}
|
|
|
-%
|
|
|
-%
|
|
|
-% \subsection{SQL}
|
|
|
-% \begin{macro}{\lstdrv@sql@}
|
|
|
-% Do you have corrections? Do you want more data base languages?
|
|
|
-% \begin{macrocode}
|
|
|
-%<*sql>
|
|
|
-\begingroup \makeatletter %
|
|
|
-\catcode`\"=12 \catcode`\*=\active \catcode`\_=11 %
|
|
|
-\gdef\lstdrv@sql@{%
|
|
|
- \keywords{absolute,action,add,allocate,alter,are,assertion,at,%
|
|
|
- between,bit,bit_length,both,cascade,cascaded,case,cast,catalog,%
|
|
|
- char_length,character_length,coalesce,collate,collation,column,%
|
|
|
- connect,connection,constraint,constraints,convert,%
|
|
|
- corresponding,cross,current_date,current_time,%
|
|
|
- current_timestamp,current_user,date,day,deallocate,deferrable,%
|
|
|
- defered,describe,descriptor,diagnostics,disconnect,domain,drop,%
|
|
|
- else,end,exec,except,exception,execute,external,extract,false,%
|
|
|
- first,full,get,global,hour,identity,immediate,initially,inner,%
|
|
|
- input,insensitive,intersect,interval,isolation,join,last,%
|
|
|
- leading,left,level,local,lower,match,minute,month,names,%
|
|
|
- national,natural,nchar,next,no,nullif,octet_length,only,outer,%
|
|
|
- output,overlaps,pad,partial,position,prepare,preserve,prior,%
|
|
|
- read,relative,restrict,revoke,right,rows,scroll,second,session,%
|
|
|
- session_user,size,space,sqlstate,substring,system_user,%
|
|
|
- temporary,then,time,timestamp,timezone_hour,timezone_minute,%
|
|
|
- trailing,transaction,translate,translation,trim,true,unknown,%
|
|
|
- upper,usage,using,value,varchar,varying,when,write,year,zone}%
|
|
|
- \sensitivefalse %
|
|
|
- \DeclareCommentLine\relax %
|
|
|
- \DeclareSingleComment /* */\relax %
|
|
|
- \stringizer{'"}\lstbaseem{0.6}%
|
|
|
- \lst@DefineCatcodes{\active}%
|
|
|
- \let\lst@PrePL \lst@PrePLDefault %
|
|
|
- \let\lst@PostPL\lst@PostPLDefault}%
|
|
|
-\endgroup %
|
|
|
-%</sql>
|
|
|
+% And this macro is to be defined right now.
|
|
|
+% \begin{macrocode}
|
|
|
+\gdef\lstFV@Convert{%
|
|
|
+ \@ifnextchar\bgroup{\lstFV@Convert@Arg}{\lstFV@Convert@}}%
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
-%
|
|
|
-%
|
|
|
-% \subsection{\TeX}
|
|
|
-% \begin{macro}{\lstdrv@tex@primitives}
|
|
|
-% \begin{macro}{\lstdrv@tex@commoncs}
|
|
|
-% \begin{macro}{\lstdrv@tex@latexcs}
|
|
|
-% We define the different classes of control sequences. The second macro
|
|
|
-% holds the common control sequences of plain-\TeX{} and \LaTeXe.
|
|
|
+% Coming to a begin group character ('\{' with catcode 1) we convert the and add the conversion together with group delimiters to |\lst@arg|.
|
|
|
+% We also add |\lst@PrintToken|, which prints all collected characters before we forget them.
|
|
|
+% Finally we continue the conversion.
|
|
|
% \begin{macrocode}
|
|
|
-%<*tex>
|
|
|
-\begingroup \makeatletter %
|
|
|
-\gdef\lstdrv@tex@primitives{above,abovedisplayshortskip,%
|
|
|
- abovedisplayskip,abovewithdelims,accent,adjdemerits,advance,%
|
|
|
- afterassignment,aftergroup,atop,atopwithdelims,badness,%
|
|
|
- baselineskip,batchmode,begingroup,belowdisplayshortskip,%
|
|
|
- belowdisplayskip,binoppenalty,botmark,box,boxmaxdepth,%
|
|
|
- brokenpenalty,catcode,char,chardef,cleaders,closein,closeout,%
|
|
|
- clubpenalty,copy,count,countdef,cr,crcr,csname,day,deadcycles,def,%
|
|
|
- defaulthyphenchar,defaultskewchar,delcode,delimiter,%
|
|
|
- delimiterfactor,delimitershortfall,dimen,dimendef,discretionary,%
|
|
|
- displayindent,displaylimits,displaystyle,displaywidowpenalty,%
|
|
|
- displaywidth,divide,doublehyphendemerits,dp,else,emergencystretch,%
|
|
|
- end,endcsname,endgroup,endinput,endlinechar,eqno,errhelp,%
|
|
|
- errmessage,errorcontextlines,errorstopmode,escapechar,everycr,%
|
|
|
- everydisplay,everyhbox,everyjob,everymath,everypar,everyvbox,%
|
|
|
- exhyphenpenalty,expandafter,fam,fi,finalhypendemerits,firstmark,%
|
|
|
- floatingpenalty,font,fontdimen,fontname,futurelet,gdef,global,%
|
|
|
- globaldefs,halign,hangafter,hangindent,hbadness,hbox,hfil,hfill,%
|
|
|
- hfilneg,hfuzz,hoffset,holdinginserts,hrule,hsize,hskip,hss,ht,%
|
|
|
- hyphenation,hyphenchar,hyphenpenalty,if,ifcase,ifcat,ifdim,ifeof,%
|
|
|
- iffalse,ifhbox,ifhmode,ifinner,ifmmode,ifnum,ifodd,iftrue,ifvbox,%
|
|
|
- ifvmode,ifvoid,ifx,ignorespaces,immediate,indent,input,insert,%
|
|
|
- insertpenalties,interlinepenalty,jobname,kern,language,lastbox,%
|
|
|
- lastkern,lastpenalty,lastskip,lccode,leaders,left,lefthyphenmin,%
|
|
|
- leftskip,leqno,let,limits,linepenalty,lineskip,lineskiplimits,long,%
|
|
|
- looseness,lower,lowercase,mag,mark,,mathaccent,mathbin,mathchar,%
|
|
|
- mathchardef,mathchoice,mathclose,mathcode,mathinner,mathop,%
|
|
|
- mathopen,mathord,mathpunct,mathrel,mathsurround,maxdeadcycles,%
|
|
|
- maxdepth,meaning,medmuskip,message,mkern,month,moveleft,moveright,%
|
|
|
- mskip,multiply,muskip,muskipdef,newlinechar,noalign,noboundary,%
|
|
|
- noexpand,noindent,nolimits,nonscript,nonstopmode,%
|
|
|
- nulldelimiterspace,nullfont,number,omit,openin,openout,or,outer,%
|
|
|
- output,outputpenalty,over,overfullrule,overline,overwithdelims,%
|
|
|
- pagedepth,pagefilllstretch,pagefillstretch,pagefilstretch,pagegoal,%
|
|
|
- pageshrink,pagestretch,pagetotal,par,parfillskip,parindent,%
|
|
|
- parshape,parskip,patterns,pausing,penalty,postdisplaypenalty,%
|
|
|
- predisplaypenalty,predisplaysize,pretolerance,prevdepth,prevgraf,%
|
|
|
- radical,raise,read,relax,relpenalty,right,righthyphenmin,rightskip,%
|
|
|
- romannumeral,scriptfont,scriptscriptfont,scriptscriptstyle,%
|
|
|
- scriptspace,scriptstyle,scrollmode,setbox,setlanguage,sfcode,%
|
|
|
- shipout,show,showbox,showboxbreadth,showboxdepth,showlists,showthe,%
|
|
|
- skewchar,skip,skipdef,spacefactor,spaceskip,span,special,%
|
|
|
- splitbotmark,splitfirstmark,splitmaxdepth,splittopskip,string,%
|
|
|
- tabskip,textfont,textstyle,the,thickmuskip,thinmuskip,time,toks,%
|
|
|
- toksdef,tolerance,topmark,topskip,tracingcommands,tracinglostchars,%
|
|
|
- tracingmacros,tracingonline,tracingoutput,tracingpages,%
|
|
|
- tracingparagraphs,tracingrestores,tracingstats,uccode,uchyph,%
|
|
|
- underline,unhbox,unhcopy,unkern,unpenalty,unskip,unvbox,unvcopy,%
|
|
|
- uppercase,vadjust,valign,vbadness,vbox,vcenter,vfil,vfill,vfilneg,%
|
|
|
- vfuzz,voffset,vrule,vsize,vskip,vsplit,vss,vtop,wd,widowpenalty,%
|
|
|
- write,xdef,xleaders,xspaceskip,year}%
|
|
|
-\gdef\lstdrv@tex@commoncs{active,acute,ae,AE,aleph,allocationnumber,%
|
|
|
- allowbreak,alpha,amalg,angle,approx,arccos,arcsin,arctan,arg,%
|
|
|
- arrowvert,Arrowvert,ast,asymp,b,backslash,bar,beta,bgroup,big,Big,%
|
|
|
- bigbreak,bigcap,bigcirc,bigcup,bigg,Bigg,biggl,Biggl,biggm,Biggm,%
|
|
|
- biggr,Biggr,bigl,Bigl,bigm,Bigm,bigodot,bigoplus,bigotimes,bigr,%
|
|
|
- Bigr,bigskip,bigskipamount,bigsqcup,bigtriangledown,bigtriangleup,%
|
|
|
- biguplus,bigvee,bigwedge,bmod,bordermatrix,bot,bowtie,brace,%
|
|
|
- braceld,bracelu,bracerd,braceru,bracevert,brack,break,breve,%
|
|
|
- buildrel,bullet,c,cap,cases,cdot,cdotp,cdots,centering,centerline,%
|
|
|
- check,chi,choose,circ,clubsuit,colon,cong,coprod,copyright,cos,%
|
|
|
- cosh,cot,coth,csc,cup,d,dag,dagger,dashv,ddag,ddagger,ddot,ddots,%
|
|
|
- deg,delta,Delta,det,diamond,diamondsuit,dim,displaylines,div,do,%
|
|
|
- dospecials,dot,doteq,dotfill,dots,downarrow,Downarrow,%
|
|
|
- downbracefill,egroup,eject,ell,empty,emptyset,endgraf,endline,%
|
|
|
- enskip,enspace,epsilon,equiv,eta,exists,exp,filbreak,flat,fmtname,%
|
|
|
- fmtversion,footins,footnote,footnoterule,forall,frenchspacing,%
|
|
|
- frown,gamma,Gamma,gcd,ge,geq,gets,gg,goodbreak,grave,H,hat,hbar,%
|
|
|
- heartsuit,hglue,hideskip,hidewidth,hom,hookleftarrow,%
|
|
|
- hookrightarrow,hphantom,hrulefill,i,ialign,iff,Im,imath,in,inf,%
|
|
|
- infty,int,interdisplaylinepenalty,interfootnotelinepenalty,intop,%
|
|
|
- iota,item,j,jmath,joinrel,jot,kappa,ker,l,L,lambda,Lambda,land,%
|
|
|
- langle,lbrace,lbrack,lceil,ldotp,ldots,le,leavevmode,leftarrow,%
|
|
|
- Leftarrow,leftarrowfill,leftharpoondown,leftharpoonup,leftline,%
|
|
|
- leftrightarrow,Leftrightarrow,leq,lfloor,lg,lgroup,lhook,lim,%
|
|
|
- liminf,limsup,line,ll,llap,lmoustache,ln,lnot,log,longleftarrow,%
|
|
|
- Longleftarrow,longleftrightarrow,Longleftrightarrow,longmapsto,%
|
|
|
- longrightarrow,Longrightarrow,loop,lor,lq,magstep,magstep,%
|
|
|
- magstephalf,mapsto,mapstochar,mathhexbox,mathpalette,mathstrut,%
|
|
|
- matrix,max,maxdimen,medbreak,medskip,medskipamount,mid,min,models,%
|
|
|
- mp,mu,multispan,nabla,narrower,natural,ne,nearrow,neg,negthinspace,%
|
|
|
- neq,newbox,newcount,newdimen,newfam,newif,newinsert,newlanguage,%
|
|
|
- newmuskip,newread,newskip,newtoks,newwrite,next,ni,nobreak,%
|
|
|
- nointerlineskip,nonfrenchspacing,normalbaselines,%
|
|
|
- normalbaselineskip,normallineskip,normallineskiplimit,not,notin,nu,%
|
|
|
- null,nwarrow,o,O,oalign,obeylines,obeyspaces,odot,oe,OE,%
|
|
|
- offinterlineskip,oint,ointop,omega,Omega,ominus,ooalign,openup,%
|
|
|
- oplus,oslash,otimes,overbrace,overleftarrow,overrightarrow,owns,P,%
|
|
|
- parallel,partial,perp,phantom,phi,Phi,pi,Pi,pm,pmatrix,pmod,Pr,%
|
|
|
- prec,preceq,prime,prod,propto,psi,Psi,qquad,quad,raggedbottom,%
|
|
|
- raggedright,rangle,rbrace,rbrack,rceil,Re,relbar,Relbar,%
|
|
|
- removelastskip,repeat,rfloor,rgroup,rho,rhook,rightarrow,%
|
|
|
- Rightarrow,rightarrowfill,rightharpoondown,rightharpoonup,%
|
|
|
- rightleftharpoons,rightline,rlap,rmoustache,root,rq,S,sb,searrow,%
|
|
|
- sec,setminus,sharp,showhyphens,sigma,Sigma,sim,simeq,sin,sinh,skew,%
|
|
|
- slash,smallbreak,smallint,smallskip,smallskipamount,smash,smile,sp,%
|
|
|
- space,spadesuit,sqcap,sqcup,sqrt,sqsubseteq,sqsupseteq,ss,star,%
|
|
|
- strut,strutbox,subset,subseteq,succ,succeq,sum,sup,supset,supseteq,%
|
|
|
- surd,swarrow,t,tan,tanh,tau,TeX,theta,Theta,thinspace,tilde,times,%
|
|
|
- to,top,tracingall,triangle,triangleleft,triangleright,u,underbar,%
|
|
|
- underbrace,uparrow,Uparrow,upbracefill,updownarrow,Updownarrow,%
|
|
|
- uplus,upsilon,Upsilon,v,varepsilon,varphi,varpi,varrho,varsigma,%
|
|
|
- vartheta,vdash,vdots,vec,vee,vert,Vert,vglue,vphantom,wedge,%
|
|
|
- widehat,widetilde,wlog,wp,wr,xi,Xi,zeta}%
|
|
|
-\gdef\lstdrv@tex@latexcs{a,AA,aa,addcontentsline,addpenalty,%
|
|
|
- addtocontents,addtocounter,addtolength,addtoversion,addvspace,alph,%
|
|
|
- Alph,and,arabic,array,arraycolsep,arrayrulewidth,arraystretch,%
|
|
|
- author,baselinestretch,begin,bezier,bfseries,bibcite,bibdata,%
|
|
|
- bibitem,bibliography,bibliographystyle,bibstyle,boldmath,%
|
|
|
- botfigrule,bottomfraction,Box,caption,center,CheckCommand,circle,%
|
|
|
- citation,cite,cleardoublepage,clearpage,cline,columnsep,%
|
|
|
- columnseprule,columnwidth,contentsline,dashbox,date,dblfigrule,%
|
|
|
- dblfloatpagefraction,dblfloatsep,dbltextfloatsep,dbltopfraction,%
|
|
|
- defaultscriptratio,defaultscriptscriptratio,depth,Diamond,%
|
|
|
- displaymath,document,documentclass,documentstyle,doublerulesep,em,%
|
|
|
- emph,endarray,endcenter,enddisplaymath,enddocument,endenumerate,%
|
|
|
- endeqnarray,endequation,endflushleft,endflushright,enditemize,%
|
|
|
- endlist,endlrbox,endmath,endminipage,endpicture,endsloppypar,%
|
|
|
- endtabbing,endtabular,endtrivlist,endverbatim,enlargethispage,%
|
|
|
- ensuremath,enumerate,eqnarray,equation,evensidemargin,extracolsep,%
|
|
|
- fbox,fboxrule,fboxsep,filecontents,fill,floatpagefraction,floatsep,%
|
|
|
- flushbottom,flushleft,flushright,fnsymbol,fontencoding,fontfamily,%
|
|
|
- fontseries,fontshape,fontsize,fontsubfuzz,footnotemark,footnotesep,%
|
|
|
- footnotetext,footskip,frac,frame,framebox,fussy,glossary,%
|
|
|
- headheight,headsep,height,hline,hspace,I,include,includeonly,index,%
|
|
|
- inputlineno,intextsep,itemindent,itemize,itemsep,iterate,itshape,%
|
|
|
- Join,kill,label,labelsep,labelwidth,LaTeX,LaTeXe,leadsto,lefteqn,%
|
|
|
- leftmargin,leftmargini,leftmarginii,leftmarginiii,leftmarginiv,%
|
|
|
- leftmarginv,leftmarginvi,leftmark,lhd,linebreak,linespread,%
|
|
|
- linethickness,linewidth,list,listfiles,listfiles,listparindent,%
|
|
|
- lrbox,makeatletter,makeatother,makebox,makeglossary,makeindex,%
|
|
|
- makelabel,MakeLowercase,MakeUppercase,marginpar,marginparpush,%
|
|
|
- marginparsep,marginparwidth,markboth,markright,math,mathbf,%
|
|
|
- mathellipsis,mathgroup,mathit,mathsf,mathsterling,mathtt,%
|
|
|
- mathunderscore,mathversion,mbox,mdseries,mho,minipage,multicolumn,%
|
|
|
- multiput,NeedsTeXFormat,newcommand,newcounter,newenvironment,%
|
|
|
- newfont,newhelp,newlabel,newlength,newline,newmathalphabet,newpage,%
|
|
|
- newsavebox,newtheorem,nobreakspace,nobreakspace,nocite,nocorr,%
|
|
|
- nocorrlist,nofiles,nolinebreak,nonumber,nopagebreak,normalcolor,%
|
|
|
- normalfont,normalmarginpar,numberline,obeycr,oddsidemargin,%
|
|
|
- oldstylenums,onecolumn,oval,pagebreak,pagenumbering,pageref,%
|
|
|
- pagestyle,paperheight,paperwidth,paragraphmark,parbox,parsep,%
|
|
|
- partopsep,picture,poptabs,pounds,protect,pushtabs,put,qbezier,%
|
|
|
- qbeziermax,r,raggedleft,raisebox,ref,refstepcounter,renewcommand,%
|
|
|
- renewenvironment,restorecr,reversemarginpar,rhd,rightmargin,%
|
|
|
- rightmark,rmfamily,roman,Roman,rootbox,rule,samepage,sbox,scshape,%
|
|
|
- secdef,sectionmark,selectfont,setcounter,settodepth,settoheight,%
|
|
|
- settowidth,sffamily,shortstack,showoutput,showoverfull,sloppy,%
|
|
|
- sloppypar,slshape,sqsubset,sqsupset,SS,stackrel,stepcounter,stop,%
|
|
|
- stretch,subparagraphmark,subsectionmark,subsubsectionmark,%
|
|
|
- suppressfloats,symbol,tabbing,tabbingsep,tabcolsep,tabular,%
|
|
|
- tabularnewline,textasciicircum,textasciitilde,textbackslash,%
|
|
|
- textbar,textbf,textbraceleft,textbraceright,textbullet,textcircled,%
|
|
|
- textcompwordmark,textdagger,textdaggerdbl,textdollar,textellipsis,%
|
|
|
- textemdash,textendash,textexclamdown,textfloatsep,textfraction,%
|
|
|
- textgreater,textheight,textit,textless,textmd,textnormal,%
|
|
|
- textparagraph,textperiodcentered,textquestiondown,textquotedblleft,%
|
|
|
- textquotedblright,textquoteleft,textquoteright,textregistered,%
|
|
|
- textrm,textsc,textsection,textsf,textsl,textsterling,%
|
|
|
- textsuperscript,texttrademark,texttt,textunderscore,textup,%
|
|
|
- textvisiblespace,textwidth,thanks,thefootnote,thempfn,thempfn,%
|
|
|
- thempfootnote,thepage,thepage,thicklines,thinlines,thispagestyle,%
|
|
|
- title,today,topfigrule,topfraction,topmargin,topsep,totalheight,%
|
|
|
- tracingfonts,trivlist,ttfamily,twocolumn,typein,typeout,unboldmath,%
|
|
|
- unitlength,unlhd,unrhd,upshape,usebox,usecounter,usefont,%
|
|
|
- usepackage,value,vector,verb,verbatim,vline,vspace,width}%
|
|
|
+\gdef\lstFV@Convert@Arg#1{%
|
|
|
+ {\let\lst@arg\@empty \lstFV@Convert#1@\global\let\@gtempa\lst@arg}%
|
|
|
+ \expandafter\lst@lAddTo\expandafter\lst@arg\expandafter{%
|
|
|
+ \expandafter{\@gtempa\lst@PrintToken}}%
|
|
|
+ \lstFV@Convert}%
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}\end{macro}\end{macro}
|
|
|
-%
|
|
|
-% \begin{macro}{\texcs}
|
|
|
-% \begin{macro}{\moretexcs}
|
|
|
-% The definitions are similar to \cs{keywords} and \cs{morekeywords}.
|
|
|
+% If we haven't found a |\bgroup|, we look whether we've found the end of the input.
|
|
|
+% If not, we convert one token ((non)active character or control sequence) and continue conversion.
|
|
|
% \begin{macrocode}
|
|
|
-\gdef\texcs#1{\edef\lst@cs{,\zap@space#1 \@empty}}%
|
|
|
-\gdef\moretexcs#1{\edef\lst@cs{\lst@cs,\zap@space#1 \@empty}}%
|
|
|
+\gdef\lstFV@Convert@#1{%
|
|
|
+ \ifx @#1\else %
|
|
|
+ \expandafter\lstFV@Convert@@\string#1\@empty\@empty\relax{#1}%
|
|
|
+ \expandafter\lstFV@Convert %
|
|
|
+ \fi}%
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}\end{macro}
|
|
|
-%
|
|
|
-% \begin{macro}{\lstdrv@tex@}
|
|
|
-% Main driver and option macros:
|
|
|
-% \begin{macrocode}
|
|
|
-\gdef\lstdrv@tex@{%
|
|
|
- \keywords{}%
|
|
|
- \texcs{\lstdrv@tex@primitives,\lstdrv@tex@commoncs,%
|
|
|
- advancepageno,beginsection,bf,bffam,bye,cal,cleartabs,columns,%
|
|
|
- dosupereject,endinsert,eqalign,eqalignno,fiverm,fivebf,fivei,%
|
|
|
- fivesy,folio,footline,hang,headline,it,itemitem,itfam,%
|
|
|
- leqalignno,magnification,makefootline,makeheadline,midinsert,%
|
|
|
- mit,mscount,nopagenumbers,normalbottom,of,oldstyle,pagebody,%
|
|
|
- pagecontents,pageinsert,pageno,plainoutput,preloaded,proclaim,%
|
|
|
- rm,settabs,sevenbf,seveni,sevensy,sevenrm,sl,slfam,supereject,%
|
|
|
- tabalign,tabs,tabsdone,tabsyet,tenbf,tenex,teni,tenit,tenrm,%
|
|
|
- tensl,tensy,tentt,textindent,topglue,topins,topinsert,tt,ttfam,%
|
|
|
- ttraggedright,vfootnote}%
|
|
|
- \sensitivetrue %
|
|
|
- \DeclareCLPercent %
|
|
|
- \DeclareSingleComment stuff \relax %
|
|
|
- \stringizer{}\lstbaseem{0.6}%
|
|
|
- \lst@DefineCatcodes{\active}%
|
|
|
- \let\lst@PrePL \relax %
|
|
|
- \let\lst@PostPL\relax}%
|
|
|
-\gdef\lstdrv@tex@plain{\lstdrv@tex@}%
|
|
|
-\gdef\lstdrv@tex@primitive{\lstdrv@tex@ \texcs{\lstdrv@tex@primitives}}%
|
|
|
-\gdef\lstdrv@tex@latex{\lstdrv@tex@ %
|
|
|
- \texcs{\lstdrv@tex@primitives,\lstdrv@tex@latexcs}}%
|
|
|
-\gdef\lstdrv@tex@allatex{\lstdrv@tex@ %
|
|
|
- \keywords{array,center,displaymath,document,enumerate,eqnarray,%
|
|
|
- equation,flushleft,flushright,itemize,list,lrbox,math,minipage,%
|
|
|
- picture,sloppypar,tabbing,tabular,trivlist,verbatim}%
|
|
|
- \texcs{\lstdrv@tex@primitives,\lstdrv@tex@latexcs,%
|
|
|
- AtBeginDocument,AtBeginDocument,AtBeginDvi,AtEndDocument,%
|
|
|
- AtEndOfClass,AtEndOfPackage,ClassError,ClassInfo,ClassWarning,%
|
|
|
- ClassWarningNoLine,CurrentOption,DeclareErrorFont,%
|
|
|
- DeclareFixedFont,DeclareFontEncoding,%
|
|
|
- DeclareFontEncodingDefaults,DeclareFontFamily,DeclareFontShape,%
|
|
|
- DeclareFontSubstitution,DeclareMathAccent,DeclareMathAlphabet,%
|
|
|
- DeclareMathAlphabet,DeclareMathDelimiter,DeclareMathRadical,%
|
|
|
- DeclareMathSizes,DeclareMathSymbol,DeclareMathVersion,%
|
|
|
- DeclareOldFontCommand,DeclareOption,DeclarePreloadSizes,%
|
|
|
- DeclareRobustCommand,DeclareSizeFunction,DeclareSymbolFont,%
|
|
|
- DeclareSymbolFontAlphabet,DeclareTextAccent,%
|
|
|
- DeclareTextAccentDefault,DeclareTextCommand,%
|
|
|
- DeclareTextCommandDefault,DeclareTextComposite,%
|
|
|
- DeclareTextCompositeCommand,DeclareTextFontCommand,%
|
|
|
- DeclareTextSymbol,DeclareTextSymbolDefault,ExecuteOptions,%
|
|
|
- GenericError,GenericInfo,GenericWarning,IfFileExists,%
|
|
|
- InputIfFileExists,LoadClass,LoadClassWithOptions,MessageBreak,%
|
|
|
- OptionNotUsed,PackageError,PackageInfo,PackageWarning,%
|
|
|
- PackageWarningNoLine,PassOptionsToClass,PassOptionsToPackage,%
|
|
|
- ProcessOptionsProvidesClass,ProvidesFile,ProvidesFile,%
|
|
|
- ProvidesPackage,ProvideTextCommand,RequirePackage,%
|
|
|
- RequirePackageWithOptions,SetMathAlphabet,SetSymbolFont,%
|
|
|
- TextSymbolUnavailable,UseTextAccent,UseTextSymbol}}%
|
|
|
-\endgroup %
|
|
|
+% |\string#1| from above expands to 'backslash + some characters' if |#1| is a control sequence.
|
|
|
+% In this case the argument |#2| here equals not |\@empty|.
|
|
|
+% The other implication: If |#2| equals |\@empty|, |\string#1| necessarily expanded to a single character, which can't be a control sequence (|\escapechar>=0| granted).
|
|
|
+% Thus, we add an active character if and only if the second argument equals |\@empty|, and we append the control sequence otherwise.
|
|
|
+% In the latter case we must print all preceding characters (and all the lost space).
|
|
|
+% \begin{macrocode}
|
|
|
+\gdef\lstFV@Convert@@#1#2#3\relax#4{%
|
|
|
+ \ifx\@empty#2%
|
|
|
+ \lccode`\~=`#4\lowercase{\lst@lAddTo\lst@arg~}%
|
|
|
+ \else %
|
|
|
+ \lst@lAddTo\lst@arg{\lst@UseLostSpace\lst@PrintToken#4}%
|
|
|
+ \fi}%
|
|
|
% \end{macrocode}
|
|
|
% \end{macro}
|
|
|
-%
|
|
|
-% \begin{macro}{\lstdrv@tex@PrepareListing}
|
|
|
-% Here we assign a different \verb!\lst@Output! macro to detect control
|
|
|
-% sequences. We also (re-) set some catcodes.
|
|
|
+% \begingroup
|
|
|
% \begin{macrocode}
|
|
|
-\begingroup \makeatletter %
|
|
|
-\gdef\lstdrv@tex@PrepareListing{\let\lst@Output\lstdrv@tex@Output %
|
|
|
- \catcode`\0=12 \catcode`\1=12 \catcode`\2=12 \catcode`\3=12 %
|
|
|
- \catcode`\4=12 \catcode`\5=12 \catcode`\6=12 \catcode`\7=12 %
|
|
|
- \catcode`\8=12 \catcode`\9=12}%
|
|
|
+\endgroup %
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}
|
|
|
-%
|
|
|
-% \begin{macro}{\lstdrv@tex@Output}
|
|
|
-% \begin{macro}{\lstdrv@tex@CSOrNot}
|
|
|
-% These macros are similar to \verb!\lst@Output! and
|
|
|
-% \verb!\lst@CaseSensitiveKeywords!. We only do some adjustments, e.g.\
|
|
|
-% we need no 'ifstring' test, since the stringizer is empty for \TeX{}.
|
|
|
% \begin{macrocode}
|
|
|
-\gdef\lstdrv@tex@Output{%
|
|
|
- \ifx\lst@text\@empty\else %
|
|
|
- \lst@ifcomment\lst@MakeBox{\lst@commentstyle}%
|
|
|
- \else\ifx\lst@lastother\lst@inputbackslash %
|
|
|
- \expandafter\lstdrv@tex@CSOrNot\lst@text\relax %
|
|
|
- \else\expandafter\lst@KeywordOrNot\lst@text\relax %
|
|
|
- \fi \fi %
|
|
|
- \global\advance\lst@pos by -\lst@length %
|
|
|
- \let\lst@text\@empty \lst@length0 %
|
|
|
- \fi}%
|
|
|
-\gdef\lstdrv@tex@CSOrNot#1\relax{%
|
|
|
- \def\lst@test##1,#1,##2\relax{%
|
|
|
- \ifx \@empty##2\@empty \lst@MakeBox{}%
|
|
|
- \else \lst@MakeBox{\lst@keywordstyle}%
|
|
|
- \fi}%
|
|
|
- \expandafter\lst@test\lst@cs,#1,\relax}%
|
|
|
-\endgroup
|
|
|
-%</tex>
|
|
|
+%</fancyvrb>
|
|
|
% \end{macrocode}
|
|
|
-% \end{macro}\end{macro}
|
|
|
+% \endgroup
|
|
|
%
|
|
|
%
|
|
|
% \begingroup\small
|
|
|
-% \section{Extensions}\label{sExtensions}
|
|
|
-% Define a new driver file for an additional language.
|
|
|
-% Refer the previous section how this is done.
|
|
|
-%
|
|
|
-% If you want comment lines or comments, which are not supported by
|
|
|
-% the declaration commands of this package, you have a problem.
|
|
|
-% Contact me or follow these steps:
|
|
|
-% \begin{enumerate}
|
|
|
-% \item \DescribeMacro\lst@CommentLine
|
|
|
-% Define the macro, which cuts up the input line into a comment
|
|
|
-% line and the noncomment rest: The macro gets the input via the
|
|
|
-% macro \verb!\lst@line!. After the call \verb!\lst@line! must hold
|
|
|
-% the noncomment rest and \verb!\lst@commentline! the comment line.
|
|
|
-% The C++ line
|
|
|
-% \begin{verbatim}
|
|
|
-% if (comments!=appear) // comment stuff\end{verbatim}
|
|
|
-% must be cut into '\verb|if (comments!=appear) |' and
|
|
|
-% '\verb!// comment stuff!'.
|
|
|
-% \item \DescribeMacro\lst@SOC
|
|
|
-% Define the macro, which finds the start of a comment:
|
|
|
-% The macro gets the input via the macro \verb!\lst@line!. After
|
|
|
-% the call \verb!\lst@line! must contain the source line upto the
|
|
|
-% first appearance of a comment (exclusive). The comment and might
|
|
|
-% the rest of the line must be in the macro \verb!\lst@comment!.
|
|
|
-% If a comment is separated (not if and only if), you have to call
|
|
|
-% \verb!\lst@commenttrue!. The Pascal line
|
|
|
-% \begin{verbatim}
|
|
|
-% if { comment } appears then\end{verbatim}
|
|
|
-% is cut into '\verb!if !' and '\verb!{ comment } appears then!'.
|
|
|
-% \item \DescribeMacro\lst@EOC
|
|
|
-% Define the macro, which finds the end of a comment:
|
|
|
-% The macro gets the input via the macro \verb!\lst@line!. After
|
|
|
-% the call \verb!\lst@comment! must hold the comment and
|
|
|
-% \verb!\lst@line! the noncomment rest of the line (which might be
|
|
|
-% empty, of course). If the end of comment is found, you have to call
|
|
|
-% \verb!\lst@commentfalse!. The Pascal line
|
|
|
-% \begin{verbatim}
|
|
|
-% { comment } appears then\end{verbatim}
|
|
|
-% must be cut into '\verb!{ comment }!' and '\verb! appears then!'.
|
|
|
-% \end{enumerate}
|
|
|
-% Assign these macros to \verb!\lst@CommentLine!, \verb!\lst@SOC! and
|
|
|
-% \verb!\lst@EOC! within your language command.
|
|
|
-%
|
|
|
-%
|
|
|
-% \section{History}\label{sHistory}
|
|
|
+% \section{History}
|
|
|
% Only major changes after version 0.15 are listed here.
|
|
|
% Previous changes are still present in the \texttt{.dtx}-file.
|
|
|
+% Introductory version numbers of the user commands are listed in the user's guide.
|
|
|
% \renewcommand\labelitemi{--}
|
|
|
% \begin{itemize}
|
|
|
% \iffalse
|
|
|
% \item[0.1] from 1996/03/09
|
|
|
% \item test version to look whether package is possible or not
|
|
|
% \item[0.11] from 1996/08/19
|
|
|
-% \item additional blank option
|
|
|
-% \item \cs{keywords}, \cs{morekeywords}, \cs{keywordstyle}
|
|
|
-% and \cs{commentstyle} are new commands
|
|
|
-% \item implementation guide improved and user's guide updated
|
|
|
+% \item additional blank option (= language)
|
|
|
% \item alignment improved by rewriting some macros
|
|
|
% \item[0.12] from 1997/01/16
|
|
|
-% \item nearly perfect alignment now
|
|
|
-% \item \cs{stringizer}, \cs{stringstyle}, \cs{prelisting}
|
|
|
-% and \cs{postlisting} are new
|
|
|
-% \item user selection \cs{listingtrue} and \cs{listingfalse} possible
|
|
|
-% \item \cs{blankstringtrue} and \cs{blankstringfalse} handle output
|
|
|
-% of blanks in strings
|
|
|
-% \item package supports tabulators now; new command \cs{tablength}
|
|
|
+% \item nearly 'perfect' alignment now
|
|
|
% \item[0.13] from 1997/02/11
|
|
|
% \item additional languages: Eiffel, Fortran 90, Modula-2, Pascal XSC
|
|
|
% \item load on demand: language specific macros moved to driver files
|
|
|
-% \item comments are declared now and not implemented for each language
|
|
|
-% again (this makes the \TeX{} sources easier to read)
|
|
|
-% \item 'string exceeds line' test moved to
|
|
|
-% \verb!\lst@PreProcessLineDefault!
|
|
|
-% \item sample files moved to .dtx-file
|
|
|
+% \item comments are declared now and not implemented for each language again (this makes the \TeX{} sources easier to read)
|
|
|
% \item[0.14] from 1997/02/18
|
|
|
% \item user's guide rewritten
|
|
|
-% \item implementation guide uses macro environment from the doc
|
|
|
-% package
|
|
|
+% \item implementation guide uses macro environment from the doc package
|
|
|
% \item (non) case sensitivity implemented, e.g.\ Pascal is not
|
|
|
-% \item multiple stringizer implemented, i.e.\ Modula-2 handles
|
|
|
-% both string types: quotes and double quotes
|
|
|
+% \item multiple stringizer implemented, i.e.\ Modula-2 handles both string types: quotes and double quotes
|
|
|
% \item comment declaration is user-accessible now
|
|
|
% \item package compatible to \verb!german.sty! now
|
|
|
-% \item changed some identifiers
|
|
|
% \item[0.15] from 1997/04/18
|
|
|
-% \item listing environment is new
|
|
|
% \item additional languages: Java, Turbo Pascal
|
|
|
-% \item \verb!\lst@width! changes from 0.65em to 0.8em for Fortran 90
|
|
|
-% \item corrected some mistakes in the documentation
|
|
|
-% \item package renamed from listing.dtx to listings.dtx, since there
|
|
|
-% is already a listing package
|
|
|
+% \item package renamed from listing.dtx to listings.dtx, since there is already a package named listing
|
|
|
% \fi
|
|
|
% \item[0.16] from 1997/06/01
|
|
|
-% \item Thanks to Anders Edenbrandt\footnote{Department of Computer
|
|
|
-% Science\ \ Lund University, Sweden.
|
|
|
-% [email protected]} for reporting two bugs:
|
|
|
-% lstmodula.sty corrected (misspelled \verb!\`"!) and
|
|
|
-% call of \verb!\lst@???style!s in \verb!\lst@Begin! avoid
|
|
|
-% loading of font files when catcodes are changed.
|
|
|
-% \item Thanks to Rolf Niepraschk\footnote{Physikalisch--Technische
|
|
|
-% Bundesanstalt\ \ Berlin, Germany.
|
|
|
-% [email protected]} for reporting wrong catcode
|
|
|
-% of \verb!$!. I've also changed catcode of \verb!@! and took
|
|
|
-% over the proposal of using \verb!\zap@space!. The catcode of
|
|
|
-% the percent \verb!%! is restored after typesetting a listing now.
|
|
|
-% \item Thanks to Knut M\"uller\footnote{[email protected]} and
|
|
|
-% Stefan Meister\footnote{FH--Wolfenb\"uttel, Germany.}
|
|
|
-% for reporting problem with the command \cs{blankstringtrue}.
|
|
|
-% The problem is gone.
|
|
|
% \iffalse
|
|
|
% \item changed '$<$' to '$>$' in \verb!\lst@SkipUptoFirst!
|
|
|
-% \item bug removed: \verb!\lst@Begin! must be placed before
|
|
|
-% \verb!\lst@SkipUptoFirst!
|
|
|
+% \item bug removed: \verb!\lst@Init! must be placed before \verb!\lst@SkipUptoFirst!
|
|
|
% \fi
|
|
|
-% \item new commands \cs{spreadlisting}, \cs{listoflistings},
|
|
|
-% \cs{labelstyle}, \cs{thelstline}, \cs{lstbaseem},
|
|
|
-% \cs{listlistingsname}
|
|
|
% \item listing environment rewritten
|
|
|
% \item[0.17] from 1997/09/29
|
|
|
-% \item \cs{spreadlisting} works correct now (e.g.\ page numbers
|
|
|
-% move not right any more), new commands \cs{selectlisting}
|
|
|
-% and \cs{lstlineskip}, \cs{labelstyle} changed
|
|
|
-% \item speed up things (quick 'if parameter empty', all \cs{long}
|
|
|
-% except one removed, faster \verb!\lst@GotoNextTabStop!, etc.)
|
|
|
+% \item |\spreadlisting| works correct now (e.g.\ page numbers move not right any more)
|
|
|
+% \item speed up things (quick 'if parameter empty', all |\long| except one removed, faster \verb!\lst@GotoNextTabStop!, etc.)
|
|
|
% \item alignment of wide other characters improved (e.g.\ $==$)
|
|
|
-% \item many new languages: Ada, Algol, Cobol, Comal 80, Elan,
|
|
|
-% Fortran 77, Lisp, Logo, Matlab, Oberon, Perl, PL/I, Simula,
|
|
|
-% SQL, \TeX{}
|
|
|
+% \iffalse
|
|
|
+% \item many new languages: Ada, Algol, Cobol, Comal 80, Elan, Fortran 77, Lisp, Logo, Matlab, Oberon, Perl, PL/I, Simula, SQL, \TeX{}
|
|
|
+% \fi
|
|
|
+% \item[pre-0.18] from 1998/03/24 (unpublished)
|
|
|
+% \item bug concerning |\labelstyle| removed (now oldstylenum example works)
|
|
|
+% \item experimental implementation of character classes
|
|
|
+% \item[0.19] from 1998/11/09
|
|
|
+% \item character classes and \lst-aspects (new) seem to be the ultimate, all became implemented in these terms
|
|
|
+% \item \lst-aspects became an application (new) to \textsf{keyval} and hooks
|
|
|
+% \item \textsf{fancyvrb} support
|
|
|
% \end{itemize}
|
|
|
%
|
|
|
%
|
|
|
-% \begin{thebibliography}{99}
|
|
|
-% \bibitem{Ada}
|
|
|
-% \textsc{Barnes, John Gilbert Presslie}:
|
|
|
-% \textbf{Programming in Ada plus language reference manual}\\
|
|
|
-% {\copyright} 1991 Addison-Wesley Publishing Company, Inc.;
|
|
|
-% ISBN 0-201-56539-0
|
|
|
-% \bibitem{Algol60}
|
|
|
-% \textsc{Uwe Pape}:
|
|
|
-% \textbf{Programmieren in ALGOL 60}\\
|
|
|
-% {\copyright} 1973 Carl Hanser Verlag M\"unchen;
|
|
|
-% ISBN 3-446-11605-2
|
|
|
-% \bibitem{Algol68}
|
|
|
-% \textsc{Frank G.\ Pagan}:
|
|
|
-% \textbf{A practical guide to ALGOL 68}\\
|
|
|
-% {\copyright} 1976 by John Wiley $\&$ Sohn Ltd.;
|
|
|
-% ISBN 0-471-65746-8 (Cloth); ISBN 0-471-65747-6 (Pbk)
|
|
|
-% \bibitem{Comal}
|
|
|
-% \textsc{Borge R. Christensen}:
|
|
|
-% \textbf{Strukturierte Programmierung mit COMAL 80} [aus dem
|
|
|
-% D\"anischen \"ubertragen und bearbeitet von Margarete Kragh]\\
|
|
|
-% 2., verb.\ Auflage -- M\"unchen; Wien: Oldenburg, 1985;
|
|
|
-% ISBN 3-486-26902-X
|
|
|
-% \bibitem{Eiffel}
|
|
|
-% \textsc{Bertrand Meyer}: \textbf{Eiffel: the language}\\
|
|
|
-% Prentice Hall International (UK) Ldt, 1992;
|
|
|
-% ISBN 0-13-247925-7
|
|
|
-% \bibitem{Elan}
|
|
|
-% \textsc{Leo~H.~Klingen, Jochen Liedtke}:
|
|
|
-% \textbf{Programmieren mit ELAN}\\
|
|
|
-% B.G.\ Teubner, Stuttgart 1983; ISBN 3-519-02507-8
|
|
|
-% \bibitem{Fortran77}
|
|
|
-% \textsc{Karl Hans M\"uller}:
|
|
|
-% \textbf{Fortran 77: Programmierungsanleitung}\\
|
|
|
-% 3., v\"ollig neu bearb.\ Aufl.\ -- Mannheim; Wien; Z\"urich:
|
|
|
-% Bibliographisches Institut, 1984;
|
|
|
-% ISBN 3-411-05804-8
|
|
|
-% \bibitem{Fortran90}
|
|
|
-% \textsc{Thomas Michel}: \textbf{Fortran 90: Lehr-- und Handbuch}\\
|
|
|
-% Mannheim; Leipzig; Wien; Z\"urich: BI-Wiss.-Verlag, 1994;
|
|
|
-% ISBN 3-411-16861-7
|
|
|
-% \bibitem{Matlab} \texttt{http://www.utexas.edu/math/Matlab/Manual}
|
|
|
-% \bibitem{Modula}
|
|
|
-% \textsc{Niklaus Wirth}: \textbf{Programmieren in Modula-2},
|
|
|
-% \"Ubers.\ Guido Pfeiffer\\
|
|
|
-% 2.\ Auflage -- Berlin; Heidelberg; New York; London; Paris; Tokyo;
|
|
|
-% Hong Kong: Springer, 1991;
|
|
|
-% ISBN 3-540-51689-1
|
|
|
-% \bibitem{java} \texttt{http://java.sun.com}
|
|
|
-% \bibitem{lisp}
|
|
|
-% \textsc{Guy Steele}:
|
|
|
-% \textbf{Common Lisp}\\
|
|
|
-% Copyright 1990 by Digital Equipment Corporation;
|
|
|
-% ISBN 1-55558-042-4
|
|
|
-% \bibitem{perl} \texttt{http://www.perl.com}
|
|
|
-% \bibitem{pli}
|
|
|
-% \textsc{Bernhard Fischer, Herman Fischer}:
|
|
|
-% \textbf{Structured Programming in PL/I and PL/C}\\
|
|
|
-% Copyright {\copyright} 1976 by Marcel Dekker, Inc.;
|
|
|
-% ISBN 0-8247-6394-7
|
|
|
-% \bibitem{simula}
|
|
|
-% \textsc{G\"unther Lamprecht}:
|
|
|
-% \textbf{Introduction to SIMULA 67}\\
|
|
|
-% Braunschweig; Wiesbaden: Vieweg, 1981
|
|
|
-% \bibitem{sql}
|
|
|
-% \textsc{Jim~Melton, Alan~R.~Simon}:
|
|
|
-% \textbf{Understanding the new SQL: A Complete Guide}\\
|
|
|
-% {\copyright} 1993 Morgan Kaufmann Publishers, Inc.;
|
|
|
-% ISBN 1-55860-245-3
|
|
|
-% \bibitem{verbatim}
|
|
|
-% \textsc{Rainer Sch\"opf, Bernd Raichle, Chris Rowley}:
|
|
|
-% \textbf{A New Implementation of \LaTeX's \texttt{verbatim}
|
|
|
-% and \texttt{verbatim*} Environments.}
|
|
|
-% \end{thebibliography}
|
|
|
-% \endgroup
|
|
|
-%
|
|
|
-%
|
|
|
% \setcounter{IndexColumns}{2}
|
|
|
% \PrintIndex
|
|
|
%
|