##// END OF EJS Templates
In-progress Emacs snapshot.
Bryan O'Sullivan -
r947:4cabedfa default
parent child Browse files
Show More
@@ -1,3 +1,4
1 \.elc$
1 \.orig$
2 \.orig$
2 \.rej$
3 \.rej$
3 ~$
4 ~$
@@ -6,17 +6,17
6
6
7 ;; $Id$
7 ;; $Id$
8
8
9 ;; mercurial.el ("this file") is free software; you can redistribute
9 ;; mercurial.el is free software; you can redistribute it and/or
10 ;; it and/or modify it under the terms of version 2 of the GNU General
10 ;; modify it under the terms of version 2 of the GNU General Public
11 ;; Public License as published by the Free Software Foundation.
11 ;; License as published by the Free Software Foundation.
12
12
13 ;; This file is distributed in the hope that it will be useful, but
13 ;; mercurial.el is distributed in the hope that it will be useful, but
14 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 ;; General Public License for more details.
16 ;; General Public License for more details.
17
17
18 ;; You should have received a copy of the GNU General Public License
18 ;; You should have received a copy of the GNU General Public License
19 ;; along with this file, GNU Emacs, or XEmacs; see the file COPYING
19 ;; along with mercurial.el, GNU Emacs, or XEmacs; see the file COPYING
20 ;; (`C-h C-l'). If not, write to the Free Software Foundation, Inc.,
20 ;; (`C-h C-l'). If not, write to the Free Software Foundation, Inc.,
21 ;; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 ;; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
22
@@ -25,7 +25,7
25 ;; This mode builds upon Emacs's VC mode to provide flexible
25 ;; This mode builds upon Emacs's VC mode to provide flexible
26 ;; integration with the Mercurial distributed SCM tool.
26 ;; integration with the Mercurial distributed SCM tool.
27
27
28 ;; To get going as quickly as possible, load this file into Emacs and
28 ;; To get going as quickly as possible, load mercurial.el into Emacs and
29 ;; type `C-c h h'; this runs hg-help-overview, which prints a helpful
29 ;; type `C-c h h'; this runs hg-help-overview, which prints a helpful
30 ;; usage overview.
30 ;; usage overview.
31
31
@@ -64,7 +64,7
64
64
65 ;;; Variables accessible through the custom system.
65 ;;; Variables accessible through the custom system.
66
66
67 (defgroup hg nil
67 (defgroup mercurial nil
68 "Mercurial distributed SCM."
68 "Mercurial distributed SCM."
69 :group 'tools)
69 :group 'tools)
70
70
@@ -76,17 +76,29
76 (return path)))
76 (return path)))
77 "The path to Mercurial's hg executable."
77 "The path to Mercurial's hg executable."
78 :type '(file :must-match t)
78 :type '(file :must-match t)
79 :group 'hg)
79 :group 'mercurial)
80
80
81 (defcustom hg-mode-hook nil
81 (defcustom hg-mode-hook nil
82 "Hook run when a buffer enters hg-mode."
82 "Hook run when a buffer enters hg-mode."
83 :type 'sexp
83 :type 'sexp
84 :group 'hg)
84 :group 'mercurial)
85
85
86 (defcustom hg-global-prefix "\C-ch"
86 (defcustom hg-global-prefix "\C-ch"
87 "The global prefix for Mercurial keymap bindings."
87 "The global prefix for Mercurial keymap bindings."
88 :type 'sexp
88 :type 'sexp
89 :group 'hg)
89 :group 'mercurial)
90
91 (defcustom hg-rev-completion-limit 100
92 "The maximum number of revisions that hg-read-rev will offer to complete.
93 This affects memory usage and performance when prompting for revisions
94 in a repository with a lot of history."
95 :type 'integer
96 :group 'mercurial)
97
98 (defcustom hg-log-limit 50
99 "The maximum number of revisions that hg-log will display."
100 :type 'integer
101 :group 'mercurial)
90
102
91
103
92 ;;; Other variables.
104 ;;; Other variables.
@@ -96,11 +108,18
96
108
97 (defvar hg-mode nil
109 (defvar hg-mode nil
98 "Is this file managed by Mercurial?")
110 "Is this file managed by Mercurial?")
111 (make-variable-buffer-local 'hg-mode)
112 (put 'hg-mode 'permanent-local t)
113
114 (defvar hg-status nil)
115 (make-variable-buffer-local 'hg-status)
116 (put 'hg-status 'permanent-local t)
99
117
100 (defvar hg-output-buffer-name "*Hg*"
118 (defvar hg-output-buffer-name "*Hg*"
101 "The name to use for Mercurial output buffers.")
119 "The name to use for Mercurial output buffers.")
102
120
103 (defvar hg-file-name-history nil)
121 (defvar hg-file-history nil)
122 (defvar hg-rev-history nil)
104
123
105
124
106 ;;; hg-mode keymap.
125 ;;; hg-mode keymap.
@@ -111,10 +130,11
111 map)
130 map)
112 "This keymap overrides some default vc-mode bindings.")
131 "This keymap overrides some default vc-mode bindings.")
113 (fset 'hg-prefix-map hg-prefix-map)
132 (fset 'hg-prefix-map hg-prefix-map)
114 (define-key hg-prefix-map "=" 'hg-diff-file)
133 (define-key hg-prefix-map "=" 'hg-diff)
115 (define-key hg-prefix-map "c" 'hg-undo)
134 (define-key hg-prefix-map "c" 'hg-undo)
116 (define-key hg-prefix-map "g" 'hg-annotate)
135 (define-key hg-prefix-map "g" 'hg-annotate)
117 (define-key hg-prefix-map "l" 'hg-log-file)
136 (define-key hg-prefix-map "l" 'hg-log)
137 (define-key hg-prefix-map "n" 'hg-commit-file)
118 ;; (define-key hg-prefix-map "r" 'hg-update)
138 ;; (define-key hg-prefix-map "r" 'hg-update)
119 (define-key hg-prefix-map "u" 'hg-revert-file)
139 (define-key hg-prefix-map "u" 'hg-revert-file)
120 (define-key hg-prefix-map "~" 'hg-version-other-window)
140 (define-key hg-prefix-map "~" 'hg-version-other-window)
@@ -122,10 +142,12
122 (defvar hg-mode-map (make-sparse-keymap))
142 (defvar hg-mode-map (make-sparse-keymap))
123 (define-key hg-mode-map "\C-xv" 'hg-prefix-map)
143 (define-key hg-mode-map "\C-xv" 'hg-prefix-map)
124
144
145 (add-minor-mode 'hg-mode 'hg-mode hg-mode-map)
146
125
147
126 ;;; Global keymap.
148 ;;; Global keymap.
127
149
128 (global-set-key "\C-xvi" 'hg-add-file)
150 (global-set-key "\C-xvi" 'hg-add)
129
151
130 (defvar hg-global-map (make-sparse-keymap))
152 (defvar hg-global-map (make-sparse-keymap))
131 (fset 'hg-global-map hg-global-map)
153 (fset 'hg-global-map hg-global-map)
@@ -140,6 +162,7
140 (define-key hg-global-map "U" 'hg-revert)
162 (define-key hg-global-map "U" 'hg-revert)
141 (define-key hg-global-map "a" 'hg-add)
163 (define-key hg-global-map "a" 'hg-add)
142 (define-key hg-global-map "c" 'hg-commit)
164 (define-key hg-global-map "c" 'hg-commit)
165 (define-key hg-global-map "f" 'hg-forget)
143 (define-key hg-global-map "h" 'hg-help-overview)
166 (define-key hg-global-map "h" 'hg-help-overview)
144 (define-key hg-global-map "i" 'hg-init)
167 (define-key hg-global-map "i" 'hg-init)
145 (define-key hg-global-map "l" 'hg-log)
168 (define-key hg-global-map "l" 'hg-log)
@@ -248,6 +271,41 Handle frickin' frackin' gratuitous even
248 (abbreviate-file-name file t)
271 (abbreviate-file-name file t)
249 (abbreviate-file-name file)))
272 (abbreviate-file-name file)))
250
273
274 (defun hg-read-file-name (&optional prompt default)
275 "Read a file or directory name, or a pattern, to use with a command."
276 (let ((path (or default (buffer-file-name))))
277 (if (or (not path) current-prefix-arg)
278 (expand-file-name
279 (read-file-name (format "File, directory or pattern%s: "
280 (or prompt ""))
281 (and path (file-name-directory path))
282 nil nil
283 (and path (file-name-nondirectory path))
284 'hg-file-history))
285 path)))
286
287 (defun hg-read-rev (&optional prompt default)
288 "Read a revision or tag, offering completions."
289 (let ((rev (or default "tip")))
290 (if (or (not rev) current-prefix-arg)
291 (let ((revs (split-string (hg-chomp
292 (hg-run0 "-q" "log" "-r"
293 (format "-%d"
294 hg-rev-completion-limit)
295 "-r" "tip"))
296 "[\n:]")))
297 (dolist (line (split-string (hg-chomp (hg-run0 "tags")) "\n"))
298 (setq revs (cons (car (split-string line "\\s-")) revs)))
299 (completing-read (format "Revision%s (%s): "
300 (or prompt "")
301 (or default "tip"))
302 (map 'list 'cons revs revs)
303 nil
304 nil
305 nil
306 'hg-rev-history
307 (or default "tip")))
308 rev)))
251
309
252 ;;; View mode bits.
310 ;;; View mode bits.
253
311
@@ -272,8 +330,27 current frame."
272 (set (make-local-variable 'hg-view-file-name)
330 (set (make-local-variable 'hg-view-file-name)
273 (hg-abbrev-file-name file-name))))
331 (hg-abbrev-file-name file-name))))
274
332
333 (defun hg-file-status (file)
334 "Return status of FILE, or nil if FILE does not exist or is unmanaged."
335 (let* ((s (hg-run "status" file))
336 (exit (car s))
337 (output (cdr s)))
338 (if (= exit 0)
339 (let ((state (assoc (substring output 0 (min (length output) 2))
340 '(("M " . modified)
341 ("A " . added)
342 ("R " . removed)))))
343 (if state
344 (cdr state)
345 'normal)))))
346
347 (defun hg-tip ()
348 (split-string (hg-chomp (hg-run0 "-q" "tip")) ":"))
349
275 (defmacro hg-view-output (args &rest body)
350 (defmacro hg-view-output (args &rest body)
276 "Execute BODY in a clean buffer, then switch that buffer to view-mode.
351 "Execute BODY in a clean buffer, then quickly display that buffer.
352 If the buffer contains one line, its contents are displayed in the
353 minibuffer. Otherwise, the buffer is displayed in view-mode.
277 ARGS is of the form (BUFFER-NAME &optional FILE), where BUFFER-NAME is
354 ARGS is of the form (BUFFER-NAME &optional FILE), where BUFFER-NAME is
278 the name of the buffer to create, and FILE is the name of the file
355 the name of the buffer to create, and FILE is the name of the file
279 being viewed."
356 being viewed."
@@ -284,12 +361,52 being viewed."
284 (,prev-buf (current-buffer)))
361 (,prev-buf (current-buffer)))
285 (get-buffer-create view-buf-name)
362 (get-buffer-create view-buf-name)
286 (kill-buffer view-buf-name)
363 (kill-buffer view-buf-name)
287 (pop-to-buffer view-buf-name)
364 (get-buffer-create view-buf-name)
365 (set-buffer view-buf-name)
288 (save-excursion
366 (save-excursion
289 ,@body)
367 ,@body)
290 (hg-view-mode ,prev-buf ,@v-m-rest))))
368 (case (count-lines (point-min) (point-max))
369 ((0)
370 (kill-buffer view-buf-name)
371 (message "(No output)"))
372 ((1)
373 (let ((msg (hg-chomp (buffer-substring (point-min) (point-max)))))
374 (kill-buffer view-buf-name)
375 (message "%s" msg)))
376 (t
377 (pop-to-buffer view-buf-name)
378 (hg-view-mode ,prev-buf ,@v-m-rest))))))
291
379
292 (put 'hg-view-output 'lisp-indent-function 1)
380 (put 'hg-view-output 'lisp-indent-function 1)
381
382 ;;; Hooks.
383
384 (defun hg-mode-line ()
385 (when (hg-root)
386 (let ((status (hg-file-status buffer-file-name)))
387 (setq hg-status status
388 hg-mode (and status (concat " Hg:"
389 (car (hg-tip))
390 (cdr (assq status
391 '((normal . "")
392 (removed . "r")
393 (added . "a")
394 (modified . "m")))))))
395 status)))
396
397 (defun hg-find-file-hook ()
398 (when (hg-mode-line)
399 (run-hooks 'hg-mode-hook)))
400
401 (add-hook 'find-file-hooks 'hg-find-file-hook)
402
403 (defun hg-after-save-hook ()
404 (let ((old-status hg-status))
405 (hg-mode-line)
406 (if (and (not old-status) hg-status)
407 (run-hooks 'hg-mode-hook))))
408
409 (add-hook 'after-save-hook 'hg-after-save-hook)
293
410
294
411
295 ;;; User interface functions.
412 ;;; User interface functions.
@@ -317,13 +434,13 SCM Task G/
317 -------- --- ----------- ------------
434 -------- --- ----------- ------------
318 Help overview (what you are reading) G C-c h h hg-help-overview
435 Help overview (what you are reading) G C-c h h hg-help-overview
319
436
320 Tell Mercurial to manage a file G C-x v i hg-add-file
437 Tell Mercurial to manage a file G C-c h a hg-add
321 Commit changes to current file only L C-x C-q vc-toggle-read-only
438 Commit changes to current file only L C-x v n hg-commit
322 Undo changes to file since commit L C-x v u hg-revert-file
439 Undo changes to file since commit L C-x v u hg-revert-file
323
440
324 Diff file vs last checkin L C-x v = hg-diff-file
441 Diff file vs last checkin L C-x v = hg-diff
325
442
326 View file change history L C-x v l hg-log-file
443 View file change history L C-x v l hg-log
327 View annotated file L C-x v a hg-annotate
444 View annotated file L C-x v a hg-annotate
328
445
329 Diff repo vs last checkin G C-c h = hg-diff
446 Diff repo vs last checkin G C-c h = hg-diff
@@ -342,13 +459,15 Push changes G
342 (hg-view-output ("Mercurial Help Overview")
459 (hg-view-output ("Mercurial Help Overview")
343 (insert (documentation 'hg-help-overview))))
460 (insert (documentation 'hg-help-overview))))
344
461
345 (defun hg-add ()
462 (defun hg-add (path)
346 (interactive)
463 (interactive (list (hg-read-file-name " to add")))
347 (error "not implemented"))
464 (let ((buf (current-buffer))
348
465 (update (equal buffer-file-name path)))
349 (defun hg-add-file ()
466 (hg-view-output (hg-output-buffer-name)
350 (interactive)
467 (apply 'call-process (hg-binary) nil t nil (list "add" path)))
351 (error "not implemented"))
468 (when update
469 (with-current-buffer buf
470 (hg-mode-line)))))
352
471
353 (defun hg-addremove ()
472 (defun hg-addremove ()
354 (interactive)
473 (interactive)
@@ -362,13 +481,31 Push changes G
362 (interactive)
481 (interactive)
363 (error "not implemented"))
482 (error "not implemented"))
364
483
365 (defun hg-diff ()
484 (defun hg-diff (path &optional rev1 rev2)
366 (interactive)
485 (interactive (list (hg-read-file-name " to diff")
367 (error "not implemented"))
486 (hg-read-rev " to start with")
487 (let ((rev2 (hg-read-rev " to end with" 'working-dir)))
488 (and (not (eq rev2 'working-dir)) rev2))))
489 (let ((a-path (hg-abbrev-file-name path)))
490 (hg-view-output ((if (equal rev1 rev2)
491 (format "Mercurial: Rev %s of %s" rev1 a-path)
492 (format "Mercurial: Rev %s to %s of %s"
493 rev1 (or rev2 "Current") a-path)))
494 (if rev2
495 (call-process (hg-binary) nil t nil "diff" "-r" rev1 "-r" rev2 path)
496 (call-process (hg-binary) nil t nil "diff" "-r" rev1 path))
497 (diff-mode)
498 (font-lock-fontify-buffer))))
368
499
369 (defun hg-diff-file ()
500 (defun hg-forget (path)
370 (interactive)
501 (interactive (list (hg-read-file-name " to forget")))
371 (error "not implemented"))
502 (let ((buf (current-buffer))
503 (update (equal buffer-file-name path)))
504 (hg-view-output (hg-output-buffer-name)
505 (apply 'call-process (hg-binary) nil t nil (list "forget" path)))
506 (when update
507 (with-current-buffer buf
508 (hg-mode-line)))))
372
509
373 (defun hg-incoming ()
510 (defun hg-incoming ()
374 (interactive)
511 (interactive)
@@ -378,13 +515,20 Push changes G
378 (interactive)
515 (interactive)
379 (error "not implemented"))
516 (error "not implemented"))
380
517
381 (defun hg-log-file ()
518 (defun hg-log (path &optional rev1 rev2)
382 (interactive)
519 (interactive (list (hg-read-file-name " to log")
383 (error "not implemented"))
520 (hg-read-rev " to start with" "-1")
384
521 (hg-read-rev " to end with" (format "-%d" hg-log-limit))))
385 (defun hg-log ()
522 (message "log %s %s" rev1 rev2)
386 (interactive)
523 (sit-for 1)
387 (error "not implemented"))
524 (let ((a-path (hg-abbrev-file-name path)))
525 (hg-view-output ((if (equal rev1 rev2)
526 (format "Mercurial: Rev %s of %s" rev1 a-path)
527 (format "Mercurial: Rev %s to %s of %s"
528 rev1 (or rev2 "Current") a-path)))
529 (call-process (hg-binary) nil t nil "log" "-r" rev1 "-r" rev2 path)
530 (diff-mode)
531 (font-lock-fontify-buffer))))
388
532
389 (defun hg-outgoing ()
533 (defun hg-outgoing ()
390 (interactive)
534 (interactive)
@@ -407,13 +551,9 Push changes G
407 (error "not implemented"))
551 (error "not implemented"))
408
552
409 (defun hg-root (&optional path)
553 (defun hg-root (&optional path)
410 (interactive)
554 (interactive (list (hg-read-file-name)))
411 (unless path
412 (setq path (if (and (interactive-p) current-prefix-arg)
413 (expand-file-name (read-file-name "Path name: "))
414 (or (buffer-file-name) "(none)"))))
415 (let ((root (do ((prev nil dir)
555 (let ((root (do ((prev nil dir)
416 (dir (file-name-directory path)
556 (dir (file-name-directory (or path (buffer-file-name)))
417 (file-name-directory (directory-file-name dir))))
557 (file-name-directory (directory-file-name dir))))
418 ((equal prev dir))
558 ((equal prev dir))
419 (when (file-directory-p (concat dir ".hg"))
559 (when (file-directory-p (concat dir ".hg"))
@@ -425,9 +565,12 Push changes G
425 (abbreviate-file-name path t))))
565 (abbreviate-file-name path t))))
426 root))
566 root))
427
567
428 (defun hg-status ()
568 (defun hg-status (path)
429 (interactive)
569 (interactive (list (hg-read-file-name " for status" (hg-root))))
430 (error "not implemented"))
570 (let ((root (hg-root)))
571 (hg-view-output (hg-output-buffer-name)
572 (apply 'call-process (hg-binary) nil t nil
573 (list "-C" root "status" path)))))
431
574
432 (defun hg-undo ()
575 (defun hg-undo ()
433 (interactive)
576 (interactive)
General Comments 0
You need to be logged in to leave comments. Login now