about summary refs log tree commit diff
diff options
context:
space:
mode:
authorChristian Neukirchen <chneukirchen@gmail.com>2008-02-04 12:14:09 +0100
committerChristian Neukirchen <chneukirchen@gmail.com>2008-02-04 12:14:09 +0100
commit02264eeb965b2aaff4e10ef13456e1ec073a384f (patch)
treea1151550288ed7703b7f2e5c5247d8de2e1a61e8
downloadgitsum-02264eeb965b2aaff4e10ef13456e1ec073a384f.tar.gz
gitsum-02264eeb965b2aaff4e10ef13456e1ec073a384f.tar.xz
gitsum-02264eeb965b2aaff4e10ef13456e1ec073a384f.zip
Import gitsum.el
-rw-r--r--gitsum.el78
1 files changed, 78 insertions, 0 deletions
diff --git a/gitsum.el b/gitsum.el
new file mode 100644
index 0000000..69df506
--- /dev/null
+++ b/gitsum.el
@@ -0,0 +1,78 @@
+;;; gitsum.el --- basic darcsum feelalike for Git
+;; Copyright (C) 2008  Christian Neukirchen <purl.org/net/chneukirchen>
+;; Licensed under the same terms as Emacs.
+
+;; Version: 0.2
+;; 04feb2008  +chris+
+
+(easy-mmode-defmap gitsum-diff-mode-shared-map
+  '(("c" . gitsum-commit)
+    ("u" . gitsum-undo)
+    ("g" . gitsum-refresh))
+  "Basic keymap for `gitsum-diff-mode', bound to various prefix keys.")
+
+(define-derived-mode gitsum-diff-mode diff-mode "gitsum"
+  "Git summary mode is for preparing patches to a Git repository.
+This mode is meant to be activated by `M-x gitsum' or pressing `s' in git-status.
+\\{gitsum-diff-mode-map}"
+  ;; magic...
+  (lexical-let ((ro-bind (cons 'buffer-read-only gitsum-diff-mode-shared-map)))
+    (add-to-list 'minor-mode-overriding-map-alist ro-bind))
+  (setq buffer-read-only t))
+
+(define-key gitsum-diff-mode-map (kbd "C-c C-c") 'gitsum-commit)
+(define-key gitsum-diff-mode-map (kbd "C-/") 'gitsum-undo)
+(define-key gitsum-diff-mode-map (kbd "C-_") 'gitsum-undo)
+
+(define-key git-status-mode-map "s" 'gitsum)
+
+;; Undo doesn't work in read-only buffers else.
+(defun gitsum-undo ()
+  "Undo some previous changes.
+Repeat this command to undo more changes.
+A numeric argument serves as a repeat count."
+  (interactive)
+  (let ((inhibit-read-only t))
+    (undo)))
+
+(defun gitsum-refresh ()
+  "Regenerate the patch based on the current state of the index."
+  (interactive)
+  (let ((inhibit-read-only t))
+    (erase-buffer)
+    (insert "# Directory:  " default-directory "\n")
+    (insert "# Use n and p to navigate and k to kill a hunk.  u is undo, g will refresh.\n")
+    (insert "# Edit the patch as you please and press 'c' to commit.\n\n")
+    (insert (shell-command-to-string "git diff"))
+    (set-buffer-modified-p nil)
+    (goto-char (point-min))))
+
+(defun gitsum-commit ()
+  "Commit the patch as-is, asking for a commit message."
+  (interactive)
+  (shell-command-on-region (point-min) (point-max) "git apply --check --cached")
+  (let ((buffer (get-buffer-create "*gitsum-commit*")))
+    (shell-command-on-region (point-min) (point-max) "git apply --stat" buffer)
+    (with-current-buffer buffer
+      (goto-char (point-min))
+      (insert "\n")
+      (while (re-search-forward "^" nil t)
+        (replace-match "# " nil nil))
+      (goto-char (point-min)))
+    (log-edit 'gitsum-do-commit nil nil buffer)))
+
+(defun gitsum-do-commit ()
+  "Perform the actual commit using the current buffer as log message."
+  (interactive)
+  (with-current-buffer log-edit-parent-buffer
+    (shell-command-on-region (point-min) (point-max)
+                             "git apply --cached"))
+  (shell-command-on-region (point-min) (point-max) "git commit -F-"))
+
+(defun gitsum ()
+  "Entry point into gitsum-diff-mode."
+  (interactive)
+  (switch-to-buffer "*gitsum*")
+  (gitsum-diff-mode)
+  (font-lock-mode 1)
+  (gitsum-refresh))
\ No newline at end of file