Function: diff--refine-hunk
diff--refine-hunk is a byte-compiled function defined in
diff-mode.el.gz.
Signature
(diff--refine-hunk START END &optional SKIP-IF-LARGE)
Source Code
;; Defined in /usr/src/emacs/lisp/vc/diff-mode.el.gz
(defun diff--refine-hunk (start end &optional skip-if-large)
(require 'smerge-mode)
(goto-char start)
(let* ((style (diff-hunk-style)) ;Skips the hunk header as well.
(beg (point))
(props-c '((diff-mode . fine) (face . diff-refine-changed)))
(props-r '((diff-mode . fine) (face . diff-refine-removed)))
(props-a '((diff-mode . fine) (face . diff-refine-added))))
(remove-overlays beg end 'diff-mode 'fine)
(goto-char beg)
(pcase style
((guard (and skip-if-large
;; FIXME: Maybe instead of testing the hunk size, we
;; should test the size of each individual "delete+insert"
;; pairs, since a big hunk with many small del+ins pairs
;; should not suffer from the usual pathological
;; complexity problems.
;; Or maybe even push the test down into
;; `smerge-refine-regions' where `smerge-mode' could
;; also use it?
(> (- end beg) diff-refine-threshold)))
nil)
('unified
(while (re-search-forward "^[-+]" end t)
(let ((beg-del (progn (beginning-of-line) (point)))
beg-add end-add)
(cond
((eq (char-after) ?+)
(diff--forward-while-leading-char ?+ end)
(when diff-refine-nonmodified
(diff--refine-propertize beg-del (point) 'diff-refine-added)))
((and (diff--forward-while-leading-char ?- end)
;; Allow for "\ No newline at end of file".
(progn (diff--forward-while-leading-char ?\\ end)
(setq beg-add (point)))
(diff--forward-while-leading-char ?+ end)
(progn (diff--forward-while-leading-char ?\\ end)
(setq end-add (point))))
(smerge-refine-regions beg-del beg-add beg-add end-add
nil #'diff-refine-preproc props-r props-a))
(t ;; If we're here, it's because
;; (diff--forward-while-leading-char ?+ end) failed.
(when diff-refine-nonmodified
(diff--refine-propertize beg-del (point)
'diff-refine-removed)))))))
('context
(let* ((middle (save-excursion (re-search-forward "^---" end t)))
(other middle))
(when middle
(while (re-search-forward "^\\(?:!.*\n\\)+" middle t)
(smerge-refine-regions (match-beginning 0) (match-end 0)
(save-excursion
(goto-char other)
(re-search-forward "^\\(?:!.*\n\\)+" end)
(setq other (match-end 0))
(match-beginning 0))
other
(if diff-use-changed-face props-c)
#'diff-refine-preproc
(unless diff-use-changed-face props-r)
(unless diff-use-changed-face props-a)))
(when diff-refine-nonmodified
(goto-char beg)
(while (re-search-forward "^\\(?:-.*\n\\)+" middle t)
(diff--refine-propertize (match-beginning 0)
(match-end 0)
'diff-refine-removed))
(goto-char middle)
(while (re-search-forward "^\\(?:\\+.*\n\\)+" end t)
(diff--refine-propertize (match-beginning 0)
(match-end 0)
'diff-refine-added))))))
(_ ;; Normal diffs.
(let ((beg1 (1+ (point))))
(cond
((re-search-forward "^---.*\n" end t)
;; It's a combined add&remove, so there's something to do.
(smerge-refine-regions beg1 (match-beginning 0)
(match-end 0) end
nil #'diff-refine-preproc props-r props-a))
(diff-refine-nonmodified
(diff--refine-propertize
beg1 end
(if (eq (char-after beg1) ?<)
'diff-refine-removed 'diff-refine-added)))))))))