summaryrefslogtreecommitdiff
path: root/lisp/ediff-util.el
diff options
context:
space:
mode:
authorMichael Kifer <kifer@cs.stonybrook.edu>1996-09-20 01:10:05 +0000
committerMichael Kifer <kifer@cs.stonybrook.edu>1996-09-20 01:10:05 +0000
commita013cdbb1e43acf8ca017fe2baf4bfe84c812492 (patch)
treef13671364d74f93110bff267ee5df4067b44d9bb /lisp/ediff-util.el
parentc1afbab1edcbced1a853ef0b8f5ae9940ca26db5 (diff)
downloademacs-a013cdbb1e43acf8ca017fe2baf4bfe84c812492.tar.gz
*** empty log message ***
Diffstat (limited to 'lisp/ediff-util.el')
-rw-r--r--lisp/ediff-util.el412
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)