From 39e399d8ecc031f94a02a51459592fc9cac4d80e Mon Sep 17 00:00:00 2001 From: adrian Date: Mon, 30 Jan 2012 21:02:19 +0200 Subject: [PATCH] python script which generates $FGROOT/Nasal API documentation --- scripts/python/nasal_api.py | 276 ++++++++++++++++++++++++++++++++++++ 1 file changed, 276 insertions(+) create mode 100755 scripts/python/nasal_api.py diff --git a/scripts/python/nasal_api.py b/scripts/python/nasal_api.py new file mode 100755 index 000000000..983cc719f --- /dev/null +++ b/scripts/python/nasal_api.py @@ -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 . + + +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='\ + Nasal API\ + ' + + buf+='

Nasal $FGROOT Library

\n
 ' + buf+='

\n' + done=[] + for namespace in top_namespaces: + color='0000cc' + if namespace[0] in modules: + color='cc0000' + if namespace[0] not in done: + buf+=''+namespace[0]+' 
\n' + done.append(namespace[0]) + buf+='

\n' + done2=[] + for namespace in top_namespaces: + if namespace[0] not in done2: + buf+='
\n' + buf += '

'+namespace[0]+'

\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=''+class_func[1]+'' + else: + f_name=class_func[1] + if class_func[1]!='': + buf+= '

'\ + +namespace[0]+''+ "." + ''+class_func[0]+''+'.'+f_name+''+' ( '+ functions[1]+ ' )' +'

\n' + else: + buf+= '

'\ + +namespace[0]+''+ "." + ''+class_func[0]+'' +'

\n' + else: + if functions[0].find('_')==0: + f_name=''+functions[0]+'' + else: + f_name=functions[0] + buf+= '\n' + if namespace[0] not in done2: + buf+='
\n' + buf+='' + 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()