Commits

Takayuki Shimizukawa committed ef50738 Merge

Merged in r_rudi/sphinx (pull request #267)

add 'diff' parameter to literalinclude.

Comments (0)

Files changed (4)

doc/markup/code.rst

    ``prepend`` and ``append`` option, respectively.  This is useful e.g. for
    highlighting PHP code that doesn't include the ``<?php``/``?>`` markers.
 
+
+   If you want to show the diff of the code, you can specify the old
+   file by giving a ``diff`` option::
+
+      .. literalinclude:: example.py
+         :diff: example.py.orig
+
+   This shows the diff between example.py and example.py.orig with unified diff format.
+
+
    .. versionadded:: 0.4.3
       The ``encoding`` option.
    .. versionadded:: 0.6
       as well as support for absolute filenames.
    .. versionadded:: 1.0
       The ``prepend`` and ``append`` options, as well as ``tab-width``.
+   .. versionadded:: 1.3
+      The ``diff`` option.
 
 
 Showing a file name

sphinx/directives/code.py

 
 import sys
 import codecs
+from difflib import unified_diff
 
 from docutils import nodes
 from docutils.parsers.rst import Directive, directives
 
+from six import string_types
+
 from sphinx import addnodes
 from sphinx.util import parselinenos
 from sphinx.util.nodes import set_source_info
         'append': directives.unchanged_required,
         'emphasize-lines': directives.unchanged_required,
         'filename': directives.unchanged,
+        'diff': directives.unchanged_required,
     }
 
+    def read_with_encoding(self, filename, document, codec_info, encoding):
+        f = None
+        try:
+            f = codecs.StreamReaderWriter(open(filename, 'rb'),
+                                          codec_info[2], codec_info[3], 'strict')
+            lines = f.readlines()
+            lines = dedent_lines(lines, self.options.get('dedent'))
+            return lines
+        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))]
+        finally:
+            if f is not None:
+                f.close()
+
     def run(self):
         document = self.state.document
         if not document.settings.file_insertion_enabled:
 
         encoding = self.options.get('encoding', env.config.source_encoding)
         codec_info = codecs.lookup(encoding)
-        f = None
-        try:
-            f = codecs.StreamReaderWriter(open(filename, 'rb'),
-                    codec_info[2], codec_info[3], 'strict')
-            lines = f.readlines()
-            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,
-                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))]
-        finally:
-            if f is not None:
-                f.close()
+
+        lines = self.read_with_encoding(filename, document,
+                                        codec_info, encoding)
+        if not isinstance(lines[0], string_types):
+            return lines
+
+        diffsource = self.options.get('diff')
+        if diffsource is not None:
+            tmp, fulldiffsource = env.relfn2path(diffsource)
+
+            difflines = self.read_with_encoding(fulldiffsource, document,
+                                           codec_info, encoding)
+            if not isinstance(difflines[0], string_types):
+                return difflines
+            diff = unified_diff(
+                difflines,
+                lines,
+                diffsource,
+                self.arguments[0])
+            lines = list(diff)
 
         objectname = self.options.get('pyobject')
         if objectname is not None:
             text = text.expandtabs(self.options['tab-width'])
         retnode = nodes.literal_block(text, text, source=filename)
         set_source_info(self, retnode)
+        if diffsource is not None:  # if diff is set, set udiff
+            retnode['language'] = 'udiff'
         if self.options.get('language', ''):
             retnode['language'] = self.options['language']
         retnode['linenos'] = 'linenos' in self.options or \

tests/root/includes.txt

 .. literalinclude:: literal.inc
    :end-before: class Foo
 
+.. literalinclude:: literal.inc
+   :diff: literal.inc.orig
+
 .. cssclass:: inc-tab3
 .. literalinclude:: tabs.inc
    :tab-width: 3

tests/root/literal.inc.orig

+# Literally included file using Python highlighting
+# -*- coding: utf-8 -*-
+
+foo = "Including Unicode characters: üöä"  # This will be changed
+
+class FooOrig:
+    pass
+
+class BarOrig:
+    def baz():
+        pass
+
+def bar(): pass