% \iffalse meta-comment
% (The MIT License)
%
% Copyright (c) 2021-2022 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
% in the Software without restriction, including without limitation the rights
% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
% copies of the Software, and to permit persons to whom the Software is
% furnished to do so, subject to the following conditions:
%
% The above copyright notice and this permission notice shall be included in all
% copies or substantial portions of the Software.
%
% THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
% SOFTWARE.
% \fi

% \CheckSum{0}
%
% \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         \~}

% \GetFileInfo{docshots.dtx}
% \DoNotIndex{\endgroup,\begingroup,\let,\else,\s,\n,\r,\\,\1,\fi}

% \iffalse
%<*driver>
\ProvidesFile{docshots.dtx}
%</driver>
%<package>\NeedsTeXFormat{LaTeX2e}
%<package>\ProvidesPackage{docshots}
%<*package>
[2022-10-18 0.0.4 TeX Samples Next to Their PDF Snapshots in DTX]
%</package>
%<*driver>
\documentclass{ltxdoc}
\usepackage[tt=false, type1=true]{libertine}
\usepackage{microtype}
\usepackage[dtx]{docshots}
\usepackage{href-ul}
\usepackage{xcolor}
\PageIndex
\EnableCrossrefs
\CodelineIndex
\RecordChanges
\begin{document}
	\DocInput{docshots.dtx}
	\PrintChanges
	\PrintIndex
\end{document}
%</driver>
% \fi

