aboutsummaryrefslogtreecommitdiffhomepage
path: root/misc/util/d/tools/endnotes_inline_from_binary.d
blob: 4d9ceb0752f022ea933bef5c3731f6c7c4d02036 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#!/usr/bin/env rdmd
/+
  - read in file .sst .ssi .ssm
  - loop twice
    - first
      - check for and skip code blocks
      - use unique code marker for endnote markers in text and give an endnote
        number ★1, increment
      - extract all endnotes in array
    - second
      - check that the footnote marker number count matches the number of notes
        in the array
        - if they match either:
            - substitute each endnote marker with the array footnote[number-1]
            - substitute each endnote marker with footnote
              as inlined footnote markup (footnote number not needed)
        - if they do not match exit
  - check whether changes have been made
    - if so write file with inline footnotes in sub-directory converted_output_/
      using the same name as the original file
    - else, exit
+/
import std.stdio;
import std.file;
import std.array : split;
import std.exception;
import core.stdc.errno;
import std.regex;
import std.format;
import std.conv;
void main(string[] args) {
  foreach(arg; args[1..$]) {
    if (
      !(arg.match(regex(r"--\w+")))
      && arg.match(regex(r"\w+?\.ss[itm]"))
    ) {
      writeln(arg);
      string filename                  = arg;
      try {
        string[] contents, endnotes, endnote_refs;
        string text                    = filename.readText;
        string[] paragraphs            = text.split("\n\n");
        int endnote_ref_count          = 0;
        int[string] type = [
          "curly_code"                 : 0,
          "tic_code"                   : 0,
        ];
        static comment                 = ctRegex!(`^%+ `);
        static block_tic_code_open     = ctRegex!("^`{3} code(?:[.](?P<syntax>[a-z][0-9a-z#+_]+))?(?:[(](?P<attrib>[ a-zA-Z0-9;:,]*)[)])?");
        static block_tic_close         = ctRegex!("^(`{3})$","m");
        static block_curly_code_open   = ctRegex!(`^(?:code(?:[.](?P<syntax>[a-z][0-9a-z_]+))?(?:[(](?P<attrib>[ a-zA-Z0-9;:,]*)[)])?[{][ ]*$)`);
        static block_curly_code_close  = ctRegex!(`^([}]code)`);
        auto rgx_endnote_ref           = ctRegex!(`([~]\^)(?P<tail>[)\]]? |$)`, "gm");
        auto rgx_endnote               = ctRegex!(`^\^~\s+(.+|\n)`, "gm");
        foreach (paragraph; paragraphs) { /+ loop to gather binary endnotes +/
          if ( !( type["curly_code"] == 1 || type["tic_code"] == 1)
            && paragraph.match(rgx_endnote)
          ) {
            endnotes ~= replaceAll!(m => m[1])
              (paragraph, rgx_endnote);
          } else {
            if ( type["curly_code"] == 1
              && paragraph.matchFirst(block_curly_code_close)
            ) {
              type["curly_code"] = 0;
            } else if (type["tic_code"] == 1
              && paragraph.matchFirst(block_tic_close)
            ) {
              type["tic_code"] = 0;
            } else if ( type["curly_code"] == 1 || type["tic_code"] == 1) {
              // prevent search for endnotes
            } else if (paragraph.matchFirst(block_curly_code_open)) {
              type["curly_code"] = 1;
            } else if (paragraph.matchFirst(block_tic_code_open)) {
              type["tic_code"] = 1;
            } else if (auto m = paragraph.matchAll(rgx_endnote_ref)) {
              foreach (n; m) {
                endnote_ref_count++; // endnote_refs ~= (n.captures[1]);
              }
            }
            contents ~= paragraph;
          }
        }
        if (endnotes.length == endnote_ref_count) {
          import std.outbuffer;
          writeln("endnote ref count:         ", endnote_ref_count);
          writeln("number of binary endnotes: ", endnotes.length);
          int endnote_count = -1;
          auto buffer = new OutBuffer();
          foreach (content; contents) { /+ loop to inline endnotes +/
            content = replaceAll!(m => "~{ " ~ endnotes[++endnote_count] ~ " }~" ~ m["tail"] )
              (content, rgx_endnote_ref);
            buffer.write(content ~ "\n\n");
          }
          if (buffer) {
            try {
              string dir_out = "converted_output_";
              string path_and_file_out = dir_out ~ "/" ~ filename;
              dir_out.mkdirRecurse;
              auto f = File(path_and_file_out, "w");
              f.write(buffer);
              writeln("wrote: ", path_and_file_out);
            } catch (FileException ex) {
              writeln("did not write file");
              // Handle errors
            }
          }
        } else {
          writeln("ERROR binary endnote mismatch, check markup,\nmisatch in the number of endnotes & endnote references!");
          writeln("  number of endnotes:     ", endnotes.length);
          writeln("  number of endnote refs: ", endnote_ref_count); // endnote_refs.length,
        }
        // assert(endnotes.length == endnote_ref_count);
      } catch (ErrnoException ex) {
        switch(ex.errno) {
          case EPERM:
          case EACCES: // Permission denied
            break;
          case ENOENT: // File does not exist
            break;
          default:     // Handle other errors
            break;
        }
      }
    }
  }
}