#!/usr/bin/env python3 import argparse import sys import re def get_opts(): parser = argparse.ArgumentParser( description="TOC for markdown.", epilog="""Automatic TOC guide: Add these hidden comments in the markdown: [TOCSTART]: # [TOCEND]: # Then, use this command to generate TOC: (make a backup first...) sed -i -n \\ -e '1,/^\[TOCSTART\]: #/p;/^\[TOCEND\]: #/,$p' \\ -e '/^\[TOCSTART\]: #/r '<( md-toc document.md ) \\ document.md """, formatter_class=argparse.RawTextHelpFormatter, ) parser.add_argument("-n", help="Number TOC", action="store_true") parser.add_argument("-l", help="TOC as links", action="store_true") parser.add_argument( "markdown", help="Filename to read. - for stdin", action="store", default="-", nargs="?", ) args = parser.parse_args() return args def main(): opts = get_opts() if opts.markdown == "-": fp = sys.stdin else: fp = open(opts.markdown, "rt") bullet = "-" counters = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] lastlev = 0 re_anchor = re.compile("[^0-9a-z-]") for row in fp: if row.startswith("#"): headers, title = row.strip().split(" ", 1) if opts.l: anchor = re_anchor.sub("", title.lower().replace(" ", "-")) title = "[{}](#{})".format(title, anchor) pad = headers.count("#") - 1 if pad < lastlev: counters = [x if i <= pad else 0 for i, x in enumerate(counters)] counters[pad] += 1 lastlev = pad if opts.n: bullet = "{:d}.".format(counters[pad]) print("{}{} {}".format(pad * " ", bullet, title)) print("") if __name__ == "__main__": main()