;;; ediff-mult.el --- support for multi-file/multi-buffer processing in Ediff
-;; Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 96, 97, 98, 99, 2000, 01, 02 Free Software Foundation, Inc.
-;; Author: Michael Kifer <kifer@cs.sunysb.edu>
+;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
;; This file is part of GNU Emacs.
;; Users are encouraged to add functionality to this file.
;; The present file contains all the infrastructure needed for that.
;;
-;; Generally, to to implement a new multisession capability within Ediff,
+;; Generally, to implement a new multisession capability within Ediff,
;; you need to tell it
;;
;; 1. How to display the session group buffer.
;; or string). The function ediff-redraw-registry-buffer displays the
;; second through last of these in the registry buffer.
;; Also, keep in mind that the function ediff-prepare-meta-buffer
-;; (which see) prepends the session group buffer to the descriptor and
+;; (which see) prepends the session group buffer to the descriptor, and
;; nil in front of each subsequent list (i.e., the above list
;; will become
;; ((meta-buf descriptor) (nil obj1 obj2 obj3) (nil ...) ...)
;;; API for ediff-meta-list
+;; Structure of the meta-list:
+;; (HEADER SESSION1 SESSION2 ...)
+;; HEADER: (GROUP-BUF REGEXP OBJA OBJB OBJC SAVE-DIR)
+;; OBJA - first directory
+;; OBJB - second directory
+;; OBJC - third directory
+;; SESSION1/2/... are described below
;; group buffer/regexp
(defsubst ediff-get-group-buffer (meta-list)
(nth 0 (car meta-list)))
(defsubst ediff-get-group-merge-autostore-dir (meta-list)
(nth 5 (car meta-list)))
+;; ELT is a session meta descriptor (what is being preserved as
+;; 'ediff-meta-info)
+;; The structure is: (SESSION-CTL-BUFFER STATUS OBJA OBJB OBJC)
+;; STATUS is ?I, ?*, ?H
+;; OBJA/B/C is (FILENAME EQSTATUS)
+;; EQSTATUS is ?= or nil (?= means that this file is equal to some other
+;; file in this session)
;; session buffer
(defsubst ediff-get-session-buffer (elt)
(nth 0 elt))
(erase-buffer)
;; delete phony overlays that used to represent sessions before the buff
;; was redrawn
- (if ediff-emacs-p
- (mapcar 'delete-overlay (overlays-in 1 1))
- (map-extents 'delete-extent))
+ (ediff-cond-compile-for-xemacs-or-emacs
+ (map-extents 'delete-extent) ; xemacs
+ (mapcar 'delete-overlay (overlays-in 1 1)) ; emacs
+ )
(insert (format ediff-meta-buffer-message
(ediff-abbrev-jobname ediff-metajob-name)))
(defun ediff-update-session-marker-in-dir-meta-buffer (session-num)
(let (buffer-meta-overlays session-info overl buffer-read-only)
(setq overl
- (if ediff-xemacs-p
- (map-extents
- (lambda (ext maparg)
- (if (and
- (ediff-overlay-get ext 'ediff-meta-info)
- (eq (ediff-overlay-get ext 'ediff-meta-session-number)
- session-num))
- ext)))
+ (ediff-cond-compile-for-xemacs-or-emacs
+ (map-extents ; xemacs
+ (lambda (ext maparg)
+ (if (and
+ (ediff-overlay-get ext 'ediff-meta-info)
+ (eq (ediff-overlay-get ext 'ediff-meta-session-number)
+ session-num))
+ ext)))
;; Emacs doesn't have map-extents, so try harder
;; Splice overlay lists to get all buffer overlays
- (setq buffer-meta-overlays (overlay-lists)
- buffer-meta-overlays (append (car buffer-meta-overlays)
- (cdr buffer-meta-overlays)))
- (car
- (delq nil
- (mapcar
- (lambda (overl)
- (if (and
- (ediff-overlay-get overl 'ediff-meta-info)
- (eq (ediff-overlay-get
- overl 'ediff-meta-session-number)
- session-num))
- overl))
- buffer-meta-overlays)))))
+ (progn
+ (setq buffer-meta-overlays (overlay-lists)
+ buffer-meta-overlays (append (car buffer-meta-overlays)
+ (cdr buffer-meta-overlays)))
+ (car
+ (delq nil
+ (mapcar
+ (lambda (overl)
+ (if (and
+ (ediff-overlay-get overl 'ediff-meta-info)
+ (eq (ediff-overlay-get
+ overl 'ediff-meta-session-number)
+ session-num))
+ overl))
+ buffer-meta-overlays))))
+ ))
(or overl
(error
"Bug in ediff-update-session-marker-in-dir-meta-buffer: no overlay with given number %S"
(erase-buffer)
;; delete phony overlays that used to represent sessions before the buff
;; was redrawn
- (if ediff-emacs-p
- (mapcar 'delete-overlay (overlays-in 1 1))
- (map-extents 'delete-extent))
+ (ediff-cond-compile-for-xemacs-or-emacs
+ (map-extents 'delete-extent) ; xemacs
+ (mapcar 'delete-overlay (overlays-in 1 1)) ; emacs
+ )
(insert "This is a registry of all active Ediff sessions.
;; Sets overlay around a meta record with 'ediff-meta-info property PROP
;; If optional SESSION-NUMBER, make it a property of the overlay,
;; ediff-meta-session-number
+;; PROP is either the ctl or meta buffer (used when we work with the registry)
+;; or a session meta descriptor of the form
+;; (SESSION-CTL-BUFFER STATUS OBJA OBJB OBJC)
(defun ediff-set-meta-overlay (b e prop &optional session-number hidden)
(let (overl)
(setq overl (ediff-make-overlay b e))
;; This function executes in meta buffer. It knows where event happened.
(defun ediff-filegroup-action ()
- "Execute appropriate action for the selected session."
+ "Execute appropriate action for a selected session."
(interactive)
(let* ((pos (ediff-event-point last-command-event))
(meta-buf (ediff-event-buffer last-command-event))
(setq frame (window-frame wind))
(raise-frame frame)
(ediff-reset-mouse frame)))
+ (sit-for 0) ; sometimes needed to synch the display and ensure that the
+ ; point ends up after the just completed session
(run-hooks 'ediff-show-session-group-hook)
))
(let (result olist tmp)
(if (and point (ediff-buffer-live-p buf))
(ediff-with-current-buffer buf
- (if ediff-xemacs-p
- (setq result
- (if (setq tmp (extent-at point buf 'ediff-meta-info))
- (ediff-overlay-get tmp 'ediff-meta-info)))
- (setq olist (overlays-at point))
- (setq olist
- (mapcar (lambda (elt) (overlay-get elt 'ediff-meta-info))
- olist))
- (while (and olist (null (car olist))
- (overlay-get (car olist) 'invisible))
- (setq olist (cdr olist)))
- (setq result (car olist)))))
+ (ediff-cond-compile-for-xemacs-or-emacs
+ (setq result ; xemacs
+ (if (setq tmp (extent-at point buf 'ediff-meta-info))
+ (ediff-overlay-get tmp 'ediff-meta-info)))
+ (progn ; emacs
+ (setq olist (overlays-at point))
+ (setq olist
+ (mapcar (lambda (elt)
+ (unless (overlay-get elt 'invisible)
+ (overlay-get elt 'ediff-meta-info)))
+ olist))
+ (while (and olist (null (car olist)))
+ (setq olist (cdr olist)))
+ (setq result (car olist)))
+ )
+ ))
(if result
result
(if noerror
(defun ediff-get-meta-overlay-at-pos (point)
- (if ediff-xemacs-p
- (extent-at point (current-buffer) 'ediff-meta-info)
- (let* ((overl-list (overlays-at point))
- (overl (car overl-list)))
- (while (and overl (null (overlay-get overl 'ediff-meta-info)))
- (setq overl-list (cdr overl-list)
- overl (car overl-list)))
- overl)))
+ (ediff-cond-compile-for-xemacs-or-emacs
+ (extent-at point (current-buffer) 'ediff-meta-info) ; xemacs
+ ;; emacs
+ (let* ((overl-list (overlays-at point))
+ (overl (car overl-list)))
+ (while (and overl (null (overlay-get overl 'ediff-meta-info)))
+ (setq overl-list (cdr overl-list)
+ overl (car overl-list)))
+ overl)
+ )
+ )
(defsubst ediff-get-session-number-at-pos (point &optional meta-buffer)
(setq meta-buffer (if (ediff-buffer-live-p meta-buffer)
(if (eobp)
(goto-char (point-min))
(let ((overl (ediff-get-meta-overlay-at-pos point)))
- (if ediff-xemacs-p
- (progn
- (if overl
- (setq overl (next-extent overl))
- (setq overl (next-extent (current-buffer))))
- (if overl
- (extent-start-position overl)
- (point-max)))
- (if overl
- ;; note: end of current overlay is the beginning of the next one
- (overlay-end overl)
- (next-overlay-change point))))
+ (ediff-cond-compile-for-xemacs-or-emacs
+ (progn ; xemacs
+ (if overl
+ (setq overl (next-extent overl))
+ (setq overl (next-extent (current-buffer))))
+ (if overl
+ (extent-start-position overl)
+ (point-max)))
+ ;; emacs
+ (if overl
+ ;; note: end of current overlay is the beginning of the next one
+ (overlay-end overl)
+ (next-overlay-change point))
+ )
+ )
))
(if (bobp)
(goto-char (point-max))
(let ((overl (ediff-get-meta-overlay-at-pos point)))
- (if ediff-xemacs-p
- (progn
- (if overl
- (setq overl (previous-extent overl))
- (setq overl (previous-extent (current-buffer))))
- (if overl
- (extent-start-position overl)
- (point-min)))
- (if overl (setq point (overlay-start overl)))
- ;; to get to the beginning of prev overlay
- (if (not (bobp))
- ;; trick to overcome an emacs bug--doesn't always find previous
- ;; overlay change correctly
- (setq point (1- point)))
- (setq point (previous-overlay-change point))
- ;; If we are not over an overlay after subtracting 1, it means we are
- ;; in the description area preceding session records. In this case,
- ;; goto the top of the registry buffer.
- (or (car (overlays-at point))
- (setq point (point-min)))
- point))))
+ (ediff-cond-compile-for-xemacs-or-emacs
+ (progn
+ (if overl
+ (setq overl (previous-extent overl))
+ (setq overl (previous-extent (current-buffer))))
+ (if overl
+ (extent-start-position overl)
+ (point-min)))
+ (progn
+ (if overl (setq point (overlay-start overl)))
+ ;; to get to the beginning of prev overlay
+ (if (not (bobp))
+ ;; trick to overcome an emacs bug--doesn't always find previous
+ ;; overlay change correctly
+ (setq point (1- point)))
+ (setq point (previous-overlay-change point))
+ ;; If we are not over an overlay after subtracting 1, it means we are
+ ;; in the description area preceding session records. In this case,
+ ;; goto the top of the registry buffer.
+ (or (car (overlays-at point))
+ (setq point (point-min)))
+ point)
+ )
+ )))
;; this is the action invoked when the user selects a patch from the meta
;; buffer.
(ediff-update-meta-buffer (current-buffer) 'must-redraw))
-(defun ediff-meta-mark-equal-files ()
- "Run though the session list and mark identical files.
-This is used only for sessions that involve 2 or 3 files at the same time."
+;; ACTION is ?h, ?m, ?=: to mark for hiding, mark for operation, or simply
+;; indicate which are equal files
+(defun ediff-meta-mark-equal-files (&optional action)
+ "Run through the session list and mark identical files.
+This is used only for sessions that involve 2 or 3 files at the same time.
+ACTION is an optional argument that can be ?h, ?m, ?=, to mark for hiding, mark
+for operation, or simply indicate which are equal files. If it is nil, then
+last-command-char is used to decide which action to take."
(interactive)
+ (if (null action)
+ (setq action last-command-char))
(let ((list (cdr ediff-meta-list))
marked1 marked2 marked3
fileinfo1 fileinfo2 fileinfo3 elt)
(or (ediff-mark-if-equal fileinfo2 fileinfo3)
(setq marked3 nil))))
(if (and marked1 marked2 marked3)
- (cond ((eq last-command-char ?h)
+ (cond ((eq action ?h)
(ediff-mark-session-for-hiding elt 'mark))
- ((eq last-command-char ?m)
+ ((eq action ?m)
(ediff-mark-session-for-operation elt 'mark))
))
(setq list (cdr list)))