diff options
author | Georg Brandl <georg@python.org> | 2009-02-18 19:55:57 +0100 |
---|---|---|
committer | Georg Brandl <georg@python.org> | 2009-02-18 19:55:57 +0100 |
commit | 044d42953db35999f68ff8d3f6f8a60d76cbc980 (patch) | |
tree | b2ca978d76a2dd68243e7249946abba41d831aee /sphinx/directives/code.py | |
parent | 8bd4e8e3984bf4b0fbd0d5b7a19a7f5c81b882f6 (diff) | |
download | sphinx-git-044d42953db35999f68ff8d3f6f8a60d76cbc980.tar.gz |
Convert builtin directives to classes. Refactor desc_directive so that it is easier to subclass.
Diffstat (limited to 'sphinx/directives/code.py')
-rw-r--r-- | sphinx/directives/code.py | 284 |
1 files changed, 154 insertions, 130 deletions
diff --git a/sphinx/directives/code.py b/sphinx/directives/code.py index 3162d5575..a66940857 100644 --- a/sphinx/directives/code.py +++ b/sphinx/directives/code.py @@ -16,135 +16,159 @@ from docutils.parsers.rst import directives from sphinx import addnodes from sphinx.util import parselinenos - - -# ------ highlight directive --------------------------------------------------- - -def highlightlang_directive(name, arguments, options, content, lineno, - content_offset, block_text, state, state_machine): - if 'linenothreshold' in options: - try: - linenothreshold = int(options['linenothreshold']) - except Exception: - linenothreshold = 10 - else: - linenothreshold = sys.maxint - return [addnodes.highlightlang(lang=arguments[0].strip(), - linenothreshold=linenothreshold)] - -highlightlang_directive.content = 0 -highlightlang_directive.arguments = (1, 0, 0) -highlightlang_directive.options = {'linenothreshold': directives.unchanged} -directives.register_directive('highlight', highlightlang_directive) -# old name -directives.register_directive('highlightlang', highlightlang_directive) - - -# ------ code-block directive -------------------------------------------------- - -def codeblock_directive(name, arguments, options, content, lineno, - content_offset, block_text, state, state_machine): - code = u'\n'.join(content) - literal = nodes.literal_block(code, code) - literal['language'] = arguments[0] - literal['linenos'] = 'linenos' in options - return [literal] - -codeblock_directive.content = 1 -codeblock_directive.arguments = (1, 0, 0) -codeblock_directive.options = {'linenos': directives.flag} -directives.register_directive('code-block', codeblock_directive) -directives.register_directive('sourcecode', codeblock_directive) - - -# ------ literalinclude directive ---------------------------------------------- - -def literalinclude_directive(name, arguments, options, content, lineno, - content_offset, block_text, state, state_machine): - """Like .. include:: :literal:, but only warns if the include file is - not found.""" - if not state.document.settings.file_insertion_enabled: - return [state.document.reporter.warning('File insertion disabled', - line=lineno)] - env = state.document.settings.env - rel_fn = arguments[0] - source_dir = path.dirname(path.abspath(state_machine.input_lines.source( - lineno - state_machine.input_offset - 1))) - fn = path.normpath(path.join(source_dir, rel_fn)) - - if 'pyobject' in options and 'lines' in options: - return [state.document.reporter.warning( - 'Cannot use both "pyobject" and "lines" options', line=lineno)] - - encoding = options.get('encoding', env.config.source_encoding) - try: - f = codecs.open(fn, 'rU', encoding) - lines = f.readlines() - f.close() - except (IOError, OSError): - return [state.document.reporter.warning( - 'Include file %r not found or reading it failed' % arguments[0], - line=lineno)] - except UnicodeError: - return [state.document.reporter.warning( - 'Encoding %r used for reading included file %r seems to ' - 'be wrong, try giving an :encoding: option' % - (encoding, arguments[0]))] - - objectname = options.get('pyobject') - if objectname is not None: - from sphinx.pycode import ModuleAnalyzer - analyzer = ModuleAnalyzer.for_file(fn, '') - tags = analyzer.find_tags() - if objectname not in tags: - return [state.document.reporter.warning( - 'Object named %r not found in include file %r' % - (objectname, arguments[0]), line=lineno)] +from sphinx.util.compat import Directive + + +class Highlight(Directive): + """ + Directive to set the highlighting language for code blocks, as well + as the threshold for line numbers. + """ + + has_content = False + required_arguments = 1 + optional_arguments = 0 + final_argument_whitespace = False + option_spec = { + 'linenothreshold': directives.unchanged, + } + + def run(self): + if 'linenothreshold' in self.options: + try: + linenothreshold = int(self.options['linenothreshold']) + except Exception: + linenothreshold = 10 else: - lines = lines[tags[objectname][1] - 1 : tags[objectname][2] - 1] - - linespec = options.get('lines') - if linespec is not None: + linenothreshold = sys.maxint + return [addnodes.highlightlang(lang=self.arguments[0].strip(), + linenothreshold=linenothreshold)] + + +class CodeBlock(Directive): + """ + Directive for a code block with special highlighting or line numbering + settings. + """ + + has_content = True + required_arguments = 1 + optional_arguments = 0 + final_argument_whitespace = False + option_spec = { + 'linenos': directives.flag, + } + + def run(self): + code = u'\n'.join(self.content) + literal = nodes.literal_block(code, code) + literal['language'] = self.arguments[0] + literal['linenos'] = 'linenos' in self.options + return [literal] + + +class LiteralInclude(Directive): + """ + Like ``.. include:: :literal:``, but only warns if the include file is + not found, and does not raise errors. Also has several options for + selecting what to include. + """ + + has_content = False + required_arguments = 1 + optional_arguments = 0 + final_argument_whitespace = False + option_spec = { + 'linenos': directives.flag, + 'language': directives.unchanged_required, + 'encoding': directives.encoding, + 'pyobject': directives.unchanged_required, + 'lines': directives.unchanged_required, + 'start-after': directives.unchanged_required, + 'end-before': directives.unchanged_required, + } + + def run(self): + document = self.state.document + filename = self.arguments[0] + if not document.settings.file_insertion_enabled: + return [document.reporter.warning('File insertion disabled', + line=self.lineno)] + env = document.settings.env + rel_fn = filename + sourcename = self.state_machine.input_lines.source( + self.lineno - self.state_machine.input_offset - 1) + source_dir = path.dirname(path.abspath(sourcename)) + fn = path.normpath(path.join(source_dir, rel_fn)) + + if 'pyobject' in self.options and 'lines' in self.options: + return [document.reporter.warning( + 'Cannot use both "pyobject" and "lines" options', + line=self.lineno)] + + encoding = self.options.get('encoding', env.config.source_encoding) try: - linelist = parselinenos(linespec, len(lines)) - except ValueError, err: - return [state.document.reporter.warning(str(err), line=lineno)] - lines = [lines[i] for i in linelist] - - startafter = options.get('start-after') - endbefore = options.get('end-before') - if startafter is not None or endbefore is not None: - use = not startafter - res = [] - for line in lines: - if not use and startafter in line: - use = True - elif use and endbefore in line: - use = False - break - elif use: - res.append(line) - lines = res - - text = ''.join(lines) - retnode = nodes.literal_block(text, text, source=fn) - retnode.line = 1 - if options.get('language', ''): - retnode['language'] = options['language'] - if 'linenos' in options: - retnode['linenos'] = True - state.document.settings.env.note_dependency(rel_fn) - return [retnode] - -literalinclude_directive.options = { - 'linenos': directives.flag, - 'language': directives.unchanged_required, - 'encoding': directives.encoding, - 'pyobject': directives.unchanged_required, - 'lines': directives.unchanged_required, - 'start-after': directives.unchanged_required, - 'end-before': directives.unchanged_required, -} -literalinclude_directive.content = 0 -literalinclude_directive.arguments = (1, 0, 0) -directives.register_directive('literalinclude', literalinclude_directive) + f = codecs.open(fn, 'rU', encoding) + 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))] + + objectname = self.options.get('pyobject') + if objectname is not None: + from sphinx.pycode import ModuleAnalyzer + analyzer = ModuleAnalyzer.for_file(fn, '') + tags = analyzer.find_tags() + if objectname not in tags: + return [document.reporter.warning( + 'Object named %r not found in include file %r' % + (objectname, filename), line=self.lineno)] + else: + lines = lines[tags[objectname][1]-1 : tags[objectname][2]-1] + + linespec = self.options.get('lines') + if linespec is not None: + try: + linelist = parselinenos(linespec, len(lines)) + except ValueError, err: + return [document.reporter.warning(str(err), line=self.lineno)] + lines = [lines[i] for i in linelist] + + startafter = self.options.get('start-after') + endbefore = self.options.get('end-before') + if startafter is not None or endbefore is not None: + use = not startafter + res = [] + for line in lines: + if not use and startafter in line: + use = True + elif use and endbefore in line: + use = False + break + elif use: + res.append(line) + lines = res + + text = ''.join(lines) + retnode = nodes.literal_block(text, text, source=fn) + retnode.line = 1 + 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] + + +directives.register_directive('highlight', Highlight) +directives.register_directive('highlightlang', Highlight) # old name +directives.register_directive('code-block', CodeBlock) +directives.register_directive('sourcecode', CodeBlock) +directives.register_directive('literalinclude', LiteralInclude) |