All of lore.kernel.org
 help / color / mirror / Atom feed
From: "David Kågedal" <davidk@lysator.liu.se>
To: git@vger.kernel.org
Subject: [PATCH 7/7] git-blame.el: Autoupdate while editing
Date: Fri, 09 Feb 2007 09:22:19 +0100	[thread overview]
Message-ID: <87ejozpwp0.fsf@morpheus.local> (raw)

This adds the support for automatically updating the buffer while editing.
A configuration variable git-blame-autoupdate controls whether this should
be enabled or not.

Signed-off-by: David Kågedal <davidk@lysator.liu.se>
---
 contrib/emacs/git-blame.el |   95 +++++++++++++++++++++++++++++++++++++++----
 1 files changed, 86 insertions(+), 9 deletions(-)

diff --git a/contrib/emacs/git-blame.el b/contrib/emacs/git-blame.el
index 7daa4e6..64ad50b 100644
--- a/contrib/emacs/git-blame.el
+++ b/contrib/emacs/git-blame.el
@@ -102,6 +102,9 @@
 
 (defvar git-blame-ancient-color "dark green")
 
+(defvar git-blame-autoupdate t
+  "*Automatically update the blame display while editing")
+
 (defvar git-blame-proc nil
   "The running git-blame process")
 (make-variable-buffer-local 'git-blame-proc)
@@ -114,6 +117,14 @@
   "A cache of git-blame information for the current buffer")
 (make-variable-buffer-local 'git-blame-cache)
 
+(defvar git-blame-idle-timer nil
+  "An idle timer that updates the blame")
+(make-variable-buffer-local 'git-blame-cache)
+
+(defvar git-blame-update-queue nil
+  "A queue of update requests")
+(make-variable-buffer-local 'git-blame-update-queue)
+
 (defvar git-blame-mode nil)
 (make-variable-buffer-local 'git-blame-mode)
 (unless (assq 'git-blame-mode minor-mode-alist)
@@ -129,6 +140,9 @@
       (setq git-blame-mode (eq arg 1))
     (setq git-blame-mode (not git-blame-mode)))
   (make-local-variable 'git-blame-colors)
+  (if git-blame-autoupdate
+      (add-hook 'after-change-functions 'git-blame-after-change nil t)
+    (remove-hook 'after-change-functions 'git-blame-after-change t))
   (git-blame-cleanup)
   (if git-blame-mode
       (progn
@@ -137,7 +151,8 @@
               (setq git-blame-colors git-blame-dark-colors)
             (setq git-blame-colors git-blame-light-colors)))
         (setq git-blame-cache (make-hash-table :test 'equal))
-        (git-blame-run))))
+        (git-blame-run))
+    (cancel-timer git-blame-idle-timer)))
 
 ;;;###autoload
 (defun git-reblame ()
@@ -148,18 +163,24 @@
   (git-blame-cleanup)
   (git-blame-run))
 
-(defun git-blame-run ()
+(defun git-blame-run (&optional startline endline)
   (if git-blame-proc
       ;; Should maybe queue up a new run here
       (message "Already running git blame")
     (let ((display-buf (current-buffer))
           (blame-buf (get-buffer-create
-                      (concat " git blame for " (buffer-name)))))
+                      (concat " git blame for " (buffer-name))))
+          (args '("--incremental" "--contents" "-")))
+      (if startline
+          (setq args (append args
+                             (list "-L" (format "%d,%d" startline endline)))))
+      (setq args (append args
+                         (list (file-name-nondirectory buffer-file-name))))
       (setq git-blame-proc
-            (start-process "git-blame" blame-buf
-                           "git" "blame"
-                           "--incremental" "--contents" "-"
-                           (file-name-nondirectory buffer-file-name)))
+            (apply 'start-process
+                   "git-blame" blame-buf
+                   "git" "blame"
+                   args))
       (with-current-buffer blame-buf
         (erase-buffer)
         (make-local-variable 'git-blame-file)
@@ -183,10 +204,28 @@
     (setq git-blame-overlays nil)
     (remove-git-blame-text-properties (point-min) (point-max)))
 
+(defun git-blame-update-region (start end)
+  "Rerun blame to get updates between START and END"
+  (let ((overlays (overlays-in start end)))
+    (while overlays
+      (let ((overlay (pop overlays)))
+        (if (< (overlay-start overlay) start)
+            (setq start (overlay-start overlay)))
+        (if (> (overlay-end overlay) end)
+            (setq end (overlay-end overlay)))
+        (setq git-blame-overlays (delete overlay git-blame-overlays))
+        (delete-overlay overlay))))
+  (remove-git-blame-text-properties start end)
+  ;; We can be sure that start and end are at line breaks
+  (git-blame-run (1+ (count-lines (point-min) start))
+                 (count-lines (point-min) end)))
+
 (defun git-blame-sentinel (proc status)
   (with-current-buffer (process-buffer proc)
     (with-current-buffer git-blame-file
-      (setq git-blame-proc nil)))
+      (setq git-blame-proc nil)
+      (if git-blame-update-queue
+          (git-blame-delayed-update))))
   ;;(kill-buffer (process-buffer proc))
   ;;(message "git blame finished")
   )
@@ -241,7 +280,8 @@
   (save-excursion
     (set-buffer git-blame-file)
     (let ((info (gethash hash git-blame-cache))
-          (inhibit-point-motion-hooks t))
+          (inhibit-point-motion-hooks t)
+          (inhibit-modification-hooks t))
       (when (not info)
         (let ((color (pop git-blame-colors)))
           (unless color
@@ -298,6 +338,43 @@
       (message "%s" (nth 4 info))
       (setq git-blame-last-identification info))))
 
+;; (defun git-blame-after-save ()
+;;   (when git-blame-mode
+;;     (git-blame-cleanup)
+;;     (git-blame-run)))
+;; (add-hook 'after-save-hook 'git-blame-after-save)
+
+(defun git-blame-after-change (start end length)
+  (when git-blame-mode
+    (git-blame-enq-update start end)))
+
+(defvar git-blame-last-update nil)
+(make-variable-buffer-local 'git-blame-last-update)
+(defun git-blame-enq-update (start end)
+  "Mark the region between START and END as needing blame update"
+  ;; Try to be smart and avoid multiple callouts for sequential
+  ;; editing
+  (cond ((and git-blame-last-update
+              (= start (cdr git-blame-last-update)))
+         (setcdr git-blame-last-update end))
+        ((and git-blame-last-update
+              (= end (car git-blame-last-update)))
+         (setcar git-blame-last-update start))
+        (t
+         (setq git-blame-last-update (cons start end))
+         (setq git-blame-update-queue (nconc git-blame-update-queue
+                                             (list git-blame-last-update)))))
+  (unless (or git-blame-proc git-blame-idle-timer)
+    (setq git-blame-idle-timer
+          (run-with-idle-timer 0.5 nil 'git-blame-delayed-update))))
+
+(defun git-blame-delayed-update ()
+  (setq git-blame-idle-timer nil)
+  (if git-blame-update-queue
+      (let ((first (pop git-blame-update-queue))
+            (inhibit-point-motion-hooks t))
+        (git-blame-update-region (car first) (cdr first)))))
+
 (provide 'git-blame)
 
 ;;; git-blame.el ends here
-- 
1.5.0.rc3.204.g93c76


-- 
David Kågedal

             reply	other threads:[~2007-02-09  8:50 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-02-09  8:22 David Kågedal [this message]
2007-02-09  9:46 ` [PATCH 7/7] git-blame.el: Autoupdate while editing Jakub Narebski
2007-02-09 11:05   ` David Kågedal

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87ejozpwp0.fsf@morpheus.local \
    --to=davidk@lysator.liu.se \
    --cc=git@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.