Add includecode directive for akka-docs
This commit is contained in:
parent
14334a65af
commit
c179cbf623
3 changed files with 138 additions and 1 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -46,5 +46,6 @@ multiverse.log
|
||||||
.eprj
|
.eprj
|
||||||
.*.swp
|
.*.swp
|
||||||
akka-docs/_build/
|
akka-docs/_build/
|
||||||
|
*.pyc
|
||||||
akka-tutorials/akka-tutorial-first/project/boot/
|
akka-tutorials/akka-tutorial-first/project/boot/
|
||||||
akka-tutorials/akka-tutorial-first/project/plugins/project/
|
akka-tutorials/akka-tutorial-first/project/plugins/project/
|
||||||
|
|
@ -7,7 +7,8 @@ import sys, os
|
||||||
|
|
||||||
# -- General configuration -----------------------------------------------------
|
# -- General configuration -----------------------------------------------------
|
||||||
|
|
||||||
extensions = ['sphinx.ext.todo']
|
sys.path.append(os.path.abspath('exts'))
|
||||||
|
extensions = ['sphinx.ext.todo', 'includecode']
|
||||||
|
|
||||||
templates_path = ['_templates']
|
templates_path = ['_templates']
|
||||||
source_suffix = '.rst'
|
source_suffix = '.rst'
|
||||||
|
|
|
||||||
135
akka-docs/exts/includecode.py
Normal file
135
akka-docs/exts/includecode.py
Normal file
|
|
@ -0,0 +1,135 @@
|
||||||
|
import os
|
||||||
|
import codecs
|
||||||
|
from os import path
|
||||||
|
|
||||||
|
from docutils import nodes
|
||||||
|
from docutils.parsers.rst import Directive, directives
|
||||||
|
|
||||||
|
class IncludeCode(Directive):
|
||||||
|
"""
|
||||||
|
Include a code example from a file with sections delimited with special comments.
|
||||||
|
"""
|
||||||
|
|
||||||
|
has_content = False
|
||||||
|
required_arguments = 1
|
||||||
|
optional_arguments = 0
|
||||||
|
final_argument_whitespace = False
|
||||||
|
option_spec = {
|
||||||
|
'section': directives.unchanged_required,
|
||||||
|
'comment': directives.unchanged_required,
|
||||||
|
'marker': directives.unchanged_required,
|
||||||
|
'include': directives.unchanged_required,
|
||||||
|
'exclude': directives.unchanged_required,
|
||||||
|
'linenos': directives.flag,
|
||||||
|
'language': directives.unchanged_required,
|
||||||
|
'encoding': directives.encoding,
|
||||||
|
'prepend': directives.unchanged_required,
|
||||||
|
'append': directives.unchanged_required,
|
||||||
|
}
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
document = self.state.document
|
||||||
|
arg0 = self.arguments[0]
|
||||||
|
(filename, sep, section) = arg0.partition('#')
|
||||||
|
|
||||||
|
if not document.settings.file_insertion_enabled:
|
||||||
|
return [document.reporter.warning('File insertion disabled',
|
||||||
|
line=self.lineno)]
|
||||||
|
env = document.settings.env
|
||||||
|
if filename.startswith('/') or filename.startswith(os.sep):
|
||||||
|
rel_fn = filename[1:]
|
||||||
|
else:
|
||||||
|
docdir = path.dirname(env.doc2path(env.docname, base=None))
|
||||||
|
rel_fn = path.join(docdir, filename)
|
||||||
|
try:
|
||||||
|
fn = path.join(env.srcdir, rel_fn)
|
||||||
|
except UnicodeDecodeError:
|
||||||
|
# the source directory is a bytestring with non-ASCII characters;
|
||||||
|
# let's try to encode the rel_fn in the file system encoding
|
||||||
|
rel_fn = rel_fn.encode(sys.getfilesystemencoding())
|
||||||
|
fn = path.join(env.srcdir, rel_fn)
|
||||||
|
|
||||||
|
encoding = self.options.get('encoding', env.config.source_encoding)
|
||||||
|
codec_info = codecs.lookup(encoding)
|
||||||
|
try:
|
||||||
|
f = codecs.StreamReaderWriter(open(fn, 'U'),
|
||||||
|
codec_info[2], codec_info[3], 'strict')
|
||||||
|
lines = f.readlines()
|
||||||
|
f.close()
|
||||||
|
except (IOError, OSError):
|
||||||
|
return [document.reporter.warning(
|
||||||
|
'Include file %r not found or reading it failed' % filename,
|
||||||
|
line=self.lineno)]
|
||||||
|
except UnicodeError:
|
||||||
|
return [document.reporter.warning(
|
||||||
|
'Encoding %r used for reading included file %r seems to '
|
||||||
|
'be wrong, try giving an :encoding: option' %
|
||||||
|
(encoding, filename))]
|
||||||
|
|
||||||
|
comment = self.options.get('comment', '//')
|
||||||
|
marker = self.options.get('marker', comment + '#')
|
||||||
|
lenm = len(marker)
|
||||||
|
if not section:
|
||||||
|
section = self.options.get('section')
|
||||||
|
include_sections = self.options.get('include', '')
|
||||||
|
exclude_sections = self.options.get('exclude', '')
|
||||||
|
include = set(include_sections.split(',')) if include_sections else set()
|
||||||
|
exclude = set(exclude_sections.split(',')) if exclude_sections else set()
|
||||||
|
if section:
|
||||||
|
include |= {section}
|
||||||
|
within = set()
|
||||||
|
res = []
|
||||||
|
excluding = False
|
||||||
|
for line in lines:
|
||||||
|
index = line.find(marker)
|
||||||
|
if index >= 0:
|
||||||
|
section_name = line[index+lenm:].strip()
|
||||||
|
if section_name in within:
|
||||||
|
within ^= {section_name}
|
||||||
|
if excluding and not (exclude & within):
|
||||||
|
excluding = False
|
||||||
|
else:
|
||||||
|
within |= {section_name}
|
||||||
|
if not excluding and (exclude & within):
|
||||||
|
excluding = True
|
||||||
|
res.append(' ' * index + comment + ' ' + section_name.replace('-', ' ') + ' ...\n')
|
||||||
|
elif not (exclude & within) and (not include or (include & within)):
|
||||||
|
res.append(line)
|
||||||
|
lines = res
|
||||||
|
|
||||||
|
def countwhile(predicate, iterable):
|
||||||
|
count = 0
|
||||||
|
for x in iterable:
|
||||||
|
if predicate(x):
|
||||||
|
count += 1
|
||||||
|
else:
|
||||||
|
return count
|
||||||
|
|
||||||
|
nonempty = filter(lambda l: l.strip(), lines)
|
||||||
|
tabcounts = map(lambda l: countwhile(lambda c: c == ' ', l), nonempty)
|
||||||
|
tabshift = min(tabcounts)
|
||||||
|
|
||||||
|
if tabshift > 0:
|
||||||
|
lines = map(lambda l: l[tabshift:] if len(l) > tabshift else l, lines)
|
||||||
|
|
||||||
|
prepend = self.options.get('prepend')
|
||||||
|
append = self.options.get('append')
|
||||||
|
if prepend:
|
||||||
|
lines.insert(0, prepend + '\n')
|
||||||
|
if append:
|
||||||
|
lines.append(append + '\n')
|
||||||
|
|
||||||
|
text = ''.join(lines)
|
||||||
|
retnode = nodes.literal_block(text, text, source=fn)
|
||||||
|
retnode.line = 1
|
||||||
|
retnode.attributes['line_number'] = self.lineno
|
||||||
|
if self.options.get('language', ''):
|
||||||
|
retnode['language'] = self.options['language']
|
||||||
|
if 'linenos' in self.options:
|
||||||
|
retnode['linenos'] = True
|
||||||
|
document.settings.env.note_dependency(rel_fn)
|
||||||
|
return [retnode]
|
||||||
|
|
||||||
|
def setup(app):
|
||||||
|
app.require_sphinx('1.0')
|
||||||
|
app.add_directive('includecode', IncludeCode)
|
||||||
Loading…
Add table
Add a link
Reference in a new issue