3636; ; `diff-hl-previous-hunk' C-x v [
3737; ; `diff-hl-next-hunk' C-x v ]
3838; ; `diff-hl-show-hunk' C-x v *
39+ ; ; `diff-hl-ediff-current-hunk' C-x v e
3940; ; `diff-hl-stage-current-hunk' C-x v S
4041; ; `diff-hl-set-reference-rev'
4142; ; `diff-hl-reset-reference-rev'
@@ -435,6 +436,17 @@ It can be a relative expression as well, such as \"HEAD^\" with Git, or
435436(declare-function vc-git--rev-parse " vc-git" )
436437(declare-function vc-hg-command " vc-hg" )
437438(declare-function vc-bzr-command " vc-bzr" )
439+ (declare-function vc-find-revision-no-save " vc" )
440+ (declare-function ediff-buffers " ediff" )
441+ (declare-function ediff-diff-at-point " ediff-util" )
442+ (declare-function ediff-jump-to-difference " ediff-util" )
443+ (defvar ediff-number-of-differences )
444+
445+ (defun diff-hl--use-git-index-base-p (backend )
446+ " Whether diff-hl should use the Git index as the reference base."
447+ (and (eq backend 'Git )
448+ (not diff-hl-reference-revision)
449+ (not diff-hl-show-staged-changes)))
438450
439451(defun diff-hl-changes-buffer (file backend &optional new-rev bufname )
440452 (diff-hl-with-diff-switches
@@ -443,9 +455,7 @@ It can be a relative expression as well, such as \"HEAD^\" with Git, or
443455(defun diff-hl-diff-against-reference (file backend buffer &optional new-rev )
444456 (cond
445457 ((and (not new-rev)
446- (not diff-hl-reference-revision)
447- (not diff-hl-show-staged-changes)
448- (eq backend 'Git ))
458+ (diff-hl--use-git-index-base-p backend))
449459 (apply #'vc-git-command buffer
450460 (if (diff-hl--use-async-p) 'async 1 )
451461 (list file)
@@ -903,6 +913,54 @@ buffer will show the position corresponding to its current line."
903913 (diff-hl-diff-skip-to line relname)
904914 (setq vc-sentinel-movepoint (point ))))))))
905915
916+ (defun diff-hl--ediff-reference-buffer (file )
917+ " Return the reference buffer for FILE used in Ediff."
918+ (unless file
919+ (user-error " No current file" ))
920+ (let ((backend (vc-backend file)))
921+ (unless backend
922+ (user-error " The buffer is not under version control" ))
923+ (let* ((reference diff-hl-reference-revision)
924+ ; ; Use the index snapshot only when diff-hl hides staged changes.
925+ (use-index (and (diff-hl--use-git-index-base-p backend)
926+ (not diff-hl-highlight-reference-function)))
927+ (buf
928+ (if use-index
929+ (let ((obj (diff-hl-git-index-object-name file)))
930+ (unless obj
931+ (user-error " No index entry for %s" file))
932+ (let ((filename (diff-hl-git-index-revision file obj)))
933+ (find-file-noselect filename)))
934+ (let ((rev (or reference
935+ (assoc-default backend diff-hl-head-revision-alist)
936+ (diff-hl-working-revision file backend))))
937+ (unless rev
938+ (user-error " No reference revision specified" ))
939+ (setq rev (diff-hl-resolved-revision backend rev))
940+ (vc-find-revision-no-save file rev backend)))))
941+ (with-current-buffer buf
942+ (set-buffer-modified-p nil )
943+ (read-only-mode 1 ))
944+ buf)))
945+
946+ ;;;### autoload
947+ (defun diff-hl-ediff-current-hunk ()
948+ " Run Ediff against current comparison base. Jump to hunk at point."
949+ (interactive )
950+ (require 'ediff )
951+ (let* ((pos (point ))
952+ (file (or buffer-file-name
953+ (and-let* ((base (buffer-base-buffer )))
954+ (buffer-file-name base))))
955+ (refbuf (diff-hl--ediff-reference-buffer file))
956+ (startup
957+ (list
958+ (lambda ()
959+ (unless (zerop ediff-number-of-differences)
960+ (ediff-jump-to-difference
961+ (max 1 (ediff-diff-at-point 'B pos))))))))
962+ (ediff-buffers refbuf (current-buffer ) startup 'diff-hl-ediff )))
963+
906964(defun diff-hl-diff-read-revisions (rev1-default )
907965 (let* ((file buffer-file-name)
908966 (files (list file))
@@ -1304,6 +1362,7 @@ Pops up a diff buffer that can be edited to choose the changes to stage."
13041362 (define-key map " [" 'diff-hl-previous-hunk )
13051363 (define-key map " ]" 'diff-hl-next-hunk )
13061364 (define-key map " *" 'diff-hl-show-hunk )
1365+ (define-key map " e" 'diff-hl-ediff-current-hunk )
13071366 (define-key map " {" 'diff-hl-show-hunk-previous )
13081367 (define-key map " }" 'diff-hl-show-hunk-next )
13091368 (define-key map " S" 'diff-hl-stage-dwim )
@@ -1376,7 +1435,8 @@ The value of this variable is a mode line template as in
13761435
13771436(defvar diff-hl-repeat-exceptions '(diff-hl-show-hunk
13781437 diff-hl-show-hunk-previous
1379- diff-hl-show-hunk-next))
1438+ diff-hl-show-hunk-next
1439+ diff-hl-ediff-current-hunk))
13801440
13811441(when (require 'smartrep nil t )
13821442 (declare-function smartrep-define-key 'smartrep )
@@ -1516,9 +1576,7 @@ CONTEXT-LINES is the size of the unified diff context, defaults to 0."
15161576 (backend (or backend (vc-backend file)))
15171577 (temporary-file-directory diff-hl-temporary-directory)
15181578 (rev
1519- (if (and (eq backend 'Git )
1520- (not diff-hl-reference-revision)
1521- (not diff-hl-show-staged-changes))
1579+ (if (diff-hl--use-git-index-base-p backend)
15221580 (diff-hl-git-index-revision
15231581 file
15241582 (diff-hl-git-index-object-name file))
0 commit comments