% \iffalse meta-comment
%
% Copyright (C) 2019 by Lanchares Sanchez, Ernesto
%
% This file may be distributed and/or modified under the
% conditions of the GNU General Public License as published by
% the Free Software Foundation; either version 3, or (at your option)
% any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program. If not, see .
%
% \fi
%
% \iffalse
%\NeedsTeXFormat{LaTeX2e}[2005/12/01]
%\ProvidesPackage{clojure-pamphlet}[2019/07/08 v1.o .dtx clojure pamphlet file]
%
%<*driver>
\documentclass{ltxdoc}
\usepackage{clojure-pamphlet}
\usepackage{hyperref}
\usepackage{csquotes}
\EnableCrossrefs
\CodelineIndex
\RecordChanges
\begin{document}
\DocInput{clojure-pamphlet.dtx}
\end{document}
%
% \fi
%
% \CheckSum{175}
%
% \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}{2019/07/14}{Initial version}
% \changes{v1.1}{2019/07/20}{Added support for indented code}
% \changes{v1.2}{2019/07/25}{Moved tangler over to Perl}
% \changes{v1.3}{2019/09/08}{Fixed small bug in tangler}
%
% \GetFileInfo{clojure-pamphlet.sty}
%
% \DoNotIndex{\bgroup,\egoup,\ ,\advance,\begin,\bf,\big,\closeout,\csname}
% \DoNotIndex{\def,\do,\edef,\else,\end,\endcsname,\endinput,\expandafter}
% \DoNotIndex{\fi,\global,\hbox,\hskip,\hyperlink,\hypertarget,\if,\ifcsname}
% \DoNotIndex{\ifdefined,\iffalse,\iftrue,\immediate,\it,\jobname,\label,\let}
% \DoNotIndex{\lstnewenvironment,\lstset,\nameref,\newcommand,\newenvironment}
% \DoNotIndex{\newline,\newwrite,\next,\noindent,\openout,\relax,\string,\the}
% \DoNotIndex{\unexpanded,\write,\xdef,\\,\{,\},\@for,\@input,\@empty}
% \DoNotIndex{\@currentlabelname}
%
% \title{The \textsf{clojure-pamphlet} package\thanks{This document
% corresponds to \textsf{clojure-pamphlet}~\fileversion,
% dated~\filedate.}}
% \author{Ernesto Lanchares Sanchez\\ \texttt{e.lancha98@gmail.com}}
%
% \maketitle
%
% \begin{abstract}
% A package to make beautiful literate programming documents. The system is
% based on clojure's pamphelt files.
% \end{abstract}
%
% \section{Introduction}
%
% \href{http://www.literateprogramming.com/}{Literate Programming} is a
% programming paradigm that changes the goal of the program:
% \begin{displayquote}
% Let us change our traditional attitude to the construction of programs:
% Instead of imagining that our main task is to instruct a computer what to do,
% let us concentrate rather on explaining to human beings what we want a
% computer to do.
% \end{displayquote}
%
% Since it's creation, many systems have been created to accomplish this goal,
% systems like \texttt{WEB}, \texttt{CWEB}, \texttt{noweb}, \ldots This systems
% all share the same structure: There is one source file and two programs
% needed, one that extracts the code to be compiled and other that extracts the
% literature (usually a \TeX/\LaTeX file) to be compiled.
%
% This is the reason that we preffer clojure's system where there is one \LaTeX
% source file that can be compiled and one program to extract the code to be
% compiled. Although the clojure system is fine as it is, we think the resulting
% documentation can be a bit prettier hence this package. The difference in
% using this package or the clojure system as a developer is non-existent,
% however we think the documentation with our system is a bit more readable. It
% also automaticly adds hyperlinks to the output in order to make it easier to
% navigate when viewing in a computer.
%
% \section{Usage}
%
% The \texttt{clojure-pamphlet} system is designed to be as simple as possible,
% so this package only provides one environment and one command. The system is
% based arround code chunks. This chunks are the part of the documents that
% contain code and can be extracted. The chunks also contain a name so that they
% can be referenced in the document and in other chunk blocks. The name is also
% needed for the tangler to extract the chunk.
%
% \subsection{\texttt{chunk} environment}
% \DescribeEnv{chunk}
% The chunk environment is used to define code blocks. This code blocks have a
% name and are what the tangler will actually output. It is based on the
% \href{https://www.ctan.org/pkg/listings}{listings} package, so all style
% formats that yo can apply to \texttt{lstlisting} environments, you can also
% apply to chunk environments by simply using the command \texttt{lstset}.
%
% Here's an example of a code usage and it's output
% \begin{verbatim}
% \begin{chunk}{main-routine}
% int main(int argc, char* argv[]) {
% printf("Hello World.\n");
% }
% \end{chunk}
% \end{verbatim}
%
% \iffalse
%<*test>
% \fi
\begin{chunk}{main-routine}
int main(int argc, char* argv[]) {
printf("Hello World.\n");
}
\end{chunk}
% \iffalse
%
% \fi
%
% \DescribeMacro{\getchunk}
% Also, inside the \texttt{chunk} environment, you can use the \verb|\getchunk|
% command, which includes the referenced chunk at that exact same spot. The \verb|\getchunk|
% command requires to be in it's own separate line. Let's
% illustrate this with an example:
%
% \begin{verbatim}
% \begin{chunk}{onechunk}
% CHUNK ONE
% \end{chunk}
% \begin{chunk}{otherchunk}
% PREVIOUS
% \getchunk{onechunk}
% POST
% \end{chunk}
% \end{verbatim}
%
% \iffalse
%<*test>
% \fi
\begin{chunk}{print}
printf("Hello World");
\end{chunk}
\begin{chunk}{main}
int main(int argc, char* argv[]) {
\getchunk{print}
}
\end{chunk}
% \iffalse
%
% \fi
%
% \subsection{The tangler}
% The tangler is designed to be as simple to use as possible. You just need
% to provide it with a \LaTeX \texttt{clojure-pamphlet} file and a code chunk to
% extract. Then the tangler will output the code to be compiled in the standard
% output. For example in order to extract the main chunk of code we will need to
% run
% \begin{verbatim}
% pamphletangler [filename.tex] main
% \end{verbatim}
%
% And the output will be
% \begin{verbatim}
% int main(int argc, char* argv[]) {
% printf("Hello World");
% }
% \end{verbatim}
%
% \StopEventually{}
%
% \section{Implementation}
%
% We need to import the listings package to create the code blocks
% and the hyperref package to create the clickable links
% \begin{macrocode}
\RequirePackage{listings}
\RequirePackage{hyperref}
% \end{macrocode}
%
% We need to import the referecences, a.k.a. the ``used by'' text
% below the code
% \begin{macrocode}
\@input{\jobname.pam}
% \end{macrocode}
%
% We initialize a counter, needed to define a unique csname in each
% \verb|getchunk| call.
% \begin{macrocode}
\newcount\pam@references
% \end{macrocode}
%
% We define commands to write and compare the \{ and \} characters
% Solution from \url{https://tex.stackexchange.com/a/47453}
% \begin{macrocode}
\edef\wbgroup{\iftrue\string{\else}\fi}
\edef\wegroup{\iffalse{\else\string}\fi}
% \end{macrocode}
% \begin{macro}{\pam@storetext}
% This macro is used inside getchunkenv. This will consume tokens
% and store them inside \verb|pam@tex| macro until it reads a ``\}'' macro
% (defined by lst), then it calls the \verb|\getchunk| command on the stored
% text. Finally, calls the ``\}'' macro needed by lst to finish processing the
% code block.
% \begin{macrocode}
\def\pam@storetext#1{%
\expandafter\if\string#1\wegroup%
\getchunk{\pam@text}%
#1%
\else%
\edef\pam@text{\pam@text#1}%
\expandafter\pam@storetext% This expandafter is so the input of
% \pam@storetext is not \fi
\fi%
}
% \end{macrocode}
% \end{macro}
% \begin{environment}{pam@getchunkenv}
% This environment is not ment to be used outside this document and it's only
% purpose it's to wrap the \verb|pam@storetext| macro inside an environment.
% \begin{macrocode}
\newenvironment{pam@getchunkenv}{\def\pam@text{}%
\expandafter\pam@storetext}{}
% \end{macrocode}
% \end{environment}
%
% \begin{environment}{chunk}
% Here is the main environment.
% \begin{macrocode}
\lstnewenvironment{chunk}[1]{%
\hypertarget{#1}%
{\ }\newline\noindent%
\hbox{\hskip 2.0cm}{\bf --- #1 ---}%
\edef\@currentlabelname{#1}%
\lstset{alsodigit={.-},alsoletter={\\}}%
\lstset{escapebegin=\begin{pam@getchunkenv}}%
\lstset{escapeend=\end{pam@getchunkenv}}%
\lstset{escapeinside={\\getchunk\{}{\}}}%
}{
{\ }\newline\noindent%
\hbox{\hskip 2.0cm}%
{\it ---\csname referenced#1\endcsname---}%
}
% \end{macrocode}
% \end{environment}
% \begin{macro}{\getchunk}
% We run into the most complicated command. First, we preparate the label so it
% can be referenced and place the text.
% \begin{macrocode}
\newcommand{\getchunk}[1]{%
{\big<}\hyperlink{#1}{#1}{\big>}%
\edef\pam@label{reference-\the\pam@references}%
\label{\pam@label}%
\ifcsname used#1\endcsname\else%
\expandafter\def\csname used#1\endcsname{Used by}%
\fi%
% \end{macrocode}
% Here we expand the Used by command two times, this is so we fully expand
% the \verb|\csname| and the command but we don't expand the refs
% \begin{macrocode}
\edef\pam@tmp{\unexpanded\expandafter\expandafter%
\expandafter{\csname used#1\endcsname}}%
% \end{macrocode}
% We add to the used by command, adding a space and the new reference. Also, we
% increase the global counter and mark the chunk as referenced.
% \begin{macrocode}
\expandafter\xdef\csname used#1\expandafter\endcsname\expandafter{%
\expandafter\unexpanded\expandafter{\pam@tmp},%
\ \unexpanded\expandafter{\expandafter\nameref\expandafter{\pam@label}}%
}%
\global\advance\pam@references 1\relax%
\ifdefined\pam@chunks%
\xdef\pam@chunks{\pam@chunks,#1}%
\else%
\xdef\pam@chunks{#1}%
\fi%
}
% \end{macrocode}
% \end{macro}
% Here we will write the used by commands and references. This will only be
% done if there are chunks referenced.
% \begin{macrocode}
\AtEndDocument{%
\ifdefined\pam@chunks%
\newwrite\@pamfile%
\immediate\openout\@pamfile=\jobname.pam%
% \end{macrocode}
% Then, we loop through the list and write out the used by commands
% but the list may contain duplicates so we need to account for it.
% loop based on \url{https://tex.stackexchange.com/a/16695}
% \begin{macrocode}
\@for\next:=\pam@chunks\do{%
\ifcsname lstel@\next\endcsname%
\else%
\expandafter\let\csname lstel@\next\endcsname\@empty%
\immediate\write\@pamfile{%
\unexpanded{\expandafter\def\csname }%
referenced\next\unexpanded{\endcsname}%
\wbgroup%
\unexpanded\expandafter\expandafter\expandafter%
{\csname used\next\endcsname}%
\wegroup%
}%
\fi%
}%
% \end{macrocode}
% Finally, we close the auxiliary file
% \begin{macrocode}
\immediate\closeout\@pamfile%
\fi%
}
\endinput
% \end{macrocode}
% \Finale
\endinput