diff --git a/src/diff_shades/_diff.py b/src/diff_shades/_diff.py index 7905206..db1e4fc 100644 --- a/src/diff_shades/_diff.py +++ b/src/diff_shades/_diff.py @@ -105,7 +105,6 @@ def marker_style(self) -> dict[str, Union[dict[str, str], str]]: }[self.theme] def raw_unified_diff(self) -> Iterator[str]: - differ = difflib.Differ() lines_lhs = self.lhs.splitlines() lines_rhs = self.rhs.splitlines() return unified_diff( @@ -171,13 +170,7 @@ def build_unified_diff(self) -> RenderResult: for line in diff: if line.startswith("---"): - output_lines.append( - Panel( - line, - box=box.DOUBLE, - style="bold", - ) - ) + output_lines.append(Text(line, style="bold")) elif line.startswith("@@"): output_lines.append( Panel( diff --git a/src/diff_shades/cli.py b/src/diff_shades/cli.py index 08d0b66..9360779 100644 --- a/src/diff_shades/cli.py +++ b/src/diff_shades/cli.py @@ -27,6 +27,7 @@ import diff_shades import diff_shades.results +from diff_shades._diff import Diff from diff_shades.analysis import ( GIT_BIN, RESULT_COLORS, @@ -36,7 +37,6 @@ ) from diff_shades.config import PROJECTS, Project from diff_shades.output import ( - color_diff, make_analysis_summary, make_comparison_summary, make_project_details_table, @@ -101,7 +101,7 @@ def compare_project_pair( found_difference = True diff = diff_two_results(r1, r2, file=f"{project.name}:{file}", diff_failure=True) - console.print(color_diff(diff), highlight=False) + console.print(diff) return found_difference @@ -355,7 +355,7 @@ def show( console.print(escape(result.log), highlight=False) elif result.type == "reformatted": diff = result.diff(file_key) - console.print(color_diff(diff), highlight=False) + console.print(diff) elif project_key and not file_key: # TODO: implement a list view diff --git a/src/diff_shades/output.py b/src/diff_shades/output.py index 55497b8..9628d21 100644 --- a/src/diff_shades/output.py +++ b/src/diff_shades/output.py @@ -8,7 +8,6 @@ from typing import Sequence, Tuple, cast import rich -from rich.markup import escape from rich.panel import Panel from rich.progress import BarColumn, Progress, TimeElapsedColumn from rich.table import Table @@ -26,22 +25,6 @@ console = rich.get_console() -def color_diff(contents: str) -> str: - """Inject rich markup into the diff.""" - lines = escape(contents).split("\n") - for i, line in enumerate(lines): - if line.startswith("+++") or line.startswith("---"): - line = "[bold]" + line + "[/]" - elif line.startswith("@@"): - line = "[cyan]" + line + "[/]" - elif line.startswith("+"): - line = "[green]" + line + "[/]" - elif line.startswith("-"): - line = "[red]" + line + "[/]" - lines[i] = line - return "\n".join(lines) - - def make_rich_progress() -> Progress: return Progress( "[progress.description]{task.description}", diff --git a/src/diff_shades/results.py b/src/diff_shades/results.py index c8f18c1..1d71e92 100644 --- a/src/diff_shades/results.py +++ b/src/diff_shades/results.py @@ -2,7 +2,6 @@ # > Analysis data representation & processing # ========================================== -import difflib import hashlib import json import pickle @@ -33,6 +32,7 @@ import platformdirs import diff_shades +from diff_shades._diff import Diff from diff_shades.config import Project CACHE_DIR: Final = Path(platformdirs.user_cache_dir("diff-shades")) @@ -42,30 +42,15 @@ ResultTypes = Literal["nothing-changed", "reformatted", "failed"] -def unified_diff(a: str, b: str, a_name: str, b_name: str) -> str: - """Return a unified diff string between strings `a` and `b`.""" - a_lines = a.splitlines(keepends=True) - b_lines = b.splitlines(keepends=True) - diff_lines = [] - for line in difflib.unified_diff(a_lines, b_lines, fromfile=a_name, tofile=b_name, n=5): - # Work around https://bugs.python.org/issue2142. See also: - # https://www.gnu.org/software/diffutils/manual/html_node/Incomplete-Lines.html - if line[-1] == "\n": - diff_lines.append(line) - else: - diff_lines.append(line + "\n") - diff_lines.append("\\ No newline at end of file\n") - return "".join(diff_lines) - - -def calculate_line_changes(diff: str) -> Tuple[int, int]: +def calculate_line_changes(diff: Diff) -> Tuple[int, int]: """Return a two-tuple (additions, deletions) of a diff.""" additions = 0 deletions = 0 - for line in diff.splitlines(): - if line[0] == "+" and not line.startswith("+++"): + raw_diff = "\n".join(diff.raw_unified_diff()) + for line in raw_diff.splitlines(): + if line.startswith("+ "): additions += 1 - elif line[0] == "-" and not line.startswith("---"): + elif line.startswith("- "): deletions += 1 return additions, deletions @@ -108,8 +93,8 @@ def __post_init__(self) -> None: object.__setattr__(self, "line_changes", changes) @lru_cache(maxsize=None) - def diff(self, filepath: str) -> str: - return unified_diff(self.src, self.dst, f"a/{filepath}", f"b/{filepath}") + def diff(self, filepath: str) -> Diff: + return Diff(self.src, self.dst, f"a/{filepath}", f"b/{filepath}") @dataclass(frozen=True) @@ -193,7 +178,7 @@ def diff_two_results( first_dst = r1.dst if r1.type == "reformatted" else r1.src second_dst = r2.dst if r2.type == "reformatted" else r2.src - return unified_diff(first_dst, second_dst, f"a/{file}", f"b/{file}") + return Diff(first_dst, second_dst, f"a/{file}", f"b/{file}") # fmt: off