##// END OF EJS Templates
mq.el: define keymaps as convensions
NIIMI Satoshi -
r5468:24eb1bf8 default
parent child Browse files
Show More
@@ -1,414 +1,418
1 ;;; mq.el --- Emacs support for Mercurial Queues
1 ;;; mq.el --- Emacs support for Mercurial Queues
2
2
3 ;; Copyright (C) 2006 Bryan O'Sullivan
3 ;; Copyright (C) 2006 Bryan O'Sullivan
4
4
5 ;; Author: Bryan O'Sullivan <bos@serpentine.com>
5 ;; Author: Bryan O'Sullivan <bos@serpentine.com>
6
6
7 ;; mq.el is free software; you can redistribute it and/or modify it
7 ;; mq.el is free software; you can redistribute it and/or modify it
8 ;; under the terms of version 2 of the GNU General Public License as
8 ;; under the terms of version 2 of the GNU General Public License as
9 ;; published by the Free Software Foundation.
9 ;; published by the Free Software Foundation.
10
10
11 ;; mq.el is distributed in the hope that it will be useful, but
11 ;; mq.el is distributed in the hope that it will be useful, but
12 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
12 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
13 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ;; General Public License for more details.
14 ;; General Public License for more details.
15
15
16 ;; You should have received a copy of the GNU General Public License
16 ;; You should have received a copy of the GNU General Public License
17 ;; along with mq.el, GNU Emacs, or XEmacs; see the file COPYING (`C-h
17 ;; along with mq.el, GNU Emacs, or XEmacs; see the file COPYING (`C-h
18 ;; C-l'). If not, write to the Free Software Foundation, Inc., 59
18 ;; C-l'). If not, write to the Free Software Foundation, Inc., 59
19 ;; Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 ;; Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20
20
21 (eval-when-compile (require 'cl))
21 (eval-when-compile (require 'cl))
22 (require 'mercurial)
22 (require 'mercurial)
23
23
24
24
25 (defcustom mq-mode-hook nil
25 (defcustom mq-mode-hook nil
26 "Hook run when a buffer enters mq-mode."
26 "Hook run when a buffer enters mq-mode."
27 :type 'sexp
27 :type 'sexp
28 :group 'mercurial)
28 :group 'mercurial)
29
29
30 (defcustom mq-global-prefix "\C-cq"
30 (defcustom mq-global-prefix "\C-cq"
31 "The global prefix for Mercurial Queues keymap bindings."
31 "The global prefix for Mercurial Queues keymap bindings."
32 :type 'sexp
32 :type 'sexp
33 :group 'mercurial)
33 :group 'mercurial)
34
34
35 (defcustom mq-edit-mode-hook nil
35 (defcustom mq-edit-mode-hook nil
36 "Hook run after a buffer is populated to edit a patch description."
36 "Hook run after a buffer is populated to edit a patch description."
37 :type 'sexp
37 :type 'sexp
38 :group 'mercurial)
38 :group 'mercurial)
39
39
40 (defcustom mq-edit-finish-hook nil
40 (defcustom mq-edit-finish-hook nil
41 "Hook run before a patch description is finished up with."
41 "Hook run before a patch description is finished up with."
42 :type 'sexp
42 :type 'sexp
43 :group 'mercurial)
43 :group 'mercurial)
44
44
45 (defcustom mq-signoff-address nil
45 (defcustom mq-signoff-address nil
46 "Address with which to sign off on a patch."
46 "Address with which to sign off on a patch."
47 :type 'string
47 :type 'string
48 :group 'mercurial)
48 :group 'mercurial)
49
49
50
50
51 ;;; Internal variables.
51 ;;; Internal variables.
52
52
53 (defvar mq-mode nil
53 (defvar mq-mode nil
54 "Is this file managed by MQ?")
54 "Is this file managed by MQ?")
55 (make-variable-buffer-local 'mq-mode)
55 (make-variable-buffer-local 'mq-mode)
56 (put 'mq-mode 'permanent-local t)
56 (put 'mq-mode 'permanent-local t)
57
57
58 (defvar mq-patch-history nil)
58 (defvar mq-patch-history nil)
59
59
60 (defvar mq-top-patch '(nil))
60 (defvar mq-top-patch '(nil))
61
61
62 (defvar mq-prev-buffer nil)
62 (defvar mq-prev-buffer nil)
63 (make-variable-buffer-local 'mq-prev-buffer)
63 (make-variable-buffer-local 'mq-prev-buffer)
64 (put 'mq-prev-buffer 'permanent-local t)
64 (put 'mq-prev-buffer 'permanent-local t)
65
65
66 (defvar mq-top nil)
66 (defvar mq-top nil)
67 (make-variable-buffer-local 'mq-top)
67 (make-variable-buffer-local 'mq-top)
68 (put 'mq-top 'permanent-local t)
68 (put 'mq-top 'permanent-local t)
69
69
70 ;;; Global keymap.
70 ;;; Global keymap.
71
71
72 (defvar mq-global-map (make-sparse-keymap))
72 (defvar mq-global-map
73 (fset 'mq-global-map mq-global-map)
73 (let ((map (make-sparse-keymap)))
74 (global-set-key mq-global-prefix 'mq-global-map)
74 (define-key map "." 'mq-push)
75 (define-key mq-global-map "." 'mq-push)
75 (define-key map ">" 'mq-push-all)
76 (define-key mq-global-map ">" 'mq-push-all)
76 (define-key map "," 'mq-pop)
77 (define-key mq-global-map "," 'mq-pop)
77 (define-key map "<" 'mq-pop-all)
78 (define-key mq-global-map "<" 'mq-pop-all)
78 (define-key map "=" 'mq-diff)
79 (define-key mq-global-map "=" 'mq-diff)
79 (define-key map "r" 'mq-refresh)
80 (define-key mq-global-map "r" 'mq-refresh)
80 (define-key map "e" 'mq-refresh-edit)
81 (define-key mq-global-map "e" 'mq-refresh-edit)
81 (define-key map "i" 'mq-new)
82 (define-key mq-global-map "i" 'mq-new)
82 (define-key map "n" 'mq-next)
83 (define-key mq-global-map "n" 'mq-next)
83 (define-key map "o" 'mq-signoff)
84 (define-key mq-global-map "o" 'mq-signoff)
84 (define-key map "p" 'mq-previous)
85 (define-key mq-global-map "p" 'mq-previous)
85 (define-key map "s" 'mq-edit-series)
86 (define-key mq-global-map "s" 'mq-edit-series)
86 (define-key map "t" 'mq-top)
87 (define-key mq-global-map "t" 'mq-top)
87 map))
88
89 (global-set-key mq-global-prefix mq-global-map)
88
90
89 (add-minor-mode 'mq-mode 'mq-mode)
91 (add-minor-mode 'mq-mode 'mq-mode)
90
92
91
93
92 ;;; Refresh edit mode keymap.
94 ;;; Refresh edit mode keymap.
93
95
94 (defvar mq-edit-mode-map (make-sparse-keymap))
96 (defvar mq-edit-mode-map
95 (define-key mq-edit-mode-map "\C-c\C-c" 'mq-edit-finish)
97 (let ((map (make-sparse-keymap)))
96 (define-key mq-edit-mode-map "\C-c\C-k" 'mq-edit-kill)
98 (define-key map "\C-c\C-c" 'mq-edit-finish)
97 (define-key mq-edit-mode-map "\C-c\C-s" 'mq-signoff)
99 (define-key map "\C-c\C-k" 'mq-edit-kill)
100 (define-key map "\C-c\C-s" 'mq-signoff)
101 map))
98
102
99
103
100 ;;; Helper functions.
104 ;;; Helper functions.
101
105
102 (defun mq-read-patch-name (&optional source prompt force)
106 (defun mq-read-patch-name (&optional source prompt force)
103 "Read a patch name to use with a command.
107 "Read a patch name to use with a command.
104 May return nil, meaning \"use the default\"."
108 May return nil, meaning \"use the default\"."
105 (let ((patches (split-string
109 (let ((patches (split-string
106 (hg-chomp (hg-run0 (or source "qseries"))) "\n")))
110 (hg-chomp (hg-run0 (or source "qseries"))) "\n")))
107 (when force
111 (when force
108 (completing-read (format "Patch%s: " (or prompt ""))
112 (completing-read (format "Patch%s: " (or prompt ""))
109 (mapcar (lambda (x) (cons x x)) patches)
113 (mapcar (lambda (x) (cons x x)) patches)
110 nil
114 nil
111 nil
115 nil
112 nil
116 nil
113 'mq-patch-history))))
117 'mq-patch-history))))
114
118
115 (defun mq-refresh-buffers (root)
119 (defun mq-refresh-buffers (root)
116 (save-excursion
120 (save-excursion
117 (dolist (buf (hg-buffers-visiting-repo root))
121 (dolist (buf (hg-buffers-visiting-repo root))
118 (when (not (verify-visited-file-modtime buf))
122 (when (not (verify-visited-file-modtime buf))
119 (set-buffer buf)
123 (set-buffer buf)
120 (let ((ctx (hg-buffer-context)))
124 (let ((ctx (hg-buffer-context)))
121 (message "Refreshing %s..." (buffer-name))
125 (message "Refreshing %s..." (buffer-name))
122 (revert-buffer t t t)
126 (revert-buffer t t t)
123 (hg-restore-context ctx)
127 (hg-restore-context ctx)
124 (message "Refreshing %s...done" (buffer-name))))))
128 (message "Refreshing %s...done" (buffer-name))))))
125 (hg-update-mode-lines root)
129 (hg-update-mode-lines root)
126 (mq-update-mode-lines root))
130 (mq-update-mode-lines root))
127
131
128 (defun mq-last-line ()
132 (defun mq-last-line ()
129 (goto-char (point-max))
133 (goto-char (point-max))
130 (beginning-of-line)
134 (beginning-of-line)
131 (when (looking-at "^$")
135 (when (looking-at "^$")
132 (forward-line -1))
136 (forward-line -1))
133 (let ((bol (point)))
137 (let ((bol (point)))
134 (end-of-line)
138 (end-of-line)
135 (let ((line (buffer-substring bol (point))))
139 (let ((line (buffer-substring bol (point))))
136 (when (> (length line) 0)
140 (when (> (length line) 0)
137 line))))
141 line))))
138
142
139 (defun mq-push (&optional patch)
143 (defun mq-push (&optional patch)
140 "Push patches until PATCH is reached.
144 "Push patches until PATCH is reached.
141 If PATCH is nil, push at most one patch."
145 If PATCH is nil, push at most one patch."
142 (interactive (list (mq-read-patch-name "qunapplied" " to push"
146 (interactive (list (mq-read-patch-name "qunapplied" " to push"
143 current-prefix-arg)))
147 current-prefix-arg)))
144 (let ((root (hg-root))
148 (let ((root (hg-root))
145 (prev-buf (current-buffer))
149 (prev-buf (current-buffer))
146 last-line ok)
150 last-line ok)
147 (unless root
151 (unless root
148 (error "Cannot push outside a repository!"))
152 (error "Cannot push outside a repository!"))
149 (hg-sync-buffers root)
153 (hg-sync-buffers root)
150 (let ((buf-name (format "MQ: Push %s" (or patch "next patch"))))
154 (let ((buf-name (format "MQ: Push %s" (or patch "next patch"))))
151 (kill-buffer (get-buffer-create buf-name))
155 (kill-buffer (get-buffer-create buf-name))
152 (split-window-vertically)
156 (split-window-vertically)
153 (other-window 1)
157 (other-window 1)
154 (switch-to-buffer (get-buffer-create buf-name))
158 (switch-to-buffer (get-buffer-create buf-name))
155 (cd root)
159 (cd root)
156 (message "Pushing...")
160 (message "Pushing...")
157 (setq ok (= 0 (apply 'call-process (hg-binary) nil t t "qpush"
161 (setq ok (= 0 (apply 'call-process (hg-binary) nil t t "qpush"
158 (if patch (list patch))))
162 (if patch (list patch))))
159 last-line (mq-last-line))
163 last-line (mq-last-line))
160 (let ((lines (count-lines (point-min) (point-max))))
164 (let ((lines (count-lines (point-min) (point-max))))
161 (if (or (<= lines 1)
165 (if (or (<= lines 1)
162 (and (equal lines 2) (string-match "Now at:" last-line)))
166 (and (equal lines 2) (string-match "Now at:" last-line)))
163 (progn
167 (progn
164 (kill-buffer (current-buffer))
168 (kill-buffer (current-buffer))
165 (delete-window))
169 (delete-window))
166 (hg-view-mode prev-buf))))
170 (hg-view-mode prev-buf))))
167 (mq-refresh-buffers root)
171 (mq-refresh-buffers root)
168 (sit-for 0)
172 (sit-for 0)
169 (when last-line
173 (when last-line
170 (if ok
174 (if ok
171 (message "Pushing... %s" last-line)
175 (message "Pushing... %s" last-line)
172 (error "Pushing... %s" last-line)))))
176 (error "Pushing... %s" last-line)))))
173
177
174 (defun mq-push-all ()
178 (defun mq-push-all ()
175 "Push patches until all are applied."
179 "Push patches until all are applied."
176 (interactive)
180 (interactive)
177 (mq-push "-a"))
181 (mq-push "-a"))
178
182
179 (defun mq-pop (&optional patch)
183 (defun mq-pop (&optional patch)
180 "Pop patches until PATCH is reached.
184 "Pop patches until PATCH is reached.
181 If PATCH is nil, pop at most one patch."
185 If PATCH is nil, pop at most one patch."
182 (interactive (list (mq-read-patch-name "qapplied" " to pop to"
186 (interactive (list (mq-read-patch-name "qapplied" " to pop to"
183 current-prefix-arg)))
187 current-prefix-arg)))
184 (let ((root (hg-root))
188 (let ((root (hg-root))
185 last-line ok)
189 last-line ok)
186 (unless root
190 (unless root
187 (error "Cannot pop outside a repository!"))
191 (error "Cannot pop outside a repository!"))
188 (hg-sync-buffers root)
192 (hg-sync-buffers root)
189 (set-buffer (generate-new-buffer "qpop"))
193 (set-buffer (generate-new-buffer "qpop"))
190 (cd root)
194 (cd root)
191 (message "Popping...")
195 (message "Popping...")
192 (setq ok (= 0 (apply 'call-process (hg-binary) nil t t "qpop"
196 (setq ok (= 0 (apply 'call-process (hg-binary) nil t t "qpop"
193 (if patch (list patch))))
197 (if patch (list patch))))
194 last-line (mq-last-line))
198 last-line (mq-last-line))
195 (kill-buffer (current-buffer))
199 (kill-buffer (current-buffer))
196 (mq-refresh-buffers root)
200 (mq-refresh-buffers root)
197 (sit-for 0)
201 (sit-for 0)
198 (when last-line
202 (when last-line
199 (if ok
203 (if ok
200 (message "Popping... %s" last-line)
204 (message "Popping... %s" last-line)
201 (error "Popping... %s" last-line)))))
205 (error "Popping... %s" last-line)))))
202
206
203 (defun mq-pop-all ()
207 (defun mq-pop-all ()
204 "Push patches until none are applied."
208 "Push patches until none are applied."
205 (interactive)
209 (interactive)
206 (mq-pop "-a"))
210 (mq-pop "-a"))
207
211
208 (defun mq-refresh-internal (root &rest args)
212 (defun mq-refresh-internal (root &rest args)
209 (hg-sync-buffers root)
213 (hg-sync-buffers root)
210 (let ((patch (mq-patch-info "qtop")))
214 (let ((patch (mq-patch-info "qtop")))
211 (message "Refreshing %s..." patch)
215 (message "Refreshing %s..." patch)
212 (let ((ret (apply 'hg-run "qrefresh" args)))
216 (let ((ret (apply 'hg-run "qrefresh" args)))
213 (if (equal (car ret) 0)
217 (if (equal (car ret) 0)
214 (message "Refreshing %s... done." patch)
218 (message "Refreshing %s... done." patch)
215 (error "Refreshing %s... %s" patch (hg-chomp (cdr ret)))))))
219 (error "Refreshing %s... %s" patch (hg-chomp (cdr ret)))))))
216
220
217 (defun mq-refresh (&optional git)
221 (defun mq-refresh (&optional git)
218 "Refresh the topmost applied patch.
222 "Refresh the topmost applied patch.
219 With a prefix argument, generate a git-compatible patch."
223 With a prefix argument, generate a git-compatible patch."
220 (interactive "P")
224 (interactive "P")
221 (let ((root (hg-root)))
225 (let ((root (hg-root)))
222 (unless root
226 (unless root
223 (error "Cannot refresh outside of a repository!"))
227 (error "Cannot refresh outside of a repository!"))
224 (apply 'mq-refresh-internal root (if git '("--git")))))
228 (apply 'mq-refresh-internal root (if git '("--git")))))
225
229
226 (defun mq-patch-info (cmd &optional msg)
230 (defun mq-patch-info (cmd &optional msg)
227 (let* ((ret (hg-run cmd))
231 (let* ((ret (hg-run cmd))
228 (info (hg-chomp (cdr ret))))
232 (info (hg-chomp (cdr ret))))
229 (if (equal (car ret) 0)
233 (if (equal (car ret) 0)
230 (if msg
234 (if msg
231 (message "%s patch: %s" msg info)
235 (message "%s patch: %s" msg info)
232 info)
236 info)
233 (error "%s" info))))
237 (error "%s" info))))
234
238
235 (defun mq-top ()
239 (defun mq-top ()
236 "Print the name of the topmost applied patch."
240 "Print the name of the topmost applied patch."
237 (interactive)
241 (interactive)
238 (mq-patch-info "qtop" "Top"))
242 (mq-patch-info "qtop" "Top"))
239
243
240 (defun mq-next ()
244 (defun mq-next ()
241 "Print the name of the next patch to be pushed."
245 "Print the name of the next patch to be pushed."
242 (interactive)
246 (interactive)
243 (mq-patch-info "qnext" "Next"))
247 (mq-patch-info "qnext" "Next"))
244
248
245 (defun mq-previous ()
249 (defun mq-previous ()
246 "Print the name of the first patch below the topmost applied patch.
250 "Print the name of the first patch below the topmost applied patch.
247 This would become the active patch if popped to."
251 This would become the active patch if popped to."
248 (interactive)
252 (interactive)
249 (mq-patch-info "qprev" "Previous"))
253 (mq-patch-info "qprev" "Previous"))
250
254
251 (defun mq-edit-finish ()
255 (defun mq-edit-finish ()
252 "Finish editing the description of this patch, and refresh the patch."
256 "Finish editing the description of this patch, and refresh the patch."
253 (interactive)
257 (interactive)
254 (unless (equal (mq-patch-info "qtop") mq-top)
258 (unless (equal (mq-patch-info "qtop") mq-top)
255 (error "Topmost patch has changed!"))
259 (error "Topmost patch has changed!"))
256 (hg-sync-buffers hg-root)
260 (hg-sync-buffers hg-root)
257 (run-hooks 'mq-edit-finish-hook)
261 (run-hooks 'mq-edit-finish-hook)
258 (mq-refresh-internal hg-root "-m" (buffer-substring (point-min) (point-max)))
262 (mq-refresh-internal hg-root "-m" (buffer-substring (point-min) (point-max)))
259 (let ((buf mq-prev-buffer))
263 (let ((buf mq-prev-buffer))
260 (kill-buffer nil)
264 (kill-buffer nil)
261 (switch-to-buffer buf)))
265 (switch-to-buffer buf)))
262
266
263 (defun mq-edit-kill ()
267 (defun mq-edit-kill ()
264 "Kill the edit currently being prepared."
268 "Kill the edit currently being prepared."
265 (interactive)
269 (interactive)
266 (when (or (not (buffer-modified-p)) (y-or-n-p "Really kill this edit? "))
270 (when (or (not (buffer-modified-p)) (y-or-n-p "Really kill this edit? "))
267 (let ((buf mq-prev-buffer))
271 (let ((buf mq-prev-buffer))
268 (kill-buffer nil)
272 (kill-buffer nil)
269 (switch-to-buffer buf))))
273 (switch-to-buffer buf))))
270
274
271 (defun mq-get-top (root)
275 (defun mq-get-top (root)
272 (let ((entry (assoc root mq-top-patch)))
276 (let ((entry (assoc root mq-top-patch)))
273 (if entry
277 (if entry
274 (cdr entry))))
278 (cdr entry))))
275
279
276 (defun mq-set-top (root patch)
280 (defun mq-set-top (root patch)
277 (let ((entry (assoc root mq-top-patch)))
281 (let ((entry (assoc root mq-top-patch)))
278 (if entry
282 (if entry
279 (if patch
283 (if patch
280 (setcdr entry patch)
284 (setcdr entry patch)
281 (setq mq-top-patch (delq entry mq-top-patch)))
285 (setq mq-top-patch (delq entry mq-top-patch)))
282 (setq mq-top-patch (cons (cons root patch) mq-top-patch)))))
286 (setq mq-top-patch (cons (cons root patch) mq-top-patch)))))
283
287
284 (defun mq-update-mode-lines (root)
288 (defun mq-update-mode-lines (root)
285 (let ((cwd default-directory))
289 (let ((cwd default-directory))
286 (cd root)
290 (cd root)
287 (condition-case nil
291 (condition-case nil
288 (mq-set-top root (mq-patch-info "qtop"))
292 (mq-set-top root (mq-patch-info "qtop"))
289 (error (mq-set-top root nil)))
293 (error (mq-set-top root nil)))
290 (cd cwd))
294 (cd cwd))
291 (let ((patch (mq-get-top root)))
295 (let ((patch (mq-get-top root)))
292 (save-excursion
296 (save-excursion
293 (dolist (buf (hg-buffers-visiting-repo root))
297 (dolist (buf (hg-buffers-visiting-repo root))
294 (set-buffer buf)
298 (set-buffer buf)
295 (if mq-mode
299 (if mq-mode
296 (setq mq-mode (or (and patch (concat " MQ:" patch)) " MQ")))))))
300 (setq mq-mode (or (and patch (concat " MQ:" patch)) " MQ")))))))
297
301
298 (defun mq-mode (&optional arg)
302 (defun mq-mode (&optional arg)
299 "Minor mode for Mercurial repositories with an MQ patch queue"
303 "Minor mode for Mercurial repositories with an MQ patch queue"
300 (interactive "i")
304 (interactive "i")
301 (cond ((hg-root)
305 (cond ((hg-root)
302 (setq mq-mode (if (null arg) (not mq-mode)
306 (setq mq-mode (if (null arg) (not mq-mode)
303 arg))
307 arg))
304 (mq-update-mode-lines (hg-root))))
308 (mq-update-mode-lines (hg-root))))
305 (run-hooks 'mq-mode-hook))
309 (run-hooks 'mq-mode-hook))
306
310
307 (defun mq-edit-mode ()
311 (defun mq-edit-mode ()
308 "Mode for editing the description of a patch.
312 "Mode for editing the description of a patch.
309
313
310 Key bindings
314 Key bindings
311 ------------
315 ------------
312 \\[mq-edit-finish] use this description
316 \\[mq-edit-finish] use this description
313 \\[mq-edit-kill] abandon this description"
317 \\[mq-edit-kill] abandon this description"
314 (interactive)
318 (interactive)
315 (use-local-map mq-edit-mode-map)
319 (use-local-map mq-edit-mode-map)
316 (set-syntax-table text-mode-syntax-table)
320 (set-syntax-table text-mode-syntax-table)
317 (setq local-abbrev-table text-mode-abbrev-table
321 (setq local-abbrev-table text-mode-abbrev-table
318 major-mode 'mq-edit-mode
322 major-mode 'mq-edit-mode
319 mode-name "MQ-Edit")
323 mode-name "MQ-Edit")
320 (set-buffer-modified-p nil)
324 (set-buffer-modified-p nil)
321 (setq buffer-undo-list nil)
325 (setq buffer-undo-list nil)
322 (run-hooks 'text-mode-hook 'mq-edit-mode-hook))
326 (run-hooks 'text-mode-hook 'mq-edit-mode-hook))
323
327
324 (defun mq-refresh-edit ()
328 (defun mq-refresh-edit ()
325 "Refresh the topmost applied patch, editing the patch description."
329 "Refresh the topmost applied patch, editing the patch description."
326 (interactive)
330 (interactive)
327 (while mq-prev-buffer
331 (while mq-prev-buffer
328 (set-buffer mq-prev-buffer))
332 (set-buffer mq-prev-buffer))
329 (let ((root (hg-root))
333 (let ((root (hg-root))
330 (prev-buffer (current-buffer))
334 (prev-buffer (current-buffer))
331 (patch (mq-patch-info "qtop")))
335 (patch (mq-patch-info "qtop")))
332 (hg-sync-buffers root)
336 (hg-sync-buffers root)
333 (let ((buf-name (format "*MQ: Edit description of %s*" patch)))
337 (let ((buf-name (format "*MQ: Edit description of %s*" patch)))
334 (switch-to-buffer (get-buffer-create buf-name))
338 (switch-to-buffer (get-buffer-create buf-name))
335 (when (= (point-min) (point-max))
339 (when (= (point-min) (point-max))
336 (set (make-local-variable 'hg-root) root)
340 (set (make-local-variable 'hg-root) root)
337 (set (make-local-variable 'mq-top) patch)
341 (set (make-local-variable 'mq-top) patch)
338 (setq mq-prev-buffer prev-buffer)
342 (setq mq-prev-buffer prev-buffer)
339 (insert (hg-run0 "qheader"))
343 (insert (hg-run0 "qheader"))
340 (goto-char (point-min)))
344 (goto-char (point-min)))
341 (mq-edit-mode)
345 (mq-edit-mode)
342 (cd root)))
346 (cd root)))
343 (message "Type `C-c C-c' to finish editing and refresh the patch."))
347 (message "Type `C-c C-c' to finish editing and refresh the patch."))
344
348
345 (defun mq-new (name)
349 (defun mq-new (name)
346 "Create a new empty patch named NAME.
350 "Create a new empty patch named NAME.
347 The patch is applied on top of the current topmost patch.
351 The patch is applied on top of the current topmost patch.
348 With a prefix argument, forcibly create the patch even if the working
352 With a prefix argument, forcibly create the patch even if the working
349 directory is modified."
353 directory is modified."
350 (interactive (list (mq-read-patch-name "qseries" " to create" t)))
354 (interactive (list (mq-read-patch-name "qseries" " to create" t)))
351 (message "Creating patch...")
355 (message "Creating patch...")
352 (let ((ret (if current-prefix-arg
356 (let ((ret (if current-prefix-arg
353 (hg-run "qnew" "-f" name)
357 (hg-run "qnew" "-f" name)
354 (hg-run "qnew" name))))
358 (hg-run "qnew" name))))
355 (if (equal (car ret) 0)
359 (if (equal (car ret) 0)
356 (progn
360 (progn
357 (hg-update-mode-lines (buffer-file-name))
361 (hg-update-mode-lines (buffer-file-name))
358 (message "Creating patch... done."))
362 (message "Creating patch... done."))
359 (error "Creating patch... %s" (hg-chomp (cdr ret))))))
363 (error "Creating patch... %s" (hg-chomp (cdr ret))))))
360
364
361 (defun mq-edit-series ()
365 (defun mq-edit-series ()
362 "Edit the MQ series file directly."
366 "Edit the MQ series file directly."
363 (interactive)
367 (interactive)
364 (let ((root (hg-root)))
368 (let ((root (hg-root)))
365 (unless root
369 (unless root
366 (error "Not in an MQ repository!"))
370 (error "Not in an MQ repository!"))
367 (find-file (concat root ".hg/patches/series"))))
371 (find-file (concat root ".hg/patches/series"))))
368
372
369 (defun mq-diff (&optional git)
373 (defun mq-diff (&optional git)
370 "Display a diff of the topmost applied patch.
374 "Display a diff of the topmost applied patch.
371 With a prefix argument, display a git-compatible diff."
375 With a prefix argument, display a git-compatible diff."
372 (interactive "P")
376 (interactive "P")
373 (hg-view-output ((format "MQ: Diff of %s" (mq-patch-info "qtop")))
377 (hg-view-output ((format "MQ: Diff of %s" (mq-patch-info "qtop")))
374 (if git
378 (if git
375 (call-process (hg-binary) nil t nil "qdiff" "--git")
379 (call-process (hg-binary) nil t nil "qdiff" "--git")
376 (call-process (hg-binary) nil t nil "qdiff"))
380 (call-process (hg-binary) nil t nil "qdiff"))
377 (diff-mode)
381 (diff-mode)
378 (font-lock-fontify-buffer)))
382 (font-lock-fontify-buffer)))
379
383
380 (defun mq-signoff ()
384 (defun mq-signoff ()
381 "Sign off on the current patch, in the style used by the Linux kernel.
385 "Sign off on the current patch, in the style used by the Linux kernel.
382 If the variable mq-signoff-address is non-nil, it will be used, otherwise
386 If the variable mq-signoff-address is non-nil, it will be used, otherwise
383 the value of the ui.username item from your hgrc will be used."
387 the value of the ui.username item from your hgrc will be used."
384 (interactive)
388 (interactive)
385 (let ((was-editing (eq major-mode 'mq-edit-mode))
389 (let ((was-editing (eq major-mode 'mq-edit-mode))
386 signed)
390 signed)
387 (unless was-editing
391 (unless was-editing
388 (mq-refresh-edit))
392 (mq-refresh-edit))
389 (save-excursion
393 (save-excursion
390 (let* ((user (or mq-signoff-address
394 (let* ((user (or mq-signoff-address
391 (hg-run0 "debugconfig" "ui.username")))
395 (hg-run0 "debugconfig" "ui.username")))
392 (signoff (concat "Signed-off-by: " user)))
396 (signoff (concat "Signed-off-by: " user)))
393 (if (search-forward signoff nil t)
397 (if (search-forward signoff nil t)
394 (message "You have already signed off on this patch.")
398 (message "You have already signed off on this patch.")
395 (goto-char (point-max))
399 (goto-char (point-max))
396 (let ((case-fold-search t))
400 (let ((case-fold-search t))
397 (if (re-search-backward "^Signed-off-by: " nil t)
401 (if (re-search-backward "^Signed-off-by: " nil t)
398 (forward-line 1)
402 (forward-line 1)
399 (insert "\n")))
403 (insert "\n")))
400 (insert signoff)
404 (insert signoff)
401 (message "%s" signoff)
405 (message "%s" signoff)
402 (setq signed t))))
406 (setq signed t))))
403 (unless was-editing
407 (unless was-editing
404 (if signed
408 (if signed
405 (mq-edit-finish)
409 (mq-edit-finish)
406 (mq-edit-kill)))))
410 (mq-edit-kill)))))
407
411
408
412
409 (provide 'mq)
413 (provide 'mq)
410
414
411
415
412 ;;; Local Variables:
416 ;;; Local Variables:
413 ;;; prompt-to-byte-compile: nil
417 ;;; prompt-to-byte-compile: nil
414 ;;; end:
418 ;;; end:
General Comments 0
You need to be logged in to leave comments. Login now