summaryrefslogtreecommitdiff
path: root/web/clojure-pamphlet
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /web/clojure-pamphlet
Initial commit
Diffstat (limited to 'web/clojure-pamphlet')
-rw-r--r--web/clojure-pamphlet/README38
-rw-r--r--web/clojure-pamphlet/clojure-pamphlet.dtx339
-rw-r--r--web/clojure-pamphlet/clojure-pamphlet.ins54
-rw-r--r--web/clojure-pamphlet/clojure-pamphlet_guide.pdfbin0 -> 189258 bytes
-rwxr-xr-xweb/clojure-pamphlet/pamphletangler191
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
new file mode 100644
index 0000000000..6ffa96f3aa
--- /dev/null
+++ b/web/clojure-pamphlet/clojure-pamphlet_guide.pdf
Binary files differ
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, "");