diff options
author | Michael Kifer <kifer@cs.stonybrook.edu> | 1996-09-20 01:10:05 +0000 |
---|---|---|
committer | Michael Kifer <kifer@cs.stonybrook.edu> | 1996-09-20 01:10:05 +0000 |
commit | 92c51e075e8bc9c2ace8487bfc42f23389d09b73 (patch) | |
tree | c1d584dd76b465b332fb990530a5987752ea5054 /lisp/ediff-util.el | |
parent | f49e14457537c130733cb10a20ff8d16d1a0bcc1 (diff) | |
download | emacs-92c51e075e8bc9c2ace8487bfc42f23389d09b73.tar.gz |
*** empty log message ***
Diffstat (limited to 'lisp/ediff-util.el')
-rw-r--r-- | lisp/ediff-util.el | 412 |
1 files changed, 222 insertions, 190 deletions
diff --git a/lisp/ediff-util.el b/lisp/ediff-util.el index 76eaaddae1f..f248135b5bf 100644 --- a/lisp/ediff-util.el +++ b/lisp/ediff-util.el @@ -24,11 +24,17 @@ ;;; Code: (require 'ediff-init) +(require 'ediff-help) (require 'ediff-mult) ;; Pacify compiler and avoid the need in checking for boundp (defvar ediff-patch-diagnostics nil) (defvar ediff-patchbufer nil) +(and noninteractive + (eval-when-compile + (let ((load-path (cons (expand-file-name ".") load-path))) + (load-file "ediff-init.el") + (load-file "ediff-help.el")))) ;; end pacifier @@ -100,6 +106,10 @@ to invocation.") (setq ediff-mode-map (make-sparse-keymap)) (suppress-keymap ediff-mode-map) + (define-key ediff-mode-map + (if ediff-emacs-p [mouse-2] [button2]) 'ediff-help-for-quick-help) + (define-key ediff-mode-map "\C-m" 'ediff-help-for-quick-help) + (define-key ediff-mode-map "p" 'ediff-previous-difference) (define-key ediff-mode-map "\C-?" 'ediff-previous-difference) (define-key ediff-mode-map [backspace] 'ediff-previous-difference) @@ -183,6 +193,7 @@ to invocation.") (define-key ediff-mode-map "wa" 'ediff-save-buffer) (define-key ediff-mode-map "wb" 'ediff-save-buffer) (define-key ediff-mode-map "wd" 'ediff-save-buffer) + (define-key ediff-mode-map "=" 'ediff-inferior-compare-regions) (if (fboundp 'ediff-show-patch-diagnostics) (define-key ediff-mode-map "P" 'ediff-show-patch-diagnostics)) (if ediff-3way-job @@ -210,10 +221,13 @@ to invocation.") ;; It now returns control buffer so other functions can do post-processing (defun ediff-setup (buffer-A file-A buffer-B file-B buffer-C file-C startup-hooks setup-parameters) - (setq file-A (expand-file-name file-A)) - (setq file-B (expand-file-name file-B)) + ;; ediff-convert-standard-filename puts file names in the form appropriate + ;; for the OS at hand. + (setq file-A (ediff-convert-standard-filename (expand-file-name file-A))) + (setq file-B (ediff-convert-standard-filename (expand-file-name file-B))) (if (stringp file-C) - (setq file-C (expand-file-name file-C))) + (setq file-C + (ediff-convert-standard-filename (expand-file-name file-C)))) (let* ((control-buffer-name (ediff-unique-buffer-name "*Ediff Control Panel" "*")) (control-buffer (ediff-eval-in-buffer buffer-A @@ -461,6 +475,8 @@ to invocation.") (shrink-window-if-larger-than-buffer) (or (ediff-multiframe-setup-p) (ediff-indent-help-message)) + (ediff-set-help-overlays) + (set-buffer-modified-p nil) (ediff-refresh-mode-lines) (setq ediff-control-window (selected-window)) @@ -476,72 +492,7 @@ to invocation.") (goto-char (point-min)) (skip-chars-forward ediff-whitespace))) -;; assuming we are in control window, calculate length of the first line in -;; help message -(defun ediff-help-message-line-length () - (save-excursion - (goto-char (point-min)) - (if ediff-use-long-help-message - (next-line 1)) - (end-of-line) - (current-column))) - -(defun ediff-indent-help-message () - (let* ((shift (/ (max 0 (- (window-width (selected-window)) - (ediff-help-message-line-length))) - 2)) - (str (make-string shift ?\ ))) - (save-excursion - (goto-char (point-min)) - (while (< (point) (point-max)) - (insert str) - (beginning-of-line) - (forward-line 1))))) - - -(defun ediff-set-help-message () - (setq ediff-long-help-message - (cond ((and ediff-long-help-message-function - (or (symbolp ediff-long-help-message-function) - (consp ediff-long-help-message-function))) - (funcall ediff-long-help-message-function)) - (ediff-word-mode - (concat ediff-long-help-message-head - ediff-long-help-message-word-mode - ediff-long-help-message-tail)) - (ediff-narrow-job - (concat ediff-long-help-message-head - ediff-long-help-message-narrow2 - ediff-long-help-message-tail)) - (ediff-merge-job - (concat ediff-long-help-message-head - ediff-long-help-message-merge - ediff-long-help-message-tail)) - (ediff-diff3-job - (concat ediff-long-help-message-head - ediff-long-help-message-compare3 - ediff-long-help-message-tail)) - (t - (concat ediff-long-help-message-head - ediff-long-help-message-compare2 - ediff-long-help-message-tail)))) - (setq ediff-brief-help-message - (cond ((and ediff-brief-help-message-function - (or (symbolp ediff-brief-help-message-function) - (consp ediff-brief-help-message-function))) - (funcall ediff-brief-help-message-function)) - ((stringp ediff-brief-help-message-function) - ediff-brief-help-message-function) - ((ediff-multiframe-setup-p) ediff-brief-message-string) - (t ; long brief msg, not multiframe --- put in the middle - ediff-brief-message-string) - )) - (setq ediff-help-message (if ediff-use-long-help-message - ediff-long-help-message - ediff-brief-help-message)) - (run-hooks 'ediff-display-help-hook)) - ;;; Commands for working with Ediff @@ -770,8 +721,9 @@ Reestablish the default three-window display." control-frame (eq this-command 'ediff-quit)))) )) - (ediff-eval-in-buffer control-buf - (ediff-refresh-mode-lines)) + + (ediff-restore-highlighting) + (ediff-eval-in-buffer control-buf (ediff-refresh-mode-lines)) )) ;; this function returns to the window it was called from @@ -881,12 +833,13 @@ On a dumb terminal, switches between ASCII highlighting and no highlighting." ediff-highlight-all-diffs t))) (if (and ediff-use-faces ediff-highlight-all-diffs) - (ediff-color-background-regions) - (ediff-color-background-regions 'unhighlight)) + (ediff-paint-background-regions) + (ediff-paint-background-regions 'unhighlight)) (ediff-unselect-and-select-difference ediff-current-difference 'select-only)) ) + (defun ediff-toggle-autorefine () "Toggle auto-refine mode." @@ -1033,7 +986,10 @@ of the current buffer." (file-writable-p file) (or (file-exists-p (concat file ",v")) - (file-exists-p (concat "RCS/" file ",v"))) + (file-exists-p (concat (file-name-directory file) + "RCS/" + (file-name-nondirectory file) + ",v"))) )) (defun ediff-file-checked-in-p (file) (and (stringp file) @@ -2188,10 +2144,17 @@ temporarily reverses the meaning of this variable." (if (ediff-overlayp overl) (ediff-delete-overlay overl)))) ediff-narrow-bounds) - + ;; restore buffer mode line id's in buffer-A/B/C (let ((control-buffer ediff-control-buffer) - (meta-buffer ediff-meta-buffer)) + (meta-buffer ediff-meta-buffer) + ;; suitable working frame + (warp-frame (if (and (ediff-window-display-p) (eq ediff-grab-mouse t)) + (cond ((window-live-p ediff-window-A) + (window-frame ediff-window-A)) + ((window-live-p ediff-window-B) + (window-frame ediff-window-B)) + (t (next-frame)))))) (condition-case nil (ediff-eval-in-buffer ediff-buffer-A (setq ediff-this-buffer-ediff-sessions @@ -2233,6 +2196,14 @@ temporarily reverses the meaning of this variable." (ediff-update-registry) ;; restore state of buffers to what it was before ediff (ediff-restore-protected-variables) + + ;; If the user interrupts (canceling saving the merge buffer), continue + ;; normally. + (condition-case nil + (if (ediff-merge-job) + (run-hooks 'ediff-quit-merge-hook)) + (quit)) + ;; good place to kill buffers A/B/C (run-hooks 'ediff-cleanup-hook) (let ((ediff-keep-variants ediff-keep-variants)) @@ -2242,6 +2213,20 @@ temporarily reverses the meaning of this variable." (run-hooks 'ediff-quit-hook) (ediff-cleanup-meta-buffer meta-buffer) + + ;; warp mouse into a working window + (setq warp-frame ; if mouse is over a reasonable frame, use it + (cond ((and ediff-xemacs-p (window-live-p (car (mouse-position)))) + (window-frame (car (mouse-position)))) + ((frame-live-p (car (mouse-position))) + (car (mouse-position))) + (t warp-frame))) + (if (frame-live-p warp-frame) + (set-mouse-position (if ediff-emacs-p + warp-frame + (frame-selected-window warp-frame)) + 2 1)) + (if (ediff-buffer-live-p meta-buffer) (ediff-show-meta-buffer meta-buffer)) )) @@ -2290,7 +2275,7 @@ temporarily reverses the meaning of this variable." (or (ediff-get-visible-buffer-window buff-A) (progn (if (ediff-get-visible-buffer-window buff-B) - (split-window-vertically)) + (funcall ediff-split-window-function)) (switch-to-buffer buff-A))) (error)) (if three-way-job @@ -2299,7 +2284,7 @@ temporarily reverses the meaning of this variable." (progn (if (or (ediff-get-visible-buffer-window buff-A) (ediff-get-visible-buffer-window buff-B)) - (split-window-vertically)) + (funcall ediff-split-window-function)) (switch-to-buffer buff-C) (balance-windows))) (error))) @@ -2337,6 +2322,52 @@ buffer in another session as well." (buffer-name ediff-buffer-C))))) (ediff-kill-buffer-carefully ediff-buffer-C)))) +(defun ediff-maybe-save-and-delete-merge () + "Default hook to run on quitting a merge job. +If `ediff-autostore-merges' is nil, this does nothing. +If it is t, it saves the merge buffer in the file `ediff-merge-store-file' +or asks the user, if the latter is nil. It then then asks the user whether to +delete the merge buffer. +If `ediff-autostore-merges' is neither nil nor t, the merge buffer is saved +only if this merge job is part of a group, i.e., was invoked from within +`ediff-merge-directories', `ediff-merge-directory-revisions', and such." + (let ((merge-store-file ediff-merge-store-file)) + (if ediff-autostore-merges + (cond ((stringp ediff-merge-store-file) + ;; store, ask to delete + (ediff-write-merge-buffer-then-kill + ediff-buffer-C merge-store-file 'show-file)) + ((eq ediff-autostore-merges t) + ;; ask for file name + (setq merge-store-file + (read-file-name "Save the result of the merge in: ")) + (ediff-write-merge-buffer-then-kill + ediff-buffer-C merge-store-file)) + ((ediff-eval-in-buffer ediff-meta-buffer + (ediff-merge-metajob)) + ;; This case shouldn't occur, as the parent metajob must pass on + ;; a file name, ediff-merge-store-file, where to save the result + ;; of the merge. + ;; Ask where to save anyway--will decide what to do here later. + (setq merge-store-file + (read-file-name "The result of the merge goes into: ")) + (ediff-write-merge-buffer-then-kill + ediff-buffer-C merge-store-file)))) + )) + +(defun ediff-write-merge-buffer-then-kill (buf file &optional show-file) + (ediff-eval-in-buffer buf + (if (or (not (file-exists-p file)) + (y-or-n-p (format "File %s exists, overwrite? " file))) + (progn + (write-region (point-min) (point-max) file) + (if show-file + (progn + (message "Merge buffer saved in: %s" file) + (sit-for 2))) + (if (y-or-n-p "Merge buffer saved in file. Now kill the buffer? ") + (ediff-kill-buffer-carefully buf)))))) + ;; The default way of suspending Ediff. ;; Buries Ediff buffers, kills all windows. (defun ediff-default-suspend-function () @@ -2583,8 +2614,7 @@ Hit \\[ediff-recenter] to reset the windows afterward." (setq ediff-current-difference n) ) ; end protected section - (ediff-eval-in-buffer control-buf - (ediff-refresh-mode-lines)) + (ediff-eval-in-buffer control-buf (ediff-refresh-mode-lines)) ))) @@ -2618,7 +2648,6 @@ Hit \\[ediff-recenter] to reset the windows afterward." prompt (cond (default-file (concat " (default " default-file "):")) - ;;((string-match "[?:!,;][ \t]*$" prompt) "") (t (concat " (default " default-dir "):")))) default-dir (or default-file default-dir) @@ -2673,7 +2702,7 @@ Hit \\[ediff-recenter] to reset the windows afterward." nil ; don't append---erase 'no-message) (set-file-modes f ediff-temp-file-mode) - f))) + (ediff-convert-standard-filename (expand-file-name f))))) ;; Quote metacharacters (using \) when executing diff in Unix, but not in ;; EMX OS/2 @@ -2796,6 +2825,108 @@ Without an argument, it saves customized diff argument, if available (ediff-reset-mouse ediff-control-frame)) (if (window-live-p ediff-control-window) (select-window ediff-control-window))) + + +(defun ediff-inferior-compare-regions () + "Compare regions in an active Ediff session. +Like ediff-regions-linewise but is called from under an active Ediff session on +the files that belong to that session. + +After quitting the session invoked via this function, type C-l to the parent +Ediff Control Panel to restore highlighting." + (interactive) + (let ((answer "") + (possibilities (list ?A ?B ?C)) + begA begB endA endB bufA bufB) + + (cond ((ediff-merge-job) + (setq bufB ediff-buffer-C) + (while (cond ((memq answer '(?A ?a)) + (setq bufA ediff-buffer-A) + nil) + ((memq answer '(?B ?b)) + (setq bufA ediff-buffer-B) + nil) + ((equal answer "")) + (t (beep 1) + (message "Valid answers are A or B") + (sit-for 2) + t)) + (let ((cursor-in-echo-area t)) + (message "Which buffer to compare to the merge buffer (A/B)? ") + (setq answer (read-char-exclusive))))) + + ((ediff-3way-comparison-job) + (while (cond ((memq answer possibilities) + (setq possibilities (delq answer possibilities)) + (setq bufA + (eval + (intern (format "ediff-buffer-%c" answer)))) + nil) + ((equal answer "")) + (t (beep 1) + (message + "Valid answers are %s" + (mapconcat 'char-to-string possibilities " or ")) + (sit-for 2) + t)) + (let ((cursor-in-echo-area t)) + (message "Enter the 1st buffer you want to compare (%s): " + (mapconcat 'char-to-string possibilities "/")) + (setq answer (capitalize (read-char-exclusive))))) + (setq answer "") ; silence error msg + (while (cond ((memq answer possibilities) + (setq possibilities (delq answer possibilities)) + (setq bufB + (eval + (intern (format "ediff-buffer-%c" answer)))) + nil) + ((equal answer "")) + (t (beep 1) + (message + "Valid answers are %s" + (mapconcat 'char-to-string possibilities " or ")) + (sit-for 2) + t)) + (let ((cursor-in-echo-area t)) + (message "Enter the 2nd buffer you want to compare (%s): " + (mapconcat 'char-to-string possibilities "/")) + (setq answer (capitalize (read-char-exclusive)))))) + (t ; 2way comparison + (setq bufA ediff-buffer-A + bufB ediff-buffer-B))) + + (ediff-eval-in-buffer bufA + (setq begA (region-beginning) + endA (region-end)) + (goto-char begA) + (beginning-of-line) + (setq begA (point)) + (goto-char endA) + (end-of-line) + (or (eobp) (forward-char)) ; include the newline char + (setq endA (point))) + (ediff-eval-in-buffer bufB + (setq begB (region-beginning) + endB (region-end)) + (goto-char begB) + (beginning-of-line) + (setq begB (point)) + (goto-char endB) + (end-of-line) + (or (eobp) (forward-char)) ; include the newline char + (setq endB (point))) + + (ediff-unselect-and-select-difference + ediff-current-difference 'unselect-only) + (ediff-paint-background-regions 'unhighlight) + + (ediff-regions-internal + bufA begA endA bufB begB endB + nil ; startup hook + 'ediff-regions-linewise ; job name + nil) ; no word mode + )) @@ -2893,68 +3024,16 @@ Without an argument, it saves customized diff argument, if available )) +;; Restore highlighting to what it should be according to ediff-use-faces, +;; ediff-highlighting-style, and ediff-highlight-all-diffs variables. +(defun ediff-restore-highlighting (&optional ctl-buf) + (ediff-eval-in-buffer (or ctl-buf (current-buffer)) + (if (and (ediff-has-face-support-p) + ediff-use-faces + ediff-highlight-all-diffs) + (ediff-paint-background-regions)) + (ediff-select-difference ediff-current-difference))) -(defun ediff-highlight-diff-in-one-buffer (n buf-type) - (if (ediff-buffer-live-p (ediff-get-buffer buf-type)) - (let* ((buff (ediff-get-buffer buf-type)) - (last (ediff-eval-in-buffer buff (point-max))) - (begin (ediff-get-diff-posn buf-type 'beg n)) - (end (ediff-get-diff-posn buf-type 'end n)) - (xtra (if (equal begin end) 1 0)) - (end-hilit (min last (+ end xtra))) - (current-diff-overlay - (symbol-value - (intern (format "ediff-current-diff-overlay-%S" buf-type)))) - ) - - (if ediff-xemacs-p - (ediff-move-overlay current-diff-overlay begin end-hilit) - (ediff-move-overlay current-diff-overlay begin end-hilit buff)) - ;; giving priority of 0 and then changing it may look funny, but - ;; this overcomes an obscure Emacs bug. - (ediff-overlay-put current-diff-overlay 'priority 0) - (ediff-overlay-put current-diff-overlay 'priority - (ediff-highest-priority begin end-hilit buff)) - (ediff-overlay-put current-diff-overlay 'ediff-diff-num n) - - ;; unhighlight the background overlay for diff n so it won't - ;; interfere with the current diff overlay - (ediff-set-overlay-face (ediff-get-diff-overlay n buf-type) nil) - ))) - - -(defun ediff-unhighlight-diff-in-one-buffer (buf-type) - (if (ediff-buffer-live-p (ediff-get-buffer buf-type)) - (let ((current-diff-overlay - (symbol-value - (intern (format "ediff-current-diff-overlay-%S" buf-type)))) - (overlay - (ediff-get-diff-overlay ediff-current-difference buf-type)) - ) - - (ediff-move-overlay current-diff-overlay 1 1) - - ;; rehighlight the overlay in the background of the - ;; current difference region - (ediff-set-overlay-face - overlay - (if (and (ediff-has-face-support-p) - ediff-use-faces ediff-highlight-all-diffs) - (ediff-background-face buf-type ediff-current-difference))) - ))) - -(defun ediff-unhighlight-diffs-totally-in-one-buffer (buf-type) - (ediff-unselect-and-select-difference -1) - (if (and (ediff-has-face-support-p) ediff-use-faces) - (let* ((inhibit-quit t) - (current-diff-overlay-var - (intern (format "ediff-current-diff-overlay-%S" buf-type))) - (current-diff-overlay (symbol-value current-diff-overlay-var))) - (ediff-color-background-regions 'unhighlight) - (if (ediff-overlayp current-diff-overlay) - (ediff-delete-overlay current-diff-overlay)) - (set current-diff-overlay-var nil) - ))) ;; null out difference overlays so they won't slow down future @@ -2973,58 +3052,10 @@ Without an argument, it saves customized diff argument, if available ;; allow them to be garbage collected (set vec-var nil)) -(defun ediff-color-background-regions (&optional unhighlight) - (ediff-color-background-regions-in-one-buffer - 'A unhighlight) - (ediff-color-background-regions-in-one-buffer - 'B unhighlight) - (ediff-color-background-regions-in-one-buffer - 'C unhighlight) - (ediff-color-background-regions-in-one-buffer - 'Ancestor unhighlight)) - -(defun ediff-color-background-regions-in-one-buffer (buf-type unhighlight) - (let ((diff-vector - (eval (intern (format "ediff-difference-vector-%S" buf-type)))) - overl diff-num) - (mapcar (function - (lambda (rec) - (setq overl (ediff-get-diff-overlay-from-diff-record rec) - diff-num (ediff-overlay-get overl 'ediff-diff-num)) - (ediff-set-overlay-face - overl - (if (not unhighlight) - (ediff-background-face buf-type diff-num)) - ))) - diff-vector))) ;;; Misc -;; These two functions are here to neutralize XEmacs unwillingless to -;; handle overlays whose buffers were deleted. -(defun ediff-move-overlay (overlay beg end &optional buffer) - "Calls `move-overlay' in Emacs and `set-extent-endpoints' in Lemacs. -Checks if overlay's buffer exists before actually doing the move." - (let ((buf (and overlay (ediff-overlay-buffer overlay)))) - (if (ediff-buffer-live-p buf) - (if ediff-xemacs-p - (set-extent-endpoints overlay beg end) - (move-overlay overlay beg end buffer)) - ;; buffer's dead - (if overlay - (ediff-delete-overlay overlay))))) - -(defun ediff-overlay-put (overlay prop value) - "Calls `overlay-put' or `set-extent-property' depending on Emacs version. -Checks if overlay's buffer exists." - (if (ediff-buffer-live-p (ediff-overlay-buffer overlay)) - (if ediff-xemacs-p - (set-extent-property overlay prop value) - (overlay-put overlay prop value)) - (ediff-delete-overlay overlay))) - - ;; In Emacs, this just makes overlay. In the future, when Emacs will start ;; supporting sticky overlays, this function will make a sticky overlay. ;; BEG and END are expressions telling where overlay starts. @@ -3462,6 +3493,7 @@ Mail anyway? (y or n) ") ;;; Local Variables: ;;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun) ;;; eval: (put 'ediff-eval-in-buffer 'lisp-indent-hook 1) +;;; eval: (put 'ediff-eval-in-buffer 'edebug-form-spec '(form body)) ;;; End: (provide 'ediff-util) |