1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2025-01-11 16:08:13 +00:00

*** empty log message ***

This commit is contained in:
Michael Kifer 1996-06-22 01:54:34 +00:00
parent fce30d79b4
commit bbe6126cba
14 changed files with 6819 additions and 2700 deletions

View File

@ -1,6 +1,6 @@
;;; ediff-diff.el --- diff-related utilities
;; Copyright (C) 1994, 1995 Free Software Foundation, Inc.
;; Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
;; Author: Michael Kifer <kifer@cs.sunysb.edu>
@ -28,7 +28,8 @@
(defvar ediff-shell
(cond ((eq system-type 'emx) "cmd") ; OS/2
((eq system-type 'ms-dos) shell-file-name) ; no standard name on MS-DOS
((memq system-type '(ms-dos windows-nt windows-95))
shell-file-name) ; no standard name on MS-DOS
((memq system-type '(vax-vms axp-vms)) "*dcl*") ; VMS
(t "sh")) ; UNIX
"*The shell used to run diff and patch. If user's .profile or
@ -63,7 +64,7 @@ Must produce output compatible with Unix's diff3 program.")
(defvar ediff-diff3-options ""
"*Options to pass to `ediff-diff3-program'.")
(defvar ediff-diff3-ok-lines-regexp
"^\\([1-3]:\\|====\\| \\|.*Warning *:\\|.*No newline\\|.*missing newline\\)"
"^\\([1-3]:\\|====\\| \\|.*Warning *:\\|.*No newline\\|.*missing newline\\|^\C-m$\\)"
"*Regexp that matches normal output lines from `ediff-diff3-program'.
Lines that do not match are assumed to be error messages.")
@ -71,18 +72,6 @@ Lines that do not match are assumed to be error messages.")
;; the status can be =diff(A), =diff(B), or =diff(A+B)
(ediff-defvar-local ediff-diff-status "" "")
;; Support for patch
(defvar ediff-patch-program "patch"
"*Name of the program that applies patches.")
(defvar ediff-patch-options ""
"*Options to pass to ediff-patch-program.")
;; The buffer of the patch file.
(defvar ediff-patch-buf nil)
;; The buffer where patch would display its diagnostics.
(defvar ediff-patch-diagnostics nil)
;;; Fine differences
@ -99,13 +88,13 @@ Use `setq-default' if setting it in .emacs")
This variable can be set either in .emacs or toggled interactively.
Use `setq-default' if setting it in .emacs")
(ediff-defvar-local ediff-auto-refine-limit 700
"Auto-refine only those regions that are smaller than this number of bytes.")
(ediff-defvar-local ediff-auto-refine-limit 1400
"*Auto-refine only the regions of this size \(in bytes\) or less.")
;;; General
(defvar ediff-diff-ok-lines-regexp
"^\\([0-9,]+[acd][0-9,]+$\\|[<>] \\|---\\|.*Warning *:\\|.*No newline\\|.*missing newline\\)"
"^\\([0-9,]+[acd][0-9,]+$\\|[<>] \\|---\\|.*Warning *:\\|.*No +newline\\|.*missing +newline\\|^\C-m$\\)"
"Regexp that matches normal output lines from `ediff-diff-program'.
This is mostly lifted from Emerge, except that Ediff also considers
warnings and `Missing newline'-type messages to be normal output.
@ -138,19 +127,47 @@ one optional arguments, diff-number to refine.")
;;; ;; When xemacs implements minibufferless frames, this won't be necessary
;;; (if ediff-xemacs-p (setq synchronize-minibuffers t))
;; create, if it doesn't exist
(or (ediff-buffer-live-p ediff-diff-buffer)
(setq ediff-diff-buffer
(get-buffer-create (ediff-unique-buffer-name "*ediff-diff" "*"))))
(message "Computing differences ...")
(ediff-exec-process ediff-diff-program ediff-diff-buffer 'synchronize
ediff-diff-options file-A file-B)
(ediff-make-diff2-buffer ediff-diff-buffer file-A file-B)
(ediff-prepare-error-list ediff-diff-ok-lines-regexp ediff-diff-buffer)
;;(message "Computing differences ... done")
(ediff-convert-diffs-to-overlays
(ediff-extract-diffs
ediff-diff-buffer ediff-word-mode ediff-narrow-bounds)))
;; fill in DIFF-BUFFER with the output from the diff program run on FILE1 and
;; FILE2
;; Return the length of that buffer.
(defun ediff-make-diff2-buffer (diff-buffer file1 file2)
(cond ((< (ediff-file-size file1) 0)
(message "Can't diff remote files: %s"
(ediff-abbreviate-file-name file1))
(sit-for 2)
;; 1 is an error exit code
1)
((< (ediff-file-size file2) 0)
(message "Can't diff remote file: %s"
(ediff-abbreviate-file-name file2))
(sit-for 2)
(message "")
;; 1 is an error exit code
1)
(t (message "Computing differences between %s and %s ..."
(file-name-nondirectory file1)
(file-name-nondirectory file2))
;; this erases the diff buffer automatically
(ediff-exec-process ediff-diff-program
diff-buffer
'synchronize
ediff-diff-options file1 file2)
;;(message "Computing differences ... done")
(message "")
(ediff-eval-in-buffer diff-buffer
(buffer-size)))))
;; If file-A/B/C is nil, do 2-way comparison with the non-nil buffers
;; This function works for diff3 and diff2 jobs
@ -500,7 +517,7 @@ one optional arguments, diff-number to refine.")
(or n (setq n ediff-current-difference))
(if (< ediff-number-of-differences 1)
(error "Sorry, it is not my job to munch identical variants..."))
(error ediff-NO-DIFFERENCES))
(if ediff-word-mode
(setq flag 'skip
@ -524,7 +541,8 @@ one optional arguments, diff-number to refine.")
(cond ((and (eq flag 'noforce) (ediff-get-fine-diff-vector n 'A))
;; don't compute fine diffs if diff vector exists
(if (ediff-no-fine-diffs-p n)
(ediff-message-if-verbose
;;(ediff-message-if-verbose
(message
"Only white-space differences in region %d" (1+ n))))
;; If one of the regions is empty (or 2 in 3way comparison)
;; then don't refine.
@ -548,16 +566,19 @@ one optional arguments, diff-number to refine.")
(empty-B 'B)
(empty-C 'C)))
)
;; if all regions happen to be whitespace, indicate this
;; if all regions happen to be whitespace
(if (and whitespace-A whitespace-B whitespace-C)
;; mark as space only
(ediff-mark-diff-as-space-only n t)
;; if some regions are white and others don't, then mark as
;; non-white-space-only
(ediff-mark-diff-as-space-only n nil)))
;; don't compute fine diffs for this region
((eq flag 'skip)
(or (ediff-get-fine-diff-vector n 'A)
(memq ediff-auto-refine '(off nix))
(ediff-message-if-verbose
"Region %d exceeds auto-refine limit. `%s' force-refines"
"Region %d exceeds auto-refine limit. Type `%s' to refine"
(1+ n)
(substitute-command-keys
"\\[ediff-make-or-kill-fine-diffs]")
@ -605,20 +626,20 @@ one optional arguments, diff-number to refine.")
((and ediff-3way-job whitespace-B)
(ediff-setup-fine-diff-regions file-A nil file-C n))
((and ediff-3way-job
(or whitespace-C
(and ediff-merge-job
(ediff-looks-like-combined-merge n))))
;; In merge-jobs, whitespace-C is t, since
;; ediff-empty-diff-region-p returns t in this case
whitespace-C)
(ediff-setup-fine-diff-regions file-A file-B nil n))
(t
(ediff-setup-fine-diff-regions file-A file-B file-C n)))
(setq cumulative-fine-diff-length
(+ (length (ediff-get-fine-diff-vector n 'A))
(length (ediff-get-fine-diff-vector n 'B))
(if file-C
(length
(ediff-get-fine-diff-vector n 'C))
0)))
(length (ediff-get-fine-diff-vector n 'B))
;; in merge jobs, the merge buffer is never refined
(if (and file-C (not ediff-merge-job))
(length (ediff-get-fine-diff-vector n 'C))
0)))
(cond ((or
;; all regions are white space
@ -632,7 +653,7 @@ one optional arguments, diff-number to refine.")
(ediff-message-if-verbose
"Only white-space differences in region %d" (1+ n)))
((eq cumulative-fine-diff-length 0)
(ediff-mark-diff-as-space-only n nil)
(ediff-mark-diff-as-space-only n t)
(ediff-message-if-verbose
"Only white-space differences in region %d %s"
(1+ n)
@ -847,7 +868,7 @@ one optional arguments, diff-number to refine.")
;; leave point after matched line
(beginning-of-line 2)
(let ((agreement (buffer-substring (match-beginning 1) (match-end 1))))
;; if the A and B files are the same and not 3way-comparison,
;; if the files A and B are the same and not 3way-comparison,
;; ignore the difference
(if (or three-way-comp (not (string-equal agreement "3")))
(let* ((a-begin (car (ediff-get-diff3-group "1")))
@ -1164,6 +1185,11 @@ argument to `skip-chars-forward'."
(point))))
;;; Local Variables:
;;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun)
;;; eval: (put 'ediff-eval-in-buffer 'lisp-indent-hook 1)
;;; End:
(provide 'ediff-diff)

View File

@ -1,6 +1,6 @@
;;; ediff-hook.el --- setup for Ediff's menus and autoloads
;; Copyright (C) 1995 Free Software Foundation, Inc.
;; Copyright (C) 1995, 1996 Free Software Foundation, Inc.
;; Author: Michael Kifer <kifer@cs.sunysb.edu>
@ -25,10 +25,6 @@
;;; These must be placed in menu-bar.el in Emacs
;;
;; (define-key menu-bar-tools-menu [ediff-doc]
;; '("Ediff Manual..." . ediff-documentation))
;; (define-key menu-bar-tools-menu [eregistry]
;; '("List Ediff Sessions..." . ediff-show-registry))
;; (define-key menu-bar-tools-menu [epatch]
;; '("Apply Patch" . menu-bar-epatch-menu))
;; (define-key menu-bar-tools-menu [ediff-merge]
@ -36,6 +32,11 @@
;; (define-key menu-bar-tools-menu [ediff]
;; '("Compare" . menu-bar-ediff-menu))
;; Compiler pacifier
(defvar ediff-menu)
(defvar ediff-merge-menu)
(defvar epatch-menu)
;; end pacifier
(defun ediff-xemacs-init-menus ()
(if (featurep 'menubar)
@ -46,12 +47,6 @@
'("Tools") ediff-merge-menu "OO-Browser...")
(add-submenu
'("Tools") epatch-menu "OO-Browser...")
(add-menu-button
'("Tools")
["List Ediff Sessions..." ediff-show-registry t] "OO-Browser...")
(add-menu-button
'("Tools")
["Ediff Manual..." ediff-documentation t] "OO-Browser...")
(add-menu-button
'("Tools")
["-------" nil nil] "OO-Browser...")
@ -78,6 +73,9 @@
"---"
["Regions Word-by-word..." ediff-regions-wordwise t]
["Regions Line-by-line..." ediff-regions-linewise t]
"---"
["List Ediff Sessions..." ediff-show-registry t]
["Ediff Manual..." ediff-documentation t]
))
(defvar ediff-merge-menu
'("Merge"
@ -97,11 +95,17 @@
["Directory Revisions..." ediff-merge-directory-revisions t]
["Directory Revisions with Ancestor..."
ediff-merge-directory-revisions-with-ancestor t]
"---"
["List Ediff Sessions..." ediff-show-registry t]
["Ediff Manual..." ediff-documentation t]
))
(defvar epatch-menu
'("Apply Patch"
["To a file..." ediff-patch-file t]
["To a buffer..." ediff-patch-buffer t]
"---"
["List Ediff Sessions..." ediff-show-registry t]
["Ediff Manual..." ediff-documentation t]
))
;; put these menus before Object-Oriented-Browser in Tools menu
@ -122,6 +126,11 @@
(fset 'menu-bar-ediff-menu (symbol-value 'menu-bar-ediff-menu))
;; define ediff-menu
(define-key menu-bar-ediff-menu [ediff-doc]
'("Ediff Manual..." . ediff-documentation))
(define-key menu-bar-ediff-menu [eregistry]
'("List Ediff Sessions..." . ediff-show-registry))
(define-key menu-bar-ediff-menu [separator-ediff-manual] '("--"))
(define-key menu-bar-ediff-menu [window]
'("This Window and Next Window" . compare-windows))
(define-key menu-bar-ediff-menu [ediff-windows-linewise]
@ -154,6 +163,12 @@
'("Two Files..." . ediff-files))
;; define merge menu
(define-key menu-bar-ediff-merge-menu [ediff-doc2]
'("Ediff Manual..." . ediff-documentation))
(define-key menu-bar-ediff-merge-menu [eregistry2]
'("List Ediff Sessions..." . ediff-show-registry))
(define-key
menu-bar-ediff-merge-menu [separator-ediff-merge-manual] '("--"))
(define-key
menu-bar-ediff-merge-menu [ediff-merge-dir-revisions-with-ancestor]
'("Directory Revisions with Ancestor..."
@ -187,6 +202,11 @@
'("Files..." . ediff-merge-files))
;; define epatch menu
(define-key menu-bar-epatch-menu [ediff-doc3]
'("Ediff Manual..." . ediff-documentation))
(define-key menu-bar-epatch-menu [eregistry3]
'("List Ediff Sessions..." . ediff-show-registry))
(define-key menu-bar-epatch-menu [separator-epatch] '("--"))
(define-key menu-bar-epatch-menu [ediff-patch-buffer]
'("To a Buffer..." . ediff-patch-buffer))
(define-key menu-bar-epatch-menu [ediff-patch-file]
@ -202,84 +222,93 @@
(autoload 'ediff "ediff" "Compare two files" t)
(autoload 'ediff-files "ediff" "Compare two files" t)
(autoload 'ediff-buffers "ediff" "Compare two bufers" t)
(autoload 'ebuffers "ediff" "Compare two bufers" t)
(autoload 'ediff3 "ediff" "Compare three files" t)
(autoload 'ediff-files3 "ediff" "Compare three files" t)
(autoload 'ediff-buffers3 "ediff" "Compare three bufers" t)
(autoload 'ebuffers3 "ediff" "Compare three bufers" t)
(autoload 'ediff-revision "ediff" "Compare versions of a file" t)
;; compare regions and windows
(autoload 'ediff-windows-wordwise
"ediff" "Compare two windows word-by-word" t)
"ediff" "Compare two windows word-by-word." t)
(autoload 'ediff-regions-wordwise
"ediff" "Compare two regions word-by-word" t)
"ediff" "Compare two regions word-by-word." t)
(autoload 'ediff-windows-linewise
"ediff" "Compare two windows line-by-line" t)
"ediff" "Compare two windows line-by-line." t)
(autoload 'ediff-regions-linewise
"ediff" "Compare two regions line-by-line" t)
"ediff" "Compare two regions line-by-line." t)
;; patch
(autoload 'ediff-patch-file "ediff" "Patch a file" t)
(autoload 'epatch "ediff" "Patch a file" t)
(autoload 'ediff-patch-buffer "ediff" "Patch a buffer")
(autoload 'epatch-buffer "ediff" "Patch a buffer" t)
(autoload 'ediff-patch-file "ediff" "Patch a file." t)
(autoload 'epatch "ediff" "Patch a file." t)
(autoload 'ediff-patch-buffer "ediff" "Patch a buffer.")
(autoload 'epatch-buffer "ediff" "Patch a buffer." t)
;; merge
(autoload 'ediff-merge "ediff" "Merge two files" t)
(autoload 'ediff-merge-files "ediff" "Merge two files" t)
(autoload 'ediff-merge "ediff" "Merge two files." t)
(autoload 'ediff-merge-files "ediff" "Merge two files." t)
(autoload 'ediff-merge-files-with-ancestor
"ediff" "Merge two files using a third file as an ancestor" t)
(autoload 'ediff-merge-buffers "ediff" "Merge two buffers" t)
"ediff" "Merge two files using a third file as an ancestor." t)
(autoload 'ediff-merge-buffers "ediff" "Merge two buffers." t)
(autoload 'ediff-merge-buffers-with-ancestor
"ediff" "Merge two buffers using a third buffer as an ancestor" t)
"ediff" "Merge two buffers using a third buffer as an ancestor." t)
(autoload 'ediff-merge-revisions "ediff" "Merge two versions of a file" t)
(autoload 'ediff-merge-revisions "ediff" "Merge two versions of a file." t)
(autoload 'ediff-merge-revisions-with-ancestor
"ediff" "Merge two versions of a file" t)
"ediff" "Merge two versions of a file." t)
;; compare directories
(autoload 'edirs "ediff" "Compare files in two directories" t)
(autoload 'ediff-directories "ediff" "Compare files in two directories" t)
(autoload 'edirs3 "ediff" "Compare files in three directories" t)
(autoload 'ediff-directories3 "ediff" "Compare files in three directories" t)
(autoload 'edirs "ediff" "Compare files in two directories." t)
(autoload 'ediff-directories "ediff" "Compare files in two directories." t)
(autoload 'edirs3 "ediff" "Compare files in three directories." t)
(autoload
'ediff-directories3 "ediff" "Compare files in three directories." t)
(autoload 'edir-revisions
"ediff" "Compare two versions of a file" t)
"ediff" "Compare two versions of a file." t)
(autoload 'ediff-directory-revisions
"ediff" "Compare two versions of a file" t)
"ediff" "Compare two versions of a file." t)
;; merge directories
(autoload 'edirs-merge "ediff" "Merge files in two directories" t)
(autoload 'edirs-merge "ediff" "Merge files in two directories." t)
(autoload 'ediff-merge-directories
"ediff" "Merge files in two directories" t)
"ediff" "Merge files in two directories." t)
(autoload 'edirs-merge-with-ancestor
"ediff"
"Merge files in two directories using files in a third dir as ancestors" t)
"Merge files in two directories using files in a third dir as ancestors."
t)
(autoload 'ediff-merge-directories-with-ancestor
"ediff"
"Merge files in two directories using files in a third dir as ancestors" t)
"Merge files in two directories using files in a third dir as ancestors."
t)
(autoload 'edir-merge-revisions
"ediff" "Merge versions of files in a directory" t)
"ediff" "Merge versions of files in a directory." t)
(autoload 'ediff-merge-directory-revisions
"ediff" "Merge versions of files in a directory" t)
"ediff" "Merge versions of files in a directory." t)
(autoload 'ediff-merge-directory-revisions-with-ancestor
"ediff"
"Merge versions of files in a directory using other versions as ancestors"
"Merge versions of files in a directory using other versions as ancestors."
t)
(autoload 'edir-merge-revisions-with-ancestor
"ediff"
"Merge versions of files in a directory using other versions as ancestors"
"Merge versions of files in a directory using other versions as ancestors."
t)
;; misc
(autoload 'ediff-show-registry
"ediff-meta"
"Display the registry of active Ediff sessions"
"Display the registry of active Ediff sessions."
t)
(autoload 'ediff-documentation
"ediff"
"Display Ediff's manual."
t)
(autoload 'ediff-version
"ediff"
"Show Ediff's version and last modification date"
"Show Ediff's version and last modification date."
t)
) ; if purify-flag

View File

@ -1,6 +1,6 @@
;;; ediff-init.el --- Macros, variables, and defsubsts used by Ediff
;; Copyright (C) 1994, 1995 Free Software Foundation, Inc.
;; Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
;; Author: Michael Kifer <kifer@cs.sunysb.edu>
@ -23,15 +23,33 @@
;;; Code:
;; Start compiler pacifier
(defvar ediff-metajob-name)
(defvar ediff-meta-buffer)
(defvar pm-color-alist)
(defvar ediff-grab-mouse)
(defvar ediff-mouse-pixel-position)
(defvar ediff-mouse-pixel-threshold)
(defvar ediff-whitespace)
(defvar ediff-multiframe)
;; end pacifier
;; Is it XEmacs?
(defconst ediff-xemacs-p (string-match "XEmacs" emacs-version))
;; Is it Emacs?
(defconst ediff-emacs-p (not ediff-xemacs-p))
(defvar ediff-force-faces nil
"If t, Ediff will think that it is running on a display that supports faces.
This is provided as a temporary relief for users of face-capable displays
that Ediff doesn't know about.")
;; Are we running as a window application or on a TTY?
(defsubst ediff-device-type ()
(if ediff-emacs-p
window-system
(device-type (selected-device))))
;; in XEmacs: device-type is tty on tty and stream in batch.
(defun ediff-window-display-p ()
(and (ediff-device-type) (not (memq (ediff-device-type) '(tty pc stream)))))
@ -45,6 +63,35 @@
(ediff-emacs-p (memq (ediff-device-type) '(pc)))
(ediff-xemacs-p (memq (ediff-device-type) '(tty pc)))))
;; Defines SYMBOL as an advertised local variable.
;; Performs a defvar, then executes `make-variable-buffer-local' on
;; the variable. Also sets the `permanent-local' property,
;; so that `kill-all-local-variables' (called by major-mode setting
;; commands) won't destroy Ediff control variables.
;;
;; Plagiarised from `emerge-defvar-local' for XEmacs.
(defmacro ediff-defvar-local (var value doc)
(` (progn
(defvar (, var) (, value) (, doc))
(make-variable-buffer-local '(, var))
(put '(, var) 'permanent-local t))))
;; Variables that control each Ediff session---local to the control buffer.
;; Mode variables
;; The buffer in which the A variant is stored.
(ediff-defvar-local ediff-buffer-A nil "")
;; The buffer in which the B variant is stored.
(ediff-defvar-local ediff-buffer-B nil "")
;; The buffer in which the C variant is stored.
(ediff-defvar-local ediff-buffer-C nil "")
;; Ancestor buffer
(ediff-defvar-local ediff-ancestor-buffer nil "")
;; The control buffer of ediff.
(ediff-defvar-local ediff-control-buffer nil "")
;;; Macros
(defmacro ediff-odd-p (arg)
@ -130,20 +177,6 @@
(` (ediff-get-fine-diff-vector-from-diff-record
(ediff-get-difference (, n) (, buf-type)))))
;; Defines SYMBOL as an advertised local variable.
;; Performs a defvar, then executes `make-variable-buffer-local' on
;; the variable. Also sets the `permanent-local' property,
;; so that `kill-all-local-variables' (called by major-mode setting
;; commands) won't destroy Ediff control variables.
;;
;; Plagiarised from `emerge-defvar-local' for XEmacs.
(defmacro ediff-defvar-local (var value doc)
(` (progn
(defvar (, var) (, value) (, doc))
(make-variable-buffer-local '(, var))
(put '(, var) 'permanent-local t))))
;; Macro to switch to BUFFER, evaluate FORMS, returns to original buffer.
;; Differs from `save-excursion' in that it doesn't save the point and mark.
;; This is essentially `emerge-eval-in-buffer' with the test for live buffers."
@ -229,9 +262,14 @@
'(ediff-directory-revisions
ediff-merge-directory-revisions
ediff-merge-directory-revisions-with-ancestor)))
;; metajob involving only one directory
(defsubst ediff-dir1-metajob (&optional metajob)
(defsubst ediff-patch-metajob (&optional metajob)
(memq (or metajob ediff-metajob-name)
'(ediff-multifile-patch)))
;; metajob involving only one group of files, such as multipatch or directory
;; revision
(defsubst ediff-one-filegroup-metajob (&optional metajob)
(or (ediff-revision-metajob metajob)
(ediff-patch-metajob metajob)
;; add more here
))
(defsubst ediff-collect-diffs-metajob (&optional metajob)
@ -431,7 +469,10 @@ the value of this variable and the variables `ediff-help-message-*' in
(defconst ediff-KILLED-VITAL-BUFFER
"You have killed a vital Ediff buffer---you must leave Ediff now!")
(defconst ediff-NO-DIFFERENCES
"Sorry, it is not my job to munch identical variants...")
"Sorry, comparison of identical variants is not what I am made for...")
(defconst ediff-BAD-DIFF-NUMBER
;; %S stands for this-command, %d - diff number, %d - max diff
"%S: Bad diff region number, %d. Valid numbers are 1 to %d")
;; Selective browsing
@ -511,12 +552,6 @@ highlighted using ASCII flags.
This variable can be set either in .emacs or toggled interactively.
Use `setq-default' if setting it in .emacs")
(defvar ediff-force-faces nil
"If t, Ediff will think that it is running on a display that supports faces.
This is provided as a temporary relief for users of face-capable displays
that Ediff doesn't know about.")
;; this indicates that diff regions are word-size, so fine diffs are
;; permanently nixed; used in ediff-windows-wordwise and ediff-regions-wordwise
(ediff-defvar-local ediff-word-mode nil "")
@ -560,22 +595,6 @@ ediff-toggle-hilit. Use `setq-default' to set it.")
;; unhighlighted, `off' -- turned off \(on a dumb terminal only\).
(ediff-defvar-local ediff-highlighting-style nil "")
;; Variables that control each Ediff session. They are local to the
;; control buffer.
;; Mode variables
;; The buffer in which the A variant is stored.
(ediff-defvar-local ediff-buffer-A nil "")
;; The buffer in which the B variant is stored.
(ediff-defvar-local ediff-buffer-B nil "")
;; The buffer in which the C variant is stored.
(ediff-defvar-local ediff-buffer-C nil "")
;; Ancestor buffer
(ediff-defvar-local ediff-ancestor-buffer nil "")
;; The control buffer of ediff.
(ediff-defvar-local ediff-control-buffer nil "")
;; The suffix of the control buffer name.
(ediff-defvar-local ediff-control-buffer-suffix nil "")
@ -797,18 +816,18 @@ appropriate symbol: `rcs', `pcl-cvs', or `generic-sc' if you so desire.")
(let ((is-current (ediff-overlay-get extent 'ediff))
(face (ediff-overlay-get extent 'face))
(diff-num (ediff-overlay-get extent 'ediff-diff-num))
face-help help-msg)
face-help)
;; This happens only for refinement overlays
(setq face-help (and face (get face 'ediff-help-echo)))
(setq help-msg
(cond ((and is-current diff-num) ; current diff region
(format "Difference region %S -- current" (1+ diff-num)))
(face-help) ; refinement of current diff region
(diff-num ; non-current
(format "Difference region %S -- non-current" (1+ diff-num)))
(t ""))))) ; none
(cond ((and is-current diff-num) ; current diff region
(format "Difference region %S -- current" (1+ diff-num)))
(face-help) ; refinement of current diff region
(diff-num ; non-current
(format "Difference region %S -- non-current" (1+ diff-num)))
(t "")) ; none
))
(defun ediff-set-face (ground face color)
"Set face foreground/background."
@ -1353,7 +1372,7 @@ More precisely, a regexp to match any one such character.")
(defun ediff-overlay-buffer (overl)
(if ediff-emacs-p
(overlay-buffer overl)
(and (extent-live-p overl) (extent-buffer overl))))
(and (extent-live-p overl) (extent-object overl))))
;; like overlay-get in Emacs. In XEmacs, returns nil if the extent is
;; dead. Otherwise, like extent-property
@ -1482,6 +1501,19 @@ More precisely, a regexp to match any one such character.")
(if ediff-verbose-p
(apply 'message string args)))
(defun ediff-file-attributes (filename attr-number)
(let ((handler (find-file-name-handler filename 'find-file-noselect)))
(if (and handler (string-match "ange-ftp" (format "%S" handler)))
-1
(nth attr-number (file-attributes filename)))))
(defsubst ediff-file-size (filename)
(ediff-file-attributes filename 7))
(defsubst ediff-file-modtime (filename)
(ediff-file-attributes filename 5))
(provide 'ediff-init)

View File

@ -1,6 +1,6 @@
;;; ediff-merg.el --- merging utilities
;; Copyright (C) 1994, 1995 Free Software Foundation, Inc.
;; Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
;; Author: Michael Kifer <kifer@cs.sunysb.edu>
@ -25,6 +25,7 @@
(require 'ediff-init)
(defvar ediff-default-variant 'combined
"*The variant to be used as a default for buffer C in merging.
Valid values are the symbols `default-A', `default-B', and `combined'.")
@ -114,9 +115,10 @@ skiped over. Nil means show all regions.")
(defun ediff-do-merge (diff-num &optional remerging)
(if (< diff-num 0) (setq diff-num 0))
(let ((n diff-num)
(default-state-of-merge (format "%S" ediff-default-variant))
;;(default-state-of-merge (format "%S" ediff-default-variant))
do-not-copy state-of-merge)
(while (< n ediff-number-of-differences)
(setq do-not-copy nil) ; reset after each cycle
(if (= (mod n 10) 0)
(message "%s buffers A & B into C ... region %d of %d"
(if remerging "Re-merging" "Merging")
@ -130,9 +132,9 @@ skiped over. Nil means show all regions.")
(reg-B (ediff-get-region-contents n 'B ediff-control-buffer))
(reg-C (ediff-get-region-contents n 'C ediff-control-buffer)))
;;; was edited since first set by default
;; if region was edited since it was first set by default
(if (or (and (string= state-of-merge "default-A")
(not (string= reg-A reg-C)))
(not (string= reg-A reg-C)))
;; was edited since first set by default
(and (string= state-of-merge "default-B")
(not (string= reg-B reg-C)))

View File

@ -1,6 +1,6 @@
;;; ediff-mult.el --- support for multi-file/multi-buffer processing in Ediff
;; Copyright (C) 1995 Free Software Foundation, Inc.
;; Copyright (C) 1995, 1996 Free Software Foundation, Inc.
;; Author: Michael Kifer <kifer@cs.sunysb.edu>
@ -23,9 +23,8 @@
;;; Commentary:
;; Users are strongly encouraged to add functionality to this file.
;; In particular, epatch needs to be enhanced to work with multi-file
;; patches. The present file contains all the infrastructure needed for that.
;; 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,
;; you need to tell it
@ -37,22 +36,36 @@
;; In all likelihood, ediff-redraw-directory-group-buffer can be used
;; directly or after a small modification.
;; 2. What action to take when the user clicks button 2 or types v,e, or
;; RET. See ediff-dir-action.
;; RET. See ediff-filegroup-action.
;; 3. Provide a list of pairs or triples of file names (or buffers,
;; depending on the particular Ediff operation you want to invoke)
;; in the following format:
;; ((obj1 obj2 [optional obj3]) (...) ...)
;; (descriptor (obj1 obj2 obj3) (...) ...)
;; Actually, the format of this list is pretty much up to the
;; developer. The only thing is that it must be a list of lists.
;; developer. The only thing is that it must be a list of lists,
;; and the first list must describe the meta session, and subsequent
;; elements must describe individual sessions.
;; This descriptor must be a list of two, three, or four elements (nil
;; 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 nil in front of each list (i.e., the above list
;; will become ((nil obj1 obj2 ...) (nil ...) ...).
;; (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 ...) ...)
;; Ediff expects that your function (in 2 above) will arrange to
;; replace this prepended nil (via setcar) with the actual ediff
;; control buffer associated with an appropriate Ediff session.
;; This is arranged through internal startup hooks that can be passed
;; to any of Ediff major entries (such as ediff-files, epatch, etc.).
;; See how this is done in ediff-dir-action.
;; See how this is done in ediff-filegroup-action.
;;
;; Session descriptions are of the form (obj1 obj2 obj3), which
;; describe objects relevant to the session. Usually they are names of
;; files, but sometimes they may be other things. For instance, obj3 is
;; nil for jobs that involve only two files. For patch jobs, obj2 and
;; obj3 are markers that specify the patch corresponding to the file
;; (whose name is obj1).
;; 4. Write a function that makes a call to ediff-prepare-meta-buffer
;; passing all this info.
;; You may be able to use ediff-directories-internal as a template.
@ -64,13 +77,7 @@
;; ediff-merge-directories-with-ancestor all use
;; ediff-directories-internal.
;;
;; In case of multifile patching, the easiest thing is to first apply the patch
;; and then find out which files were patched (using the algorithm utilized by
;; Unix patch and by parsing the patch file). The procedure ediff-patch-file
;; works for single-file patches only. However, it can deal with remote and
;; compressed files. Check out ediff-patch-file for details.
;;
;; Another useful addition here could be session groups selected by patterns
;; A useful addition here could be session groups selected by patterns
;; (which are different in each directory). For instance, one may want to
;; compare files of the form abc{something}.c to files old{something}.d
;; which may be in the same or different directories. Or, one may want to
@ -79,7 +86,7 @@
;; Implementing this requires writing an collating function, which should pair
;; up appropriate files. It will also require a generalization of the functions
;; that do the layout of the meta- and differences buffers and of
;; ediff-dir-action.
;; ediff-filegroup-action.
;;; Code:
@ -95,11 +102,11 @@
Useful commands:
button2, `v', RET over a session line: start that Ediff session
`M' in any session invoked from here: bring back this buffer
`M':\tin any session invoked from here, brings back this group panel
`R':\tdisplay the registry of active Ediff sessions
`h':\tmark session for hiding; with prefix arg--unmark
`h':\tmark session for hiding (toggle)
`x':\thide marked sessions; with prefix arg--unhide hidden sessions
`m':\tmark session for non-hiding operation; with prefix arg--unmark
`m':\tmark session for a non-hiding operation (toggle)
SPC:\tnext session
DEL:\tprevious session
`E':\tbrowse Ediff on-line manual
@ -113,12 +120,12 @@ Useful commands:
directories.")
;; Variable specifying the action to take when the use invokes ediff in the
;; meta buffer. This is usually ediff-registry-action or ediff-dir-action
;; meta buffer. This is usually ediff-registry-action or ediff-filegroup-action
(ediff-defvar-local ediff-meta-action-function nil "")
;; Tells ediff-update-meta-buffer how to redraw it
(ediff-defvar-local ediff-meta-redraw-function nil "")
;; Tells ediff-dir-action and similar procedures how to invoke Ediff for the
;; sessions in a given session group
;; Tells ediff-filegroup-action and similar procedures how to invoke Ediff for
;; the sessions in a given session group
(ediff-defvar-local ediff-session-action-function nil "")
(ediff-defvar-local ediff-metajob-name nil "")
@ -130,7 +137,7 @@ directories.")
(defvar ediff-filtering-regexp-history nil "")
;; This has the form ((ctl-buf file1 file2) (stl-buf file1 file2) ...)
;; If ctl-buf is nil, the file-pare wasn't processed yet. If it is
;; If ctl-buf is nil, the file-pair wasn't processed yet. If it is
;; killed-buffer object, the file pair has been processed. If it is a live
;; buffer, this means ediff is still working on the pair
(ediff-defvar-local ediff-meta-list nil "")
@ -153,30 +160,48 @@ ediff-directories, is run.")
(defvar ediff-show-session-group-hook nil
"*Hooks run just after a session group buffer is shown.")
;;; API
;; buffer holding the multi-file patch. local to the meta buffer
(ediff-defvar-local ediff-meta-patchbufer nil "")
;;; API for ediff-meta-list
;; group buffer/regexp
(defun ediff-get-group-buffer (meta-list)
(nth 0 (car meta-list)))
(defun ediff-get-group-regexp (meta-list)
(nth 1 (car meta-list)))
;; group objects
(defun ediff-get-group-objA (meta-list)
(nth 2 (car meta-list)))
(defun ediff-get-group-objB (meta-list)
(nth 3 (car meta-list)))
(defun ediff-get-group-objC (meta-list)
(nth 4 (car meta-list)))
;; session buffer
(defun ediff-get-session-buffer (elt)
(nth 0 elt))
(defun ediff-get-session-status (elt)
(nth 1 elt))
(defun ediff-set-session-status (session-info new-status)
(setcar (cdr session-info) new-status))
;; session objects
(defun ediff-get-session-objA (elt)
(nth 2 elt))
(defun ediff-get-session-objB (elt)
(nth 3 elt))
(defun ediff-get-session-objC (elt)
(nth 4 elt))
(defun ediff-set-session-status (session-info new-status)
(setcar (cdr session-info) new-status))
(defun ediff-get-session-objA-name (elt)
(car (nth 2 elt)))
(defun ediff-get-session-objB-name (elt)
(car (nth 3 elt)))
(defun ediff-get-session-objC-name (elt)
(car (nth 4 elt)))
;; equality indicators
(defsubst ediff-get-file-eqstatus (elt)
(nth 1 elt))
(defsubst ediff-set-file-eqstatus (elt value)
(setcar (cdr elt) value))
;; set up the keymap in the meta buffer
(defun ediff-setup-meta-map()
@ -191,6 +216,8 @@ ediff-directories, is run.")
(define-key ediff-meta-buffer-map "\C-?" 'ediff-previous-meta-item)
(define-key ediff-meta-buffer-map [delete] 'ediff-previous-meta-item)
(define-key ediff-meta-buffer-map [backspace] 'ediff-previous-meta-item)
(or (ediff-one-filegroup-metajob)
(define-key ediff-meta-buffer-map "=" 'ediff-meta-mark-equal-files))
(if ediff-no-emacs-help-in-control-buffer
(define-key ediff-meta-buffer-map "\C-h" 'ediff-previous-meta-item))
(if ediff-emacs-p
@ -253,7 +280,8 @@ Moves in circular fashion. With numeric prefix arg, skip this many items."
(if pos (goto-char pos))
(if (eq ediff-metajob-name 'ediff-registry)
(if (search-forward "*Ediff" nil t)
(if (and (ediff-get-meta-info (current-buffer) pos 'noerror)
(search-forward "*Ediff" nil t))
(skip-chars-backward "a-zA-Z*"))
(if (> (skip-chars-forward "-+?H* \t0-9") 0)
(backward-char 1)))))
@ -278,10 +306,12 @@ Moves in circular fashion. With numeric prefix arg, skip this many items."
(if pos (goto-char pos))
(if (eq ediff-metajob-name 'ediff-registry)
(if (search-forward "*Ediff" nil t)
(if (and (ediff-get-meta-info (current-buffer) pos 'noerror)
(search-forward "*Ediff" nil t))
(skip-chars-backward "a-zA-Z*"))
(if (> (skip-chars-forward "-+?H* \t0-9") 0)
(backward-char 1)))))
(backward-char 1)))
))
@ -470,15 +500,26 @@ Moves in circular fashion. With numeric prefix arg, skip this many items."
(define-key
ediff-meta-buffer-map "M" 'ediff-show-meta-buff-from-registry))
;; initialize the meta list -- don't do this for registry we prepend
;; '(nil nil) nil to all elts of meta-list, except the first. The
;; '(nil nil) to all elts of meta-list, except the first. The
;; first nil will later be replaced by the session buffer. The second
;; is reserved for session status.
;; (car ediff-meta-list) gets cons'ed with the session group buffer.
;; Also, session objA/B/C are turned into lists (obj eq-indicator)
;; For now, the eq-indicator is used only for 2 and 3-file jobs.
(setq ediff-meta-list
(cons (cons meta-buffer (car meta-list))
(mapcar (function
(lambda (elt)
(cons nil (cons nil elt))))
(cons nil
(cons nil
;; convert each obj to (obj nil),
;; where nil may later be replaced
;; by =, if this file equals some
;; other file in the same session
(mapcar (function
(lambda (obj)
(list obj nil)))
elt)))))
(cdr meta-list)))))
(or (eq meta-buffer ediff-registry-buffer)
@ -496,22 +537,25 @@ Moves in circular fashion. With numeric prefix arg, skip this many items."
;; arrange for showing directory contents differences
;; must be after run startup-hooks, since ediff-dir-difference-list is
;; set inside these hooks
(if (eq action-func 'ediff-dir-action)
(if (eq action-func 'ediff-filegroup-action)
(progn
;; put meta buffer in (car ediff-dir-difference-list)
(setq ediff-dir-difference-list
(cons (cons meta-buffer (car ediff-dir-difference-list))
(cdr ediff-dir-difference-list)))
(or (ediff-dir1-metajob jobname)
(or (ediff-one-filegroup-metajob jobname)
(ediff-draw-dir-diffs ediff-dir-difference-list))
(define-key ediff-meta-buffer-map "h" 'ediff-mark-for-hiding)
(define-key
ediff-meta-buffer-map "x" 'ediff-hide-marked-sessions)
(define-key ediff-meta-buffer-map "m" 'ediff-mark-for-operation)
(if (ediff-collect-diffs-metajob jobname)
(define-key
ediff-meta-buffer-map "P" 'ediff-collect-custom-diffs))
(cond ((ediff-collect-diffs-metajob jobname)
(define-key
ediff-meta-buffer-map "P" 'ediff-collect-custom-diffs))
((ediff-patch-metajob jobname)
(define-key
ediff-meta-buffer-map "P" 'ediff-meta-show-patch)))
(define-key ediff-meta-buffer-map "u" 'ediff-up-meta-hierarchy)
(define-key ediff-meta-buffer-map "D" 'ediff-show-dir-diffs)))
@ -539,18 +583,24 @@ Moves in circular fashion. With numeric prefix arg, skip this many items."
(setq regexp (ediff-get-group-regexp meta-list))
(if (ediff-collect-diffs-metajob)
(insert
" `P':\tcollect custom diffs of all marked sessions\n"))
(cond ((ediff-collect-diffs-metajob)
(insert
" `P':\tcollect custom diffs of all marked sessions\n"))
((ediff-patch-metajob)
(insert
" `P':\tshow patch appropriately for the context (session or group)\n")))
(insert
" `u':\tshow parent session group
`D':\tdisplay differences among the contents of directories\n\n")
" `u':\tshow parent session group\n")
(or (ediff-one-filegroup-metajob)
(insert
" `D':\tshow differences among directories\n"
" `=':\tmark identical files in each session\n\n"))
(if (and (stringp regexp) (> (length regexp) 0))
(insert (format "Filter-through regular expression: %s\n" regexp)))
(insert "\n
Size Name
Size Last modified Name
-----------------------------------------------------------------------
")
@ -569,12 +619,7 @@ Moves in circular fashion. With numeric prefix arg, skip this many items."
" ****** ****** This session group has no members\n"))
;; now organize file names like this:
;; preferred format:
;; use-mark sizeA dateA sizeB dateB filename
;; I don't have time to mess up with calculating last modtimes
;; (XEmacs has no decode-time function), so
;; the actual format is:
;; use-mark Size filename
;; make sure directories are displayed with a trailing slash.
;; If one is a directory and another isn't, indicate this with a `?'
(while meta-list
@ -609,9 +654,9 @@ Moves in circular fashion. With numeric prefix arg, skip this many items."
;; At present, problematic sessions occur only in -with-ancestor comparisons
;; when the ancestor is a directory rather than a file.
(defun ediff-problematic-session-p (session)
(let ((f1 (ediff-get-session-objA session))
(f2 (ediff-get-session-objB session))
(f3 (ediff-get-session-objC session)))
(let ((f1 (ediff-get-session-objA-name session))
(f2 (ediff-get-session-objB-name session))
(f3 (ediff-get-session-objC-name session)))
(cond ((and (stringp f1) (not (file-directory-p f1))
(stringp f2) (not (file-directory-p f2))
(stringp f3) (file-directory-p f3)
@ -620,19 +665,53 @@ Moves in circular fashion. With numeric prefix arg, skip this many items."
'ancestor-is-dir)
(t nil))))
(defun ediff-meta-insert-file-info (file)
(if (stringp file)
(insert
(format
" %10d %s\n"
(nth 7 (file-attributes file))
;; dir names in meta lists have no trailing `/' so insert it
(cond ((file-directory-p file)
(file-name-as-directory (ediff-abbreviate-file-name file)))
(t (ediff-abbreviate-file-name file)))))
))
(defun ediff-meta-insert-file-info (fileinfo)
(let ((file-size -1)
(fname (car fileinfo))
(feq (ediff-get-file-eqstatus fileinfo))
(file-modtime "*file doesn't exist*"))
(if (and (stringp fname) (file-exists-p fname))
(setq file-size (ediff-file-size fname)
file-modtime (ediff-file-modtime fname)))
(if (stringp fname)
(insert
(format
"%s %s %-20s %s\n"
(if feq "=" " ") ; equality indicator
(format "%10s" (if (< file-size 0)
"remote"
file-size))
(if (< file-size 0)
"file"
(ediff-format-date (decode-time file-modtime)))
;; dir names in meta lists have no trailing `/' so insert it
(cond ((file-directory-p fname)
(file-name-as-directory (ediff-abbreviate-file-name fname)))
(t (ediff-abbreviate-file-name fname)))))
)))
(defconst ediff-months '((1 . "Jan") (2 . "Feb") (3 . "Mar") (4 . "Apr")
(5 . "May") (6 . "Jun") (7 . "Jul") (8 . "Aug")
(9 . "Sep") (10 . "Oct") (11 . "Nov") (12 . "Dec"))
"Months' associative array.")
;; TIME is like the output of decode-time
(defun ediff-format-date (time)
(format "%s %2d %4d %s:%s:%s"
(cdr (assoc (nth 4 time) ediff-months)) ; month
(nth 3 time) ; day
(nth 5 time) ; year
(ediff-fill-leading-zero (nth 2 time)) ; hour
(ediff-fill-leading-zero (nth 1 time)) ; min
(ediff-fill-leading-zero (nth 0 time)) ; sec
))
;; returns 2char string
(defsubst ediff-fill-leading-zero (num)
(if (< num 10)
(format "0%d" num)
(number-to-string num)))
(defun ediff-draw-dir-diffs (diff-list)
(if (null diff-list) (error "Lost difference info on these directories"))
@ -740,7 +819,7 @@ Useful commands:
(defun ediff-show-dir-diffs ()
"Display differences among the directories involved in session group."
(interactive)
(if (ediff-dir1-metajob)
(if (ediff-one-filegroup-metajob)
(error "This command is inapplicable in the present context"))
(or (ediff-buffer-live-p ediff-dir-diffs-buffer)
(ediff-draw-dir-diffs ediff-dir-difference-list))
@ -810,9 +889,15 @@ Useful commands:
(ediff-abbreviate-file-name
(ediff-get-group-objA meta-list))
(ediff-abbreviate-file-name
(or (ediff-get-group-objB meta-list) ""))
(if (stringp
(ediff-get-group-objB meta-list))
(ediff-get-group-objB meta-list)
""))
(ediff-abbreviate-file-name
(or (ediff-get-group-objC meta-list) ""))))
(if (stringp
(ediff-get-group-objC meta-list))
(ediff-get-group-objC meta-list)
""))))
(ediff-set-meta-overlay pt (point) elt))
(progn
(ediff-eval-in-buffer elt
@ -867,11 +952,15 @@ Useful commands:
(info (ediff-get-meta-info meta-buf pos))
(session-buf (ediff-get-session-buffer info)))
(if (eq (ediff-get-session-status info) ?H)
(setq unmark t))
(if unmark
(ediff-set-session-status info nil)
(if (ediff-buffer-live-p session-buf)
(error "Can't hide active session, %s" (buffer-name session-buf)))
(ediff-set-session-status info ?H))
(or unmark
(ediff-next-meta-item 1))
(ediff-update-meta-buffer meta-buf)
))
@ -883,9 +972,13 @@ Useful commands:
;; ediff-get-meta-info gives error if meta-buf or pos are invalid
(info (ediff-get-meta-info meta-buf pos)))
(if (eq (ediff-get-session-status info) ?*)
(setq unmark t))
(if unmark
(ediff-set-session-status info nil)
(ediff-set-session-status info ?*))
(or unmark
(ediff-next-meta-item 1))
(ediff-update-meta-buffer meta-buf)
))
@ -897,20 +990,27 @@ Useful commands:
(from (if unhide ?I ?H))
(to (if unhide ?H ?I))
(numMarked 0)
elt)
active-sessions-exist session-buf elt)
(while meta-list
(setq elt (car meta-list)
meta-list (cdr meta-list))
meta-list (cdr meta-list)
session-buf (ediff-get-session-buffer elt))
(if (eq (ediff-get-session-status elt) from)
(progn
(setq numMarked (1+ numMarked))
(ediff-set-session-status elt to))))
(if (and (eq to ?I) (buffer-live-p session-buf))
;; shouldn't hide active sessions
(setq active-sessions-exist t)
(ediff-set-session-status elt to)))))
(if (> numMarked 0)
(ediff-update-meta-buffer grp-buf)
(beep)
(if unhide
(message "Nothing to reveal...")
(message "Nothing to hide...")))
(if active-sessions-exist
(message "Note: didn't hide active sessions!"))
))
;; Apply OPERATION to marked sessions. Operation expects one argument of type
@ -968,8 +1068,8 @@ Useful commands:
(shell-command
(format "%s %s %s %s"
ediff-custom-diff-program ediff-custom-diff-options
(ediff-get-session-objA session)
(ediff-get-session-objB session))
(ediff-get-session-objA-name session)
(ediff-get-session-objB-name session))
t))
(save-excursion
(set-buffer meta-diff-buff)
@ -999,9 +1099,31 @@ all marked sessions must be active."
(beep)
(message "No marked sessions found")))
(defun ediff-meta-show-patch ()
"Show the multi-file patch associated with this group session."
(interactive)
(let* ((pos (ediff-event-point last-command-event))
(meta-buf (ediff-event-buffer last-command-event))
(info (ediff-get-meta-info meta-buf pos 'noerror))
(patchbuffer ediff-meta-patchbufer))
(if (ediff-buffer-live-p patchbuffer)
(ediff-eval-in-buffer patchbuffer
(save-restriction
(if (not info)
(widen)
(narrow-to-region
(ediff-get-session-objB-name info)
(ediff-get-session-objC-name info)))
(set-buffer (get-buffer-create ediff-tmp-buffer))
(erase-buffer)
(insert-buffer patchbuffer)
(display-buffer ediff-tmp-buffer 'not-this-window)
))
(error "The patch buffer wasn't found"))))
;; This function executes in meta buffer. It knows where event happened.
(defun ediff-dir-action ()
(defun ediff-filegroup-action ()
"Execute appropriate action for the selected session."
(interactive)
(let* ((pos (ediff-event-point last-command-event))
@ -1011,13 +1133,13 @@ all marked sessions must be active."
session-buf file1 file2 file3 regexp)
(setq session-buf (ediff-get-session-buffer info)
file1 (ediff-get-session-objA info)
file2 (ediff-get-session-objB info)
file3 (ediff-get-session-objC info))
file1 (ediff-get-session-objA-name info)
file2 (ediff-get-session-objB-name info)
file3 (ediff-get-session-objC-name info))
;; make sure we don't start on hidden sessions
;; ?H means marked for hiding. ?I means invalid (hidden).
(if (memq (ediff-get-session-status info) '(?H ?I))
(if (memq (ediff-get-session-status info) '(?I))
(progn
(beep)
(if (y-or-n-p "This session is marked as hidden, unmark? ")
@ -1052,7 +1174,9 @@ all marked sessions must be active."
(setcar (quote (, info)) ediff-meta-buffer)))))))
;; Do ediff-revision on a subdirectory
((and (ediff-dir1-metajob) (file-directory-p file1))
((and (ediff-one-filegroup-metajob)
(ediff-revision-metajob)
(file-directory-p file1))
(if (ediff-buffer-live-p session-buf)
(ediff-show-meta-buffer session-buf)
(setq regexp (read-string "Filter through regular expression: "
@ -1070,7 +1194,7 @@ all marked sessions must be active."
;; From here on---only individual session handlers
;; handle an individual session with live control buffer
;; handle an individual session with a live control buffer
((ediff-buffer-live-p session-buf)
(ediff-eval-in-buffer session-buf
(setq ediff-mouse-pixel-position (mouse-pixel-position))
@ -1082,17 +1206,17 @@ all marked sessions must be active."
"This session's ancestor is a directory, merge without the ancestor? ")
(ediff-merge-files
file1 file2
;; arrange startup hooks
;; provide startup hooks
(` (list (lambda ()
(setq ediff-meta-buffer (, (current-buffer)))
;; see below for the explanation of what this does
(setcar
(quote (, info)) ediff-control-buffer)))))
(error "Aborted")))
((ediff-dir1-metajob) ; needs 1 file arg
((ediff-one-filegroup-metajob) ; needs 1 file arg
(funcall ediff-session-action-function
file1
;; arrange startup hooks
;; provide startup hooks
(` (list (lambda ()
(setq ediff-meta-buffer (, (current-buffer)))
;; see below for explanation of what this does
@ -1101,7 +1225,7 @@ all marked sessions must be active."
((not (ediff-metajob3)) ; need 2 file args
(funcall ediff-session-action-function
file1 file2
;; arrange startup hooks
;; provide startup hooks
(` (list (lambda ()
(setq ediff-meta-buffer (, (current-buffer)))
;; this makes ediff-startup pass the value of
@ -1321,14 +1445,13 @@ If this is a session registry buffer then just bury it."
(ediff-cleanup-meta-buffer buf)
(cond ((and (ediff-safe-to-quit buf)
(y-or-n-p "Quit this session group? "))
(message "")
(ediff-dispose-of-meta-buffer buf))
((ediff-safe-to-quit buf)
(bury-buffer))
(t
(bury-buffer)
(beep)
(message
"Session group suspended, not deleted (has active sessions)")))
(error
"This session group has active sessions---cannot exit")))
(ediff-cleanup-meta-buffer parent-buf)
(ediff-kill-buffer-carefully dir-diffs-buffer)
(ediff-kill-buffer-carefully meta-diff-buffer)
@ -1378,40 +1501,117 @@ If this is a session registry buffer then just bury it."
;; return location of the next meta overlay after point
(defun ediff-next-meta-overlay-start (point)
(let (overl)
(if ediff-xemacs-p
(progn
(setq overl (extent-at point (current-buffer) 'ediff-meta-info))
(if overl
(setq overl (next-extent overl))
(setq overl (next-extent (current-buffer))))
(if overl
(extent-start-position overl)
(point-max)))
(if (= point (point-max)) (setq point (point-min)))
(setq overl (car (overlays-at point)))
(if (and overl (overlay-get overl 'ediff-meta-info))
(overlay-end overl)
(next-overlay-change point)))))
(if (eobp)
(goto-char (point-min))
(let (overl)
(if ediff-xemacs-p
(progn
(setq overl (extent-at point (current-buffer) 'ediff-meta-info))
(if overl
(setq overl (next-extent overl))
(setq overl (next-extent (current-buffer))))
(if overl
(extent-start-position overl)
(point-max)))
(setq overl (car (overlays-at point)))
(if (and overl (overlay-get overl 'ediff-meta-info))
;; note: end of current overlay is the beginning of the next one
(overlay-end overl)
(next-overlay-change point))))
))
(defun ediff-previous-meta-overlay-start (point)
(let (overl)
(if ediff-xemacs-p
(progn
(setq overl (extent-at point (current-buffer) 'ediff-meta-info))
(if overl
(setq overl (previous-extent overl))
(setq overl (previous-extent (current-buffer))))
(if overl
(extent-start-position overl)
(point-max)))
;;(if (bobp) (setq point (point-max)))
(setq overl (car (overlays-at point)))
(setq point (if (and overl (overlay-get overl 'ediff-meta-info))
(previous-overlay-change (overlay-start overl))
(previous-overlay-change point)))
(if (= point (point-min)) (point-max) point)
)))
(if (bobp)
(goto-char (point-max))
(let (overl)
(if ediff-xemacs-p
(progn
(setq overl (extent-at point (current-buffer) 'ediff-meta-info))
(if overl
(setq overl (previous-extent overl))
(setq overl (previous-extent (current-buffer))))
(if overl
(extent-start-position overl)
(point-min)))
(setq overl (car (overlays-at point)))
(if (and overl (overlay-get overl 'ediff-meta-info))
(setq point (overlay-start overl)))
;; to get to the beginning of prev overlay
(if (not (bobp))
;; trickery 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.
(defun ediff-patch-file-form-meta (file &optional startup-hooks)
(let* ((pos (ediff-event-point last-command-event))
(meta-buf (ediff-event-buffer last-command-event))
;; ediff-get-meta-info gives error if meta-buf or pos are invalid
(info (ediff-get-meta-info meta-buf pos))
(meta-patchbuf ediff-meta-patchbufer)
session-buf beg-marker end-marker)
(if (or (file-directory-p file) (string-match "/dev/null" file))
(error "`%s' is not an ordinary file" (file-name-as-directory file)))
(setq session-buf (ediff-get-session-buffer info)
beg-marker (ediff-get-session-objB-name info)
end-marker (ediff-get-session-objC-name info))
(or (ediff-buffer-live-p session-buf) ; either an active patch session
(null session-buf) ; or it is a virgin session
(error
"Patch has been already applied to this file--cannot be repeated!"))
(ediff-eval-in-buffer meta-patchbuf
(save-restriction
(widen)
(narrow-to-region beg-marker end-marker)
(ediff-patch-file-internal meta-patchbuf file startup-hooks)))))
(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."
(interactive)
(let ((list (cdr ediff-meta-list))
fileinfo1 fileinfo2 fileinfo3 elt)
(while (setq elt (car list))
(setq fileinfo1 (ediff-get-session-objA elt)
fileinfo2 (ediff-get-session-objB elt)
fileinfo3 (ediff-get-session-objC elt))
(ediff-set-file-eqstatus fileinfo1 nil)
(ediff-set-file-eqstatus fileinfo2 nil)
(ediff-set-file-eqstatus fileinfo3 nil)
(ediff-mark-if-equal fileinfo1 fileinfo2)
(if (ediff-metajob3)
(progn
(ediff-mark-if-equal fileinfo1 fileinfo3)
(ediff-mark-if-equal fileinfo2 fileinfo3)))
(setq list (cdr list))))
(ediff-update-meta-buffer (current-buffer)))
;; mark files 1 and 2 as equal, if they are.
(defun ediff-mark-if-equal (fileinfo1 fileinfo2)
(get-buffer-create ediff-tmp-buffer)
(or (file-directory-p (car fileinfo1))
(file-directory-p (car fileinfo2))
(if (= (ediff-make-diff2-buffer
ediff-tmp-buffer (car fileinfo1) (car fileinfo2))
0)
(progn
(ediff-set-file-eqstatus fileinfo1 t)
(ediff-set-file-eqstatus fileinfo2 t)))))
;;; Local Variables:

View File

@ -1,6 +1,6 @@
;;; ediff-util.el --- the core commands and utilities of ediff
;; Copyright (C) 1994, 1995 Free Software Foundation, Inc.
;; Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
;; Author: Michael Kifer <kifer@cs.sunysb.edu>
@ -26,6 +26,11 @@
(require 'ediff-init)
(require 'ediff-mult)
;; Pacify compiler and avoid the need in checking for boundp
(defvar ediff-patch-diagnostics nil)
(defvar ediff-patchbufer nil)
;; end pacifier
;;; Functions
@ -35,9 +40,11 @@ This mode is entered through one of the following commands:
`ediff'
`ediff-files'
`ediff-buffers'
`ebuffers'
`ediff3'
`ediff-files3'
`ediff-buffers3'
`ebuffers3'
`ediff-merge'
`ediff-merge-files'
`ediff-merge-files-with-ancestor'
@ -176,6 +183,8 @@ 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)
(if (fboundp 'ediff-show-patch-diagnostics)
(define-key ediff-mode-map "P" 'ediff-show-patch-diagnostics))
(if ediff-3way-job
(progn
(define-key ediff-mode-map "wc" 'ediff-save-buffer)
@ -242,7 +251,7 @@ to invocation.")
(make-local-hook 'pre-command-hook)
(if (ediff-window-display-p)
(add-hook 'pre-command-hook 'ediff-spy-after-mouse))
(add-hook 'pre-command-hook 'ediff-spy-after-mouse nil t))
(setq ediff-mouse-pixel-position (mouse-pixel-position))
;; adjust for merge jobs
@ -273,7 +282,7 @@ to invocation.")
(insert-buffer buf)
(funcall (ediff-eval-in-buffer buf major-mode))
;; after Stig@hackvan.com
(add-hook 'local-write-file-hooks 'ediff-set-merge-mode)
(add-hook 'local-write-file-hooks 'ediff-set-merge-mode nil t)
)))
(setq buffer-read-only nil
ediff-buffer-A buffer-A
@ -740,8 +749,7 @@ Reestablish the default three-window display."
(if (and (ediff-buffer-live-p ediff-buffer-A)
(ediff-buffer-live-p ediff-buffer-B)
(or (not ediff-3way-job)
(ediff-buffer-live-p ediff-buffer-C))
)
(ediff-buffer-live-p ediff-buffer-C)))
(progn
(or no-rehighlight
(ediff-select-difference ediff-current-difference))
@ -1170,7 +1178,8 @@ This is especially useful when comparing buffers side-by-side."
(defun ediff-toggle-multiframe ()
"Switch from the multiframe display to single-frame display and back.
This is primarily for debugging, but one can use it for fun, too."
For a permanent change, set the variable `ediff-window-setup-function',
which see."
(interactive)
(ediff-barf-if-not-control-buffer)
(or (ediff-window-display-p)
@ -1381,7 +1390,7 @@ the width of the A/B/C windows."
;;BEG, END show the region to be positioned.
;;JOB-NAME holds ediff-job-name. Ediff-windows job positions regions
;;JOB-NAME holds ediff-job-name. The ediff-windows job positions regions
;;differently.
(defun ediff-position-region (beg end pos job-name)
(if (> end (point-max))
@ -1449,33 +1458,43 @@ the width of the A/B/C windows."
)))
;; region size coefficient is a coefficient by which to adjust scrolling
;; up/down of the window displaying buffer of type BUFTYPE.
;; The purpose of this coefficient is to make the windows scroll in sync, so
;; that it won't happen that one diff region is scrolled off while the other is
;; still seen.
;;
;; If the difference region is invalid, the coefficient is 1
(defun ediff-get-region-size-coefficient (buf-type op &optional n ctl-buf)
(ediff-eval-in-buffer (or ctl-buf ediff-control-buffer)
(let* ((func (cond ((eq op 'scroll-down) 'ediff-get-lines-to-region-start)
((eq op 'scroll-up) 'ediff-get-lines-to-region-end)
(t '(lambda (a b c) 0))))
(max-lines (max (funcall func 'A n ctl-buf)
(funcall func 'B n ctl-buf)
(if (ediff-buffer-live-p ediff-buffer-C)
(funcall func 'C n ctl-buf)
0))))
;; this covers the horizontal coefficient as well:
;; if max-lines = 0 then coef = 1
(if (> max-lines 0)
(/ (+ (funcall func buf-type n ctl-buf) 0.0)
(+ max-lines 0.0))
1)
)))
(if (ediff-valid-difference-p n)
(let* ((func (cond ((eq op 'scroll-down)
'ediff-get-lines-to-region-start)
((eq op 'scroll-up)
'ediff-get-lines-to-region-end)
(t '(lambda (a b c) 0))))
(max-lines (max (funcall func 'A n ctl-buf)
(funcall func 'B n ctl-buf)
(if (ediff-buffer-live-p ediff-buffer-C)
(funcall func 'C n ctl-buf)
0))))
;; this covers the horizontal coefficient as well:
;; if max-lines = 0 then coef = 1
(if (> max-lines 0)
(/ (+ (funcall func buf-type n ctl-buf) 0.0)
(+ max-lines 0.0))
1))
1)))
(defun ediff-next-difference (&optional arg)
"Advance to the next difference.
With a prefix argument, go back that many differences."
(interactive "P")
With a prefix argument, go forward that many differences."
(interactive "p")
(ediff-barf-if-not-control-buffer)
(if (< ediff-current-difference ediff-number-of-differences)
(let ((n (min ediff-number-of-differences
(+ ediff-current-difference (if arg arg 1))))
(+ ediff-current-difference arg)))
regexp-skip)
(or (>= n ediff-number-of-differences)
@ -1508,10 +1527,10 @@ With a prefix argument, go back that many differences."
(defun ediff-previous-difference (&optional arg)
"Go to the previous difference.
With a prefix argument, go back that many differences."
(interactive "P")
(interactive "p")
(ediff-barf-if-not-control-buffer)
(if (> ediff-current-difference -1)
(let ((n (max -1 (- ediff-current-difference (if arg arg 1))))
(let ((n (max -1 (- ediff-current-difference arg)))
regexp-skip)
(or (< n 0)
@ -1541,29 +1560,89 @@ With a prefix argument, go back that many differences."
(ediff-visible-region)
(error "At beginning of the difference list")))
;; The diff number is as perceived by the user (i.e., 1+ the internal
;; representation)
(defun ediff-jump-to-difference (difference-number)
"Go to the difference specified as a prefix argument."
"Go to the difference specified as a prefix argument.
If the prefix is negative, count differences from the end."
(interactive "p")
(ediff-barf-if-not-control-buffer)
(setq difference-number (1- difference-number))
(setq difference-number
(cond ((< difference-number 0)
(+ ediff-number-of-differences difference-number))
((> difference-number 0) (1- difference-number))
(t -1)))
;; -1 is allowed by ediff-unselect-and-select-difference --- it is the
;; position before the first one.
(if (and (>= difference-number -1)
(< difference-number (1+ ediff-number-of-differences)))
(<= difference-number ediff-number-of-differences))
(ediff-unselect-and-select-difference difference-number)
(error "Bad difference number, %d. Valid numbers are 1 to %d"
(1+ difference-number) ediff-number-of-differences)))
(error ediff-BAD-DIFF-NUMBER
this-command (1+ difference-number) ediff-number-of-differences)))
(defun ediff-jump-to-difference-at-point ()
(defun ediff-jump-to-difference-at-point (arg)
"Go to difference closest to the point in buffer A, B, or C.
The type of buffer depends on last command character \(a, b, or c\) that
invoked this command."
(interactive)
The buffer depends on last command character \(a, b, or c\) that invoked this
command. For instance, if the command was `ga' then the point value in buffer A
is used.
With a prefix argument, synchronize all files around the current point position
in the specified buffer."
(interactive "P")
(ediff-barf-if-not-control-buffer)
(let ((buf-type (ediff-char-to-buftype last-command-char)))
(ediff-jump-to-difference (ediff-diff-at-point buf-type))))
(let* ((buf-type (ediff-char-to-buftype last-command-char))
(buffer (ediff-get-buffer buf-type))
(pt (ediff-eval-in-buffer buffer (point)))
(diff-no (ediff-diff-at-point buf-type nil (if arg 'after)))
(past-last-diff (< ediff-number-of-differences diff-no))
(beg (if past-last-diff
(ediff-eval-in-buffer buffer (point-max))
(ediff-get-diff-posn buf-type 'beg (1- diff-no))))
ctl-wind wind-A wind-B wind-C
shift)
(if past-last-diff
(ediff-jump-to-difference -1)
(ediff-jump-to-difference diff-no))
(setq ctl-wind (selected-window)
wind-A ediff-window-A
wind-B ediff-window-B
wind-C ediff-window-C)
(if arg
(progn
(ediff-eval-in-buffer buffer
(setq shift (- beg pt)))
(select-window wind-A)
(if past-last-diff (goto-char (point-max)))
(condition-case nil
(backward-char shift) ; noerror, if beginning of buffer
(error))
(recenter)
(select-window wind-B)
(if past-last-diff (goto-char (point-max)))
(condition-case nil
(backward-char shift) ; noerror, if beginning of buffer
(error))
(recenter)
(if (window-live-p wind-C)
(progn
(select-window wind-C)
(if past-last-diff (goto-char (point-max)))
(condition-case nil
(backward-char shift) ; noerror, if beginning of buffer
(error))
(recenter)
))
(select-window ctl-wind)
))
))
;; find region most related to the current point position (or POS, if given)
(defun ediff-diff-at-point (buf-type &optional pos)
;; returns diff number as seen by the user (i.e., 1+ the internal
;; representation)
;; The optional argument WHICH-DIFF can be `after' or `before'. If `after',
;; find the diff after the point. If `before', find the diff before the
;; point. If the point is inside a diff, return that diff.
(defun ediff-diff-at-point (buf-type &optional pos which-diff)
(let ((buffer (ediff-get-buffer buf-type))
(ctl-buffer ediff-control-buffer)
(max-dif-num (1- ediff-number-of-differences))
@ -1584,10 +1663,18 @@ invoked this command."
end (ediff-get-diff-posn buf-type 'end diff-no ctl-buffer))
)
(if (< (abs (- pos prev-end))
(abs (- pos beg)))
diff-no
(1+ diff-no)) ; jump-to-diff works with diff nums higher by 1
;; boost diff-no by 1, if past the last diff region
(if (and (memq which-diff '(after before))
(> pos beg) (= diff-no max-dif-num))
(setq diff-no (1+ diff-no)))
(cond ((eq which-diff 'after) (1+ diff-no))
((eq which-diff 'before) diff-no)
((< (abs (count-lines pos (max 1 prev-end)))
(abs (count-lines pos (max 1 beg))))
diff-no) ; choose prev difference
(t
(1+ diff-no))) ; choose next difference
)))
@ -1607,8 +1694,9 @@ determine the source and the target buffers instead of the command keys."
(interactive "P")
(ediff-barf-if-not-control-buffer)
(or keys (setq keys (this-command-keys)))
(if (numberp arg)
(ediff-jump-to-difference arg))
(if (eq arg '-) (setq arg -1)) ; translate neg arg to -1
(if (numberp arg) (ediff-jump-to-difference arg))
(let* ((key1 (aref keys 0))
(key2 (aref keys 1))
(char1 (if (and ediff-xemacs-p (eventp key1)) (event-key key1) key1))
@ -1866,7 +1954,7 @@ a regular expression typed in by the user."
msg-connective alt-msg-connective alt-connective)
(cond
((or (and (eq ediff-skip-diff-region-function
'ediff-focus-on-regexp-matches-function)
ediff-focus-on-regexp-matches-function)
(eq last-command-char ?f))
(and (eq ediff-skip-diff-region-function
ediff-hide-regexp-matches-function)
@ -2063,13 +2151,13 @@ If it is t, they will be preserved unconditionally. A prefix argument,
temporarily reverses the meaning of this variable."
(interactive "P")
(ediff-barf-if-not-control-buffer)
(if (prog1
(y-or-n-p
(format "Quit this Ediff session%s? "
(if (ediff-buffer-live-p ediff-meta-buffer)
" & show containing session group" "")))
(message ""))
(ediff-really-quit reverse-default-keep-variants)))
(if (y-or-n-p (format "Quit this Ediff session%s? "
(if (ediff-buffer-live-p ediff-meta-buffer)
" & show containing session group" "")))
(progn
(message "")
(ediff-really-quit reverse-default-keep-variants))
(message "")))
;; Perform the quit operations.
@ -2258,7 +2346,7 @@ buffer in another session as well."
(buf-A-wind (ediff-get-visible-buffer-window buf-A))
(buf-B-wind (ediff-get-visible-buffer-window buf-B))
(buf-C-wind (ediff-get-visible-buffer-window buf-C))
(buf-patch ediff-patch-buf)
(buf-patch ediff-patchbufer)
(buf-patch-diag ediff-patch-diagnostics)
(buf-err ediff-error-buffer)
(buf-diff ediff-diff-buffer)
@ -2316,7 +2404,8 @@ Hit \\[ediff-recenter] to reset the windows afterward."
(ediff-barf-if-not-control-buffer)
(save-excursion
(ediff-skip-unsuitable-frames))
(with-output-to-temp-buffer " *ediff-info*"
(with-output-to-temp-buffer ediff-msg-buffer
(raise-frame (selected-frame))
(princ (ediff-version))
(princ "\n\n")
(ediff-eval-in-buffer ediff-buffer-A
@ -2525,13 +2614,14 @@ Hit \\[ediff-recenter] to reset the windows afterward."
(let (f)
(setq f (expand-file-name
(read-file-name
(format "%s%s: "
(format "%s%s "
prompt
(if default-file
(concat " (default " default-file ")")
""))
(cond (default-file
(concat " (default " default-file "):"))
;;((string-match "[?:!,;][ \t]*$" prompt) "")
(t (concat " (default " default-dir "):"))))
default-dir
default-file
(or default-file default-dir)
t ; must match, no-confirm
(if default-file (file-name-directory default-file))
)
@ -2601,9 +2691,7 @@ Hit \\[ediff-recenter] to reset the windows afterward."
;; file on disk, and attempt to remedy the situation if not.
;; Signal an error if we can't make them the same, or the user doesn't want
;; to do what is necessary to make them the same.
;; If file has file handlers (indicated by the optional arg), then we
;; offer to revert instead of saving. This is one difference with Emerge.
;; Another is that we always offer to revert obsolete files, whether they
;; Also, Ediff always offers to revert obsolete buffers, whether they
;; are modified or not.
(defun ediff-verify-file-buffer (&optional file-magic)
;; First check if the file has been modified since the buffer visited it.
@ -2611,21 +2699,19 @@ Hit \\[ediff-recenter] to reset the windows afterward."
(if (buffer-modified-p)
;; If buffer is not obsolete and is modified, offer to save
(if (yes-or-no-p
(format "Buffer out of sync with visited file. %s file %s? "
(if file-magic "Revert" "Save")
(format "Buffer out of sync with visited file. Save file %s? "
buffer-file-name))
(if (not file-magic)
(condition-case nil
(save-buffer)
;; for some reason, file-name-handlers append instead of
;; replacing, so we have to erase first.
(erase-buffer)
(revert-buffer t t))
(error "Buffer out of sync for file %s" buffer-file-name))
(error
(beep)
(message "Couldn't save %s" buffer-file-name)))
(error "Buffer is out of sync for file %s" buffer-file-name))
;; If buffer is not obsolete and is not modified, do nothing
nil)
;; If buffer is obsolete, offer to revert
(if (yes-or-no-p
(format "Buffer out of sync with visited file. Revert file %s? "
(format "Buffer is out of sync with visited file. REVERT file %s? "
buffer-file-name))
(progn
(if file-magic
@ -2776,16 +2862,17 @@ Without an argument, it saves customized diff argument, if available
))
;; Returns positions of difference sectors in the BUF-TYPE buffer.
;; BUF-TYPE should be a symbol -- `A', `B', or `C'.
;; POS is either `beg' or `end'--it specifies whether you want the position at
;; the beginning of a difference or at the end.
;;
;; The optional argument N says which difference (default:
;; `ediff-current-difference'). N is the internal difference number (1- what
;; the user sees). The optional argument CONTROL-BUF says
;; which control buffer is in effect in case it is not the current
;; buffer.
(defun ediff-get-diff-posn (buf-type pos &optional n control-buf)
"Returns positions of difference sectors in the BUF-TYPE buffer.
BUF-TYPE should be a symbol--either `A' or `B'.
POS is either `beg' or `end'--it specifies whether you want the position at the
beginning of a difference or at the end.
The optional argument N says which difference \(default:
`ediff-current-difference'\). The optional argument CONTROL-BUF says
which control buffer is in effect in case it is not the current
buffer."
(let (diff-overlay)
(or control-buf
(setq control-buf (current-buffer)))
@ -2794,8 +2881,8 @@ buffer."
(or n (setq n ediff-current-difference))
(if (or (< n 0) (>= n ediff-number-of-differences))
(if (> ediff-number-of-differences 0)
(error "Bad difference number, %d. Valid numbers are 1 to %d"
(1+ n) ediff-number-of-differences)
(error ediff-BAD-DIFF-NUMBER
this-command (1+ n) ediff-number-of-differences)
(error ediff-NO-DIFFERENCES)))
(setq diff-overlay (ediff-get-diff-overlay n buf-type)))
(if (not (ediff-buffer-live-p (ediff-overlay-buffer diff-overlay)))
@ -2957,16 +3044,18 @@ Checks if overlay's buffer exists."
(setq overl
(if ediff-xemacs-p
(make-extent beg end buff)
;; don't advance front, but advance rear
;; advance front and rear of the overlay
(make-overlay beg end buff nil 'rear-advance)))
(if ediff-emacs-p
(ediff-overlay-put overl 'evaporate nil) ; don't detach
(ediff-overlay-put overl 'detachable nil) ; don't detach
;; don't advance front, but advance rear
(ediff-overlay-put overl 'start-open nil)
(ediff-overlay-put overl 'end-open nil))
;; never detach
(ediff-overlay-put
overl (if ediff-emacs-p 'evaporate 'detachable) nil)
;; make vip-minibuffer-overlay open-ended
;; In emacs, it is made open ended at creation time
(if ediff-xemacs-p
(progn
(ediff-overlay-put overl 'start-open nil)
(ediff-overlay-put overl 'end-open nil)))
(ediff-overlay-put overl 'ediff-diff-num 0)
overl))))
@ -3265,8 +3354,8 @@ Mail anyway? (y or n) ")
(remove-hook post-hook 'ediff-calc-command-time)
(setq ediff-command-begin-time '(0 0 0))
(message "Ediff profiling disabled"))
(add-hook pre-hook 'ediff-save-time t)
(add-hook post-hook 'ediff-calc-command-time)
(add-hook pre-hook 'ediff-save-time t t)
(add-hook post-hook 'ediff-calc-command-time nil t)
(message "Ediff profiling enabled"))))
(defun ediff-print-diff-vector (diff-vector-var)

View File

@ -1,6 +1,6 @@
;;; ediff-vers.el --- version control interface to Ediff
;;; Copyright (C) 1994, 1995 Free Software Foundation, Inc.
;;; Copyright (C) 1995, 1996 Free Software Foundation, Inc.
;; Author: Michael Kifer <kifer@cs.sunysb.edu>
@ -23,6 +23,20 @@
;;; Code:
;; Compiler pacifier
(defvar rcs-default-co-switches)
(defvar sc-mode)
(defvar cvs-shell)
(defvar cvs-program)
(defvar cvs-cookie-handle)
(eval-when-compile
(load "pcl-cvs" 'noerror)
(load "rcs" 'noerror)
(load "generic-sc" 'noerror)
(load "vc" 'noerror))
;; end pacifier
;; VC.el support
(defun vc-ediff-internal (rev1 rev2 &optional startup-hooks)

View File

@ -1,6 +1,6 @@
;;; ediff-wind.el --- window manipulation utilities
;; Copyright (C) 1994, 1995 Free Software Foundation, Inc.
;; Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
;; Author: Michael Kifer <kifer@cs.sunysb.edu>
@ -25,6 +25,18 @@
(require 'ediff-init)
;; Compiler pacifier
(defvar icon-title-format)
(defvar top-toolbar-height)
(defvar bottom-toolbar-height)
(defvar left-toolbar-height)
(defvar right-toolbar-height)
(defvar left-toolbar-width)
(defvar right-toolbar-width)
(defvar default-menubar)
(defvar frame-icon-title-format)
;; end pacifier
(defvar ediff-window-setup-function (if (ediff-window-display-p)
'ediff-setup-windows-multiframe
@ -93,7 +105,6 @@ In this case, Ediff will use those frames to display these buffers.")
'(vertical-scroll-bars . nil) ; Emacs only
'(scrollbar-width . 0) ; XEmacs only
'(menu-bar-lines . 0) ; Emacs only
'(visibility . nil) ; doesn't work for XEmacs yet
;; don't lower and auto-raise
'(auto-lower . nil)
'(auto-raise . t)
@ -395,13 +406,15 @@ into icons, regardless of the window manager.")
(defun ediff-setup-windows-multiframe-merge (buf-A buf-B buf-C control-buf)
;;; Algorithm:
;;; If A and B are in the same frame but C's frame is different--- use one
;;; frame for A and B and use a separate frame for C.
;;; If C's frame is non-existent, then: if the first suitable
;;; non-dedicated frame is different from A&B's, then use it for C.
;;; Otherwise, put A,B, and C in one frame.
;;; If buffers A, B, C are is separate frames, use them to display these
;;; buffers.
;;; 1. Never use frames that have dedicated windows in them---it is bad to
;;; destroy dedicated windows.
;;; 2. If A and B are in the same frame but C's frame is different--- use one
;;; frame for A and B and use a separate frame for C.
;;; 3. If C's frame is non-existent, then: if the first suitable
;;; non-dedicated frame is different from A&B's, then use it for C.
;;; Otherwise, put A,B, and C in one frame.
;;; 4. If buffers A, B, C are is separate frames, use them to display these
;;; buffers.
;; Skip dedicated or iconified frames.
;; Unsplittable frames are taken care of later.
@ -423,13 +436,22 @@ into icons, regardless of the window manager.")
(orig-wind (selected-window))
(orig-frame (selected-frame))
(use-same-frame (or force-one-frame
;; A and C must be in one frame
(eq frame-A (or frame-C orig-frame))
;; B and C must be in one frame
(eq frame-B (or frame-C orig-frame))
;; A or B is not visible
(not (frame-live-p frame-A))
(not (frame-live-p frame-B))
;; A or B is not suitable for display
(not (ediff-window-ok-for-display wind-A))
(not (ediff-window-ok-for-display wind-B))
;; A and B in the same frame, and no good frame
;; for C
(and (eq frame-A frame-B)
(not (frame-live-p frame-C)))
))
;; use-same-frame-for-AB implies wind A and B are ok for display
(use-same-frame-for-AB (and (not use-same-frame)
(eq frame-A frame-B)))
(merge-window-share (ediff-eval-in-buffer control-buf
@ -440,37 +462,42 @@ into icons, regardless of the window manager.")
;; buf-A on its own
(if (and (window-live-p wind-A)
(null use-same-frame)
(null use-same-frame) ; implies wind-A is suitable
(null use-same-frame-for-AB))
(progn
(progn ; bug A on its own
;; buffer buf-A is seen in live wind-A
(select-window wind-A)
(delete-other-windows)
(switch-to-buffer buf-A)
(setq wind-A (selected-window))
(setq done-A t)))
;; buf-B on its own
(if (and (window-live-p wind-B) (null use-same-frame)) ; buf B on its own
(progn
(if (and (window-live-p wind-B)
(null use-same-frame) ; implies wind-B is suitable
(null use-same-frame-for-AB))
(progn ; buf B on its own
;; buffer buf-B is seen in live wind-B
(select-window wind-B)
(delete-other-windows)
(switch-to-buffer buf-B)
(setq wind-B (selected-window))
(setq done-B t)))
;; buf-C on its own
(if (and (window-live-p wind-C) (null use-same-frame)) ; buf C on its own
(if (and (window-live-p wind-C)
(ediff-window-ok-for-display wind-C)
(null use-same-frame)) ; buf C on its own
(progn
;; buffer buf-C is seen in live wind-C
(select-window wind-C)
(delete-other-windows)
(switch-to-buffer buf-C)
(setq wind-C (selected-window))
(setq done-C t)))
(if use-same-frame-for-AB
(if (and use-same-frame-for-AB ; implies wind A and B are suitable
(window-live-p wind-A))
(progn
(select-frame frame-A)
(switch-to-buffer buf-A)
;; wind-A must already be displaying buf-A
(select-window wind-A)
(delete-other-windows)
(setq wind-A (selected-window))
@ -484,31 +511,15 @@ into icons, regardless of the window manager.")
done-B t)))
(if use-same-frame
(let ((curr-frame (selected-frame))
(window-min-height 1))
(let ((window-min-height 1))
;; avoid dedicated and non-splittable windows
(ediff-skip-unsuitable-frames)
(or (eq curr-frame (selected-frame))
(setq wind-A nil
wind-B nil
wind-C nil
orig-wind (selected-window)))
;; set the right frame
(cond (wind-A (select-window wind-A))
(wind-B (select-window wind-B))
(wind-C (select-window wind-C))
(t (select-window orig-wind)))
(delete-other-windows)
(setq merge-window-lines
(max 2 (round (* (window-height) merge-window-share))))
(switch-to-buffer buf-A)
(setq wind-A (selected-window))
;; XEmacs used to have a lot of trouble with display
;; It did't set things right unless we told it to catch breath
;;(if ediff-xemacs-p (sit-for 0))
(split-window-vertically
(max 2 (- (window-height) merge-window-lines)))
(if (eq (selected-window) wind-A)
@ -529,23 +540,32 @@ into icons, regardless of the window manager.")
done-C t)
))
(or done-A ; Buf A to be set in its own frame
(progn ; It was not set up yet as it wasn't visible
(or done-A ; Buf A to be set in its own frame,
;;; or it was set before because use-same-frame = 1
(progn
;; Buf-A was not set up yet as it wasn't visible,
;; and use-same-frame = nil, use-same-frame-for-AB = nil
(select-window orig-wind)
(delete-other-windows)
(switch-to-buffer buf-A)
(setq wind-A (selected-window))
))
(or done-B ; Buf B to be set in its own frame
(progn ; It was not set up yet as it wasn't visible
(or done-B ; Buf B to be set in its own frame,
;;; or it was set before because use-same-frame = 1
(progn
;; Buf-B was not set up yet as it wasn't visible
;; and use-same-frame = nil, use-same-frame-for-AB = nil
(select-window orig-wind)
(delete-other-windows)
(switch-to-buffer buf-B)
(setq wind-B (selected-window))
))
(or done-C ; Buf C to be set in its own frame.
(progn ; It was not set up yet as it wasn't visible
(or done-C ; Buf C to be set in its own frame,
;;; or it was set before because use-same-frame = 1
(progn
;; Buf-C was not set up yet as it wasn't visible
;; and use-same-frame = nil
(select-window orig-wind)
(delete-other-windows)
(switch-to-buffer buf-C)
@ -602,9 +622,12 @@ into icons, regardless of the window manager.")
(orig-wind (selected-window))
(use-same-frame (or force-one-frame
(eq frame-A frame-B)
(not (ediff-window-ok-for-display wind-A))
(not (ediff-window-ok-for-display wind-B))
(if three-way-comparison
(or (eq frame-A frame-C)
(eq frame-B frame-C)
(not (ediff-window-ok-for-display wind-C))
(not (frame-live-p frame-A))
(not (frame-live-p frame-B))
(not (frame-live-p frame-C))))
@ -628,53 +651,36 @@ into icons, regardless of the window manager.")
(if (and (window-live-p wind-A) (null use-same-frame)) ; buf-A on its own
(progn
(select-window wind-A)
;; buffer buf-A is seen in live wind-A
(select-window wind-A) ; must be displaying buf-A
(delete-other-windows)
(switch-to-buffer buf-A)
(setq wind-A (selected-window))
(setq done-A t)))
(if (and (window-live-p wind-B) (null use-same-frame)) ; buf B on its own
(progn
(select-window wind-B)
;; buffer buf-B is seen in live wind-B
(select-window wind-B) ; must be displaying buf-B
(delete-other-windows)
(switch-to-buffer buf-B)
(setq wind-B (selected-window))
(setq done-B t)))
(if (and (window-live-p wind-C) (null use-same-frame)) ; buf C on its own
(progn
(select-window wind-C)
;; buffer buf-C is seen in live wind-C
(select-window wind-C) ; must be displaying buf-C
(delete-other-windows)
(switch-to-buffer buf-C)
(setq wind-C (selected-window))
(setq done-C t)))
(if use-same-frame
(let ((curr-frame (selected-frame))
;; this affects 3way setups only
wind-width-or-height)
(let (wind-width-or-height) ; this affects 3way setups only
;; avoid dedicated and non-splittable windows
(ediff-skip-unsuitable-frames)
(or (eq curr-frame (selected-frame))
(setq wind-A nil
wind-B nil
wind-C nil
orig-wind (selected-window)))
;; set the right frame
(cond (wind-A (select-window wind-A))
(wind-B (select-window wind-B))
(wind-C (select-window wind-C))
(t (select-window orig-wind)))
(delete-other-windows)
(switch-to-buffer buf-A)
(setq wind-A (selected-window))
;; XEmacs used to have a lot of trouble with display
;; It didn't set things right unless we told it to catch breath
;;(if ediff-xemacs-p (sit-for 0))
(if three-way-comparison
(setq wind-width-or-height
(/
@ -702,14 +708,20 @@ into icons, regardless of the window manager.")
))
(or done-A ; Buf A to be set in its own frame
(progn ; It was not set up yet as it wasn't visible
;;; or it was set before because use-same-frame = 1
(progn
;; Buf-A was not set up yet as it wasn't visible,
;; and use-same-frame = nil
(select-window orig-wind)
(delete-other-windows)
(switch-to-buffer buf-A)
(setq wind-A (selected-window))
))
(or done-B ; Buf B to be set in its own frame
(progn ; It was not set up yet as it wasn't visible
;;; or it was set before because use-same-frame = 1
(progn
;; Buf-B was not set up yet as it wasn't visible,
;; and use-same-frame = nil
(select-window orig-wind)
(delete-other-windows)
(switch-to-buffer buf-B)
@ -718,7 +730,10 @@ into icons, regardless of the window manager.")
(if three-way-comparison
(or done-C ; Buf C to be set in its own frame
(progn ; It was not set up yet as it wasn't visible
;;; or it was set before because use-same-frame = 1
(progn
;; Buf-C was not set up yet as it wasn't visible,
;; and use-same-frame = nil
(select-window orig-wind)
(delete-other-windows)
(switch-to-buffer buf-C)
@ -734,8 +749,8 @@ into icons, regardless of the window manager.")
designated-minibuffer-frame
(window-frame (minibuffer-window frame-A))))
;; It is unlikely that we'll implement ediff-windows that would compare
;; 3 windows at once. So, we don't use buffer C here.
;; It is unlikely that we'll implement a version of ediff-windows that
;; would compare 3 windows at once. So, we don't use buffer C here.
(if ediff-windows-job
(progn
(set-window-start wind-A wind-A-start)
@ -744,14 +759,14 @@ into icons, regardless of the window manager.")
(ediff-setup-control-frame control-buf designated-minibuffer-frame)
))
;; skip unsplittable and dedicated windows
;; skip unsplittable frames and frames that have dedicated windows.
;; create a new splittable frame if none is found
(defun ediff-skip-unsuitable-frames (&optional ok-unsplittable)
(if (ediff-window-display-p)
(let (last-window)
(while (and (not (eq (selected-window) last-window))
(or
(window-dedicated-p (selected-window))
(ediff-frame-has-dedicated-windows (selected-frame))
(ediff-frame-iconified-p (selected-frame))
(< (frame-height (selected-frame))
(* 3 window-min-height))
@ -765,14 +780,41 @@ into icons, regardless of the window manager.")
(if (eq (selected-window) last-window)
;; fed up, no appropriate frame
(progn
;;(redraw-display)
(select-frame (make-frame '((unsplittable)))))))))
(defun ediff-frame-has-dedicated-windows (frame)
(let ((cur-fr (selected-frame))
ans)
(select-frame frame)
(walk-windows
(function (lambda (wind)
(if (window-dedicated-p wind)
(setq ans t))))
'ignore-minibuffer
frame)
(select-frame cur-fr)
ans))
;; window is ok, if it is only one window on the frame, not counting the
;; minibuffer, or none of the frame's windows is dedicated.
;; The idea is that it is bad to destroy dedicated windows while creating an
;; ediff window setup
(defun ediff-window-ok-for-display (wind)
(and
(window-live-p wind)
(or
;; only one window
(eq wind (next-window wind 'ignore-minibuffer (window-frame wind)))
;; none is dedicated
(not (ediff-frame-has-dedicated-windows (window-frame wind)))
)))
;; Prepare or refresh control frame
(defun ediff-setup-control-frame (ctl-buffer designated-minibuffer-frame)
(let ((window-min-height 1)
ctl-frame-iconified-p dont-iconify-ctl-frame deiconify-ctl-frame
ctl-frame old-ctl-frame lines user-grabbed-mouse
ctl-frame old-ctl-frame lines
;; user-grabbed-mouse
fheight fwidth adjusted-parameters)
(ediff-eval-in-buffer ctl-buffer
@ -813,7 +855,6 @@ into icons, regardless of the window manager.")
fheight lines
fwidth (+ (ediff-help-message-line-length) 2)
adjusted-parameters (append (list
'(visibility . t)
;; possibly change surrogate minibuffer
(cons 'minibuffer
(minibuffer-window
@ -851,6 +892,7 @@ into icons, regardless of the window manager.")
(goto-char (point-min))
(modify-frame-parameters ctl-frame adjusted-parameters)
(make-frame-visible ctl-frame)
;; This works around a bug in 19.25 and earlier. There, if frame gets
;; iconified, the current buffer changes to that of the frame that
@ -865,11 +907,9 @@ into icons, regardless of the window manager.")
((or deiconify-ctl-frame (not ctl-frame-iconified-p))
(raise-frame ctl-frame)))
(if ediff-xemacs-p
(set-window-buffer-dedicated (selected-window) ctl-buffer)
(set-window-dedicated-p (selected-window) t))
(set-window-dedicated-p (selected-window) t)
;; resynch so the cursor will move to control frame
;; synchronize so the cursor will move to control frame
;; per RMS suggestion
(if (ediff-window-display-p)
(let ((count 7))
@ -886,8 +926,8 @@ into icons, regardless of the window manager.")
(if ediff-xemacs-p
(ediff-eval-in-buffer ctl-buffer
(make-local-variable 'select-frame-hook)
(add-hook 'select-frame-hook 'ediff-xemacs-select-frame-hook)
(make-local-hook 'select-frame-hook)
(add-hook 'select-frame-hook 'ediff-xemacs-select-frame-hook nil t)
))
(ediff-eval-in-buffer ctl-buffer
@ -1021,7 +1061,7 @@ It assumes that it is called from within the control buffer."
(setq mode-line-format
(list (if (ediff-narrow-control-frame-p) " " "-- ")
mode-line-buffer-identification
" Howdy!"))
" Quick Help"))
;; control buffer id
(setq mode-line-buffer-identification
(if (ediff-narrow-control-frame-p)
@ -1072,15 +1112,16 @@ It assumes that it is called from within the control buffer."
(defun ediff-refresh-control-frame ()
(setq frame-title-format (ediff-make-narrow-control-buffer-id)
frame-icon-title-format (ediff-make-narrow-control-buffer-id) ; XEmacs
icon-title-format (ediff-make-narrow-control-buffer-id)) ; Emacs
;; the emacs part will be modified once the 'name and 'title
;; frame parameters are separated
(if ediff-emacs-p
;; set frame/icon titles for Emacs
(modify-frame-parameters
ediff-control-frame
(list (cons 'name (ediff-make-narrow-control-buffer-id))))
(list (cons 'title (ediff-make-base-title))
(cons 'icon-name (ediff-make-narrow-control-buffer-id))
))
;; set frame/icon titles for XEmacs
(setq frame-title-format (ediff-make-base-title)
frame-icon-title-format (ediff-make-narrow-control-buffer-id))
;; force an update of the frame title
(modify-frame-parameters ediff-control-frame '(()))))
@ -1089,9 +1130,7 @@ It assumes that it is called from within the control buffer."
(concat
(if skip-name
" "
(concat
(cdr (assoc 'name ediff-control-frame-parameters))
ediff-control-buffer-suffix))
(ediff-make-base-title))
(cond ((< ediff-current-difference 0)
(format " _/%d" ediff-number-of-differences))
((>= ediff-current-difference ediff-number-of-differences)
@ -1100,6 +1139,11 @@ It assumes that it is called from within the control buffer."
(format " %d/%d"
(1+ ediff-current-difference)
ediff-number-of-differences)))))
(defun ediff-make-base-title ()
(concat
(cdr (assoc 'name ediff-control-frame-parameters))
ediff-control-buffer-suffix))
(defun ediff-make-wide-control-buffer-id ()
(cond ((< ediff-current-difference 0)
@ -1122,8 +1166,8 @@ It assumes that it is called from within the control buffer."
(get-buffer-window buff t)
(get-buffer-window buff 'visible))))
;;; Functions to decide when to redraw windows
;;; Functions to decide when to redraw windows
(defun ediff-keep-window-config (control-buf)
(and (eq control-buf (current-buffer))
@ -1152,6 +1196,11 @@ It assumes that it is called from within the control buffer."
ediff-wide-display-p)))))))
;;; Local Variables:
;;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun)
;;; eval: (put 'ediff-eval-in-buffer 'lisp-indent-hook 1)
;;; End:
(provide 'ediff-wind)

View File

@ -1,13 +1,14 @@
;;; ediff.el --- a comprehensive visual interface to diff & patch
;; Copyright (C) 1994, 1995 Free Software Foundation, Inc.
;; Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
;; Author: Michael Kifer <kifer@cs.sunysb.edu>
;; Created: February 2, 1994
;; Keywords: comparing, merging, patching, version control.
(defconst ediff-version "2.54" "The current version of Ediff")
(defconst ediff-date "February 14, 1996" "Date of last update")
(defconst ediff-version "2.61" "The current version of Ediff")
(defconst ediff-date "June 10, 1996" "Date of last update")
;; This file is part of GNU Emacs.
@ -29,7 +30,7 @@
;;; Commentary:
;; Never read that diff output again!
;; Apply patch selectively, like a pro!
;; Apply patch interactively!
;; Merge with ease!
;; This package provides a convenient way of simultaneous browsing through
@ -58,7 +59,7 @@
;; files with their older versions. Ediff can also work with remote and
;; compressed files. Details are given below.
;; Finally, Ediff supports directory-level comparison and merging operations.
;; Finally, Ediff supports directory-level comparison, merging and patching.
;; See the on-line manual for details.
;; This package builds upon the ideas borrowed from emerge.el and several
@ -106,8 +107,15 @@
;;; Code:
(require 'ediff-init)
;; ediff-mult is always required, because of the registry stuff
(require 'ediff-mult)
(eval-when-compile
(load "dired")
(load-file "./ediff-ptch.el")
(load-file "./ediff-vers.el")
(load "pcl-cvs" 'noerror))
(defvar ediff-use-last-dir nil
"*If t, Ediff uses previous directory as default when reading file name.")
@ -119,148 +127,14 @@
"Last directory used by an Ediff command for file-C.")
(defvar ediff-last-dir-ancestor nil
"Last directory used by an Ediff command for the ancestor file.")
(defvar ediff-last-dir-patch nil
"Last directory used by an Ediff command for file to patch.")
;;; Patching
;; Some defvars to reduce the number of compiler warnings
(defvar cvs-cookie-handle)
(defvar ediff-last-dir-patch)
(defvar ediff-patch-default-directory)
;; end of compiler pacifier
(defvar ediff-backup-extension
(if (memq system-type '(vax-vms axp-vms emx ms-dos windows-nt windows-95))
"_orig" ".orig")
"Default backup extension for the patch program.")
;;;###autoload
(defun ediff-patch-file (source-filename &optional startup-hooks job-name)
"Run Ediff by patching SOURCE-FILENAME."
;; This now returns the control buffer
(interactive
(list (ediff-read-file-name
"File to patch"
(if ediff-use-last-dir
ediff-last-dir-patch
default-directory)
(ediff-get-default-file-name))))
(setq source-filename (expand-file-name source-filename))
(ediff-get-patch-buffer
(if (eq job-name 'ediff-patch-buffer)
(ediff-eval-in-buffer (get-file-buffer source-filename)
default-directory)
(file-name-directory source-filename)))
(let* ((backup-extension
;; if the user specified a -b option, extract the backup
;; extension from there; else use ediff-backup-extension
(substring ediff-patch-options
(if (string-match "-b[ \t]+" ediff-patch-options)
(match-end 0) 0)
(if (string-match "-b[ \t]+[^ \t]+" ediff-patch-options)
(match-end 0) 0)))
(shell-file-name ediff-shell)
;; ediff-find-file may use a temp file to do the patch
;; so, we save source-filename and true-source-filename as a var
;; that initially is source-filename but may be changed to a temp
;; file for the purpose of patching.
(true-source-filename source-filename)
(target-filename source-filename)
target-buf buf-to-patch file-name-magic-p ctl-buf backup-style)
;; if the user didn't specify a backup extension, use
;; ediff-backup-extension
(if (string= backup-extension "")
(setq backup-extension ediff-backup-extension))
(if (string-match "-V" ediff-patch-options)
(error
"Ediff doesn't take the -V option in `ediff-patch-options'--sorry"))
;; Make a temp file, if source-filename has a magic file handler (or if
;; it is handled via auto-mode-alist and similar magic).
;; Check if there is a buffer visiting source-filename and if they are in
;; sync; arrange for the deletion of temp file.
(ediff-find-file 'true-source-filename 'buf-to-patch
'ediff-last-dir-patch 'startup-hooks)
;; Check if source file name has triggered black magic, such as file name
;; handlers or auto mode alist, and make a note of it.
;; true-source-filename should be either the original name or a
;; temporary file where we put the after-product of the file handler.
(setq file-name-magic-p (not (equal (file-truename true-source-filename)
(file-truename source-filename))))
;; Checkout orig file, if necessary, so that the patched file could be
;; checked back in.
(if (ediff-file-checked-in-p (buffer-file-name buf-to-patch))
(ediff-toggle-read-only buf-to-patch))
(ediff-eval-in-buffer ediff-patch-diagnostics
(message "Applying patch ... ")
;; fix environment for gnu patch, so it won't make numbered extensions
(setq backup-style (getenv "VERSION_CONTROL"))
(setenv "VERSION_CONTROL" nil)
;; always pass patch the -f option, so it won't ask any questions
(shell-command-on-region
(point-min) (point-max)
(format "%s -f %s -b %s %s"
ediff-patch-program ediff-patch-options
backup-extension
(expand-file-name true-source-filename))
t)
;; restore environment for gnu patch
(setenv "VERSION_CONTROL" backup-style))
;;(message "Applying patch ... done")(sit-for 0)
(switch-to-buffer ediff-patch-diagnostics)
(sit-for 0) ; synchronize - let the user see diagnostics
(or (file-exists-p (concat true-source-filename backup-extension))
(error "Patch failed or didn't modify the original file"))
;; If black magic is involved, apply patch to a temp copy of the
;; file. Otherwise, apply patch to the orig copy. If patch is applied
;; to temp copy, we name the result old-name_patched for local files
;; and temp-copy_patched for remote files. The orig file name isn't
;; changed, and the temp copy of the original is later deleted.
;; Without magic, the original file is renamed (usually into
;; old-name_orig) and the result of patching will have the same name as
;; the original.
(if (not file-name-magic-p)
(ediff-eval-in-buffer buf-to-patch
(set-visited-file-name (concat source-filename backup-extension))
(set-buffer-modified-p nil))
;; Black magic in effect.
;; If orig file was remote, put the patched file in the temp directory.
;; If orig file is local, put the patched file in the directory of
;; the orig file.
(setq target-filename
(concat
(if (ediff-file-remote-p (file-truename source-filename))
true-source-filename
source-filename)
"_patched"))
(rename-file true-source-filename target-filename t)
;; arrange that the temp copy of orig will be deleted
(rename-file (concat true-source-filename backup-extension)
true-source-filename t))
;; make orig buffer read-only
(setq startup-hooks
(cons 'ediff-set-read-only-in-buf-A startup-hooks))
;; set up a buf for the patched file
(setq target-buf (find-file-noselect target-filename))
(setq ctl-buf
(ediff-buffers-internal
buf-to-patch target-buf nil
startup-hooks (or job-name 'ediff-patch-file)))
(bury-buffer ediff-patch-diagnostics)
(message "Patch diagnostics are available in buffer %s"
(buffer-name ediff-patch-diagnostics))
ctl-buf))
;; Used as a startup hook to set `_orig' patch file read-only.
(defun ediff-set-read-only-in-buf-A ()
(ediff-eval-in-buffer ediff-buffer-A
@ -278,11 +152,6 @@
(file-name-nondirectory (buffer-file-name (current-buffer))))
))
;;;###autoload
(defalias 'epatch 'ediff-patch-file)
;;;###autoload
(defalias 'epatch-buffer 'ediff-patch-buffer)
;;; Compare files/buffers
;;;###autoload
@ -465,9 +334,12 @@
(save-window-excursion (other-window 1))
(ediff-other-buffer bf))
t))))
(or job-name (setq job-name 'ediff-buffers))
(ediff-buffers-internal buffer-A buffer-B nil startup-hooks job-name))
;;;###autoload
(defalias 'ebuffers 'ediff-buffers)
;;;###autoload
(defun ediff-buffers3 (buffer-A buffer-B buffer-C
@ -492,9 +364,11 @@
(ediff-other-buffer (list bf bff)))
t)
)))
(or job-name (setq job-name 'ediff-buffers3))
(ediff-buffers-internal buffer-A buffer-B buffer-C startup-hooks job-name))
;;;###autoload
(defalias 'ebuffers3 'ediff-buffers3)
@ -559,18 +433,18 @@
(defun ediff-directories (dir1 dir2 regexp)
"Run Ediff on a pair of directories, DIR1 and DIR2, comparing files that have
the same name in both. The third argument, REGEXP, is a regular expression that
further filters the file names."
can be used to filter out certain file names."
(interactive
(let ((dir-A (ediff-get-default-directory-name))
f)
(list (setq f (ediff-read-file-name "Directory A to compare" dir-A nil))
(ediff-read-file-name "Directory B to compare"
(list (setq f (ediff-read-file-name "Directory A to compare:" dir-A nil))
(ediff-read-file-name "Directory B to compare:"
(if ediff-use-last-dir
ediff-last-dir-B
(ediff-strip-last-dir f))
nil)
(read-string "Filter through regular expression: "
nil ediff-filtering-regexp-history)
nil 'ediff-filtering-regexp-history)
)))
(ediff-directories-internal
dir1 dir2 nil regexp 'ediff-files 'ediff-directories
@ -588,9 +462,9 @@ names. Only the files that are under revision control are taken into account."
(interactive
(let ((dir-A (ediff-get-default-directory-name)))
(list (ediff-read-file-name
"Directory to compare with revision" dir-A nil)
"Directory to compare with revision:" dir-A nil)
(read-string "Filter through regular expression: "
nil ediff-filtering-regexp-history)
nil 'ediff-filtering-regexp-history)
)))
(ediff-directory-revisions-internal
dir1 regexp 'ediff-revision 'ediff-directory-revisions
@ -604,23 +478,23 @@ names. Only the files that are under revision control are taken into account."
(defun ediff-directories3 (dir1 dir2 dir3 regexp)
"Run Ediff on three directories, DIR1, DIR2, and DIR3, comparing files that
have the same name in all three. The last argument, REGEXP, is a regular
expression that further filters the file names."
expression that can be used to filter out certain file names."
(interactive
(let ((dir-A (ediff-get-default-directory-name))
f)
(list (setq f (ediff-read-file-name "Directory A to compare" dir-A nil))
(setq f (ediff-read-file-name "Directory B to compare"
(list (setq f (ediff-read-file-name "Directory A to compare:" dir-A nil))
(setq f (ediff-read-file-name "Directory B to compare:"
(if ediff-use-last-dir
ediff-last-dir-B
(ediff-strip-last-dir f))
nil))
(ediff-read-file-name "Directory C to compare"
(ediff-read-file-name "Directory C to compare:"
(if ediff-use-last-dir
ediff-last-dir-C
(ediff-strip-last-dir f))
nil)
(read-string "Filter through regular expression: "
nil ediff-filtering-regexp-history)
nil 'ediff-filtering-regexp-history)
)))
(ediff-directories-internal
dir1 dir2 dir3 regexp 'ediff-files3 'ediff-directories3
@ -633,18 +507,18 @@ expression that further filters the file names."
(defun ediff-merge-directories (dir1 dir2 regexp)
"Run Ediff on a pair of directories, DIR1 and DIR2, merging files that have
the same name in both. The third argument, REGEXP, is a regular expression that
further filters the file names."
can be used to filter out certain file names."
(interactive
(let ((dir-A (ediff-get-default-directory-name))
f)
(list (setq f (ediff-read-file-name "Directory A to merge" dir-A nil))
(ediff-read-file-name "Directory B to merge"
(list (setq f (ediff-read-file-name "Directory A to merge:" dir-A nil))
(ediff-read-file-name "Directory B to merge:"
(if ediff-use-last-dir
ediff-last-dir-B
(ediff-strip-last-dir f))
nil)
(read-string "Filter through regular expression: "
nil ediff-filtering-regexp-history)
nil 'ediff-filtering-regexp-history)
)))
(ediff-directories-internal
dir1 dir2 nil regexp 'ediff-merge-files 'ediff-merge-directories
@ -654,29 +528,31 @@ further filters the file names."
(defalias 'edirs-merge 'ediff-merge-directories)
;;;###autoload
(defun ediff-merge-directories-with-ancestor (dir1 dir2 dir3 regexp)
"Run Ediff on a pair of directories, DIR1 and DIR2, merging files that have
the same name in both. The third argument, REGEXP, is a regular expression that
further filters the file names."
(defun ediff-merge-directories-with-ancestor (dir1 dir2 ancestor-dir regexp)
"Merge files in directories DIR1 and DIR2 using files in ANCESTOR-DIR as ancestors.
Ediff merges files that have identical names in DIR1, DIR2. If a pair of files
in DIR1 and DIR2 doesn't have an ancestor in ANCESTOR-DIR, Ediff will merge
without ancestor. The fourth argument, REGEXP, is a regular expression that
can be used to filter out certain file names."
(interactive
(let ((dir-A (ediff-get-default-directory-name))
f)
(list (setq f (ediff-read-file-name "Directory A to merge" dir-A nil))
(setq f (ediff-read-file-name "Directory B to merge"
(list (setq f (ediff-read-file-name "Directory A to merge:" dir-A nil))
(setq f (ediff-read-file-name "Directory B to merge:"
(if ediff-use-last-dir
ediff-last-dir-B
(ediff-strip-last-dir f))
nil))
(ediff-read-file-name "Ancestor directory: "
(ediff-read-file-name "Ancestor directory:"
(if ediff-use-last-dir
ediff-last-dir-C
(ediff-strip-last-dir f))
nil)
(read-string "Filter through regular expression: "
nil ediff-filtering-regexp-history)
nil 'ediff-filtering-regexp-history)
)))
(ediff-directories-internal
dir1 dir2 dir3 regexp
dir1 dir2 ancestor-dir regexp
'ediff-merge-files-with-ancestor 'ediff-merge-directories-with-ancestor
))
@ -688,9 +564,9 @@ names. Only the files that are under revision control are taken into account."
(interactive
(let ((dir-A (ediff-get-default-directory-name)))
(list (ediff-read-file-name
"Directory to merge with revisions" dir-A nil)
"Directory to merge with revisions:" dir-A nil)
(read-string "Filter through regular expression: "
nil ediff-filtering-regexp-history)
nil 'ediff-filtering-regexp-history)
)))
(ediff-directory-revisions-internal
dir1 regexp 'ediff-merge-revisions 'ediff-merge-directory-revisions
@ -707,9 +583,9 @@ names. Only the files that are under revision control are taken into account."
(interactive
(let ((dir-A (ediff-get-default-directory-name)))
(list (ediff-read-file-name
"Directory to merge with revisions and ancestors" dir-A nil)
"Directory to merge with revisions and ancestors:" dir-A nil)
(read-string "Filter through regular expression: "
nil ediff-filtering-regexp-history)
nil 'ediff-filtering-regexp-history)
)))
(ediff-directory-revisions-internal
dir1 regexp 'ediff-merge-revisions-with-ancestor
@ -726,8 +602,8 @@ names. Only the files that are under revision control are taken into account."
;; Run ediff-action (ediff-files, ediff-merge, ediff-merge-with-ancestors)
;; on a pair of directories (three directories, in case of ancestor).
;; The third argument, REGEXP, is a regular expression that further filters the
;; file names.
;; The third argument, REGEXP, is a regular expression that can be used to
;; filter out certain file names.
;; JOBNAME is the symbol indicating the meta-job to be performed.
(defun ediff-directories-internal (dir1 dir2 dir3 regexp
action jobname
@ -763,7 +639,7 @@ names. Only the files that are under revision control are taken into account."
(setq ediff-dir-difference-list (quote (, diffs)))))
startup-hooks))
(setq meta-buf (ediff-prepare-meta-buffer
'ediff-dir-action
'ediff-filegroup-action
file-list
"*Ediff Session Group Panel"
'ediff-redraw-directory-group-buffer
@ -787,7 +663,7 @@ names. Only the files that are under revision control are taken into account."
))
startup-hooks))
(setq meta-buf (ediff-prepare-meta-buffer
'ediff-dir-action
'ediff-filegroup-action
file-list
"*Ediff Session Group Panel"
'ediff-redraw-directory-group-buffer
@ -1225,68 +1101,48 @@ file and then run `run-ediff-from-cvs-buffer'."
;;; Apply patch
;;;###autoload
(defun ediff-patch-buffer (buffer-name &optional startup-hooks)
(defun ediff-patch-file ()
"Run Ediff by patching SOURCE-FILENAME."
;; This now returns the control buffer
(interactive)
(let (source-dir source-file patch-buf)
(require 'ediff-ptch)
(setq patch-buf (ediff-get-patch-buffer))
(setq source-dir (cond (ediff-use-last-dir ediff-last-dir-patch)
((and (not ediff-patch-default-directory)
(buffer-file-name patch-buf))
(file-name-directory
(expand-file-name
(buffer-file-name patch-buf))))
(t default-directory)))
(setq source-file
;; the default is the directory, not the visited file name
(ediff-read-file-name "Which file to patch? " source-dir source-dir))
(ediff-dispatch-file-patching-job patch-buf source-file)))
;;;###autoload
(defun ediff-patch-buffer ()
"Run Ediff by patching BUFFER-NAME."
(interactive "bBuffer to patch: ")
(interactive)
(let (patch-buf)
(require 'ediff-ptch)
(setq patch-buf (ediff-get-patch-buffer))
(ediff-patch-buffer-internal
patch-buf
(read-buffer "Which buffer to patch? "
(cond ((eq patch-buf (current-buffer))
(window-buffer (other-window 1)))
(t (current-buffer)))
'must-match))))
(let* ((buf-to-patch (get-buffer buffer-name))
(file-name-ok (if buf-to-patch (buffer-file-name buf-to-patch)))
(buf-mod-status (buffer-modified-p buf-to-patch))
default-dir file-name ctl-buf)
(if file-name-ok
(setq file-name file-name-ok)
(ediff-eval-in-buffer buffer-name
(setq default-dir default-directory)
(setq file-name (ediff-make-temp-file buffer-name))
(set-visited-file-name file-name)
(setq buffer-auto-save-file-name nil) ; don't create auto-save file
(rename-buffer buffer-name) ; don't confuse the user with new buf name
(set-buffer-modified-p nil)
(set-visited-file-modtime) ; sync buffer and temp file
(setq default-directory default-dir)
))
(setq ctl-buf
(ediff-patch-file file-name startup-hooks 'ediff-patch-buffer))
(if file-name-ok
()
(ediff-eval-in-buffer ctl-buf
(delete-file (buffer-file-name ediff-buffer-A))
(delete-file (buffer-file-name ediff-buffer-B))
(ediff-eval-in-buffer ediff-buffer-A
(if default-dir (setq default-directory default-dir))
(set-visited-file-name nil)
(rename-buffer buffer-name)
(set-buffer-modified-p buf-mod-status))
(ediff-eval-in-buffer ediff-buffer-B
(setq buffer-auto-save-file-name nil) ; don't create auto-save file
(if default-dir (setq default-directory default-dir))
(set-visited-file-name nil)
(rename-buffer (ediff-unique-buffer-name
(concat buffer-name "_patched") ""))
(set-buffer-modified-p t))))
))
;;;###autoload
(defalias 'epatch 'ediff-patch-file)
;;;###autoload
(defalias 'epatch-buffer 'ediff-patch-buffer)
(defun ediff-get-patch-buffer (dir)
"Obtain patch buffer. If patch is already in a buffer---use it.
Else, read patch file into a new buffer."
(if (y-or-n-p "Is the patch file already in a buffer? ")
(setq ediff-patch-buf
(get-buffer (read-buffer "Patch buffer name: " nil t))) ;must match
(setq ediff-patch-buf
(find-file-noselect (read-file-name "Patch file name: " dir))))
(setq ediff-patch-diagnostics
(get-buffer-create "*ediff patch diagnostics*"))
(ediff-eval-in-buffer ediff-patch-diagnostics
(insert-buffer ediff-patch-buf)))
;;; Versions Control functions
@ -1343,7 +1199,7 @@ When called interactively, displays the version."
;;;###autoload
(defun ediff-documentation ()
"Jump to Ediff's Info file."
"Display Ediff's manual."
(interactive)
(let ((ctl-window ediff-control-window)
(ctl-buf ediff-control-buffer))
@ -1355,7 +1211,7 @@ When called interactively, displays the version."
(info (if ediff-xemacs-p "ediff.info" "ediff"))
(message "Type `i' to search for a specific topic"))
(error (beep 1)
(with-output-to-temp-buffer " *ediff-info*"
(with-output-to-temp-buffer ediff-msg-buffer
(princ (format "
The Info file for Ediff does not seem to be installed.

File diff suppressed because it is too large Load Diff

View File

@ -844,7 +844,7 @@ there."
macro)))
(defun vip-char-array-p (array)
(eval (cons 'and (mapcar 'numberp array))))
(eval (cons 'and (mapcar 'vip-characterp array))))
(defun vip-macro-to-events (macro-body)
(vconcat (mapcar 'vip-key-to-emacs-key macro-body)))

View File

@ -192,8 +192,8 @@ On single or double click, returns the word as determined by
(let ((click-word "")
(click-pos (vip-mouse-click-posn click))
(click-buf (vip-mouse-click-window-buffer click)))
(or (numberp count) (setq count 1))
(or (numberp click-count) (setq click-count 1))
(or (natnump count) (setq count 1))
(or (natnump click-count) (setq click-count 1))
(save-excursion
(save-window-excursion
@ -220,9 +220,9 @@ See `vip-surrounding-word' for the definition of a word in this case."
(select-frame vip-frame-of-focus))
;; turn arg into a number
(cond ((numberp arg) nil)
(cond ((integerp arg) nil)
;; prefix arg is a list when one hits C-u then command
((and (listp arg) (numberp (car arg)))
((and (listp arg) (integerp (car arg)))
(setq arg (car arg)))
(t (setq arg 1)))

View File

@ -184,6 +184,10 @@ that Viper doesn't know about.")
(fset 'vip-color-defined-p (symbol-function 'x-color-defined-p))
)))
(fset 'vip-characterp
(symbol-function
(if vip-xemacs-p 'characterp 'integerp)))
(defsubst vip-color-display-p ()
(if vip-emacs-p
(x-display-color-p)
@ -395,6 +399,143 @@ that Viper doesn't know about.")
(setq temp (cdr temp)))
(nconc lis1 lis2)))
;;; Support for :e and file globbing
(defun vip-ex-nontrivial-find-file-unix (filespec)
"Glob the file spec and visit all files matching the spec.
This function is designed to work under Unix. It may also work under VMS.
Users who prefer other types of shells should write their own version of this
function and set the variable `ex-nontrivial-find-file-function'
appropriately."
(let ((gshell
(cond (ex-unix-type-shell shell-file-name)
((memq system-type '(vax-vms axp-vms)) "*dcl*") ; VAX VMS
(t "sh"))) ; probably Unix anyway
(gshell-options
;; using cond in anticipation of further additions
(cond (ex-unix-type-shell-options)
))
(command (cond (vip-ms-style-os-p (format "\"ls -1 %s\"" filespec))
(t (format "ls -1 %s" filespec))))
file-list)
(save-excursion
(set-buffer (setq tmp-buf (get-buffer-create vip-ex-tmp-buf-name)))
(erase-buffer)
(setq status
(if gshell-options
(call-process gshell nil t nil
gshell-options
"-c"
command)
(call-process gshell nil t nil
"-c"
command)))
(goto-char (point-min))
;; Issue an error, if no match.
(if (> status 0)
(save-excursion
(skip-chars-forward " \t\n\j")
(if (looking-at "ls:")
(vip-forward-Word 1))
(error "%s: %s"
(if (stringp gshell)
gshell
"shell")
(buffer-substring (point) (vip-line-pos 'end)))
))
(goto-char (point-min))
(setq file-list (vip-get-filenames-from-buffer 'one-per-line)))
(mapcar 'find-file file-list)
))
(defun vip-ex-nontrivial-find-file-ms (filespec)
"Glob the file spec and visit all files matching the spec.
This function is designed to work under MS type systems, such as NT, W95, and
DOS. It may also work under OS/2.
The users of Unix-type shells should be able to use
`vip-ex-nontrivial-find-file-unix', making it into the value of the variable
`ex-nontrivial-find-file-function'. If this doesn't work, the user may have
to write a custom function, similar to `vip-ex-nontrivial-find-file-unix'."
(save-excursion
(set-buffer (setq tmp-buf (get-buffer-create vip-ex-tmp-buf-name)))
(erase-buffer)
(insert filespec)
(goto-char (point-min))
(mapcar 'find-file
(vip-glob-ms-windows-files (vip-get-filenames-from-buffer)))
))
;; Interpret the stuff in the buffer as a list of file names
;; return a list of file names listed in the buffer beginning at point
;; If optional arg is supplied, assume each filename is listed on a separate
;; line
(defun vip-get-filenames-from-buffer (one-per-line)
(let ((skip-chars (if one-per-line "\t\n" " \t\n"))
result fname delim)
(skip-chars-forward skip-chars)
(while (not (eobp))
(if (cond ((looking-at "\"")
(setq delim ?\")
(re-search-forward "[^\"]+" nil t)) ; noerror
((looking-at "'")
(setq delim ?')
(re-search-forward "[^']+" nil t)) ; noerror
(t
(re-search-forward
(concat "[^" skip-chars "]+") nil t))) ;noerror
(setq fname
(buffer-substring (match-beginning 0) (match-end 0))))
(if delim
(forward-char 1))
(skip-chars-forward " \t\n")
(setq result (cons fname result)))
result))
;; convert MS-DOS wildcards to regexp
(defun vip-wildcard-to-regexp (wcard)
(save-excursion
(set-buffer (setq tmp-buf (get-buffer-create vip-ex-tmp-buf-name)))
(erase-buffer)
(insert wcard)
(goto-char (point-min))
(while (not (eobp))
(skip-chars-forward "^*?.\\\\")
(cond ((eq (char-after (point)) ?*) (insert ".")(forward-char 1))
((eq (char-after (point)) ?.) (insert "\\")(forward-char 1))
((eq (char-after (point)) ?\\) (insert "\\")(forward-char 1))
((eq (char-after (point)) ??) (delete-char 1)(insert ".")))
)
(buffer-string)
))
;; glob windows files
;; LIST is expected to be in reverse order
(defun vip-glob-ms-windows-files (list)
(let ((tmp list)
(case-fold-search t)
tmp2)
(while tmp
(setq tmp2 (cons (directory-files
;; the directory part
(or (file-name-directory (car tmp))
"")
t ; return full names
;; the regexp part: globs the file names
(concat "^"
(vip-wildcard-to-regexp
(file-name-nondirectory (car tmp)))
"$"))
tmp2))
(setq tmp (cdr tmp)))
(reverse (apply 'append tmp2))))
@ -825,18 +966,18 @@ that Viper doesn't know about.")
;; Emacs doesn't handle capital letters correctly, since
;; \S-a isn't considered the same as A (it behaves as
;; plain `a' instead). So we take care of this here
(cond ((and (numberp event) (<= ?A event) (<= event ?Z))
(cond ((and (vip-characterp event) (<= ?A event) (<= event ?Z))
(setq mod nil
event event))
;; Emacs has the oddity whereby characters 128+char
;; represent M-char *if* this appears inside a string.
;; So, we convert them manually to (meta char).
((and (numberp event) (< ?\C-? event) (<= event 255))
((and (vip-characterp event) (< ?\C-? event) (<= event 255))
(setq mod '(meta)
event (- event ?\C-? 1)))
(t (event-basic-type event)))
)))
(if (numberp basis)
(if (vip-characterp basis)
(setq basis
(if (= basis ?\C-?)
(list 'control '\?) ; taking care of an emacs bug
@ -884,16 +1025,23 @@ that Viper doesn't know about.")
;; characters, will return a string. Otherwise, will return a string
;; representing a vector of converted events. If the input was a Viper macro,
;; will return a string that represents this macro as a vector.
(defun vip-array-to-string (event-seq &optional representation)
(let (temp)
(defun vip-array-to-string (event-seq)
(let (temp temp2)
(cond ((stringp event-seq) event-seq)
((vip-event-vector-p event-seq)
(setq temp (mapcar 'vip-event-key event-seq))
(if (vip-char-symbol-sequence-p temp)
(mapconcat 'symbol-name temp "")
(prin1-to-string (vconcat temp))))
(cond ((vip-char-symbol-sequence-p temp)
(mapconcat 'symbol-name temp ""))
((and (vip-char-array-p
(setq temp2 (mapcar 'vip-key-to-character temp))))
(mapconcat 'char-to-string temp2 ""))
(t (prin1-to-string (vconcat temp)))))
((vip-char-symbol-sequence-p event-seq)
(mapconcat 'symbol-name event-seq ""))
((and (vectorp event-seq)
(vip-char-array-p
(setq temp (mapcar 'vip-key-to-character event-seq))))
(mapconcat 'char-to-string temp ""))
(t (prin1-to-string event-seq)))))
(defun vip-key-press-events-to-chars (events)
@ -919,6 +1067,21 @@ that Viper doesn't know about.")
(vip-read-event))))
char))
;; key is supposed to be in viper's representation, e.g., (control l), a
;; character, etc.
(defun vip-key-to-character (key)
(cond ((eq key 'space) ?\ )
((eq key 'delete) ?\C-?)
((eq key 'backspace) ?\C-h)
((and (symbolp key)
(= 1 (length (symbol-name key))))
(string-to-char (symbol-name key)))
((and (listp key)
(eq (car key) 'control)
(symbol-name (nth 1 key))
(= 1 (length (symbol-name (nth 1 key)))))
(read (format "?\\C-%s" (symbol-name (nth 1 key)))))
(t key)))
(defun vip-setup-master-buffer (&rest other-files-or-buffers)

View File

@ -8,7 +8,7 @@
;; Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
(defconst viper-version "2.86 of March 14, 1996"
(defconst viper-version "2.90 of June 19, 1996"
"The current version of Viper")
;; This file is part of GNU Emacs.
@ -820,8 +820,12 @@ These buffers can be cycled through via :R and :P commands.")
(defvar vip-always t
"t means, arrange that vi-state will be a default.")
(defvar vip-custom-file-name (cond ((memq system-type '(vax-vms axp-vms))
"sys$login:.vip")
(defvar vip-ms-style-os-p (memq system-type '(ms-dos windows-nt windows-95))
"Tells is Emacs is running under an MS-style OS: ms-dos, window-nt, W95.")
(defvar vip-vms-os-p (memq system-type '(vax-vms axp-vms))
"Tells if Emacs is running under VMS.")
(defvar vip-custom-file-name (cond (vip-vms-os-p "sys$login:.vip")
((memq system-type '(emx ms-dos))
"/_vip")
((memq system-type '(windows-nt windows-95))
@ -831,6 +835,7 @@ These buffers can be cycled through via :R and :P commands.")
"Viper customisation file.
This variable must be set _before_ loading Viper.")
(defvar vip-spell-function 'ispell-region
"Spell function used by #s<move> command to spell.")
@ -1257,19 +1262,17 @@ Technically speaking, Viper is a Vi emulation package for GNU Emacs 19 and
XEmacs 19. It supports virtually all of Vi and Ex functionality, extending
and improving upon much of it.
1. Viper supports Vi at several levels. Level 1 is the closest to
Vi, level 5 provides the most flexibility to depart from many Vi
conventions.
1. Viper supports Vi at several levels. Level 1 is the closest to Vi,
level 5 provides the most flexibility to depart from many Vi conventions.
You will be asked to specify your user level in a following screen.
If you select user level 1 then the keys ^X, ^C, ^Z, and ^G will
behave as in VI, to smooth transition to Viper for the beginners.
However, to use Emacs productively, you are advised to reach user
level 3 or higher.
If you select user level 1 then the keys ^X, ^C, ^Z, and ^G will behave
as in VI, to smooth transition to Viper for the beginners. However, to
use Emacs productively, you are advised to reach user level 3 or higher.
If your user level is 2 or higher, ^X and ^C will invoke Emacs
functions,as usual in Emacs; ^Z will toggle vi/emacs modes, and
functions,as usual in Emacs; ^Z will toggle vi/emacs modes, and
^G will be the usual Emacs's keyboard-quit (something like ^C in VI).
2. Vi exit functions (e.g., :wq, ZZ) work on INDIVIDUAL files -- they
@ -1280,9 +1283,8 @@ and improving upon much of it.
6. Emacs Meta functions are invoked by typing `_' or `\\ ESC'.
On a window system, the best way is to use the Meta-key.
7. Try \\[keyboard-quit] and \\[abort-recursive-edit] repeatedly,
if something funny happens. This would abort the current editing
command.
7. Try \\[keyboard-quit] and \\[abort-recursive-edit] repeatedly,if
something funny happens. This would abort the current editing command.
You can get more information on Viper by:
@ -1298,8 +1300,11 @@ This startup message appears whenever you load Viper, unless you type `y' now."
'vip-inhibit-startup-message
"Viper startup message inhibited"
vip-custom-file-name t))
(kill-buffer (current-buffer))))
(message " ")
;;(kill-buffer (current-buffer))
(message
"The last message is in buffer `Viper Startup Message'")
(sit-for 4)
))
(vip-set-expert-level 'dont-change-unless)))
(vip-change-state-to-vi))))
@ -1791,8 +1796,8 @@ behaves as in Emacs, any number of multiple escapes is allowed."
(defun vip-prefix-arg-value (event com)
(let (value)
;; read while number
(while (and (numberp event) (>= event ?0) (<= event ?9))
(setq value (+ (* (if (numberp value) value 0) 10) (- event ?0)))
(while (and (vip-characterp event) (>= event ?0) (<= event ?9))
(setq value (+ (* (if (vip-characterp value) value 0) 10) (- event ?0)))
(setq event (vip-read-event-convert-to-char)))
(setq prefix-arg value)
@ -1901,11 +1906,11 @@ behaves as in Emacs, any number of multiple escapes is allowed."
last-command-char
(cond ((null arg) nil)
((consp arg) (car arg))
((numberp arg) arg)
((integerp arg) arg)
(t (error vip-InvalidCommandArgument)))
(cond ((null arg) nil)
((consp arg) (cdr arg))
((numberp arg) nil)
((integerp arg) nil)
(t (error vip-InvalidCommandArgument))))
(quit (setq vip-use-register nil)
(signal 'quit nil)))
@ -3559,15 +3564,16 @@ called from vip-repeat, the char last used is used. This behaviour is
controlled by the sign of prefix numeric value."
(interactive "P")
(let ((val (vip-p-val arg))
(com (vip-getcom arg)))
(com (vip-getcom arg))
(cmd-representation (nth 5 vip-d-com)))
(if (> val 0)
;; this means that the function was called interactively
(setq vip-f-char (read-char)
vip-f-forward t
vip-f-offset nil)
;; vip-repeat --- set vip-F-char from command-keys
(setq vip-F-char (if (stringp (nth 5 vip-d-com))
(vip-seq-last-elt (nth 5 vip-d-com))
(setq vip-F-char (if (stringp cmd-representation)
(vip-seq-last-elt cmd-representation)
vip-F-char)
vip-f-char vip-F-char)
(setq val (- val)))
@ -3584,15 +3590,16 @@ controlled by the sign of prefix numeric value."
"Go up to char ARG forward on line."
(interactive "P")
(let ((val (vip-p-val arg))
(com (vip-getcom arg)))
(com (vip-getcom arg))
(cmd-representation (nth 5 vip-d-com)))
(if (> val 0)
;; this means that the function was called interactively
(setq vip-f-char (read-char)
vip-f-forward t
vip-f-offset t)
;; vip-repeat --- set vip-F-char from command-keys
(setq vip-F-char (if (stringp (nth 5 vip-d-com))
(vip-seq-last-elt (nth 5 vip-d-com))
(setq vip-F-char (if (stringp cmd-representation)
(vip-seq-last-elt cmd-representation)
vip-F-char)
vip-f-char vip-F-char)
(setq val (- val)))
@ -3609,15 +3616,16 @@ controlled by the sign of prefix numeric value."
"Find char ARG on line backward."
(interactive "P")
(let ((val (vip-p-val arg))
(com (vip-getcom arg)))
(com (vip-getcom arg))
(cmd-representation (nth 5 vip-d-com)))
(if (> val 0)
;; this means that the function was called interactively
(setq vip-f-char (read-char)
vip-f-forward nil
vip-f-offset nil)
;; vip-repeat --- set vip-F-char from command-keys
(setq vip-F-char (if (stringp (nth 5 vip-d-com))
(vip-seq-last-elt (nth 5 vip-d-com))
(setq vip-F-char (if (stringp cmd-representation)
(vip-seq-last-elt cmd-representation)
vip-F-char)
vip-f-char vip-F-char)
(setq val (- val)))
@ -3634,15 +3642,16 @@ controlled by the sign of prefix numeric value."
"Go up to char ARG backward on line."
(interactive "P")
(let ((val (vip-p-val arg))
(com (vip-getcom arg)))
(com (vip-getcom arg))
(cmd-representation (nth 5 vip-d-com)))
(if (> val 0)
;; this means that the function was called interactively
(setq vip-f-char (read-char)
vip-f-forward nil
vip-f-offset t)
;; vip-repeat --- set vip-F-char from command-keys
(setq vip-F-char (if (stringp (nth 5 vip-d-com))
(vip-seq-last-elt (nth 5 vip-d-com))
(setq vip-F-char (if (stringp cmd-representation)
(vip-seq-last-elt cmd-representation)
vip-F-char)
vip-f-char vip-F-char)
(setq val (- val)))
@ -3776,8 +3785,9 @@ controlled by the sign of prefix numeric value."
(defun vip-paren-match (arg)
"Go to the matching parenthesis."
(interactive "P")
(let ((com (vip-getcom arg)))
(if (numberp arg)
(let ((com (vip-getcom arg))
anchor-point)
(if (integerp arg)
(if (or (> arg 99) (< arg 1))
(error "Prefix must be between 1 and 99")
(goto-char
@ -3785,20 +3795,33 @@ controlled by the sign of prefix numeric value."
(* (/ (point-max) 100) arg)
(/ (* (point-max) arg) 100)))
(back-to-indentation))
(let (lim)
(let (beg-lim end-lim)
(if (and (eolp) (not (bolp))) (forward-char -1))
(if (not (looking-at "[][(){}]"))
(setq anchor-point (point)))
(save-excursion
(beginning-of-line)
(setq beg-lim (point))
(end-of-line)
(setq lim (point)))
(if (re-search-forward "[][(){}]" lim t)
(backward-char)
(error "No matching character on line")))
(setq end-lim (point)))
(cond ((re-search-forward "[][(){}]" end-lim t)
(backward-char) )
((re-search-backward "[][(){}]" beg-lim t))
(t
(error "No matching character on line"))))
(cond ((looking-at "[\(\[{]")
(if com (vip-move-marker-locally 'vip-com-point (point)))
(forward-sexp 1)
(if com
(vip-execute-com 'vip-paren-match nil com)
(backward-char)))
(anchor-point
(if com
(progn
(vip-move-marker-locally 'vip-com-point anchor-point)
(forward-char 1)
(vip-execute-com 'vip-paren-match nil com)
)))
((looking-at "[])}]")
(forward-char)
(if com (vip-move-marker-locally 'vip-com-point (point)))
@ -4531,7 +4554,7 @@ cursor move past the beginning of line."
(vip-change-state-to-replace t))
(kill-region (vip-replace-start)
(vip-replace-end))
(vip-restore-cursor-color)
(vip-hide-replace-overlay)
(vip-change-state-to-insert))
(error ;; make sure that the overlay doesn't stay.
;; go back to the original point
@ -4916,7 +4939,7 @@ sensitive for VI-style look-and-feel."
(interactive)
(if (not (numberp vip-expert-level)) (setq vip-expert-level 0))
(if (not (natnump vip-expert-level)) (setq vip-expert-level 0))
(save-window-excursion
(delete-other-windows)
@ -5310,7 +5333,7 @@ Mail anyway (y or n)? ")
(setq
unread-command-events
(append
(cond ((numberp arg) (list (character-to-event arg)))
(cond ((vip-characterp arg) (list (character-to-event arg)))
((eventp arg) (list arg))
((stringp arg) (mapcar 'character-to-event arg))
((vectorp arg) (append arg nil)) ; turn into list
@ -5323,7 +5346,7 @@ Mail anyway (y or n)? ")
(defun vip-eventify-list-xemacs (lis)
(mapcar
(function (lambda (elt)
(cond ((numberp elt) (character-to-event elt))
(cond ((vip-characterp elt) (character-to-event elt))
((eventp elt) elt)
(t (error
"vip-eventify-list-xemacs: can't convert to event, %S"
@ -5377,42 +5400,45 @@ Mail anyway (y or n)? ")
"Run `vip-change-state-to-vi' on entry."
(vip-change-state-to-vi))
(defvar makefile-mode-hook nil)
(defvar makefile-mode-hook)
(add-hook 'makefile-mode-hook 'viper-mode)
(defvar help-mode-hook nil)
(defvar help-mode-hook)
(add-hook 'help-mode-hook 'viper-mode)
(defvar awk-mode-hook nil)
(defvar awk-mode-hook)
(add-hook 'awk-mode-hook 'viper-mode)
(defvar html-mode-hook nil)
(defvar html-mode-hook)
(add-hook 'html-mode-hook 'viper-mode)
(defvar html-helper-mode-hook nil)
(defvar html-helper-mode-hook)
(add-hook 'html-helper-mode-hook 'viper-mode)
(defvar emacs-lisp-mode-hook nil)
(defvar emacs-lisp-mode-hook)
(add-hook 'emacs-lisp-mode-hook 'viper-mode)
(defvar lisp-mode-hook nil)
(defvar lisp-mode-hook)
(add-hook 'lisp-mode-hook 'viper-mode)
(defvar bibtex-mode-hook nil)
(defvar bibtex-mode-hook)
(add-hook 'bibtex-mode-hook 'viper-mode)
(defvar cc-mode-hook nil)
(defvar cc-mode-hook)
(add-hook 'cc-mode-hook 'viper-mode)
(defvar c-mode-hook nil)
(defvar c-mode-hook)
(add-hook 'c-mode-hook 'viper-mode)
(defvar c++-mode-hook nil)
(defvar c++-mode-hook)
(add-hook 'c++-mode-hook 'viper-mode)
(defvar lisp-interaction-mode-hook nil)
(defvar lisp-interaction-mode-hook)
(add-hook 'lisp-interaction-mode-hook 'viper-mode)
(defvar fortran-mode-hook)
(add-hook 'fortran-mode-hook 'vip-mode)
(defvar text-mode-hook nil)
(defvar text-mode-hook)
(add-hook 'text-mode-hook 'viper-mode)
(add-hook 'completion-list-mode-hook 'viper-mode)
@ -5421,7 +5447,7 @@ Mail anyway (y or n)? ")
(add-hook 'perl-mode-hook 'viper-mode)
(add-hook 'tcl-mode-hook 'viper-mode)
(defvar emerge-startup-hook nil)
(defvar emerge-startup-hook)
(add-hook 'emerge-startup-hook 'vip-change-state-to-emacs)
;; Run vip-change-state-to-vi after quitting emerge.
(vip-eval-after-load
@ -5455,14 +5481,14 @@ Mail anyway (y or n)? ")
(vip-change-state-to-vi)))
;; Emacs shell, ange-ftp, and comint-based modes
(defvar comint-mode-hook nil)
(defvar comint-mode-hook)
(add-hook 'comint-mode-hook 'vip-change-state-to-insert)
(add-hook 'comint-mode-hook 'vip-comint-mode-hook)
;; Shell scripts
(defvar sh-mode-hook nil)
(defvar sh-mode-hook)
(add-hook 'sh-mode-hook 'viper-mode)
(defvar ksh-mode-hook nil)
(defvar ksh-mode-hook)
(add-hook 'ksh-mode-hook 'viper-mode)
;; Dired
@ -5471,22 +5497,18 @@ Mail anyway (y or n)? ")
(if vip-emacs-p
(progn
(defvar view-mode-hook nil
"View hook. Run after view mode.")
(defvar view-mode-hook)
(add-hook 'view-mode-hook 'vip-change-state-to-emacs))
(defadvice view-minor-mode (after vip-view-ad activate)
"Switch to Emacs state in View mode."
(vip-change-state-to-emacs))
(defvar view-hook nil
"View hook. Run after view mode.")
(defvar view-hook)
(add-hook 'view-hook 'vip-change-state-to-emacs))
;; For VM users.
;; Put summary and other VM buffers in Emacs state.
(defvar vm-mode-hooks nil
"This hook is run after vm is started.")
(defvar vm-summary-mode-hooks nil
"This hook is run after vm switches to summary mode.")
(defvar vm-mode-hooks)
(defvar vm-summary-mode-hooks)
(add-hook 'vm-mode-hooks 'vip-change-state-to-emacs)
(add-hook 'vm-summary-mode-hooks 'vip-change-state-to-emacs)