formatting

This commit is contained in:
Werner Lemberg 2008-05-28 06:39:33 +00:00
parent c94fa6699c
commit 8f7d17bfe3
7 changed files with 63 additions and 91 deletions

View File

@ -45,7 +45,7 @@ re_identifier = re.compile( r'(\w*)' )
# The object is filled line by line by the parser; it strips the leading
# "margin" space from each input line before storing it in 'self.lines'.
#
class DocCode:
class DocCode:
def __init__( self, margin, lines ):
self.lines = []
@ -57,15 +57,15 @@ class DocCode:
l = l[margin:]
self.lines.append( l )
def dump( self, prefix = "", width=60 ):
def dump( self, prefix = "", width = 60 ):
lines = self.dump_lines( 0, width )
for l in lines:
print prefix + l
def dump_lines( self, margin=0, width=60 ):
def dump_lines( self, margin = 0, width = 60 ):
result = []
for l in self.lines:
result.append( " "*margin + l )
result.append( " " * margin + l )
return result
@ -76,7 +76,7 @@ class DocCode:
#
# 'self.words' contains the list of words that make up the paragraph
#
class DocPara:
class DocPara:
def __init__( self, lines ):
self.lines = None
@ -90,7 +90,7 @@ class DocPara:
for l in lines:
print prefix + l
def dump_lines( self, margin=0, width = 60 ):
def dump_lines( self, margin = 0, width = 60 ):
cur = "" # current line
col = 0 # current width
result = []
@ -98,10 +98,10 @@ class DocPara:
for word in self.words:
ln = len( word )
if col > 0:
ln = ln+1
ln = ln + 1
if col + ln > width:
result.append( " "*margin + cur )
result.append( " " * margin + cur )
cur = word
col = len( word )
else:
@ -111,7 +111,7 @@ class DocPara:
col = col + ln
if col > 0:
result.append( " "*margin + cur )
result.append( " " * margin + cur )
return result
@ -123,17 +123,17 @@ class DocPara:
# DocCode objects. Each DocField also has an optional "name" which is used
# when the object corresponds to a field or value definition
#
class DocField:
class DocField:
def __init__( self, name, lines ):
self.name = name # can be None for normal paragraphs/sources
self.items = [] # list of items
self.items = [] # list of items
mode_none = 0 # start parsing mode
mode_code = 1 # parsing code sequences
mode_para = 3 # parsing normal paragraph
mode_none = 0 # start parsing mode
mode_code = 1 # parsing code sequences
mode_para = 3 # parsing normal paragraph
margin = -1 # current code sequence indentation
margin = -1 # current code sequence indentation
cur_lines = []
# now analyze the markup lines to see if they contain paragraphs,
@ -141,11 +141,10 @@ class DocField:
#
start = 0
mode = mode_none
for l in lines:
for l in lines:
# are we parsing a code sequence ?
if mode == mode_code:
m = re_code_end.match( l )
if m and len( m.group( 1 ) ) <= margin:
# that's it, we finised the code sequence
@ -170,7 +169,6 @@ class DocField:
# switch to code extraction mode
margin = len( m.group( 1 ) )
mode = mode_code
else:
if not string.split( l ) and cur_lines:
# if the line is empty, we end the current paragraph,
@ -187,7 +185,6 @@ class DocField:
# unexpected end of code sequence
code = DocCode( margin, cur_lines )
self.items.append( code )
elif cur_lines:
para = DocPara( cur_lines )
self.items.append( para )
@ -204,9 +201,10 @@ class DocField:
p.dump( prefix )
first = 0
def dump_lines( self, margin=0, width=60 ):
def dump_lines( self, margin = 0, width = 60 ):
result = []
nl = None
for p in self.items:
if nl:
result.append( "" )
@ -224,7 +222,7 @@ re_field = re.compile( r"\s*(\w*|\w(\w|\.)*\w)\s*::" )
class DocMarkup:
class DocMarkup:
def __init__( self, tag, lines ):
self.tag = string.lower( tag )
@ -248,7 +246,7 @@ class DocMarkup:
field = m.group( 1 ) # record field name
ln = len( m.group( 0 ) )
l = " "*ln + l[ln:]
l = " " * ln + l[ln:]
cur_lines = [l]
else:
cur_lines.append( l )
@ -260,7 +258,6 @@ class DocMarkup:
def get_name( self ):
try:
return self.fields[0].items[0].words[0]
except:
return None
@ -270,19 +267,18 @@ class DocMarkup:
for word in self.fields[0].items[0].words:
result = result + " " + word
return result[1:]
except:
return "ERROR"
def dump( self, margin ):
print " "*margin + "<" + self.tag + ">"
print " " * margin + "<" + self.tag + ">"
for f in self.fields:
f.dump( " " )
print " "*margin + "</" + self.tag + ">"
print " " * margin + "</" + self.tag + ">"
class DocChapter:
class DocChapter:
def __init__( self, block ):
self.block = block
@ -298,7 +294,7 @@ class DocChapter:
class DocSection:
class DocSection:
def __init__( self, name = "Other" ):
self.name = name
@ -334,7 +330,7 @@ class DocSection:
class ContentProcessor:
class ContentProcessor:
def __init__( self ):
"""initialize a block content processor"""
@ -395,7 +391,7 @@ class ContentProcessor:
if m:
found = string.lower( m.group( 1 ) )
prefix = len( m.group( 0 ) )
line = " "*prefix + line[prefix:] # remove markup from line
line = " " * prefix + line[prefix:] # remove markup from line
break
# is it the start of a new markup section ?
@ -415,18 +411,18 @@ class ContentProcessor:
def parse_sources( self, source_processor ):
blocks = source_processor.blocks
count = len( blocks )
for n in range( count ):
for n in range( count ):
source = blocks[n]
if source.content:
# this is a documentation comment, we need to catch
# all following normal blocks in the "follow" list
#
follow = []
m = n+1
m = n + 1
while m < count and not blocks[m].content:
follow.append( blocks[m] )
m = m+1
m = m + 1
doc_block = DocBlock( source, follow, self )
@ -447,7 +443,7 @@ class ContentProcessor:
section.reorder()
chap.sections.append( section )
else:
sys.stderr.write( "WARNING: chapter '" +
sys.stderr.write( "WARNING: chapter '" + \
chap.name + "' in " + chap.block.location() + \
" lists unknown section '" + sec + "'\n" )
@ -468,7 +464,7 @@ class ContentProcessor:
class DocBlock:
class DocBlock:
def __init__( self, source, follow, processor ):
processor.reset()
@ -498,15 +494,13 @@ class DocBlock:
except:
pass
# detect new section starts
if self.type == "section":
# detect new section starts
processor.set_section( self.name )
processor.section.add_def( self )
# detect new chapter
elif self.type == "chapter":
# detect new chapter
processor.add_chapter( self )
else:
processor.section.add_block( self )
@ -524,7 +518,7 @@ class DocBlock:
# now strip the leading and trailing empty lines from the sources
start = 0
end = len( source )-1
end = len( source ) - 1
while start < end and not string.strip( source[start] ):
start = start + 1
@ -532,7 +526,7 @@ class DocBlock:
while start < end and not string.strip( source[end] ):
end = end - 1
source = source[start:end+1]
source = source[start:end + 1]
self.code = source

View File

@ -55,10 +55,9 @@ def main( argv ):
global output_dir
try:
opts, args = getopt.getopt( sys.argv[1:],
"hb",
opts, args = getopt.getopt( sys.argv[1:], \
"hb", \
["help", "backup"] )
except getopt.GetoptError:
usage()
sys.exit( 2 )
@ -87,10 +86,13 @@ def main( argv ):
file_list = make_file_list( args )
for filename in file_list:
source_processor.parse_file( filename )
for block in source_processor.blocks:
beautify_block( block )
new_name = filename + ".new"
ok = None
try:
file = open( new_name, "wt" )
for block in source_processor.blocks:

View File

@ -44,10 +44,9 @@ def main( argv ):
global output_dir
try:
opts, args = getopt.getopt( sys.argv[1:],
"ht:o:p:",
opts, args = getopt.getopt( sys.argv[1:], \
"ht:o:p:", \
["help", "title=", "output=", "prefix="] )
except getopt.GetoptError:
usage()
sys.exit( 2 )

View File

@ -14,7 +14,7 @@ from utils import *
# used to output -- you guessed it -- HTML.
#
class Formatter:
class Formatter:
def __init__( self, processor ):
self.processor = processor
@ -41,7 +41,7 @@ class Formatter:
def add_identifier( self, name, block ):
if self.identifiers.has_key( name ):
# duplicate name!
sys.stderr.write( \
sys.stderr.write( \
"WARNING: duplicate definition for '" + name + "' in " + \
block.location() + ", previous definition in " + \
self.identifiers[name].location() + "\n" )
@ -155,7 +155,6 @@ class Formatter:
pass
def section_dump( self, section, section_filename = None ):
output = None
if section_filename:
output = open_output( section_filename )

View File

@ -34,11 +34,10 @@ import fileinput, re, sys, os, string
## note that the 'column' pattern must contain a group that will
## be used to "unbox" the content of documentation comment blocks
##
class SourceBlockFormat:
class SourceBlockFormat:
def __init__( self, id, start, column, end ):
"""create a block pattern, used to recognize special documentation blocks"""
self.id = id
self.start = re.compile( start, re.VERBOSE )
self.column = re.compile( column, re.VERBOSE )
@ -199,7 +198,8 @@ re_source_keywords = re.compile( '''\\b ( typedef |
## (i.e. sources or ordinary comments with no starting
## markup tag)
##
class SourceBlock:
class SourceBlock:
def __init__( self, processor, filename, lineno, lines ):
self.processor = processor
self.filename = filename
@ -233,7 +233,6 @@ class SourceBlock:
def location( self ):
return "(" + self.filename + ":" + repr( self.lineno ) + ")"
# debugging only - not used in normal operations
def dump( self ):
if self.content:
@ -268,7 +267,7 @@ class SourceBlock:
## - normal sources lines, include comments
##
##
class SourceProcessor:
class SourceProcessor:
def __init__( self ):
"""initialize a source processor"""
@ -296,23 +295,20 @@ class SourceProcessor:
for line in fileinput.input( filename ):
# strip trailing newlines, important on Windows machines!
if line[-1] == '\012':
if line[-1] == '\012':
line = line[0:-1]
if self.format == None:
self.process_normal_line( line )
else:
if self.format.end.match( line ):
# that's a normal block end, add it to lines and
# create a new block
self.lines.append( line )
self.add_block_lines()
elif self.format.column.match( line ):
# that's a normal column line, add it to 'lines'
self.lines.append( line )
else:
# humm.. this is an unexpected block end,
# create a new block, but don't process the line

View File

@ -9,7 +9,6 @@ import time
# The following defines the HTML header used by all generated pages.
#
html_header_1 = """\
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
@ -53,28 +52,23 @@ html_header_3=""" API Reference</h1></center>
# The HTML footer used by all generated pages.
#
html_footer = """\
</body>
</html>"""
# The header and footer used for each section.
#
section_title_header = "<center><h1>"
section_title_footer = "</h1></center>"
# The header and footer used for code segments.
#
code_header = '<pre class="colored">'
code_footer = '</pre>'
# Paragraph header and footer.
#
para_header = "<p>"
para_footer = "</p>"
# Block header and footer.
#
block_header = '<table align=center width="75%"><tr><td>'
block_footer_start = """\
</td></tr></table>
@ -91,23 +85,19 @@ block_footer_end = """\
"""
# Description header/footer.
#
description_header = '<table align=center width="87%"><tr><td>'
description_footer = "</td></tr></table><br>"
# Marker header/inter/footer combination.
#
marker_header = '<table align=center width="87%" cellpadding=5><tr bgcolor="#EEEEFF"><td><em><b>'
marker_inter = "</b></em></td></tr><tr><td>"
marker_footer = "</td></tr></table>"
# Source code extracts header/footer.
#
source_header = '<table align=center width="87%"><tr bgcolor="#D6E8FF"><td><pre>\n'
source_footer = "\n</pre></table><br>"
# Chapter header/inter/footer.
#
chapter_header = '<br><table align=center width="75%"><tr><td><h2>'
chapter_inter = '</h2><ul class="empty"><li>'
chapter_footer = '</li></ul></td></tr></table>'
@ -124,7 +114,6 @@ index_footer_end = """\
# source language keyword coloration/styling
#
keyword_prefix = '<span class="keyword">'
keyword_suffix = '</span>'
@ -134,38 +123,34 @@ section_synopsis_footer = ''
# Translate a single line of source to HTML. This will convert
# a "<" into "&lt.", ">" into "&gt.", etc.
#
def html_quote( line ):
result = string.replace( line, "&", "&amp;" )
result = string.replace( line, "&", "&amp;" )
result = string.replace( result, "<", "&lt;" )
result = string.replace( result, ">", "&gt;" )
return result
# same as 'html_quote', but ignores left and right brackets
#
def html_quote0( line ):
return string.replace( line, "&", "&amp;" )
def dump_html_code( lines, prefix = "" ):
# clean the last empty lines
#
l = len( self.lines )
while l > 0 and string.strip( self.lines[l - 1] ) == "":
l = l - 1
# The code footer should be directly appended to the last code
# line to avoid an additional blank line.
#
print prefix + code_header,
for line in self.lines[0 : l+1]:
for line in self.lines[0 : l + 1]:
print '\n' + prefix + html_quote( line ),
print prefix + code_footer,
class HtmlFormatter( Formatter ):
class HtmlFormatter( Formatter ):
def __init__( self, processor, project_title, file_prefix ):
Formatter.__init__( self, processor )
@ -207,7 +192,6 @@ class HtmlFormatter( Formatter ):
def make_html_word( self, word ):
"""analyze a simple word to detect cross-references and styling"""
# look for cross-references
#
m = re_crossref.match( word )
if m:
try:
@ -245,8 +229,8 @@ class HtmlFormatter( Formatter ):
for word in words[1:]:
line = line + " " + self.make_html_word( word )
# convert `...' quotations into real left and right single quotes
line = re.sub( r"(^|\W)`(.*?)'(\W|$)",
r'\1&lsquo;\2&rsquo;\3',
line = re.sub( r"(^|\W)`(.*?)'(\W|$)", \
r'\1&lsquo;\2&rsquo;\3', \
line )
return para_header + line + para_footer
@ -275,7 +259,7 @@ class HtmlFormatter( Formatter ):
def print_html_field( self, field ):
if field.name:
print "<table><tr valign=top><td><p><b>"+field.name+"</b></p></td><td>"
print "<table><tr valign=top><td><p><b>" + field.name + "</b></p></td><td>"
print self.make_html_items( field.items )
@ -294,11 +278,9 @@ class HtmlFormatter( Formatter ):
if name == block_name:
# this is the current block name, if any
result = result + prefix + '<b>' + name + '</b>'
elif re_source_keywords.match( name ):
# this is a C keyword
result = result + prefix + keyword_prefix + name + keyword_suffix
elif self.identifiers.has_key( name ):
# this is a known identifier
block = self.identifiers[name]
@ -318,7 +300,7 @@ class HtmlFormatter( Formatter ):
print "<table cellpadding=3 border=0>"
for field in fields:
if len( field.name ) > 22:
print "<tr valign=top><td colspan=0><b>"+field.name+"</b></td></tr>"
print "<tr valign=top><td colspan=0><b>" + field.name + "</b></td></tr>"
print "<tr valign=top><td></td><td>"
else:
print "<tr valign=top><td><b>" + field.name + "</b></td><td>"
@ -336,7 +318,6 @@ class HtmlFormatter( Formatter ):
# all of them as a single table
#
table_fields.append( field )
else:
if table_fields:
self.print_html_field_list( table_fields )
@ -368,7 +349,7 @@ class HtmlFormatter( Formatter ):
for r in range( rows ):
line = "<tr>"
for c in range( self.columns ):
i = r + c*rows
i = r + c * rows
if i < count:
bname = self.block_index[r + c * rows]
url = self.index_items[bname]
@ -380,7 +361,7 @@ class HtmlFormatter( Formatter ):
print "</table>"
print index_footer_start + \
print index_footer_start + \
self.file_prefix + "toc.html" + \
index_footer_end
@ -418,7 +399,9 @@ class HtmlFormatter( Formatter ):
print chapter_footer
def toc_index( self, index_filename ):
print chapter_header + '<a href="' + index_filename + '">Global Index</a>' + chapter_inter + chapter_footer
print chapter_header + \
'<a href="' + index_filename + '">Global Index</a>' + \
chapter_inter + chapter_footer
def toc_exit( self ):
print self.html_footer
@ -510,7 +493,7 @@ class HtmlFormatter( Formatter ):
def block_exit( self, block ):
print block_footer_start + self.file_prefix + "index.html" + \
block_footer_middle + self.file_prefix + "toc.html" + \
block_footer_middle + self.file_prefix + "toc.html" + \
block_footer_end
def section_exit( self, section ):

View File

@ -83,7 +83,7 @@ def check_output():
if output_dir:
if output_dir != "":
if not os.path.isdir( output_dir ):
sys.stderr.write( "argument" + " '" + output_dir + "' " +
sys.stderr.write( "argument" + " '" + output_dir + "' " + \
"is not a valid directory" )
sys.exit( 2 )
else:
@ -105,7 +105,6 @@ def file_exists( pathname ):
def make_file_list( args = None ):
"""builds a list of input files from command-line arguments"""
file_list = []
# sys.stderr.write( repr( sys.argv[1 :] ) + '\n' )