]> code.delx.au - gnu-emacs/blobdiff - lisp/diff-mode.el
(gdb-flush-pending-output): New variable.
[gnu-emacs] / lisp / diff-mode.el
index 9ae6bbee7c0e35deda44dd38dff8ed47a2fcdd73..c945a6a7221ebf589d0e7e0ff1389fc0cbef3661 100644 (file)
@@ -1,6 +1,7 @@
 ;;; diff-mode.el --- a mode for viewing/editing context diffs
 
-;; Copyright (C) 1998,1999,2000,01,02,03,2004  Free Software Foundation, Inc.
+;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004
+;;           Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@cs.yale.edu>
 ;; Keywords: convenience patch diff
@@ -48,7 +49,6 @@
 ;;
 ;; - Refine hunk on a word-by-word basis.
 ;;
-;; - Use the new next-error-function to allow C-x `.
 ;; - Handle `diff -b' output in context->unified.
 
 ;;; Code:
@@ -110,7 +110,7 @@ when editing big diffs)."
     ("}" . diff-file-next)
     ("{" . diff-file-prev)
     ("\C-m" . diff-goto-source)
-    ([mouse-2] . diff-mouse-goto-source)
+    ([mouse-2] . diff-goto-source)
     ;; From XEmacs' diff-mode.
     ("W" . widen)
     ;;("." . diff-goto-source)         ;display-buffer
@@ -140,7 +140,8 @@ when editing big diffs)."
     ("\C-c\C-r" . diff-refine-hunk)
     ("\C-c\C-s" . diff-split-hunk)
     ("\C-c\C-a" . diff-apply-hunk)
