diff --git a/CHANGES b/CHANGES index 9eb401173..21abcc4d9 100644 --- a/CHANGES +++ b/CHANGES @@ -167,6 +167,8 @@ Features added * #1341 the HTML search considers words that contain a search term of length three or longer a match. * #4611: epub: Show warning for duplicated ToC entries +* #1851: Allow to omit an argument for :rst:dir:`code-block` directive. If + omitted, it follows :rst:dir:`highlight` or :confval:`highlight_language` Bugs fixed ---------- diff --git a/doc/usage/restructuredtext/directives.rst b/doc/usage/restructuredtext/directives.rst index 947146dd2..85ee22ae9 100644 --- a/doc/usage/restructuredtext/directives.rst +++ b/doc/usage/restructuredtext/directives.rst @@ -463,7 +463,7 @@ __ http://pygments.org/docs/lexers/ This will produce line numbers for all code blocks longer than five lines. -.. rst:directive:: .. code-block:: language +.. rst:directive:: .. code-block:: [language] Example:: @@ -471,9 +471,11 @@ __ http://pygments.org/docs/lexers/ Some Ruby code. - The directive's alias name :rst:dir:`sourcecode` works as well. As with - :rst:dir:`highlight`\ 's ``language`` option, ``language`` can be any lexer - alias supported by Pygments. + The directive's alias name :rst:dir:`sourcecode` works as well. This + directive takes a language name as an argument. It can be any lexer alias + supported by Pygments. If it is not given, the setting of + :rst:dir:`highlight` directive will be used. If not set, + :confval:`highlight_language` will be used. **Additional options** @@ -533,6 +535,9 @@ __ http://pygments.org/docs/lexers/ .. versionchanged:: 1.6.6 LaTeX supports the ``emphasize-lines`` option. + .. versionchanged:: 2.0 + The ``language`` argument becomes optional. + .. rst:directive:: .. literalinclude:: filename Longer displays of verbatim text may be included by storing the example text diff --git a/sphinx/directives/code.py b/sphinx/directives/code.py index 106d400b9..9ac704c55 100644 --- a/sphinx/directives/code.py +++ b/sphinx/directives/code.py @@ -47,9 +47,11 @@ class Highlight(SphinxDirective): def run(self): # type: () -> List[nodes.Node] + language = self.arguments[0].strip() linenothreshold = self.options.get('linenothreshold', sys.maxsize) - return [addnodes.highlightlang(lang=self.arguments[0].strip(), - linenothreshold=linenothreshold)] + + self.env.temp_data['highlight_language'] = language + return [addnodes.highlightlang(lang=language, linenothreshold=linenothreshold)] class HighlightLang(Highlight): @@ -110,8 +112,8 @@ class CodeBlock(SphinxDirective): """ has_content = True - required_arguments = 1 - optional_arguments = 0 + required_arguments = 0 + optional_arguments = 1 final_argument_whitespace = False option_spec = { 'linenos': directives.flag, @@ -152,10 +154,20 @@ class CodeBlock(SphinxDirective): code = '\n'.join(lines) literal = nodes.literal_block(code, code) # type: nodes.Element - literal['language'] = self.arguments[0] literal['linenos'] = 'linenos' in self.options or \ 'lineno-start' in self.options literal['classes'] += self.options.get('class', []) + if self.arguments: + # highlight language specified + literal['language'] = self.arguments[0] + literal['force_highlighting'] = True + else: + # no highlight language specified. Then this directive refers the current + # highlight setting via ``highlight`` directive or ``highlight_language`` + # configuration. + literal['language'] = self.env.temp_data.get('highlight_language', + self.config.highlight_language) + literal['force_highlighting'] = False extra_args = literal['highlight_args'] = {} if hl_lines is not None: extra_args['hl_lines'] = hl_lines diff --git a/sphinx/transforms/post_transforms/code.py b/sphinx/transforms/post_transforms/code.py index c873dd5bc..fb8533e9c 100644 --- a/sphinx/transforms/post_transforms/code.py +++ b/sphinx/transforms/post_transforms/code.py @@ -89,7 +89,7 @@ class HighlightLanguageVisitor(nodes.NodeVisitor): if 'language' not in node: node['language'] = setting.language node['force_highlighting'] = False - else: + elif 'force_highlighting' not in node: node['force_highlighting'] = True if 'linenos' not in node: lines = node.astext().count('\n') diff --git a/tests/roots/test-directive-code/highlight.rst b/tests/roots/test-directive-code/highlight.rst new file mode 100644 index 000000000..4191b58c4 --- /dev/null +++ b/tests/roots/test-directive-code/highlight.rst @@ -0,0 +1,20 @@ +highlight +--------- + +.. code-block:: + + "A code-block without no language" + +.. code-block:: python2 + + "A code-block with language argument" + +.. highlight:: python3 + +.. code-block:: + + "A code-block without no language after highlight directive" + +.. code-block:: python2 + + "A code-block without language argument after highlight directive" diff --git a/tests/test_directive_code.py b/tests/test_directive_code.py index 6e60d0e9b..8627820b9 100644 --- a/tests/test_directive_code.py +++ b/tests/test_directive_code.py @@ -11,6 +11,7 @@ import os import pytest +from docutils import nodes from sphinx.config import Config from sphinx.directives.code import LiteralIncludeReader @@ -552,3 +553,15 @@ def test_literalinclude_pydecorators(app, status, warning): ' pass\n' ) assert actual == expect + + +@pytest.mark.sphinx('dummy', testroot='directive-code') +def test_code_block_highlighted(app, status, warning): + app.builder.build(['highlight']) + doctree = app.env.get_doctree('highlight') + codeblocks = doctree.traverse(nodes.literal_block) + + assert codeblocks[0]['language'] == 'default' + assert codeblocks[1]['language'] == 'python2' + assert codeblocks[2]['language'] == 'python3' + assert codeblocks[3]['language'] == 'python2'