Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 208 lines (183 sloc) 7.346 kB
02264ee @chneukirchen Import gitsum.el
authored
1 ;;; gitsum.el --- basic darcsum feelalike for Git
2 ;; Copyright (C) 2008 Christian Neukirchen <purl.org/net/chneukirchen>
3 ;; Licensed under the same terms as Emacs.
4
aea8cbf @chneukirchen Add some docs
authored
5 ;; Repository: http://github.com/chneukirchen/gitsum
6 ;; git://github.com/chneukirchen/gitsum.git
7 ;; Patches to: chneukirchen@gmail.com
8
02264ee @chneukirchen Import gitsum.el
authored
9 ;; Version: 0.2
10 ;; 04feb2008 +chris+
11
104865b @chneukirchen Ensure lexical-let exists when compiling
authored
12 (eval-when-compile (require 'cl))
13
e2f112f @tomas-abrahamsson Can now reuse an existing buffer displaying the same directory
tomas-abrahamsson authored
14 (defcustom gitsum-reuse-buffer t
15 "Whether `gitsum' should try to reuse an existing buffer
16 if there is already one that displays the same directory."
17 :group 'git
18 :type 'boolean)
19
02264ee @chneukirchen Import gitsum.el
authored
20 (easy-mmode-defmap gitsum-diff-mode-shared-map
d33c604 @chneukirchen Add gitsum-amend, bound to A
authored
21 '(("A" . gitsum-amend)
22 ("c" . gitsum-commit)
0a97a9c @chneukirchen Make `q' kill the buffer if unchanged
authored
23 ("g" . gitsum-refresh)
974d119 @chneukirchen Make kill more intuitive
authored
24 ("k" . gitsum-kill-dwim)
a860615 @chneukirchen Add gitsum-push, bound to P
authored
25 ("P" . gitsum-push)
b802c8d @chneukirchen Add gitsum-revert, bound to R
authored
26 ("R" . gitsum-revert)
d331786 @chneukirchen Add a short-cut to switch to git-status
authored
27 ("s" . gitsum-switch-to-git-status)
0a97a9c @chneukirchen Make `q' kill the buffer if unchanged
authored
28 ("q" . gitsum-kill-buffer)
29 ("u" . gitsum-undo))
02264ee @chneukirchen Import gitsum.el
authored
30 "Basic keymap for `gitsum-diff-mode', bound to various prefix keys.")
31
32 (define-derived-mode gitsum-diff-mode diff-mode "gitsum"
33 "Git summary mode is for preparing patches to a Git repository.
34 This mode is meant to be activated by `M-x gitsum' or pressing `s' in git-status.
94e6974 @chneukirchen Show shared-map keybindings in the docstring as well
authored
35 \\{gitsum-diff-mode-shared-map}
02264ee @chneukirchen Import gitsum.el
authored
36 \\{gitsum-diff-mode-map}"
37 ;; magic...
38 (lexical-let ((ro-bind (cons 'buffer-read-only gitsum-diff-mode-shared-map)))
39 (add-to-list 'minor-mode-overriding-map-alist ro-bind))
40 (setq buffer-read-only t))
41
42 (define-key gitsum-diff-mode-map (kbd "C-c C-c") 'gitsum-commit)
43 (define-key gitsum-diff-mode-map (kbd "C-/") 'gitsum-undo)
44 (define-key gitsum-diff-mode-map (kbd "C-_") 'gitsum-undo)
45
0630f04 @chneukirchen Hack into keymap only if git.el is loaded
authored
46 ;; When git.el is loaded, hack into keymap.
47 (when (boundp 'git-status-mode-map)
bba2d31 @chneukirchen Make "s" in git-status acknowledge the currently marked files
authored
48 (define-key git-status-mode-map "s" 'gitsum-switch-from-git-status))
02264ee @chneukirchen Import gitsum.el
authored
49
50 ;; Undo doesn't work in read-only buffers else.
51 (defun gitsum-undo ()
52 "Undo some previous changes.
31660bd @chneukirchen Remove git-diff crud that confuses diff-mode
authored
53
02264ee @chneukirchen Import gitsum.el
authored
54 Repeat this command to undo more changes.
55 A numeric argument serves as a repeat count."
56 (interactive)
57 (let ((inhibit-read-only t))
58 (undo)))
59
bba2d31 @chneukirchen Make "s" in git-status acknowledge the currently marked files
authored
60 (defun gitsum-refresh (&optional arguments)
02264ee @chneukirchen Import gitsum.el
authored
61 "Regenerate the patch based on the current state of the index."
62 (interactive)
63 (let ((inhibit-read-only t))
64 (erase-buffer)
65 (insert "# Directory: " default-directory "\n")
66 (insert "# Use n and p to navigate and k to kill a hunk. u is undo, g will refresh.\n")
67 (insert "# Edit the patch as you please and press 'c' to commit.\n\n")
bba2d31 @chneukirchen Make "s" in git-status acknowledge the currently marked files
authored
68 (let ((diff (shell-command-to-string (concat "git diff " arguments))))
8e7e33a @chneukirchen Show message on empty diff
authored
69 (if (zerop (length diff))
70 (insert "## No changes. ##")
31660bd @chneukirchen Remove git-diff crud that confuses diff-mode
authored
71 (insert diff)
72 (goto-char (point-min))
73 (delete-matching-lines "^index \\|^diff --git ")))
974d119 @chneukirchen Make kill more intuitive
authored
74 (set-buffer-modified-p nil)
75 (goto-char (point-min))
76 (forward-line 4)))
77
78 (defun gitsum-kill-dwim ()
79 "Kill the current hunk or file depending on point."
80 (interactive)
81 (let ((inhibit-read-only t))
82 (if (looking-at "^---\\|^\\+\\+\\+")
83 (diff-file-kill)
84 (diff-hunk-kill)
85 (save-excursion
86 (when (or (looking-at "^--- ")
87 (eobp))
88 (let ((here (point)))
89 (forward-line -2)
90 (when (looking-at "^--- ")
91 (delete-region here (point)))))))))
02264ee @chneukirchen Import gitsum.el
authored
92
93 (defun gitsum-commit ()
94 "Commit the patch as-is, asking for a commit message."
95 (interactive)
96 (shell-command-on-region (point-min) (point-max) "git apply --check --cached")
2d34131 @chneukirchen Ensure log buffer has correct default-directory
authored
97 (let ((buffer (get-buffer-create "*gitsum-commit*"))
98 (dir default-directory))
240c611 @chneukirchen Display diffstat for whole index
authored
99 (shell-command-on-region (point-min) (point-max) "(cat; git diff --cached) | git apply --stat" buffer)
02264ee @chneukirchen Import gitsum.el
authored
100 (with-current-buffer buffer
2d34131 @chneukirchen Ensure log buffer has correct default-directory
authored
101 (setq default-directory dir)
02264ee @chneukirchen Import gitsum.el
authored
102 (goto-char (point-min))
103 (insert "\n")
104 (while (re-search-forward "^" nil t)
105 (replace-match "# " nil nil))
053c2e9 @chneukirchen Don't display empty comment line after diffstat
authored
106 (forward-line 0)
107 (forward-char -1)
108 (delete-region (point) (point-max))
02264ee @chneukirchen Import gitsum.el
authored
109 (goto-char (point-min)))
110 (log-edit 'gitsum-do-commit nil nil buffer)))
111
d33c604 @chneukirchen Add gitsum-amend, bound to A
authored
112 (defun gitsum-amend ()
113 "Amend the last commit."
114 (interactive)
115 (let ((last (substring (shell-command-to-string
116 "git log -1 --pretty=oneline --abbrev-commit")
117 0 -1)))
118 (when (y-or-n-p (concat "Are you sure you want to amend to " last "? "))
119 (shell-command-on-region (point-min) (point-max) "git apply --cached")
120 (shell-command "git commit --amend -C HEAD")
121 (gitsum-refresh))))
122
a860615 @chneukirchen Add gitsum-push, bound to P
authored
123 (defun gitsum-push ()
124 "Push the current repository."
125 (interactive)
126 (let ((args (read-string "Shell command: " "git push ")))
2a6f834 @chneukirchen Make gitsum-push async
authored
127 (let ((buffer (get-buffer-create " *gitsum-push*")))
128 (switch-to-buffer buffer)
129 (insert "Running " args "...\n\n")
130 (start-process-shell-command "gitsum-push" buffer args))))
a860615 @chneukirchen Add gitsum-push, bound to P
authored
131
b802c8d @chneukirchen Add gitsum-revert, bound to R
authored
132 (defun gitsum-revert ()
133 "Revert the active patches in the working directory."
134 (interactive)
135 (let ((count (count-matches "^@@" (point-min) (point-max))))
136 (if (not (yes-or-no-p
137 (format "Are you sure you want to revert these %d hunk(s)? "
138 count)))
139 (message "Revert canceled.")
140 (shell-command-on-region (point-min) (point-max) "git apply --reverse")
141 (gitsum-refresh))))
142
02264ee @chneukirchen Import gitsum.el
authored
143 (defun gitsum-do-commit ()
144 "Perform the actual commit using the current buffer as log message."
145 (interactive)
146 (with-current-buffer log-edit-parent-buffer
147 (shell-command-on-region (point-min) (point-max)
148 "git apply --cached"))
4c5ca17 @chneukirchen Kill the comments when committing
authored
149 (shell-command-on-region (point-min) (point-max)
8e7e33a @chneukirchen Show message on empty diff
authored
150 "git commit -F- --cleanup=strip")
151 (with-current-buffer log-edit-parent-buffer
152 (gitsum-refresh)))
02264ee @chneukirchen Import gitsum.el
authored
153
0a97a9c @chneukirchen Make `q' kill the buffer if unchanged
authored
154 (defun gitsum-kill-buffer ()
155 "Kill the current buffer if it has no manual changes."
156 (interactive)
d7cf26f @chneukirchen Don't fail silently trying to close a modified buffer
authored
157 (if (buffer-modified-p)
158 (message "Patch was modified, use C-x k to kill.")
0a97a9c @chneukirchen Make `q' kill the buffer if unchanged
authored
159 (kill-buffer nil)))
160
d331786 @chneukirchen Add a short-cut to switch to git-status
authored
161 (defun gitsum-switch-to-git-status ()
162 "Switch to git-status."
163 (interactive)
164 (git-status default-directory))
165
bba2d31 @chneukirchen Make "s" in git-status acknowledge the currently marked files
authored
166 (defun gitsum-switch-from-git-status ()
167 "Switch to gitsum, resticting diff to marked files if any."
168 (interactive)
169 (let ((marked (git-get-filenames
170 (ewoc-collect git-status
171 (lambda (info) (git-fileinfo->marked info))))))
172 (gitsum)
173 (when marked
174 (gitsum-refresh (mapconcat 'identity marked " ")))))
175
e2f112f @tomas-abrahamsson Can now reuse an existing buffer displaying the same directory
tomas-abrahamsson authored
176 (defun gitsum-find-buffer (dir)
177 "Find the gitsum buffer handling a specified directory."
178 (let ((list (buffer-list))
179 (fulldir (expand-file-name dir))
180 found)
181 (while (and list (not found))
182 (let ((buffer (car list)))
183 (with-current-buffer buffer
184 (when (and list-buffers-directory
185 (string-equal fulldir
186 (expand-file-name list-buffers-directory))
187 (eq major-mode 'gitsum-diff-mode))
188 (setq found buffer))))
189 (setq list (cdr list)))
190 found))
191
02264ee @chneukirchen Import gitsum.el
authored
192 (defun gitsum ()
193 "Entry point into gitsum-diff-mode."
194 (interactive)
e2f112f @tomas-abrahamsson Can now reuse an existing buffer displaying the same directory
tomas-abrahamsson authored
195 (let* ((dir default-directory)
196 (buffer (or (and gitsum-reuse-buffer (gitsum-find-buffer dir))
197 (generate-new-buffer "*gitsum*"))))
198 (switch-to-buffer buffer)
199 (gitsum-diff-mode)
200 (set (make-local-variable 'list-buffers-directory) dir)
201 (gitsum-refresh)))
8116bf2 @chneukirchen Provide gitsum
authored
202
1cbc163 gitsum.el: add viper compatible
Levin Du authored
203 ;; viper compatible
204 (eval-after-load "viper"
205 '(add-to-list 'viper-emacs-state-mode-list 'gitsum-diff-mode))
206
8116bf2 @chneukirchen Provide gitsum
authored
207 (provide 'gitsum)
Something went wrong with that request. Please try again.