% \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