diff --git a/CHANGES b/CHANGES index 9daae97fc..e8a57a031 100644 --- a/CHANGES +++ b/CHANGES @@ -27,6 +27,10 @@ New features added built documentation, and only written to stderr. If you want the old behavior, set the new config value ``keep_warnings`` to True. +* The new config value ``highlight_language`` set a global default + for highlighting. When ``'python3'`` is selected, console output + blocks are recognized like for ``'python'``. + * ``SerializingHTMLBuilder`` was added as new abstract builder that can be subclassed to serialize build HTML in a specific format. The ``PickleHTMLBuilder`` is a concrete subclass of it that uses diff --git a/doc/config.rst b/doc/config.rst index 3f1007585..176da06ef 100644 --- a/doc/config.rst +++ b/doc/config.rst @@ -212,6 +212,14 @@ Project information %Y'`` (or, if translation is enabled with :confval:`language`, am equivalent %format for the selected locale). +.. confval:: highlight_language + + The default language to highlight source code in. The default is + ``'python'``. The value should be a valid Pygments lexer name, see + :ref:`code-examples` for more details. + + .. versionadded:: 0.5 + .. confval:: pygments_style The style name to use for Pygments highlighting of source code. Default is diff --git a/doc/markup/code.rst b/doc/markup/code.rst index ca8f39bb8..f01070f69 100644 --- a/doc/markup/code.rst +++ b/doc/markup/code.rst @@ -1,5 +1,7 @@ .. highlight:: rest +.. _code-examples: + Showing code examples --------------------- @@ -23,7 +25,9 @@ Syntax highlighting is done with `Pygments `_ (if it's installed) and handled in a smart way: * There is a "highlighting language" for each source file. Per default, this is - ``'python'`` as the majority of files will have to highlight Python snippets. + ``'python'`` as the majority of files will have to highlight Python snippets, + but the doc-wide default can be set with the :confval:`highlight_language` + config value. * Within Python highlighting mode, interactive sessions are recognized automatically and highlighted appropriately. @@ -48,7 +52,7 @@ installed) and handled in a smart way: * The valid values for the highlighting language are: * ``none`` (no highlighting) - * ``python`` (the default) + * ``python`` (the default when :confval:`highlight_language` isn't set) * ``rest`` * ``c`` * ... and any other lexer name that Pygments supports. diff --git a/sphinx/config.py b/sphinx/config.py index 1d0f1085e..ac896424f 100644 --- a/sphinx/config.py +++ b/sphinx/config.py @@ -44,6 +44,7 @@ class Config(object): add_module_names = (True, True), show_authors = (False, True), pygments_style = ('sphinx', False), + highlight_language = ('python', False), templates_path = ([], False), template_bridge = (None, False), keep_warnings = (False, True), diff --git a/sphinx/highlighting.py b/sphinx/highlighting.py index 32217dd8e..a5f703027 100644 --- a/sphinx/highlighting.py +++ b/sphinx/highlighting.py @@ -51,6 +51,9 @@ else: none = TextLexer(), python = PythonLexer(), pycon = PythonConsoleLexer(), + # the python3 option exists as of Pygments 0.12, but it doesn't + # do any harm in previous versions + pycon3 = PythonConsoleLexer(python3=True), rest = RstLexer(), c = CLexer(), ) @@ -106,43 +109,54 @@ class PygmentsBridge(object): return '\\begin{Verbatim}[commandchars=@\\[\\]]\n' + \ source + '\\end{Verbatim}\n' + def try_parse(self, src): + # Make sure it ends in a newline + src += '\n' + + # Replace "..." by a mark which is also a valid python expression + # (Note, the highlighter gets the original source, this is only done + # to allow "..." in code and still highlight it as Python code.) + mark = "__highlighting__ellipsis__" + src = src.replace("...", mark) + + # lines beginning with "..." are probably placeholders for suite + src = re.sub(r"(?m)^(\s*)" + mark + "(.)", r"\1"+ mark + r"# \2", src) + + # if we're using 2.5, use the with statement + if sys.version_info >= (2, 5): + src = 'from __future__ import with_statement\n' + src + + if isinstance(src, unicode): + # Non-ASCII chars will only occur in string literals + # and comments. If we wanted to give them to the parser + # correctly, we'd have to find out the correct source + # encoding. Since it may not even be given in a snippet, + # just replace all non-ASCII characters. + src = src.encode('ascii', 'replace') + + try: + parser.suite(src) + except parsing_exceptions: + return False + else: + return True + def highlight_block(self, source, lang, linenos=False): if not pygments: return self.unhighlighted(source) - if lang == 'python': + if lang in ('py', 'python'): if source.startswith('>>>'): # interactive session lexer = lexers['pycon'] else: # maybe Python -- try parsing it - src = source + '\n' - - # Replace "..." by a mark which is also a valid python expression - # (Note, the highlighter gets the original source, this is only done - # to allow "..." in code and still highlight it as Python code.) - mark = "__highlighting__ellipsis__" - src = src.replace("...", mark) - - # lines beginning with "..." are probably placeholders for suite - src = re.sub(r"(?m)^(\s*)" + mark + "(.)", r"\1"+ mark + r"# \2", src) - - # if we're using 2.5, use the with statement - if sys.version_info >= (2, 5): - src = 'from __future__ import with_statement\n' + src - - if isinstance(src, unicode): - # Non-ASCII chars will only occur in string literals - # and comments. If we wanted to give them to the parser - # correctly, we'd have to find out the correct source - # encoding. Since it may not even be given in a snippet, - # just replace all non-ASCII characters. - src = src.encode('ascii', 'replace') - try: - parser.suite(src) - except parsing_exceptions: - return self.unhighlighted(source) - else: + if self.try_parse(source): lexer = lexers['python'] + else: + return self.unhighlighted(source) + elif lang in ('python3', 'py3') and source.startswith('>>>'): + # for py3, recognize interactive sessions, but do not try parsing... + lexer = lexers['pycon3'] else: if lang in lexers: lexer = lexers[lang] diff --git a/sphinx/htmlwriter.py b/sphinx/htmlwriter.py index 8eb3dad4f..424441afb 100644 --- a/sphinx/htmlwriter.py +++ b/sphinx/htmlwriter.py @@ -49,7 +49,7 @@ class HTMLTranslator(BaseTranslator): self.highlighter = PygmentsBridge('html', builder.config.pygments_style) self.no_smarty = 0 self.builder = builder - self.highlightlang = 'python' + self.highlightlang = builder.config.highlight_language self.highlightlinenothreshold = sys.maxint self.protect_literal_text = 0 diff --git a/sphinx/latexwriter.py b/sphinx/latexwriter.py index 196ed6d9a..136e50786 100644 --- a/sphinx/latexwriter.py +++ b/sphinx/latexwriter.py @@ -157,7 +157,7 @@ class LaTeXTranslator(nodes.NodeVisitor): self.bibitems = [] self.table = None self.next_table_colspec = None - self.highlightlang = 'python' + self.highlightlang = builder.config.highlight_language self.highlightlinenothreshold = sys.maxint self.written_ids = set() if docclass == 'manual':