-    ("\C-c\C-t" . diff-test-hunk))
+    ("\C-c\C-t" . diff-test-hunk)
+    ("\C-c\C-f" . next-error-follow-minor-mode))
   "Keymap for `diff-mode'.  See also `diff-mode-shared-map'.")
 
 (easy-menu-define diff-mode-menu diff-mode-map
@@ -170,81 +171,82 @@ when editing big diffs)."
 ;;;;
 
 (defface diff-header-face
-  '((((type tty pc) (class color) (background light))
-     (:foreground "blue1" :weight bold))
-    (((type tty pc) (class color) (background dark))
-     (:foreground "green" :weight bold))
+  '((((class color) (min-colors 88) (background light))
+     :background "grey85")
+    (((class color) (min-colors 88) (background dark))
+     :background "grey45")
     (((class color) (background light))
-     (:background "grey85"))
+     :foreground "blue1" :weight bold)
     (((class color) (background dark))
-     (:background "grey45"))
-    (t (:weight bold)))
+     :foreground "green" :weight bold)
+    (t :weight bold))
   "`diff-mode' face inherited by hunk and index header faces.")
 (defvar diff-header-face 'diff-header-face)
 
 (defface diff-file-header-face
-  '((((type tty pc) (class color) (background light))
-     (:foreground "yellow" :weight bold))
-    (((type tty pc) (class color) (background dark))
-     (:foreground "cyan" :weight bold))
+  '((((class color) (min-colors 88) (background light))
+     :background "grey70" :weight bold)
+    (((class color) (min-colors 88) (background dark))
+     :background "grey60" :weight bold)
     (((class color) (background light))
-     (:background "grey70" :weight bold))
+     :foreground "yellow" :weight bold)
     (((class color) (background dark))
-     (:background "grey60" :weight bold))
-    (t (:weight bold)))                        ; :height 1.3
+     :foreground "cyan" :weight bold)
+    (t :weight bold))                  ; :height 1.3
   "`diff-mode' face used to highlight file header lines.")
 (defvar diff-file-header-face 'diff-file-header-face)
 
 (defface diff-index-face
-  '((t (:inherit diff-file-header-face)))
+  '((t :inherit diff-file-header-face))
   "`diff-mode' face used to highlight index header lines.")
 (defvar diff-index-face 'diff-index-face)
 
 (defface diff-hunk-header-face
-  '((t (:inherit diff-header-face)))
+  '((t :inherit diff-header-face))
   "`diff-mode' face used to highlight hunk header lines.")
 (defvar diff-hunk-header-face 'diff-hunk-header-face)
 
 (defface diff-removed-face
-  '((t (:inherit diff-changed-face)))
+  '((t :inherit diff-changed-face))
   "`diff-mode' face used to highlight removed lines.")
 (defvar diff-removed-face 'diff-removed-face)
 
 (defface diff-added-face
-  '((t (:inherit diff-changed-face)))
+  '((t :inherit diff-changed-face))
   "`diff-mode' face used to highlight added lines.")
 (defvar diff-added-face 'diff-added-face)
 
 (defface diff-changed-face
   '((((type tty pc) (class color) (background light))
-     (:foreground "magenta" :weight bold :slant italic))
+     :foreground "magenta" :weight bold :slant italic)
     (((type tty pc) (class color) (background dark))
-     (:foreground "yellow" :weight bold :slant italic))
-    (t ()))
+     :foreground "yellow" :weight bold :slant italic))
   "`diff-mode' face used to highlight changed lines.")
 (defvar diff-changed-face 'diff-changed-face)
 
 (defface diff-function-face
-  '((t (:inherit diff-context-face)))
+  '((t :inherit diff-context-face))
   "`diff-mode' face used to highlight function names produced by \"diff -p\".")
 (defvar diff-function-face 'diff-function-face)
 
 (defface diff-context-face
   '((((class color) (background light))
-     (:foreground "grey50"))
+     :foreground "grey50")
     (((class color) (background dark))
-     (:foreground "grey70"))
-    (t ))
+     :foreground "grey70"))
   "`diff-mode' face used to highlight context and other side-information.")
 (defvar diff-context-face 'diff-context-face)
 
 (defface diff-nonexistent-face
-  '((t (:inherit diff-file-header-face)))
+  '((t :inherit diff-file-header-face))
   "`diff-mode' face used to highlight nonexistent files in recursive diffs.")
 (defvar diff-nonexistent-face 'diff-nonexistent-face)
 
 (defconst diff-yank-handler '(diff-yank-function))
 (defun diff-yank-function (text)
+  ;; FIXME: the yank-handler is now called separately on each piece of text
+  ;; with a yank-handler property, so the next-single-property-change call
+  ;; below will always return nil :-(   --stef
   (let ((mixed (next-single-property-change 0 'yank-handler text))
        (start (point)))
     ;; First insert the text.
@@ -275,14 +277,13 @@ when editing big diffs)."
     ("^\\(---\\|\\+\\+\\+\\|\\*\\*\\*\\) \\(\\S-+\\)\\(.*[^*-]\\)?\n"
      (0 diff-header-face) (2 diff-file-header-face prepend))
     ("^[0-9,]+[acd][0-9,]+$" . diff-hunk-header-face)
-    ("^!.*\n" (0 '(face diff-changed-face yank-handler ,diff-yank-handler)))
-    ("^[+>].*\n" (0 '(face diff-added-face yank-handler ,diff-yank-handler)))
-    ("^[-<].*\n" (0 '(face diff-removed-face yank-handler ,diff-yank-handler)))
+    ("^!.*\n" (0 diff-changed-face))
+    ("^[+>].*\n" (0 diff-added-face))
+    ("^[-<].*\n" (0 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"
-     (0 '(face diff-context-face yank-handler ,diff-yank-handler)))))
+    ("^[^-=+*!<>].*\n" (0 diff-context-face))))
 
 (defconst diff-font-lock-defaults
   '(diff-font-lock-keywords t nil nil nil (font-lock-multiline . nil)))
@@ -299,11 +300,15 @@ when editing big diffs)."
 ;;;;
 
 (defconst diff-hunk-header-re "^\\(@@ -[0-9,]+ \\+[0-9,]+ @@.*\\|\\*\\{15\\}.*\n\\*\\*\\* .+ \\*\\*\\*\\*\\|[0-9]+\\(,[0-9]+\\)?[acd][0-9]+\\(,[0-9]+\\)?\\)$")
-(defconst diff-file-header-re (concat "^\\(--- .+\n\\+\\+\\+\\|\\*\\*\\* .+\n---\\|[^-+!<>0-9@* ]\\).+\n" (substring diff-hunk-header-re 1)))
+(defconst diff-file-header-re (concat "^\\(--- .+\n\\+\\+\\+ \\|\\*\\*\\* .+\n--- \\|[^-+!<>0-9@* ]\\).+\n" (substring diff-hunk-header-re 1)))
 (defvar diff-narrowed-to nil)
 
 (defun diff-end-of-hunk (&optional style)
-  (if (looking-at diff-hunk-header-re) (goto-char (match-end 0)))
+  (when (looking-at diff-hunk-header-re)
+    (unless style
+      ;; Especially important for unified (because headers are ambiguous).
+      (setq style (cdr (assq (char-after) '((?@ . unified) (?* . context))))))
+    (goto-char (match-end 0)))
   (let ((end (and (re-search-forward (case style
                                       ;; A `unified' header is ambiguous.
                                       (unified (concat "^[^-+# \\]\\|"
@@ -545,14 +550,6 @@ Non-nil OLD means that we want the old file."
         file)))))
 
 
-(defun diff-mouse-goto-source (event)
-  "Run `diff-goto-source' for the diff at a mouse click."
-  (interactive "e")
-  (save-excursion
-    (mouse-set-point event)
-    (diff-goto-source)))
-
-
 (defun diff-ediff-patch ()
   "Call `ediff-patch-file' on the current buffer."
   (interactive)
@@ -800,9 +797,12 @@ else cover the whole bufer."
       (goto-char end) (diff-end-of-hunk)
       (let ((plus 0) (minus 0) (space 0) (bang 0))
        (while (and (= (forward-line -1) 0) (<= start (point)))
-         (if (not (looking-at "\\(@@ -[0-9,]+ \\+[0-9,]+ @@.*\\|[-*][-*][-*] .+ [-*][-*][-*][-*]\\)$"))
+         (if (not (looking-at
+                   (concat "@@ -[0-9,]+ \\+[0-9,]+ @@"
+                           "\\|[-*][-*][-*] [0-9,]+ [-*][-*][-*][-*]$"
+                           "\\|--- .+\n\\+\\+\\+ ")))
              (case (char-after)
-               (?\  (incf space))
+               (?\s (incf space))
                (?+ (incf plus))
                (?- (incf minus))
                (?! (incf bang))
@@ -888,9 +888,14 @@ See `after-change-functions' for the meaning of BEG, END and LEN."
          (diff-fixup-modifs (point) (cdr diff-unhandled-changes)))))
     (setq diff-unhandled-changes nil)))
 
-;;;;
-;;;; The main function
-;;;;
+(defun diff-next-error (arg reset)
+  ;; Select a window that displays the current buffer so that point
+  ;; movements are reflected in that window.  Otherwise, the user might
+  ;; never see the hunk corresponding to the source she's jumping to.
+  (pop-to-buffer (current-buffer))
+  (if reset (goto-char (point-min)))
+  (diff-hunk-next arg)
+  (diff-goto-source))
 
 ;;;###autoload
 (define-derived-mode diff-mode fundamental-mode "Diff"
@@ -918,6 +923,7 @@ a diff with \\[diff-reverse-direction]."
   ;;   (set (make-local-variable 'paragraph-separate) paragraph-start)
   ;;   (set (make-local-variable 'page-delimiter) "--- [^\t]+\t")
   ;; compile support
+  (set (make-local-variable 'next-error-function) 'diff-next-error)
 
   (when (and (> (point-max) (point-min)) diff-default-read-only)
     (toggle-read-only t))
@@ -934,7 +940,7 @@ a diff with \\[diff-reverse-direction]."
     (add-hook 'view-mode-hook
              `(lambda ()
                 (setq minor-mode-overriding-map-alist
-                      (delq ,ro-bind minor-mode-overriding-map-alist)))
+                      (delq ',ro-bind minor-mode-overriding-map-alist)))
              nil t))
   ;; add-log support
   (set (make-local-variable 'add-log-current-defun-function)
@@ -973,7 +979,7 @@ a diff with \\[diff-reverse-direction]."
   "Turn context diffs into unified diffs if applicable."
   (if (save-excursion
        (goto-char (point-min))
-       (looking-at "\\*\\*\\* "))
+       (and (looking-at diff-hunk-header-re) (eq (char-after) ?*)))
       (let ((mod (buffer-modified-p)))
        (unwind-protect
            (diff-context->unified (point-min) (point-max))
@@ -1221,16 +1227,19 @@ With a prefix argument, try to REVERSE the hunk."
     (diff-hunk-status-msg line-offset (diff-xor reverse switched) t)))
 
 
-(defun diff-goto-source (&optional other-file)
+(defalias 'diff-mouse-goto-source 'diff-goto-source)
+
+(defun diff-goto-source (&optional other-file event)
   "Jump to the corresponding source line.
 `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' is also set, for the next invocations."
-  (interactive "P")
+  (interactive (list current-prefix-arg last-input-event))
   ;; 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).
   ;; This is a convenient detail when using smerge-diff.
+  (if event (posn-set-point (event-end event)))
   (let ((rev (not (save-excursion (beginning-of-line) (looking-at "[-<]")))))
     (destructuring-bind (buf line-offset pos src dst &optional switched)
        (diff-find-source-location other-file rev)
@@ -1242,9 +1251,12 @@ If the prefix arg is bigger than 8 (for example with \\[universal-argument] \\[u
 (defun diff-current-defun ()
   "Find the name of function at point.
 For use in `add-log-current-defun-function'."
-  (destructuring-bind (buf line-offset pos src dst &optional switched)
-      (diff-find-source-location)
-    (save-excursion
+  (save-excursion
+    (when (looking-at diff-hunk-header-re)
+      (forward-line 1)
+      (re-search-forward "^[^ ]" nil t))
+    (destructuring-bind (buf line-offset pos src dst &optional switched)
+       (diff-find-source-location)
       (beginning-of-line)
       (or (when (memq (char-after) '(?< ?-))
            ;; Cursor is pointing at removed text.  This could be a removed
@@ -1342,5 +1354,5 @@ For use in `add-log-current-defun-function'."
 ;; use `combine-after-change-calls' to minimize the slowdown of font-lock.
 ;;
 
-;;; arch-tag: 2571d7ff-bc28-4cf9-8585-42e21890be66
+;; arch-tag: 2571d7ff-bc28-4cf9-8585-42e21890be66
 ;;; diff-mode.el ends here