]> code.delx.au - gnu-emacs/blobdiff - lisp/vc/diff-mode.el
Merge from trunk.
[gnu-emacs] / lisp / vc / diff-mode.el
index cec4fb24616c59d062e83ee0ccd154f44cc744d6..7de9d17e3f77bffbc0e67be03c975d04b171be30 100644 (file)
@@ -1,7 +1,6 @@
-;;; diff-mode.el --- a mode for viewing/editing context diffs
+;;; diff-mode.el --- a mode for viewing/editing context diffs -*- lexical-binding: t -*-
 
-;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,2005, 2006,
-;;   2007, 2008, 2009, 2010  Free Software Foundation, Inc.
+;; Copyright (C) 1998-2012  Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 ;; Keywords: convenience patch diff vc
@@ -123,8 +122,7 @@ when editing big diffs)."
     ("\C-m" . diff-goto-source)
     ([mouse-2] . diff-goto-source)
     ;; From XEmacs' diff-mode.
-    ;; Standard M-w is useful, so don't change M-W.
-    ;;("W" . widen)
+    ("W" . widen)
     ;;("." . diff-goto-source)         ;display-buffer
     ;;("f" . diff-goto-source)         ;find-file
     ("o" . diff-goto-source)           ;other-window
@@ -136,17 +134,21 @@ when editing big diffs)."
     ;; Not useful if you have to metafy them.
     ;;(" " . scroll-up)
     ;;("\177" . scroll-down)
-    ;; Standard M-a is useful, so don't change M-A.
-    ;;("A" . diff-ediff-patch)
-    ;; Standard M-r is useful, so don't change M-r or M-R.
-    ;;("r" . diff-restrict-view)
-    ;;("R" . diff-reverse-direction)
-    ("g" . revert-buffer)
-    ("q" . quit-window))
-  "Basic keymap for `diff-mode', bound to various prefix keys.")
+    ("A" . diff-ediff-patch)
+    ("r" . diff-restrict-view)
+    ("R" . diff-reverse-direction))
+  "Basic keymap for `diff-mode', bound to various prefix keys."
+  :inherit special-mode-map)
 
 (easy-mmode-defmap diff-mode-map
-  `(("\e" . ,diff-mode-shared-map)
+  `(("\e" . ,(let ((map (make-sparse-keymap)))
+               ;; We want to inherit most bindings from diff-mode-shared-map,
+               ;; but not all since they may hide useful M-<foo> global
+               ;; bindings when editing.
+               (set-keymap-parent map diff-mode-shared-map)
+               (dolist (key '("A" "r" "R" "g" "q" "W" "z"))
+                 (define-key map key nil))
+               map))
     ;; From compilation-minor-mode.
     ("\C-c\C-c" . diff-goto-source)
     ;; By analogy with the global C-x 4 a binding.
@@ -223,9 +225,16 @@ when editing big diffs)."
   "Keymap for `diff-minor-mode'.  See also `diff-mode-shared-map'.")
 
 (define-minor-mode diff-auto-refine-mode
-  "Automatically highlight changes in detail as the user visits hunks.
-When transitioning from disabled to enabled,
-try to refine the current hunk, as well."
+  "Toggle automatic diff hunk highlighting (Diff Auto Refine mode).
+With a prefix argument ARG, enable Diff Auto Refine mode if ARG
+is positive, and disable it otherwise.  If called from Lisp,
+enable the mode if ARG is omitted or nil.
+
+Diff Auto Refine mode is a buffer-local minor mode used with
+`diff-mode'.  When enabled, Emacs automatically highlights
+changes in detail as the user visits hunks.  When transitioning
+from disabled to enabled, it tries to refine the current hunk, as
+well."
   :group 'diff-mode :init-value t :lighter nil ;; " Auto-Refine"
   (when diff-auto-refine-mode
     (condition-case-no-debug nil (diff-refine-hunk) (error nil))))
@@ -293,9 +302,14 @@ try to refine the current hunk, as well."
 (defvar diff-added-face 'diff-added)
 
 (defface diff-changed
-  '((((type tty pc) (class color) (background light))
+  ;; We normally apply a `shadow'-based face on the `diff-context'
+  ;; face, and keep `diff-changed' the default.
+  '((((class color grayscale) (min-colors 88)))
+    ;; If the terminal lacks sufficient colors for shadowing,
+    ;; highlight changed lines explicitly.
+    (((class color) (background light))
      :foreground "magenta" :weight bold :slant italic)
-    (((type tty pc) (class color) (background dark))
+    (((class color) (background dark))
      :foreground "yellow" :weight bold :slant italic))
   "`diff-mode' face used to highlight changed lines."
   :group 'diff-mode)
@@ -801,9 +815,11 @@ PREFIX is only used internally: don't use it."
            (diff-find-file-name old noprompt (match-string 1)))
        ;; if all else fails, ask the user
        (unless noprompt
-         (let ((file (read-file-name (format "Use file %s: "
-                                             (or (first fs) ""))
-                                     nil (first fs) t (first fs))))
+         (let ((file (expand-file-name (or (first fs) ""))))
+          (setq file
+                (read-file-name (format "Use file %s: " file)
+                                (file-name-directory file) file t
+                                (file-name-nondirectory file)))
            (set (make-local-variable 'diff-remembered-files-alist)
                 (cons (cons fs file) diff-remembered-files-alist))
            file))))))
