branch: elpa/magit
commit 66f3cdaca41a041ff8c3ebcbd97cc9e33843b80c
Author: Jonas Bernoulli <jo...@bernoul.li>
Commit: Jonas Bernoulli <jo...@bernoul.li>

    Bring back a variant of delayed hunk refinement
    
    The old variant broke with [1: 95ee9d8c51], which cannot be fixed simply
    be reverting that commit, because it was in preparation of subsequent
    changes, which heavily refactored section highlighting making it both
    simpler and more generic, and also to improve performance.  Delayed hunk
    refinement conflicts with the former, and due to the latter it might not
    be necessary anymore.
    
    This commit does not fully restore the old behavior.  Previously
    delayed refinement meant that only the current hunk was ever refined;
    when another section became current, the refinement of the previously
    current section was removed again.  Now, once a hunk has been refined,
    it remains refined, until the buffer is refreshed.
    
    The reason any form of delayed hunk refinement was implemented in the
    first place, was to avoid the upfront cost of completely refining a
    large diff.  I never considered this a desirable feature; just a kludge
    that was sadly necessary for performance reasons.  IMO the new behavior
    is an improvement; though always refining all hunks is of course even
    better, unless it is too slow of course.
    
    Closes #5385.
    
    1: 2025-04-26 95ee9d8c5102bc5619f0e2c6d50104cae17b2009
       magit-diff-paint-hunk: Only refine if actually painting
---
 docs/magit.org        |  5 ++++-
 docs/magit.texi       |  7 +++++--
 lisp/magit-diff.el    | 27 ++++++++++++++++++---------
 lisp/magit-section.el |  6 +++++-
 4 files changed, 32 insertions(+), 13 deletions(-)

diff --git a/docs/magit.org b/docs/magit.org
index 31ed501d3f..db98ffa5f0 100644
--- a/docs/magit.org
+++ b/docs/magit.org
@@ -3357,8 +3357,11 @@ that they are available here too.
   Whether to show word-granularity differences within diff hunks.
 
   - ~nil~ Never show fine differences.
-  - ~t~ Show fine differences for the current diff hunk only.
   - ~all~ Show fine differences for all displayed diff hunks.
+  - ~t~ Refine each hunk once it becomes the current section.
+    Keep the refinement when another section is selected.
+    Refreshing the buffer removes all refinement.  This
+    variant is only provided for performance reasons.
 
 - User Option: magit-diff-refine-ignore-whitespace ::
 
diff --git a/docs/magit.texi b/docs/magit.texi
index ef1e9fd663..590c031bc6 100644
--- a/docs/magit.texi
+++ b/docs/magit.texi
@@ -3945,9 +3945,12 @@ Whether to show word-granularity differences within diff 
hunks.
 @item
 @code{nil} Never show fine differences.
 @item
-@code{t} Show fine differences for the current diff hunk only.
-@item
 @code{all} Show fine differences for all displayed diff hunks.
+@item
+@code{t} Refine each hunk once it becomes the current section.
+Keep the refinement when another section is selected.
+Refreshing the buffer removes all refinement.  This
+variant is only provided for performance reasons.
 @end itemize
 @end defopt
 
diff --git a/lisp/magit-diff.el b/lisp/magit-diff.el
index f3d97ff11e..58bd8c7b82 100644
--- a/lisp/magit-diff.el
+++ b/lisp/magit-diff.el
@@ -192,13 +192,16 @@ keep their distinct foreground colors."
   "Whether to show word-granularity differences within diff hunks.
 
 `nil'  Never show fine differences.
-`t'    Show fine differences for the current diff hunk only.
-`all'  Show fine differences for all displayed diff hunks."
+`all'  Show fine differences for all displayed diff hunks.
+`t'    Refine each hunk once it becomes the current section.
+       Keep the refinement when another section is selected.
+       Refreshing the buffer removes all refinement.  This
+       variant is only provided for performance reasons."
   :group 'magit-diff
   :safe (##memq % '(nil t all))
-  :type '(choice (const :tag "Never" nil)
-                 (const :tag "Current" t)
-                 (const :tag "All" all)))
+  :type '(choice (const :tag "No refinement" nil)
+                 (const :tag "Immediately refine all hunks" all)
+                 (const :tag "Refine each hunk when moving to it" t)))
 
 (defcustom magit-diff-refine-ignore-whitespace smerge-refine-ignore-whitespace
   "Whether to ignore whitespace changes in word-granularity differences."
@@ -3309,7 +3312,8 @@ actually a `diff' but a `diffstat' section."
          (magit-diff-paint-whitespace merging 'context diff-type)
          (if highlight 'magit-diff-context-highlight 'magit-diff-context))))
       (forward-line)))
-  (magit-diff-update-hunk-refinement section)
+  (when (eq magit-diff-refine-hunk 'all)
+    (magit-diff-update-hunk-refinement section))
   (oset section painted (if highlight 'highlight 'plain)))
 
 (defvar magit-diff--tab-width-cache nil)
@@ -3383,7 +3387,11 @@ actually a `diff' but a `diffstat' section."
           (overlay-put ov 'priority 2)
           (overlay-put ov 'evaporate t))))))
 
-(defun magit-diff-update-hunk-refinement (&optional section)
+(cl-defmethod magit-section--refine ((section magit-hunk-section))
+  (when (eq magit-diff-refine-hunk t)
+    (magit-diff-update-hunk-refinement section)))
+
+(defun magit-diff-update-hunk-refinement (&optional section allow-remove)
   (if section
       (unless (oref section hidden)
         (pcase (list magit-diff-refine-hunk
@@ -3400,14 +3408,15 @@ actually a `diff' but a `diffstat' section."
                      ;; Avoid fsyncing many small temp files.
                      (write-region-inhibit-fsync t))
                  (diff-refine-hunk)))))
-          ((or `(nil t ,_) '(t t nil))
+          ((and (guard allow-remove)
+                (or `(nil t ,_) '(t t nil)))
            (oset section refined nil)
            (remove-overlays (oref section start)
                             (oref section end)
                             'diff-mode 'fine))))
     (cl-labels ((recurse (section)
                   (if (magit-section-match 'hunk section)
-                      (magit-diff-update-hunk-refinement section)
+                      (magit-diff-update-hunk-refinement section t)
                     (dolist (child (oref section children))
                       (recurse child)))))
       (recurse magit-root-section))))
diff --git a/lisp/magit-section.el b/lisp/magit-section.el
index 9d486ffd6c..68fb1640ed 100644
--- a/lisp/magit-section.el
+++ b/lisp/magit-section.el
@@ -1770,7 +1770,9 @@ evaluated its BODY.  Admittedly that's a bit of a hack."
                  (magit-section-highlight-range content child-start)))
              (mapc #'magit-section-highlight children))
             ((and content (not (slot-boundp section 'painted)))
-             (magit-section-highlight-range content end))))
+             (magit-section-highlight-range content end))
+            ;; Unfortunate kludge for delayed hunk refinement.
+            ((magit-section--refine section))))
      (headlight
       (magit-section-highlight-range start (or content end) headlight)
       (when content
@@ -1845,6 +1847,8 @@ evaluated its BODY.  Admittedly that's a bit of a hack."
           (cl-pushnew section magit-section-highlighted-sections))
       (magit-section-update-paint section (magit-focused-sections)))))
 
+(cl-defmethod magit-section--refine ((_section magit-section)))
+
 ;;; Long Lines
 
 (defvar magit-show-long-lines-warning t)

Reply via email to