import sys
-from pyparsing import Word, CharsNotIn, Optional, OneOrMore, ZeroOrMore, Group, Forward, ParseException, Literal, Suppress, replaceWith, StringEnd, lineno, QuotedString
-
-class Argument:
- def __init__(self, s, loc, toks):
- self.str = toks[1]
- def __repr__(self):
- return "[%s]" % self.str
- def __str__(self):
- return self.str
-def argfun(s, loc, toks):
- return Argument(s, loc, toks)
-
-class Parameter:
- def __init__(self, s, loc, toks):
- self.str = toks[0].asList()
- def __repr__(self):
- return '{' + "".join([str(s) for s in self.str]) + '}'
- return "{%s}" % self.str
- def __str__(self):
- return "".join([str(s) for s in self.str])
-def paramfun(s, loc, toks):
- return Parameter(s, loc, toks)
-
-class TexCmd:
- def __init__(self, s, loc, toks):
- self.cmd = str(toks[0])[1:]
- #print 'cmd', self.cmd
- self.args = toks[1].asList()
- self.params = toks[2].asList()
- self.lineno = lineno(loc, s)
- self.filename = None
- def __repr__(self):
- return '\\' + self.cmd + "".join([repr(a) for a in self.args]) + "".join([repr(p) for p in self.params])
-
-class ZeroOrMoreAsList(ZeroOrMore):
- def __init__(self, *args):
- ZeroOrMore.__init__(self, *args)
- def listify(s, loc, toks):
- return [toks]
- self.setParseAction(listify)
-
-backslash = chr(92)
-
-texcmd = Forward()
-filler = CharsNotIn(backslash + '\n')
-filler2 = CharsNotIn(backslash + '\n' + '}')
-
-arg = '[' + CharsNotIn("]") + ']'
-arg.setParseAction(argfun)
-param = Suppress(Literal('{')) + ZeroOrMoreAsList(filler2 | texcmd) + Suppress(Literal('}'))
-param.setParseAction(paramfun)
-texcmd << Word("\\", "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789[]") + ZeroOrMoreAsList(arg) + ZeroOrMoreAsList(param)
-def texcmdfun(s, loc, toks):
- if str(toks[0])[1:] == 'input':
- filename = "../" + toks[2].asList()[0].str[0] + ".tex"
- print 'Now parsing', filename, loc
- return parsefile(filename, lineno(loc, s))
- else:
- return TexCmd(s, loc, toks)
-texcmd.setParseAction(texcmdfun)
-
-#legal = "".join([chr(x) for x in set(range(32, 127)) - set(backslash)])
-#filler = Word(legal)
-document = ZeroOrMore(texcmd | filler) + StringEnd().suppress()
-
-if 0:
- print document.parseString("(represented as \\cvCppCross{Mat}'s)")
- print document.parseString("(represented as \\cvCppCross{Mat \\foo{bar}}'s)")
- sys.exit(0)
-
-def parsefile(filename, startline):
- f = open(filename, "rt")
-
- lines = list(f)
- def uncomment(s):
- if '%' in s:
- return s[:s.index('%')] + '\n'
- else:
- return s
-
- lines = [uncomment(l) for l in lines]
- print len(lines), "lines"
-
- docstr = "".join(lines).replace('\\_', '_')
- # document.setFailAction(None)
- try:
- r = document.parseString(docstr)
- for x in r:
- if isinstance(x, TexCmd) and not x.filename:
- x.filename = filename
- return r
- except ParseException, pe:
- print 'Fatal problem at %s line %d col %d' % (filename, pe.lineno, pe.col)
- print pe.line
- sys.exit(1)
-
-fulldoc = parsefile(sys.argv[1], 0)
-
-# Filter on target language
-def preprocess_conditionals(fd, conditionals):
- r = []
- ifstack = []
- for x in fd:
- if isinstance(x, TexCmd):
- ll = x.cmd.rstrip()
- loc = (x.filename, x.lineno)
- if ll.startswith("if"):
- # print " " * len(ifstack), '{', loc
- ifstack.append((conditionals.get(ll[3:], False), loc))
- elif ll.startswith("else"):
- ifstack[-1] = (not ifstack[-1][0], ifstack[-1][1])
- elif ll.startswith("fi"):
- ifstack.pop()
- # print " " * len(ifstack), '}', loc
- elif not False in [p for (p,_) in ifstack]:
- r.append(x)
- else:
- if not False in [p for (p,_) in ifstack]:
- r.append(x)
- if ifstack != []:
- print "unterminated if", ifstack
- sys.exit(0)
- return r
-
-language = 'py'
-doc = preprocess_conditionals(fulldoc, {
- 'C' : language=='c',
- 'Python' : language=='py',
- 'Py' : language=='py',
- 'CPy' : (language=='py' or language == 'c'),
- 'Cpp' : language=='cpp',
- 'plastex' : True})
-
-raw = open('raw', 'w')
-for x in doc:
- print >>raw, repr(x)
-raw.close()
+from latexparser import latexparser, TexCmd
+import distutils.dep_util
+import os
+import cPickle as pickle
+import pyparsing as pp
+import StringIO
+from qfile import QOpen
+from string import Template
+
+# useful things for pyparsing
+def returnList(x):
+ def listify(s, loc, toks):
+ return [toks]
+ x.setParseAction(listify)
+ return x
+def returnTuple(x):
+ def listify(s, loc, toks):
+ return [tuple(toks)]
+ x.setParseAction(listify)
+ return x
+def CommaList(word):
+ return returnList(pp.Optional(word + pp.ZeroOrMore(pp.Suppress(',') + word)))
+def sl(s):
+ return pp.Suppress(pp.Literal(s))
+
+import pythonapi
+
+python_api = pythonapi.reader("../../interfaces/python/api")
+
class SphinxWriter:
- def __init__(self, filename):
- self.f_index = open(filename, 'wt')
+ def __init__(self, filename, language, abspath):
+ assert language in ['py', 'c', 'cpp']
+ self.language = language
+
+ self.abspath = abspath
+ os.path.abspath(os.path.dirname(filename))
+
+ self.f_index = QOpen(os.path.join(self.language, filename), 'wt')
self.f = self.f_index
self.f_chapter = None
self.f_section = None
self.indent = 0
self.state = None
self.envstack = []
- self.tags = open('TAGS', 'w')
+ self.tags = {}
+ self.errors = open('errors.%s' % language, 'wt')
+ self.unhandled_commands = set()
+ self.freshline = True
+ self.function_props = {}
+ self.covered = set() # covered functions, used for error report
+ self.description = ""
def write(self, s):
+ self.freshline = len(s) > 0 and (s[-1] == '\n')
self.f.write(s.replace('\n', '\n' + self.indent * " "))
+ def appendspace(self):
+ """ append a space to the output - if we're not at the start of a line """
+ if not self.freshline:
+ self.write(' ')
+
def doplain(self, s):
+ if (len(s) > 1) and (s[0] == '$' and s[-1] == '$') and self.state != 'math':
+ s = ":math:`%s`" % s[1:-1].strip()
+ elif self.state != 'math':
+ s.replace('\\_', '_')
+ if len(s) > 0 and s[-1] == '\n':
+ s = s[:-1]
if self.state == 'fpreamble':
self.description += s
else:
- print >>self, s
+ self.write(s)
def docmd(self, c):
if self.state == 'math':
else:
self.indent -= 1
self.state = None
- print >>self
+ self.write('\n\n')
else:
- if c.cmd == '[':
- meth = self.cmd_gomath
+ if c.cmd == '\n':
+ self.write('\\\n')
else:
- cname = "cmd_" + c.cmd
- meth = getattr(self, cname, self.default_cmd)
- meth(c)
+ if c.cmd == '[':
+ meth = self.cmd_gomath
+ else:
+ cname = "cmd_" + c.cmd
+ meth = getattr(self, cname, self.unrecognized_cmd)
+ meth(c)
def cmd_gomath(self, c):
self.state = 'math'
- print >>self, "\n.. math::"
+ print >>self, "\n\n.. math::"
self.indent += 1
print >>self
def cmd_chapter(self, c):
filename = str(c.params[0]).lower().replace(' ', '_').replace('/','_')
self.f_index.write(" %s\n" % filename)
- self.f_chapter = open(filename + '.rst', 'wt')
+ self.f_chapter = QOpen(os.path.join(self.language, filename + '.rst'), 'wt')
self.f_section = None
self.f = self.f_chapter
self.indent = 0
print >>self, title
print >>self, '*' * len(title)
print >>self
- print >>self, '.. toctree::'
- print >>self, ' :maxdepth: 2'
- print >>self
+ self.chapter_intoc = False
def cmd_section(self, c):
filename = str(c.params[0]).lower().replace(' ', '_').replace('/','_')
+ if not self.chapter_intoc:
+ self.chapter_intoc = True
+ print >>self.f_chapter
+ print >>self.f_chapter, '.. toctree::'
+ print >>self.f_chapter, ' :maxdepth: 2'
+ print >>self.f_chapter
self.f_chapter.write(" %s\n" % filename)
- self.f_section = open(filename + '.rst', 'wt')
+ self.f_section = QOpen(os.path.join(self.language, filename + '.rst'), 'wt')
self.f = self.f_section
self.indent = 0
- title = str(c.params[0])
+ title = self.render(c.params[0].str)
print >>self, title
print >>self, '=' * len(title)
print >>self
+ print >>self, '.. highlight:: %s' % {'c': 'c', 'cpp': 'cpp', 'py': 'python'}[self.language]
+ print >>self
+
+ def cmd_subsection(self, c):
+ print >>self
+ print >>self, str(c.params[0])
+ print >>self, '-' * len(str(c.params[0]))
+ print >>self
+ self.function_props = {}
+
+ def cmd_includegraphics(self, c):
+ filename = os.path.join('..', '..', str(c.params[0]))
+ print >>self, "\n\n.. image:: %s\n\n" % filename
def cmd_cvCppCross(self, c):
- print >>self, ":ref:`%s`" % str(c.params[0])
+ self.write(":ref:`%s`" % str(c.params[0]))
+
def cmd_cvCPyCross(self, c):
- print >>self, ":ref:`%s`" % str(c.params[0])
+ self.write(":ref:`%s`" % str(c.params[0]))
+
+ def cmd_cross(self, c):
+ self.write(":ref:`%s`" % str(c.params[0]))
+
+ def cmd_cvCross(self, c):
+ self.write(":ref:`%s`" % str(c.params[0]))
+
+ def cmd_cvclass(self, c):
+ self.indent = 0
+ self.state = None
+ nm = self.render(list(c.params[0].str))
+ print >>self, "\n.. index:: %s\n" % nm
+ print >>self, ".. _%s:\n" % nm
+ print >>self, nm
+ print >>self, '-' * len(nm)
+ print >>self
+ if self.language == 'py':
+ print >>self, ".. class:: " + nm + "\n"
+ else:
+ print >>self, ".. ctype:: " + nm + "\n"
+ print >>self
+ self.addtag(nm, c)
+ self.state = 'class'
+
+ def addtag(self, nm, c):
+ if nm == "":
+ self.report_error(c, "empty name")
+ self.tags[nm] = "%s\t%s\t%d" % (nm, os.path.join(os.getcwd(), c.filename), c.lineno)
+
+ def cmd_cvfunc(self, c):
+ self.cmd_cvCPyFunc(c)
def cmd_cvCPyFunc(self, c):
self.indent = 0
- nm = str(c.params[0])
+ nm = self.render(c.params[0].str)
+ print >>self, "\n.. index:: %s\n" % nm
+ print >>self, ".. _%s:\n" % nm
+ print >>self, nm
+ print >>self, '-' * len(nm)
+ print >>self
+ self.state = 'fpreamble'
+ if self.description != "":
+ self.report_error(c, "overflow - preceding cvfunc (starting %s) not terminated?" % repr(self.description[:30]))
+ self.description = ""
+ self.addtag(nm, c)
+
+ self.function_props = {'name' : nm}
+ self.covered.add(nm)
+
+ def cmd_cvCppFunc(self, c):
+ self.indent = 0
+ nm = self.render(c.params[0].str)
print >>self, "\n.. index:: %s\n" % nm
print >>self, ".. _%s:\n" % nm
print >>self, nm
print >>self, '-' * len(nm)
print >>self
self.state = 'fpreamble'
+ if self.description != "":
+ self.report_error(c, "overflow - preceding cvfunc (starting %s) not terminated?" % repr(self.description[:30]))
self.description = ""
- print >>self.tags, "%s\t%s\t%d" % (nm, c.filename, c.lineno)
+ self.addtag(nm, c)
+
+ self.function_props = {'name' : nm}
+ self.covered.add(nm)
+
+ def cmd_cvdefC(self, c):
+ if self.language != 'c':
+ return
+ s = str(c.params[0]).replace('\\_', '_')
+ s = s.replace('\\par', '')
+ s = s.replace('\n', ' ')
+ s = s.replace(';', '')
+ self.indent = 0
+ for proto in s.split('\\newline'):
+ if proto.strip() != "":
+ print >>self, "\n\n.. cfunction:: " + proto.strip() + "\n"
+ # print >>self, "=", repr(c.params[0].str)
+ print >>self, ' ' + self.description
+ self.description = ""
+ print >>self
+ self.state = None
+ self.function_props['defpy'] = s
+
+ def cmd_cvdefCpp(self, c):
+ if self.language != 'cpp':
+ return
+ s = str(c.params[0]).replace('\\_', '_')
+ s = s.replace('\\par', '')
+ s = s.replace('\n', ' ')
+ s = s.replace(';', '')
+ self.indent = 0
+ for proto in s.split('\\newline'):
+ if proto.strip() != "":
+ print >>self, "\n\n.. cfunction:: " + proto.strip() + "\n"
+ # print >>self, "=", repr(c.params[0].str)
+ if self.description != "":
+ print >>self, ' ' + self.description
+ else:
+ self.report_error(c, 'empty description')
+ self.description = ""
+ print >>self
+ self.state = None
+ self.function_props['defpy'] = s
def cmd_cvdefPy(self, c):
- s = str(c.params[0])
+ if self.language != 'py':
+ return
+ s = str(c.params[0]).replace('\\_', '_')
+ self.indent = 0
print >>self, ".. function:: " + s + "\n"
- self.indent = 1
- print >>self, self.description
+ # print >>self, "=", repr(c.params[0].str)
+ print >>self, ' ' + self.description
print >>self
+ self.description = ""
self.state = None
+ self.function_props['defpy'] = s
+
+ pp.ParserElement.setDefaultWhitespaceChars(" \n\t")
+
+ ident = pp.Word(pp.alphanums + "_.+-")
+ ident_or_tuple = ident | (sl('(') + CommaList(ident) + sl(')'))
+ initializer = ident_or_tuple
+ arg = returnList(ident + pp.Optional(sl('=') + initializer))
+
+ decl = ident + sl('(') + CommaList(arg) + sl(')') + sl("->") + ident_or_tuple + pp.StringEnd()
+
+ try:
+ l = decl.parseString(s)
+ if str(l[0]) != self.function_props['name']:
+ self.report_error(c, 'Decl "%s" does not match function name "%s"' % (str(l[0]), self.function_props['name']))
+ self.function_props['signature'] = l
+ if l[0] in python_api:
+ (ins, outs) = python_api[l[0]]
+ ins = [a for a in ins if not 'O' in a.flags]
+ if outs != None:
+ outs = outs.split(',')
+ if len(ins) != len(l[1]):
+ self.report_error(c, "function %s documented arity %d, code arity %d" % (l[0], len(l[1]), len(ins)))
+ if outs == None:
+ if l[2] != 'None':
+ self.report_error(c, "function %s documented None, but code has %s" % (l[0], l[2]))
+ else:
+ if isinstance(l[2], str):
+ doc_outs = [l[2]]
+ else:
+ doc_outs = l[2]
+ if len(outs) != len(doc_outs):
+ self.report_error(c, "function %s output documented tuple %d, code %d" % (l[0], len(outs), len(doc_outs)))
+ else:
+ # self.report_error(c, "function %s documented but not found in code" % l[0])
+ pass
+ except pp.ParseException, pe:
+ self.report_error(c, str(pe))
+ print s
+ print pe
+
+ def report_error(self, c, msg):
+ print >>self.errors, "%s:%d: [%s] Error %s" % (c.filename, c.lineno, self.language, msg)
def cmd_begin(self, c):
+ if len(c.params) == 0:
+ self.report_error(c, "Malformed begin")
+ return
+ self.write('\n')
s = str(c.params[0])
self.envstack.append((s, (c.filename, c.lineno)))
if s == 'description':
- pass
+ if self.language == 'py' and 'name' in self.function_props and not 'defpy' in self.function_props:
+ self.report_error(c, "No cvdefPy for function %s" % self.function_props['name'])
+ self.indent += 1
+ elif s == 'lstlisting':
+ # Set indent to zero while collecting code; so later write will not double-indent
+ self.saved_f = self.f
+ self.saved_indent = self.indent
+ self.f = StringIO.StringIO()
+ self.indent = 0
+ elif s in ['itemize', 'enumerate']:
+ self.indent += 1
+ elif s == 'tabular':
+ self.f = StringIO.StringIO()
else:
self.default_cmd(c)
+ def cmd_item(self, c):
+ if len(self.ee()) == 0:
+ self.report_error(c, "item without environment")
+ return
+ self.indent -= 1
+ markup = {'itemize' : '*', 'enumerate' : '#.', 'description' : '*'}[self.ee()[-1]]
+ if len(c.args) > 0:
+ markup += " " + self.render([c.args[0].str])
+ if len(c.params) > 0:
+ markup += " " + self.render(c.params[0].str)
+ self.write("\n\n" + markup)
+ self.indent += 1
+
def cmd_end(self, c):
+ if len(c.params) != 1:
+ self.report_error(c, "Malformed end")
+ return
+ if len(self.envstack) == 0:
+ self.report_error(c, "end with no env")
+ return
+ self.write('\n')
s = str(c.params[0])
if self.envstack == []:
print "Cannot pop at", (c.filename, c.lineno)
+ if self.envstack[-1][0] != s:
+ self.report_error(c, "end{%s} does not match current stack %s" % (s, repr(self.envstack)))
self.envstack.pop()
if s == 'description':
+ self.indent -= 1
+ if self.indent == 0:
+ self.function_props['done'] = True
+ elif s in ['itemize', 'enumerate']:
+ self.indent -= 1
+ elif s == 'tabular':
+ tabletxt = self.f.getvalue()
+ self.f = self.f_section
+ self.f.write(self.handle_table(tabletxt))
+ elif s == 'lstlisting':
+ listing = self.f.getvalue()
+
+ self.f = self.saved_f
+ self.indent = self.saved_indent
+ print >>self
+ if self.language == 'py':
+ ckeys = ['#define', 'void', '#include', ';\n']
+ found = [repr(k) for k in ckeys if k in listing]
+ if len(found) > 0:
+ self.report_error(c, 'listing is probably C, found %s' % ",".join(found))
+ if (self.language == 'py') and ('>>>' in listing):
+ print >>self, "\n.. doctest::\n"
+ else:
+ print >>self, "\n::\n"
+ self.indent += 1
+ print >>self
+ self.write(listing)
+ self.indent -= 1
+ print >>self
+ print >>self
+ print >>self, ".." # otherwise a following :param: gets treated as more listing
+ elif s == 'document':
pass
else:
self.default_cmd(c)
- def cmd_cvdefC(self, c):
- pass
- def cmd_cvdefCpp(self, c):
+ def cmd_label(self, c):
pass
+
+ def cmd_lstinputlisting(self, c):
+ s = str(c.params[0])
+ print >>self.f, ".. include:: %s" % os.path.normpath(os.path.join(self.abspath, s))
+ print >>self.f, " :literal:"
+ print >>self.f
+
+ # Conditionals
+ def cmd_cvC(self, c):
+ self.do_conditional(['c'], c)
def cmd_cvCpp(self, c):
- pass
+ self.do_conditional(['cpp'], c)
+ def cmd_cvPy(self, c):
+ self.do_conditional(['py'], c)
+ def cmd_cvCPy(self, c):
+ self.do_conditional(['c', 'py'], c)
+ def do_conditional(self, langs, c):
+ if self.language in langs:
+ self.doL(c.params[0].str, False)
+
+ def render(self, L):
+ """ return L rendered as a string """
+ save = self.f
+ self.f = StringIO.StringIO()
+ for x in L:
+ if isinstance(x, TexCmd):
+ self.docmd(x)
+ else:
+ self.doplain(x)
+ r = self.f.getvalue()
+ self.f = save
+ return r
def cmd_cvarg(self, c):
- ee = [n for (n,_) in self.envstack[1:]]
- if ee == ['description']:
- print >>self, '\n:param %s: ' % str(c.params[0]),
- elif ee == ['description', 'description']:
- print >>self, '\n* **%s** ' % str(c.params[0]),
+ if len(c.params) != 2:
+ self.report_error(c, "Malformed cvarg")
+ return
+ e = self.ee()
+ if self.state == 'class':
+ nm = self.render(c.params[0].str)
+ if '->' in nm:
+ print >>self, "\n\n.. method:: %s\n\n" % nm
+ else:
+ print >>self, "\n\n.. attribute:: %s\n\n" % nm
+ self.indent += 1
+ print >>self
+ self.doL(c.params[1].str, False)
+ self.indent -= 1
+ print >>self
+ return
+ is_func_arg = (e == ['description']) and (not 'done' in self.function_props)
+ if is_func_arg:
+ nm = self.render(c.params[0].str)
+ print >>self, '\n:param %s: ' % nm,
+ type = None # Try to figure out the argument type
+ # For now, multiple args get a pass
+ if (self.language == 'py') and ('signature' in self.function_props) and (not ',' in nm):
+ sig = self.function_props['signature']
+ argnames = [a[0] for a in sig[1]]
+ if isinstance(sig[2], str):
+ resnames = [sig[2]]
+ else:
+ resnames = list(sig[2])
+ if not nm in argnames + resnames:
+ self.report_error(c, "Argument %s is not mentioned in signature (%s) (%s)" % (nm, ", ".join(argnames), ", ".join(resnames)))
+
+ api = python_api.get(self.function_props['name'], None)
+ if api:
+ (ins, outs) = api
+ adict = dict([(a.nm, a) for a in ins])
+ arg = adict.get(nm, None)
+ if arg:
+ type = arg.ty
+ else:
+ self.report_error(c, 'cannot find arg %s in code' % nm)
+ elif len(e) > 0 and e[-1] == 'description':
+ print >>self, '\n* **%s** ' % self.render(c.params[0].str),
else:
- print self.envstack
- assert 0
+ self.report_error(c, "unexpected env (%s) for cvarg" % ",".join(e))
self.indent += 1
- self.doL(c.params[1].str)
+ self.doL(c.params[1].str, False)
self.indent -= 1
print >>self
+ if is_func_arg and type:
+ type = type.replace('*', '')
+ translate = {
+ "ints" : "sequence of int",
+ "floats" : "sequence of int",
+ "IplImages" : "sequence of :class:`IplImage`",
+ "double" : "float",
+ "int" : "int",
+ "float" : "float",
+ "char" : "str",
+ "cvarrseq" : ":class:`CvArr` or :class:`CvSeq`",
+ "CvPoint2D32fs" : "sequence of (float, float)",
+ "pts_npts_contours" : "list of lists of (x,y) pairs",
+ "CvSeqOfCvSURFPoint" : ":class:`CvSeq` of :class:`CvSURFPoint`",
+ "CvSeqOfCvSURFDescriptor" : ":class:`CvSeq` of list of float",
+ "cvpoint2d32f_count" : "int",
+ }
+ print >>self, "\n:type %s: %s" % (nm, translate.get(type, ':class:`%s`' % type))
+
+ def cmd_genc(self, c): pass
+ def cmd_genpy(self, c): pass
+ def cmd_author(self, c): pass
+ def cmd_date(self, c): pass
+ def cmd_def(self, c): pass
+ def cmd_documentclass(self, c): pass
+ def cmd_maketitle(self, c): pass
+ def cmd_newcommand(self, c): pass
+ def cmd_newline(self, c): pass
+ def cmd_setcounter(self, c): pass
+ def cmd_tableofcontents(self, c): pass
+ def cmd_targetlang(self, c): pass
+ def cmd_usepackage(self, c): pass
+ def cmd_title(self, c): pass
+ def cmd_par(self, c): pass
+ def cmd_hline(self, c):
+ print >>self, "\\hline"
+
+ def cmd_cite(self, c):
+ self.write("[%s]_" % str(c.params[0]))
+
+ def cmd_href(self, c):
+ if len(c.params) == 2:
+ self.write("`%s <%s>`_" % (str(c.params[1]), self.render(c.params[0].str)))
+ else:
+ self.report_error(c, "href should have two params")
+
+ def cmd_url(self, c):
+ self.write(str(c.params[0]))
+
+ def cmd_emph(self, c):
+ self.write("*" + self.render(c.params[0].str) + "*")
+
+ def cmd_textit(self, c):
+ self.write("*" + self.render(c.params[0].str) + "*")
+
+ def cmd_textbf(self, c):
+ self.write("**" + self.render(c.params[0].str) + "**")
def cmd_texttt(self, c):
- print >>self, "``" + str(c.params[0]) + "``"
+ self.write("``" + self.render(c.params[0].str) + "``")
def default_cmd(self, c):
if self.f == self.f_section:
- print >>self, repr(c)
-
- def doL(self, L):
+ self.write(repr(c))
+
+ def unrecognized_cmd(self, c):
+ # if writing the index or chapter heading, anything goes
+ if not self.f in [self.f_index, self.f_chapter]:
+ self.write(c.cmd)
+ if (not 'lstlisting' in self.ee()) and (not c.cmd in "#{}%&*\\_"):
+ if not c.cmd in self.unhandled_commands:
+ self.report_error(c, 'unhandled command %s' % c.cmd)
+ self.unhandled_commands.add(c.cmd)
+
+ def doL(self, L, newlines = True):
for x in L:
+ pos0 = self.f.tell()
if isinstance(x, TexCmd):
self.docmd(x)
else:
- self.doplain(x)
+ if 'lstlisting' in self.ee() or not newlines:
+ self.doplain(x)
+ else:
+ self.doplain(x.lstrip())
+ pos1 = self.f.tell()
+ if pos0 != pos1:
+ if self.state in ['math'] or not newlines:
+ self.appendspace()
+ else:
+ if not 'lstlisting' in self.ee():
+ self.write('\n')
+
+ def handle_table(self, s):
+ oneline = s.replace('\n', ' ').strip()
+ rows = [r.strip() for r in oneline.split('\\hline')]
+ tab = []
+ for r in rows:
+ if r != "":
+ cols = [c.strip() for c in r.split('&')]
+ tab.append(cols)
+ widths = [max([len(r[i]) for r in tab]) for i in range(len(tab[0]))]
+
+ st = "" # Sphinx table
+
+ if 0:
+ sep = "+" + "+".join(["-" * w for w in widths]) + "+"
+ st += sep + '\n'
+ for r in tab:
+ st += "|" + "|".join([c.center(w) for (c, w) in zip(r, widths)]) + "|" + '\n'
+ st += sep + '\n'
+
+ st = '.. table::\n\n'
+ sep = " ".join(["=" * w for w in widths])
+ st += ' ' + sep + '\n'
+ for y,r in enumerate(tab):
+ st += ' ' + " ".join([c.ljust(w) for (c, w) in zip(r, widths)]) + '\n'
+ if y == 0:
+ st += ' ' + sep + '\n'
+ st += ' ' + sep + '\n'
+ return st
+
+ def ee(self):
+ """ Return tags of the envstack. envstack[0] is 'document', so skip it """
+ return [n for (n,_) in self.envstack[1:]]
+
+ def get_tags(self):
+ return self.tags
+
+ def close(self):
+
+ if self.envstack != []:
+ print >>self.errors, "Error envstack not empty at end of doc: " + repr(self.envstack)
+ print >>self.errors, "Unrecognized commands:"
+ for c in sorted(self.unhandled_commands):
+ print >>self.errors, "\n " + c
+ print >>self.errors
+ if self.language == 'py':
+ print >>self.errors, "The following functions are undocumented"
+ for f in sorted(set(python_api) - self.covered):
+ print >>self.errors, ' ', f
+
+ print >>self.f_index, " bibliography"
+ print >>self.f_index, """
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`search`
+"""
+
+# Quick and dirty bibtex parser
-# dststack[0] -> index.rst
-# [1] -> current chapter
-# [2] -> current section
+def parseBib(filename, language):
+ pp.ParserElement.setDefaultWhitespaceChars(" \n\t")
+ entry = returnList(pp.Word('@', pp.alphanums) + sl('{') +
+ pp.Word(pp.alphanums + "_") + sl(',') +
+ CommaList(returnTuple(pp.Word(pp.alphanums) + sl('=') + pp.QuotedString('{', endQuoteChar = '}'))) +
+ pp.Suppress(pp.Optional(',')) +
+ sl('}'))
+ r = (pp.ZeroOrMore(entry) | pp.Suppress('#' + pp.ZeroOrMore(pp.CharsNotIn('\n'))) + pp.StringEnd()).parseFile(filename)
+ bibliography = QOpen(os.path.join(language, "bibliography.rst"), 'wt')
+ print >>bibliography, "Bibliography"
+ print >>bibliography, "============"
+ print >>bibliography
-sr = SphinxWriter('index.rst')
-print >>sr, """
-OpenCV |version| Python Reference
+ for _,e in sorted([(str(x[1]), x) for x in r]):
+ (etype, tag, attrs) = str(e[0][1:]), str(e[1]), dict([(str(a), str(b)) for (a,b) in e[2]])
+
+ representations = {
+ 'article' : '$author, "$title". $journal $volume $number, pp $pages ($year)',
+ 'inproceedings' : '$author "$title", $booktitle, $year',
+ 'misc' : '$author "$title", $year',
+ 'techreport' : '$author "$title", $edition, $edition ($year)',
+ }
+ if etype in representations:
+ if 0:
+ print >>bibliography, tag
+ print >>bibliography, "^" * len(tag)
+ print >>bibliography
+
+ print >>bibliography, ".. [%s] %s" % (tag, Template(representations[etype]).safe_substitute(attrs))
+ print >>bibliography
+ bibliography.close()
+
+if 1:
+ fulldoc = latexparser(sys.argv[1])
+
+ abspath = os.path.abspath(os.path.dirname(sys.argv[1]))
+
+ raw = open('raw.full', 'w')
+ for x in fulldoc:
+ print >>raw, repr(x)
+ raw.close()
+
+ # Filter on target language
+ def preprocess_conditionals(fd, conditionals):
+ r = []
+ ifstack = []
+ for x in fd:
+ if isinstance(x, TexCmd):
+ ll = x.cmd.rstrip()
+ loc = (x.filename, x.lineno)
+ if ll.startswith("if"):
+ # print " " * len(ifstack), '{', loc
+ ifstack.append((conditionals.get(ll[2:], False), loc))
+ elif ll.startswith("else"):
+ ifstack[-1] = (not ifstack[-1][0], ifstack[-1][1])
+ elif ll.startswith("fi"):
+ ifstack.pop()
+ # print " " * len(ifstack), '}', loc
+ elif not False in [p for (p,_) in ifstack]:
+ r.append(x)
+ else:
+ if not False in [p for (p,_) in ifstack]:
+ r.append(x)
+ if ifstack != []:
+ print "unterminated if", ifstack
+ sys.exit(0)
+ return r
+
+ tags = {}
+ for language in sys.argv[2:]:
+ doc = preprocess_conditionals(fulldoc, {
+ 'C' : language=='c',
+ 'Python' : language=='py',
+ 'Py' : language=='py',
+ 'CPy' : (language=='py' or language == 'c'),
+ 'Cpp' : language=='cpp',
+ 'plastex' : True})
+
+ raw = open('raw.%s' % language, 'w')
+ for x in doc:
+ print >>raw, repr(x)
+ raw.close()
+ sr = SphinxWriter('index.rst', language, abspath)
+ print >>sr, """
+OpenCV |version| %s Reference
=================================
The OpenCV Wiki is here: http://opencv.willowgarage.com/
.. toctree::
:maxdepth: 2
-"""
-sr.doL(doc)
-sys.exit(0)
-
-structuring = ['chapter', 'section']
-for x in doc:
- if isinstance(x, TexCmd):
- if x.cmd in structuring:
- level = structuring.index(x.cmd)
- filename = str(x.params[0]).lower().replace(' ', '_').replace('/','_')
- print >>dststack[level], " %s" % filename
- dststack[level + 1] = SphinxWriter(filename + ".rst", envstack)
- title = str(x.params[0])
- if level == 0:
- print >>dststack[level + 1], '*' * len(title)
- print >>dststack[level + 1], title
- print >>dststack[level + 1], '*' * len(title)
- print >>dststack[level + 1]
- print >>dststack[level + 1], '.. toctree::'
- print >>dststack[level + 1], ' :maxdepth: 2'
- print >>dststack[level + 1]
- if level == 1:
- print >>dststack[level + 1], title
- print >>dststack[level + 1], '=' * len(title)
- print >>dststack[level + 1]
- else:
- if dststack[level + 1]:
- dststack[level + 1].docmd(x)
- else:
- dststack[level + 1].doplain(x)
+""" % {'c': 'C', 'cpp': 'C++', 'py': 'Python'}[language]
+ sr.doL(doc)
+ sr.close()
+ parseBib('../opencv.bib', language)
+ tags.update(sr.get_tags())
+ open('TAGS', 'w').write("\n".join(sorted(tags.values())) + "\n")
-print >>dststack[0], """
-Indices and tables
-==================
-
-* :ref:`genindex`
-* :ref:`search`
-"""