#!/usr/bin/env python3 import sys import re from subprocess import Popen, PIPE from argparse import ArgumentParser __version__ = "0.1" RE_FN = re.compile("[^\s]+\s+([^\(]+)\(") RE_STRUCT = re.compile("(struct\s+[^{]+)\s*{") RE_DEFINE = re.compile("#define\s+([^(]+)\(") RE_DOC = re.compile("\s+\*\s?(.*\n)") RE_SEC = re.compile("//\s+@(.*)\n") RE_SECDOC = re.compile("//\s?(.*\n)") def main(): parser = ArgumentParser( description="Include docs to markdown", epilog="Copyright (C) 2020 Juan J Martinez ", ) parser.add_argument( "--version", action="version", version="%(prog)s " + __version__ ) parser.add_argument( "--doc-version", dest="docver", default=None, help="Use this as version instead of git tag/commit", ) parser.add_argument( "--header", dest="header", default=None, help="Add this file at the begining of the document", ) parser.add_argument( "--footer", dest="footer", default=None, help="Add this file at the end of the document", ) parser.add_argument("title", help="Title of the resulting document") args = parser.parse_args() if args.docver is None: proc = Popen( ["git", "describe", "--abbrev=0", "--tags"], stdout=PIPE, stderr=PIPE ) out, err = proc.communicate() if proc.returncode != 0: proc = Popen( ["git", "rev-parse", "--short", "HEAD"], stdout=PIPE, stderr=PIPE ) out, err = proc.communicate() out = b"git-" + out docver = out.decode("utf-8").strip() else: docver = args.docver data = sys.stdin.readlines() ref = {} section = None sections = {} while data: line = data.pop(0) # section comment if line.strip().startswith("//"): g = RE_SEC.search(line) if g: section = g.group(1) doclines = [] while True: line = data.pop(0) if not line.strip(): break doclines.append(line) doc = "" for l in doclines: g = RE_SECDOC.match(l) if g: doc += g.group(1) sections[section] = doc # begin fn/struct comment if line.strip() == "/**": doclines = [] while True: line = data.pop(0) if line.strip() == "*/": break doclines.append(line) line = data.pop(0) g = RE_DEFINE.search(line) if g is None: g = RE_STRUCT.search(line) if g is None: g = RE_FN.search(line) if g is None: continue else: fn = line.strip() else: fn = line while True: line = data.pop(0) fn += line if line.strip() == "};": break else: fn = line while True: line = data.pop(0) fn += line if not line.strip().endswith("\\"): fn = fn.rstrip() break name = g.group(1).strip() anchor = name.replace(" ", "-") doc = "" for l in doclines: g = RE_DOC.match(l) if g: doc += g.group(1) ref[name] = { "name": name, "anchor": anchor, "fn": fn, "doc": doc, "section": section, } print( """\ --- title: '{title}' subtitle: 'Version {version}' ...""".format( title=args.title, version=docver ) ) if args.header: with open(args.header, "rt") as fd: print(fd.read()) csec = None for k in sorted(ref.keys(), key=lambda k: (ref[k]["section"], k)): v = ref[k] if csec != v["section"]: csec = v["section"] print("## %s\n" % csec) if csec in sections: print(sections[csec]) print( """\ ### {name} ```c {fn} ``` {doc} """.format( **v ) ) if args.footer: with open(args.footer, "rt") as fd: print(fd.read()) if __name__ == "__main__": main()