|
40 | 40 | # Copytight © 2008 Ned Batchelder
|
41 | 41 | # Licensed under CC-BY-SA
|
42 | 42 | #
|
43 |
| -# strtobool based on the "distutils" module from CPython |
| 43 | +# strtobool based on the "distutils" module from CPython. |
| 44 | +# Some docstrings based on the Python documentation. |
44 | 45 | # Licensed under the Python Software Foundation License Version 2.
|
45 | 46 | # Copyright © 2001-2020 Python Software Foundation. All rights reserved.
|
46 | 47 | # Copyright © 2000 BeOpen.com. All rights reserved.
|
|
49 | 50 | #
|
50 | 51 |
|
51 | 52 | # stdlib
|
| 53 | +import difflib |
52 | 54 | import inspect
|
53 | 55 | import itertools
|
54 | 56 | import sys
|
|
61 | 63 | # this package
|
62 | 64 | import domdf_python_tools.words
|
63 | 65 | from domdf_python_tools import __version__
|
| 66 | +from domdf_python_tools.terminal_colours import Colour, Fore |
64 | 67 | from domdf_python_tools.typing import HasHead, String
|
65 | 68 |
|
66 | 69 | if TYPE_CHECKING:
|
@@ -475,3 +478,86 @@ def head(obj: Union[Tuple, List, "DataFrame", "Series", "String"], n: int = 10)
|
475 | 478 |
|
476 | 479 | else:
|
477 | 480 | return str(obj[:n]) + etc # type: ignore
|
| 481 | + |
| 482 | + |
| 483 | +def coloured_diff( |
| 484 | + a: Sequence[str], |
| 485 | + b: Sequence[str], |
| 486 | + fromfile: str = '', |
| 487 | + tofile: str = '', |
| 488 | + fromfiledate: str = '', |
| 489 | + tofiledate: str = '', |
| 490 | + n: int = 3, |
| 491 | + lineterm: str = '\n', |
| 492 | + removed_colour: Colour = Fore.RED, |
| 493 | + added_colour: Colour = Fore.GREEN, |
| 494 | + ) -> str: |
| 495 | + r""" |
| 496 | + Compare two sequences of lines; generate the delta as a unified diff. |
| 497 | +
|
| 498 | + Unified diffs are a compact way of showing line changes and a few |
| 499 | + lines of context. The number of context lines is set by 'n' which |
| 500 | + defaults to three. |
| 501 | +
|
| 502 | + By default, the diff control lines (those with ---, +++, or @@) are |
| 503 | + created with a trailing newline. This is helpful so that inputs |
| 504 | + created from file.readlines() result in diffs that are suitable for |
| 505 | + file.writelines() since both the inputs and outputs have trailing |
| 506 | + newlines. |
| 507 | +
|
| 508 | + For inputs that do not have trailing newlines, set the lineterm |
| 509 | + argument to "" so that the output will be uniformly newline free. |
| 510 | +
|
| 511 | + The unidiff format normally has a header for filenames and modification |
| 512 | + times. Any or all of these may be specified using strings for |
| 513 | + 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'. |
| 514 | + The modification times are normally expressed in the ISO 8601 format. |
| 515 | +
|
| 516 | + Example: |
| 517 | +
|
| 518 | + >>> for line in coloured_diff('one two three four'.split(), |
| 519 | + ... 'zero one tree four'.split(), 'Original', 'Current', |
| 520 | + ... '2005-01-26 23:30:50', '2010-04-02 10:20:52', |
| 521 | + ... lineterm=''): |
| 522 | + ... print(line) # doctest: +NORMALIZE_WHITESPACE |
| 523 | + --- Original 2005-01-26 23:30:50 |
| 524 | + +++ Current 2010-04-02 10:20:52 |
| 525 | + @@ -1,4 +1,4 @@ |
| 526 | + +zero |
| 527 | + one |
| 528 | + -two |
| 529 | + -three |
| 530 | + +tree |
| 531 | + four |
| 532 | +
|
| 533 | + :param a: |
| 534 | + :param b: |
| 535 | + :param fromfile: |
| 536 | + :param tofile: |
| 537 | + :param fromfiledate: |
| 538 | + :param tofiledate: |
| 539 | + :param n: |
| 540 | + :param lineterm: |
| 541 | + :param removed_colour: The :class:`~domdf_python_tools.terminal_colours.Colour` to use for lines that were removed. |
| 542 | + :param added_colour: The :class:`~domdf_python_tools.terminal_colours.Colour` to use for lines that were added. |
| 543 | +
|
| 544 | + :return: |
| 545 | + """ |
| 546 | + |
| 547 | + # this package |
| 548 | + from domdf_python_tools.stringlist import StringList |
| 549 | + |
| 550 | + buf = StringList() |
| 551 | + diff = difflib.unified_diff(a, b, fromfile, tofile, fromfiledate, tofiledate, n, lineterm) |
| 552 | + |
| 553 | + for line in diff: |
| 554 | + if line.startswith('+'): |
| 555 | + buf.append(added_colour(line)) |
| 556 | + elif line.startswith('-'): |
| 557 | + buf.append(removed_colour(line)) |
| 558 | + else: |
| 559 | + buf.append(line) |
| 560 | + |
| 561 | + buf.blankline(ensure_single=True) |
| 562 | + |
| 563 | + return str(buf) |
0 commit comments