makerst.py 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. #!/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3. import sys
  4. import xml.etree.ElementTree as ET
  5. input_list = []
  6. for arg in sys.argv[1:]:
  7. input_list.append(arg)
  8. if len(input_list) < 1:
  9. print 'usage: makerst.py <classes.xml>'
  10. sys.exit(0)
  11. def validate_tag(elem, tag):
  12. if elem.tag != tag:
  13. print "Tag mismatch, expected '" + tag + "', got " + elem.tag
  14. sys.exit(255)
  15. class_names = []
  16. classes = {}
  17. def ul_string(str,ul):
  18. str+="\n"
  19. for i in range(len(str)-1):
  20. str+=ul
  21. str+="\n"
  22. return str
  23. def make_class_list(class_list, columns):
  24. f = open('class_list.rst', 'wb')
  25. prev = 0
  26. col_max = len(class_list) / columns + 1
  27. print ('col max is ', col_max)
  28. col_count = 0
  29. row_count = 0
  30. last_initial = ''
  31. fit_columns = []
  32. for n in range(0, columns):
  33. fit_columns += [[]]
  34. indexers = []
  35. last_initial = ''
  36. idx = 0
  37. for n in class_list:
  38. col = idx / col_max
  39. if col >= columns:
  40. col = columns - 1
  41. fit_columns[col] += [n]
  42. idx += 1
  43. if n[:1] != last_initial:
  44. indexers += [n]
  45. last_initial = n[:1]
  46. row_max = 0
  47. f.write("\n")
  48. for n in range(0, columns):
  49. if len(fit_columns[n]) > row_max:
  50. row_max = len(fit_columns[n])
  51. f.write("| ")
  52. for n in range(0, columns):
  53. f.write(" | |")
  54. f.write("\n")
  55. f.write("+")
  56. for n in range(0, columns):
  57. f.write("--+-------+")
  58. f.write("\n")
  59. for r in range(0, row_max):
  60. s = '+ '
  61. for c in range(0, columns):
  62. if r >= len(fit_columns[c]):
  63. continue
  64. classname = fit_columns[c][r]
  65. initial = classname[0]
  66. if classname in indexers:
  67. s += '**' + initial + '** | '
  68. else:
  69. s += ' | '
  70. s += '[' + classname + '](class_'+ classname.lower()+') | '
  71. s += '\n'
  72. f.write(s)
  73. for n in range(0, columns):
  74. f.write("--+-------+")
  75. f.write("\n")
  76. def rstize_text(text,cclass):
  77. pos = 0
  78. while True:
  79. pos = text.find('[', pos)
  80. if pos == -1:
  81. break
  82. endq_pos = text.find(']', pos + 1)
  83. if endq_pos == -1:
  84. break
  85. pre_text = text[:pos]
  86. post_text = text[endq_pos + 1:]
  87. tag_text = text[pos + 1:endq_pos]
  88. if tag_text in class_names:
  89. tag_text = make_type(tag_text)
  90. else:
  91. # command
  92. cmd = tag_text
  93. space_pos = tag_text.find(' ')
  94. if cmd.find('html') == 0:
  95. cmd = tag_text[:space_pos]
  96. param = tag_text[space_pos + 1:]
  97. tag_text = param
  98. elif cmd.find('method') == 0:
  99. cmd = tag_text[:space_pos]
  100. param = tag_text[space_pos + 1:]
  101. if param.find('.') != -1:
  102. (class_param, method_param) = param.split('.')
  103. tag_text = ':ref:`'+class_param+'.'+method_param+'<' + class_param.lower() + '_' + method_param + '>`'
  104. else:
  105. tag_text = ':ref:`' + param + '<' + cclass +"_"+ param + '>`'
  106. elif cmd.find('image=') == 0:
  107. tag_text = "" #'![](' + cmd[6:] + ')'
  108. elif cmd.find('url=') == 0:
  109. tag_text = ':ref:`' + cmd[4:] + '<'+cmd[4:]+">`"
  110. elif cmd == '/url':
  111. tag_text = ')'
  112. elif cmd == 'center':
  113. tag_text = ''
  114. elif cmd == '/center':
  115. tag_text = ''
  116. elif cmd == 'br':
  117. tag_text = '\n| '
  118. elif cmd == 'i' or cmd == '/i':
  119. tag_text = '*'
  120. elif cmd == 'b' or cmd == '/b':
  121. tag_text = '**'
  122. elif cmd == 'u' or cmd == '/u':
  123. tag_text = ''
  124. else:
  125. tag_text = ':ref:`' + tag_text + '<class_'+tag_text.lower()+'>`'
  126. text = pre_text + tag_text + post_text
  127. pos = len(pre_text) + len(tag_text)
  128. # tnode = ET.SubElement(parent,"div")
  129. # tnode.text=text
  130. return text
  131. def make_type(t):
  132. global class_names
  133. if t in class_names:
  134. return ':ref:`'+t+'<class_' + t.lower()+'>`'
  135. return t
  136. def make_method(
  137. f,
  138. name,
  139. m,
  140. declare,
  141. cname,
  142. event=False,
  143. pp=None
  144. ):
  145. if (declare or pp==None):
  146. t = '- '
  147. else:
  148. t = ""
  149. ret_type = 'void'
  150. args = list(m)
  151. mdata = {}
  152. mdata['argidx'] = []
  153. for a in args:
  154. if a.tag == 'return':
  155. idx = -1
  156. elif a.tag == 'argument':
  157. idx = int(a.attrib['index'])
  158. else:
  159. continue
  160. mdata['argidx'].append(idx)
  161. mdata[idx] = a
  162. if not event:
  163. if -1 in mdata['argidx']:
  164. t += make_type(mdata[-1].attrib['type'])
  165. else:
  166. t += 'void'
  167. t += ' '
  168. if declare or pp==None:
  169. # span.attrib["class"]="funcdecl"
  170. # a=ET.SubElement(span,"a")
  171. # a.attrib["name"]=name+"_"+m.attrib["name"]
  172. # a.text=name+"::"+m.attrib["name"]
  173. s = ' **'+m.attrib['name']+'** '
  174. else:
  175. s = ':ref:`'+ m.attrib['name']+'<class_' + cname+"_"+m.attrib['name'] + '>` '
  176. s += ' **(**'
  177. argfound = False
  178. for a in mdata['argidx']:
  179. arg = mdata[a]
  180. if a < 0:
  181. continue
  182. if a > 0:
  183. s += ', '
  184. else:
  185. s += ' '
  186. s += make_type(arg.attrib['type'])
  187. if 'name' in arg.attrib:
  188. s += ' ' + arg.attrib['name']
  189. else:
  190. s += ' arg' + str(a)
  191. if 'default' in arg.attrib:
  192. s += '=' + arg.attrib['default']
  193. argfound = True
  194. if argfound:
  195. s += ' '
  196. s += ' **)**'
  197. if 'qualifiers' in m.attrib:
  198. s += ' ' + m.attrib['qualifiers']
  199. # f.write(s)
  200. if (not declare):
  201. if (pp!=None):
  202. pp.append( (t,s) )
  203. else:
  204. f.write("- "+t+" "+s+"\n")
  205. else:
  206. f.write(t+s+"\n")
  207. def make_rst_class(node):
  208. name = node.attrib['name']
  209. f = open("class_"+name.lower() + '.rst', 'wb')
  210. f.write(".. _class_"+name+":\n")
  211. f.write(name + ' \n==========\n')
  212. if 'inherits' in node.attrib:
  213. inh = node.attrib['inherits'].strip()
  214. f.write('**Inherits:** '+make_type(inh)+'\n---------\n')
  215. if 'category' in node.attrib:
  216. f.write('**Category:** ' + node.attrib['category'].strip()
  217. + '\n---------\n')
  218. briefd = node.find('brief_description')
  219. if briefd != None:
  220. f.write('\n Brief Description \n-------\n')
  221. f.write(rstize_text(briefd.text.strip(),name) + '\n')
  222. methods = node.find('methods')
  223. if methods != None and len(list(methods)) > 0:
  224. f.write('\nMember Functions \n---------\n')
  225. ml=[]
  226. for m in list(methods):
  227. make_method(f, node.attrib['name'], m, False,name,False,ml)
  228. longest_t = 0
  229. longest_s = 0
  230. for s in ml:
  231. sl = len(s[0])
  232. if (sl>longest_s):
  233. longest_s=sl
  234. tl = len(s[1])
  235. if (tl>longest_t):
  236. longest_t=tl
  237. sep="+"
  238. for i in range(longest_s+2):
  239. sep+="-"
  240. sep+="+"
  241. for i in range(longest_t+2):
  242. sep+="-"
  243. sep+="+\n"
  244. f.write(sep)
  245. for s in ml:
  246. rt = s[0]
  247. while( len(rt) < longest_s ):
  248. rt+=" "
  249. st = s[1]
  250. while( len(st) < longest_t ):
  251. st+=" "
  252. f.write("| "+rt+" | "+st+" |\n")
  253. f.write(sep)
  254. events = node.find('signals')
  255. if events != None and len(list(events)) > 0:
  256. f.write('\nSignals \n----------\n')
  257. for m in list(events):
  258. make_method(f, node.attrib['name'], m, True,name, True)
  259. members = node.find('members')
  260. if members != None and len(list(members)) > 0:
  261. f.write('\nMember Variables \n--------\n')
  262. for c in list(members):
  263. s = '- '
  264. s += make_type(c.attrib['type']) + ' '
  265. s += '**' + c.attrib['name'] + '**'
  266. if c.text.strip() != '':
  267. s += ' - ' + c.text.strip()
  268. f.write(s + '\n')
  269. constants = node.find('constants')
  270. if constants != None and len(list(constants)) > 0:
  271. f.write('\nNumeric Constants \n------\n')
  272. for c in list(constants):
  273. s = '- '
  274. s += '**' + c.attrib['name'] + '**'
  275. if 'value' in c.attrib:
  276. s += ' = **' + c.attrib['value'] + '**'
  277. if c.text.strip() != '':
  278. s += ' - ' + c.text.strip()
  279. f.write(s + '\n')
  280. descr = node.find('description')
  281. if descr != None and descr.text.strip() != '':
  282. f.write('\nDescription \n-------\n')
  283. f.write(rstize_text(descr.text.strip(),name) + '\n')
  284. methods = node.find('methods')
  285. if methods != None and len(list(methods)) > 0:
  286. f.write('\nMember Function Description \n----------\n')
  287. for m in list(methods):
  288. f.write("\n.. _class_"+name+"_"+m.attrib['name']+":\n")
  289. # f.write(ul_string(m.attrib['name'],"^"))
  290. d = m.find('description')
  291. if d == None or d.text.strip() == '':
  292. continue
  293. #f.write('\n<a name="'+m.attrib['name']+'">' + m.attrib['name'] + '</a>\n------\n')
  294. make_method(f, node.attrib['name'], m, True,name)
  295. f.write('\n')
  296. f.write(rstize_text(d.text.strip(),name))
  297. f.write('\n')
  298. for file in input_list:
  299. tree = ET.parse(file)
  300. doc = tree.getroot()
  301. if 'version' not in doc.attrib:
  302. print "Version missing from 'doc'"
  303. sys.exit(255)
  304. version = doc.attrib['version']
  305. for c in list(doc):
  306. if c.attrib['name'] in class_names:
  307. continue
  308. class_names.append(c.attrib['name'])
  309. classes[c.attrib['name']] = c
  310. class_names.sort()
  311. make_class_list(class_names, 2)
  312. for cn in class_names:
  313. c = classes[cn]
  314. make_rst_class(c)