gnu-emacs-sources
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

diff+.el - extensions to GNU `diff.el'


From: Drew Adams
Subject: diff+.el - extensions to GNU `diff.el'
Date: Wed, 17 Jan 2001 16:42:05 -0500

;;; diff+.el --- Extensions to `diff.el'.
;; 
;; Emacs Lisp Archive Entry
;; Filename: diff+.el
;; Description: Extensions to `diff.el'.
;; Author: Drew Adams
;; Maintainer: Drew Adams
;; Copyright (C) 1996-2001, Drew Adams, all rights reserved.
;; Created: Fri Mar 15 09:33:29 1996
;; Version: $Id: diff+.el,v 1.6 2001/01/08 22:42:25 dadams Exp $
;; Last-Updated: Mon Jan  8 14:42:19 2001
;;           By: dadams
;;     Update #: 368
;; Keywords: data, matching, tools, unix, local
;; Compatibility: GNU Emacs 20.x
;; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 
;;; Commentary: 
;; 
;;    Extensions to `diff.el'.
;;
;;  "*diff*" buffer is highlighted.
;;
;;
;;  New user options defined here:
;;
;;    `diff-add-face', `diff-buffer-header-face', `diff-chg-face',
;;    `diff-chg-header-face', `diff-del-face', `diff-new-file-face',
;;    `diff-old-file-face'.
;;
;;  New function defined here: `diff-font-lock-keywords'.
;;
;;
;;  ***** NOTE: The following function defined in `diff.el' has
;;              been REDEFINED HERE:
;;
;;    `diff' -  "*diff*" buffer is highlighted.
;;
;;
;;  This file should be loaded after loading the standard GNU file
;;  `diff.el'.  So, in your `~/.emacs' file, do this:
;;  (eval-after-load "diff" '(require 'diff+))
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 
;;; Change log:
;; 
;; RCS $Log: diff+.el,v $
;; RCS Revision 1.6  2001/01/08 22:42:25  dadams
;; RCS Adapted file header for Emacs Lisp Archive.
;; RCS
;; RCS Revision 1.5  2001/01/03 17:33:27  dadams
;; RCS *** empty log message ***
;; RCS
;; RCS Revision 1.4  2001/01/03 00:35:41  dadams
;; RCS *** empty log message ***
;; RCS
;; RCS Revision 1.3  2000/12/07 19:36:56  dadams
;; RCS Require: frame-cmds.el -> shrink-fit-all.el.
;; RCS
;; RCS Revision 1.2  2000/11/28 19:24:55  dadams
;; RCS Optional require's via 3rd arg=t now.
;; RCS
;; RCS Revision 1.1  2000/09/14 15:19:18  dadams
;; RCS Initial revision
;; RCS
; Revision 1.9  1999/09/03  07:22:35  dadams
; 1. diff-font-lock-keywords: defconst -> defvar; made it a user option.
; 2. Updated header.
; 3. diff: Updated doc string to mention highlighting.
;
; Revision 1.8  1999/08/26  09:18:23  dadams
; 1. Protected faces via boundp.
; 2. *4 -> Dark* (e.g. Cyan4 -> DarkCyan).
;
; Revision 1.7  1999/08/25  13:45:40  dadams
; *** empty log message ***
;
; Revision 1.6  1999/04/09  13:48:15  dadams
; 1. Require def-face-const.el when compile.
; 2. Changed compilation-mode-hook to font-lock-fontify-buffer.
; 3. Define faces here. Changed diff-chg-header-face to red-foreground-face.
; 4. diff-font-lock-keywords: Removed regexp for first 2 buffer lines.
;    Changed diff-old/new-file-face to cover 3rd & 4th buffer lines.
; 5. diff: Highlight lines 1 & 2, not 3 & 4, with blue-foreground-face.
;
; Revision 1.5  1999/04/01  14:03:57  dadams
; Added: (add-hook 'compilation-mode-hook 'turn-on-font-lock).
;
; Revision 1.4  1999/04/01  13:55:48  dadams
; 1. Removed (require 'std-faces): Protected with boundp.
; 2. Added: diff-buffer-header-face.
;
; Revision 1.3  1999/03/30  13:04:55  dadams
; eval-when-compile require diff -> require diff
;
; Revision 1.2  1997/03/21  15:54:06  dadams
; Updated from version 19.34:
; diff: 1) "diff" -> diff-command, 2) added "Avoid frightening...",
;
; Revision 1.1  1997/03/21  15:43:08  dadams
; Initial revision
;
; Revision 1.8  1996/07/01  12:48:31  dadams
; (trivial)
;
; Revision 1.7  1996/06/20  11:54:15  dadams
; (trivial)
;
; Revision 1.6  1996/06/14  14:59:04  dadams
; 1. Updated file header Commentary to mention new user options defined here
;    and redefinition of std `diff' fn.
; 2. Made variables into user options.
;
; Revision 1.5  1996/06/06  13:27:28  dadams
; 1. Require compile.el.
; 2. Update of file dependency comments (e.g. "Autoloaded from...").
;
; Revision 1.4  1996/03/18  13:35:02  dadams
; 1) Require diff.el when compile.
; 2) Fixed typo: diff-chg-file-face -> diff-chg-face.
;
; Revision 1.3  1996/03/15  15:33:17  dadams
; (trivial: added Keywords)
;
; Revision 1.2  1996/03/15  14:40:53  dadams
; (trivial: require cl.el)
;
; Revision 1.1  1996/03/15  14:32:42  dadams
; Initial revision
;; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program; see the file COPYING.  If not, write to the
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 
;;; Code: 

(require 'cl) ;; when
(require 'compile) ;; compile-internal, compilation-finish-function
(require 'diff) ;; diff-old-temp-file, diff-new-temp-file, diff-command

;; Get macro `define-face-const' when this is compiled,
;; or run interpreted, but not when the compiled code is loaded.
(eval-when-compile (require 'def-face-const))

(require 'shrink-fit-all nil t) ;; (no error if not found): pop-to-buffer
(require 'icomplete+ nil t) ;; (no error if not found): read-string


(provide 'diff+)

;;;;;;;;;;;;;;;;;;;;;;;;


(add-hook 'compilation-mode-hook 'font-lock-fontify-buffer)


(defvar diff-old-file-face
  (or (and (boundp 'palegoldenrod-on-slateblue-face)
           palegoldenrod-on-slateblue-face)
      (define-face-const "PaleGoldenrod" "SlateBlue"))
  "*Face used to highlight `diff's \"old\" file argument.
as well as deleted lines .")

(defvar diff-del-face diff-old-file-face
  "*Face used to highlight `diff' deletion lines .")

(defvar diff-new-file-face
  (or (and (boundp 'palegoldenrod-on-darkcyan-face)
           palegoldenrod-on-darkcyan-face)
      (define-face-const "PaleGoldenrod" "DarkCyan"))
  "*Face used to highlight `diff's \"new\" file argument.")

(defvar diff-add-face diff-new-file-face
  "*Face used to highlight `diff' addition lines .")

(defvar diff-chg-face
  (or (and (boundp 'palegoldenrod-on-darkmagenta-face)
           palegoldenrod-on-darkmagenta-face)
      (define-face-const "PaleGoldenrod" "DarkMagenta"))
  "*Face used to highlight `diff' change lines (`!').")

(defvar diff-chg-header-face
  (or (and (boundp 'red-foreground-face)
           red-foreground-face)
      (define-face-const nil "Red"))
  "*Face used to highlight `diff' change header lines.")

(defvar diff-buffer-header-face
  (or (and (boundp 'darkmagenta-foreground-face)
           darkmagenta-foreground-face)
      (define-face-const "DarkMagenta" nil))
  "*Face used to highlight first two lines of `diff' buffer.")


;; Based partly on `diff-regexp-alist'.
;; Not set via `font-lock-set-defaults'.  `diff' uses `compilation-mode'.
;; `diff' temporarily binds `compilation-mode-font-lock-keywords' to this.
;;;###autoload
(defun diff-font-lock-keywords ()
  "*Expressions to highlight for `diff' in Compilation mode."
  '(
    ;; First 2 lines in buffer
    ("\\`.*\n.*" . diff-buffer-header-face)
    
    ;; Difference headers.
    ;; -u format: @@ -OLDSTART,OLDEND +NEWSTART,NEWEND @@
    ("^@@ -[0-9]+,[0-9]+ \\+[0-9]+,[0-9]+ @@$" . diff-chg-header-face)
    ;; -c format: *** OLDSTART,OLDEND ****
    ("^\\*\\*\\*\\*\\(\\*\\)*$" . diff-chg-header-face)
    ("^\\*\\*\\* .*$"
     . diff-old-file-face)
    ;;            --- NEWSTART,NEWEND ----
    ("^--- .*$" . diff-new-file-face)
    ;; plain diff format: OLDSTART[,OLDEND]{a,d,c}NEWSTART[,NEWEND]
    ("^[0-9]+\\(,[0-9]+\\)?[adc][0-9]+\\(,[0-9]+\\)?$" . diff-chg-header-face)
    ;; -e (ed) format: OLDSTART[,OLDEND]{a,d,c}
    ("^[0-9]+\\(,[0-9]+\\)?[adc]$" . diff-chg-header-face)
    ;; -f format: {a,d,c}OLDSTART[ OLDEND]
    ;; -n format: {a,d,c}OLDSTART LINES-CHANGED
    ("^[adc][0-9]+\\( [0-9]+\\)?$" . diff-chg-header-face)

    ;; Difference lines.
    ;;     -c format.
    ("^\\(!\\) " 1 diff-chg-face)
    ;;     -c, -u formats.
    ("^\\([+]\\)" 1 diff-new-file-face)
    ("^\\(-\\)" 1 diff-old-file-face)
    ;;     Default (no switches).
    ("^\\(>\\)[ \t]" 1 diff-new-file-face)
    ("^\\(<\\)[ \t]" 1 diff-old-file-face)
    ("^\\(---\\)$" 1 diff-chg-header-face t)
    ))



;; REPLACES ORIGINAL in `diff.el': 
;; *diff* buffer is highlighted.
;;;###autoload
(defun diff (old new &optional switches)
  "Unix `diff'.  Find and display differences between OLD and NEW files.
Interactively the current buffer's file name is the default for NEW
and a backup file for NEW is the default for OLD.
With prefix arg, prompt for `diff' switches.
The *diff* buffer is highlighted with `font-lock-mode', using
`diff-font-lock-keywords'."
  (interactive
   (nconc
    (let (oldf newf)
      (nreverse
       (list
        (progn
          (setq newf (buffer-file-name))
          (setq newf (if (and newf (file-exists-p newf))
                         (read-file-name
                          (concat "Diff new (2nd) file: ("
                                  (file-name-nondirectory newf) ") ")
                          nil newf t)
                       (read-file-name "Diff new (2nd) file: " nil nil t))))
        (progn
          (setq oldf (file-newest-backup newf))
          (setq oldf (if (and oldf (file-exists-p oldf))
                         (read-file-name
                          (concat "Diff original (1st) file: ("
                                  (file-name-nondirectory oldf) ") ")
                          (file-name-directory oldf) oldf t)
                       (read-file-name "Diff original (1st) file: "
                                       (file-name-directory newf) nil t)))))))
    (and current-prefix-arg
         (list (read-string "Diff switches: "
                            (if (stringp diff-switches)
                                diff-switches
                              (mapconcat 'identity diff-switches " ")))))))
  (setq new (expand-file-name new))
  (setq old (expand-file-name old))
  (let ((old-alt (file-local-copy old))
        (new-alt (file-local-copy new))
        buf)
    ;; Set up font-lock mode to treat diff error messages.
    ;; Have to do it via an `flet', because `font-lock-eval-keywords' looks 
first
    ;; for a function definition. Otherwise, could just bind a variable
    ;; `compilation-mode-font-lock-keywords' via a `let'.
    (flet ((compilation-mode-font-lock-keywords () (diff-font-lock-keywords)))
      (save-excursion
        (let ((compilation-process-setup-function 'diff-process-setup)
              (command
               (mapconcat 'identity
                          (append (list diff-command)
                                  ;; 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)))
                                  (and (or old-alt new-alt)
                                       (list "-L" old "-L" new))
                                  (list
                                   (shell-quote-argument (or old-alt old)))
                                  (list
                                   (shell-quote-argument (or new-alt new))))
                          " ")))
          (setq buf (compile-internal command "No more differences" "Diff"
                                      'diff-parse-differences)) ; `compile.el'
          (pop-to-buffer buf)
;;;@@@Emacs20     ;; Avoid frightening people with "abnormally terminated"
;;;@@@Emacs20     ;; if diff finds differences.
;;;@@@Emacs20     (set (make-local-variable 'compilation-exit-message-function)
;;;@@@Emacs20          (lambda (status code msg)
;;;@@@Emacs20            (cond ((not (eq status 'exit)) (cons msg code))
;;;@@@Emacs20                  ((zerop code)
;;;@@@Emacs20                   '("finished (no differences)\n" . "no 
differences"))
;;;@@@Emacs20                  ((= code 1) '("finished\n" . "differences 
found"))
;;;@@@Emacs20                  (t (cons msg code)))))
          (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) ;`compile.el'
               (if (not (equal "" switches))
                   (function
                    (lambda (buff msg)
                      (when diff-old-temp-file
                        (delete-file diff-old-temp-file))
                      (when diff-new-temp-file
                        (delete-file diff-new-temp-file))
;;;                   NOT NEEDED NOW - DO IT IN `diff-font-lock-keywords'.
;;;                   ;; Highlight first 2 lines of buffer.
;;;                   (when (fboundp 'highlight-region)
;;;                       (save-excursion 
;;;                            (set-buffer buff)
;;;                            (goto-char (point-min))
;;;                            (highlight-region (point)
;;;                                              (progn (forward-line 2) 
(point))
;;;                                              (if (boundp 
'blue-foreground-face)
;;;                                                  blue-foreground-face
;;;                                                diff-chg-header-face))))))
                      ))
                 (function
                  (lambda (buff msg)
                    (when diff-old-temp-file
                      (delete-file diff-old-temp-file))
                    (when diff-new-temp-file
                      (delete-file diff-new-temp-file))))))
          (unless (fboundp 'start-process)
            (funcall compilation-finish-function nil nil))
          (font-lock-mode 99)
          buf))))
  )

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; `diff+.el' ends here



reply via email to

[Prev in Thread] Current Thread [Next in Thread]