summaryrefslogtreecommitdiff
path: root/lisp/diff.el
diff options
context:
space:
mode:
authorStefan Monnier <monnier@iro.umontreal.ca>2004-02-11 06:06:24 +0000
committerStefan Monnier <monnier@iro.umontreal.ca>2004-02-11 06:06:24 +0000
commit10737a591cfecffe97bb2bf0bd5f47685cc16829 (patch)
treedb2a45d682b5fe76073ec52fa3c5e53b454696ab /lisp/diff.el
parentbd203c61e450311fa759377810d4c565bb7ca418 (diff)
downloademacs-10737a591cfecffe97bb2bf0bd5f47685cc16829.tar.gz
Don't use compile any more, use diff-mode instead.
(diff-regexp-alist, diff-old-file, diff-new-file) (diff-parse-differences, diff-process-setup): Remove. (diff-sentinel): New fun. (diff): Use it. Run the process ourselves. Use diff-mode for the rest of the processing.
Diffstat (limited to 'lisp/diff.el')
-rw-r--r--lisp/diff.el219
1 files changed, 49 insertions, 170 deletions
diff --git a/lisp/diff.el b/lisp/diff.el
index 01b9e590a07..231130db212 100644
--- a/lisp/diff.el
+++ b/lisp/diff.el
@@ -30,8 +30,6 @@
;;; Code:
-(require 'compile)
-
(defgroup diff nil
"Comparing files with `diff'."
:group 'tools)
@@ -48,143 +46,11 @@
:type 'string
:group 'diff)
-(defvar diff-regexp-alist
- '(
- ;; -u format: @@ -OLDSTART,OLDEND +NEWSTART,NEWEND @@
- ("^@@ -\\([0-9]+\\),[0-9]+ \\+\\([0-9]+\\),[0-9]+ @@$" 1 2)
-
- ;; -c format: *** OLDSTART,OLDEND ****
- ("^\\*\\*\\* \\([0-9]+\\),[0-9]+ \\*\\*\\*\\*$" 1 nil)
- ;; --- NEWSTART,NEWEND ----
- ("^--- \\([0-9]+\\),[0-9]+ ----$" nil 1)
-
- ;; plain diff format: OLDSTART[,OLDEND]{a,d,c}NEWSTART[,NEWEND]
- ("^\\([0-9]+\\)\\(,[0-9]+\\)?[adc]\\([0-9]+\\)\\(,[0-9]+\\)?$" 1 3)
-
- ;; -e (ed) format: OLDSTART[,OLDEND]{a,d,c}
- ("^\\([0-9]+\\)\\(,[0-9]+\\)?[adc]$" 1)
-
- ;; -f format: {a,d,c}OLDSTART[ OLDEND]
- ;; -n format: {a,d,c}OLDSTART LINES-CHANGED
- ("^[adc]\\([0-9]+\\)\\( [0-9]+\\)?$" 1)
- )
- "Alist of regular expressions to match difference sections in \\[diff] output.
-Each element has the form (REGEXP OLD-IDX NEW-IDX).
-Any text that REGEXP matches identifies one difference hunk
-or the header of a hunk.
-
-The OLD-IDX'th subexpression of REGEXP gives the line number
-in the old file, and NEW-IDX'th subexpression gives the line number
-in the new file. If OLD-IDX or NEW-IDX
-is nil, REGEXP matches only half a hunk.")
-
-(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.
- (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)
- (concat "\\(" (car elt) "\\)"))
- diff-regexp-alist
- "\\|"))
- ;; (GROUP-IDX OLD-IDX NEW-IDX)
- (groups (let ((subexpr 1))
- (mapcar (lambda (elt)
- (prog1
- (cons subexpr
- (mapcar (lambda (n)
- (and n
- (+ subexpr n)))
- (cdr elt)))
- (setq subexpr (+ subexpr 1
- (count-regexp-groupings
- (car elt))))))
- diff-regexp-alist)))
-
- (new-error
- (function (lambda (file subexpr)
- (setq compilation-error-list
- (cons
- (list (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.
- (list file nil)
- (string-to-int
- (buffer-substring
- (match-beginning subexpr)
- (match-end subexpr)))
- nil)
- compilation-error-list)))))
-
- (found-desired nil)
- (num-loci-found 0)
- g)
-
- (while (and (not found-desired)
- ;; We don't just pass LIMIT-SEARCH to re-search-forward
- ;; because we want to find matches containing LIMIT-SEARCH
- ;; but which extend past it.
- (re-search-forward regexp nil t))
-
- ;; Find which individual regexp matched.
- (setq g groups)
- (while (and g (null (match-beginning (car (car g)))))
- (setq g (cdr g)))
- (setq g (car g))
-
- (if (nth 1 g) ;OLD-IDX
- (funcall new-error diff-old-file (nth 1 g)))
- (if (nth 2 g) ;NEW-IDX
- (funcall new-error diff-new-file (nth 2 g)))
-
- (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 loci as the user wants,
- ;; or the user wanted a specific diff, and we're past it.
- (setq found-desired t)))
- (set-marker compilation-parsing-end
- (if found-desired (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.
- (point-max)))
- (message "Parsing differences...done"))
- (setq compilation-error-list (nreverse compilation-error-list)))
-
-(defun diff-process-setup ()
- "Set up \`compilation-exit-message-function' for \`diff'."
- ;; Avoid frightening people with "abnormally terminated"
- ;; if diff finds differences.
- (set (make-local-variable 'compilation-exit-message-function)
- (lambda (status code msg)
- (cond ((not (eq status 'exit))
- (cons msg code))
- ((zerop code)
- '("finished (no differences)\n" . "no differences"))
- ((= code 1)
- '("finished\n" . "differences found"))
- (t
- (cons msg code))))))
-
;; prompt if prefix arg present
(defun diff-switches ()
(if current-prefix-arg
@@ -193,6 +59,17 @@ is nil, REGEXP matches only half a hunk.")
diff-switches
(mapconcat 'identity diff-switches " ")))))
+(defun diff-sentinel (code)
+ "Code run when the diff process exits.
+CODE is the exit code of the process. It should be 0 iff no diffs were found."
+ (if diff-old-temp-file (delete-file diff-old-temp-file))
+ (if diff-new-temp-file (delete-file diff-new-temp-file))
+ (save-excursion
+ (goto-char (point-max))
+ (insert (format "\nDiff finished%s. %s\n"
+ (if (equal 0 code) " (no differences)" "")
+ (current-time-string)))))
+
;;;###autoload
(defun diff (old new &optional switches no-async)
"Find and display the differences between OLD and NEW files.
@@ -223,43 +100,45 @@ With prefix arg, prompt for diff switches."
(or switches (setq switches diff-switches)) ; If not specified, use default.
(let* ((old-alt (file-local-copy old))
(new-alt (file-local-copy new))
- buf)
+ (command
+ (mapconcat 'identity
+ `(,diff-command
+ ;; Use explicitly specified switches
+ ,@(if (listp switches) switches (list switches))
+ ,@(if (or old-alt new-alt)
+ (list "-L" old "-L" new))
+ ,(shell-quote-argument (or old-alt old))
+ ,(shell-quote-argument (or new-alt new)))
+ " "))
+ (buf (get-buffer-create "*Diff*"))
+ proc)
(save-excursion
- (let ((compilation-process-setup-function 'diff-process-setup)
- (command
- (mapconcat 'identity
- `(,diff-command
- ;; Use explicitly specified switches
- ,@(if (listp switches) switches (list switches))
- ,@(if (or old-alt new-alt)
- (list "-L" old "-L" new))
- ,(shell-quote-argument (or old-alt old))
- ,(shell-quote-argument (or new-alt new)))
- " ")))
- (setq buf
- (compile-internal command
- "No more differences" "Diff"
- 'diff-parse-differences
- nil nil nil nil nil nil no-async))
- (set-buffer buf)
- (set (make-local-variable 'revert-buffer-function)
- `(lambda (ignore-auto noconfirm)
- (diff ',old ',new ',switches ',no-async)))
- (set (make-local-variable 'diff-old-file) old)
- (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)))))
- ;; When async processes aren't available, the compilation finish
- ;; function doesn't get chance to run. Invoke it by hand.
- (or (fboundp 'start-process)
- (funcall compilation-finish-function nil nil))
- buf))))
+ (display-buffer buf)
+ (set-buffer buf)
+ (setq buffer-read-only nil)
+ (buffer-disable-undo (current-buffer))
+ (erase-buffer)
+ (buffer-enable-undo (current-buffer))
+ (diff-mode)
+ (set (make-local-variable 'revert-buffer-function)
+ `(lambda (ignore-auto noconfirm)
+ (diff ',old ',new ',switches ',no-async)))
+ (set (make-local-variable 'diff-old-temp-file) old-alt)
+ (set (make-local-variable 'diff-new-temp-file) new-alt)
+ (insert command "\n")
+ (if (and (not no-async) (fboundp 'start-process))
+ (progn
+ (setq proc (start-process "Diff" buf shell-file-name
+ shell-command-switch command))
+ (set-process-sentinel
+ proc (lambda (proc msg)
+ (with-current-buffer (process-buffer proc)
+ (diff-sentinel (process-exit-status proc))))))
+ ;; Async processes aren't available.
+ (diff-sentinel
+ (call-process shell-file-name nil buf nil
+ shell-command-switch command))))
+ buf))
;;;###autoload
(defun diff-backup (file &optional switches)