;; Copyright (C) 1992 Free Software Foundation, Inc.
-;; Keyword: unix, tools
+;; Keywords: unix, tools
;; This file is part of GNU Emacs.
;; along with GNU Emacs; see the file COPYING. If not, write to
;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+;;; Commentary:
+
+;; This package helps you explore differences between files, using the
+;; UNIX command diff(1). The commands are `diff' and `diff-backup'.
+;; You can specify options with `diff-switches'.
+
;;; Code:
(require 'compile)
-(defvar diff-switches nil
+;;; This is duplicated in vc.el.
+(defvar diff-switches "-c"
"*A string or list of strings specifying switches to be be passed to diff.")
(defvar diff-regexp-alist
subexpression gives the line number in the new file. If OLD-IDX or NEW-IDX
is nil, REGEXP matches only half a section.")
+(defvar diff-old-file nil
+ "This is the old file name in the comparison in this buffer.")
+(defvar diff-new-file nil
+ "This is the new file name in the comparison in this buffer.")
+(defvar diff-old-temp-file nil
+ "This is the name of a temp file to be deleted after diff finishes.")
+(defvar diff-new-temp-file nil
+ "This is the name of a temp file to be deleted after diff finishes.")
+
;; See compilation-parse-errors-function (compile.el).
(defun diff-parse-differences (limit-search find-at-least)
(setq compilation-error-list nil)
(message "Parsing differences...")
;; Don't reparse diffs already seen at last parse.
- (goto-char compilation-parsing-end)
+ (if compilation-parsing-end (goto-char compilation-parsing-end))
;; Construct in REGEXP a regexp composed of all those in dired-regexp-alist.
(let ((regexp (mapconcat (lambda (elt)
(function (lambda (file subexpr)
(setq compilation-error-list
(cons
- (cons (set-marker (make-marker)
- (match-beginning subexpr)
- (current-buffer))
+ (cons (save-excursion
+ ;; Report location of message
+ ;; at beginning of line.
+ (goto-char
+ (match-beginning subexpr))
+ (beginning-of-line)
+ (point-marker))
+ ;; Report location of corresponding text.
(let ((line (string-to-int
(buffer-substring
(match-beginning subexpr)
(match-end subexpr)))))
(save-excursion
- (set-buffer (find-file-noselect file))
+ (save-match-data
+ (set-buffer (find-file-noselect file)))
(save-excursion
(goto-line line)
(point-marker)))))
compilation-error-list)))))
(found-desired nil)
+ (num-loci-found 0)
g)
(while (and (not found-desired)
(if (nth 2 g) ;NEW-IDX
(funcall new-error diff-new-file (nth 2 g)))
- (if (or (and find-at-least (>= nfound find-at-least))
+ (setq num-loci-found (1+ num-loci-found))
+ (if (or (and find-at-least
+ (>= num-loci-found find-at-least))
(and limit-search (>= (point) limit-search)))
- ;; We have found as many new errors as the user wants,
+ ;; We have found as many new loci as the user wants,
;; or the user wanted a specific diff, and we're past it.
(setq found-desired t)))
(if found-desired
(setq compilation-parsing-end (point))
;; Set to point-max, not point, so we don't perpetually
;; parse the last bit of text when it isn't a diff header.
- (setq compilation-parsing-end (point-max))
- (message "Parsing differences...done")))
+ (setq compilation-parsing-end (point-max)))
+ (message "Parsing differences...done"))
(setq compilation-error-list (nreverse compilation-error-list)))
;;;###autoload
diff-switches
(mapconcat 'identity diff-switches " "))))
nil)))
- (message "Comparing files %s %s..." new old)
(setq new (expand-file-name new)
old (expand-file-name old))
- (let ((old-alt (diff-prepare old new))
- (new-alt (diff-prepare new old))
+ (let ((old-alt (file-local-copy old))
+ (new-alt (file-local-copy new))
buf)
(unwind-protect
(let ((command
(mapconcat 'identity
(append '("diff")
- (if (consp diff-switches)
- diff-switches
- (list diff-switches))
+ ;; Use explicitly specified switches
+ (if switches
+ (if (consp switches)
+ switches (list switches))
+ ;; If not specified, use default.
+ (if (consp diff-switches)
+ diff-switches
+ (list diff-switches)))
(if (or old-alt new-alt)
(list "-L" old "-L" new))
(list (or old-alt old))
(setq buf
(compile-internal command
"No more differences" "Diff"
- 'diff-parse-differences)))
+ 'diff-parse-differences))
(save-excursion
(set-buffer buf)
(set (make-local-variable 'diff-old-file) old)
- (set (make-local-variable 'diff-new-file) new))
- buf)
- (if old-alt (delete-file old-alt))
- (if new-alt (delete-file new-alt)))))
-
-;; Copy the file FILE into a temporary file if that is necessary
-;; for comparison. (This is only necessary if the file name has a handler.)
-;; OTHER is the other file to be compared.
-(defun diff-prepare (file other)
- (let (handler handlers)
- (setq handlers file-name-handler-alist)
- (while (and (consp handlers) (null handler))
- (if (and (consp (car handlers))
- (stringp (car (car handlers)))
- (string-match (car (car handlers)) file))
- (setq handler (cdr (car handlers))))
- (setq handlers (cdr handlers)))
- (if handler
- (funcall handler 'diff-prepare file other)
- nil)))
+ (set (make-local-variable 'diff-new-file) new)
+ (set (make-local-variable 'diff-old-temp-file) old-alt)
+ (set (make-local-variable 'diff-new-temp-file) new-alt)
+ (set (make-local-variable 'compilation-finish-function)
+ (function (lambda (buff msg)
+ (if diff-old-temp-file
+ (delete-file diff-old-temp-file))
+ (if diff-new-temp-file
+ (delete-file diff-new-temp-file))))))
+ buf))))
;;;###autoload
(defun diff-backup (file &optional switches)
(> (backup-extract-version fn1)
(backup-extract-version fn2))))))))))
+(provide 'diff)
+
;;; diff.el ends here