How can I improve emacs' vc-mode annotation?
I find hg annotate
very useful in tracking the provenance of code, but I'm seeing that in emacs' vc-mode, vc-annotate
is ... not so good. Here's a snippet:
297 Wed Oct 06 15:21:30 2010 -0600 aws/lib/survey/creator/dbTemplates/web/views.sql: $$,$$
687 Mon Dec 20 10:25:41 2010 -0700 aws/lib/survey/creator/dbTemplates/web/views.sql: GRANT SELECT ON survey_length_view TO reportuser,surveyuser,sampleserver,sampleloader;
687 Mon Dec 20 10:25:41 2010 -0700 aws/lib/survey/creator/dbTemplates/web/views.sql: GRANT ALL ON survey_length_view TO adminuser, GROU开发者_如何转开发P staff;
297 Wed Oct 06 15:21:30 2010 -0600 aws/lib/survey/creator/dbTemplates/web/views.sql: $$);
As you can see, there's a lot of preamble there, and a fair amount of redundant information. I don't need to know the full ISO timestamp (most of the time, anyway) and the path to the file is covered by the fact that I was in the file when I chose to annotate. I do need to know who made the change, which is notably absent here.
How can I fix this annotation tool so that it becomes useful?
vc-hg.el seems to hardcode the arguments to hg annotate
, so you would need to redefine the command after loading vc-hg:
(require 'vc-hg)
(defun vc-hg-annotate-command (file buffer &optional revision)
"Execute \"hg annotate\" on FILE, inserting the contents in BUFFER.
Optional arg REVISION is a revision to annotate from."
(vc-hg-command buffer 0 file "annotate" "-d" "-n" "--follow"
(when revision (concat "-r" revision))))
Simply removing the arguments will probably cause you to lose functionality due to the missing information, so a better solution would be to follow the example in vc-bzr.el where some of the information is stripped out and put into a tooltip instead. If you go down that route, consider contributing your improvements back to Emacs.
This is solved in Emacs 25.
;; One line printed by "hg annotate -dq -n -u --follow" looks like this:
;; b56girard 114590 2012-03-13 CLOBBER: Lorem ipsum dolor sit
;; i.e. AUTHOR REVISION DATE FILENAME: CONTENTS
;; The user can omit options "-u" and/or "--follow". Then it'll look like:
;; 114590 2012-03-13 CLOBBER:
;; or
;; b56girard 114590 2012-03-13:
I also had this problem, here is my solution:
;; vc-mode
(defconst vc-hg-annotate-better-re
"^[ ]*\\(.+?\\) \\([0-9]+\\) \\([0-9a-f]+\\) \\(.+?\\+[0-9]+\\) +\\(.+?\\):\\([0-9]+\\):\\(.*\n?\\)")
(defconst vc-hg-annotate-result-re
"^[\t ]*\\([0-9]+\\) +\\(.+?\\) .*")
(eval-after-load "vc-hg"
'(defun vc-hg-annotate-command (file buffer &optional revision)
"Execute \"hg annotate\" on FILE, inserting the contents in BUFFER.
Optional arg REVISION is a revision to annotate from."
(vc-hg-command buffer 'async file "annotate" "-d" "-n" "-u" "-c" "-l" "--follow"
(when revision (concat "-r" revision)))
(lexical-let ((table (make-hash-table :test 'equal)))
(set-process-filter
(get-buffer-process buffer)
(lambda (proc string)
(when (process-buffer proc)
(with-current-buffer (process-buffer proc)
(setq string (concat (process-get proc :vc-left-over) string))
(while (string-match vc-hg-annotate-better-re string)
(let* ((author (match-string 1 string))
(rev (match-string 2 string))
(changeset (match-string 3 string))
(date (match-string 4 string))
(key (concat rev author date))
(file (match-string 5 string))
(lineno (match-string 6 string))
(content (match-string 7 string))
(tag (gethash key table))
(inhibit-read-only t))
(setq string (substring string (match-end 0)))
(unless tag
(setq tag
(propertize
(format "%-5s %-8.8s" rev author)
'help-echo (format "Revision: %d, author: %s, date: %s"
(string-to-number rev)
author date)
'mouse-face 'highlight))
(puthash key tag table))
(goto-char (process-mark proc))
(insert tag content)
(move-marker (process-mark proc) (point))))
(process-put proc :vc-left-over string))))))))
(eval-after-load "vc-hg"
'(defun vc-hg-annotate-time ()
(save-excursion
(beginning-of-line)
(when (looking-at vc-hg-annotate-result-re)
(let ((prop (get-text-property (line-beginning-position) 'help-echo)))
(string-match ", date: \\(.+\\)\\'" prop)
(let ((str (match-string-no-properties 1 prop)))
(vc-annotate-convert-time (date-to-time str))))))))
(eval-after-load "vc-hg"
'(defun vc-hg-annotate-extract-revision-at-line ()
(save-excursion
(beginning-of-line)
(when (looking-at vc-hg-annotate-result-re)
(match-string-no-properties 1)))))
Add that to your init file and you will get output formatted similarly to bzr annotate:
266 jimb@re | /* Window creation, deletion and examination for GNU Emacs.
266 jimb@re | Does not include redisplay.
102971 rgm@gnu | Copyright (C) 1985-1987, 1993-1998, 2000-2011
77438.1.2234 rgm@gnu | Free Software Foundation, Inc.
266 jimb@re |
266 jimb@re | This file is part of GNU Emacs.
Sadly, filtering the annotate output like this does make annotate slower on large files, I haven't found a way around that yet (annotate on files in bzr is also slow).
精彩评论