% \title{|docshots|: \LaTeX{} Package that Renders \\ \TeX{} Samples Next to Their \\ PDF Snapshots\thanks{The sources are in GitHub at \href{https://github.com/yegor256/docshots}{yegor256/docshots}}}
% \author{Yegor Bugayenko \\ \texttt{yegor256@gmail.com}}
% \date{\filedate, \fileversion}
%
% \maketitle
%
% \textbf{\color{red}NB!}
% This package doesn't work on Windows!
% Also, you must run \TeX{} processor with |--shell-escape| option.
% Also, you must have
% |pdlaftex|,
% \href{https://www.perl.org}{Perl},
% \href{https://www.ghostscript.com}{Ghostscript},
% and \href{https://ctan.org/pkg/pdfcrop}{pdfcrop}
% installed.

% \section{Introduction}
%
% When you want to demonstrate to the readers of your documentation
% how to use certain \TeX{} commands, the best way would be
% to show exactly how the entire document will be rendered in PDF,
% using a subprocess that would render it (via |pdflatex|, for example).
% To \href{https://tex.stackexchange.com/questions/661027}{my best}
% knowledge, there were no packages that would allow
% you do exactly this. That's why I created this simple package.
% For example, this code:
%
%\iffalse
%<*verb>
%\fi
\begin{verbatim}
\begin{docshot}
\documentclass{article}
\usepackage{xcolor}
\pagestyle{empty}
\begin{document}
  Hello, {\color{orange}\LaTeX}!
\end{document}
\end{docshot}
\end{verbatim}
%\iffalse
%</verb>
%\fi
% is rendered as such:
% \begin{docshot}
% \documentclass{article}
% \usepackage{xcolor}
% \pagestyle{empty}
% \begin{document}
%   Hello, {\color{orange}\LaTeX}!
% \end{document}
% \end{docshot}

% Here is a more complex example:
% \begin{docshot}
% \documentclass{article}
% \usepackage{tikz}
% \pagestyle{empty}
% \begin{document}
% \begin{tikzpicture}
% \node [circle,draw] (v0) {$v_0$};
% \node [circle,draw=orange,thick,
%   below right of=v0] (v1) {$v_1$};
% \draw [->] (v0) -- (v1);
% \end{tikzpicture}
% \end{document}
% \end{docshot}

% The picture you see on the left side is rendered by a subprocess
% executing |pdflatex| with the |.tex| content taken from the source file.
% After a successful processing of \TeX{} sources, we use
% \href{https://ctan.org/pkg/pdfcrop}{pdfcrop} to trim the document.

% We execute |pdflatex| with |-interaction=batchmode| and |-halt-on-error| options.
% This means that
% \TeX{} processing will stop at the first error. Check your \TeX{} log
% to understand what went wrong.

% When you render a text instead of a single picture, it's recommended to use
% \href{https://ctan.org/pkg/geometry}{geometry} package to change the size
% of the page and then |empty| page style to remove page numbering:
% \begin{docshot}
% \documentclass{article}
% \usepackage[paperwidth=2in]{geometry}
% \pagestyle{empty}
% \begin{document}
% ``There is no sadder thing than
% a young pessimist, except an old
% pessimist'' --- \emph{Mark Twain}
% \end{document}
% \end{docshot}

% \section{Package Options}

% \DescribeMacro{pdflatex}
% The default command line tool for turning |.tex| into
% |.pdf| is |pdflatex|. However, you can change that by using |pdflatex| package option,
% for example:
%\iffalse
%<*verb>
%\fi
\begin{verbatim}
\documentclass{article}
\usepackage[pdflatex=/usr/local/bin/pdflatex]{docshot}
\begin{document}
\begin{docshot}
Hello, world!
\end{docshot}
\end{document}
\end{verbatim}
%\iffalse
%</verb>
%\fi

% \DescribeMacro{gs}
% The default location of Ghostscript is just |gs|.
% You can change that by using |gs| package option,
% for example:
%\iffalse
%<*verb>
%\fi
\begin{verbatim}
\usepackage[gs=/usr/bin/ghostscript]{docshot}
\end{verbatim}
%\iffalse
%</verb>
%\fi

% \DescribeMacro{pdfcrop}
% The default location of |pdfcrop| is just |pdfcrop|.
% You can change that by using |pdfcrop| package option,
% for example:
%\iffalse
%<*verb>
%\fi
\begin{verbatim}
\usepackage[pdfcrop=/bin/pdfcrop]{docshot}
\end{verbatim}
%\iffalse
%</verb>
%\fi

% \DescribeMacro{margin}
% When we crop the PDF rendered, we leave a margin around the content. The
% default value may be changed by the package option |margin|:
%\iffalse
%<*verb>
%\fi
\begin{verbatim}
\usepackage[margin=10]{docshot}
\end{verbatim}
%\iffalse
%</verb>
%\fi

% \DescribeMacro{hspace}
% The horizontal distance between the image and its verbatim \TeX{} source
% may be configured via |hspace| package option:
%\iffalse
%<*verb>
%\fi
\begin{verbatim}
\usepackage[hspace=1em]{docshot}
\end{verbatim}
%\iffalse
%</verb>
%\fi

% \DescribeMacro{left}
% \DescribeMacro{right}
% The default width of the image may be changed by |left| option, while
% the width of the verbatim \TeX{} source may be modified by |right| option:
%\iffalse
%<*verb>
%\fi
\begin{verbatim}
\usepackage[left=2in,right=.5\linewidth]{docshot}
\end{verbatim}
%\iffalse
%</verb>
%\fi

% \DescribeMacro{dtx}
% If you use this package inside |.dtx| documentation, add |dtx| package option. Thanks
% to this option all comment symbols will be removed from line starts:
%\iffalse
%<*verb>
%\fi
\begin{verbatim}
\usepackage[dtx]{docshot}
\end{verbatim}
%\iffalse
%</verb>
%\fi

% \DescribeMacro{tmpdir}
% The default location of temp files is |\docshots@tmpdir|. You can change this using |tmpdir| option:
%\iffalse
%<*verb>
%\fi
\begin{verbatim}
\usepackage[tmpdir=/tmp/foo]{docshot}
\end{verbatim}
%\iffalse
%</verb>
%\fi

% \DescribeMacro{runs}
% By default, we run |pdflatex| just once for each docshot. You can change this number using the package
% option |runs|. This may be helpful if you need Bib\TeX{} processing, for example:
%\iffalse
%<*verb>
%\fi
\begin{verbatim}
\usepackage[runs=3]{docshot}
\end{verbatim}
%\iffalse
%</verb>
%\fi

% \DescribeMacro{small}
% \DescribeMacro{tiny}
% You don't have too much freedom in formatting of verbatim texts, but you can make
% their font a bit smaller using |small| package option. You can also make it very
% small using |tiny| option:
%\iffalse
%<*verb>
%\fi
\begin{verbatim}
\usepackage[small]{docshot}
\end{verbatim}
%\iffalse
%</verb>
%\fi

% \DescribeMacro{log}
% With |log| option you can make us print all possible logs to the main \TeX{} log.
% By default, we don't do this and you won't see the output of |pdflatex| compilation, for example.
% Just use it like this:
%\iffalse
%<*verb>
%\fi
\begin{verbatim}
\usepackage[log]{docshot}
\end{verbatim}
%\iffalse
%</verb>
%\fi

% \DescribeMacro{inputminted}
% By default, we render the verbatim text using |\VerbatimInput| command. You
% can change that and make us use |\inputminted|
% from \href{https://ctan.org/pkg/minted}{minted} package instead, for example:
%\iffalse
%<*verb>
%\fi
\begin{verbatim}
\usepackage{minted}
\setminted[java]{frame=lines,framesep=2mm}
\usepackage[inputminted=java]{docshot}
\end{verbatim}
%\iffalse
%</verb>
%\fi

% \DescribeMacro{lstinputlisting}
% By default, we render the verbatim text using |\VerbatimInput| command. You
% can change that and make us use |\lstinputlisting| from
% \href{https://ctan.org/pkg/listings}{listings} package instead, for example:
%\iffalse
%<*verb>
%\fi
\begin{verbatim}
\usepackage{listings}
\lstset{basicstyle=\small}
\usepackage[lstinputlisting]{docshot}
\end{verbatim}
%\iffalse
%</verb>
%\fi

% \section{Prerequisites}

% \DescribeMacro{\docshotPrerequisite}
% If you need some files to be present next to the |.tex| snippet while
% it's rendered by |pdflatex|, you can use |\docshotPrerequisite| with
% a single mandatory argument. The argument is the name of a file you need
% to be copied from current directory to the temporary directory, where
% all snippets are rendered. The command can be used either in the body
% of the document or in the preamble --- it doesn't matter, as long as
% it shows up before the docshot that needs the prerequisite. For example:
%\iffalse
%<*verb>
%\fi
\begin{verbatim}
\documentclass{article}
\usepackage{docshot}
\docshotPrerequisite{duck.jpg}
\begin{document}
\begin{docshot}
  \documentclass{article}
  \usepackage{graphicx}
  \pagestyle{empty}
  \begin{document}
    This is my favorite picture of a duck:
    \includegraphics[width=2in]{duck.jpg}
  \end{document}
\end{docshot}
\end{document}
\end{verbatim}
%\iffalse
%</verb>
%\fi

% \DescribeMacro{\docshotAfter}
% If you need something to happen after each |pdflatex| run of a docshot, you may use
% |\docshotAfter| command right before |docshot| environment. For example, you have a bibliography file that
% you want to be visible for all snippets and you want all of them to
% run \href{https://ctan.org/pkg/biber}{biber} in order to process citations:
%\iffalse
%<*verb>
%\fi
\begin{verbatim}
\documentclass{article}
\usepackage{docshot}
\docshotPrerequisite{main.bib}
\begin{document}
\docshotAfter{biber $2}
\begin{docshot}
  \documentclass{acmart}
  \usepackage[natbib=true]{biblatex}
  \addbibresource{main.bib}
  \pagestyle{empty}
  \begin{document}
    You must read the book of \citet{knuth1984}.
    \printbibliography
  \end{document}
\end{docshot}
\end{document}
\end{verbatim}
%\iffalse
%</verb>
%\fi
% The script you specify in the first argument of |\docshotAfter| will get
% three arguments when it runs:
% \begin{description}\setlength\itemsep{0em}
% \item[|\$1|] the cycle of |pdflatex| processing (1, 2, ...),
% \item[|\$2|] the hash of the snippet,
% \item[|\$3|] the name of the |.tex| file.
% \end{description}
% |$2| is basically equals to |$1| with an
% attached |.tex| suffix. |\docshotAfter| applies only to the first |docshot|
% environment that goes after it! You must specify |\docshotAfter| before
% each |docshot| where you want such post-processing to happen.

% \StopEventually{}

% \section{Implementation}

% \changes{v0.0.1}{2022/10/09}{Initial version}

% First, we include a few packages:
%    \begin{macrocode}
\RequirePackage{iexec}
\RequirePackage{fancyvrb}
\RequirePackage{xcolor}
\RequirePackage{graphicx}
\RequirePackage{tikz}
\usetikzlibrary{shadows.blur}
%    \end{macrocode}

% Then, we process package options:
%    \begin{macrocode}
\RequirePackage{pgfopts}
\pgfkeys{
  /docshots/.cd,
  dtx/.store in=\docshots@dtx,
  log/.store in=\docshots@log,
  log/.default=,
  lstinputlisting/.store in=\docshots@lstinputlisting,
  inputminted/.store in=\docshots@inputminted,
  tmpdir/.store in=\docshots@tmpdir,
  tmpdir/.default=_docshots,
  small/.store in=\docshots@small,
  tiny/.store in=\docshots@tiny,
  runs/.store in=\docshots@runs,
  runs/.default=1,
  pdflatex/.store in=\docshots@pdflatex,
  pdflatex/.default=pdflatex,
  gs/.store in=\docshots@gs,
  gs/.default=gs,
  pdfcrop/.store in=\docshots@pdfcrop,
  pdfcrop/.default=pdfcrop,
  margin/.store in=\docshots@margin,
  margin/.default=5,
  hspace/.store in=\docshots@hspace,
  hspace/.default=.05\linewidth,
  left/.store in=\docshots@left,
  left/.default=.3\linewidth,
  right/.store in=\docshots@right,
  right/.default=.55\linewidth,
  tmpdir,pdflatex,gs,pdfcrop,margin,hspace,left,right,runs,log
}
\ProcessPgfOptions{/docshots}
%    \end{macrocode}

% Then, we print the version of |pdflatex| to \TeX{} log:
%    \begin{macrocode}
\iexec[\docshots@log,quiet]{\docshots@pdflatex\space --version}%
%    \end{macrocode}

% Then, we print the version of \href{https://ctan.org/pkg/pdfcrop}{pdfcrop} to \TeX{} log:
%    \begin{macrocode}
\iexec[\docshots@log,quiet]{\docshots@pdfcrop\space --version}%
%    \end{macrocode}

% Then, we print the version of |ghostscript| to \TeX{} log:
%    \begin{macrocode}
\iexec[\docshots@log,quiet]{\docshots@gs\space --version}%
%    \end{macrocode}

% Then, we make a directory where all temporary files will be kept:
%    \begin{macrocode}
\iexec[null]{mkdir -p \docshots@tmpdir/\jobname}%
%    \end{macrocode}

% \begin{macro}{docshot}
% Then, we define |docshot| environment:
%    \begin{macrocode}
\newenvironment{docshot}
{\VerbatimEnvironment\begin{VerbatimOut}
  {\docshots@tmpdir/\jobname/verbatim.tex}}
{\end{VerbatimOut}%
%    \end{macrocode}
% If we are in |dtx| mode, leading percent characters must be removed:
%    \begin{macrocode}
  \ifdefined\docshots@dtx%
    \iexec[null]{perl -i -0777pe "s/(\\n|^)\\x{25} /\\1/g"
      \docshots@tmpdir/\jobname/verbatim.tex}%
  \fi%
%    \end{macrocode}
% We calculate MD5 hashsum of the file content:
%    \begin{macrocode}
  \def\hash{\pdfmdfivesum file
    {\docshots@tmpdir/\jobname/verbatim.tex}}%
%    \end{macrocode}
% If the PDF with the required name already exists, we ignore this step.
% Otherwise, we copy |verbatim.tex| into new file and run |pdflatex|:
%    \begin{macrocode}
  \IfFileExists{\docshots@tmpdir/\jobname/\hash.pdf}
    {\message{docshots: won't render, the PDF already exists
      (\docshots@tmpdir/\jobname/\hash.pdf)^^J}}
    {\iexec[\docshots@log,quiet]{cp \docshots@tmpdir/\jobname/verbatim.tex
      \docshots@tmpdir/\jobname/\hash.tex}%
    \foreach \n in {1,...,\docshots@runs}{
      \iexec[\docshots@log,quiet]{cd \docshots@tmpdir/\jobname;
        \docshots@pdflatex\space
        -interaction=errorstopmode
        -halt-on-error
        -shell-escape
        \hash.tex}
      \message{docshots: pdflatex run no.\n^^J}
      \IfFileExists{\docshots@tmpdir/\jobname/after.sh}
        {\iexec[\docshots@log,quiet]{chmod a+x
          \docshots@tmpdir/\jobname/after.sh}
        \iexec[\docshots@log,quiet]{cd \docshots@tmpdir/\jobname;
          ./after.sh \n\space \hash\space \hash.tex}}
        {}}}%
%    \end{macrocode}
% Here we delete |after.sh| which may exist here after the last
% compilation of |pdflatex|:
%    \begin{macrocode}
  \iexec[\docshots@log,quiet]{rm -f \docshots@tmpdir/\jobname/after.sh}
%    \end{macrocode}
% If a cropped version of the PDF with the required name already exists, we ignore this step.
% Otherwise, we ask |pdfcrop| to crop the PDF:
%    \begin{macrocode}
  \IfFileExists{\docshots@tmpdir/\jobname/\hash.crop.pdf}
    {\message{docshots: on't pdfcrop, the PDF already exists
      (\docshots@tmpdir/\jobname/\hash.crop.pdf)^^J}}
    {\iexec[\docshots@log,quiet]{\docshots@pdfcrop\space
      --margins \docshots@margin\space
      \docshots@tmpdir/\jobname/\hash.pdf
      \docshots@tmpdir/\jobname/\hash.crop.pdf}}%
%    \end{macrocode}
% We configure |fancyvrb|:
%    \begin{macrocode}
  \fvset{numbers=left,numbersep=3pt}%
  \fvset{frame=leftline,framerule=.4pt,rulecolor=\color{gray}}%
  \fvset{samepage=true}%
  \fvset{baselinestretch=1}%
  \ifdefined\docshots@small%
    \fvset{fontsize=\small}%
  \fi%
  \ifdefined\docshots@tiny%
    \fvset{fontsize=\scriptsize}%
  \fi%
%    \end{macrocode}
% We render the two column content:
%    \begin{macrocode}
  \begingroup%
  \par%
  \tikz[baseline=(a.north)]
    \node (a) [draw=gray]
    {\includegraphics[width=\docshots@left]
      {\docshots@tmpdir/\jobname/\hash.crop.pdf}};%
  \hspace{\docshots@hspace}%
  \begin{minipage}[t]{\docshots@right}%
    \vspace{0pt}%
    \ifdefined\docshots@lstinputlisting%
      \lstinputlisting{\docshots@tmpdir/\jobname/\hash.tex}%
    \else\ifdefined\docshots@inputminted%
      \inputminted{\docshots@inputminted}
        {\docshots@tmpdir/\jobname/\hash.tex}%
    \else%
      \VerbatimInput{\docshots@tmpdir/\jobname/\hash.tex}%
    \fi\fi%
    \vspace{0pt}%
  \end{minipage}%
  \par%
  \endgroup%
}
%    \end{macrocode}
% \end{macro}

% \begin{macro}{\docshotPrerequisite}
% Then, we define |\docshotPrerequisite| command:
%    \begin{macrocode}
\newcommand\docshotPrerequisite[1]{
  \iexec[\docshots@log,quiet]{cp #1 \docshots@tmpdir/\jobname}%
  \message{docshots: file #1 copied to
    \docshots@tmpdir/\jobname/#1^^J}%
}
%    \end{macrocode}
% \end{macro}

% \begin{macro}{\docshotAfter}
% Finally, we define |\docshotAfter| command:
%    \begin{macrocode}
\newcommand\docshotAfter[1]{
  \iexec[\docshots@log,quiet]{/bin/echo -n '\detokenize{#1}'
    > \docshots@tmpdir/\jobname/after.sh}%
  \message{docshots: file
    \docshots@tmpdir/\jobname/after.sh created^^J}%
}
%    \end{macrocode}
% \end{macro}

% \Finale

%\clearpage

%\PrintChanges
%\clearpage
%\PrintIndex
