Function: diff-syntax-fontify-hunk
diff-syntax-fontify-hunk is a byte-compiled function defined in
diff-mode.el.gz.
Signature
(diff-syntax-fontify-hunk BEG END OLD)
Documentation
Highlight source language syntax in diff hunk between BEG and END.
When OLD is non-nil, highlight the hunk from the old source.
Source Code
;; Defined in /usr/src/emacs/lisp/vc/diff-mode.el.gz
(defun diff-syntax-fontify-hunk (beg end old)
"Highlight source language syntax in diff hunk between BEG and END.
When OLD is non-nil, highlight the hunk from the old source."
(goto-char beg)
(let* ((hunk (buffer-substring-no-properties beg end))
;; Trim a trailing newline to find hunk in diff-syntax-fontify-props
;; in diffs that have no newline at end of diff file.
(text (string-trim-right
(or (with-demoted-errors "Error getting hunk text: %S"
(diff-hunk-text hunk (not old) nil))
"")))
(line (if (looking-at "\\(?:\\*\\{15\\}.*\n\\)?[-@* ]*\\([0-9,]+\\)\\([ acd+]+\\([0-9,]+\\)\\)?")
(if old (match-string 1)
(if (match-end 3) (match-string 3) (match-string 1)))))
(line-nb (when line
(if (string-match "\\([0-9]+\\),\\([0-9]+\\)" line)
(list (string-to-number (match-string 1 line))
(string-to-number (match-string 2 line)))
(list (string-to-number line) 1)))) ; One-line diffs
(props
(or
(when (and diff-vc-backend
(not (eq diff-font-lock-syntax 'hunk-only)))
(let* ((file (diff-find-file-name old t))
(file (and file (expand-file-name file)))
(revision (and file (if (not old) (nth 1 diff-vc-revisions)
(or (nth 0 diff-vc-revisions)
(vc-working-revision file))))))
(when file
(if (not revision)
;; Get properties from the current working revision
(when (and (not old) (file-readable-p file)
(file-regular-p file))
(let ((buf (get-file-buffer file)))
;; Try to reuse an existing buffer
(if buf
(with-current-buffer buf
(diff-syntax-fontify-props nil text line-nb))
;; Get properties from the file.
(with-current-buffer (get-buffer-create
" *diff-syntax-file*")
(let ((attrs (file-attributes file)))
(if (equal diff--syntax-file-attributes attrs)
;; Same file as last-time, unmodified.
;; Reuse buffer as-is.
(setq file nil)
(erase-buffer)
(insert-file-contents file)
(setq diff--syntax-file-attributes attrs)))
(diff-syntax-fontify-props file text line-nb)))))
(diff--get-revision-properties file revision
text line-nb)))))
(let ((file (car (diff-hunk-file-names old))))
(cond
((and file diff-default-directory
(not (eq diff-font-lock-syntax 'hunk-only))
(not diff-vc-backend)
(file-readable-p file) (file-regular-p file))
;; Try to get full text from the file.
(with-temp-buffer
(insert-file-contents file)
(diff-syntax-fontify-props file text line-nb)))
;; Otherwise, get properties from the hunk alone
((memq diff-font-lock-syntax '(hunk-also hunk-only))
(with-temp-buffer
(insert text)
(diff-syntax-fontify-props file text line-nb t))))))))
;; Put properties over the hunk text
(goto-char beg)
(when (and props (eq (diff-hunk-style) 'unified))
(while (< (progn (forward-line 1) (point)) end)
;; Skip the "\ No newline at end of file" lines as well as the lines
;; corresponding to the "other" version.
(unless (looking-at-p (if old "[+>\\]" "[-<\\]"))
(if (and old (not (looking-at-p "[-<]")))
;; Fontify context lines only from new source,
;; don't refontify context lines from old source.
(pop props)
(let ((line-props (pop props))
(bol (1+ (point))))
(dolist (prop line-props)
;; Ideally, we'd want to use text-properties as in:
;;
;; (add-face-text-property
;; (+ bol (nth 0 prop)) (+ bol (nth 1 prop))
;; (nth 2 prop) 'append)
;;
;; rather than overlays here, but they'd get removed by later
;; font-locking.
;; This is because we also apply faces outside of the
;; beg...end chunk currently font-locked and when font-lock
;; later comes to handle the rest of the hunk that we already
;; handled we don't (want to) redo it (we work at
;; hunk-granularity rather than font-lock's own chunk
;; granularity).
;; I see two ways to fix this:
;; - don't immediately apply the props that fall outside of
;; font-lock's chunk but stash them somewhere (e.g. in another
;; text property) and only later when font-lock comes back
;; move them to `face'.
;; - change the code so work at font-lock's chunk granularity
;; (this seems doable without too much extra overhead,
;; contrary to the refine highlighting, which inherently
;; works at a different granularity).
(let ((ol (make-overlay (+ bol (nth 0 prop))
(+ bol (nth 1 prop))
nil 'front-advance nil)))
(overlay-put ol 'diff-mode 'syntax)
(overlay-put ol 'evaporate t)
(overlay-put ol 'face (nth 2 prop)))))))))))