316 lines
7.3 KiB
Python
Executable file
316 lines
7.3 KiB
Python
Executable file
#!/usr/bin/env python
|
|
#
|
|
# Command line parameter self-documentation tool. Reads comments from
|
|
# the source code in the following form:
|
|
#
|
|
# //!
|
|
# // @arg <extra arguments>
|
|
# // @category Category
|
|
# // @platform <some platform that the parameter is specific to
|
|
# //
|
|
# // Long description of the parameter
|
|
# //
|
|
#
|
|
# something_involving = M_CheckParm("-param");
|
|
#
|
|
# From this, a manpage can be automatically generated of the command
|
|
# line parameters.
|
|
|
|
import sys
|
|
import re
|
|
import glob
|
|
|
|
class Category:
|
|
def __init__(self, description):
|
|
self.description = description
|
|
self.params = []
|
|
|
|
def add_param(self, param):
|
|
self.params.append(param)
|
|
|
|
# Find the maximum width of a parameter in this category
|
|
|
|
def paramtext_width(self):
|
|
w = 0
|
|
|
|
for p in self.params:
|
|
pw = len(p.name) + 5
|
|
|
|
if p.args:
|
|
pw += len(p.args)
|
|
|
|
if pw > w:
|
|
w = pw
|
|
|
|
return w
|
|
|
|
# Plain text output
|
|
|
|
def plaintext_output(self):
|
|
result = "=== %s ===\n\n" % self.description
|
|
|
|
self.params.sort()
|
|
|
|
w = self.paramtext_width()
|
|
|
|
for p in self.params:
|
|
result += p.plaintext_output(w)
|
|
|
|
result = result.rstrip() + "\n"
|
|
|
|
return result
|
|
|
|
def manpage_output(self):
|
|
result = ".SH " + self.description.upper() + "\n"
|
|
|
|
self.params.sort()
|
|
|
|
for p in self.params:
|
|
result += ".TP\n"
|
|
result += p.manpage_output()
|
|
|
|
return result
|
|
|
|
def wiki_output(self):
|
|
result = "=== %s ===\n" % self.description
|
|
|
|
self.params.sort()
|
|
|
|
for p in self.params:
|
|
result += "; " + p.wiki_output() + "\n"
|
|
|
|
return result
|
|
|
|
categories = {
|
|
None: Category("General options"),
|
|
"video": Category("Display options"),
|
|
"demo": Category("Demo options"),
|
|
"net": Category("Networking options"),
|
|
"mod": Category("Dehacked and WAD merging"),
|
|
"compat": Category("Compatibility"),
|
|
}
|
|
|
|
class Parameter:
|
|
def __cmp__(self, other):
|
|
if self.name < other.name:
|
|
return -1
|
|
else:
|
|
return 1
|
|
|
|
def __init__(self):
|
|
self.text = ""
|
|
self.name = ""
|
|
self.args = None
|
|
self.platform = None
|
|
self.category = None
|
|
|
|
def add_text(self, text):
|
|
if len(text) <= 0:
|
|
pass
|
|
elif text[0] == "@":
|
|
match = re.match('@(\S+)\s+(.*)', text)
|
|
|
|
if not match:
|
|
raise "Malformed option line: %s" % text
|
|
|
|
option_type = match.group(1)
|
|
data = match.group(2)
|
|
|
|
if option_type == "arg":
|
|
self.args = data
|
|
elif option_type == "platform":
|
|
self.platform = data
|
|
elif option_type == "category":
|
|
self.category = data
|
|
else:
|
|
raise "Unknown option type '%s'" % option_type
|
|
|
|
else:
|
|
self.text += text + " "
|
|
|
|
def manpage_output(self):
|
|
result = self.name
|
|
|
|
if self.args:
|
|
result += " " + self.args
|
|
|
|
result = '\\fB' + result + '\\fR'
|
|
|
|
result += "\n"
|
|
|
|
if self.platform:
|
|
result += "[%s only] " % self.platform
|
|
|
|
escaped = re.sub('\\\\', '\\\\\\\\', self.text)
|
|
|
|
result += escaped + "\n"
|
|
|
|
return result
|
|
|
|
def wiki_output(self):
|
|
result = self.name
|
|
|
|
if self.args:
|
|
result += " " + self.args
|
|
|
|
result += ": "
|
|
|
|
result += self.text
|
|
|
|
if self.platform:
|
|
result += "'''(%s only)'''"
|
|
|
|
return result
|
|
|
|
def plaintext_output(self, w):
|
|
|
|
# Build the first line, with the argument on
|
|
|
|
line = " " + self.name
|
|
if self.args:
|
|
line += " " + self.args
|
|
|
|
# pad up to the plaintext width
|
|
|
|
line += " " * (w - len(line))
|
|
|
|
# Build the description text
|
|
|
|
description = self.text
|
|
|
|
if self.platform:
|
|
description += " (%s only)" % self.platform
|
|
|
|
# Build the complete text for the argument
|
|
# Split the description into words and add a word at a time
|
|
|
|
result = ""
|
|
for word in re.split('\s+', description):
|
|
|
|
# Break onto the next line?
|
|
|
|
if len(line) + len(word) + 1 > 75:
|
|
result += line + "\n"
|
|
line = " " * w
|
|
|
|
# Add another word
|
|
|
|
line += word + " "
|
|
|
|
result += line + "\n\n"
|
|
|
|
return result
|
|
|
|
def process_file(file):
|
|
f = open(file)
|
|
|
|
try:
|
|
param = None
|
|
waiting_for_checkparm = False
|
|
|
|
for line in f:
|
|
line = line.rstrip()
|
|
|
|
# Currently reading a doc comment?
|
|
|
|
if param:
|
|
# End of doc comment
|
|
|
|
if not re.match('\s*//', line):
|
|
waiting_for_checkparm = True
|
|
|
|
# Waiting for the M_CheckParm call that contains the
|
|
# name of the parameter we are documenting?
|
|
|
|
if waiting_for_checkparm:
|
|
match = re.search('M_CheckParm\s*\(\s*"(.*?)"\s*\)', line)
|
|
|
|
if match:
|
|
# Found the name! Finished documenting this
|
|
# parameter.
|
|
|
|
param.name = match.group(1)
|
|
categories[param.category].add_param(param)
|
|
param = None
|
|
|
|
else:
|
|
# More documentation text
|
|
|
|
munged_line = re.sub('\s*\/\/\s*', '', line, 1)
|
|
munged_line = re.sub('\s*$', '', munged_line)
|
|
param.add_text(munged_line)
|
|
|
|
# Check for start of a doc comment
|
|
|
|
if re.search("//!", line):
|
|
param = Parameter()
|
|
waiting_for_checkparm = False
|
|
finally:
|
|
f.close()
|
|
|
|
def process_files(dir):
|
|
# Process all C source files.
|
|
|
|
files = glob.glob(dir + "/*.c")
|
|
|
|
for file in files:
|
|
process_file(file)
|
|
|
|
def print_file_contents(file):
|
|
f = open(file)
|
|
|
|
try:
|
|
for line in f:
|
|
print line.rstrip()
|
|
|
|
finally:
|
|
f.close()
|
|
|
|
def manpage_output(dir):
|
|
|
|
process_files(dir)
|
|
|
|
print_file_contents("header")
|
|
|
|
print categories[None].manpage_output()
|
|
|
|
for c in categories:
|
|
if c != None:
|
|
print categories[c].manpage_output()
|
|
|
|
print_file_contents("footer")
|
|
|
|
def wiki_output(dir):
|
|
process_files(dir)
|
|
|
|
print categories[None].wiki_output()
|
|
|
|
for c in categories:
|
|
if c != None:
|
|
print categories[c].wiki_output()
|
|
|
|
def plaintext_output(dir):
|
|
process_files(dir)
|
|
|
|
print "== Command line parameters =="
|
|
print
|
|
print "This is a list of the command line parameters supported by "
|
|
print "Chocolate Doom. A number of additional parameters are supported "
|
|
print "in addition to those present in Vanilla Doom. "
|
|
print
|
|
|
|
print categories[None].plaintext_output()
|
|
|
|
for c in categories:
|
|
if c != None:
|
|
print categories[c].plaintext_output()
|
|
|
|
if len(sys.argv) > 2 and sys.argv[1] == "-m":
|
|
manpage_output(sys.argv[2])
|
|
elif len(sys.argv) > 2 and sys.argv[1] == "-w":
|
|
wiki_output(sys.argv[2])
|
|
elif len(sys.argv) > 2 and sys.argv[1] == "-p":
|
|
plaintext_output(sys.argv[2])
|
|
else:
|
|
print "%s [ -m | -w | -p ] <directory>" % sys.argv[0]
|
|
|