Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
6 views

markdown_renderer.py

Uploaded by

dingklefard
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views

markdown_renderer.py

Uploaded by

dingklefard
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 7

import sys

import os

class String:
def __init__(self, string, indent = 0, bullet = False):
self.string = string
self.indent = indent
self.bullet = bullet
self.prefixes = ""
self.italics = False
self.underline = False
self.bold = False
self.colour = False
self.highlight = False
self.sub_element = None

def render(self, *args):


if self.string == "\n":
print()
elif len(self.string.strip()) == 0 and self.sub_element != None:
return
else:
string = self.string
indent = self.indent
print("\033[0m", end = '')
if len(args) == 1:
if self.italics:
print("\033[3m", end = '')
if self.underline:
print("\033[4m", end = '')
if self.bold:
print("\033[1m", end= '')
if self.colour:
print(f"\033[38;2;{self.colour[0]};{self.colour[1]};
{self.colour[2]};m", end = '')
if self.highlight:
print(f"\033[48;2;{self.colour[0]};{self.colour[1]};
{self.colour[2]};m", end = '')
print(string, end='')
elif self.bullet:
print(' ' * (indent - 2) + '• ', end='')
if self.italics:
print("\033[3m", end = '')
if self.underline:
print("\033[4m", end = '')
if self.bold:
print("\033[1m", end= '')
if self.colour:
print(f"\033[38;2;{self.colour[0]};{self.colour[1]};
{self.colour[2]};m", end = '')
if self.highlight:
print(f"\033[48;2;{self.colour[0]};{self.colour[1]};
{self.colour[2]};m", end = '')

print(string[0: os.get_terminal_size()[0]- 2-(indent-2)], end='')

for _ in range(os.get_terminal_size()[0] - 2+indent, len(string),


os.get_terminal_size()[0] - (indent-2)):
print(' ' * indent + string[_ - 2: _ + os.get_terminal_size()
[0] - (indent-2)], end='')
else:
if self.italics:
print("\033[3m", end = '')
if self.underline:
print("\033[4m", end = '')
if self.bold:
print("\033[1m", end= '')
if self.colour:
print(f"\033[38;2;{self.colour[0]};{self.colour[1]};
{self.colour[2]};m", end = '')
if self.highlight:
print(f"\033[48;2;{self.colour[0]};{self.colour[1]};
{self.colour[2]};m", end = '')

for _ in range(0, len(string), os.get_terminal_size()[0] -


indent+2):
print(' ' * indent + string[_: _ + os.get_terminal_size()[0] -
indent+2], end='')
if self.sub_element != None:
self.sub_element.render(True)

def __repr__(self) -> str:


if self.sub_element == None:
return self.string
return self.string + self.sub_element.__repr__().strip()

class Tag:
def construct(self, data):
pass

def execute(self, *args):


lines = []
parser = Parser(self.data)
while parser.last_index < len(self.data):
lines += parser.parse()
return lines

def __init__(self, data) -> None:


#self.contains_multiple_tags = False
self.construct(data)

class Data(Tag):
def construct(self, data) -> None:
self.data = data # line of data

def execute(self, *args):


if "</data>" in self.data.lower():
print("\033[38;2;255;0;0;m" + "Warning: Data tags do not get expanded
when already nested in another data tag")
print("\033[38;2;255;255;255;m")
if len(args) > 0:
if args[0] == False:
return [String(self.data)]
return [String(self.data)]

class Element(Tag):
def construct(self, data):
self.data = data
def execute(self, *args):
self.data = Tag.execute(self)
for index in range(len(self.data)):
if isinstance(self.data[index], str):
self.data[index] = String(self.data[index])

prev = self.data[0]
for index in range(1, len(self.data)):
prev.sub_element = self.data[index]
prev = self.data[index]
return [self.data[0]]

class Bold(Tag):
def construct(self, data) -> None:
self.data = data

def execute(self, *args):


self.data = Tag.execute(self)
for index in range(len(self.data)):
if isinstance(self.data[index], String):
self.data[index].bold = True
return self.data

class Main(Tag):
def construct(self, data) -> None:
self.data = data
#self.contains_multiple_tags = True

def execute(self, *args):


lines = []
parser = Parser(self.data)
while parser.last_index < len(self.data):
lines += parser.parse()

#print(lines)
#os.system("clear")
for line in lines:
if isinstance(line, String):
line.render()
#print(list(line.string))
else:
print()
#print(list(line))

class Colour(Tag):
def construct(self, data) -> None:
self.data = data

def execute(self, *args):


try:
self.colour = args[0]
except:
raise Exception("No colour provided for colour tag")
try:
self.colour = list(map(int, self.colour.split(",")))
except:
raise Exception(f"Invalid RGB colour {self.colour}")
if len(self.colour) != 3:
raise Exception("Invalid RGB colour (not enough numbers)")
self.data = Tag.execute(self)
for index in range(len(self.data)):
if isinstance(self.data[index], String):
self.data[index].colour = self.colour
return self.data

class Highlight(Tag):
def construct(self, data) -> None:
self.data = data

def execute(self, *args):


try:
self.colour = args[0]
except:
raise Exception("No colour provided for colour tag")
try:
self.colour = list(map(int, self.colour.split(",")))
except:
raise Exception(f"Invalid RGB colour {self.colour}")
if len(self.colour) != 3:
raise Exception("Invalid RGB colour (not enough numbers)")
self.data = Tag.execute(self)
for index in range(len(self.data)):
if isinstance(self.data[index], String):
self.data[index].highlight = self.colour
return self.data

class Bullet(Tag):
def construct(self, data):
self.data = data

def execute(self, *args):


self.data = Tag.execute(self)
#print(self.data)
for index, data in enumerate(self.data):
if isinstance(data, String):
if not data.bullet:
self.data[index].bullet = True
self.data[index].indent += 2
return self.data

class Underline(Tag):
def construct(self, data):
self.data = data

def execute(self, *args):


self.data = Tag.execute(self)
for index in range(len(self.data)):
if isinstance(self.data[index], String):
self.data[index].underline = True
return self.data

class Italic(Tag):
def construct(self, data):
self.data =data

def execute(self, *args):


self.data = Tag.execute(self)
for index in range(len(self.data)):
if isinstance(self.data[index], String):
self.data[index].italics = True
return self.data

class Parser:
# parser function <- block of markdown
# parses recursively until just a data block
# data blocks contain one line

def __init__(self, original) -> None:


self.tags = {"element": Data, "bold": Bold, "colour": Colour, "bullet":
Bullet, "highlight": Highlight, "italic": Italic, "underline": Underline, "data":
Element}
self.string = original
self.last_index = 0
self.consumed_end_tags = []

def parse(self):
index, tag, data = self.get_tag(self.string, self.last_index)
self.last_index = max(self.last_index, index)
return tag.execute(data)

def scan(self, string, character, index = 0):


for index in range(index + 1, len(string)):
if string[index] == character:
return index
return None

def identify_tag(self, tag):


data = None
if ":" in tag:
tag_type, data = tag.split(":")
else:
tag_type = tag
if tag_type.lower() in self.tags:
return (self.tags[tag_type.lower()], tag_type.lower(), data)
else:
return (None, None, None)

def search_for_end_tag(self, string, tag, index, tag_type):


c = 0
string = string.lower()
#print(f"Call to search {string[index + 1:]}")
if tag in string[index + 1:]:
f = None
for i in range(index + 1, len(string)):
if string[i] == "<":
end = self.scan(string, ">", i)
if string[i+1:end][0] == "/":
_, _tag_type, tag_data = self.identify_tag(string[i +
2:end])
#print("end", tag_type, _tag_type, end, string[i+1: end])
if _tag_type == tag_type:
c -= 1
if c == -1:
f = i
break
else:
_, _tag_type, tag_data = self.identify_tag(string[i +
1:end])
#print(tag_type, _tag_type, end, string[i+1: end])
if _tag_type == tag_type:
c += 1
else:
continue
return f

#g = []

#for i in range(index + 1, len(string)):


#if string[i: i + len(tag)] == tag:
#g.append(i)
# print(g, c)

#if c < len(g):


#return g[c]
#else:
#print("was here")
#return None
else:
return None

def get_tag(self, string, previous_index = 0):


for index in range(previous_index, len(string)):
if string[index] == "<":
if "\n" in string[previous_index: index]:
#print("!!!!!!!!!!!!!!!!!!!!!", string[:index])
return (index, Data('\n'), [False])
elif len(string[previous_index: index]) > 0:
return (index, Data(string[previous_index: index]), [False])
if (end_of_tag := self.scan(string, ">", index)) != None:
tag, tag_type, tag_data = self.identify_tag(string[index + 1 :
end_of_tag])
if tag != None:
end_tag = self.search_for_end_tag(string, f"</{tag_type}>",
end_of_tag, tag_type)
if end_tag == None:
raise Exception(f"No closing tag for tag type:
{tag_type}")
data = string[end_of_tag + 1: end_tag]
else:
raise Exception(f"Cannot identify tag
{string[end_of_tag:]}")
return (end_tag + len(f"<{tag_type}>") + 1, tag(data),
tag_data)
return (len(string), Data(string[previous_index:]), [False])

file = None
skip = True
macro_ = False
lines = []
macros = []
for index, arg in enumerate(sys.argv):
if skip:
skip = False
continue
if arg == "-f":
file = open(sys.argv[index + 1], "r")
lines = file.readlines()
file.close()

if arg == "-m" or arg == "-macro_file":


macro_ = True
macro_file = open(sys.argv[index + 1], "r")
macros = macro_file.readlines()
macro_file.close()

if file == None:
raise Exception("Need a file")

if macro_:
for line in macros:
macro, m = line.strip().split(":=")
macro = macro.strip()
m = m.strip()
if macro[0] == '\'' and macro[-1] == '\'':
macro = macro[1:-1]
for index, line in enumerate(lines):
if macro in list(map(str.lower, line.replace(',', ' ').replace('.',
' ').replace('<', ' ').replace('>', ' ').split())):
#print(macro)
lines[index] = lines[index].replace(macro, m)
lines[index] = lines[index].replace(macro[0].upper() +
macro[1:], m.replace(macro, macro[0].upper() + macro[1:]))
end_tag = ""

for index in range(0, len(m)):


if m[index] == "<":
end = Parser('').scan(m, ">", index)
_, tag_type, _ = Parser('').identify_tag(m[index + 1: end])
end_tag = f"</{tag_type}>" + end_tag
end_tag = end_tag.strip()

for index, line in enumerate(lines):


lines[index] = line.replace(f"<{macro}>", m)
lines[index] = lines[index].replace(f"</{macro}>", end_tag)

def i(x):
if x == "\n":
return "\n"
else:
return x
#print(lines)
lines = "".join(list(map(i, lines)))
#print(lines)

Main(lines).execute()

You might also like