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'."

Reply via email to