1
0
Fork 0

python script which generates $FGROOT/Nasal API documentation

This commit is contained in:
adrian 2012-01-30 21:02:19 +02:00 committed by ThorstenB
parent 9264243a71
commit 39e399d8ec

276
scripts/python/nasal_api.py Executable file
View file

@ -0,0 +1,276 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (C) 2012 Adrian Musceac
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os, sys, glob
import io
import re, string
"""Script which generates an API documentation file for Nasal libraries
located inside $FGROOT/Nasal/
Usage: nasal_api.py parse [path to $FGROOT/Nasal/]
Or configure the local path below, and ommit the path in the console.
The API doc in HTML format is generated in the current working directory"""
########### Local $FGROOT/Nasal/ path ##########
NASAL_PATH="../fgfs/fgdata/Nasal/"
def get_files(nasal_dir):
if nasal_dir[-1]!='/':
nasal_dir+='/'
try:
os.stat(nasal_dir)
except:
print "The path does not exist"
sys.exit()
top_level = []
modules = []
top_namespaces = []
files_list = os.listdir(nasal_dir)
for f in files_list:
if f.find(".nas")!=-1:
top_level.append(f)
continue
if os.path.isdir(nasal_dir + f):
modules.append(f)
top_level.sort()
modules.sort()
if len(top_level) ==0:
print "This does not look like the correct $FGROOT/Nasal path"
sys.exit()
if len(modules)==0:
print "Warning: could not find any submodules"
for f in top_level:
namespace=f.replace(".nas","")
functions=parse_file(nasal_dir + f)
top_namespaces.append([namespace,functions])
for m in modules:
files=glob.glob(nasal_dir+m+"/*.nas")
for f in files:
functions=parse_file(f)
top_namespaces.append([m,functions])
output_text(top_namespaces,modules)
def output_text(top_namespaces,modules):
fw=open('./nasal_api.html','wb')
buf='<html><head>\
<title>Nasal API</title>\
<script type="text/javascript">\
</script></head><body style="width:1024px;">'
buf+='<h1 style="padding-left:20px;display:block;color:#fff;background-color:#555588;">Nasal $FGROOT Library</h1>\n<div style="float:right;">&nbsp;'
buf+='<h2 style="font-size:14px;height:450px;width:250px;overflow:scroll;display:block;position:fixed;top:20px;right:20px;background-color:#8888AC;border:1px solid black;">\n'
done=[]
for namespace in top_namespaces:
color='0000cc'
if namespace[0] in modules:
color='cc0000'
if namespace[0] not in done:
buf+='<a style="margin-left:30px;display:block;float:left;color:'+color+'" href="#'+namespace[0]+'">'+namespace[0]+'</a>&nbsp;<br/>\n'
done.append(namespace[0])
buf+='</h2></div>\n'
done2=[]
for namespace in top_namespaces:
if namespace[0] not in done2:
buf+='<div style="background-color:#eee;clear:left;margin-top:20px;">\n'
buf += '<h2 style="padding-left:20px;color:#fff;background-color:#8888AC"><a name="'+namespace[0]+'">'+namespace[0]+'</a></h2>\n'
done2.append(namespace[0])
for functions in namespace[1]:
class_func=functions[0].split('.')
if len(class_func)>1:
f_name=''
if class_func[1].find('_')==0:
f_name='<font color="#0000cc">'+class_func[1]+'</font>'
else:
f_name=class_func[1]
if class_func[1]!='':
buf+= '<div><h4 style="padding-left:20px;background-color:#eee;color:#000033"><a onclick="c();"><b>'\
+namespace[0]+'</b>'+ "." + '<b><i>'+class_func[0]+'</i></b>'+'<b>.'+f_name+'</b>'+' ( <font color="#cc0000">'+ functions[1]+ '</font> )' +'</h4>\n'
else:
buf+= '<div><h4 style="padding-left:20px;background-color:#eee;color:#000033"><a onclick="c();"><b>'\
+namespace[0]+'</b>'+ "." + '<b><i><u><font color="#000000">'+class_func[0]+'</font></u></i></b>' +'</h4>\n'
else:
if functions[0].find('_')==0:
f_name='<font color="#0000cc">'+functions[0]+'</font>'
else:
f_name=functions[0]
buf+= '<div><h4 style="padding-left:20px;background-color:#eee;color:#000033"><a onclick="c();"><b>'\
+namespace[0]+'</b>'+ "." + '<b>'+f_name+'</b>'+ ' ( <font color="#cc0000">'+ functions[1]+ '</font> )' +'</h4>\n'
for comment in functions[2]:
if comment.find('=====')!=-1:
buf+='<hr style="margin-left:30px;margin-right:30px;"/>'
else:
buf+= '<div id="comments" style="padding-left:40px;display:inline;font-size:12px;">'+comment.replace('#','').replace('<','&lt;').replace('>','&gt;')+'</div><br/>\n'
buf+='</div>\n'
if namespace[0] not in done2:
buf+='</div>\n'
buf+='</body></html>'
fw.write(buf)
fw.close()
def parse_file(filename):
fr=open(filename,'rb')
content=fr.readlines()
i=0
retval=[]
classname=""
for line in content:
match=re.search('^var\s+([A-Za-z0-9_-]+)\s*=\s*func\s*\(?([A-Za-z0-9_\s,=.\n-]*)\)?',line)
if match!=None:
func_name=match.group(1)
comments=[]
param=match.group(2)
if(line.find(')')==-1 and line.find('(')!=-1):
k=i+1
while(content[k].find(')')==-1):
param+=content[k].rstrip('\n')
k+=1
param+=content[k].split(')')[0]
j=i-1
count=0
while ( j>i-35 and j>-1):
if count>3:
break
if len(content[j])<2:
j-=1
count+=1
continue
if re.search('^\s*#',content[j])!=None:
comments.append(content[j].rstrip('\n'))
j-=1
else:
break
if(len(comments)>1):
comments.reverse()
retval.append((func_name, param,comments))
i+=1
continue
match3=re.search('^var\s*([A-Za-z0-9_-]+)\s*=\s*{\s*(\n|})',line)
if match3!=None:
classname=match3.group(1)
comments=[]
j=i-1
count=0
while ( j>i-35 and j>-1):
if count>3:
break
if len(content[j])<2:
j-=1
count+=1
continue
if re.search('^\s*#',content[j])!=None:
comments.append(content[j].rstrip('\n'))
j-=1
else:
break
if(len(comments)>1):
comments.reverse()
retval.append((classname+'.', '',comments))
i+=1
continue
match2=re.search('^\s*([A-Za-z0-9_-]+)\s*:\s*func\s*\(?([A-Za-z0-9_\s,=.\n-]*)\)?',line)
if match2!=None:
func_name=match2.group(1)
comments=[]
param=match2.group(2)
if(line.find(')')==-1 and line.find('(')!=-1):
k=i+1
while(content[k].find(')')==-1):
param+=content[k].rstrip('\n')
k+=1
param+=content[k].split(')')[0]
j=i-1
count=0
while ( j>i-35 and j>-1):
if count>3:
break
if len(content[j])<2:
j-=1
count+=1
continue
if re.search('^\s*#',content[j])!=None:
comments.append(content[j].rstrip('\n'))
j-=1
else:
break
if(len(comments)>1):
comments.reverse()
if classname =='':
continue
retval.append((classname+'.'+func_name, param,comments))
i+=1
continue
match4=re.search('^([A-Za-z0-9_-]+)\.([A-Za-z0-9_-]+)\s*=\s*func\s*\(?([A-Za-z0-9_\s,=\n.-]*)\)?',line)
if match4!=None:
classname=match4.group(1)
func_name=match4.group(2)
comments=[]
param=match4.group(3)
if(line.find(')')==-1 and line.find('(')!=-1):
k=i+1
while(content[k].find(')')==-1):
param+=content[k].rstrip('\n')
k+=1
param+=content[k].split(')')[0]
j=i-1
count=0
while ( j>i-35 and j>-1):
if count>3:
break
if len(content[j])<2:
j-=1
count+=1
continue
if re.search('^\s*#',content[j])!=None:
comments.append(content[j].rstrip('\n'))
j-=1
else:
break
if(len(comments)>1):
comments.reverse()
retval.append((classname+'.'+func_name, param,comments))
i+=1
continue
i+=1
return retval
if __name__ == "__main__":
if len(sys.argv) <2:
print 'Usage: nasal_api.py parse [path to $FGROOT/Nasal/]'
sys.exit()
else:
if sys.argv[1]=='parse':
if len(sys.argv) <3:
nasal_path=NASAL_PATH
else:
nasal_path=sys.argv[2]
get_files(nasal_path)
else:
print 'Usage: nasal_api.py parse [path to $FGROOT/Nasal/]'
sys.exit()