24from optparse
import OptionParser
29 Normalizes whitespace in text.
36 return s.replace(
"\n",
" ").strip()
39CXX_NAMESPACE_RE = re.compile(
r'[_a-zA-Z][_0-9a-zA-Z]*::')
42 Removes C++ name qualifications from some definitions.
50 >>>
fix_definition(
"void(* _GeanyObjectClass::project_open) (GKeyFile *keyfile)")
51 'void(* project_open) (GKeyFile *keyfile)'
54 return CXX_NAMESPACE_RE.sub(
r"", s)
63 def cb(self, type, str):
65 words = str.split(
" ", 2)
67 elif (type ==
"return"):
69 elif (type ==
"since"):
70 self.
sincesince = str.rstrip()
71 elif type
in (
"geany:nullable",
77 self.
annotannot.append(type.split(
":")[1])
78 elif type
in (
"geany:array",
82 type = type.split(
":")[1]
85 self.
annotannot.append(
"%s%s" % (type, str))
88 elif type
in (
"a",
"c")
and str
in (
"NULL",
"TRUE",
"FALSE"):
106 from lxml.etree
import tostring
107 from itertools
import chain
108 parts = ([node.text] +
109 list(chain(*([c.text, tostring(c, encoding=
'unicode'), c.tail]
for c
in node.getchildren()))) +
112 return "".join(
filter(
None, parts))
115 from lxml.etree
import tostring
116 arr = [
"",
"|[<!-- language=\"C\" -->"]
117 for l
in xml.getchildren():
118 if (l.tag ==
"codeline"):
122 h = l.find(
"highlight")
124 html = tostring(h, encoding=
'unicode')
125 html = html.replace(
"<sp/>",
" ")
126 arr.append(
" " + tostring(etree.HTML(html), method=
"text", encoding=
'unicode'))
128 return "\n".join(arr)
131 s =
" ".join(map(
lambda x:
"(%s)" % x, self.
atat.annot))
132 return s +
": " if s
else ""
143 return self.
atat.retval
146 return self.
atat.since
153 for n
in xml.getchildren():
154 if n.tag ==
"emphasis":
156 if n.tag ==
"computeroutput":
158 if n.tag ==
"itemizedlist":
160 if n.tag ==
"listitem":
165 s += n.text
if n.text
else ""
166 if n.tag ==
"simplesect":
168 s += ss +
"\n" if ss
else ""
169 if n.tag ==
"programlisting":
171 if n.tag ==
"xrefsect":
173 if n.tag ==
"xreftitle":
175 if n.tag ==
"xrefdescription":
179 if n.tag ==
"linebreak":
184 if n.tag ==
"htmlonly":
188 if n.tag.startswith(
"param"):
205 self.
briefbrief = kwargs.get(
'brief',
"")
206 self.
detaildetail = kwargs.get(
'detail',
"")
207 self.
membersmembers = kwargs.get(
'members', [])
208 self.
sincesince = kwargs.get(
'since',
"")
209 self.
extraextra = kwargs.get(
'extra',
"")
210 self.
retvalretval = kwargs.get(
'retval',
None)
219 self.
briefbrief = proc.process_element(xml)
220 self.
extraextra += proc.get_extra()
224 self.
detaildetail = proc.process_element(xml)
225 self.
extraextra += proc.get_extra()
226 self.
sincesince = proc.get_since()
229 name = xml.find(
"name").text
231 brief = proc.process_element(xml.find(
"briefdescription"))
233 proc.process_element(xml.find(
"detaileddescription"))
237 name = xml.find(
"parameternamelist").find(
"parametername").text
239 brief = proc.process_element(xml.find(
"parameterdescription"))
244 brief = proc.process_element(xml)
250 s.append(
" * %s: %s" % (self.
namename, self.
extraextra))
252 s.append(
" * @%s: %s %s" % (p.name, p.extra, p.brief))
254 s.append(
" * %s" % self.
briefbrief.replace(
"\n",
"\n * "))
256 s.append(
" * %s" % self.
detaildetail.replace(
"\n",
"\n * "))
259 s.append(
" * Returns: %s %s" % (self.
retvalretval.extra, self.
retvalretval.brief))
262 s.append(
" * Since: %s" % self.
sincesince)
271 name = xml.find(
"name").text
280 name = xml.find(
"name").text
281 d =
"typedef enum {\n"
282 for member
in xml.findall(
"enumvalue"):
283 v = member.find(
"initializer")
284 d +=
"\t%s%s,\n" % (member.find(
"name").text,
" "+v.text
if v
is not None else "")
285 d +=
"} %s;\n" % name
288 e.add_brief(xml.find(
"briefdescription"))
289 for p
in xml.findall(
"enumvalue"):
297 name = xml.find(
"compoundname").text
298 d =
"struct %s {\n" % name
299 memberdefs = xml.xpath(
".//sectiondef[@kind='public-attrib']/memberdef")
309 brief = proc.process_element(p.find(
"briefdescription"))
312 if (words[0] ==
"struct"):
314 s =
" ".join(words[1:])
315 d +=
"\t/*< %s >*/\n\t%s;\n" % (
"private" if private
else "public", s)
319 e.add_brief(xml.find(
"briefdescription"))
328 name = xml.find(
"name").text
330 d +=
" " + xml.find(
"argsstring").text +
";"
334 e.add_brief(xml.find(
"briefdescription"))
335 e.add_detail(xml.find(
"detaileddescription"))
336 for p
in xml.xpath(
".//detaileddescription/*/parameterlist[@kind='param']/parameteritem"):
338 x = xml.xpath(
".//detaileddescription/*/simplesect[@kind='return']")
349 parser = OptionParser(usage=
"usage: %prog [options] XML_DIR")
350 parser.add_option(
"--xmldir", metavar=
"DIRECTORY", help=
"Path to Doxygen-generated XML files",
351 action=
"store", dest=
"xml_dir")
352 parser.add_option(
"-d",
"--outdir", metavar=
"DIRECTORY", help=
"Path to Doxygen-generated XML files",
353 action=
"store", dest=
"outdir", default=
".")
354 parser.add_option(
"-o",
"--output", metavar=
"FILE", help=
"Write output to FILE",
355 action=
"store", dest=
"outfile")
356 parser.add_option(
"--sci-output", metavar=
"FILE", help=
"Write output to FILE (only sciwrappers)",
357 action=
"store", dest=
"scioutfile")
358 opts, args = parser.parse_args(args[1:])
362 if not (os.path.exists(xml_dir)):
363 sys.stderr.write(
"invalid xml directory\n")
366 transform = etree.XSLT(etree.parse(os.path.join(xml_dir,
"combine.xslt")))
367 doc = etree.parse(os.path.join(xml_dir,
"index.xml"))
368 root = transform(doc)
374 c_files = root.xpath(
".//compounddef[@kind='file']/compoundname[substring(.,string-length(.)-1)='.c']/..")
375 h_files = root.xpath(
".//compounddef[@kind='file']/compoundname[substring(.,string-length(.)-1)='.h']/..")
378 if not (f.find(
"compoundname").text.endswith(
"private.h")):
379 for n0
in f.xpath(
".//*/memberdef[@kind='typedef' and @prot='public']"):
380 if not (DoxygenProcess.stringify_children(n0.find(
"type")).startswith(
"enum")):
381 e = DoxyTypedef.from_memberdef(n0)
384 for n0
in f.xpath(
".//*/memberdef[@kind='enum' and @prot='public']"):
385 e = DoxyEnum.from_memberdef(n0)
388 for n0
in root.xpath(
".//compounddef[@kind='struct' and @prot='public']"):
389 e = DoxyStruct.from_compounddef(n0)
393 for n0
in f.xpath(
".//*/memberdef[@kind='function' and @prot='public']"):
394 e = DoxyFunction.from_memberdef(n0)
399 outfile =
open(opts.outfile,
"w+")
400 except OSError
as err:
401 sys.stderr.write(
"failed to open \"%s\" for writing (%s)\n" % (opts.outfile, err.strerror))
406 if (opts.scioutfile):
408 scioutfile =
open(opts.scioutfile,
"w+")
409 except OSError
as err:
410 sys.stderr.write(
"failed to open \"%s\" for writing (%s)\n" % (opts.scioutfile, err.strerror))
416 outfile.write(
"/*\n * Automatically generated file - do not edit\n */\n\n")
417 outfile.write(
"#include \"gtkcompat.h\"\n")
418 outfile.write(
"#include \"Scintilla.h\"\n")
419 outfile.write(
"#include \"ScintillaWidget.h\"\n")
420 if (scioutfile != outfile):
421 scioutfile.write(
"/*\n * Automatically generated file - do not edit\n */\n\n")
422 scioutfile.write(
"#include \"gtkcompat.h\"\n")
423 scioutfile.write(
"#include \"Scintilla.h\"\n")
424 scioutfile.write(
"#include \"ScintillaWidget.h\"\n")
428 for e
in filter(
lambda x: x.is_documented(), enums):
429 outfile.write(
"\n\n")
430 outfile.write(e.to_gtkdoc())
431 outfile.write(e.definition)
432 outfile.write(
"\n\n")
437 outfile.write(e.definition)
438 outfile.write(
"\n\n")
441 for e
in filter(
lambda x: x.is_documented(), other):
442 outfile.write(
"\n\n")
443 outfile.write(e.to_gtkdoc())
444 outfile.write(e.definition)
445 outfile.write(
"\n\n")
446 if (e.name.startswith(
"sci_")):
447 if (scioutfile != outfile):
448 scioutfile.write(
"\n\n")
449 scioutfile.write(e.to_gtkdoc())
450 scioutfile.write(e.definition)
451 scioutfile.write(
"\n\n")
453 except BrokenPipeError:
459if __name__ ==
"__main__":
460 sys.exit(
main(sys.argv))
def __init__(self, name, definition, **kwargs)
def add_detail(self, xml)
def add_return(self, xml)
def add_member(self, xml)
def __init__(self, name, brief, extra="")
def from_compounddef(xml, typedefs=[])
def __process_element(self, xml)
def stringify_children(node)
def process_element(self, xml)
def get_program_listing(self, xml)
static int endswith(const char *what, const char *withwhat)