Mercurial > emacs
comparison lisp/vc-dispatcher.el @ 94579:dca2377770e7
Move context-preservation machinery.
author | Eric S. Raymond <esr@snark.thyrsus.com> |
---|---|
date | Sat, 03 May 2008 10:18:08 +0000 |
parents | 7de38dedf0a6 |
children | 8393f040d26d |
comparison
equal
deleted
inserted
replaced
94578:7bfee6b6aa8d | 94579:dca2377770e7 |
---|---|
83 Use this to impose your own rules on the entry in addition to any the | 83 Use this to impose your own rules on the entry in addition to any the |
84 version control backend imposes itself." | 84 version control backend imposes itself." |
85 :type 'hook | 85 :type 'hook |
86 :group 'vc) | 86 :group 'vc) |
87 | 87 |
88 (defcustom vc-delete-logbuf-window t | |
89 "If non-nil, delete the *VC-log* buffer and window after each logical action. | |
90 If nil, bury that buffer instead. | |
91 This is most useful if you have multiple windows on a frame and would like to | |
92 preserve the setting." | |
93 :type 'boolean | |
94 :group 'vc) | |
95 | |
96 (defcustom vc-command-messages nil | |
97 "If non-nil, display run messages from back-end commands." | |
98 :type 'boolean | |
99 :group 'vc) | |
100 | |
88 ;; Variables the user doesn't need to know about. | 101 ;; Variables the user doesn't need to know about. |
102 | |
89 (defvar vc-log-operation nil) | 103 (defvar vc-log-operation nil) |
90 (defvar vc-log-after-operation-hook nil) | 104 (defvar vc-log-after-operation-hook nil) |
91 (defvar vc-log-fileset) | 105 (defvar vc-log-fileset) |
92 (defvar vc-log-extra) | 106 (defvar vc-log-extra) |
93 | 107 |
308 (vc-exec-after | 322 (vc-exec-after |
309 `(run-hook-with-args 'vc-post-command-functions | 323 `(run-hook-with-args 'vc-post-command-functions |
310 ',command ',file-or-list ',flags)) | 324 ',command ',file-or-list ',flags)) |
311 status)))) | 325 status)))) |
312 | 326 |
327 ;; These functions are used to ensure that the view the user sees is up to date | |
328 ;; even if the dispatcher client mode has messed with file contents (as in, | |
329 ;; for example, VCS keyword expansion). | |
330 | |
331 (declare-function view-mode-exit "view" (&optional return-to-alist exit-action all-win)) | |
332 | |
333 (defun vc-position-context (posn) | |
334 "Save a bit of the text around POSN in the current buffer. | |
335 Used to help us find the corresponding position again later | |
336 if markers are destroyed or corrupted." | |
337 ;; A lot of this was shamelessly lifted from Sebastian Kremer's | |
338 ;; rcs.el mode. | |
339 (list posn | |
340 (buffer-size) | |
341 (buffer-substring posn | |
342 (min (point-max) (+ posn 100))))) | |
343 | |
344 (defun vc-find-position-by-context (context) | |
345 "Return the position of CONTEXT in the current buffer. | |
346 If CONTEXT cannot be found, return nil." | |
347 (let ((context-string (nth 2 context))) | |
348 (if (equal "" context-string) | |
349 (point-max) | |
350 (save-excursion | |
351 (let ((diff (- (nth 1 context) (buffer-size)))) | |
352 (when (< diff 0) (setq diff (- diff))) | |
353 (goto-char (nth 0 context)) | |
354 (if (or (search-forward context-string nil t) | |
355 ;; Can't use search-backward since the match may continue | |
356 ;; after point. | |
357 (progn (goto-char (- (point) diff (length context-string))) | |
358 ;; goto-char doesn't signal an error at | |
359 ;; beginning of buffer like backward-char would | |
360 (search-forward context-string nil t))) | |
361 ;; to beginning of OSTRING | |
362 (- (point) (length context-string)))))))) | |
363 | |
364 (defun vc-context-matches-p (posn context) | |
365 "Return t if POSN matches CONTEXT, nil otherwise." | |
366 (let* ((context-string (nth 2 context)) | |
367 (len (length context-string)) | |
368 (end (+ posn len))) | |
369 (if (> end (1+ (buffer-size))) | |
370 nil | |
371 (string= context-string (buffer-substring posn end))))) | |
372 | |
373 (defun vc-buffer-context () | |
374 "Return a list (POINT-CONTEXT MARK-CONTEXT REPARSE). | |
375 Used by `vc-restore-buffer-context' to later restore the context." | |
376 (let ((point-context (vc-position-context (point))) | |
377 ;; Use mark-marker to avoid confusion in transient-mark-mode. | |
378 (mark-context (when (eq (marker-buffer (mark-marker)) (current-buffer)) | |
379 (vc-position-context (mark-marker)))) | |
380 ;; Make the right thing happen in transient-mark-mode. | |
381 (mark-active nil) | |
382 ;; The new compilation code does not use compilation-error-list any | |
383 ;; more, so the code below is now ineffective and might as well | |
384 ;; be disabled. -- Stef | |
385 ;; ;; We may want to reparse the compilation buffer after revert | |
386 ;; (reparse (and (boundp 'compilation-error-list) ;compile loaded | |
387 ;; ;; Construct a list; each elt is nil or a buffer | |
388 ;; ;; if that buffer is a compilation output buffer | |
389 ;; ;; that contains markers into the current buffer. | |
390 ;; (save-current-buffer | |
391 ;; (mapcar (lambda (buffer) | |
392 ;; (set-buffer buffer) | |
393 ;; (let ((errors (or | |
394 ;; compilation-old-error-list | |
395 ;; compilation-error-list)) | |
396 ;; (buffer-error-marked-p nil)) | |
397 ;; (while (and (consp errors) | |
398 ;; (not buffer-error-marked-p)) | |
399 ;; (and (markerp (cdr (car errors))) | |
400 ;; (eq buffer | |
401 ;; (marker-buffer | |
402 ;; (cdr (car errors)))) | |
403 ;; (setq buffer-error-marked-p t)) | |
404 ;; (setq errors (cdr errors))) | |
405 ;; (if buffer-error-marked-p buffer))) | |
406 ;; (buffer-list))))) | |
407 (reparse nil)) | |
408 (list point-context mark-context reparse))) | |
409 | |
410 (defun vc-restore-buffer-context (context) | |
411 "Restore point/mark, and reparse any affected compilation buffers. | |
412 CONTEXT is that which `vc-buffer-context' returns." | |
413 (let ((point-context (nth 0 context)) | |
414 (mark-context (nth 1 context)) | |
415 ;; (reparse (nth 2 context)) | |
416 ) | |
417 ;; The new compilation code does not use compilation-error-list any | |
418 ;; more, so the code below is now ineffective and might as well | |
419 ;; be disabled. -- Stef | |
420 ;; ;; Reparse affected compilation buffers. | |
421 ;; (while reparse | |
422 ;; (if (car reparse) | |
423 ;; (with-current-buffer (car reparse) | |
424 ;; (let ((compilation-last-buffer (current-buffer)) ;select buffer | |
425 ;; ;; Record the position in the compilation buffer of | |
426 ;; ;; the last error next-error went to. | |
427 ;; (error-pos (marker-position | |
428 ;; (car (car-safe compilation-error-list))))) | |
429 ;; ;; Reparse the error messages as far as they were parsed before. | |
430 ;; (compile-reinitialize-errors '(4) compilation-parsing-end) | |
431 ;; ;; Move the pointer up to find the error we were at before | |
432 ;; ;; reparsing. Now next-error should properly go to the next one. | |
433 ;; (while (and compilation-error-list | |
434 ;; (/= error-pos (car (car compilation-error-list)))) | |
435 ;; (setq compilation-error-list (cdr compilation-error-list)))))) | |
436 ;; (setq reparse (cdr reparse))) | |
437 | |
438 ;; if necessary, restore point and mark | |
439 (if (not (vc-context-matches-p (point) point-context)) | |
440 (let ((new-point (vc-find-position-by-context point-context))) | |
441 (when new-point (goto-char new-point)))) | |
442 (and mark-active | |
443 mark-context | |
444 (not (vc-context-matches-p (mark) mark-context)) | |
445 (let ((new-mark (vc-find-position-by-context mark-context))) | |
446 (when new-mark (set-mark new-mark)))))) | |
447 | |
448 (defun vc-revert-buffer-internal (&optional arg no-confirm) | |
449 "Revert buffer, keeping point and mark where user expects them. | |
450 Try to be clever in the face of changes due to expanded version-control | |
451 key words. This is important for typeahead to work as expected. | |
452 ARG and NO-CONFIRM are passed on to `revert-buffer'." | |
453 (interactive "P") | |
454 (widen) | |
455 (let ((context (vc-buffer-context))) | |
456 ;; Use save-excursion here, because it may be able to restore point | |
457 ;; and mark properly even in cases where vc-restore-buffer-context | |
458 ;; would fail. However, save-excursion might also get it wrong -- | |
459 ;; in this case, vc-restore-buffer-context gives it a second try. | |
460 (save-excursion | |
461 ;; t means don't call normal-mode; | |
462 ;; that's to preserve various minor modes. | |
463 (revert-buffer arg no-confirm t)) | |
464 (vc-restore-buffer-context context))) | |
465 | |
466 (defun vc-resynch-window (file &optional keep noquery) | |
467 "If FILE is in the current buffer, either revert or unvisit it. | |
468 The choice between revert (to see expanded keywords) and unvisit | |
469 depends on KEEP. NOQUERY if non-nil inhibits confirmation for | |
470 reverting. NOQUERY should be t *only* if it is known the only | |
471 difference between the buffer and the file is due to | |
472 modifications by the dispatcher client code, rather than user | |
473 editing!" | |
474 (and (string= buffer-file-name file) | |
475 (if keep | |
476 (progn | |
477 (vc-revert-buffer-internal t noquery) | |
478 ;; TODO: Adjusting view mode might no longer be necessary | |
479 ;; after RMS change to files.el of 1999-08-08. Investigate | |
480 ;; this when we install the new VC. | |
481 (and view-read-only | |
482 (if (file-writable-p file) | |
483 (and view-mode | |
484 (let ((view-old-buffer-read-only nil)) | |
485 (view-mode-exit))) | |
486 (and (not view-mode) | |
487 (not (eq (get major-mode 'mode-class) 'special)) | |
488 (view-mode-enter)))) | |
489 ;; FIXME: Call into vc.el | |
490 (vc-mode-line buffer-file-name)) | |
491 (kill-buffer (current-buffer))))) | |
492 | |
493 (defun vc-resynch-buffer (file &optional keep noquery) | |
494 "If FILE is currently visited, resynch its buffer." | |
495 (if (string= buffer-file-name file) | |
496 (vc-resynch-window file keep noquery) | |
497 (let ((buffer (get-file-buffer file))) | |
498 (when buffer | |
499 (with-current-buffer buffer | |
500 (vc-resynch-window file keep noquery))))) | |
501 ;; FIME: Call into vc.el | |
502 (vc-directory-resynch-file file) | |
503 (when (memq 'vc-dir-mark-buffer-changed after-save-hook) | |
504 (let ((buffer (get-file-buffer file))) | |
505 ;; FIME: Call into vc.el | |
506 (vc-dir-mark-buffer-changed file)))) | |
507 | |
313 ;; Command closures | 508 ;; Command closures |
314 | 509 |
315 (defun vc-start-logentry (files extra comment initial-contents msg action &optional after-hook) | 510 (defun vc-start-logentry (files extra comment initial-contents msg action &optional after-hook) |
316 "Accept a comment for an operation on FILES with extra data EXTRA. | 511 "Accept a comment for an operation on FILES with extra data EXTRA. |
317 If COMMENT is nil, pop up a VC-log buffer, emit MSG, and set the | 512 If COMMENT is nil, pop up a VC-log buffer, emit MSG, and set the |
329 ;; the current buffer. | 524 ;; the current buffer. |
330 (current-buffer) | 525 (current-buffer) |
331 (if (and files (equal (length files) 1)) | 526 (if (and files (equal (length files) 1)) |
332 (get-file-buffer (car files)) | 527 (get-file-buffer (car files)) |
333 (current-buffer))))) | 528 (current-buffer))))) |
334 (when vc-before-checkin-hook | |
335 (if files | |
336 (with-current-buffer parent | |
337 (run-hooks 'vc-before-checkin-hook)) | |
338 (run-hooks 'vc-before-checkin-hook))) | |
339 (if (and comment (not initial-contents)) | 529 (if (and comment (not initial-contents)) |
340 (set-buffer (get-buffer-create "*VC-log*")) | 530 (set-buffer (get-buffer-create "*VC-log*")) |
341 (pop-to-buffer (get-buffer-create "*VC-log*"))) | 531 (pop-to-buffer (get-buffer-create "*VC-log*"))) |
342 (set (make-local-variable 'vc-parent-buffer) parent) | 532 (set (make-local-variable 'vc-parent-buffer) parent) |
343 (set (make-local-variable 'vc-parent-buffer-name) | 533 (set (make-local-variable 'vc-parent-buffer-name) |
344 (concat " from " (buffer-name vc-parent-buffer))) | 534 (concat " from " (buffer-name vc-parent-buffer))) |
345 ;;(if file (vc-mode-line file)) | |
346 (vc-log-edit files) | 535 (vc-log-edit files) |
347 (make-local-variable 'vc-log-after-operation-hook) | 536 (make-local-variable 'vc-log-after-operation-hook) |
348 (when after-hook | 537 (when after-hook |
349 (setq vc-log-after-operation-hook after-hook)) | 538 (setq vc-log-after-operation-hook after-hook)) |
350 (setq vc-log-operation action) | 539 (setq vc-log-operation action) |
399 ;; Now make sure we see the expanded headers | 588 ;; Now make sure we see the expanded headers |
400 (when log-fileset | 589 (when log-fileset |
401 (mapc | 590 (mapc |
402 (lambda (file) (vc-resynch-buffer file vc-keep-workfiles t)) | 591 (lambda (file) (vc-resynch-buffer file vc-keep-workfiles t)) |
403 log-fileset)) | 592 log-fileset)) |
593 ;; FIXME: Call into vc.el | |
404 (when vc-dired-mode | 594 (when vc-dired-mode |
405 (dired-move-to-filename)) | 595 (dired-move-to-filename)) |
406 (when (eq major-mode 'vc-dir-mode) | 596 (when (eq major-mode 'vc-dir-mode) |
407 (vc-dir-move-to-goal-column)) | 597 (vc-dir-move-to-goal-column)) |
408 (run-hooks after-hook 'vc-finish-logentry-hook))) | 598 (run-hooks after-hook 'vc-finish-logentry-hook))) |
409 | 599 |
410 | |
411 ;;; vc-dispatcher.el ends here | 600 ;;; vc-dispatcher.el ends here |