This file contains some utilities for the rest of the literate program.
It has functions for reading the entire source of a file, and functions for reporting errors and warnings.
The readall
function reads an entire text file, or
reads from stdin until control-d
is pressed, and returns the string.
// Read from a file string readall(File file) { string src = ""; while (!file.eof) { src ~= file.readln(); } file.close(); return src; } // Read from stdin string readall() { string src = ""; string line; while ((line = readln()) !is null) { src ~= line; } return src; }
Used in section 1
These functions simply write errors or warnings to stdout.
This function returns the leading whitespace of the input string.
tempCodeblocks
is an array that contains only codeblocks that
have +=
or :=
. rootCodeblocks
and codeblocks
are both associative arrays
which will hold more important information. codeblocks
will contain every
codeblock after the +=
and :=
transformations have been applied.
Here we go through every single block in the program, and add it to the
tempCodeblocks
array if it has a +=
or :=
. Otherwise, we add it to
the codeblocks
array, and if it matches the filename regex .*\.\w+
, we add
it to the rootCodeblocks
array.
void getCodeblocks(Program p, out Block[string] codeblocks, out Block[string] rootCodeblocks) { Block[] tempCodeblocks; foreach (c; p.chapters) { foreach (s; c.sections) { foreach (b; s.blocks) { bool isRootBlock = false; if (b.isCodeblock) { Block copy = b.dup(); auto fileMatch = matchAll(copy.name, regex(".*\\.\\w+")); auto quoteMatch = matchAll(copy.name, regex("^\".*\"$")); if (fileMatch || quoteMatch) { copy.isRootBlock = true; if (quoteMatch) { copy.name = copy.name[1..$-1]; } } if ((!copy.modifiers.canFind(Modifier.additive)) && (!copy.modifiers.canFind(Modifier.redef))) { codeblocks[copy.name] = copy; if (copy.isRootBlock) { rootCodeblocks[copy.name] = copy; } } else { tempCodeblocks ~= copy; } } } } } // Now we go through every codeblock in tempCodeblocks and apply the += and := foreach (b; tempCodeblocks) { if (b.modifiers.canFind(Modifier.additive)) { auto index = b.name.length; string name = strip(b.name[0..index]); if ((name in codeblocks) is null) { error(p.file, b.startLine, "Trying to add to {" ~ name ~ "} which does not exist"); } else { codeblocks[name].lines ~= b.lines; } } else if (b.modifiers.canFind(Modifier.redef)) { auto index = b.name.length; string name = strip(b.name[0..index]); if ((name in codeblocks) is null) { error(p.file, b.startLine, "Trying to redefine {" ~ name ~ "} which does not exist"); } else { codeblocks[name].lines = b.lines; } } } }
Used in section 1
This function returns the html file for a chapter given the major and minor
numbers for it. The minor and major nums are passed in as a string formatted as:
major.minor
.
string getChapterHtmlFile(Chapter[] chapters, string num) { string[] nums = num.split("."); int majorNum = to!int(nums[0]); int minorNum = 0; if (nums.length > 1) { minorNum = to!int(nums[1]); } foreach (Chapter c; chapters) { if (c.majorNum == majorNum && c.minorNum == minorNum) { return stripExtension(baseName(c.file)) ~ ".html"; } } return ""; }
Used in section 1