branch: elpa/diff-ansi commit 4ae0a6d55572efecfcf6da7288488058cf1b4bc6 Author: Campbell Barton <ideasma...@gmail.com> Commit: Campbell Barton <ideasma...@gmail.com>
Fix error canceling an existing timer that highlights progressively Magit would reuse a buffer, clearing it's local variables causing the local timer to be nil while the timer kept running. Now store the timer as an argument to its self. --- diff-ansi.el | 94 ++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 54 insertions(+), 40 deletions(-) diff --git a/diff-ansi.el b/diff-ansi.el index cf7f32999f..602dc27171 100644 --- a/diff-ansi.el +++ b/diff-ansi.el @@ -646,48 +646,56 @@ Store the result in TARGET-BUF when non-nil." ;; --------------------------------------------------------------------------- ;; ANSI Conversion (Progressive) -(defun diff-ansi-progressive-highlight-impl (buf range) - "Callback to update colors for BUF in RANGE." +(defun diff-ansi--ansi-color-timer-cancel () + "Cancel the timer." + (cancel-timer diff-ansi--ansi-color-timer) + (setq diff-ansi--ansi-color-timer nil)) + +(defun diff-ansi-progressive-highlight-impl (buf range timer) + "Callback to update colors for BUF in RANGE for TIMER." (unless (input-pending-p) (with-current-buffer buf - (let* - ( - (do-redisplay nil) - (inhibit-read-only t) - (end (cdr range)) - (end-trailing-chars (- (buffer-size) end)) - (disp-beg (car range)) - (disp-end - (min - end ;; Clamp twice because `line-end-position' could exceed the value. - (save-excursion - (goto-char (min (+ disp-beg diff-ansi-chunks-size) end)) - (line-end-position))))) - (save-excursion - (cond - ((eq disp-beg disp-end) - (when diff-ansi--ansi-color-timer - (cancel-timer diff-ansi--ansi-color-timer) - (setq diff-ansi--ansi-color-timer nil))) - (t - (let ((disp-end-mark (set-marker (make-marker) disp-end))) - (diff-ansi--ansi-color-apply-on-region-with-bg disp-beg disp-end) + (cond + ((null diff-ansi--ansi-color-timer) + ;; Local variables may have been cleared, + ;; in this case use the timer passed in to this function. + (cancel-timer timer)) + (t + (let* + ( + (do-redisplay nil) + (inhibit-read-only t) + (end (cdr range)) + (end-trailing-chars (- (buffer-size) end)) + (disp-beg (car range)) + (disp-end + (min + end ;; Clamp twice because `line-end-position' could exceed the value. + (save-excursion + (goto-char (min (+ disp-beg diff-ansi-chunks-size) end)) + (line-end-position))))) + ;; + (save-excursion + (cond + ((eq disp-beg disp-end) + (when diff-ansi--ansi-color-timer + (diff-ansi--ansi-color-timer-cancel))) + (t + (let ((disp-end-mark (set-marker (make-marker) disp-end))) + (diff-ansi--ansi-color-apply-on-region-with-bg disp-beg disp-end) - (setq do-redisplay t) - ;; Update the display start and actual end. - (setcar range (marker-position disp-end-mark)) - (setcdr range (- (buffer-size) end-trailing-chars)))))) + (setq do-redisplay t) + ;; Update the display start and actual end. + (setcar range (marker-position disp-end-mark)) + (setcdr range (- (buffer-size) end-trailing-chars)))))) - ;; Re-display outside the block that moves the cursor. - (when do-redisplay - (redisplay)))))) + ;; Re-display outside the block that moves the cursor. + (when do-redisplay + (redisplay)))))))) (defun diff-ansi--progressive-impl (beg end &optional target-buf) "Colorize the text between BEG and END using a timer. Store the result in TARGET-BUF when non-nil." - (when diff-ansi--ansi-color-timer - (cancel-timer diff-ansi--ansi-color-timer) - (setq diff-ansi--ansi-color-timer nil)) (let ( (diff-command (diff-ansi--command-preset-impl)) @@ -698,18 +706,24 @@ Store the result in TARGET-BUF when non-nil." (goto-char beg)) (with-current-buffer (or target-buf (current-buffer)) + ;; Potentially an existing timer will exist. + (when diff-ansi--ansi-color-timer + (diff-ansi--ansi-color-timer-cancel)) + (let ((inhibit-read-only t)) (setq beg (point)) (diff-ansi--call-process-pipe-chain diff-command :input diff-str :output (current-buffer)) (setq end (point)) - (setq diff-ansi--ansi-color-timer - (run-at-time - 0.0 - 0.001 + ;; Postpone activation until the timer can take it's self as an argument. + (diff-ansi--with-advice 'timer-activate + :override (lambda (&rest _) nil) + (setq diff-ansi--ansi-color-timer (run-at-time 0.0 0.001 nil)) + (timer-set-function + diff-ansi--ansi-color-timer #'diff-ansi-progressive-highlight-impl - (current-buffer) - (cons beg end))))))) + (list (current-buffer) (cons beg end) diff-ansi--ansi-color-timer))) + (timer-activate diff-ansi--ansi-color-timer))))) ;; ---------------------------------------------------------------------------