From b759f025b1f56ba1063cd6f4cb0590266854e4e7 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Thu, 17 Mar 2011 23:15:59 +0000 Subject: bashful (17mar11) git-svn-id: svn://tug.org/texlive/trunk@21748 c570f23f-e606-0410-a88d-b1316a301751 --- Master/texmf-dist/tex/latex/bashful/bashful.sty | 464 ++++++++++++++++-------- 1 file changed, 316 insertions(+), 148 deletions(-) (limited to 'Master/texmf-dist/tex/latex/bashful') diff --git a/Master/texmf-dist/tex/latex/bashful/bashful.sty b/Master/texmf-dist/tex/latex/bashful/bashful.sty index 326b999158f..fab73a2de26 100644 --- a/Master/texmf-dist/tex/latex/bashful/bashful.sty +++ b/Master/texmf-dist/tex/latex/bashful/bashful.sty @@ -16,15 +16,15 @@ \NeedsTeXFormat{LaTeX2e}% % Auxiliary identification information -\newcommand\date@bashful{2011/02/28}% -\newcommand\version@bashful{V 0.91}% +\newcommand\date@bashful{2011/03/12}% +\newcommand\version@bashful{V 0.92}% \newcommand\author@bashful{Yossi Gil}% \newcommand\mail@bashful{yogi@cs.technion.ac.il}% \newcommand\signature@bashful{% bashful \version@bashful{} by \author@bashful{} \mail@bashful }% - + % Identify this package \ProvidesPackage{bashful}[\date@bashful{} \signature@bashful: Write and execute a bash script within LaTeX, with, or @@ -32,37 +32,101 @@ ] \PackageInfo{bashful}{This is bashful, \signature@bashful}% +\RequirePackage{catchfile} +% Use xkeyval for retrieving parameters +\RequirePackage{xkeyval}% + +% If true, all activities take place in a designated directory. +\newif\if@hide@BL@\@hide@BL@false + +% This is the default name for a directory in which processing should +% take place if \@hide@BL@true. +\def\directory@BL{_00} + % Use listing to display bash scripts. \RequirePackage{listings}% + % listings style for the script, can be redefined by client - \lstdefinestyle{bashfulList}{ + \lstdefinestyle{bashfulScript}{ basicstyle=\ttfamily, + keywords={}, showstringspaces=false}% % listings style for the stdoutFile, can be redefined by client \lstdefinestyle{bashfulStdout}{ basicstyle=\sl\ttfamily, + keywords={}, + showstringspaces=false + }% + % listings style for the stderrFile, can be redefined by client + \lstdefinestyle{bashfulStderr}{ + basicstyle=\sl\ttfamily\color{red}, + keywords={}, showstringspaces=false }% -% Use xkeyval for retrieving parameters -\RequirePackage{xkeyval}% - %%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % Keys in alphabetical order: - %%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % File Name keys in alphabetical order: + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + % scriptFile: String = \BL@exitCodeFile: Where should the exit code be stored + % if it is not zero. + \edef\BL@exitCodeFile{\jobname.exitCode}% + \define@cmdkey{bashful}[BL@]{exitCodeFile}{}% + + % scriptFile: String = \BL@scriptFile: Where should the script be saved? + \edef\BL@scriptFile{\jobname.sh}% + \define@cmdkey{bashful}[BL@]{scriptFile}{}% + + % stderrFile: String = \BL@stderrFile: Where should the standard error + % sream be saved? + \edef\BL@stderrFile{\jobname.stderr}% + \define@cmdkey{bashful}[BL@]{stderrFile}{}% + + % stdoutFile: String = \BL@stdoutFile: Where should the standard output stream + % be saved? + \edef\BL@stdoutFile{\jobname.stdout}% + \define@cmdkey{bashful}[BL@]{stdoutFile}{}% + + % dir: String = \directory@BL: name of directory in which execution is going to take + % place + \define@cmdkey{bashful}[BL@]{dir}{\def\directory@BL{#1}}% + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % List configuration boolean keys + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + % list: Boolean = \ifBL@script: Should we list the script we generate? + \define@boolkey{bashful}[BL@]{script}[true]{}% + + % stdout: Boolean = \ifBL@stderr: Should we list the standard error? + \define@boolkey{bashful}[BL@]{stderr}[true]{}% + + % stdout: Boolean = \ifBL@stdout: Should we list the standard output? + \define@boolkey{bashful}[BL@]{stdout}[true]{} + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % Error checking Boolean keys. + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + % stdout: Boolean = \ifBL@ignoreExitCode: Should we ignore the exit + % code? + \define@boolkey{bashful}[BL@]{ignoreExitCode}[true]{} + + % stdout: Boolean = \ifBL@ignoreStderr: Should we ignore the exit + % code? + \define@boolkey{bashful}[BL@]{ignoreStderr}[true]{} + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % Miscelaneous keys + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % environment: String = \BL@environment: Which environment should we wrap the listings + % environment: String = \BL@environment: Which environment should we wrap + % the listings \def\BL@environment{none@BL}% \define@cmdkey{bashful}[BL@]{environment}{}% \newenvironment{none@BL}{}{} % Default, empty environment for wrapping the listings - % scriptFile: String = Where should the listed script be saved? - \def\BL@scriptFile{\jobname.lsh}% - \define@cmdkey{bashful}[BL@]{scriptFile}{}% - - % list: Boolean = \ifBL@list: Should we list the script we generate? - \define@boolkey{bashful}[BL@]{list}[true]{}% - % prefix: String = \BL@prefix: What prefix should be printed before a listing. \def\BL@prefix{\@percentchar\space}% \define@cmdkey{bashful}[BL@]{prefix}{}% @@ -70,58 +134,47 @@ % shell: String = \BL@shell: Which shell should be used for execution? \def\BL@shell{bash}% \define@cmdkey{bashful}[BL@]{shell}{}% - - % scriptFile: String = \BL@scriptFile: Where should the script be saved? - \def\BL@scriptFile{\jobname.sh}% - \define@cmdkey{bashful}[BL@]{scriptFile}{}% - % stderrFile: String = \BL@stderrFile: Where should the standard error be saved? - \def\BL@stderrFile{\jobname.stderr}% - \define@cmdkey{bashful}[BL@]{stderrFile}{}% + % verbose: Boolean = \ifBL@verbose: Log every step we do + \define@boolkey{bashful}[BL@]{verbose}[true]{}% - % stdout: Boolean = \ifBL@stdout: Should we list the standard output? - \define@boolkey{bashful}[BL@]{stdout}[true]{}% - - % stdoutFile: String = \BL@stdoutFile: Where should the standard output be saved? - \def\BL@stdoutFile{\jobname.stdout}% - \define@cmdkey{bashful}[BL@]{stdoutFile}{}% - % verbose: Boolean = \ifBL@verbose: Log every step we do - \define@boolkey{bashful}[BL@]{verbose}[true]{}% +\DeclareOptionX{hide}{\@hide@BL@true} +\DeclareOptionX{dir}{\@hide@BL@true\def\directory@BL{#1}} +\DeclareOptionX{verbose}{\BL@verbosetrue} +\ExecuteOptionsX{} +\ProcessOptionsX\relax % \bash: the main command we define. It chains to \bashI which chains to % \bashII, etc. \begingroup + %\where@BL \catcode`\^^M\active% \gdef\bash{% - \log@BL{Beginning a group so that all cat code changes are local}% + \logBL{Beginning a group so that all cat code changes are local}% \begingroup% - \log@BL{Making \^\^M a true newline}% + \logBL{Making \^\^M a true newline}% \catcode`\^^M\active% \def^^M{^^J}% - \log@BL{Checking for optional arguments}% + \logBL{Checking for optional arguments}% \@ifnextchar[\bashI{\bashI[]}% }% \endgroup % \bashI: Process the optional arguments and continue -\def\bashI[#1]{% - \setKeys@BL{#1}% - \bashII% And, continue processing. -}% +\def\bashI[#1]{\setKeys@BL{#1}\bashII} -% \bashII: Set category codes of all to special, and proceed. +% \bashII: Set category codes of all characters to special, and proceed. \begingroup \catcode`\^^M\active% \gdef\bashII{% - \log@BL{bashII: Making ^^M a true new line}% + \logBL{bashII: Making \^\^M a true new line}% \catcode`\^^M\active% \def^^M{^^J}% - \log@BL{bashII: Making all characters other}% + \logBL{bashII: Making all characters other}% \let\do\@makeother% \dospecials% - \bashIII% - }% + \bashIII}% \endgroup % \bashIII: Consume all tokens until \END (but ignoring the preceding and @@ -130,23 +183,61 @@ \catcode`\@=0\relax \catcode`\^^M\active @catcode`@\=12@relax% - @gdef@bashIII^^M#1^^M\END{@bashIV{#1}}@relax% -@endgroup + @gdef@bashIII^^M#1^^M\END{@bashIV{#1}@bashV{#1}@logBL{bashV: Done!}@endgroup}@endgroup +% -% \bashIV: Process the tokens by storing them in a script file, executing this -% file, listing it if required, and presenting the standard output if required. +\newcommand\logBL[1]{\ifBL@verbose\typeout{L\the\inputlineno: #1}\fi} + +% \bashIV: Process the tokens by storing them in a script file, and executing +% this file, \newcommand\bashIV[1]{% - \generateScriptFile@BL{#1}\relax + \logBL{BashIV: begin}% + \makeDirectory@BL + \generateScriptFile@BL{#1}\relax \executeScriptFile@BL - \checkStderr@BL - \listScript@BL{#1}\relax% - \listStdout@BL - \log@BL{Ending group so that all cat codes changes disappear}\relax% - \endgroup + \logBL{BashIV: done}% }% +\def\makeDirectory@BL{% + \if@hide@BL@ + \logBL{Making directory \directory@BL}% + \immediate\write18{mkdir -p \directory@BL}% + \else + \logBL{Using current directory}% + \fi +} + +\newcommand\splice[1]{% + \bashIV{#1}% + \expandFileName@BL{\BL@stdoutFile}% + \CatchFileDef{\BL@file@contents}{\BL@stdoutFile}{\relax}% + \ignorespaces\BL@file@contents\unskip +} + +% listing the script file if required, and presenting the standard output and +% standar error if required. +\newcommand\bashV[1]{% + \logBL{Wrapping up after execution}% + \storeToFile@BL{\BL@prefix#1}{\BL@scriptFile}% + \expandFileName@BL\BL@scriptFile + \expandFileName@BL\BL@stdoutFile + \expandFileName@BL\BL@stderrFile + \logBL{Files are: \BL@scriptFile, \BL@stdoutFile, and \BL@stderrFile}% + %\checkScriptErrors@BL + \listEverything@BL + \logBL{Wrap up done}} + +\def\expandFileName@BL#1{% + \logBL{expandFileName}% + \logBL{Setting, if necessary, correct path of \noexpand#1 }% + \if@hide@BL@ + \logBL{Prepending path (\directory@BL) to #1}% + \edef#1{\directory@BL/#1}% + \logBL{Obtained #1}% + \fi +} \def\setKeys@BL#1{% - \log@BL{Processing key=val pairs in options string [#1]}\relax + \logBL{Processing key=val pairs in options string [#1]}\relax \setkeys{bashful}{#1}% }% @@ -157,153 +248,230 @@ \newwrite\writer@BL % Store the list of tokens in the first argument into the file given -% in the second argument -\newcommand\storeToFile@BL[2]{% - \log@BL{Creating file #2 :=^^J#1^^J}% - \immediate\openout\writer@BL#2 +% in the second argument; prepend directory if necessary +\newcommand\storeToFile@BL[2]{% + \logBL{ #2 :=^^J#1^^J}% + \if@hide@BL@ + \logBL{File #2 will be created in \directory@BL}% + \storeToFileI@BL{#1}{\directory@BL/#2} + \else + \logBL{File #2 will be created in current directory}% + \storeToFileI@BL{#1}{#2}% + \fi + \logBL{Writing done!}% +}% + +% Store the list of tokens in the first argument into the file given +% in the second argument; the second argument could be qualified with +% a directory name. +\newcommand\storeToFileI@BL[2]{% + \logBL{Writing to file #2...}% + \immediate\openout\writer@BL#2% \immediate\write\writer@BL{#1}% \immediate\closeout\writer@BL }% % Execute the content of our script file. \newcommand\executeScriptFile@BL{% - \def\command@BL{\BL@shell\space\BL@scriptFile}% - \edef\command@BL{% - \BL@shell\space -c - "\command@BL \space > \BL@stdoutFile \space2> \BL@stderrFile \space - || echo '\command@BL' exit code was $? 2>>\BL@stderrFile"% - }% - \log@BL{Executing:^^J \command@BL}% - \immediate\write18{\command@BL}% + \edef\command@BL{\BL@shell \space \BL@scriptFile}% + \if@hide@BL@ + \logBL{Adding a "cd command"}% + \edef\command@BL{cd \directory@BL;\command@BL} + \fi% + \edef\command@BL{\command@BL \space >\BL@stdoutFile \space 2>\BL@stderrFile}% + \edef\command@BL{\command@BL \space || echo $? >\BL@exitCodeFile}% + \edef\command@BL{\BL@shell\space -c "\command@BL"}% + \logBL{Executing:^^J \command@BL}% + \immediate\write18{\command@BL}% }% \newread\reader@BL -% Issue an error if stderr is not empty -\newcommand\checkStderr@BL{% - \log@BL{Examining \BL@stderrFile}% + +% Issue an error message if errors found during execution +\newcommand\checkScriptErrors@BL{% + \logBL{Checking for script errors}% \begingroup \newif\ifErrorsFound@\ErrorsFound@false - \log@BL{Opening \BL@stderrFile}% + \checkExitCodeFile@BL + \ifdefined\exitCode@BL + \logBL{Non zero exit code found (\exitCode@BL), and I was not instructed to ignore it} + \ErrorsFound@true + \fi + \def\eoln{\par} + \def\firstErrorLine{\par} + \checkStderrFile@BL + \logBL{I will print content of \BL@stderrFile\space (if found)} + \ifx\firstErrorLine\eoln + \relax + \else + \logBL{Standard error was not empty, and I was not instructed to ignore it} + \message{Standard error not empty. Here is how + ^^Jfile \BL@stderrFile\space begins: + ^^J>>>>\space + ^^Jbut, you really ought to examine this file yourself!} + \ErrorsFound@true + \fi + \ifErrorsFound@ + \logBL{Issuing an error message since \BL@stderrFile\space was not empty}% + \errmessage{Your shell script failed....} + \else + \logBL{Proceeding as usual}% + \fi + \endgroup +}% + +\newcommand\checkExitCodeFile@BL{% + \ifBL@ignoreExitCode + \logBL{Ignoring \BL@exitCodeFile, as per command flag}% + \else + \logBL{Opening \BL@exitCodeFile}% + \openin\reader@BL=\BL@exitCodeFile + \ifeof\reader@BL + \logBL{File \BL@exitCodeFile\space missing, exit code was probably 0} + \else + \logBL{File \BL@exitCodeFile\space exists, let's get the exit code}% + \logBL{Reading first line of \BL@exitCodeFile}% + \catcode`\^^M=5 + \read\reader@BL to \exitCode@BL + \closein\reader@BL + \fi + \fi +} + +\newcommand\checkStderrFile@BL{% + \ifBL@stderr + \logBL{Will be listing \BL@stderrFile, so erroneous content is ignored}% + \else + \ifBL@ignoreStderr + \logBL{Ignoring \BL@stderrFile, as per command flag}% + \else + \checkStderrFileI@BL + \fi + \fi +} + +\newcommand\checkStderrFileI@BL{% + \logBL{Opening \BL@stderrFile}% \openin\reader@BL=\BL@stderrFile\relax \ifeof\reader@BL \BL@verbosetrue - \log@BL{Strange... \BL@stderrFile{} does not exist (probably bashful bug)}% - \log@BL{Switching to verbose mode}% + \logBL{Hmm... \BL@stderrFile\space does not exist (probably a package bug)}% + \logBL{Switching to verbose mode}% \else - \log@BL{Reading first line of \BL@stderrFile}% + \logBL{Reading first line of \BL@stderrFile}% \catcode`\^^M=5 \read\reader@BL to \firstErrorLine \ifeof\reader@BL - \def\eoln{\par} \ifx\firstErrorLine\eoln - \log@BL{File \BL@stderrFile\space is empty}% - \closein\reader@BL + \logBL{File \BL@stderrFile\space is empty} \else - \log@BL{File \BL@stderrFile\space has one line [\firstErrorLine]}% - \ErrorsFound@true - \closein\reader@BL + \logBL{File \BL@stderrFile\space has one line [\firstErrorLine]}% + \ErrorsFound@true \fi \else - \log@BL{File \BL@stderrFile\space has two lines or more}% - \ErrorsFound@true - \closein\reader@BL - \fi - \fi - \ifErrorsFound@ - \log@BL{Issuing an error message since \BL@stderrFile\space was not empty}% - \let\please=\relax\let\examine=\relax\let\stderr=\relax - \errmessage{^^JError(s) executing \BL@scriptFile. Here is how - ^^Jfile \BL@stderrFile\space begins: - ^^J\firstErrorLine - ^^Jbut, you really ought to examine this file yourself} - \please - \examine - \stderr + \logBL{File \BL@stderrFile\space has two lines or more}% + \ErrorsFound@true + \fi + \closein\reader@BL +} + +% List the contents of the script, stdout and stderr, as per the flags. +\newcommand\listEverything@BL{% + \logBL{Checking whether any listings are required}% + \newif\if@listSomething@BL@ + \ifBL@script\@listSomething@BL@true\fi + \ifBL@stdout\@listSomething@BL@true\fi + \ifBL@stderr\@listSomething@BL@true\fi + \if@listSomething@BL@ + \beginWrappingEnvironment@BL + \listEverythingI@BL + \endWrappingEnvironment@BL \else - \log@BL{Proceeding as usual since \BL@stderrFile{} is empty}% + \logBL{Nothing has to be listed}% \fi - \endgroup +} + +% Auxiliary macro to list the contents of the script, stdout and stderr, as per +% the flags. +\newcommand\listEverythingI@BL{% + \logBL{Laying out the correct \noexpand\lstinputlisting commands}%1 + \ifBL@script\listScript@BL\BL@scriptFile\fi + \ifBL@stdout\listStdout@BL\BL@stdoutFile\fi + \ifBL@stderr\listStderr@BL\BL@stderrFile\fi }% -% List the content of the script file. \newcommand\listScript@BL[1]{% - \ifBL@list{% - \log@BL{Prepending prefix [[\BL@prefix]] to generate \BL@scriptFile}% - \storeToFile@BL{\BL@prefix#1}{\BL@scriptFile}% - \forceLTR@BL - \fixPolyglossiaBug@BL - \log@BL{Invoking \noexpand\lstinputlisting to list \BL@scriptFile}% - \ifBL@stdout - % trim bottom - \beginWrappingEnvironment@BL - \lstinputlisting[style=bashfulList,belowskip=0pt]{\BL@scriptFile}% - \else - \beginWrappingEnvironment@BL - \lstinputlisting[style=bashfulList]{\BL@scriptFile}% - \endWrappingEnvironment@BL - \fi - }\else\relax\fi + \logBL{Listing script: #1} + \def\flags@BL{style=bashfulScript} + \logBL{Initial flags for listing #1 are \flags@BL} + \ifBL@stdout\edef\flags@BL{\flags@BL, belowskip=0pt}\fi + \ifBL@stderr\edef\flags@BL{\flags@BL, belowskip=0pt}\fi + \doList@BL#1\flags@BL +} + +\newcommand\listStdout@BL[1]{% + \logBL{Listing stdout: #1} + \edef\flags@BL{style=bashfulStdout} + \logBL{Initial flags for listing stdout file are \flags@BL} + \ifBL@script\edef\flags@BL{\flags@BL, aboveskip=0pt}\fi + \ifBL@stderr\edef\flags@BL{\flags@BL, belowskip=0pt}\fi + \doList@BL#1\flags@BL }% +\newcommand\listStderr@BL[1]{% + \logBL{Listing stderr: #1}% + \def\flags@BL{style=bashfulStderr}% + \logBL{Initial flags for listing stderr file are \flags@BL} + \ifBL@script\edef\flags@BL{\flags@BL, aboveskip=0pt}\fi + \ifBL@stdout\edef\flags@BL{\flags@BL, aboveskip=0pt}\fi + \doList@BL#1\flags@BL +}% + +\newcommand\doList@BL[2]{% + \logBL{Flags for listing #1 are #2}% + \expandafter\lstset\expandafter{#2}% + \lstinputlisting{#1}% + }% + \def\beginWrappingEnvironment@BL{% + \logBL{Beginning environment \BL@environment}% \expandafter\csname\BL@environment\endcsname + \forceLTR@BL + \fixPolyglossiaBug@BL }% \def\endWrappingEnvironment@BL{% \expandafter\csname end\BL@environment\endcsname }% -% Display the standard output of the execution -\newcommand\listStdout@BL{% - \ifBL@stdout{% - \log@BL{Listing stdout file \BL@stdoutFile}% - \forceLTR@BL - \fixPolyglossiaBug@BL - \log@BL{Invoking \noexpand\lstinputlisting to list \BL@stdoutFile}% - \ifBL@list % trim top - \lstinputlisting[style=bashfulStdout,aboveskip=0pt]{\BL@stdoutFile}% - \endWrappingEnvironment@BL - \else - \beginWrappingEnvironment@BL - \lstinputlisting[style=bashfulStdout]{\BL@stdoutFile}% - \endWrappingEnvironment@BL - \fi - }\else\relax\fi -}% - \newcommand\fixPolyglossiaBug@BL{% - \log@BL{Trying to fix a Polyglossia package bug}% + \logBL{Trying to fix a Polyglossia package bug}% \ifdefined\ttfamilylatin - \log@BL{Replacing \noexpand\ttfamily with \noexpand\ttfamilylatin}% + \logBL{Replacing \noexpand\ttfamily with \noexpand\ttfamilylatin}% \let\ttfamily=\ttfamilylatin - \log@BL{Replacing \noexpand\rmfamily with \noexpand\rmfamilylatin}% + \logBL{Replacing \noexpand\rmfamily with \noexpand\rmfamilylatin}% \let\rmfamily=\rmfamilylatin - \log@BL{Replacing \noexpand\sffamily with \noexpand\sffamilylatin}% + \logBL{Replacing \noexpand\sffamily with \noexpand\sffamilylatin}% \let\sffamily=\sffamilylatin - \log@BL{Replacing \noexpand\normalfont with \noexpand\normalfontlatin}% + \logBL{Replacing \noexpand\normalfont with \noexpand\normalfontlatin}% \let\normalfont=\normalfontlatin \else - \log@BL{Polyglossia package probably not loaded}% + \logBL{Polyglossia package probably not loaded}% \relax \fi }% \newcommand\forceLTR@BL{% - \log@BL{Making sure we are not in right-to-left mode}% + \logBL{Making sure we are not in right-to-left mode}% \ifdefined\setLTR - \log@BL{Command \noexpand\setLTR is defined, invoking it}% + \logBL{Command \noexpand\setLTR is defined, invoking it}% \setLTR \else - \log@BL{Command \noexpand\setLTR is not defined, we are probably LTR}% + \logBL{Command \noexpand\setLTR is not defined, we are probably LTR}% \relax \fi }% -\newcommand\log@BL[1]{% - \ifBL@verbose - \typeout{L\the\inputlineno: #1}% - \else - \relax - \fi -}% + + -- cgit v1.2.3