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