@@ -812,7 +828,7 @@ PREFIX is only used internally: don't use it."
 (defun diff-ediff-patch ()
   "Call `ediff-patch-file' on the current buffer."
   (interactive)
-  (condition-case err
+  (condition-case nil
       (ediff-patch-file nil (current-buffer))
     (wrong-number-of-arguments (ediff-patch-file))))
 
@@ -1134,12 +1150,14 @@ else cover the whole buffer."
                     (old2 (match-string 4))
                     (new1 (number-to-string (+ space minus)))
                     (new2 (number-to-string (+ space plus))))
-                (if old2
-                    (unless (string= new2 old2) (replace-match new2 t t nil 4))
-                  (goto-char (match-end 4)) (insert "," new2))
-                (if old1
-                    (unless (string= new1 old1) (replace-match new1 t t nil 2))
-                  (goto-char (match-end 2)) (insert "," new1))))
+               (if old2
+                   (unless (string= new2 old2) (replace-match new2 t t nil 4))
+                 (goto-char (match-end 3))
+                 (insert "," new2))
+               (if old1
+                   (unless (string= new1 old1) (replace-match new1 t t nil 2))
+                 (goto-char (match-end 1))
+                 (insert "," new1))))
             ((looking-at diff-context-mid-hunk-header-re)
              (when (> (+ space bang plus) 0)
                (let* ((old1 (match-string 1))
@@ -1169,7 +1187,7 @@ else cover the whole buffer."
 ;; *-change-function is asking for trouble, whereas making them
 ;; from a post-command-hook doesn't pose much problems
 (defvar diff-unhandled-changes nil)
-(defun diff-after-change-function (beg end len)
+(defun diff-after-change-function (beg end _len)
   "Remember to fixup the hunk header.
 See `after-change-functions' for the meaning of BEG, END and LEN."
   ;; Ignoring changes when inhibit-read-only is set is strictly speaking
@@ -1267,7 +1285,7 @@ a diff with \\[diff-reverse-direction].
 
   ;; Set up `whitespace-mode' so that turning it on will show trailing
   ;; whitespace problems on the modified lines of the diff.
-  (set (make-local-variable 'whitespace-style) '(trailing))
+  (set (make-local-variable 'whitespace-style) '(face trailing))
   (set (make-local-variable 'whitespace-trailing-regexp)
        "^[-\+!<>].*?\\([\t ]+\\)$")
 
@@ -1279,7 +1297,7 @@ a diff with \\[diff-reverse-direction].
     (add-hook 'after-change-functions 'diff-after-change-function nil t)
     (add-hook 'post-command-hook 'diff-post-command-hook nil t))
   ;; Neat trick from Dave Love to add more bindings in read-only mode:
-  (lexical-let ((ro-bind (cons 'buffer-read-only diff-mode-shared-map)))
+  (let ((ro-bind (cons 'buffer-read-only diff-mode-shared-map)))
     (add-to-list 'minor-mode-overriding-map-alist ro-bind)
     ;; Turn off this little trick in case the buffer is put in view-mode.
     (add-hook 'view-mode-hook
@@ -1297,7 +1315,11 @@ a diff with \\[diff-reverse-direction].
 
 ;;;###autoload
 (define-minor-mode diff-minor-mode
-  "Minor mode for viewing/editing context diffs.
+  "Toggle Diff minor mode.
+With a prefix argument ARG, enable Diff minor mode if ARG is
+positive, and disable it otherwise.  If called from Lisp, enable
+the mode if ARG is omitted or nil.
+
 \\{diff-minor-mode-map}"
   :group 'diff-mode :lighter " Diff"
   ;; FIXME: setup font-lock
@@ -1691,7 +1713,7 @@ With a prefix argument, REVERSE the hunk."
   "See whether it's possible to apply the current hunk.
 With a prefix argument, try to REVERSE the hunk."
   (interactive "P")
-  (destructuring-bind (buf line-offset pos src dst &optional switched)
+  (destructuring-bind (buf line-offset pos src _dst &optional switched)
       (diff-find-source-location nil reverse)
     (set-window-point (display-buffer buf) (+ (car pos) (cdr src)))
     (diff-hunk-status-msg line-offset (diff-xor reverse switched) t)))
@@ -1711,7 +1733,7 @@ then `diff-jump-to-old-file' is also set, for the next invocations."
   ;; 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)
+    (destructuring-bind (buf line-offset pos src _dst &optional switched)
        (diff-find-source-location other-file rev)
       (pop-to-buffer buf)
       (goto-char (+ (car pos) (cdr src)))
@@ -1729,7 +1751,7 @@ For use in `add-log-current-defun-function'."
     (when (looking-at diff-hunk-header-re)
       (forward-line 1)
       (re-search-forward "^[^ ]" nil t))
-    (destructuring-bind (&optional buf line-offset pos src dst switched)
+    (destructuring-bind (&optional buf _line-offset pos src dst switched)
         ;; Use `noprompt' since this is used in which-func-mode and such.
        (ignore-errors                ;Signals errors in place of prompting.
           (diff-find-source-location nil nil 'noprompt))
@@ -1823,16 +1845,22 @@ For use in `add-log-current-defun-function'."
     (replace-match (cdr (assq (char-before) '((?+ . "-") (?> . "<"))))))
   )
 
+(declare-function smerge-refine-subst "smerge-mode"
+                  (beg1 end1 beg2 end2 props &optional preproc))
+
 (defun diff-refine-hunk ()
   "Highlight changes of hunk at point at a finer granularity."
   (interactive)
-  (eval-and-compile (require 'smerge-mode))
+  (require 'smerge-mode)
   (save-excursion
     (diff-beginning-of-hunk 'try-harder)
-    (let* ((style (diff-hunk-style))    ;Skips the hunk header as well.
+    (let* ((start (point))
+           (style (diff-hunk-style))    ;Skips the hunk header as well.
            (beg (point))
            (props '((diff-mode . fine) (face diff-refine-change)))
-           (end (progn (diff-end-of-hunk) (point))))
+           ;; Be careful to go back to `start' so diff-end-of-hunk gets
+           ;; to read the hunk header's line info.
+           (end (progn (goto-char start) (diff-end-of-hunk) (point))))
 
       (remove-overlays beg end 'diff-mode 'fine)
 
@@ -1874,28 +1902,27 @@ I.e. like `add-change-log-entry-other-window' but applied to all hunks."
   ;; good to call it for each change.
   (save-excursion
     (goto-char (point-min))
-    (let ((orig-buffer (current-buffer)))
-      (condition-case nil
-         ;; Call add-change-log-entry-other-window for each hunk in
-         ;; the diff buffer.
-         (while (progn
-                   (diff-hunk-next)
-                   ;; Move to where the changes are,
-                   ;; `add-change-log-entry-other-window' works better in
-                   ;; that case.
-                   (re-search-forward
-                    (concat "\n[!+-<>]"
-                            ;; If the hunk is a context hunk with an empty first
-                            ;; half, recognize the "--- NNN,MMM ----" line
-                            "\\(-- [0-9]+\\(,[0-9]+\\)? ----\n"
-                            ;; and skip to the next non-context line.
-                            "\\( .*\n\\)*[+]\\)?")
-                    nil t))
-            (save-excursion
-              ;; FIXME: this pops up windows of all the buffers.
-              (add-change-log-entry nil nil t nil t)))
-        ;; When there's no more hunks, diff-hunk-next signals an error.
-       (error nil)))))
+    (condition-case nil
+        ;; Call add-change-log-entry-other-window for each hunk in
+        ;; the diff buffer.
+        (while (progn
+                 (diff-hunk-next)
+                 ;; Move to where the changes are,
+                 ;; `add-change-log-entry-other-window' works better in
+                 ;; that case.
+                 (re-search-forward
+                  (concat "\n[!+-<>]"
+                          ;; If the hunk is a context hunk with an empty first
+                          ;; half, recognize the "--- NNN,MMM ----" line
+                          "\\(-- [0-9]+\\(,[0-9]+\\)? ----\n"
+                          ;; and skip to the next non-context line.
+                          "\\( .*\n\\)*[+]\\)?")
+                  nil t))
+          (save-excursion
+            ;; FIXME: this pops up windows of all the buffers.
+            (add-change-log-entry nil nil t nil t)))
+      ;; When there's no more hunks, diff-hunk-next signals an error.
+      (error nil))))
 
 ;; provide the package
 (provide 'diff-mode)
@@ -1935,5 +1962,4 @@ I.e. like `add-change-log-entry-other-window' but applied to all hunks."
 ;; use `combine-after-change-calls' to minimize the slowdown of font-lock.
 ;;
 
-;; arch-tag: 2571d7ff-bc28-4cf9-8585-42e21890be66
 ;;; diff-mode.el ends here