From 3a1f85cb699353cb44527c27c76ff0313960b937 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 8 May 2018 23:32:21 +0530 Subject: [PATCH] diff: Make the diff implementation configurable --- kittens/diff/diff.conf | 5 +++++ kittens/diff/main.py | 3 ++- kittens/diff/patch.py | 29 +++++++++++++++++++++++++---- 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/kittens/diff/diff.conf b/kittens/diff/diff.conf index 2cfa431cc..199f3f693 100644 --- a/kittens/diff/diff.conf +++ b/kittens/diff/diff.conf @@ -12,6 +12,11 @@ pygments_style default # The number of lines of context to show around each change. num_context_lines 3 +# The diff command to use. Must contain the placeholder _CONTEXT_ +# which will be replaced by the number of lines of context. The default +# is to search the system for either git or diff and use that, if found. +diff_cmd auto + # Colors foreground black background white diff --git a/kittens/diff/main.py b/kittens/diff/main.py index c395a7c3f..11f285dcf 100644 --- a/kittens/diff/main.py +++ b/kittens/diff/main.py @@ -17,7 +17,7 @@ from ..tui.handler import Handler from ..tui.loop import Loop from .collect import create_collection, data_for_path, set_highlight_data from .config import init_config -from .patch import Differ +from .patch import Differ, set_diff_command from .render import LineRef, render_diff try: @@ -299,6 +299,7 @@ def main(args): if os.path.isdir(left) != os.path.isdir(right): raise SystemExit('The items to be diffed should both be either directories or files. Comparing a directory to a file is not valid.') opts = init_config(args) + set_diff_command(opts.diff_cmd) loop = Loop() handler = DiffHandler(args, opts, left, right) diff --git a/kittens/diff/patch.py b/kittens/diff/patch.py index deed213a2..7ea3440a4 100644 --- a/kittens/diff/patch.py +++ b/kittens/diff/patch.py @@ -4,20 +4,41 @@ import concurrent.futures import os +import shlex +import shutil import subprocess from .collect import lines_for_path from .diff_speedup import changed_center left_lines = right_lines = None +GIT_DIFF = 'git diff --no-color --no-ext-diff --exit-code -U_CONTEXT_ --no-index --' +DIFF_DIFF = 'diff -p -U _CONTEXT_ --' + + +def find_differ(): + if shutil.which('git'): + return GIT_DIFF + if shutil.which('diff'): + return DIFF_DIFF + + +def set_diff_command(opt): + if opt == 'auto': + cmd = find_differ() + if cmd is None: + raise SystemExit('Failed to find either the git or diff programs on your system') + else: + cmd = opt + set_diff_command.cmd = cmd def run_diff(file1, file2, context=3): # returns: ok, is_different, patch - p = subprocess.Popen([ - 'git', 'diff', '--no-color', '--no-ext-diff', '--exit-code', '-U' + str(context), '--no-index', '--' - ] + [file1, file2], - stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.DEVNULL) + cmd = shlex.split(set_diff_command.cmd.replace('_CONTEXT_', str(context))) + p = subprocess.Popen( + cmd + [file1, file2], + stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.DEVNULL) stdout, stderr = p.communicate() returncode = p.wait() if returncode in (0, 1):