Mercurial > hg > mercurial-crew-with-dirclash
comparison contrib/mercurial.el @ 1003:6dfc9cc71f42
Emacs support: numerous changes.
Most SCM commands now work in derived buffers (e.g. diff viewing
buffers) as well as buffers backed by files.
diff and log now work properly on repositories and files.
Commit support is more solid.
Doc strings are better.
author | bos@serpentine.internal.keyresearch.com |
---|---|
date | Mon, 22 Aug 2005 15:08:20 -0700 |
parents | ab3939ccbf10 |
children | ad6fcceaf59b |
comparison
equal
deleted
inserted
replaced
1002:254ab35709e6 | 1003:6dfc9cc71f42 |
---|---|
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 'mercurial) | 84 :group 'mercurial) |
85 | 85 |
86 (defcustom hg-commit-mode-hook nil | |
87 "Hook run when a buffer is created to prepare a commit." | |
88 :type 'sexp | |
89 :group 'mercurial) | |
90 | |
91 (defcustom hg-pre-commit-hook nil | |
92 "Hook run before a commit is performed. | |
93 If you want to prevent the commit from proceeding, raise an error." | |
94 :type 'sexp | |
95 :group 'mercurial) | |
96 | |
86 (defcustom hg-global-prefix "\C-ch" | 97 (defcustom hg-global-prefix "\C-ch" |
87 "The global prefix for Mercurial keymap bindings." | 98 "The global prefix for Mercurial keymap bindings." |
88 :type 'sexp | 99 :type 'sexp |
89 :group 'mercurial) | 100 :group 'mercurial) |
90 | 101 |
129 | 140 |
130 (defvar hg-status nil) | 141 (defvar hg-status nil) |
131 (make-variable-buffer-local 'hg-status) | 142 (make-variable-buffer-local 'hg-status) |
132 (put 'hg-status 'permanent-local t) | 143 (put 'hg-status 'permanent-local t) |
133 | 144 |
145 (defvar hg-prev-buffer nil) | |
146 (make-variable-buffer-local 'hg-prev-buffer) | |
147 (put 'hg-prev-buffer 'permanent-local t) | |
148 | |
149 (defvar hg-root nil) | |
150 (make-variable-buffer-local 'hg-root) | |
151 (put 'hg-root 'permanent-local t) | |
152 | |
134 (defvar hg-output-buffer-name "*Hg*" | 153 (defvar hg-output-buffer-name "*Hg*" |
135 "The name to use for Mercurial output buffers.") | 154 "The name to use for Mercurial output buffers.") |
136 | 155 |
137 (defvar hg-file-history nil) | 156 (defvar hg-file-history nil) |
138 (defvar hg-rev-history nil) | 157 (defvar hg-rev-history nil) |
146 (defconst hg-commit-message-end | 165 (defconst hg-commit-message-end |
147 "--- Files in bold will be committed. Click to toggle selection. ---\n") | 166 "--- Files in bold will be committed. Click to toggle selection. ---\n") |
148 | 167 |
149 | 168 |
150 ;;; hg-mode keymap. | 169 ;;; hg-mode keymap. |
170 | |
171 (defvar hg-mode-map (make-sparse-keymap)) | |
172 (define-key hg-mode-map "\C-xv" 'hg-prefix-map) | |
151 | 173 |
152 (defvar hg-prefix-map | 174 (defvar hg-prefix-map |
153 (let ((map (copy-keymap vc-prefix-map))) | 175 (let ((map (copy-keymap vc-prefix-map))) |
154 (if (functionp 'set-keymap-name) | 176 (if (functionp 'set-keymap-name) |
155 (set-keymap-name map 'hg-prefix-map)); XEmacs | 177 (set-keymap-name map 'hg-prefix-map)); XEmacs |
158 (fset 'hg-prefix-map hg-prefix-map) | 180 (fset 'hg-prefix-map hg-prefix-map) |
159 (define-key hg-prefix-map "=" 'hg-diff) | 181 (define-key hg-prefix-map "=" 'hg-diff) |
160 (define-key hg-prefix-map "c" 'hg-undo) | 182 (define-key hg-prefix-map "c" 'hg-undo) |
161 (define-key hg-prefix-map "g" 'hg-annotate) | 183 (define-key hg-prefix-map "g" 'hg-annotate) |
162 (define-key hg-prefix-map "l" 'hg-log) | 184 (define-key hg-prefix-map "l" 'hg-log) |
163 (define-key hg-prefix-map "n" 'hg-commit-file) | 185 (define-key hg-prefix-map "n" 'hg-commit-start) |
164 ;; (define-key hg-prefix-map "r" 'hg-update) | 186 ;; (define-key hg-prefix-map "r" 'hg-update) |
165 (define-key hg-prefix-map "u" 'hg-revert-buffer) | 187 (define-key hg-prefix-map "u" 'hg-revert-buffer) |
166 (define-key hg-prefix-map "~" 'hg-version-other-window) | 188 (define-key hg-prefix-map "~" 'hg-version-other-window) |
167 | |
168 (defvar hg-mode-map (make-sparse-keymap)) | |
169 (define-key hg-mode-map "\C-xv" 'hg-prefix-map) | |
170 | 189 |
171 (add-minor-mode 'hg-mode 'hg-mode hg-mode-map) | 190 (add-minor-mode 'hg-mode 'hg-mode hg-mode-map) |
172 | 191 |
173 | 192 |
174 ;;; Global keymap. | 193 ;;; Global keymap. |
179 (fset 'hg-global-map hg-global-map) | 198 (fset 'hg-global-map hg-global-map) |
180 (global-set-key hg-global-prefix 'hg-global-map) | 199 (global-set-key hg-global-prefix 'hg-global-map) |
181 (define-key hg-global-map "," 'hg-incoming) | 200 (define-key hg-global-map "," 'hg-incoming) |
182 (define-key hg-global-map "." 'hg-outgoing) | 201 (define-key hg-global-map "." 'hg-outgoing) |
183 (define-key hg-global-map "<" 'hg-pull) | 202 (define-key hg-global-map "<" 'hg-pull) |
184 (define-key hg-global-map "=" 'hg-diff) | 203 (define-key hg-global-map "=" 'hg-diff-repo) |
185 (define-key hg-global-map ">" 'hg-push) | 204 (define-key hg-global-map ">" 'hg-push) |
186 (define-key hg-global-map "?" 'hg-help-overview) | 205 (define-key hg-global-map "?" 'hg-help-overview) |
187 (define-key hg-global-map "A" 'hg-addremove) | 206 (define-key hg-global-map "A" 'hg-addremove) |
188 (define-key hg-global-map "U" 'hg-revert) | 207 (define-key hg-global-map "U" 'hg-revert) |
189 (define-key hg-global-map "a" 'hg-add) | 208 (define-key hg-global-map "a" 'hg-add) |
190 (define-key hg-global-map "c" 'hg-commit) | 209 (define-key hg-global-map "c" 'hg-commit-start) |
191 (define-key hg-global-map "f" 'hg-forget) | 210 (define-key hg-global-map "f" 'hg-forget) |
192 (define-key hg-global-map "h" 'hg-help-overview) | 211 (define-key hg-global-map "h" 'hg-help-overview) |
193 (define-key hg-global-map "i" 'hg-init) | 212 (define-key hg-global-map "i" 'hg-init) |
194 (define-key hg-global-map "l" 'hg-log) | 213 (define-key hg-global-map "l" 'hg-log-repo) |
195 (define-key hg-global-map "r" 'hg-root) | 214 (define-key hg-global-map "r" 'hg-root) |
196 (define-key hg-global-map "s" 'hg-status) | 215 (define-key hg-global-map "s" 'hg-status) |
197 (define-key hg-global-map "u" 'hg-update) | 216 (define-key hg-global-map "u" 'hg-update) |
198 | 217 |
199 | 218 |
214 | 233 |
215 ;;; Commit mode keymaps. | 234 ;;; Commit mode keymaps. |
216 | 235 |
217 (defvar hg-commit-mode-map (make-sparse-keymap)) | 236 (defvar hg-commit-mode-map (make-sparse-keymap)) |
218 (define-key hg-commit-mode-map "\C-c\C-c" 'hg-commit-finish) | 237 (define-key hg-commit-mode-map "\C-c\C-c" 'hg-commit-finish) |
219 (define-key hg-commit-mode-map "\C-c\C-k" 'hg-commit-abort) | 238 (define-key hg-commit-mode-map "\C-c\C-k" 'hg-commit-kill) |
220 | 239 |
221 (defvar hg-commit-mode-file-map (make-sparse-keymap)) | 240 (defvar hg-commit-mode-file-map (make-sparse-keymap)) |
222 (define-key hg-commit-mode-file-map | 241 (define-key hg-commit-mode-file-map |
223 (if hg-running-xemacs [button2] [mouse-2]) | 242 (if hg-running-xemacs [button2] [mouse-2]) |
224 'hg-commit-mouse-clicked) | 243 'hg-commit-mouse-clicked) |
318 (abbreviate-file-name file t) | 337 (abbreviate-file-name file t) |
319 (abbreviate-file-name file))) | 338 (abbreviate-file-name file))) |
320 | 339 |
321 (defun hg-read-file-name (&optional prompt default) | 340 (defun hg-read-file-name (&optional prompt default) |
322 "Read a file or directory name, or a pattern, to use with a command." | 341 "Read a file or directory name, or a pattern, to use with a command." |
323 (let ((path (or default (buffer-file-name)))) | 342 (save-excursion |
324 (if (or (not path) current-prefix-arg) | 343 (while hg-prev-buffer |
325 (expand-file-name | 344 (set-buffer hg-prev-buffer)) |
326 (read-file-name (format "File, directory or pattern%s: " | 345 (let ((path (or default (buffer-file-name)))) |
327 (or prompt "")) | 346 (if (or (not path) current-prefix-arg) |
328 (and path (file-name-directory path)) | 347 (expand-file-name |
329 nil nil | 348 (read-file-name (format "File, directory or pattern%s: " |
330 (and path (file-name-nondirectory path)) | 349 (or prompt "")) |
331 'hg-file-history)) | 350 (and path (file-name-directory path)) |
332 path))) | 351 nil nil |
352 (and path (file-name-nondirectory path)) | |
353 'hg-file-history)) | |
354 path)))) | |
333 | 355 |
334 (defun hg-read-rev (&optional prompt default) | 356 (defun hg-read-rev (&optional prompt default) |
335 "Read a revision or tag, offering completions." | 357 "Read a revision or tag, offering completions." |
336 (let ((rev (or default "tip"))) | 358 (save-excursion |
337 (if (or (not rev) current-prefix-arg) | 359 (while hg-prev-buffer |
338 (let ((revs (split-string (hg-chomp | 360 (set-buffer hg-prev-buffer)) |
339 (hg-run0 "-q" "log" "-r" | 361 (let ((rev (or default "tip"))) |
340 (format "-%d" | 362 (if (or (not rev) current-prefix-arg) |
341 hg-rev-completion-limit) | 363 (let ((revs (split-string (hg-chomp |
342 "-r" "tip")) | 364 (hg-run0 "-q" "log" "-r" |
343 "[\n:]"))) | 365 (format "-%d" |
344 (dolist (line (split-string (hg-chomp (hg-run0 "tags")) "\n")) | 366 hg-rev-completion-limit) |
345 (setq revs (cons (car (split-string line "\\s-")) revs))) | 367 "-r" "tip")) |
346 (completing-read (format "Revision%s (%s): " | 368 "[\n:]"))) |
347 (or prompt "") | 369 (dolist (line (split-string (hg-chomp (hg-run0 "tags")) "\n")) |
348 (or default "tip")) | 370 (setq revs (cons (car (split-string line "\\s-")) revs))) |
349 (map 'list 'cons revs revs) | 371 (completing-read (format "Revision%s (%s): " |
350 nil | 372 (or prompt "") |
351 nil | 373 (or default "tip")) |
352 nil | 374 (map 'list 'cons revs revs) |
353 'hg-rev-history | 375 nil |
354 (or default "tip"))) | 376 nil |
355 rev))) | 377 nil |
378 'hg-rev-history | |
379 (or default "tip"))) | |
380 rev)))) | |
356 | 381 |
357 (defmacro hg-do-across-repo (path &rest body) | 382 (defmacro hg-do-across-repo (path &rest body) |
358 (let ((root-name (gensym "root-")) | 383 (let ((root-name (gensym "root-")) |
359 (buf-name (gensym "buf-"))) | 384 (buf-name (gensym "buf-"))) |
360 `(let ((,root-name (hg-root ,path))) | 385 `(let ((,root-name (hg-root ,path))) |
434 (let ((msg (hg-chomp (buffer-substring (point-min) (point-max))))) | 459 (let ((msg (hg-chomp (buffer-substring (point-min) (point-max))))) |
435 (kill-buffer view-buf-name) | 460 (kill-buffer view-buf-name) |
436 (message "%s" msg))) | 461 (message "%s" msg))) |
437 (t | 462 (t |
438 (pop-to-buffer view-buf-name) | 463 (pop-to-buffer view-buf-name) |
464 (setq hg-prev-buffer ,prev-buf) | |
439 (hg-view-mode ,prev-buf ,@v-m-rest)))))) | 465 (hg-view-mode ,prev-buf ,@v-m-rest)))))) |
440 | 466 |
441 (put 'hg-view-output 'lisp-indent-function 1) | 467 (put 'hg-view-output 'lisp-indent-function 1) |
442 | 468 |
443 ;;; Context save and restore across revert. | 469 ;;; Context save and restore across revert. |
497 (removed . "r") | 523 (removed . "r") |
498 (added . "a") | 524 (added . "a") |
499 (modified . "m"))))))) | 525 (modified . "m"))))))) |
500 status))) | 526 status))) |
501 | 527 |
502 (defun hg-find-file-hook () | 528 (defun hg-mode () |
503 (when (hg-mode-line) | 529 "Minor mode for Mercurial distributed SCM integration. |
504 (run-hooks 'hg-mode-hook))) | 530 |
505 | 531 The Mercurial mode user interface is based on that of VC mode, so if |
506 (add-hook 'find-file-hooks 'hg-find-file-hook) | 532 you're already familiar with VC, the same keybindings and functions |
507 | 533 will generally work. |
508 (defun hg-after-save-hook () | 534 |
509 (let ((old-status hg-status)) | 535 Below is a list of many common SCM tasks. In the list, `G/L' |
510 (hg-mode-line) | 536 indicates whether a key binding is global (G) to a repository or local |
511 (if (and (not old-status) hg-status) | 537 (L) to a file. Many commands take a prefix argument. |
512 (run-hooks 'hg-mode-hook)))) | |
513 | |
514 (add-hook 'after-save-hook 'hg-after-save-hook) | |
515 | |
516 | |
517 ;;; User interface functions. | |
518 | |
519 (defun hg-help-overview () | |
520 "This is an overview of the Mercurial SCM mode for Emacs. | |
521 | |
522 You can find the source code, license (GPL v2), and credits for this | |
523 code by typing `M-x find-library mercurial RET'. | |
524 | |
525 The Mercurial mode user interface is based on that of the older VC | |
526 mode, so if you're already familiar with VC, the same keybindings and | |
527 functions will generally work. | |
528 | |
529 Below is a list of common SCM tasks, with the key bindings needed to | |
530 perform them, and the command names. This list is not exhaustive. | |
531 | |
532 In the list below, `G/L' indicates whether a key binding is global (G) | |
533 or local (L). Global keybindings work on any file inside a Mercurial | |
534 repository. Local keybindings only apply to files under the control | |
535 of Mercurial. Many commands take a prefix argument. | |
536 | |
537 | 538 |
538 SCM Task G/L Key Binding Command Name | 539 SCM Task G/L Key Binding Command Name |
539 -------- --- ----------- ------------ | 540 -------- --- ----------- ------------ |
540 Help overview (what you are reading) G C-c h h hg-help-overview | 541 Help overview (what you are reading) G C-c h h hg-help-overview |
541 | 542 |
546 Diff file vs last checkin L C-x v = hg-diff | 547 Diff file vs last checkin L C-x v = hg-diff |
547 | 548 |
548 View file change history L C-x v l hg-log | 549 View file change history L C-x v l hg-log |
549 View annotated file L C-x v a hg-annotate | 550 View annotated file L C-x v a hg-annotate |
550 | 551 |
551 Diff repo vs last checkin G C-c h = hg-diff | 552 Diff repo vs last checkin G C-c h = hg-diff-repo |
552 View status of files in repo G C-c h s hg-status | 553 View status of files in repo G C-c h s hg-status |
553 Commit all changes G C-c h c hg-commit | 554 Commit all changes G C-c h c hg-commit |
554 | 555 |
555 Undo all changes since last commit G C-c h U hg-revert | 556 Undo all changes since last commit G C-c h U hg-revert |
556 View repo change history G C-c h l hg-log | 557 View repo change history G C-c h l hg-log |
558 See changes that can be pulled G C-c h , hg-incoming | 559 See changes that can be pulled G C-c h , hg-incoming |
559 Pull changes G C-c h < hg-pull | 560 Pull changes G C-c h < hg-pull |
560 Update working directory after pull G C-c h u hg-update | 561 Update working directory after pull G C-c h u hg-update |
561 See changes that can be pushed G C-c h . hg-outgoing | 562 See changes that can be pushed G C-c h . hg-outgoing |
562 Push changes G C-c h > hg-push" | 563 Push changes G C-c h > hg-push" |
564 (run-hooks 'hg-mode-hook)) | |
565 | |
566 (defun hg-find-file-hook () | |
567 (when (hg-mode-line) | |
568 (hg-mode))) | |
569 | |
570 (add-hook 'find-file-hooks 'hg-find-file-hook) | |
571 | |
572 (defun hg-after-save-hook () | |
573 (let ((old-status hg-status)) | |
574 (hg-mode-line) | |
575 (if (and (not old-status) hg-status) | |
576 (hg-mode)))) | |
577 | |
578 (add-hook 'after-save-hook 'hg-after-save-hook) | |
579 | |
580 | |
581 ;;; User interface functions. | |
582 | |
583 (defun hg-help-overview () | |
584 "This is an overview of the Mercurial SCM mode for Emacs. | |
585 | |
586 You can find the source code, license (GPL v2), and credits for this | |
587 code by typing `M-x find-library mercurial RET'." | |
563 (interactive) | 588 (interactive) |
564 (hg-view-output ("Mercurial Help Overview") | 589 (hg-view-output ("Mercurial Help Overview") |
565 (insert (documentation 'hg-help-overview)))) | 590 (insert (documentation 'hg-help-overview)) |
591 (let ((pos (point))) | |
592 (insert (documentation 'hg-mode)) | |
593 (goto-char pos) | |
594 (kill-line)))) | |
566 | 595 |
567 (defun hg-add (path) | 596 (defun hg-add (path) |
568 "Add PATH to the Mercurial repository on the next commit. | 597 "Add PATH to the Mercurial repository on the next commit. |
569 With a prefix argument, prompt for the path to add." | 598 With a prefix argument, prompt for the path to add." |
570 (interactive (list (hg-read-file-name " to add"))) | 599 (interactive (list (hg-read-file-name " to add"))) |
606 (defun hg-commit-mouse-clicked (event) | 635 (defun hg-commit-mouse-clicked (event) |
607 "Toggle whether or not the file at POS will be committed." | 636 "Toggle whether or not the file at POS will be committed." |
608 (interactive "@e") | 637 (interactive "@e") |
609 (hg-commit-toggle-file (event-point event))) | 638 (hg-commit-toggle-file (event-point event))) |
610 | 639 |
611 (defun hg-commit-abort () | 640 (defun hg-commit-kill () |
612 (interactive) | 641 "Kill the commit currently being prepared." |
613 (let ((buf hg-prev-buffer)) | 642 (interactive) |
614 (kill-buffer nil) | 643 (when (or (not (buffer-modified-p)) (y-or-n-p "Really kill this commit? ")) |
615 (switch-to-buffer buf))) | |
616 | |
617 (defun hg-commit-finish () | |
618 (interactive) | |
619 (goto-char (point-min)) | |
620 (search-forward hg-commit-message-start) | |
621 (let ((root hg-root) | |
622 message files) | |
623 (let ((start (point))) | |
624 (goto-char (point-max)) | |
625 (search-backward hg-commit-message-end) | |
626 (setq message (hg-strip (buffer-substring start (point))))) | |
627 (when (and (= (length message) 0) | |
628 (not hg-commit-allow-empty-message)) | |
629 (error "Cannot proceed - commit message is empty")) | |
630 (forward-line 1) | |
631 (beginning-of-line) | |
632 (while (< (point) (point-max)) | |
633 (let ((pos (+ (point) 4))) | |
634 (end-of-line) | |
635 (when (eq (get-text-property pos 'face) 'bold) | |
636 (end-of-line) | |
637 (setq files (cons (buffer-substring pos (point)) files)))) | |
638 (forward-line 1)) | |
639 (when (and (= (length files) 0) | |
640 (not hg-commit-allow-empty-file-list)) | |
641 (error "Cannot proceed - no files to commit")) | |
642 (setq message (concat message "\n")) | |
643 (apply 'hg-run0 "--cwd" hg-root "commit" "-m" message files) | |
644 (let ((buf hg-prev-buffer)) | 644 (let ((buf hg-prev-buffer)) |
645 (kill-buffer nil) | 645 (kill-buffer nil) |
646 (switch-to-buffer buf)) | 646 (switch-to-buffer buf)))) |
647 (hg-do-across-repo root | 647 |
648 (hg-mode-line)))) | 648 (defun hg-commit-finish () |
649 "Finish preparing a commit, and perform the actual commit. | |
650 The hook hg-pre-commit-hook is run before anything else is done. If | |
651 the commit message is empty and hg-commit-allow-empty-message is nil, | |
652 an error is raised. If the list of files to commit is empty and | |
653 hg-commit-allow-empty-file-list is nil, an error is raised." | |
654 (interactive) | |
655 (let ((root hg-root)) | |
656 (save-excursion | |
657 (run-hooks 'hg-pre-commit-hook) | |
658 (goto-char (point-min)) | |
659 (search-forward hg-commit-message-start) | |
660 (let (message files) | |
661 (let ((start (point))) | |
662 (goto-char (point-max)) | |
663 (search-backward hg-commit-message-end) | |
664 (setq message (hg-strip (buffer-substring start (point))))) | |
665 (when (and (= (length message) 0) | |
666 (not hg-commit-allow-empty-message)) | |
667 (error "Cannot proceed - commit message is empty")) | |
668 (forward-line 1) | |
669 (beginning-of-line) | |
670 (while (< (point) (point-max)) | |
671 (let ((pos (+ (point) 4))) | |
672 (end-of-line) | |
673 (when (eq (get-text-property pos 'face) 'bold) | |
674 (end-of-line) | |
675 (setq files (cons (buffer-substring pos (point)) files)))) | |
676 (forward-line 1)) | |
677 (when (and (= (length files) 0) | |
678 (not hg-commit-allow-empty-file-list)) | |
679 (error "Cannot proceed - no files to commit")) | |
680 (setq message (concat message "\n")) | |
681 (apply 'hg-run0 "--cwd" hg-root "commit" "-m" message files)) | |
682 (let ((buf hg-prev-buffer)) | |
683 (kill-buffer nil) | |
684 (switch-to-buffer buf)) | |
685 (hg-do-across-repo root | |
686 (hg-mode-line))))) | |
649 | 687 |
650 (defun hg-commit-mode () | 688 (defun hg-commit-mode () |
651 "Mode for describing a commit of changes to a Mercurial repository. | 689 "Mode for describing a commit of changes to a Mercurial repository. |
652 This involves two actions: describing the changes with a commit | 690 This involves two actions: describing the changes with a commit |
653 message, and choosing the files to commit. | 691 message, and choosing the files to commit. |
660 | 698 |
661 To toggle whether a file will be committed, move the cursor over a | 699 To toggle whether a file will be committed, move the cursor over a |
662 particular file and hit space or return. Alternatively, middle click | 700 particular file and hit space or return. Alternatively, middle click |
663 on the file. | 701 on the file. |
664 | 702 |
665 When you are finished with preparations, type \\[hg-commit-finish] to | 703 Key bindings |
666 proceed with the commit." | 704 ------------ |
705 \\[hg-commit-finish] proceed with commit | |
706 \\[hg-commit-kill] kill commit | |
707 | |
708 \\[hg-diff-repo] view diff of pending changes" | |
667 (interactive) | 709 (interactive) |
668 (use-local-map hg-commit-mode-map) | 710 (use-local-map hg-commit-mode-map) |
669 (set-syntax-table text-mode-syntax-table) | 711 (set-syntax-table text-mode-syntax-table) |
670 (setq local-abbrev-table text-mode-abbrev-table | 712 (setq local-abbrev-table text-mode-abbrev-table |
671 major-mode 'hg-commit-mode | 713 major-mode 'hg-commit-mode |
672 mode-name "Hg-Commit") | 714 mode-name "Hg-Commit") |
673 (set-buffer-modified-p nil) | 715 (set-buffer-modified-p nil) |
674 (setq buffer-undo-list nil) | 716 (setq buffer-undo-list nil) |
675 (run-hooks 'text-mode-hook 'hg-commit-mode-hook)) | 717 (run-hooks 'text-mode-hook 'hg-commit-mode-hook)) |
676 | 718 |
677 (defun hg-commit () | 719 (defun hg-commit-start () |
678 (interactive) | 720 "Prepare a commit of changes to the repository containing the current file." |
721 (interactive) | |
722 (while hg-prev-buffer | |
723 (set-buffer hg-prev-buffer)) | |
679 (let ((root (hg-root)) | 724 (let ((root (hg-root)) |
680 (prev-buffer (current-buffer))) | 725 (prev-buffer (current-buffer)) |
726 modified-files) | |
681 (unless root | 727 (unless root |
682 (error "Cannot commit outside a repository!")) | 728 (error "Cannot commit outside a repository!")) |
683 (hg-do-across-repo | 729 (hg-do-across-repo |
684 (vc-buffer-sync)) | 730 (vc-buffer-sync)) |
731 (setq modified-files (hg-chomp (hg-run0 "--cwd" root "status" "-arm"))) | |
732 (when (and (= (length modified-files) 0) | |
733 (not hg-commit-allow-empty-file-list)) | |
734 (error "No pending changes to commit")) | |
685 (let* ((buf-name (format "*Mercurial: Commit %s*" root))) | 735 (let* ((buf-name (format "*Mercurial: Commit %s*" root))) |
686 (pop-to-buffer (get-buffer-create buf-name)) | 736 (pop-to-buffer (get-buffer-create buf-name)) |
687 (when (= (point-min) (point-max)) | 737 (when (= (point-min) (point-max)) |
688 (set (make-local-variable 'hg-root) root) | 738 (set (make-local-variable 'hg-root) root) |
689 (set (make-local-variable 'hg-prev-buffer) prev-buffer) | 739 (setq hg-prev-buffer prev-buffer) |
690 (insert "\n") | 740 (insert "\n") |
691 (let ((bol (point))) | 741 (let ((bol (point))) |
692 (insert hg-commit-message-end) | 742 (insert hg-commit-message-end) |
693 (add-text-properties bol (point) '(read-only t face bold-italic))) | 743 (add-text-properties bol (point) '(read-only t face bold-italic))) |
694 (let ((file-area (point))) | 744 (let ((file-area (point))) |
695 (insert (hg-chomp (hg-run0 "--cwd" root "status" "-arm"))) | 745 (insert modified-files) |
696 (goto-char file-area) | 746 (goto-char file-area) |
697 (while (< (point) (point-max)) | 747 (while (< (point) (point-max)) |
698 (let ((bol (point))) | 748 (let ((bol (point))) |
699 (forward-char 1) | 749 (forward-char 1) |
700 (insert " ") | 750 (insert " ") |
737 (diff-mode) | 787 (diff-mode) |
738 (setq diff (not (= (point-min) (point-max)))) | 788 (setq diff (not (= (point-min) (point-max)))) |
739 (font-lock-fontify-buffer)) | 789 (font-lock-fontify-buffer)) |
740 diff)) | 790 diff)) |
741 | 791 |
792 (defun hg-diff-repo () | |
793 "Show the differences between the working copy and the tip revision." | |
794 (interactive) | |
795 (hg-diff (hg-root))) | |
796 | |
742 (defun hg-forget (path) | 797 (defun hg-forget (path) |
743 "Lose track of PATH, which has been added, but not yet committed. | 798 "Lose track of PATH, which has been added, but not yet committed. |
744 This will prevent the file from being incorporated into the Mercurial | 799 This will prevent the file from being incorporated into the Mercurial |
745 repository on the next commit. | 800 repository on the next commit. |
746 With a prefix argument, prompt for the path to forget." | 801 With a prefix argument, prompt for the path to forget." |
762 (error "not implemented")) | 817 (error "not implemented")) |
763 | 818 |
764 (defun hg-log (path &optional rev1 rev2) | 819 (defun hg-log (path &optional rev1 rev2) |
765 "Display the revision history of PATH, between REV1 and REV2. | 820 "Display the revision history of PATH, between REV1 and REV2. |
766 REV1 defaults to the initial revision, while REV2 defaults to the tip. | 821 REV1 defaults to the initial revision, while REV2 defaults to the tip. |
767 With a prefix argument, prompt for each parameter." | 822 With a prefix argument, prompt for each parameter. |
823 Variable hg-log-limit controls the number of log entries displayed." | |
768 (interactive (list (hg-read-file-name " to log") | 824 (interactive (list (hg-read-file-name " to log") |
769 (hg-read-rev " to start with" "-1") | 825 (hg-read-rev " to start with" "-1") |
770 (hg-read-rev " to end with" (format "-%d" hg-log-limit)))) | 826 (hg-read-rev " to end with" (format "-%d" hg-log-limit)))) |
771 (let ((a-path (hg-abbrev-file-name path))) | 827 (let ((a-path (hg-abbrev-file-name path))) |
772 (hg-view-output ((if (equal rev1 rev2) | 828 (hg-view-output ((if (equal rev1 rev2) |
773 (format "Mercurial: Rev %s of %s" rev1 a-path) | 829 (format "Mercurial: Rev %s of %s" rev1 a-path) |
774 (format "Mercurial: Rev %s to %s of %s" | 830 (format "Mercurial: Rev %s to %s of %s" |
775 rev1 (or rev2 "Current") a-path))) | 831 rev1 (or rev2 "Current") a-path))) |
776 (call-process (hg-binary) nil t nil "log" "-r" rev1 "-r" rev2 path) | 832 (if (> (length path) (length (hg-root path))) |
833 (call-process (hg-binary) nil t nil "log" "-r" rev1 "-r" rev2 path) | |
834 (call-process (hg-binary) nil t nil "log" "-r" rev1 "-r" rev2)) | |
777 (diff-mode) | 835 (diff-mode) |
778 (font-lock-fontify-buffer)))) | 836 (font-lock-fontify-buffer)))) |
837 | |
838 (defun hg-log-repo (path &optional rev1 rev2) | |
839 "Display the revision history of the repository containing PATH. | |
840 History is displayed between REV1, which defaults to the tip, and | |
841 REV2, which defaults to the initial revision. | |
842 Variable hg-log-limit controls the number of log entries displayed." | |
843 (interactive (list (hg-read-file-name " to log") | |
844 (hg-read-rev " to start with" "tip") | |
845 (hg-read-rev " to end with" (format "-%d" hg-log-limit)))) | |
846 (hg-log (hg-root path) rev1 rev2)) | |
779 | 847 |
780 (defun hg-outgoing () | 848 (defun hg-outgoing () |
781 (interactive) | 849 (interactive) |
782 (error "not implemented")) | 850 (error "not implemented")) |
783 | 851 |
824 "Return the root of the repository that contains the given path. | 892 "Return the root of the repository that contains the given path. |
825 If the path is outside a repository, return nil. | 893 If the path is outside a repository, return nil. |
826 When called interactively, the root is printed. A prefix argument | 894 When called interactively, the root is printed. A prefix argument |
827 prompts for a path to check." | 895 prompts for a path to check." |
828 (interactive (list (hg-read-file-name))) | 896 (interactive (list (hg-read-file-name))) |
829 (let ((root (do ((prev nil dir) | 897 (if (or path (not hg-root)) |
830 (dir (file-name-directory (or path buffer-file-name "")) | 898 (let ((root (do ((prev nil dir) |
831 (file-name-directory (directory-file-name dir)))) | 899 (dir (file-name-directory (or path buffer-file-name "")) |
832 ((equal prev dir)) | 900 (file-name-directory (directory-file-name dir)))) |
833 (when (file-directory-p (concat dir ".hg")) | 901 ((equal prev dir)) |
834 (return dir))))) | 902 (when (file-directory-p (concat dir ".hg")) |
835 (when (interactive-p) | 903 (return dir))))) |
836 (if root | 904 (when (interactive-p) |
837 (message "The root of this repository is `%s'." root) | 905 (if root |
838 (message "The path `%s' is not in a Mercurial repository." | 906 (message "The root of this repository is `%s'." root) |
839 (abbreviate-file-name path t)))) | 907 (message "The path `%s' is not in a Mercurial repository." |
840 root)) | 908 (abbreviate-file-name path t)))) |
909 root) | |
910 hg-root)) | |
841 | 911 |
842 (defun hg-status (path) | 912 (defun hg-status (path) |
843 "Print revision control status of a file or directory. | 913 "Print revision control status of a file or directory. |
844 With prefix argument, prompt for the path to give status for. | 914 With prefix argument, prompt for the path to give status for. |
845 Names are displayed relative to the repository root." | 915 Names are displayed relative to the repository root." |