Skip to content

Instantly share code, notes, and snippets.

@josephsdavid
Last active January 30, 2022 08:07
Show Gist options
  • Save josephsdavid/815ebdb894020088f48af88d75da627e to your computer and use it in GitHub Desktop.
Save josephsdavid/815ebdb894020088f48af88d75da627e to your computer and use it in GitHub Desktop.
takes lua docstrings or whatever and makes them norg
#!/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