% \iffalse meta-comment % % Copyright (C) 2015 by Timothy Bourke % and Marc Pouzet % ------------------------------------------------------- % % This file may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.2 % of this license or (at your option) any later version. % The latest version of this license is in: % % http://www.latex-project.org/lppl.txt % % and version 1.2 or later is part of all distributions of LaTeX version % 1999/12/01 or later. % % CTAN Topic: callback, listing % \fi % % \iffalse %<*driver> \ProvidesFile{checklistings.dtx} % %\NeedsTeXFormat{LaTeX2e} %\ProvidesPackage{checklistings} % [2015/09/01 v1.0 compile code samples and insert the results] %\RequirePackage{keyval} %\RequirePackage{kvoptions} %\RequirePackage{fancyvrb} %\RequirePackage{color} %\RequirePackage{listings} %\makeatletter %\lst@RequireAspects{writefile} %\SetupKeyvalOptions{family=CHKL,prefix=CHKL@} %\makeatother % %<*driver> \documentclass{ltxdoc} \usepackage{checklistings} \usepackage{url} \usepackage{hypdoc} \usepackage{showexpl} \usepackage{array} \usepackage{longtable} \lstset{ basicstyle=\small\ttfamily, numbers=none, keywordstyle=\color{blue}\bfseries, pos=l, } \checklistings{ msgstyle={formatcom=\footnotesize}, errstyle={formatcom=\footnotesize}} \EnableCrossrefs \CodelineIndex \RecordChanges \newcommand{\refsec}[1]{Section~\ref{sec:#1}} \begin{document} \DocInput{checklistings.dtx} \PrintChanges \PrintIndex \end{document} % % \fi % % \CheckSum{444} % % \CharacterTable % {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z % Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z % Digits \0\1\2\3\4\5\6\7\8\9 % Exclamation \! Double quote \" Hash (number) \# % Dollar \$ Percent \% Ampersand \& % Acute accent \' Left paren \( Right paren \) % Asterisk \* Plus \+ Comma \, % Minus \- Point \. Solidus \/ % Colon \: Semicolon \; Less than \< % Equals \= Greater than \> Question mark \? % Commercial at \@ Left bracket \[ Backslash \\ % Right bracket \] Circumflex \^ Underscore \_ % Grave accent \` Left brace \{ Vertical bar \| % Right brace \} Tilde \~} % % % \changes{v1.0}{2015/09/01}{Initial version} % % \GetFileInfo{checklistings.sty} % % \DoNotIndex{\newcommand,\newenvironment} % \DoNotIndex{\@file,\@ifundefined,\@tempboxa,\@undefined} % \DoNotIndex{\arabic,\bgroup,\color,\dimexpr,\relax,\topsep,\vspace} % \DoNotIndex{\CurrentOption,\DeclareBoolOption,\DeclareComplementaryOption} % \DoNotIndex{\DeclareDefaultOption,\DeclareStringOption,\DeclareVoidOption} % \DoNotIndex{\def,\define@key,\edef,\egroup,\else,\emph,\expandafter} % \DoNotIndex{\fi,\global,\hbox,\ifnum,\InputIfFileExists,\langle,\let} % \DoNotIndex{\newcounter,\newif,\PackageWarning,\ProcessKeyvalOptions} % \DoNotIndex{\rangle,\setbox,\setkeys,\space,\stepcounter} % \DoNotIndex{\value,\@currentlabel,\@firstoftwo,\AtEndDocument,\em} % \DoNotIndex{\closeout,\csname,\endcsname,\DefineVerbatimEnvironment} % \DoNotIndex{\jobname,\kvsetkeys,\label,\newwrite,\noexpand,\openout} % \DoNotIndex{\partopsep,\setlength,\thepage,\write,\resetcounteronoverlays} % \DoNotIndex{\@tempa,\fvset,\ifx,\inputlineno,\lstset,\the} % \DoNotIndex{\DeclareRobustCommand,\empty,\ifdefined,\meta} % \expandafter\DoNotIndex\expandafter{\string\$} % \expandafter\DoNotIndex\expandafter{\string\#} % % \title{The \textsf{checklistings} package\thanks{This document % corresponds to \textsf{checklistings}~\fileversion, dated \filedate.}} % \author{Timothy Bourke and Marc Pouzet} % % \maketitle % \section{Introduction} % % User manuals and papers about programming languages usually contain many % code samples, often with accompanying compiler messages giving the types % of declarations or error messages explaining why certain declarations are % invalid. % This package extends % |fancyvrb|\footnote{\url{http://www.ctan.org/pkg/fancyvrb}} and % |listings|\footnote{\url{http://www.ctan.org/pkg/listings}}, which are % ideal for displaying code, with a way to pass code samples through a % compiler and include the resulting messages in a \LaTeX{} document. % The motivation is to check the code samples in a document for syntax and % typing errors and to facilitate the inclusion of inferred types and % compiler warnings or errors in a text. % This package is intentionally very lightweight and unlike packages like % |python|,\footnote{\url{http://www.ctan.org/pkg/python}} it is not % intended for interacting with an interpretor or including the execution % traces of code. % While it does not focus on a specific programming language, it is designed % to work well with ML-like languages. % % As an example, the text at left below is generated by the \LaTeX{} code at % right: % % \iffalse %<*example> % \fi \begin{LTXexample} Code samples are included verbatim and the results of compilation can be included automatically: \begin{chklisting}[withresult] let inc x = x + 1 let y = inc 3 \end{chklisting} \end{LTXexample} % \iffalse % % \fi % % A first pass through |latex| generates both a |.chkl| file, % with parameters for the compiler, and an |.ml| file containing the source % code (i.e., the two lines in the example above). % Running the |checklistings.sh| script processes these files to produce a % |.tex| file with the results of compilation. % A second pass through |latex| updates the compiler message. % % \noindent % It is possible to continue examples and to label them (to be continued at % some later point): % \iffalse %<*example> % \fi \begin{LTXexample}[pos=b] These definitions follow on from the previous ones: \begin{chklisting}[continue,withresult,label=early] let z = y + inc y \end{chklisting} \end{LTXexample} % \iffalse % % \fi % % \bigskip\noindent % Examples need not necessarily succeed: % \iffalse %<*example> % \fi \begin{LTXexample}[pos=b] This code does not compile: \begin{chklisting}[continue,fail,withresult,skipone] let u = 3 let w = u + "four" \end{chklisting} \end{LTXexample} % \iffalse % % \fi % Note that the line number in the error message is 1 even though the % |continue| option added a line to include the previous definitions and the % |skipone| option hid the |let u = 3| line. % The |checklistings.sh| script performs this adjustment by looking for the % regular expression `|line *[0-9][0-9]*|' and decrementing the number % appropriately. % This approach is simple and effective but obviously not foolproof. % Some manual tuning of the script may be required for correct results. % % \section{Use}\label{sec:use} % % Using the package involves three elements: % \begin{enumerate} % % \item % The declaration \verb|\usepackage{checklistings}|.\\ % \refsec{rvpkg} describes the options for configuring package behaviour. % % \item % The environment \verb|chklisting|.\\ % This environment is used like any other verbatim environment. % \refsec{rvenv} describes options that may be given to control its % behaviour. % % \item % The script \verb|checklistings.sh|.\\ % Running this script passes the contents of each \verb|chklisting| % environment through a compiler or interpreter and copies the resulting % output into a file. % % \end{enumerate} % % Additionally, the file \verb|checklistings.hva| can be used to incorporate % the output of |checklistings| in HTML documents generated by % HeVeA.\footnote{\url{http://hevea.inria.fr}} % % \subsection{Package options}\label{sec:rvpkg} % % \DescribeMacro{\checklistings} % Package options are either given as optional arguments to % \verb|\usepackage| or via one or more calls to \verb|\checklistings|. % The advantage of the latter is that macros are not expanded (for a % detailed explanation see the documentation for % |kvoptions|,\footnote{\url{http://www.ctan.org/pkg/kvoptions}} Section % 4.1, \emph{Package kvoptions-patch}). % Options are passed as a comma separated list of \meta{key}|=|\meta{value} % pairs and single \meta{key}s. % % There are three classes of options: options controlling the default % behaviour of \verb|chklisting|, options for configuring the % \verb|checklistings.sh| script, and options controlling the display of % code and results. % % \subsubsection{Behavioural options} % % These options control the default behaviour of the \verb|chklisting| % environment. % % \begin{longtable}{@{}>{\ttfamily}lp{75mm}>{\ttfamily}l@{}} % \parbox{15mm}{option} & description & \parbox{25mm}{default}\\\hline % withresult % & Automatically show compilation results. % & false % \\ % skipone % & Do not display the first line of code (see the description under the % |chklisting| environment). % & % false % \\ % skiptwo % & Do not display the first two lines of code (see the description under % the |chklisting| environment). % & % false % \\ % hideproblems % & Globally disable the display of failure messages (within a red box) when % compilation fails or succeeds unexpectedly. % & % false % \\ % \end{longtable} % % \subsubsection{Configuring compilation}\label{sec:compileconfig} % % These options are used for naming and placing the files generated by % \verb|chklisting| environments. % They are passed to the \verb|checklistings.sh| script and thus control % its behaviour. % % \makeatletter % \begin{longtable}{@{}>{\ttfamily}lp{75mm}>{\ttfamily}l@{}} % \parbox{15mm}{option} & description & \parbox{25mm}{default}\\\hline % prefix % & Prefix for naming source files. % It must not contain underscores (\verb|_|). % & \CHKL@prefix % \\ % ext % & Extension of source files. % & \CHKL@ext % \\ % subdir % & If defined, source files are created in the given subdirectory, which % must already exist. % A final slash (\verb|/|) should not be given. % The name must not contain underscores (\verb|_|). % & \CHKL@subdir % \\ % prompt % & The prompt displayed by |\chklistingcmd|. % & \CHKL@prompt % \\ % compiler % & Path of the compiler to execute. % & \CHKL@compiler % \\ % compilerflags % & Flags passed to the compiler. % These are not revealed by |\chklistingcmd|. % & \CHKL@compilerflags % \\ % lastflags % & Flags passed to the compiler before the main source file, that is, the % last one given. % & \CHKL@lastflags % \\ % includecmd % & The source language command for importing the definitions of another % file. % & \CHKL@includecmd % \\ % html % & The path of a program that renders source code as html. % This value can be useful when using HeVeA to produce web pages from % \LaTeX{} documents. % In any case, it is optional. % & \CHKL@html % \end{longtable} % \makeatother % % Each \verb|chklisting| environment is assigned a number $n$, from zero, % and its contents are written to the file: % \meta{subdir}|/|\meta{prefix}\meta{n}|.|\meta{ext}, % where \meta{n} is zero-padded to four characters. % For example, by default, the fourth environment is written to the file % \verb|chklisting0003.ml| in the current directory. % % Source lines are added for each dependency, and those files are compiled % using the \meta{compiler}, \meta{compilerflags}, and \meta{lastflags} % options. % For example, if the fourth environment depends on the first and the % second, a line is added: % \begin{center} % \meta{includecmd} |Withopen0000| \meta{includecmd} |Withopen0001|, % \end{center} % where \verb|Withopen| is the prefix used for such augmented files, and the % compiler is invoked with:\\ % \begin{center} % \begin{tabular}{ll} % \meta{compiler} % & \meta{compilerflags}\ \ |Withopen0000|\ \ |Withopen0001| \\ % & \meta{lastflags}\ \ |Withopen0003| % \end{tabular} % \end{center} % % \subsubsection{Controlling the display} % % This package exploits the display options given by the |fancyvrb| package. % % \begin{longtable}{@{}>{\ttfamily}lp{75mm}>{\ttfamily}l@{}} % \parbox{15mm}{option} & description & \parbox{25mm}{default}\\\hline % codestyle % & |fancyvrb| options for code % & \\ % msgstyle % & |fancyvrb| options for compiler messages % & formatcom=\string\em % \\ % errstyle % & |fancyvrb| options for error messages % & formatcom=\string\em % \\ % codelst % & |listings| options for source code, passed with |\lstset|. When this % option is not empty, |fancyvrb=true| is included automatically. % \\ % msglst % & As for |codelst|, but applied to compiler messages. % \\ % errlst % & As for |codelst|, but applied to error messages. % \\ % \end{longtable} % % Other options are passed directly through to the |fancyvrb| package and % applied to all |chklisting| code blocks (but not to messages or errors). % For example, \verb|frame=single|. % These options must typically be set using |\checklistings|, since they % will usually contain commands that should not be expanded immediately % (like |\em| or |\bf|). % % \subsection{The \texttt{chklisting} environment}\label{sec:rvenv} % % \DescribeEnv{chklisting} % As an optional argument, this environment takes a comma separated list of % \meta{key}|=|\meta{value} and single \meta{key}s. % % \begin{longtable}{@{}>{\ttfamily}lp{100mm}} % \parbox{15mm}{option} & description \\\hline % fail % & This code is expected to fail; an error is reported if it succeeds. % \\ % continue % & This code is continued from the previous |chklisting| environment; all % of the definitions available there are imported. % \\ % label % & Label this code for later inclusion. % \\ % include % & All of the definitions available after the environment with the given % label are imported. % \\ % withresult % & The result of compiling the code is displayed (see also % |\chklistingmsg| and |\chklistingerr|). % This is normally either the types of declared values or the results of % evaluation. % For environments marked |fail|, it will be an error message. % \\ % withoutresult % & The result of compiling code is not displayed automatically. % This is the default behaviour, but it can be overridden by the package % options. % \\ % hide % & The code is not displayed, but it is still compiled, compiler messages % are still displayed (if |withresult| is active), and definitions are still % available for continuation (|continue|), labelling (|label|), and later % inclusion (|include|). % \\ % skipone % & Do not display the first line of the code. % This line is still sent to the compiler and may thus be used to open % other modules, or to pass execution options (via comments). % \\ % skiptwo % & As pre the previous option, but two lines are skipped. % \\ % skipnone % & Do not skip any lines; this option overrides any package-level skip % setting. % \\ % hideproblems % & Do not display an error message within the document when compilation % fails or succeeds unexpectedly. % \\ % showproblems % & Display an error message within the document when compilation fails or % succeeds unexpectedly. % This is the default behaviour unless the |hideproblems| package option was % set. % \\ % \end{longtable} % % The results of compiling the code of a |chklisting| environment are made % available in the following macros until the next |chklisting| which will % redefine them. % \begin{description} % % \item[\texttt{\string\chklistingcmd}] % \DescribeMacro{\chklistingcmd} % contains an idealised version of the command line used to compile the code % sample. % It includes the |prompt|, the basename of |compiler|, and |lastflags|, but % not |compilerflags| or the list of included files. % Furthermore, the |subdir| and serial number are removed from the filename % of the code sample, which becomes simply \meta{prefix}|.|\meta{ext}. % % \item[\texttt{\string\chklistingmsg\marg{label}}] % \DescribeMacro{\chklistingmsg}: inserts the verbatim text emitted by the % compiler, provided compilation succeeded, for the |chklisting| % environment labelled \meta{label}. % When \meta{label} is left empty, the message for the last environment is % inserted. % It should not be used after environments marked |fail|. % % \item[\texttt{\string\chklistingerr\marg{label}}] % \DescribeMacro{\chklistingerr}: inserts the verbatim text emitted by the % compiler, provided compilation failed, for the |chklisting| environment % labelled \meta{label}. % When \meta{label} is left empty, the message for the last environment is % inserted. % It should only be used after environments marked |fail|. % \end{description} % % \subsection{The \texttt{checklistings.sh} script}\label{sec:rvsh} % % Processing a document that uses the |checklistings| package produces a % |.chkl| file containing compiler options and a list of source files % together with their interdependencies. % The |checklistings.sh| script processes |.chkl| files by executing the % specified compiler against each listed source file % \meta{subdir}|/|\meta{prefix}\meta{n}|.|\meta{ext} and copying the % results---the command-line used, whether it succeeded or failed, the % messages on |stdout|, and the messages on |stderr|---into a corresponding % file, \meta{subdir}|/|\meta{prefix}\meta{n}|.tex|, for inclusion in the % original document. % % The \verb|checklistings.sh| script is written for the Bourne shell % (\verb|sh|). % It takes a list of |.chkl| files as arguments (with or without the % exentions), but if none are given it processes all such files in the % current working directory. % % The compilation options specified within a \LaTeX{} source file, see % \refsec{compileconfig}, can be manually overridden by processing a |.chkl| % file, before any others, containing a `|lock|' directive, for example: % |lock compiler=/usr/local/bin/ocamlc|. % This feature is useful when working with others to develop the compiler % being documented. % % \StopEventually{} \makeatletter % % \section{Remarks} % % \subsection{Known limitations} % % The package and script have some known limitations. % \begin{itemize} % % \item % Line numbers in error messages may not correspond correctly with the line % numbers of sample files, due to either the |skip*| options, or because of % lines added to import code. % % \item % The system has been designed to work with ML-style compilers. % It has not been tested with other compilers and interpreters. % Please contact \url{tim@tbrk.org} if you would like to support other % systems. % Patches are most welcome, but the intent is to keep this package % relatively simple rather than to try to do everything. % % \item % Multiple languages in a single document are not supported. % % \item % Care must be taken when using |checklistings| with the overlays of the % Beamer package. % In particular, |chklisting| environment commands are to be avoided within % commands that completely omit material from slides, like |only|, |alt|, or % |temporal|, or with `closed' overlay specifications, like |2| or |1-3|. % As these commands do not execute the material, the environment sequence % numbers do not increase monotonically, and the compilation results may not % be properly synchronized with the verbatim text. % Commands that only hide material, or that introduce it successively, like % |uncover| or |visible|, or `open' overlay specifications, like |2-|, % should function as expected. % % \end{itemize} % % \section{Implementation} % % All internal macros have names of the form |\CHKL@|\meta{name}. % % \begin{macro}{\chklisting} % Generate the sequence of source code identifiers used in per-environment % filenames and to manage dependencies. % If |beamer| is being used, reset the counter on each overlay to avoid % generating multiple output files for the same program. % \begin{macrocode} \newcounter{chklisting} \ifdefined\resetcounteronoverlays \resetcounteronoverlays{chklisting} \fi % \end{macrocode} % \end{macro} % % \begin{macro}{\ifCHKL@fileexists} % An internal boolean variable for remembering whether an input |.tex| file, % corresponding to the compilation of source code, was found. % \begin{macrocode} \newif\ifCHKL@fileexists % \end{macrocode} % \end{macro} % % \subsection{Package Options} % % The package options are processed using the |kvoptions| package. % % \begin{macro}{\CHKL@pkg@verbopts} % This list accumulates package-level options for the |verbatim| % environments. % \begin{macrocode} \def\CHKL@pkg@verbopts{} % \end{macrocode} % \end{macro} % % \begin{macro}{\CHKL@pkg@globalskip} % Defines the number of lines to be skipped when displaying a code sample as % defined by the global options |skipone| and |skiptwo|. % \begin{macrocode} \def\CHKL@pkg@globalskip{0} % \end{macrocode} % \end{macro} % % \noindent % Declare the package options and their default values: % \begin{macrocode} \DeclareBoolOption{withresult} \DeclareComplementaryOption{withoutresult}{withresult} \DeclareBoolOption[true]{showproblems} \DeclareComplementaryOption{hideproblems}{showproblems} \DeclareVoidOption{skipone} {\edef\CHKL@pkg@globalskip{1}% \edef\CHKL@pkg@verbopts{\CHKL@pkg@verbopts,firstline=2}} \DeclareVoidOption{skiptwo} {\edef\CHKL@pkg@globalskip{2}% \edef\CHKL@pkg@verbopts{\CHKL@pkg@verbopts,firstline=3}} \DeclareDefaultOption {\edef\CHKL@pkg@verbopts{\CHKL@pkg@verbopts,\CurrentOption}} \DeclareStringOption[]{codestyle} \DeclareStringOption[formatcom=\em]{msgstyle} \DeclareStringOption[formatcom=\em]{errstyle} \DeclareStringOption{codelst} \DeclareStringOption{msglst} \DeclareStringOption{errlst} \DeclareStringOption{emptyoption} \DeclareStringOption[.]{subdir} \DeclareStringOption[chklisting]{prefix} \DeclareStringOption[.ml]{ext} \DeclareStringOption[\#]{prompt} \DeclareStringOption[ocamlc]{compiler} \DeclareStringOption{compilerflags} \DeclareStringOption[-i]{lastflags} \DeclareStringOption[open]{includecmd} \DeclareStringOption[]{html} \ProcessKeyvalOptions* % \end{macrocode} % % \begin{macro}{\checklistings} % This macro offers another way of setting package options with the % advantage that values are not expanded. % \begin{macrocode} \def\checklistings{\kvsetkeys{CHKL}} % \end{macrocode} % \end{macro} % % \subsection{Logging Files to be Processed} % % Several definitions and commands are used to create and write to the % |.chkl| file. % % \begin{macro}{\CHKL@samplefile} % The file generated when a \LaTeX{} document that uses the |checklistings| % package is processed. % \begin{macrocode} \newwrite\CHKL@samplefile \openout\CHKL@samplefile=\jobname.chkl \AtEndDocument{\closeout\CHKL@samplefile} % \end{macrocode} % \end{macro} % % Package options are logged to the file. % \begin{macrocode} \write\CHKL@samplefile{subdir=\CHKL@subdir/} \write\CHKL@samplefile{prefix=\CHKL@prefix} \write\CHKL@samplefile{ext=\CHKL@ext} \write\CHKL@samplefile{compiler=\CHKL@compiler} \write\CHKL@samplefile{compilerflags=\CHKL@compilerflags} \write\CHKL@samplefile{lastflags=\CHKL@lastflags} \write\CHKL@samplefile{includecmd=\CHKL@includecmd} \write\CHKL@samplefile{htmlfilter=\CHKL@html} % \end{macrocode} % % \begin{macro}{\CHKL@logsample} % An entry is logged for each |chklisting| environment. % It contains the sequence number for the example, followed by a colon, an % ordered list of other sample files to import, and the page and line % numbers (to include in error messages). % \begin{macrocode} \DeclareRobustCommand{\CHKL@logsample}[2]{% \edef\CHKL@tolog{#1:#2 [page=\noexpand\thepage] [line=\the\inputlineno]}% \expandafter\write\expandafter\CHKL@samplefile\expandafter{\CHKL@tolog}% } % \end{macrocode} % \end{macro} % % \subsection{Insertion of Compilation Results} % % Several macros are defined for use by the |checklistings.sh| script (and % any similar program). % These macros are called from within the |.tex| file generated for each % |chklisting| environment. % % \begin{macro}{\ifchklisting} % A successful compilation is signalled by |\chklistingtrue|, and a failed % compilation by |\chklistingfalse|. % \begin{macrocode} \newif\ifchklisting % \end{macrocode} % \end{macro} % % \begin{macro}{\setchklistingcmd} % The command used to compile a sample is recorded by |\setchklistingcmd| % which (re)defines the internal |\CHKL@prompt| value. % \begin{macrocode} \DeclareRobustCommand{\setchklistingcmd}[1]{% \global\def\chklistingcmd{\emph{\CHKL@prompt{#1}}}} % \end{macrocode} % \end{macro} % \begin{environment}{ChkListingMsg} % Normal compiler messages (written on |stdout|) should be communicated % between |\begin{ChkListingMsg}| and |\end{ChkListingMsg}|. % This verbatim text is saved using the |SaveVerbatim| feature of % |fancyvrb|. % \begin{macrocode} \def\ChkListingMsg{\FV@Environment{}{ChkListingMsg}} \def\FVB@ChkListingMsg{\FVB@SaveVerbatim{ChkListingMsg}} \let\FVE@ChkListingMsg\FVE@SaveVerbatim \DefineVerbatimEnvironment{ChkListingMsg}{ChkListingMsg}{} % \end{macrocode} % \end{environment} % \begin{environment}{ChkListingErr} % Compiler error messages (usually written on |stderr|) should be % communicated between |\begin{ChkListingErr}| and |\end{ChkListingErr}|. % This verbatim text is saved using the |SaveVerbatim| feature of % |fancyvrb|. % \begin{macrocode} \def\ChkListingErr{\FV@Environment{}{ChkListingErr}} \def\FVB@ChkListingErr{\FVB@SaveVerbatim{ChkListingErr}} \let\FVE@ChkListingErr\FVE@SaveVerbatim \DefineVerbatimEnvironment{ChkListingErr}{ChkListingErr}{} % \end{macrocode} % \end{environment} % \begin{macro}{\chklistingfile} % This is the filename used by |checklistings.sh| to refer to the file % containing sample code when |\setchklistingcmd| is called. % \begin{macrocode} \DeclareRobustCommand{\chklistingfile}{\CHKL@prefix\CHKL@ext} % \end{macrocode} % \end{macro} % % \subsection{Main Environment} % % Several auxiliary definitions are needed to track per-environment % configuration options. % % \begin{macro}{\ifCHKL@shouldfail} % This boolean variable records whether sample code is expected to fail. % \begin{macrocode} \newif\ifCHKL@shouldfail % \end{macrocode} % \end{macro} % % \begin{macro}{\ifCHKL@showcode} % This boolean variable records whether the compilation result should be % shown. % \begin{macrocode} \newif\ifCHKL@showcode % \end{macrocode} % \end{macro} % % \begin{macro}{\CHKL@skip} % Defines the number of lines to be skipped when displaying a code sample. % It defaults to the value of |\CHKL@pkg@globalskip|, but may be altered by % the environment options |skipone| and |skiptwo|. % This value is only used to generate the |skip=| field in the |.chkl| file. % The actual skipping is done by the |firstline| option of |verbopts|. % \begin{macrocode} \def\CHKL@skip{0} % \end{macrocode} % \end{macro} % % The |keyval| package\footnote{\url{http://www.ctan.org/pkg/keyval}} is % used to parse environment options. % The following macros setup parameters used by the |chklisting| % environment. % % \begin{macro}{\CHKL@continue} % \begin{macro}{\CHKL@precontinue} % These two macros hold lists of source code identifiers: % |\CHKL@precontinue| tracks the dependencies of the previous |chklisting| % environment and |\CHKL@continue| tracks those of the current one. % The |continue| option appends the previous dependencies onto the list of % current ones. % The dependencies used at each labelled environment are remembered in % |\RBRB@deps|\meta{label}. % The |include| option causes them to be added to the list of current % dependencies. % % \begin{macrocode} \edef\CHKL@precontinue{} \define@key{CHKL@envkeys}{continue}[]{\edef\CHKL@continue{\CHKL@precontinue}} \define@key{CHKL@envkeys}{include}{% \edef\CHKL@continue{\CHKL@continue\space\@ifundefined{CHKL@deps@#1}% {#1}{\csname CHKL@deps@#1\endcsname}}} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macrocode} \define@key{CHKL@envkeys}{fail}[]{\CHKL@shouldfailtrue} \define@key{CHKL@envkeys}{label}{\edef\CHKL@label{#1}} \define@key{CHKL@envkeys}{skipnone}[]{% \edef\CHKL@skip{0}\edef\CHKL@verbopts{\CHKL@verbopts,firstline=1}} \define@key{CHKL@envkeys}{skipone}[]{% \edef\CHKL@skip{1}\edef\CHKL@verbopts{\CHKL@verbopts,firstline=2}} \define@key{CHKL@envkeys}{skiptwo}[]{% \edef\CHKL@skip{2}\edef\CHKL@verbopts{\CHKL@verbopts,firstline=3}} \define@key{CHKL@envkeys}{hide}[]{\CHKL@showcodefalse} \define@key{CHKL@envkeys}{withresult}[]{\CHKL@withresulttrue} \define@key{CHKL@envkeys}{withoutresult}[]{\CHKL@withresultfalse} \define@key{CHKL@envkeys}{showproblems}[]{\CHKL@showproblemstrue} \define@key{CHKL@envkeys}{hideproblems}[]{\CHKL@showproblemsfalse} % \end{macrocode} % % \begin{macro}{\chklistingmsg} % This macro takes a single argument \meta{label}. % It first configures the |listings| and |fancyvrb| packages with the % current display options. % It then checks the |fancyvrb| saved text namespace % (`\texttt{FV@SV@\ldots}') for an entry named `\texttt{\ldots % CHKL@MSG@\meta{label}}'. % If found, the associated verbatim text is inserted via the |\UseVerbatim| % feature of |fancyvrb|, otherwise an error message is inserted. % In the latter case, we prefer not to fail outright, because the user may % not yet have had the chance to run the compiler on the extracted code, in % which case the log will already contain warnings from |chklisting|. % By convention, the |chklisting| environment creates an entry for the % empty label (`\texttt{FV@SV@CHKL@MSG@}') when compilation succeeds. % \begin{macrocode} \DeclareRobustCommand{\chklistingmsg}[1]{ \bgroup% \ifx\CHKL@msglst\CHKL@emptyoption\else \expandafter\lstset\expandafter{\CHKL@msglst,fancyvrb=true}\fi% \@ifundefined{FV@SV@CHKL@MSG@#1} {\def\@tempa{#1} \ifx\@tempa\empty \CHKL@none \else $\langle$No message found for the label `#1'!$\rangle$ \fi} {\expandafter\UseVerbatim\expandafter[\CHKL@msgstyle]{CHKL@MSG@#1}}% \egroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\chklistingerr} % This macro is essentially the same as the previous one---only that the % substring `\texttt{ERR}' is used instead of `\texttt{MSG}'. % \begin{macrocode} \DeclareRobustCommand{\chklistingerr}[1]{ \bgroup% \ifx\CHKL@errlst\CHKL@emptyoption\else \expandafter\lstset\expandafter{\CHKL@errlst,fancyvrb=true}\fi% \@ifundefined{FV@SV@CHKL@ERR@#1} {\def\@tempa{#1} \ifx\@tempa\empty \CHKL@none \else $\langle$No message found for the label `#1'!$\rangle$ \fi} {\expandafter\UseVerbatim\expandafter[\CHKL@errstyle]{CHKL@ERR@#1}}% \egroup} % \end{macrocode} % \end{macro} % % \begin{environment}{chklisting} % This is the main environment for including source code. % This macro works in two parts: % \begin{enumerate} % \item % It uses the listings package to write the code to a file, % \item % It either loads the corresponding |.tex| file or logs an error message. % \end{enumerate} % % The |listings| package allows the definition of custom verbatim % environments. % This one has a single argument (a list of |keyval| options). % % \begin{macrocode} \lstnewenvironment{chklisting}[1][] {% % \end{macrocode} % Set default parameter values before invoking |\setkeys|: % \begin{macrocode} \CHKL@shouldfailfalse% \CHKL@showcodetrue% \let\CHKL@label\@undefined% \edef\CHKL@continue{}% \def\CHKL@skip{\CHKL@pkg@globalskip}% \let\CHKL@verbopts\CHKL@pkg@verbopts% \def\@currentlabel{\thechklisting}% \setkeys{CHKL@envkeys}{#1}% % \end{macrocode} % % Log an entry to the |.chkl| file: % % \begin{macrocode} \CHKL@logsample{\arabic{chklisting}}{\CHKL@continue% \space\ifnum\CHKL@skip>0[skip=\CHKL@skip]\fi% \ifCHKL@shouldfail\space[fail]\fi}% % \end{macrocode} % % Update |\CHKL@precontinue| for the next source code block, and, if a label % was defined, add an |\CHKL@deps@|\meta{label} entry. % % \begin{macrocode} \global\edef\CHKL@precontinue{\CHKL@continue\space\arabic{chklisting}}% \@ifundefined{CHKL@label}{}{% \global\expandafter\edef\csname CHKL@deps@\CHKL@label\endcsname{\CHKL@precontinue}}% % \end{macrocode} % % A file will be created in the |\CHKL@subdir| subdirectory, with the name % |\CHKL@prefix| followed by the value of the |chklisting| counter, padded % out with zeroes to four digits, and the extension |\RBRB@ext|. % % \begin{macrocode} \edef\CHKL@num{% \ifnum\value{chklisting}<1000 0\fi \ifnum\value{chklisting}<100 0\fi \ifnum\value{chklisting}<10 0\fi \arabic{chklisting}}% \stepcounter{chklisting}% \def\CHKL@file{\CHKL@subdir/\CHKL@prefix\CHKL@num}% % \end{macrocode} % % Clear the definitions used to return information about the compilation % run, and close the environment by opening a file, using the |listings| % package, into which to write the ensuing contents. % % \begin{macrocode} \global\let\chklistingcmd\@undefined% \global\let\FV@SV@ChkListingMsg\@undefined% \global\let\FV@SV@ChkListingErr\@undefined% \chklistingtrue% \setbox\@tempboxa\hbox\bgroup% \lst@BeginWriteFile{\CHKL@file\CHKL@ext}% } % \end{macrocode} % % Start closing the environment by closing the previously opened file and % group. % % \begin{macrocode} {% \lst@EndWriteFile% \egroup% % \end{macrocode} % % If |hide| is not active, apply |\CHKL@verbopts| and reload the newly % created file. % % \begin{macrocode} \ifCHKL@showcode% \bgroup% \ifx\CHKL@codelst\CHKL@emptyoption\else% \expandafter\lstset\expandafter{\CHKL@codelst,fancyvrb=true}% \fi% \expandafter\fvset\expandafter{\CHKL@verbopts}% \expandafter\VerbatimInput\expandafter[\CHKL@codestyle]{\CHKL@file\CHKL@ext}% \egroup% \fi% % \end{macrocode} % % Check whether a corresponding |.tex| file was created: % % \begin{macrocode} \global\edef\CHKL@none{$\langle$Cannot load \CHKL@file.tex!$\rangle$}% \InputIfFileExists{\CHKL@file.tex}{\CHKL@fileexiststrue}{\CHKL@fileexistsfalse}% % \end{macrocode} % % If the |.tex| file was loaded successfully, create `unlabelled' saved % verbatim environments for the message and error texts. % These are exploited, respectively, by the |\chklistingmsg| and % |\chklistingerr| macros. % % \begin{macrocode} \ifCHKL@fileexists% \@ifundefined{FV@SV@ChkListingMsg}% {}{\global\let\FV@SV@CHKL@MSG@=\FV@SV@ChkListingMsg}% \@ifundefined{FV@SV@ChkListingErr}% {}{\global\let\FV@SV@CHKL@ERR@=\FV@SV@ChkListingErr}% % \end{macrocode} % % Then, if compilation failed and the |fail| option was not active, or if % compilation succeeded and the |fail| option is active, log a warning % message and, if errors are not being ignored, include details in the % document. % Otherwise, if |withresult| was given, expand either |\chklistingerr| or % |\chklistingmsg|. % % \begin{macrocode} \ifCHKL@shouldfail% \ifchklisting% \PackageWarning{checklistings}% {Compilation of \CHKL@file\CHKL@ext\space should have failed}% \ifCHKL@showproblems% \UseVerbatim[frame=single, label=Unexpected success, rulecolor=\color{red}]{ChkListingMsg}% \fi% \else% \ifCHKL@withresult% {\setlength{\partopsep}{0em}\chklistingerr{}}% \fi% \fi% \else% \ifchklisting% \ifCHKL@withresult% {%\vspace{\dimexpr-2\topsep-2\partopsep+.5em\relax}% \setlength{\partopsep}{0em}\chklistingmsg{}}% \fi% \else% \PackageWarning{checklistings}% {Compilation of \CHKL@file\CHKL@ext\space should not have failed}% \ifCHKL@showproblems% \UseVerbatim[frame=single, label=Unexpected failure, rulecolor=\color{red}]{ChkListingErr}% \fi% \fi% \fi% \else% % \end{macrocode} % % If the |.tex| file was not loaded successfully, clear the % |\chklistingcmd| macros, and the `unlabelled' saved verbatim environments % for the message and error results. % % \begin{macrocode} \PackageWarning{checklistings}{Cannot load \CHKL@file.tex}% \global\let\chklistingcmd\CHKL@none% \global\let\FV@SV@CHKL@MSG@\@undefined% \global\let\FV@SV@CHKL@ERR@\@undefined% \fi% % If this environment is labelled, create persistent references to the saved % verbatim environments for the message and error results. % These are exploited, respectively, by the |\chklistingmsg| and % |\chklistingerr| macros when their \meta{label} argument is not empty. % \@ifundefined{CHKL@label}{}{% \global\expandafter\let% \csname FV@SV@CHKL@MSG@\CHKL@label\endcsname=\FV@SV@CHKL@MSG@% \global\expandafter\let% \csname FV@SV@CHKL@ERR@\CHKL@label\endcsname=\FV@SV@CHKL@ERR@% }% }% % \end{macrocode} % \end{environment} % \makeatother \clearpage % \Finale \endinput