git-blame.el: Change how blame information is shown.
It is more customizable, and uses a line prefix to show the commit. Signed-off-by: David Kågedal <davidk@lysator.liu.se> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
David Kågedal committed
Sep 29, 2009 at 17:12 UTC
c5022f576aa583429c245054d8600564b788ff33
1 file changed
+102
-54
contrib/emacs/git-blame.el
+102
-54
@@ -80,6 +80,57 @@
80
81
(eval-when-compile (require 'cl)) ; to use `push', `pop'
82
83
+(defface git-blame-prefix-face
84
+ '((((background dark)) (:foreground "gray"
85
+ :background "black"))
86
+ (((background light)) (:foreground "gray"
87
+ :background "white"))
88
+ (t (:weight bold)))
89
+ "The face used for the hash prefix."
90
+ :group 'git-blame)
91
+
92
+(defgroup git-blame nil
93
+ "A minor mode showing Git blame information."
94
+ :group 'git
95
+ :link '(function-link git-blame-mode))
96
+
97
+
98
+(defcustom git-blame-use-colors t
99
+ "Use colors to indicate commits in `git-blame-mode'."
100
+ :type 'boolean
101
+ :group 'git-blame)
102
+
103
+(defcustom git-blame-prefix-format
104
+ "%h %20A:"
105
+ "The format of the prefix added to each line in `git-blame'
106
+mode. The format is passed to `format-spec' with the following format keys:
107
+
108
+ %h - the abbreviated hash
109
+ %H - the full hash
110
+ %a - the author name
111
+ %A - the author email
112
+ %c - the committer name
113
+ %C - the committer email
114
+ %s - the commit summary
115
+"
116
+ :group 'git-blame)
117
+
118
+(defcustom git-blame-mouseover-format
119
+ "%h %a %A: %s"
120
+ "The format of the description shown when pointing at a line in
121
+`git-blame' mode. The format string is passed to `format-spec'
122
+with the following format keys:
123
+
124
+ %h - the abbreviated hash
125
+ %H - the full hash
126
+ %a - the author name
127
+ %A - the author email
128
+ %c - the committer name
129
+ %C - the committer email
130
+ %s - the commit summary
131
+"
132
+ :group 'git-blame)
133
+
134
135
(defun git-blame-color-scale (&rest elements)
136
"Given a list, returns a list of triples formed with each
@@ -302,72 +353,69 @@ See also function `git-blame-mode'."
353
(src-line (string-to-number (match-string 2)))
354
(res-line (string-to-number (match-string 3)))
355
(num-lines (string-to-number (match-string 4))))
305
- (setq git-blame-current
306
- (if (string= hash "0000000000000000000000000000000000000000")
307
- nil
308
- (git-blame-new-commit
309
- hash src-line res-line num-lines))))
310
- (delete-region (point) (match-end 0))
311
- t)
312
- ((looking-at "filename \\(.+\\)\n")
313
- (let ((filename (match-string 1)))
314
- (git-blame-add-info "filename" filename))
315
- (delete-region (point) (match-end 0))
356
+ (delete-region (point) (match-end 0))
357
+ (setq git-blame-current (list (git-blame-new-commit hash)
358
+ src-line res-line num-lines)))
359
t)
360
((looking-at "\\([a-z-]+\\) \\(.+\\)\n")
361
(let ((key (match-string 1))
362
(value (match-string 2)))
320
- (git-blame-add-info key value))
321
- (delete-region (point) (match-end 0))
322
- t)
323
- ((looking-at "boundary\n")
324
- (setq git-blame-current nil)
325
- (delete-region (point) (match-end 0))
363
+ (delete-region (point) (match-end 0))
364
+ (git-blame-add-info (car git-blame-current) key value)
365
+ (when (string= key "filename")
366
+ (git-blame-create-overlay (car git-blame-current)
367
+ (caddr git-blame-current)
368
+ (cadddr git-blame-current))
369
+ (setq git-blame-current nil)))
370
t)
371
(t
372
nil)))
373
330
-(defun git-blame-new-commit (hash src-line res-line num-lines)
374
+(defun git-blame-new-commit (hash)
375
+ (with-current-buffer git-blame-file
376
+ (or (gethash hash git-blame-cache)
377
+ ;; Assign a random color to each new commit info
378
+ ;; Take care not to select the same color multiple times
379
+ (let* ((color (if git-blame-colors
380
+ (git-blame-random-pop git-blame-colors)
381
+ git-blame-ancient-color))
382
+ (info `(,hash (color . ,color))))
383
+ (puthash hash info git-blame-cache)
384
+ info))))
385
+
386
+(defun git-blame-create-overlay (info start-line num-lines)
387
(save-excursion
388
(set-buffer git-blame-file)
333
- (let ((info (gethash hash git-blame-cache))
334
- (inhibit-point-motion-hooks t)
389
+ (let ((inhibit-point-motion-hooks t)
390
(inhibit-modification-hooks t))
336
- (when (not info)
337
- ;; Assign a random color to each new commit info
338
- ;; Take care not to select the same color multiple times
339
- (let ((color (if git-blame-colors
340
- (git-blame-random-pop git-blame-colors)
341
- git-blame-ancient-color)))
342
- (setq info (list hash src-line res-line num-lines
343
- (git-describe-commit hash)
344
- (cons 'color color))))
345
- (puthash hash info git-blame-cache))
346
- (goto-line res-line)
347
- (while (> num-lines 0)
348
- (if (get-text-property (point) 'git-blame)
349
- (forward-line)
350
- (let* ((start (point))
351
- (end (progn (forward-line 1) (point)))
352
- (ovl (make-overlay start end)))
353
- (push ovl git-blame-overlays)
354
- (overlay-put ovl 'git-blame info)
355
- (overlay-put ovl 'help-echo hash)
391
+ (goto-line start-line)
392
+ (let* ((start (point))
393
+ (end (progn (forward-line num-lines) (point)))
394
+ (ovl (make-overlay start end))
395
+ (hash (car info))
396
+ (spec `((?h . ,(substring hash 0 6))
397
+ (?H . ,hash)
398
+ (?a . ,(git-blame-get-info info 'author))
399
+ (?A . ,(git-blame-get-info info 'author-mail))
400
+ (?c . ,(git-blame-get-info info 'committer))
401
+ (?C . ,(git-blame-get-info info 'committer-mail))
402
+ (?s . ,(git-blame-get-info info 'summary)))))
403
+ (push ovl git-blame-overlays)
404
+ (overlay-put ovl 'git-blame info)
405
+ (overlay-put ovl 'help-echo
406
+ (format-spec git-blame-mouseover-format spec))
407
+ (if git-blame-use-colors
408
(overlay-put ovl 'face (list :background
357
- (cdr (assq 'color (nthcdr 5 info)))))
358
- ;; the point-entered property doesn't seem to work in overlays
359
- ;;(overlay-put ovl 'point-entered
360
- ;; `(lambda (x y) (git-blame-identify ,hash)))
361
- (let ((modified (buffer-modified-p)))
362
- (put-text-property (if (= start 1) start (1- start)) (1- end)
363
- 'point-entered
364
- `(lambda (x y) (git-blame-identify ,hash)))
365
- (set-buffer-modified-p modified))))
366
- (setq num-lines (1- num-lines))))))
367
-
368
-(defun git-blame-add-info (key value)
369
- (if git-blame-current
370
- (nconc git-blame-current (list (cons (intern key) value)))))
409
+ (cdr (assq 'color (cdr info))))))
410
+ (overlay-put ovl 'line-prefix
411
+ (propertize (format-spec git-blame-prefix-format spec)
412
+ 'face 'git-blame-prefix-face))))))
413
+
414
+(defun git-blame-add-info (info key value)
415
+ (nconc info (list (cons (intern key) value))))
416
+
417
+(defun git-blame-get-info (info key)
418
+ (cdr (assq key (cdr info))))
419
420
(defun git-blame-current-commit ()
421
(let ((info (get-char-property (point) 'git-blame)))