aboutsummaryrefslogtreecommitdiffhomepage
path: root/org/ao_emitters_and_interfaces.org
diff options
context:
space:
mode:
authorRalph Amissah <ralph@amissah.com>2015-10-20 18:52:12 -0400
committerRalph Amissah <ralph@amissah.com>2015-10-20 22:13:25 -0400
commit4b0c115b58211dcc063bcd09f8fe122e558b92ce (patch)
treeb60e38935a4f5fbd723c13a5035d952976c851bf /org/ao_emitters_and_interfaces.org
parentupdate minor (diff)
literate programming introduced, tangle not yet run
Diffstat (limited to 'org/ao_emitters_and_interfaces.org')
-rw-r--r--org/ao_emitters_and_interfaces.org1599
1 files changed, 1599 insertions, 0 deletions
diff --git a/org/ao_emitters_and_interfaces.org b/org/ao_emitters_and_interfaces.org
new file mode 100644
index 0000000..d068b78
--- /dev/null
+++ b/org/ao_emitters_and_interfaces.org
@@ -0,0 +1,1599 @@
+#+TITLE: Emacs config file written in org-mode
+#+AUTHOR: Ralph Amissah
+#+EMAIL: ralph.amissah@gmail.com
+#+STARTUP: indent
+#+LANGUAGE: en
+#+OPTIONS: H:3 num:nil toc:t \n:nil @:t ::t |:t ^:nil -:t f:t *:t <:t
+#+OPTIONS: TeX:t LaTeX:t skip:nil d:nil todo:t pri:nil tags:not-in-toc
+#+OPTIONS: author:nil email:nil creator:nil timestamp:nil
+#+OPTIONS: ^:nil _:nil#+OPTIONS: ^:nil _:nil
+#+EXPORT_SELECT_TAGS: export
+#+EXPORT_EXCLUDE_TAGS: noexport
+#+TAGS: Amissah(A) Class(c) WEB(W) noexport(n)
+
+* emitters & interfaces
+ao_interface.d
+ao_emitter.d
+various emitters and their interfaces (where available)
+** e: command line interface/instructions
+*** emitter
+#+name: ao_emitter
+#+BEGIN_SRC d :exports none
+class CLI {
+ string[string] extract_actions(string cmdlnins, string[string] actions)
+ in { }
+ body {
+ switch (cmdlnins) {
+ case "--no-assert":
+ actions["assert"] = "no";
+ break;
+ default:
+ break;
+ }
+ return actions;
+ }
+}
+#+end_src
+** e&i: ocn
+*** emitter
+#+name: ao_emitter
+#+BEGIN_SRC d :exports none
+class OCNemitter : AssertOCN {
+ int ocn, ocn_;
+ int ocn_emitter(int ocn_status_flag)
+ in { assert(ocn_status_flag <= 2); }
+ body {
+ if (ocn_status_flag == 0) {
+ ocn=++ocn_;
+ } else {
+ ocn=0;
+ }
+ return ocn;
+ }
+ invariant() {
+ }
+}
+#+end_src
+*** interface assert
+#+name: ao_interface
+#+BEGIN_SRC d :exports none
+interface AssertOCN {
+ int ocn_emitter(int ocn_status_flag)
+ in { assert(ocn_status_flag <= 2); }
+ out(ocn) { assert(ocn >= 0); }
+}
+#+end_src
+** e: object attributes
+*** emitter
+#+name: ao_emitter
+#+BEGIN_SRC d :exports none
+class ObjAttributes {
+ string[string] obj_txt;
+ string para_and_blocks(string obj_txt_in)
+ in { }
+ body {
+ auto rgx = new Rgx();
+ obj_txt["munge"]=obj_txt_in;
+ if (match(obj_txt_in, rgx.para_bullet)) {
+ obj_txt["attrib"] =" \"bullet\": \"true\","
+ ~ " \"indent_first\": 0,"
+ ~ " \"indent_rest\": 0,";
+ } else if (auto m = match(obj_txt_in, rgx.para_bullet_indent)) {
+ obj_txt["attrib"] =" \"bullet\": \"true\","
+ ~ " \"indent_first\": " ~ to!string(m.captures[1]) ~ ","
+ ~ " \"indent_rest\": " ~ to!string(m.captures[1]) ~ ",";
+ } else if (auto m = match(obj_txt_in, rgx.para_indent_hang)) {
+ obj_txt["attrib"] =" \"bullet\": \"false\","
+ ~ " \"indent_first\": " ~ to!string(m.captures[1]) ~ ","
+ ~ " \"indent_rest\": " ~ to!string(m.captures[2]) ~ ",";
+ } else if (auto m = match(obj_txt_in, rgx.para_indent)) {
+ obj_txt["attrib"] =" \"bullet\": \"false\","
+ ~ " \"indent_first\": " ~ to!string(m.captures[1]) ~ ","
+ ~ " \"indent_rest\": " ~ to!string(m.captures[1]) ~ ",";
+ } else {
+ obj_txt["attrib"] =" \"bullet\": \"false\","
+ ~ " \"indent_first\": 0,"
+ ~ " \"indent_rest\": 0,";
+ }
+ return obj_txt["attrib"];
+ }
+ string para(string obj_txt_in)
+ in { }
+ body {
+ obj_txt["munge"]=obj_txt_in;
+ obj_txt["attrib"] = " \"use\": \"content\","
+ ~ " \"of\": \"para\","
+ ~ " \"is\": \"para\"";
+ return obj_txt["attrib"];
+ }
+ invariant() {
+ }
+ string heading(string obj_txt_in)
+ in { }
+ body {
+ obj_txt["munge"]=obj_txt_in;
+ obj_txt["attrib"] = " \"use\": \"content\","
+ ~ " \"of\": \"para\","
+ ~ " \"is\": \"heading\"";
+ return obj_txt["attrib"];
+ }
+ invariant() {
+ }
+ string header_make(string obj_txt_in)
+ in { }
+ body {
+ obj_txt["munge"]=obj_txt_in;
+ obj_txt["attrib"] = " \"use\": \"head\","
+ ~ " \"of\": \"header\","
+ ~ " \"is\": \"header_make\"";
+ return obj_txt["attrib"];
+ }
+ invariant() {
+ }
+ string header_metadata(string obj_txt_in)
+ in { }
+ body {
+ obj_txt["munge"]=obj_txt_in;
+ obj_txt["attrib"] = " \"use\": \"head\","
+ ~ " \"of\": \"header\","
+ ~ " \"is\": \"header_metadata\"";
+ return obj_txt["attrib"];
+ }
+ invariant() {
+ }
+ string code(string obj_txt_in)
+ in { }
+ body {
+ obj_txt["munge"]=obj_txt_in;
+ obj_txt["attrib"] = " \"use\": \"content\","
+ ~ " \"of\": \"block\","
+ ~ " \"is\": \"code\"";
+ return obj_txt["attrib"];
+ }
+ invariant() {
+ }
+ string group(string obj_txt_in)
+ in { }
+ body {
+ obj_txt["munge"]=obj_txt_in;
+ obj_txt["attrib"] = " \"use\": \"content\","
+ ~ " \"of\": \"block\","
+ ~ " \"is\": \"group\"";
+ return obj_txt["attrib"];
+ }
+ invariant() {
+ }
+ string block(string obj_txt_in)
+ in { }
+ body {
+ obj_txt["munge"]=obj_txt_in;
+ obj_txt["attrib"] = " \"use\": \"content\","
+ ~ " \"of\": \"block\","
+ ~ " \"is\": \"block\"";
+ return obj_txt["attrib"];
+ }
+ invariant() {
+ }
+ string verse(string obj_txt_in)
+ in { }
+ body {
+ obj_txt["munge"]=obj_txt_in;
+ obj_txt["attrib"] = " \"use\": \"content\","
+ ~ " \"of\": \"block\","
+ ~ " \"is\": \"verse\"";
+ return obj_txt["attrib"];
+ }
+ invariant() {
+ }
+ string quote(string obj_txt_in)
+ in { }
+ body {
+ obj_txt["munge"]=obj_txt_in;
+ obj_txt["attrib"] = " \"use\": \"content\","
+ ~ " \"of\": \"block\","
+ ~ " \"is\": \"quote\"";
+ return obj_txt["attrib"];
+ }
+ invariant() {
+ }
+ string table(string obj_txt_in)
+ in { }
+ body {
+ obj_txt["munge"]=obj_txt_in;
+ obj_txt["attrib"] = " \"use\": \"content\","
+ ~ " \"of\": \"block\","
+ ~ " \"is\": \"table\"";
+ return obj_txt["attrib"];
+ }
+ invariant() {
+ }
+ string comment(string obj_txt_in)
+ in { }
+ body {
+ obj_txt["munge"]=obj_txt_in;
+ obj_txt["attrib"] = " \"use\": \"comment\","
+ ~ " \"of\": \"comment\","
+ ~ " \"is\": \"comment\"";
+ return obj_txt["attrib"];
+ }
+ invariant() {
+ }
+}
+#+end_src
+** e: object inline markup munge
+*** emitter
+#+name: ao_emitter
+#+BEGIN_SRC d :exports none
+class ObjInlineMarkupMunge {
+ string[string] obj_txt;
+ int n_foot, n_foot_reg, n_foot_sp_asterisk, n_foot_sp_plus;
+ string obj_txt_out, tail, note;
+ private auto initialize_note_numbers() {
+ n_foot = 0;
+ n_foot_reg = 0;
+ n_foot_sp_asterisk = 0;
+ n_foot_sp_plus = 0;
+ }
+ private auto object_notes_(string obj_txt_in)
+ in { }
+ body {
+ auto rgx = new Rgx();
+ auto mkup = new InternalMarkup();
+ obj_txt_out = "";
+ tail = "";
+ obj_txt_in = replaceAll(
+ obj_txt_in,
+ rgx.inline_notes_curly_sp_asterisk,
+ (mkup.en_a_o ~ "*" ~ " $1" ~ mkup.en_a_c)
+ );
+ obj_txt_in =
+ replaceAll(
+ obj_txt_in,
+ rgx.inline_notes_curly_sp_plus,
+ (mkup.en_a_o ~ "+" ~ " $1" ~ mkup.en_a_c)
+ );
+ obj_txt_in =
+ replaceAll(
+ obj_txt_in,
+ rgx.inline_notes_curly,
+ (mkup.en_a_o ~ " $1" ~ mkup.en_a_c)
+ );
+ if (match(obj_txt_in, rgx.inline_notes_al_gen)) {
+ foreach(m; matchAll(obj_txt_in, rgx.inline_text_and_note_al)) {
+ if (match(obj_txt_in, rgx.inline_al_delimiter_open_asterisk)) {
+ n_foot_sp_asterisk++;
+ n_foot=n_foot_sp_asterisk;
+ } else if (match(obj_txt_in, rgx.inline_al_delimiter_open_plus)) {
+ n_foot_sp_plus++;
+ n_foot=n_foot_sp_plus;
+ } else {
+ n_foot_reg++;
+ n_foot=n_foot_reg;
+ }
+ obj_txt_out ~= replaceFirst(
+ m.hit,
+ rgx.inline_al_delimiter_open_regular,
+ (mkup.en_a_o ~ to!string(n_foot))
+ );
+ tail = m.post;
+ }
+ } else {
+ obj_txt_out = obj_txt_in;
+ }
+ debug(footnotes) {
+ writeln(obj_txt_out, tail);
+ }
+ obj_txt_out = obj_txt_out ~ tail;
+ debug(footnotesdone) {
+ foreach(m; matchAll(obj_txt_out,
+ (mkup.en_a_o ~ `\s*(.+?)` ~ mkup.en_a_c))) {
+ writeln(m.captures[1]);
+ writeln(m.hit);
+ }
+ }
+ return obj_txt_out;
+ }
+ string para(string obj_txt_in)
+ in { }
+ body {
+ auto rgx = new Rgx();
+ obj_txt["munge"]=obj_txt_in;
+ obj_txt["munge"]=replaceFirst(obj_txt["munge"], rgx.para_attribs, "");
+ obj_txt["munge"]=replaceFirst(obj_txt["munge"], rgx.ocn_off_all, "");
+ obj_txt["munge"]=object_notes_(obj_txt["munge"]);
+ debug(munge) {
+ writeln(__LINE__);
+ writeln(obj_txt_in);
+ writeln(__LINE__);
+ writeln(to!string(obj_txt["munge"]));
+ }
+ return obj_txt["munge"];
+ }
+ string heading(string obj_txt_in)
+ in { }
+ body {
+ auto rgx = new Rgx();
+ obj_txt["munge"]=obj_txt_in;
+ obj_txt["munge"]=replaceFirst(obj_txt["munge"], rgx.heading, "");
+ obj_txt["munge"]=replaceFirst(obj_txt["munge"], rgx.ocn_off_all, "");
+ obj_txt["munge"]=object_notes_(obj_txt["munge"]);
+ debug(munge) {
+ writeln(__LINE__);
+ writeln(obj_txt_in);
+ writeln(__LINE__);
+ writeln(to!string(obj_txt["munge"]));
+ }
+ return obj_txt["munge"];
+ }
+ invariant() {
+ }
+ string header_make(string obj_txt_in)
+ in { }
+ body {
+ obj_txt["munge"]=obj_txt_in;
+ return obj_txt["munge"];
+ }
+ invariant() {
+ }
+ string header_metadata(string obj_txt_in)
+ in { }
+ body {
+ obj_txt["munge"]=obj_txt_in;
+ return obj_txt["munge"];
+ }
+ invariant() {
+ }
+ string code(string obj_txt_in)
+ in { }
+ body {
+ obj_txt["munge"]=obj_txt_in;
+ return obj_txt["munge"];
+ }
+ invariant() {
+ }
+ string group(string obj_txt_in)
+ in { }
+ body {
+ obj_txt["munge"]=obj_txt_in;
+ obj_txt["munge"]=object_notes_(obj_txt["munge"]);
+ return obj_txt["munge"];
+ }
+ invariant() {
+ }
+ string block(string obj_txt_in)
+ in { }
+ body {
+ obj_txt["munge"]=obj_txt_in;
+ obj_txt["munge"]=object_notes_(obj_txt["munge"]);
+ return obj_txt["munge"];
+ }
+ invariant() {
+ }
+ string verse(string obj_txt_in)
+ in { }
+ body {
+ obj_txt["munge"]=obj_txt_in;
+ obj_txt["munge"]=object_notes_(obj_txt["munge"]);
+ return obj_txt["munge"];
+ }
+ invariant() {
+ }
+ string quote(string obj_txt_in)
+ in { }
+ body {
+ obj_txt["munge"]=obj_txt_in;
+ return obj_txt["munge"];
+ }
+ invariant() {
+ }
+ string table(string obj_txt_in)
+ in { }
+ body {
+ obj_txt["munge"]=obj_txt_in;
+ return obj_txt["munge"];
+ }
+ invariant() {
+ }
+ string comment(string obj_txt_in)
+ in { }
+ body {
+ obj_txt["munge"]=obj_txt_in;
+ return obj_txt["munge"];
+ }
+ invariant() {
+ }
+}
+#+end_src
+** e&i: object inline markup
+*** emitter
+#+name: ao_emitter
+#+BEGIN_SRC d :exports none
+class ObjInlineMarkup : AssertObjInlineMarkup {
+ auto munge = new ObjInlineMarkupMunge();
+ string[string] obj_txt;
+ string obj_inline_markup(string obj_is_, string obj_raw)
+ in { }
+ body {
+ obj_txt["munge"]=obj_raw.dup;
+ obj_txt["munge"]=(match(obj_is_, ctRegex!(`verse|code`)))
+ ? obj_txt["munge"]
+ : strip(obj_txt["munge"]);
+ switch (obj_is_) {
+ case "header_make":
+ obj_txt["munge"]=munge.header_make(obj_txt["munge"]);
+ break;
+ case "header_metadata":
+ obj_txt["munge"]=munge.header_metadata(obj_txt["munge"]);
+ break;
+ case "heading":
+ obj_txt["munge"]=munge.heading(obj_txt["munge"]);
+ break;
+ case "para":
+ obj_txt["munge"]=munge.para(obj_txt["munge"]);
+ break;
+ case "code":
+ obj_txt["munge"]=munge.code(obj_txt["munge"]);
+ break;
+ case "group":
+ obj_txt["munge"]=munge.group(obj_txt["munge"]);
+ break;
+ case "block":
+ obj_txt["munge"]=munge.block(obj_txt["munge"]);
+ break;
+ case "verse":
+ obj_txt["munge"]=munge.verse(obj_txt["munge"]);
+ break;
+ case "quote":
+ obj_txt["munge"]=munge.quote(obj_txt["munge"]);
+ break;
+ case "table":
+ obj_txt["munge"]=munge.table(obj_txt["munge"]);
+ break;
+ case "comment":
+ obj_txt["munge"]=munge.comment(obj_txt["munge"]);
+ break;
+ case "doc_end_reset":
+ munge.initialize_note_numbers();
+ break;
+ default:
+ break;
+ }
+ return obj_txt["munge"];
+ }
+ invariant() {
+ }
+}
+#+end_src
+*** interface assert
+#+name: ao_interface
+#+BEGIN_SRC d :exports none
+interface AssertObjInlineMarkup {
+ string obj_inline_markup(string obj_raw, string obj_type_)
+ in {
+ }
+ out(inline_markup) {
+ }
+}
+#+end_src
+** e&i: object attrib
+*** emitter
+#+name: ao_emitter
+#+BEGIN_SRC d :exports none
+class ObjAttrib : AssertObjAttrib {
+ auto attrib = new ObjAttributes();
+ string[string] obj_attrib;
+ string obj_attributes(string obj_is_, string obj_raw, string node)
+ in { }
+ body {
+ scope(exit) {
+ destroy(obj_raw);
+ destroy(node);
+ }
+ JSONValue node_j = parseJSON(node);
+ obj_attrib.remove("json");
+ obj_attrib["json"] ="{";
+ switch (obj_is_) {
+ case "header_make":
+ obj_attrib["json"] ~= attrib.header_make(obj_raw);
+ break;
+ case "header_metadata":
+ obj_attrib["json"] ~= attrib.header_metadata(obj_raw);
+ break;
+ case "heading":
+ obj_attrib["json"] ~= attrib.heading(obj_raw); //
+ break;
+ case "para":
+ obj_attrib["json"] ~= attrib.para_and_blocks(obj_raw)
+ ~ attrib.para(obj_raw);
+ break;
+ case "code":
+ obj_attrib["json"] ~= attrib.code(obj_raw);
+ break;
+ case "group":
+ obj_attrib["json"] ~= attrib.para_and_blocks(obj_raw)
+ ~ attrib.group(obj_raw);
+ break;
+ case "block":
+ obj_attrib["json"] ~= attrib.para_and_blocks(obj_raw)
+ ~ attrib.block(obj_raw);
+ break;
+ case "verse":
+ obj_attrib["json"] ~= attrib.verse(obj_raw);
+ break;
+ case "quote":
+ obj_attrib["json"] ~= attrib.quote(obj_raw);
+ break;
+ case "table":
+ obj_attrib["json"] ~= attrib.table(obj_raw);
+ break;
+ case "comment":
+ obj_attrib["json"] ~= attrib.comment(obj_raw);
+ break;
+ default:
+ obj_attrib["json"] ~= attrib.para(obj_raw);
+ break;
+ }
+ obj_attrib["json"] ~=" }";
+ JSONValue oa_j = parseJSON(obj_attrib["json"]);
+ assert(
+ (oa_j.type == JSON_TYPE.OBJECT) &&
+ (node_j.type == JSON_TYPE.OBJECT)
+ );
+ if (obj_is_ == "heading") {
+ oa_j.object["ocn"] = node_j["ocn"];
+ oa_j.object["lvn"] = node_j["lvn"];
+ oa_j.object["lcn"] = node_j["lcn"];
+ oa_j.object["heading_pointer"] =
+ node_j["heading_pointer"]; // check
+ oa_j.object["doc_object_pointer"] =
+ node_j["doc_object_pointer"]; // check
+ }
+ oa_j.object["parent_ocn"] = node_j["parent_ocn"];
+ oa_j.object["parent_lvn"] = node_j["parent_lvn"];
+ obj_attrib["json"] = oa_j.toString();
+ debug(structattrib) {
+ if (oa_j["is"].str() == "heading") {
+ writeln(obj_attrib["json"]);
+ writeln(
+ "is: ", oa_j["is"].str(),
+ "; ocn: ", oa_j["ocn"].integer()
+ );
+ }
+ }
+ return obj_attrib["json"];
+ }
+ invariant() {
+ }
+}
+#+end_src
+*** interface assert
+#+name: ao_interface
+#+BEGIN_SRC d :exports none
+interface AssertObjAttrib {
+ string obj_attributes(string obj_raw, string node, string obj_type_)
+ in {
+ }
+ out(obj_attrib_json) {
+ }
+}
+#+end_src
+** e: header document metadata in json
+*** emitter
+#+name: ao_emitter
+#+BEGIN_SRC d :exports none
+class HeaderDocMetadataMakeJson {
+ auto rgx = new Rgx();
+ string hm, hs;
+ auto header_metadata_and_make_jsonstr(
+ string header,
+ JSONValue[string] dochead_metadata,
+ JSONValue[string] dochead_make
+ )
+ in { }
+ body {
+ scope(exit) {
+ destroy(header);
+ destroy(dochead_metadata);
+ destroy(dochead_make);
+ }
+ if (auto t = match(header, rgx.head_main)) {
+ char[][] obj_spl = split(
+ cast(char[]) header,
+ rgx.line_delimiter_ws_strip
+ );
+ auto hm = to!string(t.captures[1]);
+ if (match(hm, rgx.main_headers)) {
+ foreach (line; obj_spl) {
+ if (auto m = match(line, rgx.head_main)) {
+ if (!empty(m.captures[2])) {
+ if (hm == "creator") {
+ dochead_metadata[hm]["author"].str =
+ to!string(m.captures[2]);
+ } else if (hm == "title") {
+ dochead_metadata[hm]["main"].str =
+ to!string(m.captures[2]);
+ } else if (hm == "publisher") {
+ dochead_metadata[hm]["name"].str =
+ to!string(m.captures[2]);
+ }
+ }
+ } else if (auto s = match(line, rgx.head_sub)) {
+ if (!empty(s.captures[2])) {
+ auto hs = to!string(s.captures[1]);
+ if ((hm == "make" )
+ && (dochead_make[hm].type() == JSON_TYPE.OBJECT)) {
+ switch (hm) {
+ case "make":
+ if (match(hs, rgx.subhead_make)) {
+ if (dochead_make[hm][hs].type() == JSON_TYPE.STRING) {
+ dochead_make[hm][hs].str = to!string(s.captures[2]);
+ }
+ } else {
+ writeln("not a valid header type:", hm, ":", hs);
+ destroy(hm);
+ destroy(hs);
+ }
+ break;
+ default:
+ break;
+ }
+ } else if (dochead_metadata[hm].type() == JSON_TYPE.OBJECT) {
+ switch (hm) {
+ case "creator":
+ if (match(hs, rgx.subhead_creator)) {
+ if (dochead_metadata[hm][hs].type() == JSON_TYPE.STRING) {
+ dochead_metadata[hm][hs].str =
+ to!string(s.captures[2]);
+ }
+ } else {
+ writeln("not a valid header type:", hm, ":", hs);
+ destroy(hm);
+ destroy(hs);
+ }
+ break;
+ case "title":
+ if (match(hs, rgx.subhead_title)) {
+ if ((hs == "subtitle")
+ && (dochead_metadata[hm]["sub"].type() == JSON_TYPE.STRING)) {
+ dochead_metadata[hm]["sub"].str =
+ to!string(s.captures[2]);
+ } else if (dochead_metadata[hm][hs].type() == JSON_TYPE.STRING) {
+ dochead_metadata[hm][hs].str =
+ to!string(s.captures[2]);
+ }
+ } else {
+ writeln("not a valid header type:", hm, ":", hs);
+ destroy(hm);
+ destroy(hs);
+ }
+ break;
+ case "rights":
+ if (match(hs, rgx.subhead_rights)) {
+ if (dochead_metadata[hm][hs].type() == JSON_TYPE.STRING) {
+ dochead_metadata[hm][hs].str =
+ to!string(s.captures[2]);
+ }
+ } else {
+ writeln("not a valid header type:", hm, ":", hs);
+ destroy(hm);
+ destroy(hs);
+ }
+ break;
+ case "date":
+ if (match(hs, rgx.subhead_date)) {
+ if (dochead_metadata[hm][hs].type() == JSON_TYPE.STRING) {
+ dochead_metadata[hm][hs].str =
+ to!string(s.captures[2]);
+ }
+ } else {
+ writeln("not a valid header type:", hm, ":", hs);
+ destroy(hm);
+ destroy(hs);
+ }
+ break;
+ case "original":
+ if (match(hs, rgx.subhead_original)) {
+ if (dochead_metadata[hm][hs].type() == JSON_TYPE.STRING) {
+ dochead_metadata[hm][hs].str =
+ to!string(s.captures[2]);
+ }
+ } else {
+ writeln("not a valid header type:", hm, ":", hs);
+ destroy(hm);
+ destroy(hs);
+ }
+ break;
+ case "classify":
+ if (match(hs, rgx.subhead_classify)) {
+ if (dochead_metadata[hm][hs].type() == JSON_TYPE.STRING) {
+ dochead_metadata[hm][hs].str =
+ to!string(s.captures[2]);
+ }
+ } else {
+ writeln("not a valid header type:", hm, ":", hs);
+ destroy(hm);
+ destroy(hs);
+ }
+ break;
+ case "identifier":
+ if (match(hs, rgx.subhead_identifier)) {
+ if (dochead_metadata[hm][hs].type() == JSON_TYPE.STRING) {
+ dochead_metadata[hm][hs].str =
+ to!string(s.captures[2]);
+ }
+ } else {
+ writeln("not a valid header type:", hm, ":", hs);
+ destroy(hm);
+ destroy(hs);
+ }
+ break;
+ case "notes":
+ if (match(hs, rgx.subhead_notes)) {
+ if (dochead_metadata[hm][hs].type() == JSON_TYPE.STRING) {
+ dochead_metadata[hm][hs].str =
+ to!string(s.captures[2]);
+ }
+ } else {
+ writeln("not a valid header type:", hm, ":", hs);
+ destroy(hm);
+ destroy(hs);
+ }
+ break;
+ case "publisher":
+ if (match(hs, rgx.subhead_publisher)) {
+ if (dochead_metadata[hm][hs].type() == JSON_TYPE.STRING) {
+ dochead_metadata[hm][hs].str =
+ to!string(s.captures[2]);
+ }
+ } else {
+ writeln("not a valid header type:", hm, ":", hs);
+ destroy(hm);
+ destroy(hs);
+ }
+ break;
+ case "links":
+ destroy(hm);
+ destroy(hs);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ }
+ } else {
+ writeln("not a valid header type:", hm);
+ }
+ }
+ auto t = tuple(dochead_metadata, dochead_make);
+ static assert(!isTypeTuple!(t));
+ return t;
+ }
+}
+#+end_src
+** e: header document metadata as hash
+*** emitter
+#+name: ao_emitter
+#+BEGIN_SRC d :exports none
+class HeaderMetadataMakeHash {
+ auto rgx = new Rgx();
+ string header_main;
+ string[string] head;
+ string[string] header_topic_hash(string header)
+ in { }
+ body {
+ if (auto t = match(header, rgx.head_main)) {
+ char[][] obj_spl = split(
+ cast(char[]) header,
+ rgx.line_delimiter_ws_strip
+ );
+ auto header_main = to!string(t.captures[1]);
+ head[header_main] = "{";
+ foreach (line; obj_spl) {
+ if (auto m = match(line, rgx.head_main)) {
+ if (!empty(m.captures[2])) {
+ head[header_main] ~=
+ "\"" ~ header_main ~
+ "\": \"" ~
+ to!string(m.captures[2]) ~
+ "\",";
+ }
+ } else if (auto s = match(line, rgx.head_sub)) {
+ head[header_main] ~= "\"" ~ s.captures[1] ~ "\":";
+ if (!empty(s.captures[2])) {
+ head[header_main] ~= "\"" ~ s.captures[2] ~ "\",";
+ }
+ }
+ }
+ head[header_main] = replaceFirst(
+ head[header_main],
+ rgx.tailing_comma,
+ ""
+ );
+ head[header_main] ~= "}";
+ debug(headerjson) {
+ JSONValue j = parseJSON(head[header_main]);
+ assert(
+ (j.type == JSON_TYPE.OBJECT)
+ );
+ }
+ }
+ return head;
+ }
+ invariant() {
+ }
+}
+#+end_src
+** e&i: book index nugget hash
+*** emitter
+#+name: ao_emitter
+#+BEGIN_SRC d :exports none
+class BookIndexNuggetHash : AssertBookIndexNuggetHash {
+ string main_term, sub_term, sub_term_bits;
+ uint ocn_offset, ocn_endpoint;
+ string[] ocns;
+ string[][string][string] bi;
+ string[][string][string] hash_nugget;
+ string[] bi_main_terms_split_arr;
+ string[][string][string] bookindex_nugget_hash(string bookindex, int ocn)
+ in { }
+ body {
+ auto rgx = new Rgx();
+ if (!bookindex.empty) {
+ auto bi_main_terms_split_arr =
+ split(bookindex, rgx.bi_main_terms_split);
+ foreach (bi_main_terms_content; bi_main_terms_split_arr) {
+ auto bi_main_term_and_rest =
+ split(bi_main_terms_content, rgx.bi_main_term_plus_rest_split);
+ if (auto m = match(
+ bi_main_term_and_rest[0],
+ rgx.bi_term_and_ocns_match)
+ ) {
+ main_term = strip(m.captures[1]);
+ ocn_offset = to!uint(m.captures[2]);
+ ocn_endpoint=(ocn + ocn_offset);
+ ocns ~= (to!string(ocn) ~ "-" ~ to!string(ocn_endpoint));
+ } else {
+ main_term = strip(bi_main_term_and_rest[0]);
+ ocns ~= to!string(ocn);
+ }
+ bi[main_term]["_a"] ~= ocns;
+ ocns=null;
+ if (bi_main_term_and_rest.length > 1) {
+ auto bi_sub_terms_split_arr =
+ split(
+ bi_main_term_and_rest[1],
+ rgx.bi_sub_terms_plus_ocn_offset_split
+ );
+ foreach (sub_terms_bits; bi_sub_terms_split_arr) {
+ if (auto m = match(sub_terms_bits, rgx.bi_term_and_ocns_match)) {
+ sub_term = strip(m.captures[1]);
+ ocn_offset = to!uint(m.captures[2]);
+ ocn_endpoint=(ocn + ocn_offset);
+ ocns ~= (to!string(ocn) ~ " - " ~ to!string(ocn_endpoint));
+ } else {
+ sub_term = strip(sub_terms_bits);
+ ocns ~= to!string(ocn);
+ }
+ if (!empty(sub_term)) {
+ bi[main_term][sub_term] ~= ocns;
+ }
+ ocns=null;
+ }
+ }
+ }
+ }
+ hash_nugget = bi;
+ return hash_nugget;
+ }
+ invariant() {
+ }
+}
+#+end_src
+*** interface assert
+#+name: ao_interface
+#+BEGIN_SRC d :exports none
+interface AssertBookIndexNuggetHash {
+ string[][string][string] bookindex_nugget_hash(string bookindex, int ocn)
+ in {
+ debug(bookindexraw) {
+ mixin ScreenTxtColors;
+ if (!bookindex.empty) {
+ writeln(
+ scr_txt_color["blue"], "* [bookindex] ", scr_txt_color["off"],
+ "[", to!string(ocn), "] ", bookindex
+ );
+ }
+ }
+ }
+ out(hash_nugget) {
+ }
+}
+#+end_src
+** e&i: book index report
+*** emitter
+#+name: ao_emitter
+#+BEGIN_SRC d :exports none
+class BookIndexReport {
+ int mkn, skn;
+ auto bookindex_report_sorted(
+ string[][string][string] bookindex_unordered_hashes
+ ) {
+ auto mainkeys=bookindex_unordered_hashes.byKey.array.
+ sort!("toLower(a) < toLower(b)", SwapStrategy.stable).release;
+ foreach (mainkey; mainkeys) {
+ auto subkeys=bookindex_unordered_hashes[mainkey].byKey.array.
+ sort!("toLower(a) < toLower(b)", SwapStrategy.stable).release;
+ foreach (subkey; subkeys) {
+ debug(bookindex) {
+ writeln(
+ mainkey, ": ",
+ subkey, ": ",
+ to!string(bookindex_unordered_hashes[mainkey][subkey])
+ );
+ }
+ skn++;
+ }
+ mkn++;
+ }
+ }
+}
+#+end_src
+*** interface assert
+#+name: ao_interface
+#+BEGIN_SRC d :exports none
+interface AssertBookIndexReport {
+ string[][string][][string][] bookindex_nugget_hash(string[][string][string] bookindex_unordered_hashes)
+ in {
+ }
+}
+#+end_src
+** e: book index report indented
+*** emitter
+#+name: ao_emitter
+#+BEGIN_SRC d :exports none
+class BookIndexReportIndent {
+ int mkn, skn;
+ auto bookindex_report_indented(
+ string[][string][string] bookindex_unordered_hashes
+ ) {
+ auto mainkeys=
+ bookindex_unordered_hashes.byKey.array.sort().release;
+ foreach (mainkey; mainkeys) {
+ debug(bookindex) {
+ writeln(mainkey);
+ }
+ auto subkeys=
+ bookindex_unordered_hashes[mainkey].byKey.array.sort().release;
+ foreach (subkey; subkeys) {
+ debug(bookindex) {
+ writeln(" ", subkey);
+ writeln(" ", to!string(
+ bookindex_unordered_hashes[mainkey][subkey]
+ ));
+ }
+ skn++;
+ }
+ mkn++;
+ }
+ }
+}
+#+end_src
+** e: book index report section
+*** emitter
+#+name: ao_emitter
+#+BEGIN_SRC d :exports none
+class BookIndexReportSection {
+ mixin ObjectSetters;
+ int mkn, skn;
+ auto rgx = new Rgx();
+ auto bookindex_write_section(
+ string[][string][string] bookindex_unordered_hashes
+ ) {
+ auto mainkeys=bookindex_unordered_hashes.byKey.array.sort().release;
+ foreach (mainkey; mainkeys) {
+ write("_0_1 !{", mainkey, "}! ");
+ foreach (ref_; bookindex_unordered_hashes[mainkey]["_a"]) {
+ auto go = replaceAll(ref_, rgx.book_index_go, "$1");
+ write(" {", ref_, "}#", go, ", ");
+ }
+ writeln(" \\\\");
+ bookindex_unordered_hashes[mainkey].remove("_a");
+ auto subkeys=
+ bookindex_unordered_hashes[mainkey].byKey.array.sort().release;
+ foreach (subkey; subkeys) {
+ write(" ", subkey, ", ");
+ foreach (ref_; bookindex_unordered_hashes[mainkey][subkey]) {
+ auto go = replaceAll(ref_, rgx.book_index_go, "$1");
+ write(" {", ref_, "}#", go, ", ");
+ }
+ writeln(" \\\\");
+ skn++;
+ }
+ mkn++;
+ }
+ }
+ auto bookindex_build_section(
+ string[][string][string] bookindex_unordered_hashes,
+ int ocn
+ ) {
+ string type;
+ int type_heading;
+ string lev, lvn, lcn;
+ string attrib;
+ string indent_first;
+ string indent_second;
+ auto set_oa = new ObjectAbstractSet();
+ auto mainkeys =
+ bookindex_unordered_hashes.byKey.array.sort().release;
+ string bi_tmp;
+ string[string][1024] bookindex_arbitrary_max_length_set;
+ writeln(mainkeys.length);
+ type_heading=1;
+ bi_tmp = "Book Index";
+ attrib="";
+ lev="B";
+ lvn="1";
+ lcn="1";
+ bookindex_arbitrary_max_length_set[mkn] =
+ set_oa.contents_heading(
+ type_heading,
+ bi_tmp,
+ attrib,
+ ocn,
+ lev,
+ lvn,
+ lcn
+ );
+ ocn++;
+ mkn++;
+ type_heading=1;
+ bi_tmp = "Index";
+ attrib="";
+ lev="1";
+ lvn="4";
+ lcn="2";
+ bookindex_arbitrary_max_length_set[mkn] =
+ set_oa.contents_heading(
+ type_heading,
+ bi_tmp,
+ attrib,
+ ocn,
+ lev,
+ lvn,
+ lcn
+ );
+ ocn++;
+ mkn++;
+ foreach (mainkey; mainkeys) {
+ bi_tmp = "!{" ~ mainkey ~ "}! ";
+ foreach (ref_; bookindex_unordered_hashes[mainkey]["_a"]) {
+ auto go = replaceAll(ref_, rgx.book_index_go, "$1");
+ bi_tmp ~= " {" ~ ref_ ~ "}#" ~ go ~ ", ";
+ }
+ bi_tmp ~= " \\\\\n ";
+ bookindex_unordered_hashes[mainkey].remove("_a");
+ auto subkeys =
+ bookindex_unordered_hashes[mainkey].byKey.array.sort().release;
+ foreach (subkey; subkeys) {
+ bi_tmp ~= subkey ~ ", ";
+ foreach (ref_; bookindex_unordered_hashes[mainkey][subkey]) {
+ auto go = replaceAll(ref_, rgx.book_index_go, "$1");
+ bi_tmp ~= " {" ~ ref_ ~ "}#" ~ go ~ ", ";
+ }
+ bi_tmp ~= " \\\\\n ";
+ skn++;
+ }
+ bi_tmp = replaceFirst(bi_tmp, rgx.trailing_linebreak, "");
+ type="para";
+ attrib="";
+ indent_first = "0";
+ indent_second = "1";
+ attrib="";
+ bookindex_arbitrary_max_length_set[mkn] =
+ set_oa.contents_para(
+ type,
+ bi_tmp,
+ attrib,
+ ocn,
+ indent_first,
+ indent_second,
+ false
+ );
+ ocn++;
+ mkn++;
+ }
+ auto bookindex =
+ bookindex_arbitrary_max_length_set[0..mkn].dup;
+ auto t = tuple(bookindex, ocn);
+ return t;
+ }
+ auto bookindex_build_section_(
+ string[][string][string] bookindex_unordered_hashes
+ ) {
+ auto mainkeys =
+ bookindex_unordered_hashes.byKey.array.sort().release;
+ string bi_tmp;
+ string[1024] bookindex_arbitrary_max_length_set;
+ writeln(mainkeys.length);
+ foreach (mainkey; mainkeys) {
+ bi_tmp = "_0_1 !{" ~ mainkey ~ "}! ";
+ foreach (ref_; bookindex_unordered_hashes[mainkey]["_a"]) {
+ auto go = replaceAll(ref_, rgx.book_index_go, "$1");
+ bi_tmp ~= " {" ~ ref_ ~ "}#" ~ go ~ ", ";
+ }
+ bi_tmp ~= " \\\\\n ";
+ bookindex_unordered_hashes[mainkey].remove("_a");
+ auto subkeys =
+ bookindex_unordered_hashes[mainkey].byKey.array.sort().release;
+ foreach (subkey; subkeys) {
+ bi_tmp ~= subkey ~ ", ";
+ foreach (ref_; bookindex_unordered_hashes[mainkey][subkey]) {
+ auto go = replaceAll(ref_, rgx.book_index_go, "$1");
+ bi_tmp ~= " {" ~ ref_ ~ "}#" ~ go ~ ", ";
+ }
+ bi_tmp ~= " \\\\\n ";
+ skn++;
+ }
+ bi_tmp = replaceFirst(bi_tmp, rgx.trailing_linebreak, "");
+ bookindex_arbitrary_max_length_set[mkn] = bi_tmp;
+ mkn++;
+ }
+ auto bookindex =
+ bookindex_arbitrary_max_length_set[0..mkn].dup;
+ return bookindex;
+ }
+}
+#+end_src
+** e: (end)notes section
+*** emitter
+#+name: ao_emitter
+#+BEGIN_SRC d :exports none
+class NotesSection {
+ mixin ObjectSetters;
+ string object_notes;
+ int previous_count;
+ int mkn;
+ auto rgx = new Rgx();
+ private auto gather_notes_for_endnote_section(
+ string[string][131072] contents_arbitrary_max_length_set,
+ int counter
+ )
+ in {
+ // endnotes/ footnotes for
+ // doc objects other than paragraphs & headings
+ // various forms of grouped text
+ assert((contents_arbitrary_max_length_set[counter]["is"] == "para")
+ || (contents_arbitrary_max_length_set[counter]["is"] == "heading"));
+ assert(counter > previous_count);
+ previous_count=counter;
+ assert(
+ match(contents_arbitrary_max_length_set[counter]["obj"],
+ rgx.inline_notes_delimiter_al_regular_number_note)
+ );
+ }
+ body {
+ foreach(m;
+ matchAll(contents_arbitrary_max_length_set[counter]["obj"],
+ rgx.inline_notes_delimiter_al_regular_number_note)) {
+ debug(endnotes_build) {
+ writeln(
+ "{^{", m.captures[1], ".}^}#noteref_", m.captures[1], " ",
+ m.captures[2]); // sometimes need segment name (segmented html & epub)
+ }
+ object_notes ~=
+ "{^{" ~ m.captures[1] ~ ".}^}#noteref_" ~
+ m.captures[1] ~ " " ~ m.captures[2] ~ "』";
+ }
+ return object_notes;
+ }
+ private auto gathered_notes()
+ in {
+ }
+ body {
+ string[] endnotes_;
+ if (object_notes.length > 1) {
+ endnotes_ = (split(object_notes, rgx.break_string))[0..$-1];
+ }
+ return endnotes_;
+ }
+ private auto endnote_objects(int ocn)
+ in {
+ }
+ body {
+ auto set_oa = new ObjectAbstractSet();
+ string[string][1024] endnotes_arbitrary_max_length_set;
+ auto endnotes_ = gathered_notes();
+ string type;
+ int type_heading;
+ string lev, lvn, lcn;
+ string attrib;
+ string indent_first;
+ string indent_second;
+ type_heading=1;
+ attrib="";
+ lev="B";
+ lvn="1";
+ lcn="1";
+ endnotes_arbitrary_max_length_set[mkn] =
+ set_oa.contents_heading(
+ type_heading,
+ "Endnotes",
+ attrib,
+ ocn,
+ lev,
+ lvn,
+ lcn
+ );
+ ocn++;
+ mkn++;
+ type_heading=1;
+ attrib="";
+ lev="1";
+ lvn="4";
+ lcn="2";
+ endnotes_arbitrary_max_length_set[mkn] =
+ set_oa.contents_heading(
+ type_heading,
+ "Endnotes",
+ attrib,
+ ocn,
+ lev,
+ lvn,
+ lcn
+ );
+ ocn++;
+ mkn++;
+ foreach (endnote; endnotes_) {
+ type="para";
+ attrib="";
+ indent_first = "0";
+ indent_second = "0";
+ attrib="";
+ endnotes_arbitrary_max_length_set[mkn] =
+ set_oa.contents_para(
+ type,
+ endnote,
+ attrib,
+ ocn,
+ indent_first,
+ indent_second,
+ false
+ );
+ ocn++;
+ mkn++;
+ }
+ auto endnotes =
+ endnotes_arbitrary_max_length_set[0..mkn].dup;
+ auto t = tuple(endnotes, ocn);
+ return t;
+ }
+}
+#+end_src
+** e: bibliography
+*** emitter
+#+name: ao_emitter
+#+BEGIN_SRC d :exports none
+class Bibliography {
+ public JSONValue[] bibliography(string[] biblio_unsorted_incomplete)
+ in { }
+ body {
+ JSONValue[] biblio_unsorted =
+ biblio_unsorted_complete(biblio_unsorted_incomplete);
+ JSONValue[] biblio_sorted = biblio_sort(biblio_unsorted);
+ biblio_debug(biblio_sorted);
+ return biblio_sorted;
+ }
+ final private JSONValue[] biblio_unsorted_complete(
+ string[] biblio_unordered
+ ) {
+ JSONValue[1024] bib_arr_json;
+ int count_biblio_entry;
+ count_biblio_entry=0;
+ foreach (bibent; biblio_unordered) {
+ // update bib to include deemed_author, needed for:
+ // sort_bibliography_array_by_deemed_author_year_title
+ // either: sort on multiple fields, or; create such sort field
+ JSONValue j = parseJSON(bibent);
+ if (!empty(j["fulltitle"].str)) {
+ if (!empty(j["author_raw"].str)) {
+ j["deemed_author"]=j["author_arr"][0];
+ } else if (!empty(j["editor_raw"].str)) {
+ j["deemed_author"]=j["editor_arr"][0];
+ }
+ j["sortby_deemed_author_year_title"] = (
+ j["deemed_author"].str ~
+ "; " ~
+ j["year"].str ~
+ "; " ~
+ j["fulltitle"].str
+ );
+ }
+ bib_arr_json[count_biblio_entry] = j;
+ count_biblio_entry++;
+ }
+ JSONValue[] biblio_unsorted_array_of_json_objects =
+ bib_arr_json[0..(count_biblio_entry)].dup;
+ return biblio_unsorted_array_of_json_objects;
+ }
+ final private JSONValue[] biblio_sort(JSONValue[] biblio_unordered) {
+ JSONValue[] biblio_sorted;
+ biblio_sorted =
+ sort!((a, b){
+ return ((a["sortby_deemed_author_year_title"].str) < (b["sortby_deemed_author_year_title"].str));
+ })(biblio_unordered).array;
+ debug(bibliosorted) {
+ foreach (j; biblio_sorted) {
+ if (!empty(j["fulltitle"].str)) {
+ writeln(j["sortby_deemed_author_year_title"]);
+ }
+ }
+ }
+ return biblio_sorted;
+ }
+ auto biblio_debug(JSONValue[] biblio_sorted) {
+ debug(biblio) {
+ foreach (j; biblio_sorted) {
+ if (!empty(j["fulltitle"].str)) {
+ writeln(j["sortby_deemed_author_year_title"]);
+ }
+ }
+ }
+ }
+}
+#+end_src
+** e&i: node structure metadata
+*** emitter
+#+name: ao_emitter
+#+BEGIN_SRC d :exports none
+class NodeStructureMetadata : AssertNodeJSON {
+ int lv, lv0, lv1, lv2, lv3, lv4, lv5, lv6, lv7;
+ uint ocn;
+ uint[string] p_; // p_ parent_
+ string node;
+ string node_emitter(
+ string lvn,
+ int ocn_,
+ int counter_,
+ int pointer_,
+ string is_
+ )
+ in {
+ auto rgx = new Rgx();
+ }
+ body {
+ assert(is_ != "heading"); // should not be necessary
+ assert(to!int(ocn_) >= 0); // should not be necessary
+ uint ocn=to!uint(ocn_);
+ if (lv7 > 0) {
+ p_["lvn"] = 7; p_["ocn"] = lv7;
+ } else if (lv6 > 0) {
+ p_["lvn"] = 6; p_["ocn"] = lv6;
+ } else if (lv5 > 0) {
+ p_["lvn"] = 5; p_["ocn"] = lv5;
+ } else {
+ p_["lvn"] = 4; p_["ocn"] = lv4;
+ }
+ node=("{ " ~
+ "\"is\": \"" ~ is_ ~ "\"" ~
+ ", \"heading_pointer\": " ~ to!string(pointer_) ~
+ ", \"doc_object_pointer\": " ~ to!string(counter_) ~
+ ", \"ocn\": " ~ to!string(ocn_) ~
+ ", \"parent_ocn\": " ~ to!string(p_["ocn"]) ~
+ ", \"parent_lvn\": " ~ to!string(p_["lvn"]) ~
+ " }"
+ );
+ return node;
+ }
+ invariant() {
+ }
+ string node_emitter_heading(
+ string lvn,
+ string lcn,
+ int ocn_,
+ int counter_,
+ int pointer_,
+ string is_
+ )
+ in {
+ auto rgx = new Rgx();
+ }
+ body {
+ uint ocn=to!uint(ocn_);
+ switch (lvn) { // switch (to!string(lv)) {
+ case "0":
+ lv=0;
+ lv0=ocn; lv1=0; lv2=0; lv3=0; lv4=0; lv5=0; lv6=0; lv7=0;
+ p_["lvn"] = 0; p_["ocn"] = 0;
+ break;
+ case "1":
+ lv=1;
+ lv1=ocn; lv2=0; lv3=0; lv4=0; lv5=0; lv6=0; lv7=0;
+ p_["lvn"] = 0; p_["ocn"] = lv0;
+ break;
+ case "2":
+ lv=2;
+ lv2=ocn; lv3=0; lv4=0; lv5=0; lv6=0; lv7=0;
+ p_["lvn"] = 1; p_["ocn"] = lv1;
+ break;
+ case "3":
+ lv=3;
+ lv3=ocn; lv4=0; lv5=0; lv6=0; lv7=0;
+ p_["lvn"] = 2; p_["ocn"] = lv2;
+ break;
+ case "4":
+ lv=4;
+ lv4=ocn; lv5=0; lv6=0; lv7=0;
+ if (lv3 > 0) {
+ p_["lvn"] = 3; p_["ocn"] = lv3;
+ } else if (lv2 > 0) {
+ p_["lvn"] = 2; p_["ocn"] = lv2;
+ } else if (lv1 > 0) {
+ p_["lvn"] = 1; p_["ocn"] = lv1;
+ } else {
+ p_["lvn"] = 0; p_["ocn"] = lv0;
+ }
+ break;
+ case "5":
+ lv=5;
+ lv5=ocn; lv6=0; lv7=0;
+ p_["lvn"] = 4; p_["ocn"] = lv4;
+ break;
+ case "6":
+ lv=6;
+ lv6=ocn; lv7=0;
+ p_["lvn"] = 5; p_["ocn"] = lv5;
+ break;
+ case "7":
+ lv=7;
+ lv7=ocn;
+ p_["lvn"] = 6; p_["ocn"] = lv6;
+ break;
+ default:
+ break;
+ }
+ node=("{ " ~
+ "\"is\": \"" ~ is_ ~ "\"" ~
+ ", \"heading_pointer\": " ~ to!string(pointer_) ~
+ ", \"doc_object_pointer\": " ~ to!string(counter_) ~
+ ", \"ocn\": " ~ to!string(ocn_) ~
+ ", \"lvn\": " ~ to!string(lvn) ~
+ ", \"lcn\": " ~ to!string(lcn) ~
+ ", \"parent_ocn\": " ~ to!string(p_["ocn"]) ~
+ ", \"parent_lvn\": " ~ to!string(p_["lvn"]) ~
+ " }"
+ );
+ return node;
+ }
+ invariant() {
+ }
+}
+#+end_src
+
+*** interface assert
+#+name: ao_interface
+#+BEGIN_SRC d :exports none
+interface AssertNodeJSON {
+ string node_emitter(
+ string lvn,
+ int ocn_,
+ int counter_,
+ int pointer_,
+ string is_
+ )
+ in {
+ auto rgx = new Rgx();
+ assert(is_ != "heading");
+ assert(to!int(ocn_) >= 0);
+ }
+ out(node) {
+ debug(node) {
+ mixin ScreenTxtColors;
+ if (match(lvn, rgx.levels_numbered_headings)) {
+ writeln(scr_txt_marker["yellow"], to!string(node));
+ } else {
+ writeln(scr_txt_marker["white"], to!string(node));
+ }
+ }
+ JSONValue j = parseJSON(node);
+ assert(j["parent_lvn"].integer >= 4);
+ assert(j["parent_lvn"].integer <= 7);
+ assert(j["parent_ocn"].integer >= 0);
+ }
+ string node_emitter_heading(
+ string lvn,
+ string lcn,
+ int ocn_,
+ int counter_,
+ int pointer_,
+ string is_
+ )
+ in {
+ auto rgx = new Rgx();
+ assert(is_ == "heading");
+ assert(to!uint(ocn_) >= 0);
+ assert(
+ match(lvn, rgx.levels_numbered),
+ ("not a valid heading level: " ~ lvn ~ " at " ~ to!string(ocn_))
+ );
+ if (match(lvn, rgx.levels_numbered)) {
+ if (to!uint(lvn) == 0) {
+ assert(to!uint(ocn_) == 1);
+ }
+ }
+ }
+ out(node) {
+ auto rgx = new Rgx();
+ debug(heading) {
+ mixin ScreenTxtColors;
+ if (match(lvn, rgx.levels_numbered_headings)) {
+ writeln(scr_txt_marker["yellow"], to!string(node));
+ }
+ }
+ debug(node) {
+ mixin ScreenTxtColors;
+ if (match(lvn, rgx.levels_numbered_headings)) {
+ writeln(scr_txt_marker["yellow"], to!string(node));
+ } else {
+ writeln(scr_txt_marker["white"], to!string(node));
+ }
+ }
+ JSONValue j = parseJSON(node);
+ assert(j["parent_lvn"].integer <= 7);
+ assert(j["parent_ocn"].integer >= 0);
+ if (match(lvn, rgx.levels_numbered_headings)) {
+ assert(j["lvn"].integer <= 7);
+ assert(j["ocn"].integer >= 0);
+ if (j["parent_lvn"].integer > 0) {
+ assert(j["parent_lvn"].integer < j["lvn"].integer);
+ if (j["ocn"].integer != 0) {
+ assert(j["parent_ocn"].integer < j["ocn"].integer);
+ }
+ }
+ if (j["lvn"].integer == 0) {
+ assert(j["parent_lvn"].integer == 0);
+ } else if (j["lvn"].integer == 1) {
+ assert(j["parent_lvn"].integer == 0);
+ } else if (j["lvn"].integer == 2) {
+ assert(j["parent_lvn"].integer == 1);
+ } else if (j["lvn"].integer == 3) {
+ assert(j["parent_lvn"].integer == 2);
+ } else if (j["lvn"].integer == 4) {
+ assert(j["parent_lvn"].integer <= 3);
+ } else if (j["lvn"].integer == 5) {
+ assert(j["parent_lvn"].integer == 4);
+ } else if (j["lvn"].integer == 6) {
+ assert(j["parent_lvn"].integer == 5);
+ } else if (j["lvn"].integer == 7) {
+ assert(j["parent_lvn"].integer == 6);
+ } else if (j["lvn"].integer == 8) {
+ }
+ }
+ }
+}
+#+end_src
+* tangles
+** code structure: :ao_emitter.d:
+#+name: tangle_ao_emitter
+#+BEGIN_SRC d :tangle ../lib/sdp/ao_emitter.d :exports none :noweb yes
+/*
+ emitters
+ ao_emitters.d
+*/
+mixin template Emitters() {
+ mixin InternalMarkup;
+ <<ao_emitter>>
+}
+#+end_src
+** code structure: :ao_interface.d:
+#+name: tangle_ao_interface
+#+BEGIN_SRC d :tangle ../lib/sdp/ao_interface.d :exports none :noweb yes
+/*
+ interface
+ ao_interface.d
+*/
+mixin template Interfaces() {
+ <<ao_interface>>
+}
+#+end_src