##// END OF EJS Templates
In-progress Emacs snapshot.
Bryan O'Sullivan -
r947:4cabedfa default
parent child Browse files
Show More
@@ -1,15 +1,16
1 \.elc$
1 2 \.orig$
2 3 \.rej$
3 4 ~$
4 5 \.so$
5 6 \.pyc$
6 7 \.swp$
7 8 \.prof$
8 9 ^tests/.*\.err$
9 10 ^build/
10 11 ^dist/
11 12 ^doc/.*\.[0-9](\.(x|ht)ml)?$
12 13 ^MANIFEST$
13 14 ^\.pc/
14 15 ^patches/
15 16 ^mercurial/__version__.py$
@@ -1,447 +1,590
1 1 ;;; mercurial.el --- Emacs support for the Mercurial distributed SCM
2 2
3 3 ;; Copyright (C) 2005 Bryan O'Sullivan
4 4
5 5 ;; Author: Bryan O'Sullivan <bos@serpentine.com>
6 6
7 7 ;; $Id$
8 8
9 ;; mercurial.el ("this file") is free software; you can redistribute
10 ;; it and/or modify it under the terms of version 2 of the GNU General
11 ;; Public License as published by the Free Software Foundation.
9 ;; mercurial.el is free software; you can redistribute it and/or
10 ;; modify it under the terms of version 2 of the GNU General Public
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 14 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
15 15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 16 ;; General Public License for more details.
17 17
18 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 20 ;; (`C-h C-l'). If not, write to the Free Software Foundation, Inc.,
21 21 ;; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 22
23 23 ;;; Commentary:
24 24
25 25 ;; This mode builds upon Emacs's VC mode to provide flexible
26 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 29 ;; type `C-c h h'; this runs hg-help-overview, which prints a helpful
30 30 ;; usage overview.
31 31
32 32 ;; Much of the inspiration for mercurial.el comes from Rajesh
33 33 ;; Vaidheeswarran's excellent p4.el, which does an admirably thorough
34 34 ;; job for the commercial Perforce SCM product. In fact, substantial
35 35 ;; chunks of code are adapted from p4.el.
36 36
37 37 ;; This code has been developed under XEmacs 21.5, and may will not
38 38 ;; work as well under GNU Emacs (albeit tested under 21.2). Patches
39 39 ;; to enhance the portability of this code, fix bugs, and add features
40 40 ;; are most welcome. You can clone a Mercurial repository for this
41 41 ;; package from http://www.serpentine.com/hg/hg-emacs
42 42
43 43 ;; Please send problem reports and suggestions to bos@serpentine.com.
44 44
45 45
46 46 ;;; Code:
47 47
48 48 (require 'advice)
49 49 (require 'cl)
50 50 (require 'diff-mode)
51 51 (require 'easymenu)
52 52 (require 'vc)
53 53
54 54
55 55 ;;; XEmacs has view-less, while GNU Emacs has view. Joy.
56 56
57 57 (condition-case nil
58 58 (require 'view-less)
59 59 (error nil))
60 60 (condition-case nil
61 61 (require 'view)
62 62 (error nil))
63 63
64 64
65 65 ;;; Variables accessible through the custom system.
66 66
67 (defgroup hg nil
67 (defgroup mercurial nil
68 68 "Mercurial distributed SCM."
69 69 :group 'tools)
70 70
71 71 (defcustom hg-binary
72 72 (dolist (path '("~/bin/hg"
73 73 "/usr/bin/hg"
74 74 "/usr/local/bin/hg"))
75 75 (when (file-executable-p path)
76 76 (return path)))
77 77 "The path to Mercurial's hg executable."
78 78 :type '(file :must-match t)
79 :group 'hg)
79 :group 'mercurial)
80 80
81 81 (defcustom hg-mode-hook nil
82 82 "Hook run when a buffer enters hg-mode."
83 83 :type 'sexp
84 :group 'hg)
84 :group 'mercurial)
85 85
86 86 (defcustom hg-global-prefix "\C-ch"
87 87 "The global prefix for Mercurial keymap bindings."
88 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 104 ;;; Other variables.
93 105
94 106 (defconst hg-running-xemacs (string-match "XEmacs" emacs-version)
95 107 "Is mercurial.el running under XEmacs?")
96 108
97 109 (defvar hg-mode nil
98 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 118 (defvar hg-output-buffer-name "*Hg*"
101 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 125 ;;; hg-mode keymap.
107 126
108 127 (defvar hg-prefix-map
109 128 (let ((map (copy-keymap vc-prefix-map)))
110 129 (set-keymap-name map 'hg-prefix-map)
111 130 map)
112 131 "This keymap overrides some default vc-mode bindings.")
113 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 134 (define-key hg-prefix-map "c" 'hg-undo)
116 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 138 ;; (define-key hg-prefix-map "r" 'hg-update)
119 139 (define-key hg-prefix-map "u" 'hg-revert-file)
120 140 (define-key hg-prefix-map "~" 'hg-version-other-window)
121 141
122 142 (defvar hg-mode-map (make-sparse-keymap))
123 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 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 152 (defvar hg-global-map (make-sparse-keymap))
131 153 (fset 'hg-global-map hg-global-map)
132 154 (global-set-key hg-global-prefix 'hg-global-map)
133 155 (define-key hg-global-map "," 'hg-incoming)
134 156 (define-key hg-global-map "." 'hg-outgoing)
135 157 (define-key hg-global-map "<" 'hg-pull)
136 158 (define-key hg-global-map "=" 'hg-diff)
137 159 (define-key hg-global-map ">" 'hg-push)
138 160 (define-key hg-global-map "?" 'hg-help-overview)
139 161 (define-key hg-global-map "A" 'hg-addremove)
140 162 (define-key hg-global-map "U" 'hg-revert)
141 163 (define-key hg-global-map "a" 'hg-add)
142 164 (define-key hg-global-map "c" 'hg-commit)
165 (define-key hg-global-map "f" 'hg-forget)
143 166 (define-key hg-global-map "h" 'hg-help-overview)
144 167 (define-key hg-global-map "i" 'hg-init)
145 168 (define-key hg-global-map "l" 'hg-log)
146 169 (define-key hg-global-map "r" 'hg-root)
147 170 (define-key hg-global-map "s" 'hg-status)
148 171 (define-key hg-global-map "u" 'hg-update)
149 172
150 173
151 174 ;;; View mode keymap.
152 175
153 176 (defvar hg-view-mode-map
154 177 (let ((map (copy-keymap (if (boundp 'view-minor-mode-map)
155 178 view-minor-mode-map
156 179 view-mode-map))))
157 180 (set-keymap-name map 'hg-view-mode-map)
158 181 map))
159 182 (fset 'hg-view-mode-map hg-view-mode-map)
160 183 (define-key hg-view-mode-map
161 184 (if hg-running-xemacs [button2] [mouse-2])
162 185 'hg-buffer-mouse-clicked)
163 186
164 187
165 188 ;;; Convenience functions.
166 189
167 190 (defun hg-binary ()
168 191 (if hg-binary
169 192 hg-binary
170 193 (error "No `hg' executable found!")))
171 194
172 195 (defun hg-replace-in-string (str regexp newtext &optional literal)
173 196 "Replace all matches in STR for REGEXP with NEWTEXT string.
174 197 Return the new string. Optional LITERAL non-nil means do a literal
175 198 replacement.
176 199
177 200 This function bridges yet another pointless impedance gap between
178 201 XEmacs and GNU Emacs."
179 202 (if (fboundp 'replace-in-string)
180 203 (replace-in-string str regexp newtext literal)
181 204 (replace-regexp-in-string regexp newtext str nil literal)))
182 205
183 206 (defun hg-chomp (str)
184 207 "Strip trailing newlines from a string."
185 208 (hg-replace-in-string str "[\r\n]+$" ""))
186 209
187 210 (defun hg-run-command (command &rest args)
188 211 "Run the shell command COMMAND, returning (EXIT-CODE . COMMAND-OUTPUT).
189 212 The list ARGS contains a list of arguments to pass to the command."
190 213 (let* (exit-code
191 214 (output
192 215 (with-output-to-string
193 216 (with-current-buffer
194 217 standard-output
195 218 (setq exit-code
196 219 (apply 'call-process command nil t nil args))))))
197 220 (cons exit-code output)))
198 221
199 222 (defun hg-run (command &rest args)
200 223 "Run the Mercurial command COMMAND, returning (EXIT-CODE . COMMAND-OUTPUT)."
201 224 (apply 'hg-run-command (hg-binary) command args))
202 225
203 226 (defun hg-run0 (command &rest args)
204 227 "Run the Mercurial command COMMAND, returning its output.
205 228 If the command does not exit with a zero status code, raise an error."
206 229 (let ((res (apply 'hg-run-command (hg-binary) command args)))
207 230 (if (not (eq (car res) 0))
208 231 (error "Mercurial command failed %s - exit code %s"
209 232 (cons command args)
210 233 (car res))
211 234 (cdr res))))
212 235
213 236 (defun hg-buffer-commands (pnt)
214 237 "Use the properties of a character to do something sensible."
215 238 (interactive "d")
216 239 (let ((rev (get-char-property pnt 'rev))
217 240 (file (get-char-property pnt 'file))
218 241 (date (get-char-property pnt 'date))
219 242 (user (get-char-property pnt 'user))
220 243 (host (get-char-property pnt 'host))
221 244 (prev-buf (current-buffer)))
222 245 (cond
223 246 (file
224 247 (find-file-other-window file))
225 248 (rev
226 249 (hg-diff hg-view-file-name rev rev prev-buf))
227 250 ((message "I don't know how to do that yet")))))
228 251
229 252 (defun hg-buffer-mouse-clicked (event)
230 253 "Translate the mouse clicks in a HG log buffer to character events.
231 254 These are then handed off to `hg-buffer-commands'.
232 255
233 256 Handle frickin' frackin' gratuitous event-related incompatibilities."
234 257 (interactive "e")
235 258 (if hg-running-xemacs
236 259 (progn
237 260 (select-window (event-window event))
238 261 (hg-buffer-commands (event-point event)))
239 262 (select-window (posn-window (event-end event)))
240 263 (hg-buffer-commands (posn-point (event-start event)))))
241 264
242 265 (unless (fboundp 'view-minor-mode)
243 266 (defun view-minor-mode (prev-buffer exit-func)
244 267 (view-mode)))
245 268
246 269 (defun hg-abbrev-file-name (file)
247 270 (if hg-running-xemacs
248 271 (abbreviate-file-name file t)
249 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 310 ;;; View mode bits.
253 311
254 312 (defun hg-exit-view-mode (buf)
255 313 "Exit from hg-view-mode.
256 314 We delete the current window if entering hg-view-mode split the
257 315 current frame."
258 316 (when (and (eq buf (current-buffer))
259 317 (> (length (window-list)) 1))
260 318 (delete-window))
261 319 (when (buffer-live-p buf)
262 320 (kill-buffer buf)))
263 321
264 322 (defun hg-view-mode (prev-buffer &optional file-name)
265 323 (goto-char (point-min))
266 324 (set-buffer-modified-p nil)
267 325 (toggle-read-only t)
268 326 (view-minor-mode prev-buffer 'hg-exit-view-mode)
269 327 (use-local-map hg-view-mode-map)
270 328 (setq truncate-lines t)
271 329 (when file-name
272 330 (set (make-local-variable 'hg-view-file-name)
273 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 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 354 ARGS is of the form (BUFFER-NAME &optional FILE), where BUFFER-NAME is
278 355 the name of the buffer to create, and FILE is the name of the file
279 356 being viewed."
280 357 (let ((prev-buf (gensym "prev-buf-"))
281 358 (v-b-name (car args))
282 359 (v-m-rest (cdr args)))
283 360 `(let ((view-buf-name ,v-b-name)
284 361 (,prev-buf (current-buffer)))
285 362 (get-buffer-create view-buf-name)
286 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 366 (save-excursion
289 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 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 412 ;;; User interface functions.
296 413
297 414 (defun hg-help-overview ()
298 415 "This is an overview of the Mercurial SCM mode for Emacs.
299 416
300 417 You can find the source code, license (GPL v2), and credits for this
301 418 code by typing `M-x find-library mercurial RET'.
302 419
303 420 The Mercurial mode user interface is based on that of the older VC
304 421 mode, so if you're already familiar with VC, the same keybindings and
305 422 functions will generally work.
306 423
307 424 Below is a list of common SCM tasks, with the key bindings needed to
308 425 perform them, and the command names. This list is not exhaustive.
309 426
310 427 In the list below, `G/L' indicates whether a key binding is global (G)
311 428 or local (L). Global keybindings work on any file inside a Mercurial
312 429 repository. Local keybindings only apply to files under the control
313 430 of Mercurial. Many commands take a prefix argument.
314 431
315 432
316 433 SCM Task G/L Key Binding Command Name
317 434 -------- --- ----------- ------------
318 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
321 Commit changes to current file only L C-x C-q vc-toggle-read-only
437 Tell Mercurial to manage a file G C-c h a hg-add
438 Commit changes to current file only L C-x v n hg-commit
322 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 444 View annotated file L C-x v a hg-annotate
328 445
329 446 Diff repo vs last checkin G C-c h = hg-diff
330 447 View status of files in repo G C-c h s hg-status
331 448 Commit all changes G C-c h c hg-commit
332 449
333 450 Undo all changes since last commit G C-c h U hg-revert
334 451 View repo change history G C-c h l hg-log
335 452
336 453 See changes that can be pulled G C-c h , hg-incoming
337 454 Pull changes G C-c h < hg-pull
338 455 Update working directory after pull G C-c h u hg-update
339 456 See changes that can be pushed G C-c h . hg-outgoing
340 457 Push changes G C-c h > hg-push"
341 458 (interactive)
342 459 (hg-view-output ("Mercurial Help Overview")
343 460 (insert (documentation 'hg-help-overview))))
344 461
345 (defun hg-add ()
346 (interactive)
347 (error "not implemented"))
348
349 (defun hg-add-file ()
350 (interactive)
351 (error "not implemented"))
462 (defun hg-add (path)
463 (interactive (list (hg-read-file-name " to add")))
464 (let ((buf (current-buffer))
465 (update (equal buffer-file-name path)))
466 (hg-view-output (hg-output-buffer-name)
467 (apply 'call-process (hg-binary) nil t nil (list "add" path)))
468 (when update
469 (with-current-buffer buf
470 (hg-mode-line)))))
352 471
353 472 (defun hg-addremove ()
354 473 (interactive)
355 474 (error "not implemented"))
356 475
357 476 (defun hg-annotate ()
358 477 (interactive)
359 478 (error "not implemented"))
360 479
361 480 (defun hg-commit ()
362 481 (interactive)
363 482 (error "not implemented"))
364 483
365 (defun hg-diff ()
366 (interactive)
367 (error "not implemented"))
484 (defun hg-diff (path &optional rev1 rev2)
485 (interactive (list (hg-read-file-name " to diff")
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 ()
370 (interactive)
371 (error "not implemented"))
500 (defun hg-forget (path)
501 (interactive (list (hg-read-file-name " to forget")))
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 510 (defun hg-incoming ()
374 511 (interactive)
375 512 (error "not implemented"))
376 513
377 514 (defun hg-init ()
378 515 (interactive)
379 516 (error "not implemented"))
380 517
381 (defun hg-log-file ()
382 (interactive)
383 (error "not implemented"))
384
385 (defun hg-log ()
386 (interactive)
387 (error "not implemented"))
518 (defun hg-log (path &optional rev1 rev2)
519 (interactive (list (hg-read-file-name " to log")
520 (hg-read-rev " to start with" "-1")
521 (hg-read-rev " to end with" (format "-%d" hg-log-limit))))
522 (message "log %s %s" rev1 rev2)
523 (sit-for 1)
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 533 (defun hg-outgoing ()
390 534 (interactive)
391 535 (error "not implemented"))
392 536
393 537 (defun hg-pull ()
394 538 (interactive)
395 539 (error "not implemented"))
396 540
397 541 (defun hg-push ()
398 542 (interactive)
399 543 (error "not implemented"))
400 544
401 545 (defun hg-revert ()
402 546 (interactive)
403 547 (error "not implemented"))
404 548
405 549 (defun hg-revert-file ()
406 550 (interactive)
407 551 (error "not implemented"))
408 552
409 553 (defun hg-root (&optional path)
410 (interactive)
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)"))))
554 (interactive (list (hg-read-file-name)))
415 555 (let ((root (do ((prev nil dir)
416 (dir (file-name-directory path)
556 (dir (file-name-directory (or path (buffer-file-name)))
417 557 (file-name-directory (directory-file-name dir))))
418 558 ((equal prev dir))
419 559 (when (file-directory-p (concat dir ".hg"))
420 560 (return dir)))))
421 561 (when (interactive-p)
422 562 (if root
423 563 (message "The root of this repository is `%s'." root)
424 564 (message "The path `%s' is not in a Mercurial repository."
425 565 (abbreviate-file-name path t))))
426 566 root))
427 567
428 (defun hg-status ()
429 (interactive)
430 (error "not implemented"))
568 (defun hg-status (path)
569 (interactive (list (hg-read-file-name " for status" (hg-root))))
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 575 (defun hg-undo ()
433 576 (interactive)
434 577 (error "not implemented"))
435 578
436 579 (defun hg-version-other-window ()
437 580 (interactive)
438 581 (error "not implemented"))
439 582
440 583
441 584 (provide 'mercurial)
442 585
443 586
444 587 ;;; Local Variables:
445 588 ;;; mode: emacs-lisp
446 589 ;;; prompt-to-byte-compile: nil
447 590 ;;; end:
General Comments 0
You need to be logged in to leave comments. Login now