{"thread":{"id":"21092","subject":"[PATCH] git-blame.el: Change how blame information is shown.","startedAt":"2009-09-29T15:12:57Z","lastAt":"2009-09-29T15:12:57Z","messageCount":1,"participants":["David Kågedal"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"123998","messageId":"1254237177-20355-1-git-send-email-davidk@lysator.liu.se","threadId":"21092","inReplyTo":null,"subject":"[PATCH] git-blame.el: Change how blame information is shown.","fromName":"David Kågedal","fromEmail":"davidk@lysator.liu.se","sentAt":"2009-09-29T15:12:57Z","receivedAt":"2009-09-29T15:12:57Z","isPatch":true,"sender":{"key":"davidk@lysator.liu.se","avatar":"https://avatars.githubusercontent.com/u/60530?v=4"},"body":"It is more customizable, and uses a line prefix to show the commit.\n\nSigned-off-by: David Kågedal <davidk@lysator.liu.se>\n---\n\nI have only tested this on Emacs 23, so please test it on at least\nEmacs 22 and let me know if there are any problems.\n\nSuggestions for the default value of git-blame-prefix-format are also\nwelcome.\n\ncontrib/emacs/git-blame.el |  156 +++++++++++++++++++++++++++++---------------\n 1 files changed, 102 insertions(+), 54 deletions(-)\n\ndiff --git a/contrib/emacs/git-blame.el b/contrib/emacs/git-blame.el\nindex 4fa70c5..2f25ff4 100644\n--- a/contrib/emacs/git-blame.el\n+++ b/contrib/emacs/git-blame.el\n@@ -80,6 +80,57 @@\n \n (eval-when-compile (require 'cl))\t\t\t      ; to use `push', `pop'\n \n+(defface git-blame-prefix-face\n+  '((((background dark)) (:foreground \"gray\"\n+                          :background \"black\"))\n+    (((background light)) (:foreground \"gray\"\n+                           :background \"white\"))\n+    (t (:weight bold)))\n+  \"The face used for the hash prefix.\"\n+  :group 'git-blame)\n+\n+(defgroup git-blame nil\n+  \"A minor mode showing Git blame information.\"\n+  :group 'git\n+  :link '(function-link git-blame-mode))\n+\n+\n+(defcustom git-blame-use-colors t\n+  \"Use colors to indicate commits in `git-blame-mode'.\"\n+  :type 'boolean\n+  :group 'git-blame)\n+\n+(defcustom git-blame-prefix-format\n+  \"%h %20A:\"\n+  \"The format of the prefix added to each line in `git-blame'\n+mode. The format is passed to `format-spec' with the following format keys:\n+\n+  %h - the abbreviated hash\n+  %H - the full hash\n+  %a - the author name\n+  %A - the author email\n+  %c - the committer name\n+  %C - the committer email\n+  %s - the commit summary\n+\"\n+  :group 'git-blame)\n+\n+(defcustom git-blame-mouseover-format\n+  \"%h %a %A: %s\"\n+  \"The format of the description shown when pointing at a line in\n+`git-blame' mode. The format string is passed to `format-spec'\n+with the following format keys:\n+\n+  %h - the abbreviated hash\n+  %H - the full hash\n+  %a - the author name\n+  %A - the author email\n+  %c - the committer name\n+  %C - the committer email\n+  %s - the commit summary\n+\"\n+  :group 'git-blame)\n+\n \n (defun git-blame-color-scale (&rest elements)\n   \"Given a list, returns a list of triples formed with each\n@@ -302,72 +353,69 @@ See also function `git-blame-mode'.\"\n                (src-line (string-to-number (match-string 2)))\n                (res-line (string-to-number (match-string 3)))\n                (num-lines (string-to-number (match-string 4))))\n-           (setq git-blame-current\n-                 (if (string= hash \"0000000000000000000000000000000000000000\")\n-                     nil\n-                   (git-blame-new-commit\n-                    hash src-line res-line num-lines))))\n-         (delete-region (point) (match-end 0))\n-         t)\n-        ((looking-at \"filename \\\\(.+\\\\)\\n\")\n-         (let ((filename (match-string 1)))\n-           (git-blame-add-info \"filename\" filename))\n-         (delete-region (point) (match-end 0))\n+           (delete-region (point) (match-end 0))\n+           (setq git-blame-current (list (git-blame-new-commit hash)\n+                                         src-line res-line num-lines)))\n          t)\n         ((looking-at \"\\\\([a-z-]+\\\\) \\\\(.+\\\\)\\n\")\n          (let ((key (match-string 1))\n                (value (match-string 2)))\n-           (git-blame-add-info key value))\n-         (delete-region (point) (match-end 0))\n-         t)\n-        ((looking-at \"boundary\\n\")\n-         (setq git-blame-current nil)\n-         (delete-region (point) (match-end 0))\n+           (delete-region (point) (match-end 0))\n+           (git-blame-add-info (car git-blame-current) key value)\n+           (when (string= key \"filename\")\n+             (git-blame-create-overlay (car git-blame-current)\n+                                       (caddr git-blame-current)\n+                                       (cadddr git-blame-current))\n+             (setq git-blame-current nil)))\n          t)\n         (t\n          nil)))\n \n-(defun git-blame-new-commit (hash src-line res-line num-lines)\n+(defun git-blame-new-commit (hash)\n+  (with-current-buffer git-blame-file\n+    (or (gethash hash git-blame-cache)\n+        ;; Assign a random color to each new commit info\n+        ;; Take care not to select the same color multiple times\n+        (let* ((color (if git-blame-colors\n+                          (git-blame-random-pop git-blame-colors)\n+                        git-blame-ancient-color))\n+               (info `(,hash (color . ,color))))\n+          (puthash hash info git-blame-cache)\n+          info))))\n+\n+(defun git-blame-create-overlay (info start-line num-lines)\n   (save-excursion\n     (set-buffer git-blame-file)\n-    (let ((info (gethash hash git-blame-cache))\n-          (inhibit-point-motion-hooks t)\n+    (let ((inhibit-point-motion-hooks t)\n           (inhibit-modification-hooks t))\n-      (when (not info)\n-\t;; Assign a random color to each new commit info\n-\t;; Take care not to select the same color multiple times\n-\t(let ((color (if git-blame-colors\n-\t\t\t (git-blame-random-pop git-blame-colors)\n-\t\t       git-blame-ancient-color)))\n-          (setq info (list hash src-line res-line num-lines\n-                           (git-describe-commit hash)\n-                           (cons 'color color))))\n-        (puthash hash info git-blame-cache))\n-      (goto-line res-line)\n-      (while (> num-lines 0)\n-        (if (get-text-property (point) 'git-blame)\n-            (forward-line)\n-          (let* ((start (point))\n-                 (end (progn (forward-line 1) (point)))\n-                 (ovl (make-overlay start end)))\n-            (push ovl git-blame-overlays)\n-            (overlay-put ovl 'git-blame info)\n-            (overlay-put ovl 'help-echo hash)\n+      (goto-line start-line)\n+      (let* ((start (point))\n+             (end (progn (forward-line num-lines) (point)))\n+             (ovl (make-overlay start end))\n+             (hash (car info))\n+             (spec `((?h . ,(substring hash 0 6))\n+                     (?H . ,hash)\n+                     (?a . ,(git-blame-get-info info 'author))\n+                     (?A . ,(git-blame-get-info info 'author-mail))\n+                     (?c . ,(git-blame-get-info info 'committer))\n+                     (?C . ,(git-blame-get-info info 'committer-mail))\n+                     (?s . ,(git-blame-get-info info 'summary)))))\n+        (push ovl git-blame-overlays)\n+        (overlay-put ovl 'git-blame info)\n+        (overlay-put ovl 'help-echo\n+                     (format-spec git-blame-mouseover-format spec))\n+        (if git-blame-use-colors\n             (overlay-put ovl 'face (list :background\n-                                         (cdr (assq 'color (nthcdr 5 info)))))\n-            ;; the point-entered property doesn't seem to work in overlays\n-            ;;(overlay-put ovl 'point-entered\n-            ;;             `(lambda (x y) (git-blame-identify ,hash)))\n-            (let ((modified (buffer-modified-p)))\n-              (put-text-property (if (= start 1) start (1- start)) (1- end)\n-                                 'point-entered\n-                                 `(lambda (x y) (git-blame-identify ,hash)))\n-              (set-buffer-modified-p modified))))\n-        (setq num-lines (1- num-lines))))))\n-\n-(defun git-blame-add-info (key value)\n-  (if git-blame-current\n-      (nconc git-blame-current (list (cons (intern key) value)))))\n+                                         (cdr (assq 'color (cdr info))))))\n+        (overlay-put ovl 'line-prefix\n+                     (propertize (format-spec git-blame-prefix-format spec)\n+                                 'face 'git-blame-prefix-face))))))\n+\n+(defun git-blame-add-info (info key value)\n+  (nconc info (list (cons (intern key) value))))\n+\n+(defun git-blame-get-info (info key)\n+  (cdr (assq key (cdr info))))\n \n (defun git-blame-current-commit ()\n   (let ((info (get-char-property (point) 'git-blame)))\n-- \n1.6.4.rc3.21.g3b9e\n"}]}