diff options
author | shimizukawa <shimizukawa@gmail.com> | 2014-08-10 23:03:02 +0900 |
---|---|---|
committer | shimizukawa <shimizukawa@gmail.com> | 2014-08-10 23:03:02 +0900 |
commit | b1d122e2446d16452711023561614869e74fb77f (patch) | |
tree | 661708835e2d98ee78cd12b22c70858728e26732 | |
parent | aa0520d0d8818b58856fabaf1408dfe0fe439235 (diff) | |
download | sphinx-b1d122e2446d16452711023561614869e74fb77f.tar.gz |
* for pull request #258: update CHANGES, add tests, add a document and refactoring.
-rw-r--r-- | CHANGES | 2 | ||||
-rw-r--r-- | doc/markup/code.rst | 16 | ||||
-rw-r--r-- | sphinx/directives/code.py | 34 | ||||
-rw-r--r-- | tests/roots/test-directive-code/conf.py | 3 | ||||
-rw-r--r-- | tests/roots/test-directive-code/dedent.rst | 22 | ||||
-rw-r--r-- | tests/roots/test-directive-code/index.rst | 24 | ||||
-rw-r--r-- | tests/roots/test-directive-code/literal.inc | 13 | ||||
-rw-r--r-- | tests/test_directive_code.py | 131 |
8 files changed, 231 insertions, 14 deletions
@@ -184,6 +184,8 @@ Bugs fixed qualified name. It should be rather easy to change this behaviour and potentially index by namespaces/classes as well. +* PR#258: Add dedent option for :rst:dir:`code-block` and + :rst:dir:`literal-include`. Thanks to Zafar Siddiqui. Documentation ------------- diff --git a/doc/markup/code.rst b/doc/markup/code.rst index 9dafdb18..936080d6 100644 --- a/doc/markup/code.rst +++ b/doc/markup/code.rst @@ -208,6 +208,22 @@ additional feature that if you leave the value empty, the shown filename will be exactly the one given as an argument. +Dedent +^^^^^^ + +.. versionadded:: 1.3 + +A ``dedent`` option can be given to strip a precedence characters from the code +block. For example:: + + .. literalinclude:: example.rb + :language: ruby + :dedent: 4 + :lines: 10-15 + +:rst:dir:`code-block` also supports the ``dedent`` option. + + .. rubric:: Footnotes .. [1] There is a standard ``.. include`` directive, but it raises errors if the diff --git a/sphinx/directives/code.py b/sphinx/directives/code.py index a3e32be1..7f08b814 100644 --- a/sphinx/directives/code.py +++ b/sphinx/directives/code.py @@ -44,6 +44,21 @@ class Highlight(Directive): linenothreshold=linenothreshold)] + +def dedent_lines(lines, dedent): + if not dedent: + return lines + + new_lines = [] + for line in lines: + new_line = line[dedent:] + if line.endswith('\n') and not new_line: + new_line = '\n' # keep CRLF + new_lines.append(new_line) + + return new_lines + + class CodeBlock(Directive): """ Directive for a code block with special highlighting or line numbering @@ -77,13 +92,9 @@ class CodeBlock(Directive): hl_lines = None if 'dedent' in self.options: - linesArray = code.split('\n') - for i in range(0, len(linesArray)): - if len(linesArray[i]) <= self.options['dedent']: - linesArray[i] = linesArray[i][len(linesArray[i]) - 1:] - else: - linesArray[i] = linesArray[i][self.options['dedent']:] - code = '\n'.join(linesArray) + lines = code.split('\n') + lines = dedent_lines(lines, self.options['dedent']) + code = '\n'.join(lines) literal = nodes.literal_block(code, code) literal['language'] = self.arguments[0] @@ -113,7 +124,7 @@ class LiteralInclude(Directive): optional_arguments = 0 final_argument_whitespace = True option_spec = { - 'dedent': int, + 'dedent': int, 'linenos': directives.flag, 'lineno-start': int, 'tab-width': int, @@ -149,12 +160,7 @@ class LiteralInclude(Directive): f = codecs.StreamReaderWriter(open(filename, 'rb'), codec_info[2], codec_info[3], 'strict') lines = f.readlines() - if 'dedent' in self.options: - for i in range(0, len(lines)): - if len(lines[i]) <= self.options['dedent']: - lines[i] = lines[i][len(lines[i]) - 1:] - else: - lines[i] = lines[i][self.options['dedent']:] + lines = dedent_lines(lines, self.options.get('dedent')) except (IOError, OSError): return [document.reporter.warning( 'Include file %r not found or reading it failed' % filename, diff --git a/tests/roots/test-directive-code/conf.py b/tests/roots/test-directive-code/conf.py new file mode 100644 index 00000000..f81c30bc --- /dev/null +++ b/tests/roots/test-directive-code/conf.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +master_doc = 'index' diff --git a/tests/roots/test-directive-code/dedent.rst b/tests/roots/test-directive-code/dedent.rst new file mode 100644 index 00000000..d29e2cfa --- /dev/null +++ b/tests/roots/test-directive-code/dedent.rst @@ -0,0 +1,22 @@ +Dedent +====== + +Code blocks +----------- + +.. code-block:: ruby + :linenos: + :dedent: 4 + + def ruby? + false + end + + +Literal Include +--------------- + +.. literalinclude:: literal.inc + :language: python + :lines: 10-11 + :dedent: 4 diff --git a/tests/roots/test-directive-code/index.rst b/tests/roots/test-directive-code/index.rst new file mode 100644 index 00000000..ac7e519e --- /dev/null +++ b/tests/roots/test-directive-code/index.rst @@ -0,0 +1,24 @@ +test-directive-code +=================== + +.. toctree:: + + * + + +Code blocks +----------- + +.. code-block:: ruby + :linenos: + + def ruby? + false + end + + +Literal Includes +---------------- + +.. literalinclude:: literal.inc + :language: python diff --git a/tests/roots/test-directive-code/literal.inc b/tests/roots/test-directive-code/literal.inc new file mode 100644 index 00000000..694f15ed --- /dev/null +++ b/tests/roots/test-directive-code/literal.inc @@ -0,0 +1,13 @@ +# Literally included file using Python highlighting +# -*- coding: utf-8 -*- + +foo = "Including Unicode characters: üöä" + +class Foo: + pass + +class Bar: + def baz(): + pass + +def bar(): pass diff --git a/tests/test_directive_code.py b/tests/test_directive_code.py new file mode 100644 index 00000000..bc2609df --- /dev/null +++ b/tests/test_directive_code.py @@ -0,0 +1,131 @@ +# -*- coding: utf-8 -*-
+"""
+ test_directive_code
+ ~~~~~~~~~~~~~~~~~~~
+
+ Test the code-block directive.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import re
+from xml.etree import ElementTree
+
+from util import with_app, test_roots
+
+
+def teardown_module():
+ (test_roots / 'test-directive-code' / '_build').rmtree(True)
+
+
+@with_app(buildername='xml',
+ srcdir=(test_roots / 'test-directive-code'),
+ _copy_to_temp=True)
+def test_code_block(app):
+ app.builder.build('index')
+ et = ElementTree.parse(app.outdir / 'index.xml')
+ secs = et.findall('/section/section')
+ code_block = secs[0].findall('literal_block')
+ assert len(code_block) > 0
+ actual = code_block[0].text
+ expect = (
+ " def ruby?\n" +
+ " false\n" +
+ " end"
+ )
+ assert actual == expect
+
+
+@with_app(buildername='xml',
+ srcdir=(test_roots / 'test-directive-code'),
+ _copy_to_temp=True)
+def test_code_block_dedent(app):
+ outdir = app.outdir
+
+ def get_dedent_actual(dedent):
+ dedent_text = (app.srcdir / 'dedent.rst').text(encoding='utf-8')
+ dedent_text = re.sub(
+ r':dedent: \d', ':dedent: %d' % dedent, dedent_text)
+ (app.srcdir / 'dedent.rst').write_text(dedent_text, encoding='utf-8')
+
+ # use another output dir to force rebuild
+ app.outdir = outdir / str(dedent)
+ app._init_env(freshenv=True)
+ app._init_builder(app.builder.name)
+ app.builder.build(['dedent'], method='specific')
+
+ et = ElementTree.parse(app.outdir / 'dedent.xml')
+ secs = et.findall('/section/section')
+ code_block = secs[0].findall('literal_block')
+
+ assert len(code_block) > 0
+ actual = code_block[0].text
+ return actual
+
+ for i in range(5): # 0-4
+ actual = get_dedent_actual(i)
+ indent = " " * (4 - i)
+ expect = (
+ indent + "def ruby?\n" +
+ indent + " false\n" +
+ indent + "end"
+ )
+ assert (i, actual) == (i, expect)
+
+ actual = get_dedent_actual(1000)
+ assert actual == '\n\n'
+
+
+@with_app(buildername='xml',
+ srcdir=(test_roots / 'test-directive-code'),
+ _copy_to_temp=True)
+def test_literal_include(app):
+ app.builder.build('index')
+ et = ElementTree.parse(app.outdir / 'index.xml')
+ secs = et.findall('/section/section')
+ literal_include = secs[1].findall('literal_block')
+ literal_src = (app.srcdir / 'literal.inc').text(encoding='utf-8')
+ assert len(literal_include) > 0
+ actual = literal_include[0].text
+ assert actual == literal_src
+
+
+@with_app(buildername='xml',
+ srcdir=(test_roots / 'test-directive-code'),
+ _copy_to_temp=True)
+def test_literal_include_dedent(app):
+ outdir = app.outdir
+ literal_src = (app.srcdir / 'literal.inc').text(encoding='utf-8')
+ literal_lines = [l[4:] for l in literal_src.split('\n')[9:11]]
+
+ def get_dedent_actual(dedent):
+ dedent_text = (app.srcdir / 'dedent.rst').text(encoding='utf-8')
+ dedent_text = re.sub(
+ r':dedent: \d', ':dedent: %d' % dedent, dedent_text)
+ (app.srcdir / 'dedent.rst').write_text(dedent_text, encoding='utf-8')
+
+ # use another output dir to force rebuild
+ app.outdir = outdir / str(dedent)
+ app._init_env(freshenv=True)
+ app._init_builder(app.builder.name)
+ app.builder.build(['dedent'])
+
+ et = ElementTree.parse(app.outdir / 'dedent.xml')
+ secs = et.findall('/section/section')
+ literal_include = secs[1].findall('literal_block')
+
+ assert len(literal_include) > 0
+ actual = literal_include[0].text
+ return actual
+
+
+ for i in range(5): # 0-4
+ actual = get_dedent_actual(i)
+ indent = " " * (4 - i)
+ expect = '\n'.join(indent + l for l in literal_lines) + '\n'
+ assert (i, actual) == (i, expect)
+
+
+ actual = get_dedent_actual(1000)
+ assert actual == '\n\n'
|