;;; diff-mode.el --- A mode for viewing/editing context diffs
-;; Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@cs.yale.edu>
;; Keywords: patch diff
-;; Revision: $Id: diff-mode.el,v 1.34 2000/11/12 16:59:52 monnier Exp $
;; This file is part of GNU Emacs.
;;; Commentary:
-;; Provides support for font-lock patterns, outline-regexps, navigation
+;; Provides support for font-lock, outline, navigation
;; commands, editing and various conversions as well as jumping
;; to the corresponding source file.
;; Todo:
;; - Improve narrowed-view support.
-;; - Improve the `compile' support (?).
+;; - re-enable (conditionally) the `compile' support after improving it to use
+;; the same code as diff-goto-source.
;; - Support for # comments in context->unified.
;; - Do a fuzzy search in diff-goto-source.
;; - Allow diff.el to use diff-mode.
:group 'tools
:group 'diff)
-(defcustom diff-jump-to-old-file-flag nil
+(defcustom diff-default-read-only t
+ "If non-nil, `diff-mode' buffers default to being read-only."
+ :type 'boolean
+ :group 'diff-mode)
+
+(defcustom diff-jump-to-old-file nil
"*Non-nil means `diff-goto-source' jumps to the old file.
Else, it jumps to the new file."
:group 'diff-mode
:type '(boolean))
-(defcustom diff-update-on-the-fly-flag t
+(defcustom diff-update-on-the-fly t
"*Non-nil means hunk headers are kept up-to-date on-the-fly.
When editing a diff file, the line numbers in the hunk headers
need to be kept consistent with the actual diff. This can
:group 'diff-mode)
(defvar diff-context-face 'diff-context-face)
+(defface diff-nonexistent-face
+ '((t (:inherit diff-file-header-face)))
+ "`diff-mode' face used to highlight nonexistent files in recursive diffs."
+ :group 'diff-mode)
+(defvar diff-nonexistent-face 'diff-nonexistent-face)
+
(defvar diff-font-lock-keywords
'(("^\\(@@ -[0-9,]+ \\+[0-9,]+ @@\\)\\(.*\\)$" ;unified
(1 diff-hunk-header-face)
(2 diff-function-face))
- ("^--- .+ ----$" ;context
- . diff-hunk-header-face)
- ("\\(\\*\\{15\\}\\)\\(.*\\)$" ;context
+ ("^--- .+ ----$" . diff-hunk-header-face) ;context
+ ("^\\(\\*\\{15\\}\\)\\(.*\\)$" ;context
(1 diff-hunk-header-face)
(2 diff-function-face))
("^\\*\\*\\* .+ \\*\\*\\*\\*". diff-hunk-header-face) ;context
("^[+>].*\n" . diff-added-face)
("^[-<].*\n" . diff-removed-face)
("^Index: \\(.+\\).*\n" (0 diff-header-face) (1 diff-index-face prepend))
+ ("^Only in .*\n" . diff-nonexistent-face)
("^#.*" . font-lock-string-face)
("^[^-=+*!<>].*\n" . diff-context-face)))
;;;###autoload
(define-derived-mode diff-mode fundamental-mode "Diff"
"Major mode for viewing/editing context diffs.
-Supports unified and context diffs as well as (to a lesser extent) normal diffs.
-When the buffer is read-only, the ESC prefix is not necessary.
-This mode runs `diff-mode-hook'.
-\\{diff-mode-map}"
+Supports unified and context diffs as well as (to a lesser extent)
+normal diffs.
+When the buffer is read-only, the ESC prefix is not necessary."
(set (make-local-variable 'font-lock-defaults) diff-font-lock-defaults)
(set (make-local-variable 'outline-regexp) diff-outline-regexp)
(set (make-local-variable 'imenu-generic-expression)
;; (set (make-local-variable 'paragraph-separate) paragraph-start)
;; (set (make-local-variable 'page-delimiter) "--- [^\t]+\t")
;; compile support
- (set (make-local-variable 'compilation-file-regexp-alist)
- diff-file-regexp-alist)
- (set (make-local-variable 'compilation-error-regexp-alist)
- diff-error-regexp-alist)
- (when (string-match "\\.rej\\'" (or buffer-file-name ""))
- (set (make-local-variable 'compilation-current-file)
- (substring buffer-file-name 0 (match-beginning 0))))
- (compilation-shell-minor-mode 1)
+
+ ;;;; compile support is not good enough yet. Also it can be annoying
+ ;; and should thus only be enabled conditionally.
+ ;; (set (make-local-variable 'compilation-file-regexp-alist)
+ ;; diff-file-regexp-alist)
+ ;; (set (make-local-variable 'compilation-error-regexp-alist)
+ ;; diff-error-regexp-alist)
+ ;; (when (string-match "\\.rej\\'" (or buffer-file-name ""))
+ ;; (set (make-local-variable 'compilation-current-file)
+ ;; (substring buffer-file-name 0 (match-beginning 0))))
+ ;; (compilation-shell-minor-mode 1)
+
+ (when (and (> (point-max) (point-min)) diff-default-read-only)
+ (toggle-read-only t))
;; setup change hooks
- (toggle-read-only t)
- (if (not diff-update-on-the-fly-flag)
+ (if (not diff-update-on-the-fly)
(add-hook 'write-contents-hooks 'diff-write-contents-hooks)
(make-local-variable 'diff-unhandled-changes)
(add-hook 'after-change-functions 'diff-after-change-function nil t)
nil " Diff" nil
;; FIXME: setup font-lock
;; setup change hooks
- (if (not diff-update-on-the-fly-flag)
+ (if (not diff-update-on-the-fly)
(add-hook 'write-contents-hooks 'diff-write-contents-hooks)
(make-local-variable 'diff-unhandled-changes)
(add-hook 'after-change-functions 'diff-after-change-function nil t)
(defun diff-find-source-location (&optional other-file reverse)
"Find out (BUF LINE-OFFSET POS SRC DST SWITCHED)."
(save-excursion
- (let* ((other (diff-xor other-file diff-jump-to-old-file-flag))
+ (let* ((other (diff-xor other-file diff-jump-to-old-file))
(char-offset (- (point) (progn (diff-beginning-of-hunk) (point))))
(hunk (buffer-substring (point)
(save-excursion (diff-end-of-hunk) (point))))
(buf (find-file-noselect file)))
;; Update the user preference if he so wished.
(when (> (prefix-numeric-value other-file) 8)
- (setq diff-jump-to-old-file-flag other))
+ (setq diff-jump-to-old-file other))
(with-current-buffer buf
(goto-line (string-to-number line))
(let* ((orig-pos (point))
(defun diff-apply-hunk (&optional reverse)
"Apply the current hunk to the source file and go to the next.
By default, the new source file is patched, but if the variable
-`diff-jump-to-old-file-flag' is non-nil, then the old source file is
+`diff-jump-to-old-file' is non-nil, then the old source file is
patched instead (some commands, such as `diff-goto-source' can change
the value of this variable when given an appropriate prefix argument).
((null line-offset)
(error "Can't find the text to patch"))
((and switched
- ;; A reversed patch was detected, perhaps apply it in reverse
+ ;; A reversed patch was detected, perhaps apply it in reverse.
(not (save-window-excursion
(pop-to-buffer buf)
(goto-char (+ pos (cdr old)))
(defun diff-goto-source (&optional other-file)
"Jump to the corresponding source line.
-`diff-jump-to-old-file-flag' (or its opposite if the OTHER-FILE prefix arg
+`diff-jump-to-old-file' (or its opposite if the OTHER-FILE prefix arg
is given) determines whether to jump to the old or the new file.
If the prefix arg is bigger than 8 (for example with \\[universal-argument] \\[universal-argument])
- then `diff-jump-to-old-file-flag' is also set, for the next invocations."
+ then `diff-jump-to-old-file' is also set, for the next invocations."
(interactive "P")
;; When pointing at a removal line, we probably want to jump to
;; the old location, and else to the new (i.e. as if reverting).