#!/usr/bin/python
"""
- Whitespace and line breaks are ignored.
- The first line is the title
- One or more blank lines start a new paragraph.
- = == == and so on at the beginning are for headers.
- +contenst generates a TOC
- +img inserts an image
- + marks preformated text
- - creates a bulletted list
- http:// starts a link
"""
import sys
import re
import htmlentitydefs
import string
import textwrap
def main ():
global title
global wrap_width
global what
global section_number
global sections
sections = []
section_number = 0
title = ""
wrap_width = 75
if len (sys.argv) == 3:
text = file (sys.argv[1]).read ()
what = sys.argv[2]
else:
print "gendoc.py <filename> text|html"
sys.exit (-1)
# remove trailing whitespace
text = re.sub ("(?m)[ \t]+$", "", text)
# remove multiple empty lines
text = re.sub ("([^\n]+)\n{3,}", "\\1\n\n", text)
# extract title (first line)
title_end = str.find (text, "\n\n")
add_title (text[0:title_end])
# extract sections
done = 0
section_heading_start = str.find (text, "\n\n=", title_end)
while not done:
section_heading_end = str.find (text, "\n\n", section_heading_start + 3)
if section_heading_end == -1:
section_head = text[section_heading_start + 2:]
section_text = ""
done = 1
else:
section_head = text[section_heading_start + 2:section_heading_end]
section_end = str.find (text, "\n\n=", section_heading_end)
if section_end == -1:
section_text = text[section_heading_end + 2:]
done = 1
else:
section_text = text[section_heading_end + 2:section_end]
add_section(section_head, section_text)
section_heading_start = section_end
if what == "html":
output_html ()
elif what == "text":
output_text ()
else:
print sections
def output_html ():
global title
global sections
print "<html>"
print "<head>"
print "<title>%s</title>" % title
print "<style>"
print "body {margin-left: 10px; background-color: #fffefd; width: 750px;}"
print "p {margin-left: 20px; }"
print "pre {margin-left: 30px; background-color: #ffefdf}"
print "</style>"
print "</head>"
print "<body>"
for section in sections:
sys.stdout.write (("<a name = \"%i\"" % section["number"]) + "</a>\n")
sys.stdout.write (("<h%i>" % section["level"]) + section["header"] + "</h%i>\n" % section["level"])
for paragraph in section["text"]:
if paragraph["type"] == "code":
text = paragraph["data"]
#replace html special chars
text = re.sub ("&", "&", text)
text = re.sub ("<", "<", text)
text = re.sub (">", ">", text)
sys.stdout.write ("<pre>" + text + "</pre>\n")
elif paragraph["type"] == "list":
list = paragraph["data"]
sys.stdout.write ("<ul>\n")
for item in list:
sys.stdout.write ("<li>" + item + "</li>\n")
sys.stdout.write ("</ul>\n")
elif paragraph["type"] == "text":
text = paragraph["data"]
sys.stdout.write ("<p>" + text + "</p>")
elif paragraph["type"] == "contents":
level = 0
for toc in sections:
while level < toc["level"]:
sys.stdout.write ("<ul>\n")
level += 1
while level > toc["level"]:
sys.stdout.write ("</ul>\n")
level -= 1
sys.stdout.write ("<li><a href=\"#%i\">\n" % toc["number"])
sys.stdout.write (toc["header"])
sys.stdout.write ("</li></a>\n")
while level > 0:
sys.stdout.write ("</ul>\n")
level -= 1
elif paragraph["type"] == "img":
img = string.split (paragraph["data"])
if len (img) > 1:
sys.stdout.write ("""<a href="%s">""" % img[1])
sys.stdout.write ("""<img src="%s" />""" % img[0])
if len (img) > 1:
sys.stdout.write ("</a>")
print "</body>"
print "</html>"
def output_text ():
global title
global sections
lines = textwrap.wrap ("This is the text version of the documentation, " +
"which is autogenerated from the HTML version.", wrap_width)
for line in lines:
print line
print
for section in sections:
level = section["level"]
header = section["header"]
if level == 1:
sys.stdout.write ("," + "-" * (wrap_width - 2) + ".\n")
t = "| " + header
t += " " * (wrap_width - len (t) - 2)
sys.stdout.write (t + " |\n")
sys.stdout.write ("`" + "-" * (wrap_width - 2) + "'\n")
sys.stdout.write ("\n")
elif level == 2:
sys.stdout.write ("\n" + header + "\n")
sys.stdout.write ("~" * wrap_width + "\n\n")
else:
sys.stdout.write ("_" * wrap_width + "\n")
sys.stdout.write (header + "\n\n")
for paragraph in section["text"]:
if paragraph["type"] == "list":
list = paragraph["data"]
for item in list:
lines = textwrap.wrap (item, wrap_width - 3)
sys.stdout.write ("\n * " + lines[0] + "\n")
for line in lines[1:]:
sys.stdout.write(" " + line + "\n")
sys.stdout.write ("\n")
elif paragraph["type"] == "text":
text = paragraph["data"]
lines = textwrap.wrap (text, wrap_width)
text = ""
for line in lines:
text += line + "\n"
sys.stdout.write (text)
elif paragraph["type"] == "code":
text = paragraph["data"]
sys.stdout.write (text)
elif paragraph["type"] == "contents":
sys.stdout.write ("Not present in the .txt output.")
sys.stdout.write ("\n")
sys.stdout.write ("\n")
def add_title (text):
global title
title = text
def beautify (text):
global what
if what == "html":
#replace html special chars
text = re.sub ("&", "&", text)
text = re.sub ("<", "<", text)
text = re.sub (">", ">", text)
#replace links
text = re.sub ("(http://\\S+\\w)", "<a href=\"\\1\">\\1</a>", text)
#remove leading and superfluous whitespace
text = re.sub ("\n", " ", text)
text = re.sub (" {2,}", " ", text)
text = re.sub ("^ ", "", text)
return text
def put_list (text):
lines = text.splitlines()
list = []
item = None
for line in lines:
if line[0] == "-":
if item:
list += [beautify(item)]
item = line[1:]
else:
item += line
if item:
list += [beautify(item)]
return list
def put_code (text):
lines = string.split (text, "\n")
text = ""
for line in lines:
if line[0:2] == "+ " or line[0:2] == "++":
line = line[2:]
text += line + "\n"
return text
def put_paragraph (text):
text = beautify (text)
return text
def add_text (text):
text = string.lstrip (text, "\n ")
paragraphs = []
paragraph_start = 0
done = 0
while not done:
paragraph_end = string.find (text, "\n\n", paragraph_start)
if paragraph_end == -1:
done = 1
paragraph = text[paragraph_start:]
else:
paragraph = text[paragraph_start:paragraph_end]
paragraph_start = paragraph_end + 2
if len(paragraph):
if paragraph == "+contents":
paragraphs += [{"type": "contents", "data": 0}]
elif paragraph[:5] == "+img ":
paragraphs += [{"type": "img", "data": paragraph[5:]}]
elif paragraph[0:2] == "+ " or paragraph[0:2] == "++":
paragraphs += [{"type": "code", "data": put_code(paragraph)}]
elif paragraph[0] == "-":
paragraphs += [{"type": "list", "data": put_list(paragraph)}]
else:
paragraphs += [{"type": "text", "data": put_paragraph(paragraph)}]
return paragraphs
def add_section(header, text):
global what
global wrap_width
global sections
global section_number
level = string.count(header, "=")
header = beautify(header[level:])
text = add_text(text)
section = {"level":level, "header":header, "text":text, "number":section_number}
sections += [section]
section_number += 1
return ""
main ()