Function: diff-find-source-location
diff-find-source-location is a byte-compiled function defined in
diff-mode.el.gz.
Signature
(diff-find-source-location &optional OTHER-FILE REVERSE NOPROMPT)
Documentation
Find current diff location within the source file.
OTHER-FILE, if non-nil, means to look at the diff's name and line
numbers for the old file. Furthermore, use diff-vc-revisions
if it's available. If diff-jump-to-old-file is non-nil, the
sense of this parameter is reversed. If OTHER-FILE considered
as a raw prefix argument has a numeric value bigger than 8,
toggle diff-jump-to-old-file for the remainder of this Emacs
session, i.e., set it to nil if it's non-nil, non-nil if it's nil.
REVERSE, if non-nil, switches the sense of SRC and DST (see below).
NOPROMPT, if non-nil, means not to prompt the user.
Return a list (BUF LINE-OFFSET (BEG . END) SRC DST SWITCHED).
BUF is the buffer corresponding to the source file.
LINE-OFFSET is the offset between the expected and actual positions
of the text of the hunk or nil if the text was not found.
(BEG . END) is a pair indicating the position of the text in the buffer.
SRC and DST are the two variants of text as returned by diff-hunk-text.
SRC is the variant that was found in the buffer.
SWITCHED is non-nil if the patch is already applied.
Source Code
;; Defined in /usr/src/emacs/lisp/vc/diff-mode.el.gz
(defun diff-find-source-location (&optional other-file reverse noprompt)
"Find current diff location within the source file.
OTHER-FILE, if non-nil, means to look at the diff's name and line
numbers for the old file. Furthermore, use `diff-vc-revisions'
if it's available. If `diff-jump-to-old-file' is non-nil, the
sense of this parameter is reversed. If OTHER-FILE considered
as a raw prefix argument has a numeric value bigger than 8,
toggle `diff-jump-to-old-file' for the remainder of this Emacs
session, i.e., set it to nil if it's non-nil, non-nil if it's nil.
REVERSE, if non-nil, switches the sense of SRC and DST (see below).
NOPROMPT, if non-nil, means not to prompt the user.
Return a list (BUF LINE-OFFSET (BEG . END) SRC DST SWITCHED).
BUF is the buffer corresponding to the source file.
LINE-OFFSET is the offset between the expected and actual positions
of the text of the hunk or nil if the text was not found.
\(BEG . END) is a pair indicating the position of the text in the buffer.
SRC and DST are the two variants of text as returned by `diff-hunk-text'.
SRC is the variant that was found in the buffer.
SWITCHED is non-nil if the patch is already applied."
(save-excursion
(let* ((other (xor other-file diff-jump-to-old-file))
(char-offset (- (point) (diff-beginning-of-hunk t)))
;; Check that the hunk is well-formed. Otherwise diff-mode and
;; the user may disagree on what constitutes the hunk
;; (e.g. because an empty line truncates the hunk mid-course),
;; leading to potentially nasty surprises for the user.
;;
;; Suppress check when NOPROMPT is non-nil (Bug#3033).
(_ (unless noprompt (diff-sanity-check-hunk)))
(hunk (buffer-substring
(point) (save-excursion (diff-end-of-hunk) (point))))
(old (diff-hunk-text hunk reverse char-offset))
(new (diff-hunk-text hunk (not reverse) char-offset))
;; Find the location specification.
(line (if (not (looking-at "\\(?:\\*\\{15\\}.*\n\\)?[-@* ]*\\([0-9,]+\\)\\([ acd+]+\\([0-9,]+\\)\\)?"))
(error "Can't find the hunk header")
(if other (match-string 1)
(if (match-end 3) (match-string 3)
(unless (re-search-forward
diff-context-mid-hunk-header-re nil t)
(error "Can't find the hunk separator"))
(match-string 1)))))
(file (or (diff-find-file-name other noprompt)
(error "Can't find the file")))
(revision (and other diff-vc-backend
(if reverse (nth 1 diff-vc-revisions)
(or (nth 0 diff-vc-revisions)
;; When diff shows changes in working revision
(vc-working-revision file)))))
(buf (if revision
(let ((vc-find-revision-no-save t))
(vc-find-revision (expand-file-name file) revision diff-vc-backend))
;; NOPROMPT is only non-nil when called from
;; `which-function-mode', so avoid "File x changed
;; on disk. Reread from disk?" warnings.
(find-file-noselect file noprompt))))
;; Update the user preference if he so wished.
(when (> (prefix-numeric-value other-file) 8)
(setq diff-jump-to-old-file other))
(with-current-buffer buf
(goto-char (point-min)) (forward-line (1- (string-to-number line)))
(let* ((orig-pos (point))
(switched nil)
(maybe-old (diff-find-text (car old)))
(maybe-new (diff-find-text (car new)))
(pos (or (and maybe-new maybe-old (null reverse) (setq switched t) maybe-new)
maybe-old
(progn (setq switched t) maybe-new)
(progn (setq switched nil)
(condition-case nil
(diff-find-approx-text (car old))
(invalid-regexp nil))) ;Regex too big.
(progn (setq switched t)
(condition-case nil
(diff-find-approx-text (car new))
(invalid-regexp nil))) ;Regex too big.
(progn (setq switched nil) nil))))
(nconc
(list buf)
(if pos
(list (count-lines orig-pos (car pos)) pos)
(list nil (cons orig-pos (+ orig-pos (length (car old))))))
(if switched (list new old t) (list old new))))))))