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