diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /web/clojure-pamphlet |
Initial commit
Diffstat (limited to 'web/clojure-pamphlet')
-rw-r--r-- | web/clojure-pamphlet/README | 38 | ||||
-rw-r--r-- | web/clojure-pamphlet/clojure-pamphlet.dtx | 339 | ||||
-rw-r--r-- | web/clojure-pamphlet/clojure-pamphlet.ins | 54 | ||||
-rw-r--r-- | web/clojure-pamphlet/clojure-pamphlet_guide.pdf | bin | 0 -> 189258 bytes | |||
-rwxr-xr-x | web/clojure-pamphlet/pamphletangler | 191 |
5 files changed, 622 insertions, 0 deletions
diff --git a/web/clojure-pamphlet/README b/web/clojure-pamphlet/README new file mode 100644 index 0000000000..00b7603d76 --- /dev/null +++ b/web/clojure-pamphlet/README @@ -0,0 +1,38 @@ +CLOJURE PAMPHLET SYSTEM +=========== + +The clojure pamphlet system is a system based on the clojure literate +system. In the clojure's pamphlet system you have your main LaTeX +file, which can be compiled regularly. This file contains +documentation and source code (just like in other forms of literate +programming). This code snippets are wrapped in the 'chunk' +environment, hence they can be recognized by the tangler in order to +extract them. Chunks can be included inside each other by the +'getchunk' command (which will be typesetted acordingly). Finally, you +run your LaTeX file through the tangler and get your desired chunk of +code. + +See the INSTALL file for detailed information about how to configure +and install the tangler. + This tangler is a program that takes a pamphlet latex file (A simple +latex file with special commands in it, see the latex clojure-pamphlet +package manual page) and a code section and outputs the specified code +section adding the chunks that are needed (and can be in any other +part of the document). + +----- + +Copyright (C) 2019, Ernesto Lanchares Sanchez. + +This program is free software; you can redistribute it and/or modify +it under the terms 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 <http://www.gnu.org/licenses/>. diff --git a/web/clojure-pamphlet/clojure-pamphlet.dtx b/web/clojure-pamphlet/clojure-pamphlet.dtx new file mode 100644 index 0000000000..e0cb5b2f02 --- /dev/null +++ b/web/clojure-pamphlet/clojure-pamphlet.dtx @@ -0,0 +1,339 @@ +% \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 <http://www.gnu.org/licenses/>. +% +% \fi +% +% \iffalse +%<package>\NeedsTeXFormat{LaTeX2e}[2005/12/01] +%<package>\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} +%</driver> +% \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} +% +% \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} +% int main(int argc, char* argv[]) { +% printf("Hello World.\n"); +% } +% \end{chunk} +% \end{verbatim} +% +% \iffalse +%<*test> +% \fi +\begin{chunk}{main} + int main(int argc, char* argv[]) { + printf("Hello World.\n"); + } +\end{chunk} +% \iffalse +%</test> +% \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 +%</test> +% \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{\PrintIndex} +% +% \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 diff --git a/web/clojure-pamphlet/clojure-pamphlet.ins b/web/clojure-pamphlet/clojure-pamphlet.ins new file mode 100644 index 0000000000..97cb979484 --- /dev/null +++ b/web/clojure-pamphlet/clojure-pamphlet.ins @@ -0,0 +1,54 @@ +%% +%% 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 <http://www.gnu.org/licenses/>. + +\input docstrip.tex +\keepsilent +\usedir{/tex/latex/pam} + +\preamble +This is a generated file. + +Copyright (C) 2019 by Lanchares Sanchez, Ernesto + +This file may be distributed and/or modified under the +conditions of the LaTeX Project Public License, either +version 1.3 of this license or (at your option) any later +version. The latest version of this license is in: + + http://www.latex-project.org/lppl.txt + +and version 1.3 or later is part of all distributions of +LaTeX version 2005/12/01 or later. +\endpreamble + +\generate{\file{clojure-pamphlet.sty}{\from{clojure-pamphlet.dtx}{package}}} + +\obeyspaces +\Msg{****************************************************} +\Msg{* *} +\Msg{* To finish the installation you have to move the *} +\Msg{* following file into a directory searched by TeX: *} +\Msg{* *} +\Msg{* clojure-pamphlet.sty *} +\Msg{* *} +\Msg{* To produce the documentation run the file *} +\Msg{* clojure-pamphelt.dtx through LaTeX. *} +\Msg{* *} +\Msg{* Happy TeXing! *} +\Msg{* *} +\Msg{****************************************************} + +\endbatchfile diff --git a/web/clojure-pamphlet/clojure-pamphlet_guide.pdf b/web/clojure-pamphlet/clojure-pamphlet_guide.pdf Binary files differnew file mode 100644 index 0000000000..6ffa96f3aa --- /dev/null +++ b/web/clojure-pamphlet/clojure-pamphlet_guide.pdf diff --git a/web/clojure-pamphlet/pamphletangler b/web/clojure-pamphlet/pamphletangler new file mode 100755 index 0000000000..32571347ac --- /dev/null +++ b/web/clojure-pamphlet/pamphletangler @@ -0,0 +1,191 @@ +#!/usr/bin/perl -w + +=head1 NAME + +pamphletangler - Extract code bits from LaTeX pamphlet files. + +=cut + +=head1 SYNOPSIS + +B<pamphletangler> [OPTION...] I<FILE> I<CHUNKNAME> + +=cut + +=head1 DESCRIPTION + +The clojure pamphlet system is a system based on the clojure literate +system. In the clojure's pamphlet system you have your main LaTeX file, which +can be compiled regularly. This file contains documentation and source code +(just like in other forms of literate programming). This code snippets are +wrapped in the 'chunk' environment, hence they can be recognized by the tangler +in order to extract them. Chunks can be included inside each other by the +'getchunk' command (which will be typesetted acordingly). Finally, you run your +LaTeX file through the tangler and get your desired chunk of code. + +=cut + +=head1 OPTIONS + +=over 29 + +=item -L, --line=linetext + +If set, this text will be inserted after jumps of lines, changing the string +inside "changetext" for the line number. This is used so that error report +refers to pamphlet line number instead of output line number + +=item -C, --change=changetext + +Defaults to "{}" this is the text that will be replaced with the line number if +the linetext option is specified + +=item -?, --help + +Give this help list + +=item --usage + +Give a short usage message + +=item --man + +Print manual page + +=item -V, --version + +Print program version + +=back + +=head1 LICENSE + +Copyright (C) 2019 Ernesto Lanchares Sanchez. + + The clojure-pamphlet tagler is free software; you can redistribute + it and/or modify it under the terms of the GNU Lesser General + Public License as published by the Free Software Foundation; + either version 3 of the License, or (at your option) any later + version. + + The clojure-pamphlet tangler 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, see + L<http://www.gnu.org/licenses/>. + + +=head1 AUTHOR + +Ernesto Lanchares <e.lancha98@gmail.com> + +=head1 BUGS + +Report bugs to e.lancha98@gmail.com + +=cut + +use strict; +use warnings; +use Getopt::Long; +use Pod::Usage qw(pod2usage); +use vars qw/$VERSION/; + +BEGIN { $VERSION = '1.2' } + +my $linetext = ""; +my $changetext = "{}"; +my $filename; +my $chunkname; + +OPTS: { + GetOptions( + 'usage' => sub { pod2usage( -verbose => 99, -sections => [ qw(SYNOPSIS) ]); }, + 'help|?' => sub { pod2usage( -verbose => 99, -sections => [ qw(SYNOPSIS DESCRIPTION OPTIONS BUGS) ]); }, + 'man' => sub { pod2usage( -verbose => 2) }, + 'version|V' => sub { print "$VERSION\n"; exit; }, + 'line|L=s' => \$linetext, + 'change|C=s' => \$changetext + ); + + +=pod + while ( my ($option, $value, $pretty) = Getopt::Mixed::nextOption() ) { + $linetext = $value if $option eq 'L'; + if( $option eq 'V' ) { + print "$VERSION\n"; + exit; + } + if ($option eq '?') { + pod2usage( -verbose => 99, -sections => [ qw(SYNOPSIS OPTIONS BUGS) ]); + exit; + } + if ($option eq 'man') { + pod2usage( -verbose => 2 ); + exit; + } + $linetext = $value if $option eq 'L'; + $changetext = $value if $option eq 'C'; + } +=cut + + pod2usage( -message => "[ERROR]: Invalid number of arguments." ) + if scalar(@ARGV) != 2; + $filename = shift; + $chunkname = shift; +} + +open(my $file, "<", $filename) or die "Can't open $filename: $!"; + +my $file_contents = do { local $/; <$file> }; +my %codeblocks; + +while ($file_contents =~ /\\begin\{chunk\}\{([\w.]+)\}[\s\h\t]*\n?(.*?)\n?[\s\t\h]*\\end\{chunk\}/sg) { + $codeblocks{$1} = { source => $2, printing => undef }; +} + +open($file, "<", $filename) or die "Can't open $filename: $!"; +my $index = 1; +while (my $line = <$file>) { + while ($line =~ /\\begin\{chunk\}\{([\w.]+)\}/g) { + $codeblocks{$1}{line} = $index+1; + } + $index++; +} + +sub printchunk { + my ($chunk, $indent) = @_; + + die "Chunk $chunk not found." if (!exists($codeblocks{$chunk})); + + die "Cyclic reference found: $chunk" if $codeblocks{$chunk}{printing}; + $codeblocks{$chunk}{printing} = 1; + + my $localines = 1; + print $linetext =~ s/$changetext/$codeblocks{$chunk}{line}/gr, "\n"; + foreach my $line (split(/\n/, $codeblocks{$chunk}{source})) { + if ($line =~ /([\s\t\h]*)\\getchunk\{([\w.]+)\}/) { + eval { + printchunk($2, $1); #$1 contains indent and $2 contains chunkname + print $linetext =~ s/$changetext/@{[$codeblocks{$chunk}{line} + $localines]}/gr, "\n"; + 1; + } or do { + if (rindex($@, "Cyclic reference found:", 0) == 0) { + $@ =~ /(.+?)( at .*)/s; + die "$1 <- $chunk"; + } + die $@; + } + } else { + print $indent, $line, "\n"; + } + $localines++; + } + + $codeblocks{$chunk}{printing} = undef; + return 0; +} +printchunk($chunkname, ""); |