branch: elpa/magit commit 2bc1df5cbe187fcf34caf44ecccc40372685d9bd Author: Jonas Bernoulli <jo...@bernoul.li> Commit: Jonas Bernoulli <jo...@bernoul.li>
magit-diff--locate-file-position: New function Compared to its predecessor, `magit-diff-locate-hunk', this not only tries to locate the appropriate hunk, it also takes care of the next step, which is to locate the position within the hunk, provided we found the appropriate hunk. Previously callers had to take care of that. Because callers may act differently depending on whether they found the exact position, the hunk, or just the file, include the exact locality in the return value. The predecessor already did this, except it only used a boolean, indicating whether a hunk was found or not. Return the position, not the section. --- lisp/magit-diff.el | 65 ++++++++++++++++++++++++++++------------------------ lisp/magit-status.el | 20 ++++++++-------- 2 files changed, 46 insertions(+), 39 deletions(-) diff --git a/lisp/magit-diff.el b/lisp/magit-diff.el index fc794544b66..ea395677825 100644 --- a/lisp/magit-diff.el +++ b/lisp/magit-diff.el @@ -1428,38 +1428,43 @@ for a revision." (with-current-buffer buf (magit-diff--goto-file-position file line col)))))))) -(defun magit-diff--locate-hunk (file line &optional parent) - (and-let* ((diff (cl-find-if (##and (cl-typep % 'magit-file-section) - (equal (oref % value) file)) - (oref (or parent magit-root-section) children)))) - (let ((hunks (oref diff children))) - (cl-block nil - (while-let ((hunk (pop hunks))) - (when-let ((range (oref hunk to-range))) - (pcase-let* ((`(,beg ,len) range) - (end (+ beg len))) - (cond ((> beg line) (cl-return (list diff nil))) - ((<= beg line end) (cl-return (list hunk t))) - ((null hunks) (cl-return (list hunk nil))))))))))) +(defun magit-diff--locate-file-position (file line column &optional parent) + (and-let* + ((diff (cl-find-if (##and (cl-typep % 'magit-file-section) + (equal (oref % value) file)) + (oref (or parent magit-root-section) children))) + (hunks (oref diff children))) + (let (hunk pos found) + (while (and (setq hunk (pop hunks)) + (not pos)) + (when-let* ((range (oref hunk to-range)) + (beg (car range)) + (len (cadr range)) + (end (+ beg len))) + (cond + ((> beg line) + (setq pos (oref diff start))) + ((<= beg line end) + (save-excursion + (goto-char (oref hunk content)) + (let ((l beg)) + (while (or (< l line) + (= (char-after) ?-)) + (unless (= (char-after) ?-) + (cl-incf l)) + (forward-line))) + (setq found (if (= (char-after) ?+) 'line 'hunk)) + (forward-char (1+ column)) + (setq pos (point)))) + ((null hunks) + (setq pos (oref hunk start)))))) + (and pos + (list pos (or found file)))))) (defun magit-diff--goto-file-position (file line column &optional parent) - (when-let ((pos (magit-diff--locate-hunk file line parent))) - (pcase-let ((`(,section ,exact) pos)) - (cond ((cl-typep section 'magit-file-section) - (goto-char (oref section start))) - (exact - (goto-char (oref section content)) - (let ((pos (car (oref section to-range)))) - (while (or (< pos line) - (= (char-after) ?-)) - (unless (= (char-after) ?-) - (cl-incf pos)) - (forward-line))) - (forward-char (1+ column))) - (t - (goto-char (oref section start)) - (setq section (oref section parent)))) - (magit-section-reveal section)))) + (when-let ((pos (magit-diff--locate-file-position file line column parent))) + (goto-char (car pos)) + (magit-section-reveal (magit-current-section)))) ;;;; Setting Commands diff --git a/lisp/magit-status.el b/lisp/magit-status.el index 2f66ed692a9..19e5a698ec6 100644 --- a/lisp/magit-status.el +++ b/lisp/magit-status.el @@ -470,15 +470,17 @@ Type \\[magit-commit] to create a commit. (list file (line-number-at-pos) (current-column))))) (defun magit-status--goto-file-position (file line column) - (let ((staged (magit-get-section '((staged) (status))))) - (if (and staged - (cadr (magit-diff--locate-hunk file line staged))) - (magit-diff--goto-file-position file line column staged) - (let ((unstaged (magit-get-section '((unstaged) (status))))) - (unless (and unstaged - (magit-diff--goto-file-position file line column unstaged)) - (when staged - (magit-diff--goto-file-position file line column staged))))))) + (pcase-let ((`(,upos ,_uhunk) + (magit-diff--locate-file-position + file line column (magit-get-section '((unstaged) (status))))) + (`(,spos ,shunk) + (magit-diff--locate-file-position + file line column (magit-get-section '((staged) (status)))))) + (cond (shunk (goto-char spos)) + (upos (goto-char upos)) + (spos (goto-char spos))) + (when (or upos spos) + (magit-section-reveal (magit-current-section))))) (defun magit-status-goto-initial-section () "Jump to the section specified by `magit-status-initial-section'."