#!/usr/bin/python3 from fileinput import input as finput import re class UntitledError(BaseException): pass class InternalError(UntitledError): pass class ParsingError(UntitledError): pass class MiscError(UntitledError): pass class Element: def __init__(self, element, data=None, data2=None): if not data: self.data = "" else: self.data = data if not data2: self.data2 = "" else: self.data2 = data2 self.element = element def append(self, string, space=False): if type(data) == str: if space: self.data += " " self.data += string else: raise InternalError("Appending to object!") def set(self, data): self.data = data def __str__(self): return str((str(self.element), str(self.data))) def __repl__(self): return self.__str__() class Table: def __init__(self, data=None): if data == None: self.data = [] else: self.data = [] self.addrow(data) def addrow(self, data): if type(data) == str: buf = [i.rstrip().lstrip() for i in data.split("|")] if len(self.data) > 0: if len(self.data[-1]) == len(buf): self.data.append(buf) else: raise ParsingError("tables must have uniform dimensions throughout") else: self.data.append(buf) elif type(data) == list: if len(self.data) > 0: if len(self.data[-1]) == len(data): self.data.append(data) else: raise ParsingError("tables must have uniform dimensions throughout") else: self.data.append(data) def __str__(self): return str(self.data) def __repl__(self): return self.__str__() def printchain(chain): for i in chain: if not i.data == None: print(i.data, i.element) else: print(i.element) def renderer(chain): for i in chain: rendered = False if i.element == "h1": rendered = True print("+" + (len(i.data) + 2) * "-" + "+") print("| " + i.data + " |") print("+" + (len(i.data) + 2) * "-" + "+") elif i.element == "h2": rendered = True print(" " + i.data + " ") print("=" * (len(i.data) + 2)) elif i.element == "h3": rendered = True print(" " + i.data + " ") print("-" * (len(i.data) + 2)) elif "h" in i.element: raise ParsingError("you cannot have more than three levels of headers") elif i.element == "p": rendered = True isplit = i.data.split(' ') buf = "" for i in isplit: if (len(i) + len(buf) + 1) <= 63: if not len(buf) == 0: buf += " " buf += i else: print(buf) buf = "" buf += i print(buf) elif i.element == "t": rendered = True buf = [0] * len(i.data.data[0]) for j in i.data.data: c = 0 for k in j: if len(k) > buf[c]: buf[c] = len(k) c += 1 width = max(buf) * len(i.data.data[0]) width += 2 * len(i.data.data[0]) + 1 print("+" + "-" * width + "+") # don't ask for j in range(len(i.data.data)): c = 0 for k in range(len(i.data.data[j])): if len(i.data.data[j][k]) < buf[c]: i.data.data[j][k] = i.data.data[j][k].ljust(buf[c], " ") cbuf = "" for j in i.data.data: cbuf = "| " + ' | '.join(j) + " |" print(cbuf) print("+" + "-" * width + "+") elif i.element == "l": rendered = True buf = i.data.split(' ') cbuf = "* " for i in buf: if (len(cbuf) + len(i) + 1) <= 63: if not len(cbuf) == 2: cbuf += " " cbuf += i else: print(cbuf) cbuf = " " cbuf += i print(cbuf) elif i.element == "r": rendered = True print("=>", i.data, i.data2) elif i.element == "x": print(i.data) if rendered: print() chain = [] flags = { "TABLE_PREV": False, "PARA_PREV": False, "IN_PREFORMATTED": False, } def main(): for i in finput(): i = i.rstrip() # ignore blank lines (but not seperating paragraphs) if len(i) == 0 and not flags["IN_PREFORMATTED"]: if flags["PARA_PREV"]: flags["PARA_PREV"] = False continue # lines with text if i[0].isalpha() and not flags["IN_PREFORMATTED"]: if not flags["PARA_PREV"]: flags["PARA_PREV"] = True chain.append(Element("p", i)) else: if not chain[-1].data[-1] == " ": chain[-1].data += " " + i else: chain[-1].data += i continue if i[0:3] == '```': if not flags["IN_PREFORMATTED"]: flags["IN_PREFORMATTED"] = True params = i[3:] chain.append(Element("x", "", params)) else: flags["IN_PREFORMATTED"] = False continue # we have a processing command if not i[0].isalpha() and not flags["IN_PREFORMATTED"]: command = "" params = "" counter = 0 for j in i: if not j.isalpha() \ and not j == ' ': command += j else: if j == ' ': params = i[counter + 1:] else: params = i[counter:] break counter += 1 if command[0] == "#": chain.append(Element("h" + str(len(command)), params)) elif command == "%": chain.append(Element("c", params)) elif command == "*": chain.append(Element("l", params)) elif command == "-": chain.append(Element("l", params)) elif command == ">": chain.append(Element("q", params)) elif command == "=": splitted = params.split(' ') url = splitted[0] desc = ' '.join(splitted[1:]) chain.append(Element("r", url, desc)) elif command == "|": if flags["TABLE_PREV"]: chain[-1].data.addrow(params) continue else: chain.append(Element("t", Table(params))) flags["TABLE_PREV"] = True continue flags["TABLE_PREV"] = False flags["PARA_PREV"] = False continue elif flags["IN_PREFORMATTED"]: chain[-1].data += i + "\n" renderer(chain) if __name__ == "__main__": main()