;; Author: Steve Youngs <steve@sxemacs.org>
;; Maintainer: Steve Youngs <steve@sxemacs.org>
;; Created: <2015-07-05>
-;; Time-stamp: <Monday Oct 16, 2017 09:05:17 steve>
+;; Time-stamp: <Thursday Oct 19, 2017 21:43:53 steve>
;; Homepage: http://git.sxemacs.org/slh
;; Keywords: git, tools, convenience
(require 'ediff)
(require 'diff-mode)
-;; diff
+
+(defun sy-git-check-hook (hook)
+ "Return non-nil when HOOK script exists and is usable.
+
+By \"usable\" we mean for `sy-git-add-log-entry'."
+ (let ((hookname (file-basename hook)))
+ (when (file-exists-p hook)
+ (with-temp-buffer
+ (insert-file-contents-literally hook)
+ (goto-char (point-min))
+ (cond
+ ((equal hookname "commit-msg")
+ (re-search-forward (regexp-quote "sed -i '/^#/d'") nil t))
+ ((equal hookname "post-commit")
+ (re-search-forward (regexp-quote "rm -f ${LOG}") nil t))
+ (t nil))))))
+
+;;; diff
+;; FIXME: might be nice to be able to diff against other revisions
+;; aside from HEAD.
(defun sy-git-diff ()
"Show a diff of the current file against HEAD."
(interactive)
(vc-version-other-window "HEAD")
(ediff-buffers bufferA bufferB))))
-;; blame
+;;; blame
(defun sy-git-blame ()
"Display git blame for the current file.
file within the region."
(interactive)
(let ((gitcmd "git blame ")
+ (cb (current-buffer))
+ (gb (format "*GIT Blame::%s*"
+ (file-basename (buffer-file-name))))
beg end)
(when (region-active-p)
(setq beg (line-number (region-beginning))
(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.
+ (push-window-configuration)
+ (with-current-buffer (get-buffer-create gb)
+ (erase-buffer)
+ (setq truncate-lines t)
+ (insert (shell-command-to-string gitcmd))
+ (goto-char (point-min))
+ (view-mode cb #'(lambda (gb)
+ (kill-buffer gb)
+ (pop-window-configuration))))
+ (pop-to-buffer gb)
+ (shrink-window-if-larger-than-buffer)))
-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*")))
+;;; log
+(defvar sy-git-log-font-lock-keywords
+ '(;;
+ ;; Headers
+ ("^commit .*$"
+ (0 font-lock-warning-face))
+ (#r"^\(Author\(Date\)?:\|Commit\(Date\)?:\|Date:\|Merge:\)"
+ (1 gnus-header-content))
+ ;; date
+ (#r"Date:\(.*$\)"
+ (1 change-log-date-face))
+ ;; name/email
+ (#r":\s-+\(.*\)\s-+<\(.*\)>"
+ (1 change-log-name-face)
+ (2 change-log-email-face))
+ ;; file name
+ (#r"^\s-+\* \([^ ,:(]+\)"
+ (1 change-log-file-face))
+ ;; Function or variable names.
+ ("(\\([^) ,:\n]+\\)"
+ (1 change-log-list-face)
+ ("\\=, *\\([^) ,:\n]+\\)" nil nil
+ (1 change-log-list-face)))
+ ;; Signed-off
+ (#r"\(Signed-off\|Reviewed\|Reported\|Acked\)-by:\|Cc:"
+ (0 gnus-header-content))))
-(defun sy-git-check-hook (hook)
- "Return non-nil when HOOK script exists and is usable.
+(defun sy-git-log (opts)
+ "Display git log of current file.
-By \"usable\" we mean for `sy-git-add-log-entry'."
- (let ((hookname (file-basename hook)))
- (when (file-exists-p hook)
- (with-temp-buffer
- (insert-file-contents-literally hook)
- (goto-char (point-min))
- (cond
- ((equal hookname "commit-msg")
- (re-search-forward (regexp-quote "sed -i '/^#/d'") nil t))
- ((equal hookname "post-commit")
- (re-search-forward (regexp-quote "rm -f ${LOG}") nil t))
- (t nil))))))
+With one prefix arg, OPTS, display the log for the entire repo.
+With two prefix args, prompt for options to pass to git-log.
+
+The default options used are: `--shortstat', except when two prefix
+args are used and then the only options used are those the user
+supplies."
+ (interactive "P")
+ (let ((cb (current-buffer))
+ (gb "*GIT Log::%s*")
+ (gitcmd "git log"))
+ (case (car opts)
+ ;; 1 prefix arg, log for whole repo
+ (4 (setq gitcmd (concat gitcmd " --shortstat")
+ gb (format gb "Whole Repo")))
+ ;; 2 prefix args, prompt for options
+ (16 (setq gitcmd (concat gitcmd " "
+ (read-string "Git Log options: "))
+ gb (format gb "Custom")))
+ ;; default, show log of current file
+ (otherwise (setq gitcmd (concat gitcmd
+ " --shortstat "
+ (file-basename (buffer-file-name)))
+ gb (format gb (file-basename (buffer-file-name))))))
+ (push-window-configuration)
+ (with-current-buffer (get-buffer-create gb)
+ (erase-buffer)
+ (set (make-local-variable 'font-lock-defaults)
+ '(sy-git-log-font-lock-keywords t t))
+ (insert (shell-command-to-string gitcmd))
+ (goto-char (point-min))
+ (view-mode cb #'(lambda (gb)
+ (kill-buffer gb)
+ (pop-window-configuration))))
+ (pop-to-buffer gb)
+ (shrink-window-if-larger-than-buffer)))
+;;; add-log
(defun sy-git-add-log-entry (&optional newlog)
"*A wrapper for `add-change-log-entry'.