#+TITLE: sdp header extract
#+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 _: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
#+PROPERTY: header-args :padline no :exports code :noweb yes
#+EXPORT_SELECT_TAGS: export
#+EXPORT_EXCLUDE_TAGS: noexport
#+FILETAGS: :sdp:rel:ao:
#+TAGS: assert(a) class(c) debug(d) mixin(m) sdp(s) tangle(T) template(t) WEB(W) noexport(n)
[[./sdp.org][sdp]] [[./][org/]]
* 0. Code Skeleton / Outline / Structure (tangles) :tangle:
** 1. Header Hub :ao_markup_header_extract:
#+BEGIN_SRC d :tangle ../src/sdp/ao_conf_make_meta.d
/++
extract native/orig header return associative array
the header is passed as text (lopped off top of a sisu markup file until the
required first heading ^A~), determine whether is a native header or sdlang one
with a regex check if whether it contains the "native header" required tag/field
@title: then process accordingly as a "native header" or "sdlang header"
converting the metadata and make instructions to a common json format used by
program internally. Moved to associative array.
+/
template SiSUheaderExtractHub() {
private import
std.regex;
private import
ao_rgx;
struct HeaderDocMetadataAndMake {
mixin SiSUheaderExtractNative;
mixin SiSUheaderExtractSDLang;
auto rgx = Rgx();
private auto headerContentAA(char[] header_src, string[string][string] conf_doc_make_aa) {
auto head_native = HeaderDocMetadataAndMakeNativeToAA();
auto head_sdlang = HeaderExtractSDL();
auto header_make_and_meta_tuple = (match(header_src, rgx.native_header_meta_title))
? (head_native.headerNativeToAA(header_src))
: (head_sdlang.headerSDLangToAA(header_src, conf_doc_make_aa));
static assert(!isTypeTuple!(header_make_and_meta_tuple));
static assert(header_make_and_meta_tuple.length==2);
return header_make_and_meta_tuple;
}
}
}
#+END_SRC
** 2a. Header Native :ao_markup_header_extract_native:
#+BEGIN_SRC d :tangle ../src/sdp/ao_conf_make_meta_native.d
/++
native headers using
@title:
:subtitle:
type tags
extract native/orig header return associative array
+/
template SiSUheaderExtractNative() {
private import
std.exception,
std.regex,
std.utf,
std.conv : to;
private import
ao_rgx;
struct HeaderDocMetadataAndMakeNativeToAA {
mixin SiSUregisters;
mixin SiSUrgxInitFlags;
mixin RgxInit;
auto rgx = Rgx();
enum State { off, on }
string hm, hs;
<>
}
}
#+END_SRC
** 2b. Header SDLang :ao_markup_header_extract_sdlang:
#+BEGIN_SRC d :tangle ../src/sdp/ao_conf_make_meta_sdlang.d
/++
sdlang headers
extract sdlang header return sdlang
+/
template SiSUheaderExtractSDLang() {
private import
std.regex;
private import
ao_rgx;
struct HeaderExtractSDL {
mixin SiSUregisters;
mixin RgxInit;
auto rgx = Rgx();
<>
}
}
#+END_SRC
* A. sdlang to AA
#+name: ao_conf_make_meta_sdl
#+BEGIN_SRC d
private auto sdlangToAAmake(string[string][string] conf, Tag conf_sdlang) {
foreach (maintag, subtags; conf) {
foreach (subtag, content; subtags) {
if (!(conf_sdlang.maybe.tags[maintag].empty)) {
if (!(conf_sdlang.tags[maintag][0].maybe.attributes[subtag].empty)
&& (conf_sdlang.tags[maintag][0].attributes[subtag][0].value.length > 0)) {
debug(headersdlang) {
writeln(conf_sdlang.tags[maintag][0].attributes[subtag][0].value);
}
conf[maintag][subtag] =
to!string(conf_sdlang.tags[maintag][0].attributes[subtag][0].value);
}
}
}
}
return conf;
}
#+END_SRC
* B. conf settings sdlang
#+name: ao_conf_make_meta_sdl
#+BEGIN_SRC d
private auto configSettingsSDLangToAAmake(Tag conf_sdlang) {
auto conf = sdlangToAAmake(conf_aa, conf_sdlang);
return conf;
}
#+END_SRC
* C. conf make sdlang
#+name: ao_conf_make_meta_sdl
#+BEGIN_SRC d
private auto documentMakeSDLangToAAmake(Tag document_make_sdlang) {
auto dochead_make = sdlangToAAmake(make_aa, document_make_sdlang);
/+
/+ dochead +/
string hm;
string hs;
/+ make +/
auto dochead_make = make_aa;
if (!(document_make_sdlang.maybe.tags["make"].empty)) {
hm = "make";
hs = "bold";
if (!(document_make_sdlang.tags[hm][0].maybe.attributes[hs].empty)
&& (document_make_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
debug(headersdlang) {
writeln(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
}
dochead_make[hm][hs] =
to!string(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
}
hs = "breaks";
if (!(document_make_sdlang.tags[hm][0].maybe.attributes[hs].empty)
&& (document_make_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
debug(headersdlang) {
writeln(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
}
dochead_make[hm][hs] =
to!string(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
}
hs = "cover_image";
if (!(document_make_sdlang.tags[hm][0].maybe.attributes[hs].empty)
&& (document_make_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
debug(headersdlang) {
writeln(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
}
dochead_make[hm][hs] =
to!string(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
}
hs = "css";
if (!(document_make_sdlang.tags[hm][0].maybe.attributes[hs].empty)
&& (document_make_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
debug(headersdlang) {
writeln(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
}
dochead_make[hm][hs] =
to!string(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
}
hs = "emphasis";
if (!(document_make_sdlang.tags[hm][0].maybe.attributes[hs].empty)
&& (document_make_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
debug(headersdlang) {
writeln(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
}
dochead_make[hm][hs] =
to!string(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
}
hs = "footer";
if (!(document_make_sdlang.tags[hm][0].maybe.attributes[hs].empty)
&& (document_make_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
debug(headersdlang) {
writeln(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
}
dochead_make[hm][hs] =
to!string(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
}
hs = "headings";
if (!(document_make_sdlang.tags[hm][0].maybe.attributes[hs].empty)
&& (document_make_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
debug(headersdlang) {
writeln(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
}
dochead_make[hm][hs] =
to!string(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
}
hs = "home_button_image";
if (!(document_make_sdlang.tags[hm][0].maybe.attributes[hs].empty)
&& (document_make_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
debug(headersdlang) {
writeln(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
}
dochead_make[hm][hs] =
to!string(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
}
hs = "home_button_text";
if (!(document_make_sdlang.tags[hm][0].maybe.attributes[hs].empty)
&& (document_make_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
debug(headersdlang) {
writeln(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
}
dochead_make[hm][hs] =
to!string(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
}
hs = "italics";
if (!(document_make_sdlang.tags[hm][0].maybe.attributes[hs].empty)
&& (document_make_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
debug(headersdlang) {
writeln(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
}
dochead_make[hm][hs] =
to!string(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
}
hs = "num_top";
if (!(document_make_sdlang.tags[hm][0].maybe.attributes[hs].empty)
&& (document_make_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
debug(headersdlang) {
writeln(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
}
dochead_make[hm][hs] =
to!string(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
}
hs = "substitute";
if (!(document_make_sdlang.tags[hm][0].maybe.attributes[hs].empty)
&& (document_make_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
debug(headersdlang) {
writeln(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
}
dochead_make[hm][hs] =
to!string(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
}
hs = "texpdf_font";
if (!(document_make_sdlang.tags[hm][0].maybe.attributes[hs].empty)
&& (document_make_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
debug(headersdlang) {
writeln(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
}
dochead_make[hm][hs] =
to!string(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
}
}
+/
/+
hm = "links";
if (!(document_make_sdlang.maybe.tags[hm].empty)) {
/+ TODO
stuff to fix
+/
}
+/
return dochead_make;
}
#+END_SRC
* D. header :header:
** a. header native :header:native:
*** native header document metadata in associative array :aa:
#+name: ao_markup_header_extract_native
#+BEGIN_SRC d
auto header_metadata_and_make_aa(
string header,
string[string][string] dochead_meta,
string[string][string] dochead_make
)
in { }
body {
scope(exit) {
destroy(header);
destroy(dochead_meta);
destroy(dochead_make);
}
if (auto t = match(header, rgx.native_header_main)) {
char[][] header_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; header_obj_spl) {
if (auto m = match(line, rgx.native_header_main)) {
if (!empty(m.captures[2])) {
if (hm == "creator") {
dochead_meta[hm]["author"] =
to!string(m.captures[2]);
} else if (hm == "title") {
dochead_meta[hm]["main"] =
to!string(m.captures[2]);
} else if (hm == "publisher") {
dochead_meta[hm]["name"] =
to!string(m.captures[2]);
}
}
} else if (auto s = match(line, rgx.native_header_sub)) {
if (!empty(s.captures[2])) {
auto hs = to!string(s.captures[1]);
if ((hm == "make" )
&& (dochead_make[hm])) {
switch (hm) {
case "make":
if (match(hs, rgx.native_subhead_make)) {
if (dochead_make[hm][hs]) {
dochead_make[hm][hs] = to!string(s.captures[2]);
}
} else {
writeln("not a valid header type:", hm, ":", hs);
destroy(hm);
destroy(hs);
}
break;
default:
break;
}
} else if (dochead_meta[hm]) {
switch (hm) {
case "creator":
if (match(hs, rgx.native_subhead_creator)) {
if (dochead_meta[hm][hs]) {
dochead_meta[hm][hs] =
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.native_subhead_title)) {
if ((hs == "subtitle")
&& (dochead_meta[hm]["sub"])) {
dochead_meta[hm]["sub"] =
to!string(s.captures[2]);
} else if (dochead_meta[hm][hs]) {
dochead_meta[hm][hs] =
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.native_subhead_rights)) {
if (dochead_meta[hm][hs]) {
dochead_meta[hm][hs] =
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.native_subhead_date)) {
if (dochead_meta[hm][hs]) {
dochead_meta[hm][hs] =
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.native_subhead_original)) {
if (dochead_meta[hm][hs]) {
dochead_meta[hm][hs] =
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.native_subhead_classify)) {
if (dochead_meta[hm][hs]) {
dochead_meta[hm][hs] =
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.native_subhead_identifier)) {
if (dochead_meta[hm][hs]) {
dochead_meta[hm][hs] =
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.native_subhead_notes)) {
if (dochead_meta[hm][hs]) {
dochead_meta[hm][hs] =
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.native_subhead_publisher)) {
if (dochead_meta[hm][hs]) {
dochead_meta[hm][hs] =
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_meta, dochead_make);
static assert(t.length==2);
return t;
}
#+END_SRC
*** native header extract to string object :string:
#+name: ao_markup_header_extract_native
#+BEGIN_SRC d
private auto native_header_extract(
char[] line,
ref int[string] line_occur,
ref string[string] an_object,
ref int[string] type
) {
if (matchFirst(line, rgx.native_header_make)) { /+ matched header_make +/
debug(header1) { /+ writeln(line); +/ }
type["header"] = State.on;
type["header_make"] = State.on;
type["header_meta"] = State.off;
++line_occur["header_make"];
an_object["body_nugget"] ~= line ~= "\n";
} else if (matchFirst(line, rgx.native_header)) { /+ matched header_metadata +/
/+ (generic header match and not previously caught by header_make) +/
debug(header1) { /+ writeln(line); +/ }
type["header"] = State.on;
type["header_make"] = State.off;
type["header_meta"] = State.on;
++line_occur["header_meta"];
an_object["body_nugget"] ~= line ~= "\n";
} else if (type["header_make"] == State.on
&& (line_occur["header_make"] > State.off)) { /+ header_make flag set +/
if (matchFirst(line, rgx.native_header_sub)) { /+ sub-header +/
debug(header1) { /+ writeln(line); +/ }
++line_occur["header_make"];
an_object["body_nugget"] ~= line ~= "\n";
}
} else if (type["header_meta"] == State.on
&& (line_occur["header_meta"] > State.off)) { /+ header_metadata flag set +/
if (matchFirst(line, rgx.native_header_sub)) { /+ sub-header +/
debug(header1) { /+ writeln(line); +/ }
++line_occur["header_meta"];
an_object["body_nugget"] ~= line ~= "\n";
}
}
return an_object;
}
#+END_SRC
*** native header reset states :reset:
#+name: ao_markup_header_extract_native
#+BEGIN_SRC d
auto header_reset_states_common(
ref int[string] line_occur,
ref string[string] an_object,
ref int[string] type
) {
line_occur["header_make"] = State.off;
line_occur["header_meta"] = State.off;
type["header"] = State.off;
an_object.remove("body_nugget");
an_object.remove("is");
an_object.remove("attrib");
}
#+END_SRC
*** hub: native header start :hub:
#+name: ao_markup_header_extract_native
#+BEGIN_SRC d
private auto headerNativeToAA(in char[] src_header) {
auto type = flags_type_init;
type = [
"header" : State.off,
"header_make" : State.off,
"header_meta" : State.off,
];
string[string] an_object;
int[string] line_occur;
auto dochead_make = make_aa;
auto dochead_meta = meta_aa;
auto set_header = HeaderDocMetadataAndMakeNativeToAA();
char[][] source_header_arr =
split(cast(char[]) src_header, rgx.newline_eol_delimiter);
foreach(header_line; source_header_arr) {
if (auto m = matchFirst(header_line, rgx.comment)) {
/+ matched comment +/
debug(comment) {
}
header_reset_states_common(line_occur, an_object, type);
} else if ((matchFirst(header_line, rgx.native_header))
|| (type["header_make"] == State.on
&& (line_occur["header_make"] > State.off))
|| (type["header_meta"] == State.on
&& (line_occur["header_meta"] > State.off))) {
if (header_line.length == 0) {
/+ header_make instructions (current line empty) +/
auto dochead_metadata_and_make =
set_header.header_metadata_and_make_aa(strip(an_object["body_nugget"]), dochead_meta, dochead_make);
static assert(!isTypeTuple!(dochead_metadata_and_make));
dochead_meta = dochead_metadata_and_make[0];
dochead_make = dochead_metadata_and_make[1];
header_reset_states_common(line_occur, an_object, type);
type["header_make"] = State.off;
type["header_meta"] = State.off;
debug(headersdlang) {
writeln(dochead_metadata_and_make);
}
} else {
an_object = native_header_extract(header_line, line_occur, an_object, type);
}
}
}
auto t = tuple(
dochead_make,
dochead_meta,
);
return t;
}
#+END_SRC
** b. header sdlang :header:sdl:
*** sdlang header parse and extract root Tag :sdlang:root:tag:
#+name: ao_conf_make_meta_sdl
#+BEGIN_SRC d
final private auto headerMakeSDLang(in string src_header) {
scope(failure) {
stderr.writefln(
"%s\n%s\n%s:%s failed here:\n src_header: %s",
__MODULE__, __FUNCTION__,
__FILE__, __LINE__,
src_header,
);
}
Tag sdl_root_header;
try {
sdl_root_header = parseSource(src_header);
}
catch(ParseException e) {
stderr.writeln("SDLang problem with this document header:");
stderr.writeln(src_header);
// Error messages of the form:
// myFile.sdl(5:28): Error: Invalid integer suffix.
stderr.writeln(e.msg);
}
debug(sdlang) {
writeln("header SDL:");
writeln(sdl_root_header.toSDLDocument());
}
return sdl_root_header;
}
#+END_SRC
*** sdlang header get :sdlang:get:src:
#+name: ao_conf_make_meta_sdl
#+BEGIN_SRC d
private auto headerSDLangGet(in char[] src_header) {
char[][] source_header_arr =
split(cast(char[]) src_header, rgx.newline_eol_delimiter);
char[] header_clean;
// TODO
foreach(header_line; source_header_arr) {
if (!match(header_line, rgx.comments)) {
header_clean ~= header_line ~ "\n";
}
}
/+ get sdlang tags +/
auto header_sdlang=headerMakeSDLang(to!string(header_clean));
debug(sdlang) {
writeln("--------------");
stdout.rawWrite( header_sdlang.toSDLDocument() );
writeln("--------------");
Value test = header_sdlang.tags["title"][0].values[0];
assert(test == typeid(string));
writeln(header_sdlang.maybe.tags["title"]);
writeln(header_sdlang.maybe.tags["title"][0].maybe.attributes["subtitle"]);
}
return header_sdlang; // sdlang.ast.Tag
}
#+END_SRC
*** sdlang header to associative array make sdlTag in :sdlang:aa:
#+name: ao_conf_make_meta_sdl
#+BEGIN_SRC d
private auto headerSDLangToAAmake(Tag header_sdlang, string[string][string] dochead_make) {
dochead_make = sdlangToAAmake(dochead_make, header_sdlang);
auto dochead_meta = sdlangToAAmake(meta_aa, header_sdlang);
if (dochead_meta["title"]["main"].empty) {
dochead_meta["title"]["main"] =
to!string(header_sdlang.maybe.tags["title"][0].values[0]); // test that this exists
}
if (!(dochead_meta["title"]["subtitle"].empty)
&& (dochead_meta["title"]["sub"].empty)) {
dochead_meta["title"]["sub"] ~= dochead_meta["title"]["subtitle"];
}
dochead_meta["title"].remove("subtitle");
if (dochead_meta["title"]["sub"].empty) {
dochead_meta["title"]["full"] ~= dochead_meta["title"]["main"];
} else {
dochead_meta["title"]["full"] ~= format(
"%s - %s",
dochead_meta["title"]["main"],
dochead_meta["title"]["sub"],
);
}
dochead_meta["creator"]["author_raw"] = dochead_meta["creator"]["author"];
string[] authors_arr;
auto authors_raw_arr = split(dochead_meta["creator"]["author"], rgx.arr_delimiter);
foreach (author_raw; authors_raw_arr) {
authors_arr ~= replace(author_raw, rgx.raw_author_munge, "$2 $1");
}
dochead_meta["creator"]["author"] = join(authors_arr, ", ").chomp.chomp;
auto t = tuple(dochead_make, dochead_meta);
static assert(t.length==2);
return t;
}
#+END_SRC
*** hub: get sdlang header and convert to associative array :hub:sdlang:aa:
#+name: ao_conf_make_meta_sdl
#+BEGIN_SRC d
private auto headerSDLangToAA(char[] header_sdlang_src, string[string][string] conf_doc_make_aa) {
auto header_sdlang_tag = headerSDLangGet(header_sdlang_src); // sdlang.ast.Tag
auto header_aa_tuple = headerSDLangToAAmake(header_sdlang_tag, conf_doc_make_aa);
return header_aa_tuple;
}
#+END_SRC