ref: bc891834b827991be2071d50d8d09519637fc26d
parent: b06a291ce9eb2937623cadb4b854f94faebe4bfa
author: David Turner <[email protected]>
date: Tue May 8 03:48:33 EDT 2001
* docs/docmaker.py: updated the DocMaker script in order to add command line options (--output,--prefix,--title), fix the erroneous line numbers reported during errors and warnings, and other formatting issues..
--- a/docs/docmaker.py
+++ b/docs/docmaker.py
@@ -1,19 +1,47 @@
#!/usr/bin/env python
#
-# DocMaker is a very simple program used to generate HTML documentation
-# from the source files of the FreeType packages.
+# DocMaker 0.1 (c) 2000-2001 David Turner <[email protected]>
#
-# I should really be using regular expressions to do this, but hey,
-# i'm too lazy right now, and the damn thing seems to work :-)
+# DocMaker is a very simple program used to generate the API Reference
+# of programs by extracting comments from source files, and generating
+# the equivalent HTML documentation.
+#
+# DocMaker is very similar to other tools like Doxygen, with the
+# following differences:
+#
+# - it is written in Python (so it's slow, but easy to maintain and
+# improve)
+#
+# - the comment syntax used by DocMaker is simpler and makes for
+# clearer comments
+#
+# Of course, it doesn't have all the goodies of most similar tools,
+# (e.g. C++ class hierarchies), but hey, it's only 2000 lines of
+# python
+#
+# DocMaker is mainly used to generate the API references of several
+# FreeType packages.
+#
# - David
#
-import fileinput, sys, string, glob
+import fileinput, sys, os, string, glob, getopt
# The Project's title. This can be overridden from the command line with
-# an option.
-project_title = "Project"
+# the options "-t" or "--title"
+project_title = "Project"
+# The project's filename prefix. This can be set from the command line with
+# the options "-p" or "--prefix"
+#
+project_prefix = ""
+
+# The project's documentation output directory. This can be set from the
+# command line with the options "-o" or "--output"
+#
+output_dir = None
+
+
# The following defines the HTML header used by all generated pages.
#
html_header_1 = """\
@@ -22,7 +50,7 @@
<title>"""
html_header_2= """ API Reference</title>
-<basefont face="Georgia, Arial, Helvetica, Geneva">
+<basefont face="Verdana,Geneva,Arial,Helvetica">
<style content="text/css">
P { text-align=justify }
H1 { text-align=center }
@@ -43,6 +71,7 @@
#
html_header = html_header_1 + project_title + html_header_2 + project_title + html_header_3
+
# The HTML footer used by all generated pages.
#
html_footer = """\
@@ -141,7 +170,7 @@
# Translate a single line of source to HTML. This will convert
# a "<" into "<.", ">" into ">.", etc.
#
-def html_format( line )
+def html_format( line ):
result = string.replace( line, "<", "<." )
result = string.replace( line, ">", ">." )
result = string.replace( line, "&", "&." )
@@ -148,6 +177,43 @@
return result
+# open the standard output to a given project documentation file
+# use "output_dir" to determine the filename location, when necessary
+# and save the old stdout in a tuple that is returned by this function
+#
+def open_output( filename ):
+ global output_dir
+
+ if output_dir and output_dir != "":
+ filename = output_dir + os.sep + filename
+
+ old_stdout = sys.stdout
+ new_file = open( filename, "w" )
+ sys.stdout = new_file
+
+ return ( new_file, old_stdout )
+
+
+# close the output that was returned by "close_output"
+#
+#
+def close_output( output ):
+ output[0].close()
+ sys.stdout = output[1]
+
+# check output directoy
+#
+def check_output( ):
+ global output_dir
+ if output_dir:
+ if output_dir != "":
+ if not os.path.isdir( output_dir ):
+ sys.stderr.write( "argument '"+output_dir+"' is not a valid directory" )
+ sys.exit(2)
+ else:
+ output_dir = None
+
+
# The FreeType 2 reference is extracted from the source files. These
# contain various comment blocks that follow one of the following formats:
#
@@ -346,11 +412,12 @@
# we need to find non-alphanumeric characters
#
- i = len( word )
- while i > 0 and not word[i - 1] in alphanum:
- i = i - 1
-
- if i > 0:
+ l = len( word )
+ i = 0
+ while i < l and word[i] in alphanum:
+ i = i + 1
+
+ if i < l:
extra = word[i :]
word = word[0 : i]
@@ -363,7 +430,7 @@
if cursor + len( word ) + 1 > max_width:
print html_format( line )
cursor = 0
- line = ""
+ line = ""
line = line + word
if not extra:
@@ -413,7 +480,7 @@
# DocContent is used to store the content of a given marker.
#
# The "self.items" list contains (field,elements) records, where "field"
-# corresponds to a given structure fields or function parameter (indicated
+# corresponds to a given structure field or function parameter (indicated
# by a "::"), or NULL for a normal section of text/code.
#
# Hence, the following example:
@@ -871,7 +938,7 @@
# section
#
if self.elements.has_key( block.name ):
- self.print_error( "duplicate element definition for " +
+ block.print_error( "duplicate element definition for " +
"'" + block.name + "' " +
"in section " +
"'" + self.name + "'\n" +
@@ -1052,23 +1119,21 @@
def dump_html_sections( self ):
- old_stdout = sys.stdout
-
+
for section in self.sections.values():
if section.filename:
- new_file = open( section.filename, "w" )
- sys.stdout = new_file
+ output = open_output( section.filename )
+
section.dump_html( self.identifiers )
- new_file.close()
-
- sys.stdout = old_stdout
+
+ close_output( output )
+
def dump_html_index( self ):
- old_stdout = sys.stdout
- new_file = open( self.index_filename, "w" )
- sys.stdout = new_file
+ output = open_output( self.index_filename )
+
num_columns = 3
total = len( self.index )
line = 0
@@ -1096,7 +1161,7 @@
print "</tr></table></center>"
print html_footer
- sys.stdout = old_stdout
+ close_output( output )
@@ -1190,9 +1255,7 @@
def dump_toc_html( self ):
# dump an html table of contents
#
- old_stdout = sys.stdout
- new_file = open( self.section_list.toc_filename, "w" )
- sys.stdout = new_file
+ output = open_output( self.section_list.toc_filename )
print html_header
@@ -1240,7 +1303,7 @@
print html_footer
- sys.stdout = old_stdout
+ close_output( output )
def dump_index_html( self ):
@@ -1317,13 +1380,16 @@
list.append( block )
-def make_block_list():
+def make_block_list( args = None ):
"""parse a file and extract comments blocks from it"""
file_list = []
# sys.stderr.write( repr( sys.argv[1 :] ) + '\n' )
- for pathname in sys.argv[1 :]:
+ if not args:
+ args = sys.argv[1:]
+
+ for pathname in args:
if string.find( pathname, '*' ) >= 0:
newpath = glob.glob( pathname )
newpath.sort() # sort files -- this is important because
@@ -1358,6 +1424,7 @@
source = []
state = 0
+ fileinput.close()
for line in fileinput.input( file_list ):
l = len( line )
if l > 0 and line[l - 1] == '\012':
@@ -1399,7 +1466,7 @@
block = []
source = []
format = 1
- lineno = fileinput.lineno()
+ lineno = fileinput.filelineno()
elif i == l - 1 and line2[i] == '/':
# this is '/**' followed by any number of '*', followed
@@ -1408,7 +1475,7 @@
block = []
source = []
format = 2
- lineno = fileinput.lineno()
+ lineno = fileinput.filelineno()
##############################################################
#
@@ -1507,38 +1574,72 @@
print "---------the end-----------------------"
+def usage():
+ print "\nDocMaker 0.1 Usage information\n"
+ print " docmaker [options] file1 [ file2 ... ]\n"
+ print "using the following options:\n"
+ print " -h : print this page"
+ print " -t : set project title, as in '-t \"My Project\"'"
+ print " -o : set output directory, as in '-o mydir'"
+ print " -p : set documentation prefix, as in '-p ft2'"
+ print ""
+ print " --title : same as -t, as in '--title=\"My Project\"'"
+ print " --output : same as -o, as in '--output=mydir'"
+ print " --prefix : same as -p, as in '--prefix=ft2'"
+
+
def main( argv ):
"""main program loop"""
+ global output_dir, project_title, project_prefix
+ global html_header, html_header1, html_header2, html_header3
+
+ try:
+ opts, args = getopt.getopt( sys.argv[1:], "ht:o:p:", [ "help", "title=", "output=", "prefix=" ] )
+
+ except getopt.GetoptError:
+ usage()
+ sys.exit(2)
+
+ if args == []:
+ usage()
+ sys.exit(1)
+
+ # process options
+ project_title = "Project"
+ project_prefix = None
+ output_dir = None
+
+ for opt in opts:
+ if opt[0] in ( "-h", "--help" ):
+ usage()
+ sys.exit(0)
+
+ if opt[0] in ( "-t", "--title" ):
+ project_title = opt[1]
+
+ if opt[0] in ( "-o", "--output" ):
+ output_dir = opt[1]
+
+ if opt[0] in ( "-p", "--prefix" ):
+ project_prefix = opt[1]
+
+ html_header = html_header_1 + project_title + html_header_2 + project_title + html_header_3
+ check_output( )
+
# we begin by simply building a list of DocBlock elements
- #
- sys.stderr.write( "extracting comment blocks from sources...\n" )
- list = make_block_list()
+ list = make_block_list( args )
# now, sort the blocks into sections
- #
document = DocDocument()
for block in list:
document.append_block( block )
- document.prepare_files( "ft2" )
+ document.prepare_files( project_prefix )
document.dump_toc_html()
document.dump_sections_html()
document.dump_index_html()
-
-## section_list = DocSectionList()
-## for block in list:
-## section_list.append_block( block )
-##
-## section_list.prepare_files( "ft2" )
-
-## # dump the section list TOC and sections
-## #
-## section_list.dump_html_toc()
-## section_list.dump_html_sections()
-## section_list.dump_html_index()
-
# if called from the command line
#