#!/usr/bin/python3 # # Generate documentation for how this machine works by # parsing our bash scripts! import cgi, re import markdown from modgrammar import * def generate_documentation(): print("""
Here’s how you can build your own mail server from scratch. This document is generated automatically from our setup script.
" + cgi.escape(self[7].string) + "
" + cgi.escape(self.string) + "\n" return "" class EditConf(Grammar): grammar = ( L('tools/editconf.py '), FILENAME, SPACE, OPTIONAL((LIST_OF( L("-w") | L("-s"), sep=SPACE, ), SPACE)), REST_OF_LINE, OPTIONAL(SPACE), EOL ) def value(self): conffile = self[1] options = [""] mode = 1 for c in self[4].string: if mode == 1 and c in (" ", "\t") and options[-1] != "": # new word options.append("") elif mode < 0: # escaped character options[-1] += c mode = -mode elif c == "\\": # escape next character mode = -mode elif mode == 1 and c == '"': mode = 2 elif mode == 2 and c == '"': mode = 1 else: options[-1] += c if options[-1] == "": options.pop(-1) return "
" + "\n".join(cgi.escape(s) for s in options) + "
" + cgi.escape(cmd) + "
replace
" + cgi.escape(self[3].string.replace(".*", ". . .")) + "
with
" + cgi.escape(self[5].string.replace("\\n", "\n").replace("\\t", "\t")) + "
" + self[0].string + "apt-get install -y " + cgi.escape(re.sub(r"\s+", " ", self[2].string)) + "\n" class UfwAllow(Grammar): grammar = (ZERO_OR_MORE(SPACE), L("ufw_allow "), REST_OF_LINE, EOL) def value(self): return "
" + self[0].string + "ufw allow " + cgi.escape(self[2].string) + "\n" class OtherLine(Grammar): grammar = (REST_OF_LINE, EOL) def value(self): if self.string.strip() == "": return "" return "
" + cgi.escape(self.string.rstrip()) + "\n" class BashElement(Grammar): grammar = Comment | Source | CatEOF | SuppressedLine | HideOutput | EditConf | CaptureOutput | SedReplace | AptGet | UfwAllow | OtherLine def value(self): return self[0].value() class BashScript(Grammar): grammar = (OPTIONAL(HashBang), REPEAT(BashElement)) def value(self): return [line.value() for line in self[1]] @staticmethod def parse(fn): if fn in ("setup/functions.sh", "/etc/mailinabox.conf"): return "" parser = BashScript.parser() string = open(fn).read() string = re.sub(r"\s*\\\n\s*", " ", string) string = re.sub(".* #NODOC\n", "", string) string = re.sub("\n\s*if .*|\n\s*fi|\n\s*else", "", string) string = re.sub("hide_output ", "", string) result = parser.parse_string(string) v = "\n" % ("https://github.com/mail-in-a-box/mailinabox/tree/master/" + fn, fn) v += "".join(result.value()) v = v.replace("\n
", "\n") v = re.sub("([\w\W]*?)", lambda m : "" + strip_indent(m.group(1)) + "", v) v = re.sub(r"\$?PRIMARY_HOSTNAME", "box.yourdomain.com", v) v = re.sub(r"\$?STORAGE_ROOT", "/path/to/user-data
", v) v = v.replace("`pwd`", "/path/to/mailinabox
") return v if __name__ == '__main__': generate_documentation()