summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/iexec/iexec.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'macros/latex/contrib/iexec/iexec.dtx')
-rw-r--r--macros/latex/contrib/iexec/iexec.dtx245
1 files changed, 137 insertions, 108 deletions
diff --git a/macros/latex/contrib/iexec/iexec.dtx b/macros/latex/contrib/iexec/iexec.dtx
index e6e9905fb2..43e6da2333 100644
--- a/macros/latex/contrib/iexec/iexec.dtx
+++ b/macros/latex/contrib/iexec/iexec.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
% (The MIT License)
%
-% Copyright (c) 2021-2023 Yegor Bugayenko
+% Copyright (c) 2021-2024 Yegor Bugayenko
%
% Permission is hereby granted, free of charge, to any person obtaining a copy
% of this software and associated documentation files (the 'Software'), to deal
@@ -50,7 +50,7 @@
%<package>\NeedsTeXFormat{LaTeX2e}
%<package>\ProvidesPackage{iexec}
%<*package>
-[2023-12-28 0.13.0 Inputable Shell Executions]
+[2024-01-14 0.14.0 Inputable Shell Executions]
%</package>
%<*driver>
\documentclass{ltxdoc}
@@ -265,32 +265,44 @@ Today is \iexec{date +\%Y}!
%</verb>
%\fi
+% \DescribeMacro{maybe}
+% If |-shell-escape| is not set, the |\iexec| command will lead to compilation failure. This
+% failure may be avoided with the help of the |maybe| option, which means that the execution
+% of |\iexec| must be quietly skipped if |-shell-escape| is not set:
+%\iffalse
+%<*verb>
+%\fi
+\begin{verbatim}
+\iexec[maybe]{echo 'Hello, world!'}
+\end{verbatim}
+%\iffalse
+%</verb>
+%\fi
+
% \StopEventually{}
% \section{Implementation}
-% First, we include \href{https://ctan.org/pkg/shellesc}{shellesc} package, which
-% we use to execute shell commands:
+% First, we include the \href{https://ctan.org/pkg/shellesc}{shellesc} package, which
+% we use in order to execute shell commands:
% \begin{macrocode}
\RequirePackage{shellesc}
% \end{macrocode}
-% Then, we parse package options:
+% Then, we parse package options, with the help
+% of \href{https://ctan.org/pkg/pgfopts}{pgfopts}:
+% \changes{0.14.0}{2024/01/14}{The \texttt{xkeyval} package is not used anymore. Instead, we use \texttt{pfgopts} in order to parse package options.}
% \begin{macrocode}
-\RequirePackage{xkeyval}
-\makeatletter
-\newif\ifiexec@trace
-\DeclareOptionX{trace}{\iexec@tracetrue}
-\ProcessOptionsX\relax
-\makeatother
+\RequirePackage{pgfopts}
+\pgfkeys{
+ /iexec/.cd,
+ trace/.store in=\iexec@trace,
+}
+\ProcessPgfPackageOptions{/iexec}
% \end{macrocode}
-% Then, we prepare to parse the options of |\iexec| command:
-% \changes{0.10.0}{2022/10/19}{The option ``\texttt{ignore}'' suppresses the checking of ``\texttt{iexec.ret}'' value.}
-% \changes{0.7.0}{2022/09/25}{The option "append" was introduced --- if it's turned on, stdout will be appended to the file, instead of rewriting it (this is how it was before).}
-% \changes{0.7.0}{2022/09/25}{The option ``\texttt{log}'' was introduced, to turn on log/debug messages in TeX log (they were all visible always, which was sometimes annoying. Also, this option enables printing of the entire content of stdout to the log too (this may be pretty convenient for debugging).}
-% \changes{0.11.0}{2022/10/22}{The option ``\texttt{exit}'' allows to change the name of the file with exit code.}
-% \changes{0.12.0}{2023/10/12}{The option ``\texttt{unskip}'' adds \texttt{\char`\\unskip} after each \texttt{\char`\\iexec}, in order to trip the tailing end of line space.}
+% Then, we prepare to parse the options of the |\iexec| command, with the help
+% of \href{https://ctan.org/pkg/pgfkeys}{pgfkeys}:
% \begin{macrocode}
\RequirePackage{pgfkeys}
\makeatletter\pgfkeys{
@@ -308,6 +320,7 @@ Today is \iexec{date +\%Y}!
unskip/.store in = \iexec@unskip,
quiet/.store in = \iexec@quiet,
ignore/.store in = \iexec@ignore,
+ maybe/.store in = \iexec@maybe,
stdout,exit
}\makeatother
% \end{macrocode}
@@ -336,6 +349,11 @@ Today is \iexec{date +\%Y}!
% Then, we define |\iexec| command.
% It is implemented with the help of |\ShellEscape| from |shellesc| package:
% \changes{0.10.0}{2022/10/19}{The file "iexec.ret" is reused for all scripts.}
+% \changes{0.10.0}{2022/10/19}{The option ``\texttt{ignore}'' suppresses the checking of ``\texttt{iexec.ret}'' value.}
+% \changes{0.7.0}{2022/09/25}{The option "append" was introduced --- if it's turned on, stdout will be appended to the file, instead of rewriting it (this is how it was before).}
+% \changes{0.7.0}{2022/09/25}{The option ``\texttt{log}'' was introduced, to turn on log/debug messages in TeX log (they were all visible always, which was sometimes annoying. Also, this option enables printing of the entire content of stdout to the log too (this may be pretty convenient for debugging).}
+% \changes{0.11.0}{2022/10/22}{The option ``\texttt{exit}'' allows to change the name of the file with exit code.}
+% \changes{0.12.0}{2023/10/12}{The option ``\texttt{unskip}'' adds \texttt{\char`\\unskip} after each \texttt{\char`\\iexec}, in order to trip the tailing end of line space.}
% \begin{macrocode}
\makeatletter
\newread\iexec@exitfile
@@ -346,26 +364,23 @@ Today is \iexec{date +\%Y}!
% First, we verify that |latex| is running with |--shell-escape| option, since without
% it nothing will work; so, it's better to throw an error earlier than later:
% \begin{macrocode}
- \ifnum\ShellEscapeStatus=1\else%
- \PackageError{iexec}{You must run TeX processor with
- --shell-escape option}{}%
- \fi%
- \begingroup%
+ \ifnum\ShellEscapeStatus=1%
+ \begingroup%
% \end{macrocode}
% Then, we start the log from a clean line:
% \begin{macrocode}
- \ifdefined\iexec@log%
- \message{^^J}%
- \fi%
+ \ifdefined\iexec@log%
+ \message{^^J}%
+ \fi%
% \end{macrocode}
% Then, we define a few special chars in order to escape them in the shell
% (the full
% list of them is in \href{https://ctan.mirror.norbert-ruehl.de/info/macros2e/macros2e.pdf}{macros2e}):
% \begin{macrocode}
- \let\%\@percentchar%
- \let\\\@backslashchar%
- \let\{\@charlb%
- \let\}\@charrb%
+ \let\%\@percentchar%
+ \let\\\@backslashchar%
+ \let\{\@charlb%
+ \let\}\@charrb%
% \end{macrocode}
% Then, we execute it and save exit code into a file (where we also add \texttt{\%} in order to trim the content to exactly one number, as suggested \href{https://tex.stackexchange.com/questions/662756}{here}):
% \changes{0.10.0}{2022/10/19}{The ability to track exit code was added. Now, the code is saved into ``\texttt{iexec.ret}'' file, which is then read and checked for zero value.}
@@ -376,118 +391,132 @@ Today is \iexec{date +\%Y}!
% \changes{0.11.3}{2022/10/29}{Bug fixed, because of which we had an extra leading space.}
% \changes{0.11.4}{2022/11/01}{In this version we escape dollar sign with \texttt{\char`\\string} command.}
% \begin{macrocode}
- \def\iexec@cmd{(#2)
- \ifdefined\iexec@append>\fi>
- \ifdefined\iexec@null/dev/null\else\iexec@stdout\fi
- \space\ifdefined\iexec@stderr2>\iexec@stderr\else2>&1\fi;
- /bin/echo -n \string$?\% >\iexec@exit}%
- \ShellEscape{\iexec@cmd}%
+ \def\iexec@cmd{(#2)
+ \ifdefined\iexec@append>\fi>
+ \ifdefined\iexec@null/dev/null\else\iexec@stdout\fi
+ \space\ifdefined\iexec@stderr2>\iexec@stderr\else2>&1\fi;
+ /bin/echo -n \string$?\% >\iexec@exit}%
+ \ShellEscape{\iexec@cmd}%
% \end{macrocode}
% Then, a message is printed to \TeX{} log:
% \begin{macrocode}
- \ifdefined\iexec@log%
- \message{iexec: [\iexec@cmd]^^J}%
- \fi%
- \endgroup%
+ \ifdefined\iexec@log%
+ \message{iexec: [\iexec@cmd]^^J}%
+ \fi%
+ \endgroup%
% \end{macrocode}
% Then, we read back the exit code, from the file:
% \begin{macrocode}
- \immediate\openin\iexec@exitfile=\iexec@exit%
- \read\iexec@exitfile to \iexec@code%
- \immediate\closein\iexec@exitfile%
+ \immediate\openin\iexec@exitfile=\iexec@exit%
+ \read\iexec@exitfile to \iexec@code%
+ \immediate\closein\iexec@exitfile%
% \end{macrocode}
% Then, if required, we print the content of the stdout file to \TeX{} log:
% \changes{0.11.2}{2022/10/25}{If execution fails, we print the content of ``\texttt{stdout}'' anyway, even if the ``\texttt{log}'' is not turned on.}
% \begin{macrocode}
- \ifdefined\iexec@null\else%
- \IfFileExists
- {\iexec@stdout}
- {}
- {\PackageError{iexec}{The "\iexec@stdout" file is absent
- after processing, looks like some internal error}{}}%
- \ifdefined\iexec@log%
- \message{iexec: This is the content of '\iexec@stdout':^^J}%
+ \ifdefined\iexec@null\else%
\IfFileExists
{\iexec@stdout}
- {\iexec@typeout{\iexec@stdout}}
+ {}
{\PackageError{iexec}{The "\iexec@stdout" file is absent
after processing, looks like some internal error}{}}%
- \message{<EOF>^^J}%
- \else%
- \ifnum\iexec@code=0\else%
- \ifdefined\iexec@ignore\else%
- \message{iexec: See the content of '\iexec@stdout'
- after failure:^^J}%
- \iexec@typeout{\iexec@stdout}%
- \message{<EOF>^^J}%
+ \ifdefined\iexec@log%
+ \message{iexec: This is the content of '\iexec@stdout':^^J}%
+ \IfFileExists
+ {\iexec@stdout}
+ {\iexec@typeout{\iexec@stdout}}
+ {\PackageError{iexec}{The "\iexec@stdout" file is absent
+ after processing, looks like some internal error}{}}%
+ \message{<EOF>^^J}%
+ \else%
+ \ifnum\iexec@code=0\else%
+ \ifdefined\iexec@ignore\else%
+ \message{iexec: See the content of '\iexec@stdout'
+ after failure:^^J}%
+ \iexec@typeout{\iexec@stdout}%
+ \message{<EOF>^^J}%
+ \fi%
\fi%
\fi%
\fi%
- \fi%
% \end{macrocode}
% Then, we check whether it's zero or not (if not zero, we either print a message or fail the build, depending on the presence of |ignore| option):
% \begin{macrocode}
- \ifnum\iexec@code=0\else%
- \ifdefined\iexec@ignore%
- \ifdefined\iexec@log%
- \message{iexec: Execution failure ignored,
- the exit code was \iexec@code^^J}%
+ \ifnum\iexec@code=0\else%
+ \ifdefined\iexec@ignore%
+ \ifdefined\iexec@log%
+ \message{iexec: Execution failure ignored,
+ the exit code was \iexec@code^^J}%
+ \fi%
+ \else%
+ \PackageError{iexec}{Execution failure,
+ the exit code was \iexec@code}{}%
\fi%
- \else%
- \PackageError{iexec}{Execution failure,
- the exit code was \iexec@code}{}%
\fi%
- \fi%
% \end{macrocode}
% Then, we include the produced output into the current document:
% \begin{macrocode}
- \ifdefined\iexec@null\else%
- \ifdefined\iexec@quiet%
- \ifdefined\iexec@log%
- \message{iexec: Due to 'quiet' option we didn't read
- the content of '\iexec@stdout'
- \ifdefined\pdffilesize (\pdffilesize{\iexec@stdout}
- bytes)\fi^^J}%
- \fi%
- \else%
- \ifdefined\iexec@log%
- \message{iexec: We are going to include the content of
- '\iexec@stdout'\ifdefined\pdffilesize (\pdffilesize
- {\iexec@stdout} bytes)\fi...^^J}%
- \fi%
- \input{\iexec@stdout}%
- \ifdefined\iexec@unskip\unskip\fi%
- \message{iexec: The content of '\iexec@stdout'
- was included into the document^^J}%
- \fi\fi%
-% \end{macrocode}
-% Finally, we delete the file or leave it untouched:
-% \begin{macrocode}
- \ifdefined\iexec@null\else%
- \ifiexec@trace%
- \ifdefined\iexec@log%
- \message{iexec: Due to package option 'trace',
- the files '\iexec@stdout' and `\iexec@exit` were
- not deleted^^J}%
- \fi%
- \else%
- \ifdefined\iexec@traceit%
+ \ifdefined\iexec@null\else%
+ \ifdefined\iexec@quiet%
\ifdefined\iexec@log%
- \message{iexec: Due to 'trace' package option,
- the files '\iexec@stdout' and '\iexec@exit'
- were not deleted^^J}%
+ \message{iexec: Due to 'quiet' option we didn't read
+ the content of '\iexec@stdout'
+ \ifdefined\pdffilesize (\pdffilesize{\iexec@stdout}
+ bytes)\fi^^J}%
\fi%
\else%
- \ShellEscape{rm \iexec@stdout}%
\ifdefined\iexec@log%
- \message{iexec: The file '\iexec@stdout' was deleted^^J}%
+ \message{iexec: We are going to include the content of
+ '\iexec@stdout'\ifdefined\pdffilesize (\pdffilesize
+ {\iexec@stdout} bytes)\fi...^^J}%
\fi%
- \ShellEscape{rm \iexec@exit}%
+ \input{\iexec@stdout}%
+ \ifdefined\iexec@unskip\unskip\fi%
+ \message{iexec: The content of '\iexec@stdout'
+ was included into the document^^J}%
+ \fi\fi%
+% \end{macrocode}
+% Then, we delete the file or leave it untouched:
+% \begin{macrocode}
+ \ifdefined\iexec@null\else%
+ \ifdefined\iexec@trace%
\ifdefined\iexec@log%
- \message{iexec: The file '\iexec@exit' was deleted^^J}%
+ \message{iexec: Due to package option 'trace',
+ the files '\iexec@stdout' and `\iexec@exit` were
+ not deleted^^J}%
\fi%
+ \else%
+ \ifdefined\iexec@traceit%
+ \ifdefined\iexec@log%
+ \message{iexec: Due to 'trace' package option,
+ the files '\iexec@stdout' and '\iexec@exit'
+ were not deleted^^J}%
+ \fi%
+ \else%
+ \ShellEscape{rm \iexec@stdout}%
+ \ifdefined\iexec@log%
+ \message{iexec: The file '\iexec@stdout' was deleted^^J}%
+ \fi%
+ \ShellEscape{rm \iexec@exit}%
+ \ifdefined\iexec@log%
+ \message{iexec: The file '\iexec@exit' was deleted^^J}%
+ \fi%
+ \fi%
+ \fi\fi%
+% \end{macrocode}
+% \changes{0.14.0}{2024/01/14}{The \texttt{maybe} option introduced, allowing the user to skip the entire execution of the \texttt{\char`\\iexec} command, when \texttt{-shell-escape} option is off.}
+% Finally, we ignore the whole story if the |maybe| option is provided
+% and the |-shell-escape| is not set:
+% \begin{macrocode}
+ \else%
+ \ifdefined\iexec@maybe%
+ \message{iexec: The execution skipped because -shell-escape
+ is not set and 'maybe' option is provided^^J}%
+ \else%
+ \PackageError{iexec}{You must run TeX processor with
+ --shell-escape option}{}%
\fi%
- \fi\fi%
+ \fi%
\endgroup%
}\makeatother
% \end{macrocode}