Last active
January 30, 2022 08:07
-
-
Save josephsdavid/815ebdb894020088f48af88d75da627e to your computer and use it in GitHub Desktop.
takes lua docstrings or whatever and makes them norg
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import os | |
import sys | |
from collections import defaultdict, deque | |
from typing import List, Optional | |
def read_file(path: str) -> str: | |
if os.path.isfile(path): | |
with open(path, 'r') as f: | |
out = f.read() | |
return out | |
else: | |
raise FileNotFoundError("{} is not a file".format(path)) | |
class LuaFunction(object): | |
def __init__(self, | |
func: str, | |
docs: List[str], | |
parent: Optional["LuaFunction"] = None) -> None: | |
self.func = func | |
self.docs = docs | |
self.parent = parent | |
self.children = [] | |
def __repr__(self): | |
out = [] | |
out.append( | |
f"parent:{self.parent.func if self.parent is not None else ''}") | |
out.append(f"name:{self.func}") | |
out.append(f"doc:{''.join(self.docs)}") | |
return "\n".join(out) | |
def __hash__(self): | |
return hash((self.func, "".join(self.docs), | |
self.parent.func if self.parent is not None else '')) | |
def get_func_name(r: str) -> str: | |
return r.split("function ")[-1].split("(")[0] | |
def get_docs(rawdata: str) -> List[LuaFunction]: | |
data = [d for d in rawdata.splitlines() if len(d) > 0] # strip empty lines | |
stack = deque() | |
out = [] | |
for i, row in enumerate(data): | |
if "function" in row: # hacky, theres a better way to do this | |
funcname = get_func_name(row) | |
if i == 0: | |
doc = ["no docs"] | |
else: | |
# TODO: this is disgusting | |
to_now = data[:i][::-1] | |
doc = [] | |
curr = to_now.pop(0).strip() | |
while curr.startswith("---") and len(to_now) > 0: | |
doc.append(curr) | |
curr = to_now.pop(0).strip() | |
doc = doc[::-1] | |
doc = doc | |
parent = stack[-1] if len(stack) > 0 else None | |
LuaFunc = LuaFunction(funcname, doc, parent) | |
out.append(LuaFunc) | |
stack.append(LuaFunc) | |
elif any([x in row for x in ["for", "while", "if"]]): | |
stack.append("thing") | |
elif row.strip() == "end": | |
lhs = stack.pop() | |
else: | |
pass | |
return out | |
def parse_single_doc(d: List[str], heading_level: int = 1): | |
q = deque(dd.replace('---', '') for dd in d) | |
keys = {"param": "Parameters", "return": "Returns"} | |
out_dict = defaultdict(list) | |
while q: | |
curr = q.popleft() | |
if len(curr.strip()) == 0: | |
continue | |
elif curr.strip().startswith("@"): | |
# map the @s to stupid sections | |
currsplit = curr.split() | |
curr_idx = currsplit[0].replace('@', '') | |
currtype = keys[curr_idx] if curr_idx in keys.keys() else curr_idx | |
out_dict[currtype].append(" ".join(currsplit[1:])) | |
else: | |
out_dict["comment"].append(curr) | |
doc = [] | |
if "comment" in out_dict.keys(): | |
for item in out_dict.pop('comment'): | |
doc.append(" " * (heading_level + 1) + "" + item) | |
for k, v in out_dict.items(): | |
doc.append("*" * (heading_level + 1) + " " + k) | |
for vv in v: | |
doc.append(" " * (heading_level + 1) + "- " + vv) | |
return "\n".join(doc) | |
def set_children(docs: List[LuaFunction]) -> List[LuaFunction]: | |
for d in docs: | |
if d.parent is not None: | |
docs[docs.index(d.parent)].children.append(d) | |
for d in docs: | |
d.children = sorted(d.children, key=lambda x: docs.index(x)) | |
return docs | |
def parse(docs: List[LuaFunction], heading_level: int = 1, seen: set = set()): | |
q = deque(docs) | |
out = deque() | |
while q: | |
curr = q.popleft() | |
if curr not in seen: | |
seen.add(curr) | |
out.append("*" * heading_level + " " + curr.func) | |
out.append(parse_single_doc(curr.docs, heading_level)) | |
if len(curr.children) > 0: | |
out.extend(parse(curr.children, heading_level + 1, seen)) | |
return out | |
def main(): | |
path = sys.argv[1] | |
data = read_file(path) | |
ret = "\n".join(parse(set_children(get_docs(data)))) | |
return ret | |
if __name__ == "__main__": | |
print(main()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment