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
|
||||
.*.swp
|
||||
akka-docs/_build/
|
||||
*.pyc
|
||||
akka-tutorials/akka-tutorial-first/project/boot/
|
||||
akka-tutorials/akka-tutorial-first/project/plugins/project/
|
||||
|
|
@ -7,7 +7,8 @@ import sys, os
|
|||
|
||||
# -- General configuration -----------------------------------------------------
|
||||
|
||||
extensions = ['sphinx.ext.todo']
|
||||
sys.path.append(os.path.abspath('exts'))
|
||||
extensions = ['sphinx.ext.todo', 'includecode']
|
||||
|
||||
templates_path = ['_templates']
|
||||
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