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>
This commit is contained in:
parent
1be224ba6e
commit
c5022f576a
@ -80,6 +80,57 @@
|
|||||||
|
|
||||||
(eval-when-compile (require 'cl)) ; to use `push', `pop'
|
(eval-when-compile (require 'cl)) ; to use `push', `pop'
|
||||||
|
|
||||||
|
(defface git-blame-prefix-face
|
||||||
|
'((((background dark)) (:foreground "gray"
|
||||||
|
:background "black"))
|
||||||
|
(((background light)) (:foreground "gray"
|
||||||
|
:background "white"))
|
||||||
|
(t (:weight bold)))
|
||||||
|
"The face used for the hash prefix."
|
||||||
|
:group 'git-blame)
|
||||||
|
|
||||||
|
(defgroup git-blame nil
|
||||||
|
"A minor mode showing Git blame information."
|
||||||
|
:group 'git
|
||||||
|
:link '(function-link git-blame-mode))
|
||||||
|
|
||||||
|
|
||||||
|
(defcustom git-blame-use-colors t
|
||||||
|
"Use colors to indicate commits in `git-blame-mode'."
|
||||||
|
:type 'boolean
|
||||||
|
:group 'git-blame)
|
||||||
|
|
||||||
|
(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
|
||||||
|
"
|
||||||
|
: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:
|
||||||
|
|
||||||
|
%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
|
||||||
|
"
|
||||||
|
:group 'git-blame)
|
||||||
|
|
||||||
|
|
||||||
(defun git-blame-color-scale (&rest elements)
|
(defun git-blame-color-scale (&rest elements)
|
||||||
"Given a list, returns a list of triples formed with each
|
"Given a list, returns a list of triples formed with each
|
||||||
@ -302,72 +353,69 @@ See also function `git-blame-mode'."
|
|||||||
(src-line (string-to-number (match-string 2)))
|
(src-line (string-to-number (match-string 2)))
|
||||||
(res-line (string-to-number (match-string 3)))
|
(res-line (string-to-number (match-string 3)))
|
||||||
(num-lines (string-to-number (match-string 4))))
|
(num-lines (string-to-number (match-string 4))))
|
||||||
(setq git-blame-current
|
(delete-region (point) (match-end 0))
|
||||||
(if (string= hash "0000000000000000000000000000000000000000")
|
(setq git-blame-current (list (git-blame-new-commit hash)
|
||||||
nil
|
src-line res-line num-lines)))
|
||||||
(git-blame-new-commit
|
|
||||||
hash src-line res-line num-lines))))
|
|
||||||
(delete-region (point) (match-end 0))
|
|
||||||
t)
|
|
||||||
((looking-at "filename \\(.+\\)\n")
|
|
||||||
(let ((filename (match-string 1)))
|
|
||||||
(git-blame-add-info "filename" filename))
|
|
||||||
(delete-region (point) (match-end 0))
|
|
||||||
t)
|
t)
|
||||||
((looking-at "\\([a-z-]+\\) \\(.+\\)\n")
|
((looking-at "\\([a-z-]+\\) \\(.+\\)\n")
|
||||||
(let ((key (match-string 1))
|
(let ((key (match-string 1))
|
||||||
(value (match-string 2)))
|
(value (match-string 2)))
|
||||||
(git-blame-add-info key value))
|
(delete-region (point) (match-end 0))
|
||||||
(delete-region (point) (match-end 0))
|
(git-blame-add-info (car git-blame-current) key value)
|
||||||
t)
|
(when (string= key "filename")
|
||||||
((looking-at "boundary\n")
|
(git-blame-create-overlay (car git-blame-current)
|
||||||
(setq git-blame-current nil)
|
(caddr git-blame-current)
|
||||||
(delete-region (point) (match-end 0))
|
(cadddr git-blame-current))
|
||||||
|
(setq git-blame-current nil)))
|
||||||
t)
|
t)
|
||||||
(t
|
(t
|
||||||
nil)))
|
nil)))
|
||||||
|
|
||||||
(defun git-blame-new-commit (hash src-line res-line num-lines)
|
(defun git-blame-new-commit (hash)
|
||||||
|
(with-current-buffer git-blame-file
|
||||||
|
(or (gethash hash git-blame-cache)
|
||||||
|
;; Assign a random color to each new commit info
|
||||||
|
;; Take care not to select the same color multiple times
|
||||||
|
(let* ((color (if git-blame-colors
|
||||||
|
(git-blame-random-pop git-blame-colors)
|
||||||
|
git-blame-ancient-color))
|
||||||
|
(info `(,hash (color . ,color))))
|
||||||
|
(puthash hash info git-blame-cache)
|
||||||
|
info))))
|
||||||
|
|
||||||
|
(defun git-blame-create-overlay (info start-line num-lines)
|
||||||
(save-excursion
|
(save-excursion
|
||||||
(set-buffer git-blame-file)
|
(set-buffer git-blame-file)
|
||||||
(let ((info (gethash hash git-blame-cache))
|
(let ((inhibit-point-motion-hooks t)
|
||||||
(inhibit-point-motion-hooks t)
|
|
||||||
(inhibit-modification-hooks t))
|
(inhibit-modification-hooks t))
|
||||||
(when (not info)
|
(goto-line start-line)
|
||||||
;; Assign a random color to each new commit info
|
(let* ((start (point))
|
||||||
;; Take care not to select the same color multiple times
|
(end (progn (forward-line num-lines) (point)))
|
||||||
(let ((color (if git-blame-colors
|
(ovl (make-overlay start end))
|
||||||
(git-blame-random-pop git-blame-colors)
|
(hash (car info))
|
||||||
git-blame-ancient-color)))
|
(spec `((?h . ,(substring hash 0 6))
|
||||||
(setq info (list hash src-line res-line num-lines
|
(?H . ,hash)
|
||||||
(git-describe-commit hash)
|
(?a . ,(git-blame-get-info info 'author))
|
||||||
(cons 'color color))))
|
(?A . ,(git-blame-get-info info 'author-mail))
|
||||||
(puthash hash info git-blame-cache))
|
(?c . ,(git-blame-get-info info 'committer))
|
||||||
(goto-line res-line)
|
(?C . ,(git-blame-get-info info 'committer-mail))
|
||||||
(while (> num-lines 0)
|
(?s . ,(git-blame-get-info info 'summary)))))
|
||||||
(if (get-text-property (point) 'git-blame)
|
(push ovl git-blame-overlays)
|
||||||
(forward-line)
|
(overlay-put ovl 'git-blame info)
|
||||||
(let* ((start (point))
|
(overlay-put ovl 'help-echo
|
||||||
(end (progn (forward-line 1) (point)))
|
(format-spec git-blame-mouseover-format spec))
|
||||||
(ovl (make-overlay start end)))
|
(if git-blame-use-colors
|
||||||
(push ovl git-blame-overlays)
|
|
||||||
(overlay-put ovl 'git-blame info)
|
|
||||||
(overlay-put ovl 'help-echo hash)
|
|
||||||
(overlay-put ovl 'face (list :background
|
(overlay-put ovl 'face (list :background
|
||||||
(cdr (assq 'color (nthcdr 5 info)))))
|
(cdr (assq 'color (cdr info))))))
|
||||||
;; the point-entered property doesn't seem to work in overlays
|
(overlay-put ovl 'line-prefix
|
||||||
;;(overlay-put ovl 'point-entered
|
(propertize (format-spec git-blame-prefix-format spec)
|
||||||
;; `(lambda (x y) (git-blame-identify ,hash)))
|
'face 'git-blame-prefix-face))))))
|
||||||
(let ((modified (buffer-modified-p)))
|
|
||||||
(put-text-property (if (= start 1) start (1- start)) (1- end)
|
|
||||||
'point-entered
|
|
||||||
`(lambda (x y) (git-blame-identify ,hash)))
|
|
||||||
(set-buffer-modified-p modified))))
|
|
||||||
(setq num-lines (1- num-lines))))))
|
|
||||||
|
|
||||||
(defun git-blame-add-info (key value)
|
(defun git-blame-add-info (info key value)
|
||||||
(if git-blame-current
|
(nconc info (list (cons (intern key) value))))
|
||||||
(nconc git-blame-current (list (cons (intern key) value)))))
|
|
||||||
|
(defun git-blame-get-info (info key)
|
||||||
|
(cdr (assq key (cdr info))))
|
||||||
|
|
||||||
(defun git-blame-current-commit ()
|
(defun git-blame-current-commit ()
|
||||||
(let ((info (get-char-property (point) 'git-blame)))
|
(let ((info (get-char-property (point) 'git-blame)))
|
||||||
|
Loading…
Reference in New Issue
Block a user