Subject: Re: git-blame.el: does not show one-line summary in echo area

From: David Kågedal <[email-masked]>
Date: Fri, 04 Feb 2011 13:26:16 +0100

David Kågedal <[email-masked]> writes:

> Jakub Narebski <[email-masked]> writes:
>
>> Dnia piątek 4. lutego 2011 10:53, David Kågedal napisał:
>>
>>> 3) Showing when you move to a different blame chunk, by showing a
>>>    one-line summary in the echo area.
>>
>> There is even some prior art for this to borrow from, namely cperl-mode
>> shows information about syntax at given point in echo area (minibuffer
>> area) after some delay.  Just FYI.
>
> Sure, there are a number of those (eldoc comes to mind). I think the
> hardest part is figuring out what to show. A 40-charater hash is
> probably not very useful. The problem is that the committer information,
> date, and commit message first line takes up a lot of space. But we can
> of course let the echo area grow to two lines, or even three.
>
> I don't think I'll have time to cook something up right now, though.

I whipped up a patch anyway. This adds an echo area message shown after
0.5 seconds of idleness, using the git-blame-echo-format format string.
Try it and see if makes sense. I can clean it up (and split it up)
later.

diff --git a/contrib/emacs/git-blame.el b/contrib/emacs/git-blame.el
index d351cfb..9f60a6f 100644
--- a/contrib/emacs/git-blame.el
+++ b/contrib/emacs/git-blame.el
@@ -104,34 +104,53 @@
 (defcustom git-blame-prefix-format
   "%h %20A:"
   "The format of the prefix added to each line in `git-blame'
-mode. The format is passed to `format-spec' with the following format keys:
-
-  %h - the abbreviated hash
-  %H - the full hash
-  %a - the author name
-  %A - the author email
-  %c - the committer name
-  %C - the committer email
-  %s - the commit summary
+mode. See `git-blame-format' for more information.
 "
   :group 'git-blame)
 
 (defcustom git-blame-mouseover-format
   "%h %a %A: %s"
   "The format of the description shown when pointing at a line in
-`git-blame' mode. The format string is passed to `format-spec'
-with the following format keys:
+`git-blame' mode. See `git-blame-format' for more information
+"
+  :group 'git-blame)
+
+(defcustom git-blame-echo-format
+  "%H\n%a %A %t\n%s"
+  "The format of the description shown in the echo area when moving around in
+`git-blame' mode. See `git-blame-format' for more information."
+  :group 'git-blame)
+
+(defun git-blame-format (info format)
+  "Use format-spec to format the blame info in INFO with the following keys:
 
   %h - the abbreviated hash
   %H - the full hash
   %a - the author name
   %A - the author email
+  %t - the author time
   %c - the committer name
   %C - the committer email
+  %T - the commtter time
   %s - the commit summary
 "
-  :group 'git-blame)
-
+  (let ((hash (car info))
+        (author-time (let ((time (string-to-number
+                                  (git-blame-get-info info 'author-time))))
+                       (list (/ time 65536) (% time 65536) 0)))
+        (committer-time (let ((time (string-to-number
+                                  (git-blame-get-info info 'committer-time))))
+                          (list (/ time 65536) (% time 65536) 0))))
+    (format-spec format
+                 `((?h . ,(substring (car info) 0 6))
+                   (?H . ,(car info))
+                   (?a . ,(git-blame-get-info info 'author))
+                   (?A . ,(git-blame-get-info info 'author-mail))
+                   (?t . ,(format-time-string "%c" author-time))
+                   (?c . ,(git-blame-get-info info 'committer))
+                   (?C . ,(git-blame-get-info info 'committer-mail))
+                   (?T . ,(format-time-string "%c" committer-time))
+                   (?s . ,(git-blame-get-info info 'summary))))))
 
 (defun git-blame-color-scale (&rest elements)
   "Given a list, returns a list of triples formed with each
@@ -198,10 +217,13 @@ minor mode.")
   "A cache of git-blame information for the current buffer")
 (make-variable-buffer-local 'git-blame-cache)
 
-(defvar git-blame-idle-timer nil
+(defvar git-blame-update-timer nil
   "An idle timer that updates the blame")
 (make-variable-buffer-local 'git-blame-cache)
 
+(defvar git-blame-show-timer nil
+  "An idle timer that show the current blame info.")
+
 (defvar git-blame-update-queue nil
   "A queue of update requests")
 (make-variable-buffer-local 'git-blame-update-queue)
@@ -246,6 +268,10 @@ See also function `git-blame-mode'."
 	(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))
+  (unless (and git-blame-show-timer
+               (memq git-blame-show-timer timer-idle-list))
+    (setq git-blame-show-timer
+          (run-with-idle-timer 0.5 t 'git-blame-echo-current)))
   (setq git-blame-mode t)
   (git-blame-run))
 
@@ -254,7 +280,7 @@ See also function `git-blame-mode'."
 
 See also function `git-blame-mode'."
   (git-blame-cleanup)
-  (if git-blame-idle-timer (cancel-timer git-blame-idle-timer))
+  (if git-blame-update-timer (cancel-timer git-blame-update-timer))
   (setq git-blame-mode nil))
 
 ;;;###autoload
@@ -392,34 +418,33 @@ See also function `git-blame-mode'."
       (goto-line start-line)
       (let* ((start (point))
              (end (progn (forward-line num-lines) (point)))
-             (ovl (make-overlay start end))
-             (hash (car info))
-             (spec `((?h . ,(substring hash 0 6))
-                     (?H . ,hash)
-                     (?a . ,(git-blame-get-info info 'author))
-                     (?A . ,(git-blame-get-info info 'author-mail))
-                     (?c . ,(git-blame-get-info info 'committer))
-                     (?C . ,(git-blame-get-info info 'committer-mail))
-                     (?s . ,(git-blame-get-info info 'summary)))))
+             (ovl (make-overlay start end)))
         (push ovl git-blame-overlays)
         (overlay-put ovl 'git-blame info)
         (overlay-put ovl 'help-echo
-                     (format-spec git-blame-mouseover-format spec))
+                     (git-blame-format info git-blame-mouseover-format))
         (if git-blame-use-colors
             (overlay-put ovl 'face (list :background
                                          (cdr (assq 'color (cdr info))))))
         (overlay-put ovl 'line-prefix
-                     (propertize (format-spec git-blame-prefix-format spec)
+                     (propertize (git-blame-format info git-blame-prefix-format)
                                  'face 'git-blame-prefix-face))))))
 
 (defun git-blame-add-info (info key value)
-  (nconc info (list (cons (intern key) value))))
+  (let* ((keysym (intern key))
+         (a (assq keysym (cdr info))))
+    (if a
+        (setcdr a value)
+      (nconc info (list (cons (intern key) value))))))
 
 (defun git-blame-get-info (info key)
   (cdr (assq key (cdr info))))
 
+(defun git-blame-current-info ()
+  (get-char-property (point) 'git-blame))
+
 (defun git-blame-current-commit ()
-  (let ((info (get-char-property (point) 'git-blame)))
+  (let ((info (git-blame-current-info)))
     (if info
         (car info)
       (error "No commit info"))))
@@ -467,17 +492,22 @@ See also function `git-blame-mode'."
          (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
+  (unless (or git-blame-proc git-blame-update-timer)
+    (setq git-blame-update-timer
           (run-with-idle-timer 0.5 nil 'git-blame-delayed-update))))
 
 (defun git-blame-delayed-update ()
-  (setq git-blame-idle-timer nil)
+  (setq git-blame-update-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)))))
 
+(defun git-blame-echo-current ()
+  (let ((info (git-blame-current-info)))
+    (when info
+      (message "%s" (git-blame-format info git-blame-echo-format)))))
+
 (provide 'git-blame)
 
 ;;; git-blame.el ends here

-- 
David Kågedal