@matheusbsbs / matheus-bagliano / commits / c5022f576a
Fork 0

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)))