Add rudimentary support for git diff, blame, and log.
authorSteve Youngs <steve@sxemacs.org>
Mon, 16 Oct 2017 00:01:46 +0000 (10:01 +1000)
committerSteve Youngs <steve@sxemacs.org>
Mon, 16 Oct 2017 00:01:46 +0000 (10:01 +1000)
* sy-git.el (sy-git-diff): New.
(sy-git-ediff): New.
(sy-git-blame): New.
(sy-git-log): New.

Signed-off-by: Steve Youngs <steve@sxemacs.org>
sy-git.el

index f141125..962c641 100644 (file)
--- a/sy-git.el
+++ b/sy-git.el
@@ -1,11 +1,11 @@
 ;; sy-git.el --- A couple of nice git tools   -*- Emacs-Lisp -*-
 
-;; Copyright (C) 2015 Steve Youngs
+;; Copyright (C) 2015 - 2017 Steve Youngs
 
 ;; Author:     Steve Youngs <steve@sxemacs.org>
 ;; Maintainer: Steve Youngs <steve@sxemacs.org>
 ;; Created:    <2015-07-05>
-;; Time-stamp: <Friday Jul 15, 2016 15:02:16 steve>
+;; Time-stamp: <Monday Oct 16, 2017 09:05:17 steve>
 ;; Homepage:   http://git.sxemacs.org/slh
 ;; Keywords:   git, tools, convenience
 
 ;;   lets you write commit logs in a similar format to that of
 ;;   `add-change-log-entry'.  It is globally bound to `C-x G a'.
 ;;   See: `sy-git-add-log-entry'.
+;;
+;;   [2017-10-16 08:59]: Added rudimentary support for git-diff,
+;;   git-blame, and git-log.  For examining changes you can use
+;;   either plain `diff-mode' with `sy-git-diff', or Ediff with
+;;   `sy-git-ediff'.
 
 ;;; Todo:
 ;;
-;;     o Implement a variation of `patch-to-change-log'
+;;     o Implement a variation of `patch-to-change-log'.
+;;        [2017-10-15 15:09]: Turns out that this isn't really needed
+;;        as you can invoke `sy-git-add-log-entry' directly from a diff.
 
 ;;; Code:
+;; Need VC, ediff, and diff-mode
+(vc-load-vc-hooks)
+(add-to-list 'vc-handled-backends 'GIT)
+(require 'ediff)
+(require 'diff-mode)
+
+;; diff
+(defun sy-git-diff ()
+  "Show a diff of the current file against HEAD."
+  (interactive)
+  (vc-diff nil))
+
+(defun sy-git-ediff ()
+  "Run ediff-buffers on the working file and the HEAD version."
+  (interactive)
+  (let* ((bufferA (file-basename (buffer-file-name)))
+        (bufferB (concat bufferA ".~HEAD~")))
+    (progn
+      (vc-version-other-window "HEAD")
+      (ediff-buffers bufferA bufferB))))
+
+;; blame
+(defun sy-git-blame ()
+  "Display git blame for the current file.
+
+If the region is active the output will be for just the lines of the
+file within the region."
+  (interactive)
+  (let ((gitcmd "git blame ")
+       beg end)
+    (when (region-active-p)
+      (setq beg (line-number (region-beginning))
+           end (line-number (region-end))))
+    (and beg end
+        (setq gitcmd (concat gitcmd (format "-L%d,%d " beg end))))
+    (setq gitcmd (concat gitcmd (file-basename (buffer-file-name))))
+    (with-electric-help
+     #'(lambda ()
+        (setq truncate-lines t)
+        (insert
+         (with-temp-buffer
+           (insert (shell-command-to-string gitcmd))
+           (buffer-string (current-buffer)))))
+     "*GIT Blame*")))
+
+;; log
+(defun sy-git-log (all)
+  "Display git log of current file.
+
+With prefix arg, ALL, display the log for the entire repo."
+  (interactive "p")
+  (let ((gitcmd "git log --format=fuller"))
+    (unless current-prefix-arg
+      (setq gitcmd
+           (concat gitcmd
+                   (format " %s" (file-basename (buffer-file-name))))))
+    (with-electric-help
+     #'(lambda ()
+        (insert
+         (with-temp-buffer
+           (insert (shell-command-to-string gitcmd))
+           (buffer-string (current-buffer)))))
+     "*GIT Log*")))
+
 (defun sy-git-check-hook (hook)
   "Return non-nil when HOOK script exists and is usable.