6 Textile Sphinx builder.
8 Derived from Sphinx's plain-text sphinx builder.
10 NOTE: NOT COMPLETED YET.
12 :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
13 Copyright 2011 by Kouhei Sutou.
14 :license: BSD, see LICENSE for details.
21 from docutils.io
import StringOutput
23 from sphinx.builders
import Builder
24 from sphinx.util.osutil
import ensuredir, os_path
29 out_suffix =
'.textile'
35 for docname
in self.env.found_docs:
36 if docname
not in self.env.all_docs:
39 targetname = self.env.doc2path(docname, self.outdir,
42 targetmtime = path.getmtime(targetname)
46 srcmtime = path.getmtime(self.env.doc2path(docname))
47 if srcmtime > targetmtime:
49 except EnvironmentError:
60 destination = StringOutput(encoding=
'utf-8')
61 self.writer.write(doctree, destination)
62 outfilename = path.join(self.outdir, os_path(docname) + self.
out_suffix)
63 ensuredir(path.dirname(outfilename))
65 f = codecs.open(outfilename,
'w',
'utf-8')
67 f.write(self.writer.output)
70 except (IOError, OSError), err:
71 self.warn(
"error writing file %s: %s" % (outfilename, err))
80 from docutils
import nodes, writers
82 from sphinx
import addnodes
83 from sphinx.locale
import admonitionlabels, versionlabels, _
86 supported = (
'textile',)
87 settings_spec = (
'No options here.',
'', ())
88 settings_defaults = {}
93 writers.Writer.__init__(self)
98 self.document.walkabout(visitor)
106 sectionchars =
'*=-~"+'
109 nodes.NodeVisitor.__init__(self, document)
120 self.states.append([])
121 self.stateindent.append(indent)
123 content = self.states.pop()
125 indent = self.stateindent.pop()
132 res = textwrap.wrap(
''.join(toformat), width=MAXWIDTH-maxindent)
134 res =
''.join(toformat).splitlines()
137 result.append((indent, res))
138 for itemindent, item
in content:
140 toformat.append(item)
143 result.append((indent + itemindent, item))
146 if first
is not None and result:
147 itemindent, item = result[0]
149 result.insert(0, (itemindent - indent, [first + item[0]]))
150 result[1] = (itemindent, item[1:])
151 self.
states[-1].extend(result)
157 self.
body =
'\n'.join(line
and (
' '*indent + line)
158 for indent, lines
in self.
states[0]
176 visit_sidebar = visit_topic
177 depart_sidebar = depart_topic
197 if isinstance(node.parent, nodes.Admonition):
198 self.add_text(node.astext()+
': ')
202 text =
''.join(x[1]
for x
in self.states.pop()
if x[0] == -1)
204 self.stateindent.pop()
224 if node.parent[
'objtype']
in (
'class',
'exception'):
225 self.add_text(
'%s ' % node.parent[
'objtype'])
246 self.add_text(
' -> ')
298 for production
in node:
299 names.append(production[
'tokenname'])
300 maxlen = max(len(name)
for name
in names)
301 for production
in node:
302 if production[
'tokenname']:
303 self.add_text(production[
'tokenname'].ljust(maxlen) +
' ::=')
304 lastname = production[
'tokenname']
306 self.add_text(
'%s ' % (
' '*len(lastname)))
307 self.add_text(production.astext() +
'\n')
308 self.end_state(wrap=
False)
317 self.
_footnote = node.children[0].astext().strip()
323 if len(node)
and isinstance(node[0], nodes.label):
365 self.add_text(node[
'delimiter'])
392 self.table.append(
'sep')
397 self.table.append([])
402 if node.has_key(
'morerows')
or node.has_key(
'morecols'):
403 raise NotImplementedError(
'Column or row spanning cells are '
407 text =
'\n'.join(
'\n'.join(x[1])
for x
in self.states.pop())
408 self.stateindent.pop()
413 raise NotImplementedError(
'Nested tables are not supported.')
417 lines = self.
table[1:]
419 colwidths = self.
table[0]
420 realwidths = colwidths[:]
425 separator = len(fmted_rows)
428 for i, cell
in enumerate(line):
429 par = textwrap.wrap(cell, width=colwidths[i])
431 maxwidth = max(map(len, par))
434 realwidths[i] = max(realwidths[i], maxwidth)
436 fmted_rows.append(cells)
438 def writesep(char='-'):
440 for width
in realwidths:
441 out.append(char * (width+2))
446 lines = map(
None, *row)
449 for i, cell
in enumerate(line):
451 out.append(
' ' + cell.ljust(realwidths[i]+1))
453 out.append(
' ' * (realwidths[i] + 2))
457 for i, row
in enumerate(fmted_rows):
458 if separator
and i == separator:
469 self.
add_text(
', '.join(n.astext()
for n
in node.children[0].children)
481 self.
add_text(
'=' * (MAXWIDTH - indent))
486 self.list_counter.append(-1)
488 self.list_counter.pop()
491 self.list_counter.append(0)
493 self.list_counter.pop()
496 self.list_counter.append(-2)
498 self.list_counter.pop()
521 isinstance(node[1], nodes.classifier)
582 def _visit_admonition(self, node):
584 def _make_depart_admonition(name):
586 self.
end_state(first=admonitionlabels[name] +
': ')
587 return depart_admonition
589 visit_attention = _visit_admonition
590 depart_attention = _make_depart_admonition(
'attention')
591 visit_caution = _visit_admonition
592 depart_caution = _make_depart_admonition(
'caution')
593 visit_danger = _visit_admonition
594 depart_danger = _make_depart_admonition(
'danger')
595 visit_error = _visit_admonition
596 depart_error = _make_depart_admonition(
'error')
597 visit_hint = _visit_admonition
598 depart_hint = _make_depart_admonition(
'hint')
599 visit_important = _visit_admonition
600 depart_important = _make_depart_admonition(
'important')
601 visit_note = _visit_admonition
602 depart_note = _make_depart_admonition(
'note')
603 visit_tip = _visit_admonition
604 depart_tip = _make_depart_admonition(
'tip')
605 visit_warning = _visit_admonition
606 depart_warning = _make_depart_admonition(
'warning')
611 self.
add_text(versionlabels[node[
'type']] % node[
'version'] +
': ')
613 self.
add_text(versionlabels[node[
'type']] % node[
'version'] +
'.')
648 if not isinstance(node.parent, nodes.Admonition)
or \
649 isinstance(node.parent, addnodes.seealso):
652 if not isinstance(node.parent, nodes.Admonition)
or \
653 isinstance(node.parent, addnodes.seealso):
698 if node.hasattr(
'explanation'):
699 self.
add_text(
' (%s)' % node[
'explanation'])
722 self.add_text(
'[%s]' % node.astext())
726 self.
add_text(
'[%s]' % node.astext())
751 self.
add_text(
'<SYSTEM MESSAGE: %s>' % node.astext())
763 if 'text' in node.get(
'format',
'').split():
764 self.body.append(node.astext())
768 raise NotImplementedError(
'Unknown node: ' + node.__class__.__name__)
771 app.add_builder(TextileBuilder)